Skip to content

Instantly share code, notes, and snippets.

@eahydra
Created January 6, 2014 02:52
Show Gist options
  • Save eahydra/8277490 to your computer and use it in GitHub Desktop.
Save eahydra/8277490 to your computer and use it in GitHub Desktop.
execute program from shell context menu
#include "ShellLink.h"
#include <shobjidl.h>
#include <ShlGuid.h>
#include "pidl.h"
#include <string>
#include <CommonControls.h>
#include <ustd/ustd_international.h>
namespace{
#define PROP_NAME_OLD_WNDPROC _T("OldWndProc")
#define PROP_NAME_CONTEXT_INFO _T("ContextInfo")
struct CONTEXT_INFO
{
IContextMenu2 *pContextMenu2;
IContextMenu3 *pContextMenu3;
CONTEXT_INFO()
: pContextMenu2(NULL)
, pContextMenu3(NULL)
{
}
};
LRESULT CALLBACK HookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_MENUCHAR: // only supported by IContextMenu3
{
CONTEXT_INFO *pInfo = (CONTEXT_INFO*)GetProp(hWnd, PROP_NAME_CONTEXT_INFO);
if (pInfo && pInfo->pContextMenu3)
{
LRESULT lResult = 0;
pInfo->pContextMenu3->HandleMenuMsg2 (message, wParam, lParam, &lResult);
return lResult;
}
}
break;
case WM_DRAWITEM:
case WM_MEASUREITEM:
if (wParam)
break; // if wParam != 0 then the message is not menu-related
case WM_INITMENUPOPUP:
{
CONTEXT_INFO *pInfo = (CONTEXT_INFO*)GetProp(hWnd, PROP_NAME_CONTEXT_INFO);
if (pInfo)
{
if (pInfo->pContextMenu2)
pInfo->pContextMenu2->HandleMenuMsg (message, wParam, lParam);
else if(pInfo->pContextMenu3)
pInfo->pContextMenu3->HandleMenuMsg (message, wParam, lParam);
return 0;
}
}
break;
default:
break;
}
return ::CallWindowProc((WNDPROC)GetProp(hWnd, PROP_NAME_OLD_WNDPROC), hWnd, message, wParam, lParam);
}
}
HRESULT OS::CreateShortcut(LPCTSTR lpszPathLink, LPCTSTR lpszPathObj, LPCTSTR lpszDesc)
{
IShellLink* psl = NULL;
// Get a pointer to the IShellLink interface.
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
if (lpszDesc)
{
psl->SetDescription(lpszDesc);
}
IPersistFile* ppf = NULL;
// Query IShellLink for the IPersistFile interface for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(lpszPathLink, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
BOOL OS::ShowContextMenu(HWND hwnd, LPCTSTR pszPath, POINT point)
{
if (hwnd == NULL || pszPath == NULL)
{
return FALSE;
}
WCHAR wchPath[MAX_PATH] = {0};
#ifdef _UNICODE
::GetFullPathName(pszPath, sizeof(wchPath)/sizeof(wchPath[0]), wchPath, NULL);
#else
TCHAR tchPath[MAX_PATH];
::GetFullPathName(pszPath, sizeof(tchPath)/sizeof(tchPath[0]), tchPath, NULL);
::MultiByteToWideChar(CP_ACP, 0, tchPath, -1, wchPath, sizeof(wchPath)/sizeof(wchPath[0]));
#endif
BOOL bResult = FALSE;
LPSHELLFOLDER psfFolder = NULL;
LPITEMIDLIST pidlItem = NULL;
if (GetShellFolderAndRelativeItemidlist(wchPath, &psfFolder, &pidlItem))
{
LPCONTEXTMENU pContextMenu = NULL;
if (SUCCEEDED(psfFolder->GetUIObjectOf(hwnd, 1, (LPCITEMIDLIST*)&pidlItem, IID_IContextMenu, NULL, (LPVOID*)&pContextMenu)))
{
bResult = PopContextMenu(hwnd, point, pContextMenu);
pContextMenu->Release();
}
PIDL::ILFree(pidlItem);
psfFolder->Release();
}
return bResult;
}
BOOL OS::ShowContextMenu(HWND hwnd, const std::vector<std::wstring> &vctFilePaths, POINT point)
{
if (hwnd == NULL || vctFilePaths.empty())
{
return FALSE;
}
LPITEMIDLIST *idList = new LPITEMIDLIST[vctFilePaths.size()];
int nIDCount = 0;
std::vector<std::wstring>::const_iterator ite = vctFilePaths.begin();
LPSHELLFOLDER psfFolder = NULL;
for (; ite != vctFilePaths.end(); ++ite)
{
LPSHELLFOLDER psfFolderTemp = NULL;
LPITEMIDLIST pidlItem = NULL;
if (GetShellFolderAndRelativeItemidlist((*ite).c_str(), &psfFolderTemp, &pidlItem))
{
idList[nIDCount++] = pidlItem;
if (psfFolder == NULL)
{
psfFolder = psfFolderTemp;
}
else
{
psfFolderTemp->Release();
}
}
}
BOOL bResult = FALSE;
if (nIDCount > 0)
{
LPCONTEXTMENU pContextMenu = NULL;
if (SUCCEEDED(psfFolder->GetUIObjectOf(hwnd, nIDCount, (LPCITEMIDLIST*)idList, IID_IContextMenu, NULL, (LPVOID*)&pContextMenu)))
{
bResult = PopContextMenu(hwnd, point, pContextMenu);
pContextMenu->Release();
}
for (int i = 0; i < nIDCount; ++i)
{
PIDL::ILFree(idList[i]);
}
psfFolder->Release();
}
delete []idList;
return bResult;
}
BOOL OS::PopContextMenu(HWND hwnd, POINT point, LPCONTEXTMENU pContextMenu)
{
BOOL bResult = FALSE;
HMENU hMenu = CreatePopupMenu();
HRESULT hr = pContextMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE);//CMF_ITEMMENU
if (SUCCEEDED(hr))
{
#if 0
int nCount = ::GetMenuItemCount(hMenu);
for (int i = 0; i < nCount; ++i)
{
MENUITEMINFO info = {0};
TCHAR szText[MAX_PATH] = {0};
info.cbSize = sizeof(info);
info.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE |MIIM_SUBMENU;
info.dwTypeData = (LPTSTR)szText;
info.cch = MAX_PATH;
GetMenuItemInfo(hMenu, i, TRUE, &info);
int err = GetLastError();
if (info.hSubMenu)
{
int nCount2 = ::GetMenuItemCount(info.hSubMenu);
for (int i2 = 0; i2 < nCount2; ++i2)
{
MENUITEMINFO info2 = {0};
TCHAR szText2[MAX_PATH] = {0};
info2.cbSize = sizeof(info2);
info2.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE |MIIM_SUBMENU;
info2.dwTypeData = (LPTSTR)szText2;
info2.cch = MAX_PATH;
GetMenuItemInfo(info.hSubMenu, i2, TRUE, &info2);
int err = GetLastError();
}
}
}
#endif
::ClientToScreen(hwnd, &point);
UINT nCmd = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, 0, hwnd, NULL);
if(nCmd)
{
CMINVOKECOMMANDINFO ici = {0};
ici.cbSize = sizeof(ici);
ici.fMask = 0;
ici.hwnd = hwnd;
ici.lpVerb = (LPCSTR)MAKEINTRESOURCE(nCmd - 1);
ici.lpParameters = NULL;
ici.lpDirectory = NULL;
ici.nShow = SW_SHOWNORMAL;
ici.dwHotKey = 0;
ici.hIcon = NULL;
if (SUCCEEDED(pContextMenu->InvokeCommand(&ici)))
{
bResult = TRUE;
}
}
::DestroyMenu(hMenu);
}
return bResult;
}
BOOL OS::PopContextMenuEx(HWND hwnd, POINT point, LPCONTEXTMENU pContextMenu, LPCTSTR pszFilePath)
{
BOOL bResult = FALSE;
HMENU hMenu = CreatePopupMenu();
HRESULT hr = pContextMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE | CMF_CANRENAME);//CMF_ITEMMENU);
if (SUCCEEDED(hr))
{
#if 0
int nCount = ::GetMenuItemCount(hMenu);
for (int i = 0; i < nCount; ++i)
{
MENUITEMINFO info = {0};
TCHAR szText[MAX_PATH] = {0};
info.cbSize = sizeof(info);
info.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE;
info.dwTypeData = (LPTSTR)szText;
info.cch = MAX_PATH;
GetMenuItemInfo(hMenu, i, TRUE, &info);
int err = GetLastError();
}
#endif
WNDPROC oldWndProc = NULL;
CONTEXT_INFO info;
if (SUCCEEDED(pContextMenu->QueryInterface(IID_IContextMenu3, (void**)&info.pContextMenu3)) ||
SUCCEEDED(pContextMenu->QueryInterface(IID_IContextMenu2, (void**)&info.pContextMenu2)) )
{
oldWndProc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)HookWndProc);
::SetProp(hwnd, PROP_NAME_OLD_WNDPROC, (HANDLE)oldWndProc);
::SetProp(hwnd, PROP_NAME_CONTEXT_INFO, (HANDLE)&info);
}
::ClientToScreen(hwnd, &point);
UINT nCmd = ::TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, 0, hwnd, NULL);
if (oldWndProc)
{
SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)oldWndProc);
::RemoveProp(hwnd, PROP_NAME_OLD_WNDPROC);
::RemoveProp(hwnd, PROP_NAME_CONTEXT_INFO);
}
// 剪切复制菜单,直接InvokeCommand没有效果,原因未知。
switch (nCmd)
{
case 0x13: // rename
case 0x12: // delete
bResult = nCmd;
::DestroyMenu(hMenu);
return bResult;
default:
break;
}
CMINVOKECOMMANDINFO ici = {0};
ici.cbSize = sizeof(ici);
ici.fMask = 0;
ici.hwnd = hwnd;
ici.lpVerb = (LPCSTR)MAKEINTRESOURCE(nCmd - 1);
//if (nCmd == 29)
//{//
// ici.fMask |= CMIC_MASK_FLAG_NO_UI|CMIC_MASK_FLAG_LOG_USAGE;
//}
ici.nShow = SW_SHOWNORMAL;
if (SUCCEEDED(pContextMenu->InvokeCommand(&ici)))
{
if (nCmd != 0x12)
{
bResult = TRUE;
}
}
else
{
bResult = FALSE;
}
::DestroyMenu(hMenu);
}
return bResult;
}
BOOL OS::ShowSysFolerContextMenu(HWND hwnd, int nFolder, POINT point)
{
BOOL bRet = FALSE;
HRESULT hr;
IShellFolder* pDesktopFolder = NULL;
// Get desktop folder.
hr = ::SHGetDesktopFolder(&pDesktopFolder);
ITEMIDLIST* pidlFolder = NULL;
hr = ::SHGetFolderLocation(NULL, nFolder, NULL, 0, &pidlFolder);
if (SUCCEEDED(hr))
{
IContextMenu* pContextMenu = NULL;
const ITEMIDLIST* pidl2 = pidlFolder;
hr = pDesktopFolder-> GetUIObjectOf(NULL, 1, &pidl2, IID_IContextMenu, NULL, (void**)&pContextMenu);
if (SUCCEEDED(hr))
{
bRet = PopContextMenu(hwnd, point, pContextMenu);
pContextMenu-> Release();
}
PIDL::ILFree(pidlFolder);
}
pDesktopFolder->Release();
return bRet;
}
BOOL OS::ShowSysContextMenu(HWND hwnd, const wchar_t* Path, POINT point)
{
BOOL bRet = FALSE;
HRESULT hr;
#if 0
IShellFolder* pDesktopFolder = NULL;
// Get desktop folder.
hr = ::SHGetDesktopFolder(&pDesktopFolder);
ITEMIDLIST* pidlFolder = NULL;
ULONG attributes = SFGAO_FOLDER | SFGAO_LINK | SFGAO_CANMOVE | SFGAO_HASPROPSHEET | SFGAO_CANRENAME;
hr = SHParseDisplayName(Path, NULL, &pidlFolder, attributes, &attributes);
#endif
LPSHELLFOLDER psfFolder = NULL;
LPITEMIDLIST pidlItem = NULL;
if (GetShellFolderAndRelativeItemidlist(Path, &psfFolder, &pidlItem))
{
IContextMenu* pContextMenu = NULL;
const ITEMIDLIST* pidl2 = pidlItem;
hr = psfFolder-> GetUIObjectOf(NULL, 1, &pidl2, IID_IContextMenu, NULL, (void**)&pContextMenu);
if (SUCCEEDED(hr))
{
bRet = PopContextMenuEx(hwnd, point, pContextMenu, Path);
pContextMenu-> Release();
}
PIDL::ILFree(pidlItem);
psfFolder->Release();
}
return bRet;
}
HRESULT OS::SHInvokeCommand(HWND hwnd, IShellFolder* pShellFolder, LPCITEMIDLIST pidlItem, LPCSTR lpVerb)
{
HRESULT hr = E_FAIL;
if (pShellFolder)
{
IContextMenu *pContextMenu;
if (SUCCEEDED(pShellFolder->GetUIObjectOf(hwnd, 1, &pidlItem, IID_IContextMenu, 0, (void**)&pContextMenu)))
{
if (pContextMenu)
{
HMENU hmenu = CreatePopupMenu();
if (hmenu)
{
if (SUCCEEDED(pContextMenu->QueryContextMenu(hmenu, 0, 1, 0x7FFF, lpVerb ? 0 : CMF_DEFAULTONLY)))
{
UINT idCmd = -1;
if (lpVerb == NULL)
{
idCmd = GetMenuDefaultItem(hmenu, MF_BYCOMMAND, 0);
if ((UINT)-1 != idCmd)
lpVerb = MAKEINTRESOURCEA(idCmd - 1);
}
// if idCmd == 0, then lpVerb would be Zero. So we need to check to
// see if idCmd is not -1.
if (lpVerb || idCmd != (UINT)-1)
{
CMINVOKECOMMANDINFO ici = { 0 };
ici.cbSize = sizeof(CMINVOKECOMMANDINFO);
ici.hwnd = hwnd;
ici.lpVerb = lpVerb;
ici.nShow = SW_NORMAL;
hr = pContextMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
}
}
DestroyMenu(hmenu);
}
// Release our use of the context menu
pContextMenu->Release();
}
}
}
return hr;
}
HRESULT OS::ShellExecute(LPCWSTR FilePath)
{
HRESULT hr = E_FAIL;
if (FilePath != NULL)
{
LPSHELLFOLDER psfFolder = NULL;
LPITEMIDLIST pidlItem = NULL;
if (GetShellFolderAndRelativeItemidlist(FilePath, &psfFolder, &pidlItem))
{
hr = SHInvokeCommand(::GetDesktopWindow(), psfFolder, pidlItem, NULL);
psfFolder->Release();
PIDL::ILFree(pidlItem);
}
}
return hr;
}
HICON OS::GetIcon(LPCITEMIDLIST pidl)
{
HICON hIcon = NULL;
SHFILEINFO shFi;
memset(&shFi, 0, sizeof(SHFILEINFO));
if(SHGetFileInfoW((LPWSTR)pidl, 0, &shFi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_PIDL) != 0)
{
IImageList *pIImageList = NULL;
HRESULT hr = SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void **)&pIImageList);
if (SUCCEEDED(hr))
{
pIImageList->GetIcon(shFi.iIcon, ILD_NORMAL, &hIcon);
pIImageList->Release();
}
}
return hIcon;
}
HICON OS::LoadIconFromShell(LPCTSTR FilePath)
{
HICON hIcon = NULL;
ULONG attributes = SFGAO_FOLDER | SFGAO_LINK | SFGAO_CANMOVE | SFGAO_HASPROPSHEET | SFGAO_CANRENAME;
ULONG oldAttributes = attributes;
LPITEMIDLIST ItemIdList = NULL;
HRESULT hr = SHParseDisplayName(FilePath, NULL, &ItemIdList, attributes, &attributes);
if (SUCCEEDED(hr))
{
if ((attributes & oldAttributes) != 0)
{
hIcon = GetIcon(ItemIdList);
}
PIDL::ILFree(ItemIdList);
}
return hIcon;
}
BOOL OS::CutOrCopyFiles(LPCWSTR pszFilePath, BOOL bCopy)
{
UINT uLens = pszFilePath ? _tcslen(pszFilePath) : 0;
if (uLens == 0)
{
return FALSE;
}
DROPFILES dropFiles = {0};
UINT uGblLen,uDropFilesLen;
HGLOBAL hGblFiles,hGblEffect;
char *szData;
DWORD *pdwDropEffect;
const UINT uDropEffect=RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
hGblEffect=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, sizeof(DWORD));
pdwDropEffect=(DWORD*)GlobalLock(hGblEffect);
*pdwDropEffect= (bCopy ? DROPEFFECT_COPY : DROPEFFECT_MOVE);
GlobalUnlock(hGblEffect);
uDropFilesLen=sizeof(dropFiles);
dropFiles.pFiles =uDropFilesLen;
dropFiles.pt.x=0;
dropFiles.pt.y=0;
dropFiles.fNC =FALSE;
dropFiles.fWide =TRUE;
uGblLen=uDropFilesLen + (uLens+1)*sizeof(WCHAR)+ 8;
hGblFiles= GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, uGblLen);
szData=(char*)GlobalLock(hGblFiles);
memcpy(szData,(LPVOID)(&dropFiles),uDropFilesLen);
wcscpy_s((WCHAR*)(szData+uDropFilesLen), uLens + 1, pszFilePath);
GlobalUnlock(hGblFiles);
if(OpenClipboard(NULL))
{
EmptyClipboard();
SetClipboardData(CF_HDROP, hGblFiles);
SetClipboardData(uDropEffect,hGblEffect);
CloseClipboard();
return TRUE;
}
return FALSE;
}
BOOL OS::CutOrCopyFiles(const std::vector<std::wstring> &vctFiles, BOOL bCopy)
{
UINT uLens = 0;
std::vector<std::wstring>::const_iterator ite = vctFiles.begin();
for (; ite != vctFiles.end(); ++ite)
{
uLens += ite->length() + 1;
}
if (uLens == 0)
{
return FALSE;
}
DROPFILES dropFiles = {0};
UINT uGblLen,uDropFilesLen;
HGLOBAL hGblFiles,hGblEffect;
char *szData;
DWORD *pdwDropEffect;
const UINT uDropEffect=RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
hGblEffect=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, sizeof(DWORD));
pdwDropEffect=(DWORD*)GlobalLock(hGblEffect);
*pdwDropEffect= (bCopy ? DROPEFFECT_COPY : DROPEFFECT_MOVE);
GlobalUnlock(hGblEffect);
uDropFilesLen=sizeof(dropFiles);
dropFiles.pFiles =uDropFilesLen;
dropFiles.pt.x=0;
dropFiles.pt.y=0;
dropFiles.fNC =FALSE;
dropFiles.fWide =TRUE;
uGblLen=uDropFilesLen + (uLens+1)*sizeof(WCHAR)+ 8;
hGblFiles= GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, uGblLen);
szData=(char*)GlobalLock(hGblFiles);
memcpy(szData,(LPVOID)(&dropFiles),uDropFilesLen);
ite = vctFiles.begin();
WCHAR *pPos = (WCHAR*)(szData+uDropFilesLen);
for (; ite != vctFiles.end(); ++ite)
{
wcscpy_s(pPos, ite->length() + 1, ite->c_str());
pPos += ite->length() + 1;
}
GlobalUnlock(hGblFiles);
if(OpenClipboard(NULL))
{
EmptyClipboard();
SetClipboardData(CF_HDROP, hGblFiles);
SetClipboardData(uDropEffect,hGblEffect);
CloseClipboard();
return TRUE;
}
return FALSE;
}
BOOL OS::GetClipboardFiles(HWND hwndOwner, std::vector<std::wstring> &vctFiles, BOOL &bCopy, BOOL bClearClipboardOnMove)
{
vctFiles.clear();
if (IsClipboardFormatAvailable(CF_HDROP))
{
const UINT DROP_EFFECT = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
if(OpenClipboard(hwndOwner))
{
bCopy = TRUE;
HGLOBAL hDropEffect = ::GetClipboardData(DROP_EFFECT);
if (hDropEffect)
{
DWORD dwEffect = *(DWORD*)::GlobalLock(hDropEffect);
bCopy = (dwEffect & DROPEFFECT_COPY) != 0;
::GlobalUnlock(hDropEffect);
}
HGLOBAL hFiles = ::GetClipboardData(CF_HDROP);
if (hFiles)
{
char *pdata = (char*)::GlobalLock(hFiles);
DROPFILES dropFiles = {0};
memcpy(&dropFiles, pdata, sizeof(dropFiles));
pdata += dropFiles.pFiles;
if (dropFiles.fWide)
{
WCHAR *pFile = (WCHAR*)pdata;
while (*pFile != 0)
{
vctFiles.push_back(std::wstring(pFile));
pFile += wcslen(pFile) + 1;
}
}
else
{
char *pFile = pdata;
std::wstring wstr;
while (*pFile != 0)
{
ustd::ConvertToWideChar(pFile, wstr, CP_ACP);
vctFiles.push_back(wstr);
pFile += strlen(pFile) + 1;
}
}
::GlobalUnlock(hFiles);
}
if (bClearClipboardOnMove && !bCopy)
{
::EmptyClipboard();
}
::CloseClipboard();
}
}
return !vctFiles.empty();
}
UINT OS::IsClipboardHaveFiles()
{
if (IsClipboardFormatAvailable(CF_HDROP))
return ClipboardFileType_LOCAL;
UINT Ret = ClipboardFileType_NONE;
IDataObject *pDataObj = NULL;
FORMATETC ftetc = {0};
ftetc.dwAspect = DVASPECT_CONTENT;
ftetc.lindex = -1;
ftetc.tymed = TYMED_HGLOBAL;
ftetc.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
HRESULT hr = OleGetClipboard(&pDataObj);
if(SUCCEEDED(hr))
{
STGMEDIUM medium;
FILEGROUPDESCRIPTOR* fgd;
hr = pDataObj->GetData(&ftetc, &medium);
if(SUCCEEDED(hr))
{
fgd = (FILEGROUPDESCRIPTOR*)GlobalLock(medium.hGlobal);
if(fgd->cItems > 0)
Ret = ClipboardFileType_REMOTE;
}
GlobalUnlock(medium.hGlobal);
ReleaseStgMedium(&medium);
}
pDataObj->Release();
return Ret;
}
BOOL OS::ReadShortcut(LPCWSTR lpwLnkFile, LPWSTR lpDescFile, int length)
{
BOOL isSuccess = FALSE;
IShellLink *pShellLink = NULL;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (void **)&pShellLink);
if(SUCCEEDED(hr))
{
IPersistFile *ppf;
hr = pShellLink->QueryInterface(IID_IPersistFile, (void **)&ppf);
if(SUCCEEDED(hr))
{
hr = ppf->Load(lpwLnkFile, TRUE);
if(SUCCEEDED(hr))
{
hr = pShellLink->GetPath(lpDescFile, length, NULL, 0);
isSuccess = SUCCEEDED(hr);
}
ppf->Release ();
}
pShellLink->Release ();
}
CoUninitialize();
return isSuccess;
}
BOOL OS::GetShellFolderAndRelativeItemidlist(LPCWSTR pwszPath, IShellFolder **ppFolder, ITEMIDLIST **ppItemlist)
{
LPSHELLFOLDER psfFolder = NULL;
if (!SUCCEEDED(SHGetDesktopFolder(&psfFolder)))
{
return FALSE;
}
ULONG ulCount = 0;
ULONG ulAttr = 0;
LPITEMIDLIST pidlMain = NULL;
do
{
if (FAILED(psfFolder->ParseDisplayName(NULL, NULL, (LPWSTR)pwszPath, &ulCount, &pidlMain, &ulAttr)) || (pidlMain == NULL))
{
break;
}
UINT nCount = PIDL::ILGetCount(pidlMain);
if (nCount == 0)
{
break;
}
LPITEMIDLIST pidlItem = pidlMain;
while (--nCount)
{
LPITEMIDLIST pidlNextItem = PIDL::ILCloneFirst (pidlItem);
if(pidlNextItem == NULL)
{
break;
}
LPSHELLFOLDER psfNextFolder = NULL;
// Bind to the folder specified in the new item ID list.
if(!SUCCEEDED(psfFolder->BindToObject(pidlNextItem, NULL, IID_IShellFolder, (void**)&psfNextFolder)))
{
PIDL::ILFree(pidlNextItem);
break;
}
// Release the IShellFolder pointer to the parent folder and set psfFolder equal to the IShellFolder pointer for the current folder.
psfFolder->Release();
psfFolder = psfNextFolder;
PIDL::ILFree(pidlNextItem);
pidlItem = (LPITEMIDLIST)PIDL::ILGetNext(pidlItem);
}
if (nCount != 0)
{// 上面的循环出错
break;
}
*ppFolder = psfFolder;
*ppItemlist = PIDL::ILClone(pidlItem);
PIDL::ILFree(pidlMain);
return TRUE;
}while(0);
psfFolder->Release();
if (pidlMain)
{
PIDL::ILFree(pidlMain);
}
return FALSE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment