32与64位下通用查找桌边图标坐标具体信息的方法

思路:
1、遍历/Desktop目录下所有.link结尾的文件的具体路径
2、基于这些图标的具体路径和名称,查找图标对应的真实的程序
3、查找对应程序的原始文件名字
4、判断32或者64位系统,来分别获取所有图标的位置
5、把所有的结果放入PMYICON 的结构中

//桌面图标的具体信息
typedef struct{
    DWORD num;
    TCHAR *pathName[MAX_PATH];      //icon具体路径
    TCHAR *processName[MAX_PATH];   //icon对应的程序位置
    TCHAR *realName[MAX_PATH];      //对应程序的真实姓名
    RECT rect[MAX_PATH];            //对应坐标的位置
}MYICON,*PMYICON;
BOOL Is64Os(){
    BOOL bIsWow64 = FALSE; 
    IsWow64Process(GetCurrentProcess(), &bIsWow64);
    return bIsWow64;
}


//通过图标路径获取图标中的具体内容
HRESULT SHResolveShortcut(LPCTSTR szLnkFile, LPSHORTCUTSTRUCT lpss)  
{  
    WCHAR wszLnkFile[MAX_PATH] = {0};  
    IShellLink* pShellLink = NULL;  
    IPersistFile* pPF = NULL;
    
    // 建立合适的COM服务器  
    HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL,CLSCTX_INPROC_SERVER,  
        IID_IShellLink,reinterpret_cast(&pShellLink));  
    if(FAILED(hr)){
        printf("CoCreateInstance:%d\n",GetLastError());
        return hr;
    }
    // 取得装入.LNK 文件的IPersistFile接口  
    hr = pShellLink->QueryInterface(IID_IPersistFile,  
        reinterpret_cast(&pPF));  
    if(FAILED(hr))  
    {  
        pShellLink->Release();  
        return hr;  
    }  
    // 装入快捷方式(Unicode 名)  
    MultiByteToWideChar(CP_ACP, 0, szLnkFile, -1, wszLnkFile, MAX_PATH);  
    hr = pPF->Load(wszLnkFile, STGM_READ);  
    if(FAILED(hr))  
    {  
        pPF->Release();  
        pShellLink->Release();  
        return hr;  
    }  
    // 解析连接  
    hr = pShellLink->Resolve(NULL, SLR_ANY_MATCH);  
    if(FAILED(hr))  
    {  
        pPF->Release();  
        pShellLink->Release();  
        return hr;  
    }  
    // 抽取信息,充填到lpss  
    if(lpss != NULL)  
    {  
        TCHAR szPath[MAX_PATH] = {0};  
        TCHAR szDesc[MAX_PATH] = {0};  
        TCHAR szIcon[MAX_PATH] = {0};  
        WORD w = 0;  
        WORD wIcon = 0;  
        WIN32_FIND_DATA wfd;  
        pShellLink->GetPath(szPath, MAX_PATH, &wfd, SLGP_RAWPATH);  
        pShellLink->GetDescription(szDesc, MAX_PATH);  
        pShellLink->GetHotkey(&w);  
        pShellLink->GetIconLocation(szIcon, MAX_PATH,  
            reinterpret_cast(&wIcon));

        memset(lpss->pszTarget,0,MAX_PATH);
        memcpy(lpss->pszTarget,szPath,sizeof(szPath));

        memset(lpss->pszDesc,0,MAX_PATH);
        memcpy(lpss->pszDesc,szDesc,sizeof(szDesc));

        memset(lpss->pszIconPath,0,MAX_PATH);
        memcpy(lpss->pszIconPath,szIcon,sizeof(szIcon));

        lpss->wHotKey = w;  
        lpss->wIconIndex = wIcon;  
    }  
    pPF->Release();  
    pShellLink->Release();  
    return hr;  
}  



//传入要遍历的文件夹路径,并遍历相应文件夹  
void TraverseDirectory(char *Dir,PMYICON pMyIcon)      
{  
    WIN32_FIND_DATA FindFileData;  
    HANDLE hFind=INVALID_HANDLE_VALUE;
    int i=0;

    hFind=FindFirstFile(Dir,&FindFileData);          //找到文件夹中的第一个文件  

    if(hFind==INVALID_HANDLE_VALUE)                               //如果hFind句柄创建失败,输出错误信息  
    {  
        FindClose(hFind);   
        return;    
    }  
    else   
    {
        do{ //&& strstr(FindFileData.cFileName,".lnk")
            if((FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)==0 && strstr(FindFileData.cFileName,".lnk"))    //如果不是文件夹,并且是图标  
            {  
                pMyIcon->pathName[i] = (char *)malloc(strlen(Dir)+strlen(FindFileData.cFileName)+0x10);            //输出完整路径
                if(pMyIcon->pathName[i] != NULL){
                    memset(pMyIcon->pathName[i],0,strlen(Dir)+strlen(FindFileData.cFileName)+0x10);
                    memcpy(pMyIcon->pathName[i],Dir,strlen(Dir) - 1);
                    memcpy(pMyIcon->pathName[i] + strlen(Dir) - 1,FindFileData.cFileName,strlen(FindFileData.cFileName));

                    pMyIcon->num = i;
                    i++;
                }
            }  

        }while(FindNextFile(hFind,&FindFileData)!=0);                            //当文件或者文件夹存在时 
        
        FindClose(hFind);  
    }
    pMyIcon->num += 1;
} 


//得到桌面图标的具体路径和名称
void GetDeskIconName(PMYICON pMyIcon){
    //获取桌面路径
    TCHAR path[MAX_PATH];
    ZeroMemory(path,MAX_PATH);
    SHGetSpecialFolderPath(0,path,CSIDL_DESKTOPDIRECTORY,0);
    path[strlen(path)] = '\\';
    path[strlen(path)] = '*';
    //得到桌面目录下的所有文件
    TraverseDirectory(path,pMyIcon);

    //
    CoInitialize(NULL);
    LPSHORTCUTSTRUCT lpss = (LPSHORTCUTSTRUCT)malloc(sizeof(SHORTCUTSTRUCT));
    if(lpss == NULL)
        return ;
    
    
    //得到当前
    for(int i=0;i < pMyIcon->num;i++){
        memset(lpss,0,sizeof(SHORTCUTSTRUCT));
        if(pMyIcon->pathName[i]){
            SHResolveShortcut(pMyIcon->pathName[i],lpss);
            /*printf("***********************************\n");
            printf("%s\n",lpss->pszTarget);
            printf("%s\n",lpss->pszIconPath);
            printf("%s\n",lpss->pszDesc);*/
            pMyIcon->processName[i] = (char *)malloc(strlen(lpss->pszTarget) + 0x10);
            if(pMyIcon->processName[i]){
                memset(pMyIcon->processName[i],0,strlen(lpss->pszTarget) + 0x10);
                memcpy(pMyIcon->processName[i],lpss->pszTarget,strlen(lpss->pszTarget));
            }
        }
    }
    CoUninitialize();


}


//得到对应图标的位置
void GetDeskIconPos(PMYICON pMyIcon){
    HWND hDestTop;   
    hDestTop = FindWindow("progman", NULL);   
    hDestTop = FindWindowEx(hDestTop, 0, "shelldll_defview", NULL);   
    hDestTop = FindWindowEx(hDestTop, 0, "syslistview32", NULL);   

    int count=(int)::SendMessage( hDestTop, LVM_GETITEMCOUNT, 0, 0);  

    if(Is64Os()){
        //printf("64\n");
        LVITEM64 lvi, *_lvi;  
        wchar_t item[512], subitem[512];  
        wchar_t *_item, *_subitem;  
        unsigned long pid;  
        HANDLE process;  

        GetWindowThreadProcessId( hDestTop, &pid);  
        process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);  

        _lvi=(LVITEM64*)VirtualAllocEx(process, NULL, sizeof(LVITEM64), MEM_COMMIT, PAGE_READWRITE);  
        _item=(wchar_t*)VirtualAllocEx(process, NULL, 512*sizeof(wchar_t), MEM_COMMIT, PAGE_READWRITE);  
        _subitem=(wchar_t*)VirtualAllocEx(process, NULL, 512*sizeof(wchar_t), MEM_COMMIT, PAGE_READWRITE);  

        RECT  rc;  
        rc.left = LVIR_ICON;  //这个一定要设定 可以去看MSDN关于LVM_GETITEMRECT的说明  
        RECT* _rc =(RECT*)VirtualAllocEx( process, NULL, sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);   

        lvi.cchTextMax=512;  

        for( int i=0; i< count; i++) {  

            lvi.iSubItem=0;  
            lvi.pszText=(_int64)_item;  
            WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM64), NULL);  
            SendMessage( hDestTop, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);  

            lvi.iSubItem=1;  
            lvi.pszText=(_int64)_subitem;  
            WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM64), NULL);  
            SendMessage( hDestTop, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);  

            memset(&rc,0,sizeof(RECT));
            rc.left = LVIR_ICON;


            WriteProcessMemory( process, _rc, &rc, sizeof(rc), NULL);  
            SendMessage( hDestTop, LVM_GETITEMRECT, (WPARAM)i, (LPARAM)_rc);  

            ReadProcessMemory(process, _item, item, 512*sizeof(wchar_t), NULL);  
            ReadProcessMemory(process, _subitem, subitem, 512*sizeof(wchar_t), NULL);  

            ReadProcessMemory(process, _rc, &rc, sizeof(rc), NULL);



            for(int j=0;j < pMyIcon->num;j++){
                //比较图标是否是对应的
                if(MyStrStr(pMyIcon->pathName[j],(char *)item,"\\",".lnk")){
                    //printf("find it\n");
                    pMyIcon->rect[j].bottom = rc.bottom;
                    pMyIcon->rect[j].top = rc.top;
                    pMyIcon->rect[j].left = rc.left;
                    pMyIcon->rect[j].right = rc.right;

                    //printf("item:%s\tbottom:%d\ttop:%d\tleft:%d\tright:%d\n",(char *)item,rc.bottom,rc.top,rc.left,rc.right);
                    //printf("pathName:%s\tbottom:%d\ttop:%d\tleft:%d\tright:%d\n",pMyIcon->pathName[j],pMyIcon->rect[j].bottom,pMyIcon->rect[j].top,pMyIcon->rect[j].left,pMyIcon->rect[j].right);
                    break;
                }


            }

        }  

        VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);  
        VirtualFreeEx(process, _item, 0, MEM_RELEASE);  
        VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);  
        VirtualFreeEx(process, _rc, 0, MEM_RELEASE);  

        CloseHandle( process );  

    }else{
        
        LVITEM lvi, *_lvi;  
        wchar_t item[512], subitem[512];  
        wchar_t *_item, *_subitem;  
        unsigned long pid;  
        HANDLE process;  

        GetWindowThreadProcessId( hDestTop, &pid);  
        process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);  
        
        _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);  
        _item=(wchar_t*)VirtualAllocEx(process, NULL, 512*sizeof(wchar_t), MEM_COMMIT, PAGE_READWRITE);  
        _subitem=(wchar_t*)VirtualAllocEx(process, NULL, 512*sizeof(wchar_t), MEM_COMMIT, PAGE_READWRITE);  
        
        RECT  rc;  
        rc.left = LVIR_ICON;  //这个一定要设定 可以去看MSDN关于LVM_GETITEMRECT的说明  
        RECT* _rc =(RECT*)VirtualAllocEx( process, NULL, sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);   
        
        lvi.cchTextMax=512;  
        
        for( int i=0; i< count; i++) {  

            lvi.iSubItem=0;  
            lvi.pszText=(LPSTR)_item;  
            WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);  
            SendMessage( hDestTop, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);  

            lvi.iSubItem=1;  
            lvi.pszText=(LPSTR)_subitem;  
            WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);  
            SendMessage( hDestTop, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);  

            memset(&rc,0,sizeof(RECT));
            rc.left = LVIR_ICON;


            WriteProcessMemory( process, _rc, &rc, sizeof(rc), NULL);  
            SendMessage( hDestTop, LVM_GETITEMRECT, (WPARAM)i, (LPARAM)_rc);  

            ReadProcessMemory(process, _item, item, 512*sizeof(wchar_t), NULL);  
            ReadProcessMemory(process, _subitem, subitem, 512*sizeof(wchar_t), NULL);  

            ReadProcessMemory(process, _rc, &rc, sizeof(rc), NULL);


            
            for(int j=0;j < pMyIcon->num;j++){
                //比较图标是否是对应的
                if(MyStrStr(pMyIcon->pathName[j],(char *)item,"\\",".lnk")){
                    //printf("find it\n");
                    pMyIcon->rect[j].bottom = rc.bottom;
                    pMyIcon->rect[j].top = rc.top;
                    pMyIcon->rect[j].left = rc.left;
                    pMyIcon->rect[j].right = rc.right;

                    //printf("item:%s\tbottom:%d\ttop:%d\tleft:%d\tright:%d\n",(char *)item,rc.bottom,rc.top,rc.left,rc.right);
                    //printf("pathName:%s\tbottom:%d\ttop:%d\tleft:%d\tright:%d\n",pMyIcon->pathName[j],pMyIcon->rect[j].bottom,pMyIcon->rect[j].top,pMyIcon->rect[j].left,pMyIcon->rect[j].right);
                    break;
                }


            }

        }  

        VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);  
        VirtualFreeEx(process, _item, 0, MEM_RELEASE);  
        VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);  
        VirtualFreeEx(process, _rc, 0, MEM_RELEASE);  

        CloseHandle( process );  

    }


    

}




//得到指定文件的详细信息,比如原始文件名
void GetRealName(PMYICON pMyIcon){

    DWORD i=0;
    UINT uLen = 0;
    char *pVerValue;
    DWORD   m_dwLangCharset;
    char tmp[MAX_PATH];

    for(i=0;inum;i++){
        pVerValue = NULL;
        DWORD dwSize = GetFileVersionInfoSize(pMyIcon->processName[i],NULL);
        LPVOID pBlock = malloc(dwSize);
        if(pBlock != NULL){
            memset(pBlock,0,dwSize);
            GetFileVersionInfo(pMyIcon->processName[i],NULL,dwSize,pBlock);

            m_dwLangCharset = 0;
            DWORD* pTransTable;
            VerQueryValue(pBlock,"\\VarFileInfo\\Translation",(LPVOID*)&pTransTable,&uLen);
            m_dwLangCharset = MAKELONG(HIWORD(pTransTable[0]), LOWORD(pTransTable[0]));
            memset(tmp,0,MAX_PATH);

            sprintf(tmp,"\\StringFileInfo\\%08lx\\OriginalFileName",m_dwLangCharset);
            //printf("tmp:%s\n",tmp);
            VerQueryValue(pBlock,tmp,(LPVOID*)&pVerValue,&uLen);
            if(pVerValue != NULL){
                pMyIcon->realName[i] = (char *)malloc(strlen(pVerValue)+0x10);
                if(pMyIcon->realName[i] != NULL){
                    memset(pMyIcon->realName[i],0,strlen(pVerValue)+0x10);
                    memcpy(pMyIcon->realName[i],pVerValue,strlen(pVerValue));
                }
            }
        }

    }
    return ;
}



//得到所有的图标信息
void GetAllIconInfo(PMYICON pMyIcon){
    //得到桌面图标的具体路径和名称
    GetDeskIconName(pMyIcon);
    //得到图标具体程序的真实名字
    GetRealName(pMyIcon);
    //得到对应图标的位置
    GetDeskIconPos(pMyIcon);
}

你可能感兴趣的:(32与64位下通用查找桌边图标坐标具体信息的方法)