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<LPVOID*>(&pShellLink));  
    if(FAILED(hr)){
        printf("CoCreateInstance:%d\n",GetLastError());
        return hr;
    }
    // 取得装入.LNK 文件的IPersistFile接口  
    hr = pShellLink->QueryInterface(IID_IPersistFile,  
        reinterpret_cast<LPVOID*>(&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<int*>(&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;i<pMyIcon->num;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);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容