思路:
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);
}