发几个iphone助手相关代码,供大家参考

// IOSApi.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"

#include "IOSApi.h"
#include "IOSConnect.h"
#include "io.h"
#include "common.h"

#include "Plist.hpp"


// 这是导出变量的一个示例
IOSAPI int nIOSApi=0;

// 这是导出函数的一个示例。
IOSAPI int fnIOSApi(void)
{
    return 42;
}

// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 IOSApi.h
CIOSApi::CIOSApi()
{
    return ;
}

#ifdef __cplusplus
    extern "C"
    {
#endif
    //初始化
    IOSAPI UINT IOS::Initialize(void){
        UINT ret = iTunesApi::InitApi();
        iTunesVersion = iTunesApi::GetiTunesVersion();
        wchar_t wpsz_computer_name[512] = { 0 };
        DWORD name_size = 0;
        wstring wstr;
        GetComputerName(NULL, &name_size);
        GetComputerName(wpsz_computer_name, &name_size);
        ComputerName = wpsz_computer_name;
        return ret;
    }
    
    //释放
    IOSAPI BOOL IOS::Dispose(void){
        return iTunesApi::ReleaseApi();
    }

    IOSAPI void IOS::SetApplicationDataFolder(const wchar_t* wpsz_path){
        iTunesApi::SetApplicationDataFolder(wpsz_path);
    }
    IOSAPI void IOS::GetApplicationDataFolder(wchar_t* wpsz_path){
        iTunesApi::GetApplicationDataFolder(wpsz_path);
    }

    //注册连接回调函数
    IOSAPI BOOL IOS::RegisterOnConnectListener(pConnecttion callback, void* pUserData){
        IOSConnect::OnConnect = callback;
        IOSConnect::OnConnectUserData = pUserData;
        return TRUE;
    }

    //注册断开回调函数
    IOSAPI BOOL IOS::RegisterOnDisConnectListener(pConnecttion callback, void* pUserData){
        IOSConnect::OnDisConnect = callback;
        IOSConnect::OnDisconnectUserData = pUserData;
        return TRUE;
    }

    //开始监听
    IOSAPI BOOL IOS::StartListen(){
        HANDLE hDevice;
        // 异步监听。
        iTunesApi::AMDeviceNotificationSubscribe(IOSConnect::DeviceOnConnection,0,0,0,&hDevice);
        return TRUE;
    }

    //打开设备
    IOSAPI BOOL IOS::DeviceOpen(HANDLE hDevice){
        UINT ret = 0;
        if((ret = iTunesApi::AMDeviceConnect(hDevice)) != 0)
            return FALSE;
        if((ret = iTunesApi::AMDeviceIsPaired(hDevice)) != 1)
            return FALSE;
        if((ret = iTunesApi::AMDeviceValidatePairing(hDevice)) != 0)
            return FALSE;
        if((ret = iTunesApi::AMDeviceStartSession(hDevice)) != 0)
            return FALSE;
        return TRUE;
    }

    //保持设备打开状态
    IOSAPI BOOL IOS::DeviceKeepConnect(HANDLE hDevice){
        std::wstring str_SerialNumber;
        UINT ret = 0;
        IOSConnect::GetCharProperty(hDevice, str_SerialNumber, "SerialNumber");
        if ((ret = iTunesApi::AMDeviceStartSession(hDevice))!=0)
        {
            if((ret = iTunesApi::AMDeviceDisconnect(hDevice)) != 0)
                return FALSE;
            if((ret = iTunesApi::AMDeviceConnect(hDevice)) != 0)
                return FALSE;
            if((ret = iTunesApi::AMDeviceIsPaired(hDevice)) != 1)
                return FALSE;
            if((ret = iTunesApi::AMDeviceValidatePairing(hDevice)) != 0)
                return FALSE;
            if((ret = iTunesApi::AMDeviceStartSession(hDevice)) != 0)
                return FALSE;
        }
        return TRUE;
    }

    //关闭设备
    IOSAPI BOOL IOS::DeviceClose(HANDLE hDevice){
        iTunesApi::AMDeviceStopSession(hDevice);
        iTunesApi::AMDeviceDisconnect(hDevice);
        return TRUE;
    }

    //获取设备基本信息
    IOSAPI BOOL IOS::GetDeviceInformation(HANDLE hDevice, ios_device_information* info){
        IOSConnect::GetCharProperty(hDevice, info->SerialNumber, "SerialNumber");        // 序列号
        IOSConnect::GetCharProperty(hDevice, info->DeviceName, "DeviceName");            // 设备名称
        IOSConnect::GetCharProperty(hDevice, info->UniqueDeviceID, "UniqueDeviceID");    // 设备唯一ID
        IOSConnect::GetCharProperty(hDevice, info->ProductType, "ProductType");            // 产品类型
        IOSConnect::GetCharProperty(hDevice, info->DeviceClass, "DeviceClass");            // 设备类型
        IOSConnect::GetCharProperty(hDevice, info->ProductVersion, "ProductVersion");    // 系统版本
        IOSConnect::GetCharProperty(hDevice, info->ModelNumber, "ModelNumber");            // 设备型号
        IOSConnect::GetCharProperty(hDevice, info->BuildVersion, "BuildVersion");        // 产品版本
        IOSConnect::GetCharProperty(hDevice, info->HardwareModel, "HardwareModel");        // 硬件型号
        IOSConnect::GetCharProperty(hDevice, info->DeviceColor, "DeviceColor");            // 设备颜色
        IOSConnect::GetCharProperty(hDevice, info->RegionInfo, "RegionInfo");            // 地区信息
        IOSConnect::GetCharProperty(hDevice, info->FirmwareVersion, "FirmwareVersion");    // 固件版本
        IOSConnect::GetCharProperty(hDevice, info->ActivationState, "ActivationState");    // 激活状态    
        IOSConnect::GetBoolProperty(hDevice, info->ActivationStateAcknowledged, "ActivationStateAcknowledged");    // 激活确认 bool
        IOSConnect::GetCharProperty(hDevice, info->BasebandVersion, "BasebandVersion");    // 调制解调器固件 
        IOSConnect::GetBoolProperty(hDevice, info->iTunesHasConnected, "iTunesHasConnected");// itunes 连接    bool
        IOSConnect::GetCharProperty(hDevice, info->BluetoothAddress, "BluetoothAddress");    // 蓝牙
        IOSConnect::GetCharProperty(hDevice, info->WiFiAddress, "WiFiAddress");                //WIFI
        IOSConnect::GetCharProperty(hDevice, info->InternationalMobileEquipmentIdentity, "InternationalMobileEquipmentIdentity");//IMEI
        IOSConnect::GetCharProperty(hDevice, info->IntegratedCircuitCardIdentity, "IntegratedCircuitCardIdentity");
        IOSConnect::GetBoolProperty(hDevice, info->BatteryIsCharging, "BatteryIsCharging", "com.apple.mobile.battery");
        IOSConnect::GetNumberProperty(hDevice, info->BatteryCurrentCapacity, "BatteryCurrentCapacity", "com.apple.mobile.battery");
        IOSConnect::GetCharProperty(hDevice, info->CPUArchitecture, "CPUArchitecture");
        IOSConnect::GetCharProperty(hDevice, info->Keyboard, "Keyboard", "com.apple.international");
        IOSConnect::GetBoolProperty(hDevice, info->Uses24HourClock, "Uses24HourClock");
        IOSConnect::GetCharProperty(hDevice, info->TimeZone, "TimeZone");
        IOSConnect::GetCharProperty(hDevice, info->AppleID, "AppleID", "com.apple.itunesstored");
        return TRUE;
    }

    //获取设备容量信息
    IOSAPI void IOS::GetDiskusage(HANDLE hDevice, char* pszLibraryID, ios_device_usage* usage){
        HANDLE handleResult,cfName;
        cfName = iTunesApi::CFStringMakeConstantString("com.apple.disk_usage");
        handleResult = iTunesApi::AMDeviceCopyValue(hDevice, cfName, iTunesApi::CFStringMakeConstantString("TotalDiskCapacity"));
        iTunesApi::GetCFInt64Number(handleResult, usage->TotalDiskCapacity);
        handleResult = iTunesApi::AMDeviceCopyValue(hDevice, cfName, iTunesApi::CFStringMakeConstantString("TotalSystemAvailable"));
        iTunesApi::GetCFInt64Number(handleResult, usage->TotalSystemAvailable);
        handleResult = iTunesApi::AMDeviceCopyValue(hDevice, cfName, iTunesApi::CFStringMakeConstantString("TotalSystemCapacity"));
        iTunesApi::GetCFInt64Number(handleResult, usage->TotalSystemCapacity);
        handleResult = iTunesApi::AMDeviceCopyValue(hDevice, cfName, iTunesApi::CFStringMakeConstantString("TotalDataCapacity"));
        iTunesApi::GetCFInt64Number(handleResult, usage->TotalDataCapacity);
        handleResult = iTunesApi::AMDeviceCopyValue(hDevice, cfName, iTunesApi::CFStringMakeConstantString("TotalDataAvailable"));
        iTunesApi::GetCFInt64Number(handleResult, usage->TotalDataAvailable);
    }

    //服务发送数据
    IOSAPI int IOS::ServiceConnectionSend(HANDLE h,const char* pszBuffer, int len){
        char lenchar[4] = { 0 };
        memcpy(lenchar, &len, 4);
        int ret = iTunesApi::AMDServiceConnectionSend(h, lenchar, 4);
        int pos = 0;
        int relsend = 0;
        if (ret == 4){
            do 
            {
                if ((pos + SERVICE_DATA_SECTION) < len) relsend = SERVICE_DATA_SECTION;
                else relsend = len - pos;
                ret = iTunesApi::AMDServiceConnectionSend(h, (char*)(pszBuffer + pos), relsend);
                if (ret != relsend)
                    return -1;
                pos += relsend;
            } while (pos<len);
            Sleep(50);
            return len;
        }
        else
            return -1;
    }
    //服务收取数据
    IOSAPI int IOS::ServiceConnectionReceive(HANDLE h, char*& pszBuffer){
        int ret = -1;
        void* hBuffer = 0;
        int len_buffer;
        int pos = 0;
        int left = 0;
        ret = iTunesApi::AMDServiceConnectionReceive(h, &len_buffer, 4);
        if (ret == 4){//buffer length
            pszBuffer = (char*)malloc(len_buffer);
            do 
            {
                if (pos + SECTIONSIZE < len_buffer)
                    left = SECTIONSIZE;
                else
                    left = len_buffer - pos;
                ret = iTunesApi::AMDServiceConnectionReceive(h, pszBuffer + pos, left);
                if (ret<=0)
                    return -1;
                pos += ret;
            } while (pos<len_buffer);
            return len_buffer;
        }
        return -1;
    }

    //开启服务
    IOSAPI IOSServiceHandle* IOS::DeviceOpenService(HANDLE hDevice, char* pszServiceName){
        int iRet = -1;
        HANDLE hCFServiceName = iTunesApi::CFStringMakeConstantString(pszServiceName);
        HANDLE hServiceHandle = 0;
        iRet = iTunesApi::AMDeviceSecureStartService(hDevice,hCFServiceName,NULL,&hServiceHandle);
        if(hServiceHandle == 0)return NULL;
        UINT hServiceSocketHandle = iTunesApi::AMDServiceConnectionGetSocket(hServiceHandle);
        iRet = iTunesApi::AMDServiceConnectionGetSecureIOContext(hServiceHandle);
        IOSServiceHandle* pService = new IOSServiceHandle();
        pService->pServiceHandle = hServiceHandle;
        pService->pServiceSocketHandle = hServiceSocketHandle;
        return pService;
    }

    //打开文件服务
    IOSAPI BOOL IOS::OpenAfc(UINT pServiceSocketHandle, unsigned int io_timeout, HANDLE* pAfcServiceHandle){
        int iRet = iTunesApi::AFCConnectionOpen(pServiceSocketHandle,io_timeout,pAfcServiceHandle);
        if (iRet == 0)
        {
            return TRUE;
        }
        return FALSE;
    }

    //获取目录信息
    IOSAPI AFCFileInfomation* IOS::GetPathInfo(HANDLE pAfcServiceHandle, const wchar_t* pszPath){
        std::string str_path;
        common::G2Utf8(common::WC2MB(pszPath).c_str(), str_path);
        HANDLE pFileInfo = NULL;
        int iRet = -1;
        iRet = iTunesApi::AFCFileInfoOpen(pAfcServiceHandle, str_path.c_str(), &pFileInfo);
        if (iRet!=0 || pFileInfo== NULL)
            return NULL;
        HANDLE pKey = NULL,pValue = NULL;
        AFCPathDictPair* pInfoRoot,*pCurrent;
        pInfoRoot = pCurrent = NULL;
        iRet = iTunesApi::AFCKeyValueRead(pFileInfo,&pKey,&pValue);
        while (iRet == 0 && pKey && pValue)
        {
            AFCPathDictPair* pInfo = (AFCPathDictPair*)malloc(sizeof(AFCPathDictPair));
            memset(pInfo,0,sizeof(AFCPathDictPair));
            strcpy(pInfo->pszKey,(char*)pKey);
            strcpy(pInfo->pszValue,(char*)pValue);
            if (pInfoRoot==NULL)
            {
                pInfoRoot = pCurrent = pInfo;
            }else{
                pCurrent->pNext = pInfo;
                pCurrent = pInfo;
            }
            iRet = iTunesApi::AFCKeyValueRead(pFileInfo,&pKey,&pValue);
        }
        iTunesApi::AFCKeyValueClose(pFileInfo);
        if (pInfoRoot)
        {
            AFCFileInfomation* infomation = (AFCFileInfomation*)malloc(sizeof(AFCFileInfomation));
            memset(infomation,0,sizeof(AFCFileInfomation));
            wcscpy(infomation->pszFilePath,pszPath);
            char pszType[512] = {0};
            pCurrent = pInfoRoot;
            while (pCurrent)
            {
                if (strcmp(pCurrent->pszKey,"st_blocks") == 0)
                    infomation->st_blocks = atol(pCurrent->pszValue);
                else if (strcmp(pCurrent->pszKey,"st_size") == 0)
                    infomation->st_size = atol(pCurrent->pszValue);
                else if (strcmp(pCurrent->pszKey,"st_mtime") == 0)
                    infomation->st_mtime = atol(pCurrent->pszValue);
                else if (strcmp(pCurrent->pszKey,"st_nlink") == 0)
                    infomation->st_nlink = atol(pCurrent->pszValue);
                else if (strcmp(pCurrent->pszKey,"st_birthtime") == 0)
                    infomation->st_birthtime = atol(pCurrent->pszValue);
                else if (strcmp(pCurrent->pszKey,"st_ifmt") == 0)
                {
                    if (strcmp(pCurrent->pszValue,"S_IFDIR") == 0)
                        infomation->st_ifmt = DFS_Folder;
                    else if (strcmp(pCurrent->pszValue,"S_IFREG") == 0)
                        infomation->st_ifmt = DFS_File;
                    else if (strcmp(pCurrent->pszValue,"S_IFBLK") == 0)
                        infomation->st_ifmt = DFS_BlockDevice;
                    else if (strcmp(pCurrent->pszValue,"S_IFCHR") == 0)
                        infomation->st_ifmt = DFS_CharDevice;
                    else if (strcmp(pCurrent->pszValue,"S_IFIFO") == 0)
                        infomation->st_ifmt = DFS_FIFO;
                    else if (strcmp(pCurrent->pszValue,"S_IFLNK") == 0)
                        infomation->st_ifmt = DFS_Link;
                    else if (strcmp(pCurrent->pszValue,"S_IFMT") == 0)
                        infomation->st_ifmt = DFS_FileMask;
                    else if (strcmp(pCurrent->pszValue,"S_IFSOCK") == 0)
                        infomation->st_ifmt = DFS_Socket;
                    else
                        infomation->st_ifmt = DFS_Unknown;
                }
                pCurrent = pCurrent->pNext;
            }
            
            return infomation;
        }
        return NULL;
    }

    //读取设备上文件内容
    IOSAPI LONG64 IOS::ReadDeviceFile(HANDLE pAfcServiceHandle, const wchar_t* pszRemote, char* pszBuffer){
        std::string str_remote;
        common::G2Utf8(common::WC2MB(pszRemote).c_str(), str_remote);
        LONG64 hRemoteFile;
        int ret = -1;
        LONG64 filelength = 0;
        LONG64 pos = 0;
        LONG64 left = 0;
        AFCFileInfomation* fileinfo = GetPathInfo(pAfcServiceHandle, pszRemote);
        if (!fileinfo || fileinfo->st_ifmt != DFS_File)
            return FALSE;
        filelength = fileinfo->st_size;
        ret = iTunesApi::AFCFileRefOpen(pAfcServiceHandle, str_remote.c_str(), 1, 0, &hRemoteFile);
        if (ret == 0){
            char* buffer = NULL;
            buffer = (char*)malloc((size_t)filelength);
            memset(buffer, 0, (size_t)filelength);
            do
            {
                if (pos + SECTIONSIZE < filelength)
                    left = SECTIONSIZE;
                else
                    left = filelength - pos;
                iTunesApi::AFCFileRefRead(pAfcServiceHandle, hRemoteFile, buffer + pos, &left);
                pos += left;
            } while (pos < filelength);
            memcpy(pszBuffer, buffer, (size_t)filelength);
            ret = iTunesApi::AFCFileRefClose(pAfcServiceHandle, hRemoteFile);
            return filelength;
        }
        return 0;
    }

    //写入数据到设备上
    IOSAPI BOOL IOS::WriteDeviceFile(HANDLE pAfcServiceHandle, const wchar_t* pszRemote, const char* pszBuffer, long bufferSize){
        std::string str_remote;
        common::G2Utf8(common::WC2MB(pszRemote).c_str(), str_remote);
        LONG64 hRemoteFile;
        int ret = -1;
        LONG64 pos = 0;
        LONG64 left = 0;

        AFCFileInfomation* fileinfo = GetPathInfo(pAfcServiceHandle, pszRemote);
        if (fileinfo && fileinfo->st_ifmt == DFS_File) DeletePath(pAfcServiceHandle, pszRemote);

        ret = iTunesApi::AFCFileRefOpen(pAfcServiceHandle, str_remote.c_str(), 3, 0, &hRemoteFile);
        if (ret == 0){
            char* buffer = (char*)pszBuffer;
            do
            {
                if (pos + SECTIONSIZE < bufferSize)
                    left = SECTIONSIZE;
                else
                    left = bufferSize - pos;
                iTunesApi::AFCFileRefWrite(pAfcServiceHandle, hRemoteFile, buffer, left);
                pos += left;
                buffer = buffer + left;
            } while (pos < bufferSize);
            ret = iTunesApi::AFCFileRefClose(pAfcServiceHandle, hRemoteFile);
            return TRUE;
        }
        return FALSE;
    }

    //下载文件
    IOSAPI BOOL IOS::DownloadDeviceFile(HANDLE pAfcServiceHandle, const wchar_t* pszRemote, const wchar_t* pszLocal){
        std::string str_remote;
        std::string str_local;
        common::G2Utf8(common::WC2MB(pszRemote).c_str(), str_remote);
        common::G2Utf8(common::WC2MB(pszLocal).c_str(), str_local);
        LONG64 hRemoteFile;
        int ret = -1;
        LONG64 filelength = 0;
        LONG64 pos = 0;
        LONG64 left = 0;
        AFCFileInfomation* fileinfo = GetPathInfo(pAfcServiceHandle, pszRemote);
        if (!fileinfo || fileinfo->st_ifmt != DFS_File)
            return FALSE;
        filelength = fileinfo->st_size;
        ret = iTunesApi::AFCFileRefOpen(pAfcServiceHandle, str_remote.c_str(), 1, 0, &hRemoteFile);
        if (ret == 0){
            FILE* file = _wfopen(pszLocal, L"rb");
            if (file){ fclose(file); _wremove(pszLocal); }
            file = _wfopen(pszLocal, L"wb");
            fseek(file, 0, SEEK_SET);
            char* buffer = NULL;
            buffer = (char*)malloc(SECTIONSIZE);
            memset(buffer, 0, SECTIONSIZE);
            if (!file){
                ret = iTunesApi::AFCFileRefClose(pAfcServiceHandle, hRemoteFile);
                return FALSE;
            }
            do
            {
                if (pos + SECTIONSIZE < filelength)
                    left = SECTIONSIZE;
                else
                    left = filelength - pos;
                iTunesApi::AFCFileRefRead(pAfcServiceHandle, hRemoteFile, buffer, &left);
                fwrite(buffer, 1, (size_t)left, file);
                pos += left;
            } while (pos < filelength);
            free(buffer);
            fclose(file);
            ret = iTunesApi::AFCFileRefClose(pAfcServiceHandle, hRemoteFile);
            return TRUE;
        }
        return FALSE;
    }

    //上传文件
    IOSAPI BOOL IOS::UploadDeviceFile(HANDLE pAfcServiceHandle, const wchar_t* pszRemote, const wchar_t* pszLocal){
        std::string str_remote;
        std::string str_local;
        common::G2Utf8(common::WC2MB(pszRemote).c_str(), str_remote);
        common::G2Utf8(common::WC2MB(pszLocal).c_str(), str_local);
        LONG64 hRemoteFile;
        int ret = -1;
        LONG64 filelength = 0;
        LONG64 pos = 0;
        LONG64 left = 0;

        AFCFileInfomation* fileinfo = GetPathInfo(pAfcServiceHandle, pszRemote);
        if (fileinfo && fileinfo->st_ifmt == DFS_File) DeletePath(pAfcServiceHandle, pszRemote);

        ret = iTunesApi::AFCFileRefOpen(pAfcServiceHandle, str_remote.c_str(), 3, 0, &hRemoteFile);
        if (ret == 0){
            FILE* file = _wfopen(pszLocal, L"rb");
            if (!file){
                ret = iTunesApi::AFCFileRefClose(pAfcServiceHandle, hRemoteFile);
                return FALSE;
            }
            fseek(file, 0, SEEK_END);
            filelength = ftell(file);
            fseek(file, 0, SEEK_SET);
            char* buffer = NULL;
            buffer = (char*)malloc(SECTIONSIZE);
            memset(buffer, 0, SECTIONSIZE);
            do
            {
                if (pos + SECTIONSIZE < filelength)
                    left = SECTIONSIZE;
                else
                    left = filelength - pos;
                fread(buffer, 1, (size_t)left, file);
                iTunesApi::AFCFileRefWrite(pAfcServiceHandle, hRemoteFile, buffer, left);
                pos += left;
            } while (pos < filelength);
            free(buffer);
            fclose(file);
            ret = iTunesApi::AFCFileRefClose(pAfcServiceHandle, hRemoteFile);
            return TRUE;
        }
        return FALSE;
    }

    //获取二级目录信息
    IOSAPI std::vector<AFCFileInfomation*>* IOS::DirPath(HANDLE pAfcServiceHandle,const wchar_t* pszPath){
        std::string str_path;
        common::G2Utf8(common::WC2MB(pszPath).c_str(), str_path);
        std::vector<AFCFileInfomation*>* pPathVector = new std::vector<AFCFileInfomation*>();
        HANDLE pDirInfo = NULL;
        HANDLE pBuffer = NULL;
        wchar_t pszTempPath[512] = {0};
        wchar_t pszFolder[512] = {0};
        wchar_t pszFullPath[512] = {0};
        
        int iLength = -1;
        wcscpy(pszFolder,pszPath);
        iLength = wcslen(pszFolder);
        if (pszFolder[iLength-1] != '/')
            wcscat(pszFolder,L"/");
        int iRet = -1;
        iRet = iTunesApi::AFCDirectoryOpen(pAfcServiceHandle, str_path.c_str(), &pDirInfo);
        if (iRet!=0)
            return NULL; // iRet = 1; ?? 
        iTunesApi::AFCDirectoryRead(pAfcServiceHandle,pDirInfo,&pBuffer);
        while (pBuffer)
        {
            wcscpy(pszTempPath,(wchar_t*)pBuffer);
            if (wcscmp(pszTempPath,L".") != 0 && wcscmp(pszTempPath,L"..") != 0){
                wsprintf(pszFullPath,L"%s%s",pszFolder,pszTempPath);
                AFCFileInfomation* info = GetPathInfo(pAfcServiceHandle,pszFullPath);
                if (info)
                    pPathVector->push_back(info);
            }
            pBuffer = NULL;
            iTunesApi::AFCDirectoryRead(pAfcServiceHandle,pDirInfo,&pBuffer);
        }
        return pPathVector;
    }

    //删除路径
    IOSAPI BOOL IOS::DeletePath(HANDLE pAfcServiceHandle,const wchar_t* pszPath)
    {
        std::string str_path;
        common::G2Utf8(common::WC2MB(pszPath).c_str(), str_path);
        if (GetPathInfo(pAfcServiceHandle, pszPath))
        {
            if (iTunesApi::AFCRemovePath(pAfcServiceHandle, str_path.c_str()) == 0)
                return TRUE;
        }
        return FALSE;
    }

    //创建文件夹
    IOSAPI int IOS::DirectoryCreate(HANDLE pAfcServiceHandle, const wchar_t *path)
    {
        std::string str_path;
        common::G2Utf8(common::WC2MB(path).c_str(), str_path);
        return iTunesApi::AFCDirectoryCreate(pAfcServiceHandle, str_path.c_str());
    }

    // 判断文件是否存在
    IOSAPI bool IOS::FileExist(HANDLE pAfcServiceHandle, const wchar_t *path)
    {
        std::string str_path;
        common::G2Utf8(common::WC2MB(path).c_str(), str_path);
        LONG64 pFileHandle = 0;
        int ret = iTunesApi::AFCFileRefOpen(pAfcServiceHandle, str_path.c_str(), 1, 0, &pFileHandle);
        if (ret == 0)
            ret = iTunesApi::AFCFileRefClose(pAfcServiceHandle, pFileHandle);
        return ret == 0;
    }

    //从XML转换成Plist
    IOSAPI void IOS::GetPlistDataFromXmlData(std::vector<char> source_data, std::vector<char>& plist_data){
        CFStringRef  cferror;
        bool ret;
        CFDataRef cfdata = iTunesApi::CFDataCreate(nullptr, (const uint8_t*)source_data.data(), source_data.size());
        CFPropertyListRef cfplist = iTunesApi::CFPropertyListCreateFromXMLData(nullptr, cfdata, 0, &cferror);
        iTunesApi::CFRelease(cfdata);
        CFWriteStreamRef cfstream = iTunesApi::CFWriteStreamCreateWithAllocatedBuffers(nullptr, nullptr);
        ret = iTunesApi::CFWriteStreamOpen(cfstream);
        if (ret){
            CFIndex write_length = iTunesApi::CFPropertyListWriteToStream(cfplist, cfstream, kCFPropertyListBinaryFormat_v1_0, &cferror);
            CFTypeRef cfproperty = iTunesApi::CFWriteStreamCopyProperty(cfstream, iTunesApi::kCFStreamPropertyDataWritten);
            CFIndex property_length = iTunesApi::CFDataGetLength(cfproperty);
            const uint8_t* property_buffer = iTunesApi::CFDataGetBytePtr(cfproperty);
            for (int i = 0; i < property_length; i++)
            {
                plist_data.push_back(property_buffer[i]);
            }
            iTunesApi::CFRelease(cfproperty);
            iTunesApi::CFWriteStreamClose(cfstream);
            iTunesApi::CFRelease(cfplist);
        }
    }

    //获取CF数据的类型
    IOSAPI CFDataType IOS::GetCFDataType(CFTypeRef data){
        CFDataType type  = CFTYPE_UnKnow;
        CFIndex dataid = iTunesApi::CFGetTypeID(data);
        if (dataid == iTunesApi::CFDictionaryGetTypeID()) type = CFTYPE_Dictionary;
        if (dataid == iTunesApi::CFArrayGetTypeID()) type = CFTYPE_Array;
        if (dataid == iTunesApi::CFStringGetTypeID()) type = CFTYPE_String;
        if (dataid == iTunesApi::CFNumberGetTypeID()) type = CFTYPE_Number;
        if (dataid == iTunesApi::CFBooleanGetTypeID()) type = CFTYPE_Boolean;
        if (dataid == iTunesApi::CFDataGetTypeID()) type = CFTYPE_Data;
        if (dataid == iTunesApi::CFDateGetTypeID()) type = CFTYPE_Date;
        return type;
    }

    //获取Plist的数据类型
    IOSAPI CFDataType IOS::GetPlistDataType(void* plist){
        using namespace std;
        boost::any* bootanydata = (boost::any*)plist;
        const std::type_info &objType = bootanydata->type();
        if (objType == typeid(int32_t))
            return CFTYPE_Number;
        else if (objType == typeid(int64_t))
            return CFTYPE_Number;
        else if (objType == typeid(long))
            return CFTYPE_Number;
        else if (objType == typeid(short))
            return CFTYPE_Number;
        else if (objType == typeid(std::map<std::string, boost::any>))
            return CFTYPE_Dictionary;
        else if (objType == typeid(std::string))
            return CFTYPE_String;
        else if (objType == typeid(std::vector<boost::any>))
            return CFTYPE_Array;
        else if (objType == typeid(std::vector<char>))
            return CFTYPE_Data;
        else if (objType == typeid(double))
            return CFTYPE_Real;
        else if (objType == typeid(float))
            return CFTYPE_Real;
        else if (objType == typeid(Plist::Date))
            return CFTYPE_Date;
        else if (objType == typeid(bool))
            return CFTYPE_Boolean;
        return CFTYPE_UnKnow;
    }

    //CFTypeRef to Plist
    IOSAPI boost::any IOS::GetPlistDataFromCFData(CFTypeRef cfdata, CFDataType type){
        switch (type)
        {
        case CFTYPE_Dictionary:
        {
            Plist::dictionary_type dict;
            CFIndex dict_count = iTunesApi::CFDictionaryGetCount(cfdata);
            if (dict_count > 0){
                CFTypeRef *keys = new CFTypeRef[dict_count];
                CFTypeRef *values = new CFTypeRef[dict_count];
                iTunesApi::CFDictionaryGetKeysAndValues(cfdata, keys, values);
                for (size_t i = 0; i < dict_count; i++)
                {
                    CFDataType value_type = GetCFDataType(values[i]);
                    dict[boost::any_cast<const std::string&>(GetPlistDataFromCFData(keys[i], CFTYPE_String))] = GetPlistDataFromCFData(values[i], value_type);
                }
            }
            return dict;
        }
            break;
        case CFTYPE_Array:
        {
            Plist::array_type arr;
            CFIndex arr_count = iTunesApi::CFArrayGetCount(cfdata);
            if (arr_count > 0){
                for (size_t i = 0; i < arr_count; i++)
                {
                    CFTypeRef value = iTunesApi::CFArrayGetValueAtIndex(cfdata, i);
                    CFDataType value_type = GetCFDataType(value);
                    arr.push_back(GetPlistDataFromCFData(value,value_type));
                }
            }
            return arr;
        }
            break;
        case CFTYPE_Data:
        {
            Plist::data_type data;
            CFIndex data_length = iTunesApi::CFDataGetLength(cfdata);
            const uint8_t* databuffer = iTunesApi::CFDataGetBytePtr(cfdata);
            for (size_t i = 0; i < data_length; i++)
                data.push_back(databuffer[i]);
            return data;
        }
            break;
        case CFTYPE_String:
        {
            Plist::string_type str;
            CFIndex len = iTunesApi::CFStringGetLength(cfdata);
            char* pszbuffer = new char[len * 4 + 1];
            iTunesApi::CFStringGetCString(cfdata, pszbuffer, len * 4 + 1, kCFStringEncodingUTF8);
            str = pszbuffer;
            return str;
        }
            break;
        case CFTYPE_Number:
        {
            CFIndex len = iTunesApi::CFNumberGetByteSize(cfdata);
            CFNumberType number_type = iTunesApi::CFNumberGetType(cfdata);
            switch (number_type)
            {
            case kCFNumberSInt8Type:
            case kCFNumberSInt16Type:
            case kCFNumberSInt32Type:
            case kCFNumberSInt64Type:
            {
                Plist::integer_type intret;
                iTunesApi::CFNumberGetValue(cfdata, number_type, &intret);
                return intret;
            }
                break;
            case kCFNumberFloat32Type:
            case kCFNumberFloat64Type:
            {
                Plist::real_type floatret;
                iTunesApi::CFNumberGetValue(cfdata, number_type, &floatret);
                return floatret;
            }
                break;
            case kCFNumberCharType:
            case kCFNumberShortType:
            case kCFNumberIntType:
            case kCFNumberLongType:
            case kCFNumberLongLongType:
            {
                Plist::integer_type intret;
                iTunesApi::CFNumberGetValue(cfdata, number_type, &intret);
                return intret;
            }
                break;
            case kCFNumberFloatType:
            case kCFNumberDoubleType:
            {
                Plist::real_type floatret;
                iTunesApi::CFNumberGetValue(cfdata, number_type, &floatret);
                return floatret;
            }
                break;
            case kCFNumberCFIndexType:
            case kCFNumberNSIntegerType:
            {
                Plist::integer_type intret;
                iTunesApi::CFNumberGetValue(cfdata, number_type, &intret);
                return intret;
            }
                break;
            case kCFNumberCGFloatType:
            {
                Plist::real_type floatret;
                iTunesApi::CFNumberGetValue(cfdata, number_type, &floatret);
                return floatret;
            }
                break;
            default:
                break;
            }
            Plist::integer_type intret = 0;
            return intret;
        }
            break;
        case CFTYPE_Date:
        {
            CFAbsoluteTime timestamp = iTunesApi::CFDateGetAbsoluteTime(cfdata);
            Plist::date_type date;
            date.setTimeFromAppleEpoch(timestamp);
            return date;
        }
            break;
        case CFTYPE_Boolean:
        {
            Plist::boolean_type boolret;
            CFBooleanRef ref = iTunesApi::CFBooleanGetValue(cfdata);
            if (ref == iTunesApi::kCFBooleanTrue) boolret = true;
            else if (ref == iTunesApi::kCFBooleanFalse) boolret = false;
            return boolret;
        }
            break;
        case CFTYPE_Real:
        {
            CFIndex len = iTunesApi::CFNumberGetByteSize(cfdata);
            CFNumberType number_type = iTunesApi::CFNumberGetType(cfdata);
            Plist::real_type floatret;
            iTunesApi::CFNumberGetValue(cfdata, number_type, &floatret);
            return floatret;
        }
            break;
        case CFTYPE_UnKnow:
            break;
        default:
            break;
        }
        return NULL;
    }

    //Plist to CFTypeRef
    IOSAPI CFTypeRef IOS::GetCFDataFromPlistData(boost::any plist, CFDataType type){
        switch (type)
        {
        case CFTYPE_Dictionary:
        {
            CFMutableDictionaryRef cf_dict = iTunesApi::CFDictionaryCreateMutable(NULL, 0, &iTunesApi::kCFTypeDictionaryKeyCallBacks, &iTunesApi::kCFTypeDictionaryValueCallBacks);
            Plist::dictionary_type dict = boost::any_cast<const std::map<std::string, boost::any>&>(plist);
            if (dict.size())
            {
                Plist::dictionary_type::iterator piar = dict.begin();
                for (; piar != dict.end(); piar++)
                {
                    CFDataType value_type = GetPlistDataType(&piar->second);
                    CFTypeRef value = GetCFDataFromPlistData(piar->second, value_type);
                    iTunesApi::CFDictionaryAddValue(cf_dict, iTunesApi::CFStringMakeConstantString(piar->first.c_str()), value);
                }
            }
            return cf_dict;
        }
            break;
        case CFTYPE_Array:
        {
            CFMutableArrayRef cf_array = iTunesApi::CFArrayCreateMutable(NULL, 0, &iTunesApi::kCFTypeArrayCallBacks);
            Plist::array_type arr = boost::any_cast<const std::vector<boost::any>&>(plist);
            if (arr.size())
            {
                Plist::array_type::iterator item = arr.begin();
                for (; item != arr.end(); item++)
                {
                    CFDataType value_type = GetPlistDataType(&*item);
                    CFTypeRef value = GetCFDataFromPlistData(*item, value_type);
                    iTunesApi::CFArrayAppendValue(cf_array, value);
                }
            }
            return cf_array;
        }
            break;
        case CFTYPE_Data:
        {
            Plist::data_type data = boost::any_cast<const std::vector<char>&>(plist);
            CFDataRef cf_data = iTunesApi::CFDataCreate(NULL, (const uint8_t*)data.data(), data.size());
            return cf_data;
        }
            break;
        case CFTYPE_String:
        {
            Plist::string_type str = boost::any_cast<const std::string&>(plist);
            CFStringRef cf_str = iTunesApi::CFStringMakeConstantString(str.c_str());
            return cf_str;
        }
            break;
        case CFTYPE_Number:
        {
            Plist::integer_type number = boost::any_cast<const int64_t&>(plist);
            CFNumberRef cf_number = iTunesApi::CFNumberCreate(NULL, kCFNumberSInt64Type, &number);
            return cf_number;
        }
            break;
        case CFTYPE_Date:
        {
            Plist::date_type date = boost::any_cast<const Plist::Date&>(plist);
            date.timeAsAppleEpoch();
            CFDateRef cf_date = iTunesApi::CFDateCreate(NULL, date.timeAsAppleEpoch());
            return cf_date;
        }
            break;
        case CFTYPE_Boolean:
        {
            Plist::boolean_type flag = boost::any_cast<const bool&>(plist);
            if (flag) return iTunesApi::kCFBooleanTrue;
            else return iTunesApi::kCFBooleanFalse;
        }
            break;
        case CFTYPE_Real:
        {
            Plist::real_type number = boost::any_cast<const double&>(plist);
            CFNumberRef cf_number = iTunesApi::CFNumberCreate(NULL, kCFNumberDoubleType, &number);
            return cf_number;
        }
            break;
        case CFTYPE_UnKnow:
            break;
        default:
            break;
        }
        return NULL;
    }

#ifdef __cplusplus
};

#endif

 

#include "StdAfx.h"
#include "PhoneMgr.h"
#include <time.h>
#include <shlobj.h>
#include <stdio.h>
#include <io.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
#include "boost/thread/thread.hpp"
#include "boost/bind.hpp"
#include <string>
using namespace std;

// 静态对象初始化
CPhoneMgr* CPhoneMgr::m_pSelf = NULL;
void* CPhoneMgr::m_pUserData = NULL;
HANDLE CPhoneMgr::_hMutex = CreateMutex(NULL, FALSE, NULL);
am_device_notification* CPhoneMgr::m_notif = NULL;
CPhoneMgr::CDodetele CPhoneMgr::m_Dodelete;

CPhoneMgr::CPhoneMgr(void)
{
}

CPhoneMgr::~CPhoneMgr(void)
{
}

// iTunes支持检测
UINT CPhoneMgr::GetITunesApi()
{
    return iTunesApi::InitApi();
}

// 开始监听设备
UINT CPhoneMgr::StartListenDevice(void* pUserData)
{
    boost::thread thread(boost::bind(&CPhoneMgr::StartListenDeviceThread,this,pUserData));
    //StartListenDeviceThread(pUserData);
    return 0;
}

// 开始监听设备
UINT CPhoneMgr::StartListenDeviceThread(void* pUserData)
{
    
    CPhoneMgr::m_pUserData = pUserData;
    /*
    *      MDERR_OK            if successful   ------0
    *      MDERR_SYSCALL       if CFRunLoopAddSource() failed
    *      MDERR_OUT_OF_MEMORY if we ran out of memory 
    */
    // 设置监听回调
    return iTunesApi::AMDeviceNotificationSubscribe((am_device_notification_callback)CPhoneMgr::OnDeviceNotifyStaticFunc,0,0,0,&m_notif);
}
// 设备连接监听回调
void CPhoneMgr::OnDeviceNotifyStaticFunc( am_device_notification_callback_info* pNotify )
{
    switch (pNotify->msg)
    {
    case ADNCI_MSG_CONNECTED:
        {
            // 检测到有IOS设备接入 尝试连接
            CPhoneMgr* pMgr = CPhoneMgr::GetInstance();
            unsigned int nConnect = pMgr->ConnectDevice(pNotify->dev);
            if(MDERR_OK == nConnect)
            {
                pMgr->DisConnectDevice(pNotify->dev);
            }
            am_device_notification_callback_info* pParam = new am_device_notification_callback_info;
            memcpy(pParam,pNotify,sizeof(am_device_notification_callback_info));
            PostMessage((HWND)m_pUserData,MSG_DEVICENOFITY,nConnect,(LPARAM)pParam);
        }
        break;
    case ADNCI_MSG_DISCONNECTED:
        {
            CPhoneMgr* pMgr = CPhoneMgr::GetInstance();
            unsigned int nConnect = pMgr->DisConnectDevice(pNotify->dev);
            am_device_notification_callback_info* pParam = new am_device_notification_callback_info;
            memcpy(pParam,pNotify,sizeof(am_device_notification_callback_info));
            PostMessage((HWND)m_pUserData,MSG_DEVICENOFITY,nConnect,(LPARAM)pParam);
        }
        break;
    }
}

void CPhoneMgr::GetDeviceInfo( am_device* pDev ,HWND hWnd/* = NULL*/)
{
    // 启动线程获取基础信息
    boost::thread thread(boost::bind(&CPhoneMgr::GetDeviceInfoThread,this,pDev,hWnd==NULL?(HWND)m_pUserData:hWnd));
    //thread.detach();

}

// 获取基础信息
void CPhoneMgr::GetDeviceInfoThread(am_device* pDevice,HWND hWnd /*= NULL*/)
{
    //sleep(5000);
    if(!pDevice)
        return;

    mach_error_t nMach_error;
    // 连接设备
    if (MDERR_OK != (nMach_error = ConnectDevice(pDevice)))
    {
        PostMessage(hWnd,MSG_DEVICEINFO,nMach_error,0);
        return;
    }

    // 通过domain、key获取对应信息
    auto f_Dev_Info = [this](am_device* pDev, /*const*/ char* domain, /*const*/ char* key, void* pResult, int nResultLen)->bool
    {
        CFStringRef cfDomain = NULL, cfKey=NULL;
        if(domain)
            cfDomain = iTunesApi::__CFStringMakeConstantString(domain); 
        if(key)
            cfKey = iTunesApi::__CFStringMakeConstantString(key);
        CFStringRef cfValue = iTunesApi::AMDeviceCopyValue( pDev, cfDomain, cfKey );
        if( !cfValue) 
        {
            string sMsg = "f_Dev_Info";
            if(domain)
            {
                sMsg+=" domain[";
                sMsg+=domain;    
                sMsg+="]";    
            }
            if(key)
            {
                sMsg+=" key[";
                sMsg+=key;
                sMsg+="]";
            }
            LOG4CPLUS_ERROR(Logger::getRoot(),sMsg<<" faild");
            return false; 
        }

        // 获取值类型
        unsigned int tid = iTunesApi::CFGetTypeID( cfValue ); 
        if( tid == iTunesApi::CFStringGetTypeID())
        {
            CFString2CString(cfValue,(char*)pResult,nResultLen);
            if(strcmp(key,"ProductType") == 0)
            {
                auto it = mapProductType.find(string((char*)pResult));
                if(it != mapProductType.end())
                {
                    string sProType = it->second;
                    memset(pResult,0,nResultLen);
                    strncpy( (char*)pResult, sProType.c_str(), sProType.length());
                }
            }
        }
        else if( tid == iTunesApi::CFNumberGetTypeID() )
        {        
            Boolean b = iTunesApi::CFNumberGetValue( (CFNumberRef)cfValue, nResultLen?kCFNumberSInt64Type:kCFNumberSInt32Type, pResult );  
        }
        else if( tid == iTunesApi::CFBooleanGetTypeID())
        {
            Boolean b = iTunesApi::CFBooleanGetValue( (CFBooleanRef)cfValue); 
            *((bool*)pResult) = b?true:false;
        }
        iTunesApi::CFRelease(cfValue); 
        return true;
    };

    // 将作为消息传递出去  由外部释放
    DeviceInfo* pInfo = new DeviceInfo;
    memset(pInfo,0,sizeof(DeviceInfo));
    bool bRet = false;
#define CC(A,B) f_Dev_Info( pDevice, 0, A, B, sizeof(B));
#define CN64(A,B,C ) f_Dev_Info( pDevice, A,B, &C, 1 );
#define CN32(A,B,C ) f_Dev_Info( pDevice, A,B, &C, 0 );
    CC("DeviceName", pInfo->sDeviceName);
    CC("DeviceClass", pInfo->sDeviceType);
    CC("ProductType", pInfo->sProductType);
    CC("ProductVersion", pInfo->sOsVersion);
    CC("SerialNumber", pInfo->sSerialNum); 
    CC("UniqueDeviceID", pInfo->sDeviceId);
    CC("ModelNumber", pInfo->sDeviceModel);
    CC("BuildVersion",pInfo->sDeviceVersion);
    CC("HardwareModel",pInfo->sHardwareModel);
    CC("DeviceColor", pInfo->sDeviceColor);
    CC("DeviceEnclosureColor", pInfo->sDeviceColor);
    CC("RegionInfo", pInfo->sRegionInfo);//购买地区(中国、美国、香港等)
    CC("CPUArchitecture", pInfo->sCpuInfo);
    CC("WiFiAddress", pInfo->sWifiAddress);
    CC("BluetoothAddress", pInfo->sBthAddress);
    CC("FirmwareVersion",pInfo->sFirmwareVersion);
    CC("ActivationState", pInfo->sActiveState);
    CN32(NULL,"ActivationStateAcknowledged", pInfo->bActiveAck);
    CC("BasebandVersion", pInfo->sBootVersion);
    CC("BasebandBootloaderVersion", pInfo->sBootloaderVersion);
    CN32(NULL, "BasebandChipId",pInfo->nBootChipId);
    CN32(NULL, "BasebandGoldCertId", pInfo->nBootCertId);
    CC("IntegratedCircuitCardIdentity", pInfo->sICCID);
    CC("InternationalMobileEquipmentIdentity",pInfo->sIMEI);
    CC("InternationalMobileSubscriberIdentity",pInfo->sIMSI);
    CC("MLBSerialNumber",pInfo->sMLBSerialNum); 
    CC("MobileSubscriberCountryCode", pInfo->sSubscriberCountryCode);
    CC("MobileSubscriberNetworkCode", pInfo->sSubscriberNetworkCode); 
    CN32( NULL, "PasswordProtected", pInfo->bPasswordProtected); 
    CC("PhoneNumber", pInfo->sPhoneNum);
    CN32(NULL,"ProductionSOC", pInfo->bProductSOC);
    //CC("SDIOProductInfo", pInfo->sSDIOInfo);
    CC("SIMStatus", pInfo->sSimStatus);
    CC("TimeZone", pInfo->sTimeZone);
    CN64(NULL,"UniqueChipID", pInfo->nChipId); 
    f_Dev_Info( pDevice, "com.apple.international","Keyboard", pInfo->sKeyBoard, sizeof(pInfo->sKeyBoard)); 

    CN64( "com.apple.disk_usage", "TotalDiskCapacity", pInfo->disk_info.nDiskAll);          //总内存容量
    CN64( "com.apple.disk_usage", "TotalDataCapacity", pInfo->disk_info.nDataAll);          //占用内存容量
    CN64( "com.apple.disk_usage", "TotalDataAvailable", pInfo->disk_info.nDataFree);        //剩余内存容量
    CN64( "com.apple.disk_usage", "TotalSystemCapacity", pInfo->disk_info.nSysAll);         //系统总容量
    CN64( "com.apple.disk_usage", "TotalSystemAvailable", pInfo->disk_info.nSysFree);       //系统容量(可用)
    CN64( "com.apple.disk_usage", "MobileApplicationUsage", pInfo->disk_info.nAppUsed);     //应用程序占内存大小
    CN32( "com.apple.mobile.battery","BatteryCurrentCapacity", pInfo->battery_info.current);//电池容量
    CN32( "com.apple.mobile.battery","BatteryIsCharging", pInfo->battery_info.is_charging); 

    // 越狱标志
    afc_connection* pSocket = NULL;
    pInfo->bBreakedStatus = true;
    // 打开AFC服务
    nMach_error = iTunesApi::AMDeviceStartService( pDevice, iTunesApi::__CFStringMakeConstantString("com.apple.afc2"), &pSocket, NULL);
    if(nMach_error)
    {
        closesocket((SOCKET)pSocket);
        pInfo->bBreakedStatus = false;
    }
    // 断开连接
    DisConnectDevice( pDevice ); 
    GetDeviceInfoEx(pDevice,pInfo);
    PostMessage(hWnd,MSG_DEVICEINFO,MDERR_OK,(LPARAM)pInfo);
    GetAppDetail(pDevice,hWnd);
}

// 获取磁盘占用信息
bool CPhoneMgr::GetDeviceInfoEx( am_device* pDevice, DeviceInfo* pInfo )
{
    HAFC_ENV pAfc = Afc_Open(pDevice);
    if( !pAfc)
        return false;
    Afc_Dirinfo_t di; 

    GetDirInfo( pAfc, "/DCIM", &di ); 
    pInfo->disk_info.nPicUsed = di.di_total_size; 

    GetDirInfo( pAfc, "/Books", &di ); 
    pInfo->disk_info.nEbookUsed = di.di_total_size;

    GetDirInfo( pAfc, "/iTunes_Control/Music", &di ); 
    pInfo->disk_info.nMusicUsed = di.di_total_size;

    GetDirInfo( pAfc, "/iTunes_Control/Sync/Media", &di ); 
    pInfo->disk_info.nVideoUsed = di.di_total_size; 

    GetDirInfo( pAfc, "/general_storage", &di ); 
    pInfo->disk_info.nMobileUsed = di.di_total_size; 

    Afc_Close( pAfc ); 
    return true;
}

// 连接设备
mach_error_t CPhoneMgr::ConnectDevice( am_device* pDev )
{
    mach_error_t ret = MDERR_OK; 
    int nTryTimes = 3;
    do 
    {
        ret = iTunesApi::AMDeviceConnect(pDev);
        if (ret) 
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"Could not connect Device [AMDeviceConnect:"<<ret<<"]");
            --nTryTimes;
            continue;
        }

        ret = iTunesApi::AMDeviceIsPaired(pDev);
        if (!ret)
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"Could not pair Device [AMDeviceIsPaired:"<<ret<<"]");
            --nTryTimes;
            continue;
        }

        ret = iTunesApi::AMDeviceValidatePairing(pDev);
        if (ret)
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"Could not validate device pairing [AMDeviceValidatePairing:"<<ret<<"]");
            --nTryTimes;
            continue;
        }

        ret = iTunesApi::AMDeviceStartSession(pDev);
        if (ret)
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"Could not start session [AMDeviceStartSession:"<<ret<<"]");
            --nTryTimes;
            continue;
        }
        break;
    } while (nTryTimes>0);
    return ret; 
}

// 断开连接
mach_error_t CPhoneMgr::DisConnectDevice( am_device* device )
{
    mach_error_t ret = MDERR_OK; 
    do 
    {
        ret = iTunesApi::AMDeviceStopSession(device);
        if (ret)
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"Could not Stop session [AMDeviceStopSession:"<<ret<<"]");
            break;
        }
        ret = iTunesApi::AMDeviceDisconnect(device);
        if (ret)
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"Could not Disconnect device [AMDeviceDisconnect:"<<ret<<"]");
            break;
        }
    } while (0);

    return ret;
}

// 打开并连接到AFC服务
HAFC_ENV CPhoneMgr::Afc_Open( am_device* device )
{
    if( MDERR_OK !=ConnectDevice( device ) )
        return NULL; 

    afc_connection* pSocket = NULL;
    // 打开AFC服务
    mach_error_t ret = iTunesApi::AMDeviceStartService( (am_device*)device, iTunesApi::__CFStringMakeConstantString("com.apple.afc"), &pSocket, NULL);
    DisConnectDevice( device ); 
    if( ret ) 
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AMDeviceStartService faild:"<<ret);
        return NULL;
    }

    afc_connection* pAfc;
    // 连接到AFC
    ret = iTunesApi::AFCConnectionOpen( pSocket, 0, &pAfc); 
    if(ret)
    {
        closesocket((SOCKET)pSocket);
        LOG4CPLUS_ERROR(Logger::getRoot(),"AFCConnectionOpen faild:"<<ret);
        return NULL; 
    }
    ///
    Afc_Env_t* pAfc_Env = new Afc_Env_t;
    memset(pAfc_Env,0,sizeof(Afc_Env_t));
    pAfc_Env->pSocket = pSocket;
    pAfc_Env->pAfc = pAfc;
    /
    return pAfc_Env;
}

// 关闭AFC连接
void CPhoneMgr::Afc_Close( HAFC_ENV pAfcEnv )
{
    if(!pAfcEnv)
        return;

    iTunesApi::AFCConnectionClose( pAfcEnv->pAfc);
    closesocket((SOCKET)pAfcEnv->pSocket); 

    delete pAfcEnv; 
    pAfcEnv = NULL;
}

// 获取目录信息
bool CPhoneMgr::GetDirInfo( HAFC_ENV pAfc,const char* sRemotePath, Afc_Dirinfo_t* di )
{
    if(!pAfc || !di || !sRemotePath )
        return false; 

    memset( di, 0, sizeof(*di)); 
    
    Afc_Stat_t st; 
    if( !GetStatInfo( pAfc, sRemotePath, &st)) 
        return false;
    // 是否目录
    if( st.st_mode != S_IFDIR )
        return false;

    di->di_ctime = st.st_ctime;
    di->di_mtime = st.st_mtime; 

    // 获取详细信息
    return GetDirInfoDetail( pAfc, sRemotePath, di );
}

// 获取文件属性
bool CPhoneMgr::GetStatInfo( HAFC_ENV pAfc, const char* path, Afc_Stat_t* st )
{
    if( !pAfc || !st ) 
        return false; 

    memset( st, 0, sizeof(*st) );
    mach_error_t ret;
    struct afc_dictionary *pInfo;
    char *pKey, *pVal;
    unsigned int size = 0;
    ret = iTunesApi::AFCFileInfoOpen( pAfc->pAfc, (char*)path, &pInfo);
    if (ret) 
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AFCFileInfoOpen path["<<path<<"] faild:"<<ret);
        return false;
    }
    ret = iTunesApi::AFCKeyValueRead(pInfo, &pKey, &pVal);
    while( pKey || pVal ) 
    {
        if (pKey == NULL || pVal == NULL)
            break;
        if (!_stricmp(pKey, "st_size")) 
        {
            st->st_size = _atoi64(pVal);
        }
        else if( !_stricmp( pKey, "st_ifmt"))
        {
            if( _stricmp(pVal,"S_IFDIR")==0) 
                st->st_mode = S_IFDIR; 
            else 
                st->st_mode = S_IFREG;
        }
        else if( !_stricmp( pKey,"st_mtime"))
        {
            st->st_mtime = (time_t)(_atoi64(pVal)/1000000000);
        }
        else if( !_stricmp( pKey,"st_birthtime"))
        {
            st->st_ctime = (time_t)(_atoi64(pVal)/1000000000);
        }
        iTunesApi::AFCKeyValueRead(pInfo, &pKey, &pVal);
    }
    iTunesApi::AFCKeyValueClose(pInfo);

    return true;
}

// 获取目录详细信息
bool CPhoneMgr::GetDirInfoDetail( HAFC_ENV pAfc,const char* sRemotePath, Afc_Dirinfo_t* di )
{
    HAFC_HANDLE pDirHandle = Afc_Open_Dir( pAfc, sRemotePath );
    if( !pDirHandle )
    {
        ++di->di_error_count;
        return false; 
    }
    const char* name;
    while( name = Afc_Read_Dir( pDirHandle))
    {
        if( _stricmp(name,".")==0 || _stricmp( name,"..")==0)
            continue; 
        char path[512]; 
        sprintf_s( path,"%s/%s", sRemotePath, name ); 
        Afc_Stat_t st; 
        if( !GetStatInfo( pAfc, path, &st)) 
        {
            ++di->di_error_count;
            continue; 
        }
        if( st.st_mode == S_IFDIR)
        { // dir
            di->di_dir_count++;
            GetDirInfoDetail( pAfc, path, di ); 
        }
        else
        {
            di->di_file_count++;
            di->di_total_size += st.st_size ; 
        }
    }
    Afc_Close_Handle( pDirHandle ); 

    return true;
}

// 打开AFC目录
HAFC_HANDLE CPhoneMgr::Afc_Open_Dir( HAFC_ENV pAfc, const char* path )
{
    if(!pAfc || !path)
        return NULL;

    struct afc_directory *pDir;
    mach_error_t ret;

    ret = iTunesApi::AFCDirectoryOpen( pAfc->pAfc, (char*)path, &pDir );
    if (ret) 
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AFCDirectoryOpen["<<path<<"] faild:"<<ret);
        return NULL;
    }

    Afc_Handle_t* h = new Afc_Handle_t;
    memset( h, 0, sizeof(Afc_Handle_t));
    h->pEnv = pAfc;
    h->bIsDir = true;
    h->pDir = pDir;

    return h; 
}

// 读取目录信息
const char* CPhoneMgr::Afc_Read_Dir( HAFC_HANDLE pDir )
{
    if(!pDir ||!pDir->pDir)
        return NULL; 

    char *pEntry = NULL ;
    mach_error_t ret;
    ret = iTunesApi::AFCDirectoryRead(pDir->pEnv->pAfc,pDir->pDir, &pEntry);
    if (ret) 
    {
        //printf("AFCDirectoryRead() = %d\n", ret );
        LOG4CPLUS_ERROR(Logger::getRoot(),"AFCDirectoryRead faild:"<<ret);
    }
    return pEntry; 
}

// 关闭AFC句柄
void CPhoneMgr::Afc_Close_Handle( HAFC_HANDLE handle )
{
    if(!handle)
        return;

    if( handle->pFile)
        iTunesApi::AFCFileRefClose( handle->pEnv->pAfc, handle->pFile);
    if( handle->pDir)
        iTunesApi::AFCDirectoryClose( handle->pEnv->pAfc, handle->pDir);

    delete handle;
    handle = NULL;
}

// 获取APP信息线程
void CPhoneMgr::GetDeviceAppThread(am_device* pDevice,HWND hWnd)
{
    LOG4CPLUS_DEBUG(Logger::getRoot(),"GetDeviceAppThread begin device_id:"<<pDevice->device_id);
    // 连接手机
    if( MDERR_OK!=ConnectDevice(pDevice))
    {
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return;
    }

    afc_connection* fd;
    // 开启com.apple.mobile.installation_proxy 服务
    mach_error_t ret = iTunesApi::AMDeviceStartService(pDevice, iTunesApi::__CFStringMakeConstantString("com.apple.mobile.installation_proxy"), &fd, NULL);
    DisConnectDevice(pDevice); // 及时断开手机连接
    if( ret )
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AMDeviceStartService[com.apple.mobile.installation_proxy] faild:"<<ret);
        PostMessage(hWnd,MSG_DEVICEAPP,ret,(LPARAM)NULL);
        return;
    }

    // 
    CFDictionaryRef cfDicRef_Req = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL); 
    if( !cfDicRef_Req ) 
    { 
        closesocket((SOCKET)fd);
        LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryCreateMutable( NULL,0,NULL,NULL) faild");
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return ;
    }
    CFDictionaryRef cfDicRef_Opt = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL);  
    if( !cfDicRef_Opt ) 
    { 
        iTunesApi::CFRelease(cfDicRef_Req); 
        closesocket((SOCKET)fd); 
        LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryCreateMutable( NULL,0,NULL,NULL) faild");
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return ; 
    }
    CFMutableArrayRef cfMutArrRef = iTunesApi::CFArrayCreateMutable( NULL, 0, NULL );
    if( !cfMutArrRef ) 
    { 
        iTunesApi::CFRelease(cfDicRef_Req); 
        iTunesApi::CFRelease(cfDicRef_Opt); 
        closesocket((SOCKET)fd); 
        LOG4CPLUS_ERROR(Logger::getRoot(),"CFArrayCreateMutable( NULL,0,NULL,NULL) faild");
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return ; 
    }

    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("CFBundleIdentifier"));
    //iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("StaticDiskUsage")); 
    //iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("DynamicDiskUsage"));
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("iTunesMetadata"));
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("CFBundleName"));
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("CFBundleExecutable"));
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("CFBundleDisplayName"));
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("CFBundleVersion"));

    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Opt, (void*)iTunesApi::__CFStringMakeConstantString("ReturnAttributes"), (void*)cfMutArrRef );
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Opt, (void*)iTunesApi::__CFStringMakeConstantString("ApplicationType"),(void*)iTunesApi::__CFStringMakeConstantString("User") );
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Req, (void*)iTunesApi::__CFStringMakeConstantString("Command"), (void*)iTunesApi::__CFStringMakeConstantString("Browse") ); 
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Req, (void*)iTunesApi::__CFStringMakeConstantString("ClientOptions"), (void*)cfDicRef_Opt ); 

    bool bHadTotal = false;
    int nAppIndex = 0; 
    int nAppTotal = 0;
    //boost::shared_ptr<AppArray> pAppArray;// = NULL;
    AppArray* pAppArray = NULL;
    //pAppArray.
    LOG4CPLUS_DEBUG(Logger::getRoot(),"Send_Xml_Request for get applist");
    bool bSend = Send_Xml_Request( fd, cfDicRef_Req); 
    while(bSend)
    {
        CFPropertyListRef cfPlRef_Res = Recv_Xml_Response(fd );
        if( !cfPlRef_Res )
            break; 
        CFStringRef cfRef_Status = (CFStringRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)cfPlRef_Res, iTunesApi::__CFStringMakeConstantString("Status"));
        if(!cfRef_Status)
        {
            iTunesApi::CFRelease(cfPlRef_Res);
            LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryGetValue[Status] error");
            break; 
        }
        char sStatus[64]; 
        memset(sStatus,0,64); 
        iTunesApi::CFStringGetCString( cfRef_Status, sStatus,64, kCFStringEncodingUTF8 ); 
        if( !bHadTotal )
        {
            CFNumberRef cfRefTotal = (CFNumberRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)cfPlRef_Res, iTunesApi::__CFStringMakeConstantString("Total"));
            if( !cfRefTotal )
            { 
                iTunesApi::CFRelease(cfPlRef_Res);
                LOG4CPLUS_ERROR(Logger::getRoot(),"AppTotal is 0");
                break; 
            }
            iTunesApi::CFNumberGetValue(cfRefTotal, kCFNumberSInt32Type, &nAppTotal); 
            if( nAppTotal <=0 )
            { 
                iTunesApi::CFRelease(cfPlRef_Res);
                LOG4CPLUS_ERROR(Logger::getRoot(),"AppTotal is 0");
                break; 
            }
            //boost::shared_ptr<AppArray> pTemp((AppArray*)new char[sizeof(AppArray) + nAppTotal* sizeof( AppInfo)]);
            //pAppArray = pTemp;
            pAppArray = (AppArray*)new char[sizeof(AppArray) + nAppTotal* sizeof( AppInfo)]; 
            if(!pAppArray) 
            {
                iTunesApi::CFRelease(cfPlRef_Res); 
                break; 
            } 
            pAppArray->pAppDetail = (AppInfo*)( ((char*)pAppArray) + sizeof( AppArray) );
            pAppArray->nAppCount = nAppTotal;
            memset( pAppArray->pAppDetail,0, nAppTotal*sizeof(AppInfo) );

            bHadTotal = true ;
        }
        CFArrayRef cfRefList = (CFArrayRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)cfPlRef_Res, iTunesApi::__CFStringMakeConstantString("CurrentList"));
        if( !cfRefList )
        {
            iTunesApi::CFRelease(cfPlRef_Res); 
            LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryGetValue[CurrentList] error");
            break;
        }
        int nListCount = iTunesApi::CFArrayGetCount( cfRefList ); 
        for (int i=0; i<nListCount;++i)
        {
            CFDictionaryRef cfDicRef_App=(CFDictionaryRef)iTunesApi::CFArrayGetValueAtIndex(cfRefList, i);
            AppInfo* pAppInfo = &pAppArray->pAppDetail[nAppIndex++]; 
            pAppInfo->bDel = false;
            CFString2CString((CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App,iTunesApi::__CFStringMakeConstantString("CFBundleIdentifier"))
                ,pAppInfo->sAppleID
                ,sizeof(pAppInfo->sAppleID));
            CFString2CString((CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App,iTunesApi::__CFStringMakeConstantString("CFBundleName"))
                ,pAppInfo->sName
                ,sizeof(pAppInfo->sName));
            CFString2CString((CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App,iTunesApi::__CFStringMakeConstantString("CFBundleDisplayName"))
                ,pAppInfo->sDisplayName
                ,sizeof(pAppInfo->sDisplayName));
            CFString2CString((CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App,iTunesApi::__CFStringMakeConstantString("CFBundleVersion"))
                ,pAppInfo->sVersion
                ,sizeof(pAppInfo->sVersion));
            if( strlen(pAppInfo->sDisplayName)<=0 ) 
            {
                strcpy( pAppInfo->sDisplayName,pAppInfo->sName); 
                if( strlen(pAppInfo->sDisplayName)<=0) 
                    CFString2CString((CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App,iTunesApi::__CFStringMakeConstantString("CFBundleExecutable"))
                    ,pAppInfo->sDisplayName
                    ,sizeof(pAppInfo->sDisplayName));
            }
        }
        iTunesApi::CFRelease( cfPlRef_Res ); 
        if( _stricmp( sStatus,"BrowsingApplications") !=0 ) 
            break; 
        if( nAppIndex>= nAppTotal)
            break; 
    }
    closesocket((SOCKET)fd);
    iTunesApi::CFRelease( cfDicRef_Req); 
    iTunesApi::CFRelease( cfDicRef_Opt);
    iTunesApi::CFRelease( cfMutArrRef);
    
    // 获取APP图标
    if(bHadTotal)
    {
        AppGetIconFile(pDevice, pAppArray->pAppDetail, pAppArray->nAppCount);
        LOG4CPLUS_DEBUG(Logger::getRoot(),"GetDeviceAppThread Suc AppCount:"<<nAppTotal);
    }
    PostMessage(hWnd,MSG_DEVICEAPP,MDERR_OK,(LPARAM)pAppArray);

    // 获取APP大小
    // 连接手机
    if( MDERR_OK!=ConnectDevice(pDevice))
    {
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return;
    }

    // 开启com.apple.mobile.installation_proxy 服务
    ret = iTunesApi::AMDeviceStartService(pDevice, iTunesApi::__CFStringMakeConstantString("com.apple.mobile.installation_proxy"), &fd, NULL);
    DisConnectDevice(pDevice); // 及时断开手机连接

    cfDicRef_Req = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL); 
    if( !cfDicRef_Req ) 
    { 
        closesocket((SOCKET)fd);
        LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryCreateMutable( NULL,0,NULL,NULL) faild");
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return ;
    }
    cfDicRef_Opt = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL);  
    if( !cfDicRef_Opt ) 
    { 
        iTunesApi::CFRelease(cfDicRef_Req); 
        closesocket((SOCKET)fd); 
        LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryCreateMutable( NULL,0,NULL,NULL) faild");
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return ; 
    }
    cfMutArrRef = iTunesApi::CFArrayCreateMutable( NULL, 0, NULL );
    if( !cfMutArrRef ) 
    { 
        iTunesApi::CFRelease(cfDicRef_Req); 
        iTunesApi::CFRelease(cfDicRef_Opt); 
        closesocket((SOCKET)fd); 
        LOG4CPLUS_ERROR(Logger::getRoot(),"CFArrayCreateMutable( NULL,0,NULL,NULL) faild");
        PostMessage(hWnd,MSG_DEVICEAPP,1,(LPARAM)NULL);
        return ; 
    }

    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("CFBundleIdentifier"));
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("StaticDiskUsage")); 
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("DynamicDiskUsage"));
    iTunesApi::CFArrayAppendValue(cfMutArrRef,iTunesApi::__CFStringMakeConstantString("iTunesMetadata"));

    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Opt, (void*)iTunesApi::__CFStringMakeConstantString("ReturnAttributes"), (void*)cfMutArrRef );
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Opt, (void*)iTunesApi::__CFStringMakeConstantString("ApplicationType"),(void*)iTunesApi::__CFStringMakeConstantString("User") );
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Req, (void*)iTunesApi::__CFStringMakeConstantString("Command"), (void*)iTunesApi::__CFStringMakeConstantString("Browse") ); 
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)cfDicRef_Req, (void*)iTunesApi::__CFStringMakeConstantString("ClientOptions"), (void*)cfDicRef_Opt ); 

    bHadTotal = false;
    nAppIndex = 0; 
    nAppTotal = 0;
    bSend = Send_Xml_Request( fd, cfDicRef_Req); 
    while(bSend)
    {
        CFPropertyListRef cfPlRef_Res = Recv_Xml_Response(fd );
        if( !cfPlRef_Res )
            break; 
        CFStringRef cfRef_Status = (CFStringRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)cfPlRef_Res, iTunesApi::__CFStringMakeConstantString("Status"));
        if(!cfRef_Status)
        {
            iTunesApi::CFRelease(cfPlRef_Res);
            LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryGetValue[Status] error");
            break; 
        }
        char sStatus[64]; 
        memset(sStatus,0,64); 
        iTunesApi::CFStringGetCString( cfRef_Status, sStatus,64, kCFStringEncodingUTF8 );
        if( !bHadTotal )
        {
            CFNumberRef cfRefTotal = (CFNumberRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)cfPlRef_Res, iTunesApi::__CFStringMakeConstantString("Total"));
            if( !cfRefTotal )
            { 
                iTunesApi::CFRelease(cfPlRef_Res);
                LOG4CPLUS_ERROR(Logger::getRoot(),"AppTotal is 0");
                break; 
            }
            iTunesApi::CFNumberGetValue(cfRefTotal, kCFNumberSInt32Type, &nAppTotal); 
            if( nAppTotal <=0 )
            { 
                iTunesApi::CFRelease(cfPlRef_Res);
                LOG4CPLUS_ERROR(Logger::getRoot(),"AppTotal is 0");
                break; 
            }

            bHadTotal = true ;
        }
        CFArrayRef cfRefList = (CFArrayRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)cfPlRef_Res, iTunesApi::__CFStringMakeConstantString("CurrentList"));
        if( !cfRefList )
        {
            iTunesApi::CFRelease(cfPlRef_Res); 
            LOG4CPLUS_ERROR(Logger::getRoot(),"CFDictionaryGetValue[CurrentList] error");
            break;
        }
        int nListCount = iTunesApi::CFArrayGetCount( cfRefList ); 
        for (int i=0; i<nListCount;++i)
        {
            ++nAppIndex;
            CFDictionaryRef cfDicRef_App=(CFDictionaryRef)iTunesApi::CFArrayGetValueAtIndex(cfRefList, i);
            AppInfo* pAppInfo = NULL;
            char sAppleID[256];
            CFString2CString((CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App,iTunesApi::__CFStringMakeConstantString("CFBundleIdentifier"))
                ,sAppleID,sizeof(sAppleID));

            for (int j = 0;j<pAppArray->nAppCount;++j)
            {
                AppInfo* pAppFind = &pAppArray->pAppDetail[j]; 
                if(strcmp(pAppFind->sAppleID,sAppleID) == 0)
                {
                    pAppInfo = pAppFind;
                    break;
                }
            }
            if(pAppInfo == NULL)
                continue;

            CFNumberRef d1 = (CFNumberRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App, iTunesApi::__CFStringMakeConstantString("StaticDiskUsage"));
            CFNumberRef d2 = (CFNumberRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App, iTunesApi::__CFStringMakeConstantString("DynamicDiskUsage"));
            if(d1) iTunesApi::CFNumberGetValue( (CFNumberRef)d1, kCFNumberSInt64Type, &pAppInfo->nStaticSize); 
            if(d1) iTunesApi::CFNumberGetValue( (CFNumberRef)d2, kCFNumberSInt64Type, &pAppInfo->nDynamicSize);

            CFDictionaryRef cfDicRef_iIMD = NULL;
            CFDataRef cfIData = (CFDataRef)iTunesApi::CFDictionaryGetValue(cfDicRef_App, iTunesApi::__CFStringMakeConstantString("iTunesMetadata"));
            if(cfIData)
            {
                cfDicRef_iIMD = (CFDictionaryRef)iTunesApi::CFPropertyListCreateFromXMLData( 0, cfIData,0,0);            
            }
            else//尝试读取 iTunesMetadata.plist
            {
                cfDicRef_iIMD = Get_iTunesMetadata( pDevice, pAppInfo->sAppleID ); 
            }

            if(cfDicRef_iIMD)
            {
                CFString2CString( (CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_iIMD, iTunesApi::__CFStringMakeConstantString("genre")), pAppInfo->sAppClass, sizeof(pAppInfo->sAppClass));
                CFString2CString( (CFStringRef)iTunesApi::CFDictionaryGetValue(cfDicRef_iIMD, iTunesApi::__CFStringMakeConstantString("appleId")), pAppInfo->sAccount ,sizeof(pAppInfo->sAccount));
                CFNumberRef cfNumDef_Tmp = (CFNumberRef)iTunesApi::CFDictionaryGetValue(cfDicRef_iIMD, iTunesApi::__CFStringMakeConstantString("genreId")); 
                if(cfNumDef_Tmp)
                    iTunesApi::CFNumberGetValue(cfNumDef_Tmp, kCFNumberSInt32Type, &pAppInfo->nAppClassId);
                cfNumDef_Tmp = (CFNumberRef)iTunesApi::CFDictionaryGetValue( cfDicRef_iIMD, iTunesApi::__CFStringMakeConstantString("softwareVersionExternalIdentifier"));
                if(cfNumDef_Tmp) 
                    iTunesApi::CFNumberGetValue(cfNumDef_Tmp, kCFNumberSInt32Type, &pAppInfo->nExternalVer);
                CFDictionaryRef dd = (CFDictionaryRef)iTunesApi::CFDictionaryGetValue( cfDicRef_iIMD, iTunesApi::__CFStringMakeConstantString("com.apple.iTunesStore.downloadInfo"));
                if( dd )
                {
                    CFDictionaryRef kk = (CFDictionaryRef)iTunesApi::CFDictionaryGetValue(dd, iTunesApi::__CFStringMakeConstantString("accountInfo"));
                    if(kk)
                    {
                        CFString2CString( (CFStringRef)iTunesApi::CFDictionaryGetValue(kk, iTunesApi::__CFStringMakeConstantString("AppleID")), pAppInfo->sAccount ,sizeof(pAppInfo->sAccount));                        
                    }
                }
                iTunesApi::CFRelease(cfDicRef_iIMD);
            }
        }
        iTunesApi::CFRelease( cfPlRef_Res ); 
        if( _stricmp( sStatus,"BrowsingApplications") !=0 ) 
            break; 
        if( nAppIndex>= nAppTotal)
            break; 
    }
    closesocket((SOCKET)fd);
    iTunesApi::CFRelease( cfDicRef_Req); 
    iTunesApi::CFRelease( cfDicRef_Opt);
    iTunesApi::CFRelease( cfMutArrRef);

    PostMessage(hWnd,MSG_DEVICEAPPEX,MDERR_OK,(LPARAM)pAppArray);
}

// 获取APP信息接口
void CPhoneMgr::GetAppDetail( am_device* pDevice,HWND hWnd/* = NULL*/)
{
    if(hWnd == NULL)
        hWnd = (HWND)m_pUserData;
    if(!pDevice)
    {
        LOG4CPLUS_DEBUG(Logger::getRoot(),"Call GetAppDetail failed:pDevice is null");
        PostMessage(hWnd,MSG_DEVICEAPP,1,0);
        return;
    }

    // 启动线程获取基础信息
    boost::thread thread(boost::bind(&CPhoneMgr::GetDeviceAppThread,this,pDevice,hWnd));
}

// 获取APP图标信息
void CPhoneMgr::AppGetIconFile(am_device* pDevice,AppInfo* pAppDetail, int nAppCount)
{
    ///
    char path[512];
    memset(path,0,512);
    Common_Data_Path( path ); 
    strcat( path, "\\app_icons" ); 
    CreateDirectoryA(path, NULL); 

    bool bPar = false;

    afc_connection* fd;
    for(int i=0; i< nAppCount ; ++i )
    {
        CFDictionaryRef req = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL);
        if(!req)
            continue; 

        AppInfo* a = &pAppDetail[i];

        // 判断图标是否存在
        char png_path[260]; 
        sprintf( png_path, "%s\\%s_icon.png", path, a->sAppleID); 
        if(_access(png_path,0) == 0)
        {
            strcpy( a->sLogoPath, png_path ); 
            continue;
        }

        if (bPar == false)
        {
            //LOG4CPLUS_DEBUG(Logger::getRoot(),"AppGetIconFile Begin");
            if( MDERR_OK != ConnectDevice(pDevice)) 
            {
                LOG4CPLUS_ERROR(Logger::getRoot(),"AppGetIconFile faild when ConnectDevice(),try again");
                if( MDERR_OK != ConnectDevice(pDevice)) 
                {
                    LOG4CPLUS_ERROR(Logger::getRoot(),"AppGetIconFile faild when ConnectDevice()");
                    return ; 
                }
            }
            

            mach_error_t ret = iTunesApi::AMDeviceStartService(pDevice, iTunesApi::__CFStringMakeConstantString("com.apple.springboardservices"), &fd, NULL);
            DisConnectDevice(pDevice); 
            if( ret )
            {
                //sprintf( apple_errmsg, "start installation_proxy error <%u>" , ret );
                LOG4CPLUS_ERROR(Logger::getRoot(),"AMDeviceStartService[com.apple.springboardservices] error");
                return ; 
            }
            
            bPar = true;
        }

        CFStringRef sapp_id = iTunesApi::CFStringCreateWithCString( NULL, a->sAppleID, kCFStringEncodingUTF8 ); 
        if( !sapp_id)
        {
            iTunesApi::CFRelease( req); 
            continue; 
        }
        iTunesApi::CFDictionaryAddValue((CFMutableDictionaryRef)(req), (void*)iTunesApi::__CFStringMakeConstantString("command"), (void*)iTunesApi::__CFStringMakeConstantString("getIconPNGData") );
        iTunesApi::CFDictionaryAddValue((CFMutableDictionaryRef)(req), (void*)iTunesApi::__CFStringMakeConstantString("bundleId"), (void*)sapp_id );
        
        bool bSend = Send_Xml_Request( fd, req ); 
        CFPropertyListRef res = 0; 
        if( bSend ) 
            res = Recv_Xml_Response( fd ); 
        if( res )
        {
            //
            CFDataRef data = (CFDataRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)res, iTunesApi::__CFStringMakeConstantString("pngData"));
            if(data )
            {
                int len = iTunesApi::CFDataGetLength( data ); 
                const void* ptr = iTunesApi::CFDataGetBytePtr( data ); 
                //char png_path[260]; 
                //sprintf( png_path, "%s\\%s_icon.png", path, a->sAppleID); 
                FILE* fp = fopen( png_path , "wb" ); 
                if(fp)
                { 
                    fwrite( ptr,1,len, fp); 
                    fclose(fp);
                    ///
                    strcpy( a->sLogoPath, png_path ); 
                }
                else 
                {
                    //printf("fopen %s error \n", png_path );
                }
            }
            ///
            iTunesApi::CFRelease( res ); 
        }
        /
        iTunesApi::CFRelease( req); 
        iTunesApi::CFRelease( sapp_id); 
    }
    /

    closesocket((SOCKET)fd);
    
    //LOG4CPLUS_DEBUG(Logger::getRoot(),"AppGetIconFile End");
}

// 发送请求包到设备
bool CPhoneMgr::Send_Xml_Request( void* pSocket,CFDictionaryRef cfDicRef )
{
    int sock = (int)pSocket; 
    CFPropertyListRef cfXml_Data = iTunesApi::CFPropertyListCreateXMLData( NULL, cfDicRef ); 
    if( !cfXml_Data )
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"CFPropertyListCreateXMLData Error");
        return false;
    }
    CFIndex cfLen = iTunesApi::CFDataGetLength( (CFDataRef)cfXml_Data ); 
    uint32_t nSendSize = htonl( cfLen );
    const void* pSendBuf = iTunesApi::CFDataGetBytePtr( (CFDataRef)cfXml_Data ); 
    // 发送长度字段和具体buf数据
    if( send( sock, (char*)&nSendSize, sizeof(nSendSize),0) != sizeof(nSendSize) || 
        send( sock, (char*)pSendBuf, cfLen,0) != cfLen )
    {
        iTunesApi::CFRelease( cfXml_Data ); 
        LOG4CPLUS_ERROR(Logger::getRoot(),"Send_Xml_Request send Error");
        return false;
    }
    iTunesApi::CFRelease( cfXml_Data ); 

    return true; 
}

// 从设备接收请求数据
CFPropertyListRef CPhoneMgr::Recv_Xml_Response( void* pSocket )
{
    CFPropertyListRef cfPlRef_Res = NULL;
    int sock = (int)pSocket; 
    uint32_t nBufSize; 
    // 先接收Response数据长度
    if( sizeof(nBufSize) != recv( sock, (char*)&nBufSize, sizeof(nBufSize),0) )
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"Recv_Xml_Response recv ResponseLen error");
        return cfPlRef_Res; // NULL
    }
    nBufSize = ntohl(nBufSize); 
    if( nBufSize==0) 
        return cfPlRef_Res; // NULL

    char* pBuf = new char[nBufSize];
    int pos = 0; 
    // 开始接收数据
    while( pos<nBufSize )
    {
        int nRecv = recv( sock, pBuf+pos, nBufSize-pos, 0); 
        if( nRecv <=0)
        {
            delete[] pBuf;
            LOG4CPLUS_ERROR(Logger::getRoot(),"Recv_Xml_Response recv data error");
            return NULL;
        }
        pos += nRecv; 
    }
    CFDataRef dd = iTunesApi::CFDataCreateWithBytesNoCopy( 0, (UInt8*)pBuf, nBufSize, iTunesApi::s_kCFAllocatorNull ); 
    cfPlRef_Res = iTunesApi::CFPropertyListCreateFromXMLData(0,dd,0,0);
    iTunesApi::CFRelease( dd ); 
    delete[] pBuf;
    return cfPlRef_Res; 
}

// 尝试读取iTunesMetadata数据
CFDictionaryRef CPhoneMgr::Get_iTunesMetadata(am_device* pDevice, const char* apple_id )
{
    CFDictionaryRef cfDicRef_Res = NULL; 
    HAFC_ENV pEvn = App_Open_Dir(pDevice, apple_id); 
    if( !pEvn) 
        return NULL ;
    Afc_Stat_t st; 
    const char* itunes = "/iTunesMetadata.plist"; 
    if( !GetStatInfo( pEvn, itunes, &st )) 
    {
        Afc_Close( pEvn );
        return NULL; 
    }
    HAFC_HANDLE h = Afc_Open_File( pEvn, itunes , "r"); 
    if( !h )
    {
        Afc_Close( pEvn); 
        return NULL; 
    }
    char* buf = new char[st.st_size];
    if( !buf)
    { 
        Afc_Close_Handle( h ); 
        Afc_Close( pEvn ); 
        return NULL;
    }
    int pos = 0; 
    while( pos < st.st_size )
    {
        int len = Afc_Read_File( h, buf + pos, st.st_size - pos ); 
        if( len <=0 ) 
            break;
        pos += len ; 
    }    
    Afc_Close_Handle( h ); 
    Afc_Close( pEvn ); 
    ///
    CFDataRef dd = iTunesApi::CFDataCreateWithBytesNoCopy( 0, (UInt8*)buf, st.st_size, iTunesApi::s_kCFAllocatorNull ); 
    cfDicRef_Res = (CFDictionaryRef)iTunesApi::CFPropertyListCreateFromXMLData(0,dd,0,0);
    iTunesApi::CFRelease(dd);
    delete[] buf; 
    /
    return cfDicRef_Res; 
}

// 打开APP程序包路径
HAFC_ENV CPhoneMgr::App_Open_Dir( am_device* pDevice, const char* apple_id)
{
    ///
    if(MDERR_OK != ConnectDevice(pDevice))
        return NULL;

    afc_connection* fd = NULL;
    mach_error_t ret = iTunesApi::AMDeviceStartService( pDevice, iTunesApi::__CFStringMakeConstantString("com.apple.mobile.house_arrest"), &fd, NULL);
    DisConnectDevice(pDevice); 
    if( ret ) 
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AMDeviceStartService[com.apple.mobile.house_arrest] error");
        return NULL;
    }
    
    CFDictionaryRef res = NULL;
    CFStringRef cfRef_AppID = iTunesApi::CFStringCreateWithCString( NULL, apple_id, kCFStringEncodingUTF8 );
    if( !cfRef_AppID) 
    {
        closesocket((SOCKET)fd); 
        return NULL; 
    }
    CFDictionaryRef cfDicRef_Req = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL); 
    if(!cfDicRef_Req)
    { 
        iTunesApi::CFRelease(cfRef_AppID); 
        closesocket((SOCKET)fd); 
        return NULL; 
    }
    //    iTunesApi::CFDictionaryAddValue((CFMutableDictionaryRef)(mp), (void*)(k), (void*)(v) )
    iTunesApi::CFDictionaryAddValue((CFMutableDictionaryRef)cfDicRef_Req,(void*)iTunesApi::__CFStringMakeConstantString("Command"), (void*)iTunesApi::__CFStringMakeConstantString("VendContainer")); 
    iTunesApi::CFDictionaryAddValue((CFMutableDictionaryRef)cfDicRef_Req,(void*)iTunesApi::__CFStringMakeConstantString("Identifier"), (void*)cfRef_AppID ); 
    bool bSend = Send_Xml_Request( fd, cfDicRef_Req ); 
    if( !bSend ) 
    {
        iTunesApi::CFRelease(cfDicRef_Req); 
        iTunesApi::CFRelease(cfRef_AppID); 
        closesocket((SOCKET)fd); 
        return NULL;
    }
    CFPropertyListRef cfPlRef_Res = Recv_Xml_Response( fd ); 
    if( !cfPlRef_Res )
    {
        iTunesApi::CFRelease(cfDicRef_Req); 
        iTunesApi::CFRelease(cfRef_AppID); 
        closesocket((SOCKET)fd); 
        return NULL;
    }
    if( iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)cfPlRef_Res, iTunesApi::__CFStringMakeConstantString("Error") ) )
    {
        iTunesApi::CFRelease(cfDicRef_Req); 
        iTunesApi::CFRelease(cfRef_AppID); 
        iTunesApi::CFRelease(cfPlRef_Res); 
        closesocket((SOCKET)fd); 
        return NULL; 
    }
    iTunesApi::CFRelease(cfPlRef_Res); 

    afc_connection* afc;
    ret = iTunesApi::AFCConnectionOpen( fd, 0, &afc); 
    if(ret)
    {
        iTunesApi::CFRelease(cfDicRef_Req); 
        iTunesApi::CFRelease(cfRef_AppID);
        closesocket((SOCKET)fd); 
        return NULL; 
    }
    ///

    Afc_Env_t* pEnv = new Afc_Env_t;
    memset(pEnv,0,sizeof(Afc_Env_t));
    pEnv->pAfc = afc;
    pEnv->pSocket = fd; 
    return pEnv; 
}

// AFC打开文件
HAFC_HANDLE CPhoneMgr::Afc_Open_File( HAFC_ENV pEnv, const char* path, const char* str_mode )
{
    if( !str_mode || !path || !pEnv ) 
        return NULL; 
    /
    unsigned int mode = 0; 
    if( _stricmp( str_mode,"r") ==0 )
    {
        mode = 1; 
    }
    else if( _stricmp( str_mode,"w")==0)
    {
        mode = 2; 
    }
    else
    {
        return NULL; 
    }
    /
    afc_file_ref handle=0;
    mach_error_t ret = iTunesApi::AFCFileRefOpen( pEnv->pAfc, (char*)path , mode , 0, &handle );
    if ( ret != MDERR_OK ) 
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AFCFileRefOpen["<<path<<"] error["<<ret<<"]");
        return NULL;
    }
    ///
    Afc_Handle_t* h = new Afc_Handle_t;
    memset(h, 0,sizeof(Afc_Handle_t));
    h->pEnv = pEnv;
    h->bIsDir = false;
    h->pFile = handle; 

    return h; 
}

// AFC读取文件
int CPhoneMgr::Afc_Read_File( HAFC_HANDLE pFile, char* buf, int len )
{
    if(!buf || len<=0 || !pFile )return -1;
    unsigned int ret_len = (unsigned int)len;
    mach_error_t ret = iTunesApi::AFCFileRefRead(pFile->pEnv->pAfc, pFile->pFile, buf, &ret_len);
    if(ret)
    {
        //printf("AFCFileRefRead() = %d\n", ret);
        LOG4CPLUS_ERROR(Logger::getRoot(),"AFCFileRefRead error["<<ret<<"]");
        return -1;
    }
    return ret_len;
}

// AFC写文件
int CPhoneMgr::Afc_Write_File( HAFC_HANDLE pFile, char* buf, int len )
{
    if(!buf || len<=0 || !pFile )
        return -1;
    mach_error_t ret; 
    unsigned int ret_len = (unsigned int)len;
    ret = iTunesApi::AFCFileRefWrite(pFile->pEnv->pAfc, pFile->pFile, buf, ret_len);
    if(ret)
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AFCFileRefWrite error["<<ret<<"]");
        return -1;
    }
    return ret_len;
}

// 获取操作系统Common_Data路径
void CPhoneMgr::Common_Data_Path( char* path )
{
    if( !::SHGetSpecialFolderPathA( NULL, path, CSIDL_COMMON_APPDATA, FALSE))
    {
        strcpy( path,"c:\\xApp_tools");
    }
    else
    {
        strcat(path, "\\xApp_tools");
    }
    CreateDirectoryA(path, NULL); 
}

// APP安装线程
bool CPhoneMgr::AppInstallThread(am_device* pDevice,const char* packetPath, DWORD dwUserdata,HWND hWnd)
{
    char install_path[260]; 
    sprintf( install_path, "/PublicStaging/%ld.ipa", time(0) ); 

    // 打开AFC服务
    HAFC_ENV afc = Afc_Open( pDevice); 
    if( !afc )
    {
        PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_ERROR,MAKELPARAM(dwUserdata,0));
        return false; 
    }

    // 上传文件
    if( Afc_UpFile( afc, install_path, packetPath, hWnd, dwUserdata))
    {
        PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_ERROR,MAKELPARAM(dwUserdata,0));
        Afc_Close( afc ); 
        return false; 
    }
    // 文件上传成功
    //PostMessage(hWnd,MSG_AFC_UPFILE,0,100);
    Afc_Close( afc ); 

    // 连接设备
    if( MDERR_OK != ConnectDevice(pDevice) ) 
    {
        PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_ERROR,MAKELPARAM(dwUserdata,0));
        return false; 
    }

    afc_connection* fd;
    afc_connection* house_arrest_fd = NULL; 
    mach_error_t ret; 
    // 打开安装服务
    ret = iTunesApi::AMDeviceStartService( pDevice, iTunesApi::__CFStringMakeConstantString("com.apple.mobile.installation_proxy"), &fd, NULL);
    DisConnectDevice(pDevice); 
    if( ret )
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AMDeviceStartService[com.apple.mobile.installation_proxy] Error:"<<ret);
        PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_ERROR,MAKELPARAM(dwUserdata,0));
        return false; 
    }
    
    CFDictionaryRef req = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL);
    CFStringRef pkt_path = iTunesApi::CFStringCreateWithCString( NULL, install_path, kCFStringEncodingUTF8 ); 
    if( !req || !pkt_path)
    {
        if( req)
            iTunesApi::CFRelease( req); 
        if( pkt_path)
            iTunesApi::CFRelease( pkt_path); 
        closesocket((SOCKET)fd); 
        LOG4CPLUS_ERROR(Logger::getRoot(),"Something Error");
        PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_ERROR,MAKELPARAM(dwUserdata,0));
        return false; 
    }

    // 构造安装命令
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)req, (void*)iTunesApi::__CFStringMakeConstantString("Command"), (void*)iTunesApi::__CFStringMakeConstantString("Install")); 
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)req, (void*)iTunesApi::__CFStringMakeConstantString("PackagePath"), (void*)pkt_path); 

    // 发送安装请求
    bool bSend = Send_Xml_Request(fd,req);
    ret = INSTALL_STATUS_OK;
    if(!bSend)
        ret = INSTALL_STATUS_ERROR;
    while( bSend )
    {
        CFPropertyListRef res = Recv_Xml_Response( fd ); 
        if( !res ) 
        {
            ret = INSTALL_STATUS_ERROR;
            break; 
        }

        CFStringRef aerr= (CFStringRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)res, iTunesApi::__CFStringMakeConstantString("Error") );
        CFStringRef astatus= (CFStringRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)res, iTunesApi::__CFStringMakeConstantString("Status") ); 
        if( aerr )
        {
            char err[256]=""; 
            CFString2CString( aerr, err, 256 );
            //sprintf( apple_errmsg, "ab_app_install error: %s", err ); 
            LOG4CPLUS_ERROR(Logger::getRoot(),"AppInstall Error:"<<err);
            iTunesApi::CFRelease(res);
            ret = INSTALL_STATUS_ERROR;
            break; 
        }
        if( !astatus )
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"AppInstall Error:unknown err");
            ret = INSTALL_STATUS_ERROR;
            iTunesApi::CFRelease( res );
            break; 
        }
        char status[256]="";
        CFString2CString( astatus, status, 256 ); 
        LOG4CPLUS_DEBUG(Logger::getRoot(),"AppInstall Status : "<<status);
        if( _stricmp( status, "Complete") == 0 )
        {    
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,100));
            iTunesApi::CFRelease( res ); 
            break;
        }        
        ///
        if( _stricmp( status, "CreatingStagingDirectory" )==0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,5));    
        }
        else if( stricmp( status, "ExtractingPackage") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,15));    
        }
        else if( stricmp( status, "InspectingPackage") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,20));    
        }
        else if( stricmp( status, "PreflightingApplication") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,30));    
        }
        else if( stricmp( status, "VerifyingApplication") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,40));    
        }
        else if( stricmp( status, "CreatingContainer") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,50));    
        }
        else if( stricmp( status, "InstallingApplication") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,60));    
        }
        else if( stricmp( status, "PostflightingApplication") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,70));    
        }
        else if( stricmp( status, "SandboxingApplication") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,80));    
        }
        else if( stricmp( status, "GeneratingApplicationMap") == 0)
        {
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_INSTALL,MAKELPARAM(dwUserdata,90));    
        }
        ///
        iTunesApi::CFRelease( res ); 
    }
    iTunesApi::CFRelease( req );
    iTunesApi::CFRelease( pkt_path ); 
    //
    closesocket( (SOCKET)fd ); 
        
    PostMessage(hWnd,MSG_DEVICEINSTALL,ret,MAKELPARAM(dwUserdata,0));
    return ret == INSTALL_STATUS_OK;
}

// 安装APP接口
void CPhoneMgr::App_Install(am_device* pDevice, const char* packetPath, DWORD dwUserdata,HWND hWnd)
{
    if(hWnd == NULL)
        hWnd = (HWND)m_pUserData;
    if(!pDevice)
    {
        LOG4CPLUS_DEBUG(Logger::getRoot(),"Call App_Install failed:pDevice is null");
        PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_ERROR,MAKELPARAM(dwUserdata,0));
        return;
    }
    if(!packetPath)
    {
        LOG4CPLUS_DEBUG(Logger::getRoot(),"Call App_Install failed: Ipa Packet Path Is Null");
        PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_ERROR,MAKELPARAM(dwUserdata,0));
        return;
    }

    // 启动线程获取基础信息
    boost::thread thread(boost::bind(&CPhoneMgr::AppInstallThread,this,pDevice,packetPath,dwUserdata,hWnd));
}

// 上传文件
int CPhoneMgr::Afc_UpFile( HAFC_ENV env, const char* remote_path,const char* local_path,HWND hWnd,DWORD dwUserdata)
{
    if( !env || !remote_path || !local_path )
        return -1; 
    struct _stat64 st; 
    if( _stati64( local_path, &st) < 0) 
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"_stati64["<<local_path<<"] Error");
        return -1; 
    }
    FILE* fp = fopen( local_path, "rb"); 
    if( !fp)
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"fopen["<<local_path<<" , rb] Error");
        return -1; 
    }
    HAFC_HANDLE h = Afc_Open_File( env, remote_path,"w");
    if( !h )
    {
        fclose(fp); 
        return -1;
    }

    char buf[BUF_SIZE];
    __int64 size = st.st_size; 
    __int64 idx = 0; 
    COleDateTime dtTimer(COleDateTime::GetCurrentTime());
    while( idx < size )
    {
        int len = fread( buf, 1, BUF_SIZE, fp ); 
        if( len<=0) break; 

        int r = Afc_Write_File( h, buf, len ); 
        if( r != len ) 
            break; 
        ///
        idx += len; 
        double pos = (double)idx/(double)size*100;
        //(*pFunSetProgressPos)(pos,0);
        LOG4CPLUS_DEBUG(Logger::getRoot(),"Afc_UpFile["<<remote_path<<"] Cul:"<<idx<<" total:"<<size);
        if((COleDateTime::GetCurrentTime() - dtTimer).GetTotalSeconds()>=1)
        {
            dtTimer = COleDateTime::GetCurrentTime();
            PostMessage(hWnd,MSG_DEVICEINSTALL,INSTALL_STATUS_UPFILE,MAKELPARAM(dwUserdata,pos));
        }
    }
    
    Afc_Close_Handle( h ); 
    fclose(fp); 
    if( idx != size )
    { // fail 
        remove(remote_path ); 
        LOG4CPLUS_ERROR(Logger::getRoot(),"UpFile["<<remote_path<<"] Error");
        return -1; 
    }
    ///
    return 0;
}

void CPhoneMgr::AppUnInstallThread(am_device* pDevice, const AppInfo* pAppInfo,HWND hWnd)
{
    if( MDERR_OK != ConnectDevice( pDevice)) 
    {
        PostMessage(hWnd,MSG_UNINSTALL,1,(LPARAM)pAppInfo);
        return ; 
    }

    afc_connection* fd;
    afc_connection* house_arrest_fd = NULL; 
    mach_error_t ret = iTunesApi::AMDeviceStartService(pDevice, iTunesApi::__CFStringMakeConstantString("com.apple.mobile.installation_proxy"), &fd, NULL);
    DisConnectDevice( pDevice); 
    if( ret )
    {
        LOG4CPLUS_ERROR(Logger::getRoot(),"AMDeviceStartService[com.apple.mobile.installation_proxy] Error:"<<ret);
        PostMessage(hWnd,MSG_UNINSTALL,1,(LPARAM)pAppInfo);
        return; 
    }
    /
    //int nRet = RemoveApp(fd,apple_id,"Uninstall"); 
    //
    CFDictionaryRef req = iTunesApi::CFDictionaryCreateMutable( NULL,0,NULL,NULL);
    CFStringRef sappid = iTunesApi::CFStringCreateWithCString( NULL, pAppInfo->sAppleID, kCFStringEncodingUTF8 );
    if( !req || !sappid )
    {    
        if( req)
            iTunesApi::CFRelease(req); 
        if(sappid)
            iTunesApi::CFRelease(sappid); 

        LOG4CPLUS_ERROR(Logger::getRoot(),"SomeThing Error");
        PostMessage(hWnd,MSG_UNINSTALL,1,(LPARAM)pAppInfo);
        return; 
    }
    
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)req,(void*)iTunesApi::__CFStringMakeConstantString("Command"),(void*)iTunesApi::__CFStringMakeConstantString("Uninstall") ); 
    iTunesApi::CFDictionaryAddValue( (CFMutableDictionaryRef)req,(void*)iTunesApi::__CFStringMakeConstantString("ApplicationIdentifier"),(void*)sappid); 

    bool bSend = Send_Xml_Request( fd, req ); 
    ret = MDERR_OK;
    while( bSend )
    {
        CFPropertyListRef res = Recv_Xml_Response( fd ); 
        if( !res ) 
        {
            ret = 1;
            break;
        }

        CFStringRef aerr= (CFStringRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)res, iTunesApi::__CFStringMakeConstantString("Error") );
        CFStringRef astatus= (CFStringRef)iTunesApi::CFDictionaryGetValue( (CFDictionaryRef)res, iTunesApi::__CFStringMakeConstantString("Status") ); 
        if( aerr )
        {
            char err[256]=""; 
            CFString2CString( aerr, err, 256 );
            //sprintf( apple_errmsg, "ab_app_install error: %s", err ); 
            LOG4CPLUS_ERROR(Logger::getRoot(),"AppUnInstallThread Error:"<<err);
            iTunesApi::CFRelease(res);
            iTunesApi::CFRelease(sappid);
            ret = 1;
            break;
        }
        if( !astatus )
        {
            LOG4CPLUS_ERROR(Logger::getRoot(),"AppUnInstallThread Error:unknown err");
            iTunesApi::CFRelease( res ); 
            iTunesApi::CFRelease(sappid);
            ret = 1;
            break;
        }
        char status[256]="";
        CFString2CString( astatus, status, 256 ); 
        if( _stricmp( status, "Complete")==0)
        {
            iTunesApi::CFRelease(res);
            ret = MDERR_OK;
            break; 
        }
        ///
        iTunesApi::CFRelease( res );
    }

    iTunesApi::CFRelease(sappid);
    closesocket((SOCKET)fd);

    LOG4CPLUS_DEBUG(Logger::getRoot(),"AppUnInstall AppleID["<<pAppInfo->sAppleID<<"]");
    PostMessage(hWnd,MSG_UNINSTALL,ret,(LPARAM)pAppInfo);
}

// 卸载APP接口
void CPhoneMgr::App_UnInstall( am_device* pDevice, const AppInfo* pAppInfo,bool bThread /*= true*/,HWND hWnd)
{
    if(hWnd==NULL)
        hWnd = (HWND)m_pUserData;
    if(!pDevice)
    {
        LOG4CPLUS_DEBUG(Logger::getRoot(),"Call App_UnInstall failed:pDevice is null");
        PostMessage(hWnd,MSG_UNINSTALL,1,0);
        return;
    }

    /*char* sAppleID = new char[256];
    memset(sAppleID,0,256);
    memcpy(sAppleID,apple_id,256);*/
    // 启动线程获取基础信息
    if(bThread)
        boost::thread thread(boost::bind(&CPhoneMgr::AppUnInstallThread,this,pDevice,pAppInfo,hWnd));
    else
        AppUnInstallThread(pDevice,pAppInfo,hWnd);
}

// IOS字符串转换
void CPhoneMgr::CFString2CString( CFStringRef cfValue, char* pResult,int nResultLen)
{
    if(!cfValue)
        return;

    char cUtf8[MAX_PATH]; memset(cUtf8,0,MAX_PATH); 
    wchar_t wcTmp[MAX_PATH]; memset(wcTmp,0,MAX_PATH);
    iTunesApi::CFStringGetCString(cfValue, cUtf8, MAX_PATH-1, kCFStringEncodingUTF8 );
    ::MultiByteToWideChar( CP_UTF8,0,cUtf8,-1, wcTmp, 256); 
    memset(cUtf8,0,sizeof(cUtf8));
    ::WideCharToMultiByte(CP_ACP,0,wcTmp,-1,cUtf8, MAX_PATH,NULL,NULL); 
    if( nResultLen>0)
        strncpy( pResult, cUtf8, nResultLen>(MAX_PATH-1)?(MAX_PATH-1):nResultLen);
}

// 修改手机名称
bool CPhoneMgr::RenameIphone(am_device* pDevice,  const char* sNewName )
{
    if(!pDevice)
        return false;

    mach_error_t nMach_error;
    // 连接设备
    if (MDERR_OK != (nMach_error = ConnectDevice(pDevice)))
        return false;

    CFStringRef cfKey = iTunesApi::__CFStringMakeConstantString("DeviceName");
    //CFStringRef cfValue = iTunesApi::__CFStringMakeConstantString(sNewName);
    CFStringRef cfValue = iTunesApi::CFStringCreateWithCString(NULL,sNewName,kCFStringEncodingUTF8);
    iTunesApi::AMDeviceSetValue( pDevice, NULL, cfKey, cfValue);
    
    // 断开连接
    DisConnectDevice( pDevice );
    return true;
}
_kCFTypeDictionaryKeyCallBacks    = (CFDictionaryKeyCallBacks*) GetProcAddress(corefoundation, "kCFTypeDictionaryKeyCallBacks");
    _kCFTypeDictionaryValueCallBacks= (CFDictionaryValueCallBacks*) GetProcAddress(corefoundation, "kCFTypeDictionaryValueCallBacks");

void RebootDevice(void *pDeviceSession) 
{
    CFMutableDictionaryRef request = cfDictionaryCreateMutable(NULL, 0, _kCFTypeDictionaryKeyCallBacks, _kCFTypeDictionaryValueCallBacks);
    cfDictionarySetValue(request, getConstCFString("Request"), getConstCFString("Restart"));
    cfDictionarySetValue(request, getConstCFString("DisplayPass"), *boolRefTrue);
    cfDictionarySetValue(request, getConstCFString("WaitForDisconnect"), *boolRefFalse);
    SendDeviceCommand(pDeviceSession, request);
}

void ShutdownDevice(void *pDeviceSession) 
{
    CFMutableDictionaryRef request = cfDictionaryCreateMutable(NULL, 0, _kCFTypeDictionaryKeyCallBacks, _kCFTypeDictionaryValueCallBacks);
    cfDictionarySetValue(request, getConstCFString("Request"), getConstCFString("Shutdown"));
    cfDictionarySetValue(request, getConstCFString("DisplayPass"), *boolRefTrue);
    cfDictionarySetValue(request, getConstCFString("WaitForDisconnect"), *boolRefFalse);
    SendDeviceCommand(pDeviceSession, request);
}
void SendDeviceCommand(void *pDeviceSession, CFMutableDictionaryRef& ref)
{
    int socket = AttachToDeviceAndService(pDeviceSession, "com.apple.mobile.diagnostics_relay");
    if (socket == -1)
    {
        return;
    }

    CFDataRef xmlData = CFPropertyListCreateData(NULL, ref, kCFPropertyListBinaryFormat_v1_0, 0, NULL);

    const char *buf = (const char *)cfDataGetBytePtr(xmlData);
    size_t Size = cfDataGetLength(xmlData);

    CSocketOperation sockOperation;

    char *buff = (char *)Bplist2Xml((const char*)buf, Size);

    if (!sockOperation.write(socket, buf, Size))
    {
        cfRelease(xmlData);
    }

    unsigned char *msg = NULL;
    int len = 0;

    if (!sockOperation.read(socket, &msg, &len))
    {
        return;
    }

    closesocket(socket);
}
int AttachToDeviceAndService(void* pDeviceSession, char *service) {
    AMDeviceRef device = (AMDeviceRef)pDeviceSession;

    SDMMD_AMConnectionRef serviceCon = NULL;
    if (device) {
        mach_error_t result = am_device_connect(device);
        if (0 == result) {
            result = am_device_start_session(device);
            if (0 == result) {
                CFStringRef serviceString = cfStringCreateWithCString(NULL, service, kCFStringEncodingMacRoman);

                int  afc_conn = -1;
                CFStringRef afc_refVal; 
                afc_refVal = getConstCFString(service);
                result = amdeviceStartService(device, afc_refVal, &afc_conn, NULL);
                //result = amdeviceStartService(device, serviceString, NULL, (unsigned int**)&serviceCon);
                 if (0 == result) {

                    CFStringRef deviceName = (CFStringRef)am_copy_value(device, NULL, getConstCFString("DeviceName"));
                    char *name = (char*)cfStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman);
                    if (!name) {
                        name = "unnamed device";
                    }
                    printf("Connected to %s on \"%s\" ...\n", name, service);
                    //stopSession(device);
                    serviceCon = NULL;
                 }
                else
                {
                    afc_conn = -1;
                }
                cfRelease(serviceString);

                amdeviceStopSession(device);
                amdeviceDisconnect(device);

                return afc_conn;
            }
        }
    }
    else {
        printf("Could not find device with that UDID\n");
    }

    return -1;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值