ShellPidl.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:21k
源码类别:

图形图象

开发平台:

Visual C++

  1. //*******************************************************************************
  2. // COPYRIGHT NOTES
  3. // ---------------
  4. // You may use this source code, compile or redistribute it as part of your application 
  5. // for free. You cannot redistribute it as a part of a software development 
  6. // library without the agreement of the author. If the sources are 
  7. // distributed along with the application, you should leave the original 
  8. // copyright notes in the source code without any changes.
  9. // This code can be used WITHOUT ANY WARRANTIES at your own risk.
  10. // 
  11. // For the latest updates to this code, check this site:
  12. // http://www.masmex.com 
  13. // after Sept 2000
  14. // 
  15. // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
  16. //*******************************************************************************
  17. // ShellPidl.cpp: implementation of the CShellPidl class.
  18. //
  19. //////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "ShellPidl.h"
  22. #include "UIMessages.h"
  23. #include <intshcut.h>
  24. #include <subsmgr.h>
  25. #include <ExDisp.h>
  26. #include "ShellContextMenu.h"
  27. #include "UICoolMenu.h"
  28. #include "cbformats.h"
  29. #define SF_DRAGDROP_FLAGS SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK;
  30. UINT CF_IDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
  31. UINT CF_SHELLURL = RegisterClipboardFormat(CFSTR_SHELLURL);
  32. #define TPM_FLAGS               (TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD)
  33. //////////////////////////////////////////////////////////////////////
  34. // Construction/Destruction
  35. //////////////////////////////////////////////////////////////////////
  36. CShellPidl::CShellPidl()
  37. {
  38. SHGetMalloc(&m_pMalloc);
  39.     SHGetDesktopFolder(&m_psfDesktop);
  40. ZeroMemory(&m_EmptyPidl,sizeof(ITEMIDLIST));
  41. }
  42. CShellPidl::~CShellPidl()
  43. {
  44. if (m_pMalloc)
  45. m_pMalloc->Release();
  46. if (m_psfDesktop)
  47. m_psfDesktop->Release();
  48. }
  49. IMalloc *CShellPidl::GetMalloc()
  50. {
  51. return m_pMalloc;
  52. }
  53. DWORD CShellPidl::GetDragDropAttributes(LPLVITEMDATA plvid)
  54. {
  55. return GetDragDropAttributes(plvid->lpsfParent,plvid->lpi);
  56. }
  57. DWORD CShellPidl::GetDragDropAttributes(LPTVITEMDATA ptvid)
  58. {
  59. return GetDragDropAttributes(ptvid->lpsfParent,ptvid->lpi);
  60. }
  61. DWORD CShellPidl::GetDragDropAttributes(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl)
  62. {
  63. if (pFolder == NULL)
  64. pFolder = m_psfDesktop;
  65. DWORD dwAttrs=SF_DRAGDROP_FLAGS;
  66. HRESULT hr = pFolder->GetAttributesOf(1,(LPCITEMIDLIST*)&pidl,&dwAttrs);
  67. if (FAILED(hr))
  68. dwAttrs = SF_DRAGDROP_FLAGS;
  69. return dwAttrs;
  70. }
  71. DWORD CShellPidl::GetDragDropAttributes(COleDataObject *pDataObject)
  72. {
  73. IDataObject *pDataObj = pDataObject->m_lpDataObject;
  74. STGMEDIUM stgm;
  75. ZeroMemory(&stgm, sizeof(stgm));
  76.     FORMATETC fetc;
  77.     fetc.cfFormat = CF_IDLIST;
  78.     fetc.ptd = NULL;
  79.     fetc.dwAspect = DVASPECT_CONTENT;
  80.     fetc.lindex = -1;
  81.     fetc.tymed = TYMED_HGLOBAL;
  82. DWORD dwAttrs=DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
  83.     HRESULT hr = pDataObj->QueryGetData(&fetc);
  84. if (FAILED(hr))
  85. return dwAttrs;
  86.     hr = pDataObj->GetData(&fetc, &stgm);
  87. if (FAILED(hr))
  88. return dwAttrs;
  89.     DWORD pData = (DWORD)GlobalLock(stgm.hGlobal);
  90. LPIDA pIDList = (LPIDA)pData;
  91. UINT nFolderOffset = pIDList->aoffset[0];
  92. TRACE2("PIDL(%u) offfset=%un",0,nFolderOffset);
  93. DWORD pFolder = pData+nFolderOffset;
  94.     LPITEMIDLIST pidl = (LPITEMIDLIST)pFolder;
  95.     LPSHELLFOLDER psfParent = GetFolder(pidl);
  96. if (psfParent)
  97. {
  98. // get attributes for the children
  99. TRACE1("PIDL count=%un",pIDList->cidl);
  100. for(UINT i=1;i < (pIDList->cidl+1);i++)
  101. {
  102. UINT nListOffset = pIDList->aoffset[i];
  103. TRACE2("PIDL(%u) offfset=%un",i,nListOffset);
  104. ULONG ulAttrs = SF_DRAGDROP_FLAGS;
  105. DWORD dwPidl = pData+nListOffset;
  106. LPITEMIDLIST pidlist = (LPITEMIDLIST)dwPidl;
  107. psfParent->GetAttributesOf(1,(LPCITEMIDLIST*)&pidlist,&ulAttrs);
  108. #ifdef _DEBUG
  109. CString sPath;
  110. SHPidlToPathEx(pidlist,sPath,psfParent);
  111. TRACE2("Drag drop source path=%s Attributes=%un",sPath,ulAttrs);
  112. #endif
  113. if (ulAttrs)
  114. dwAttrs = dwAttrs & ulAttrs;
  115. }
  116. psfParent->Release();
  117. }
  118. GlobalUnlock(stgm.hGlobal);
  119.     ReleaseStgMedium(&stgm);
  120. return dwAttrs;
  121. }
  122. LPCITEMIDLIST CShellPidl::GetEmptyPidl()
  123. {
  124. return &m_EmptyPidl;
  125. }
  126. bool CShellPidl::IsDesktopFolder(LPSHELLFOLDER psFolder)
  127. {
  128. return psFolder == NULL || psFolder == m_psfDesktop;
  129. }
  130. LPSHELLFOLDER CShellPidl::GetDesktopFolder()
  131. {
  132. return m_psfDesktop;
  133. }
  134. LPSHELLFOLDER CShellPidl::GetFolder(LPITEMIDLIST pidl)
  135. {
  136. if (pidl == NULL || pidl->mkid.cb == 0)
  137. return m_psfDesktop;
  138. LPSHELLFOLDER pFolder=NULL;
  139. if (FAILED(m_psfDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pFolder)))
  140. return NULL;
  141. return pFolder;
  142. }
  143. // CopyItemID - creates an item identifier list containing the first 
  144. //     item identifier in the specified list. 
  145. // Returns a PIDL if successful, or NULL if out of memory. 
  146. LPITEMIDLIST CShellPidl::CopyItemID(LPITEMIDLIST pidl,int n) 
  147. // Get the size of the specified item identifier. 
  148. ASSERT(pidl);
  149. if (n == 0)
  150. {
  151. int cb = pidl->mkid.cb;
  152. int nSize = cb + sizeof(pidl->mkid.cb);
  153. // Allocate a new item identifier list. 
  154. LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(nSize); 
  155. ZeroMemory(pidlNew,nSize);
  156. if (pidlNew == NULL) 
  157. return NULL; 
  158. // Copy the specified item identifier. 
  159. CopyMemory(pidlNew, pidl, nSize-sizeof(pidl->mkid.cb)); 
  160. return pidlNew; 
  161. }
  162. else
  163. {
  164. LPITEMIDLIST pidl_index=NULL;
  165.    for(int i=0;i < n && pidl->mkid.cb;i++)
  166. {
  167. pidl_index = pidl;
  168. pidl = Next(pidl);
  169. }
  170. return pidl_index ? CopyItemID(pidl_index,0) : NULL;
  171. }
  172. return NULL;
  173. }
  174. // Returns a PIDL if successful, or NULL if out of memory. 
  175. LPITEMIDLIST CShellPidl::CopyLastItemID(LPITEMIDLIST pidl) 
  176. // Get the size of the specified item identifier. 
  177. ASSERT(pidl);
  178.     if (pidl == NULL)
  179. return NULL;
  180. LPITEMIDLIST last_pidl=pidl;
  181.     while (pidl->mkid.cb)
  182.     {
  183. last_pidl = pidl;
  184.         pidl = Next(pidl);
  185.     }
  186. if (last_pidl == NULL)
  187. return NULL;
  188. return CopyItemID(last_pidl);
  189. }
  190. // copies the absolute pidl up till n
  191. LPITEMIDLIST CShellPidl::CopyAbsItemID(LPITEMIDLIST pidl,int n) 
  192. // Get the size of the specified item identifier. 
  193. ASSERT(pidl);
  194.     if (pidl == NULL)
  195. return NULL;
  196. LPITEMIDLIST first_pidl=NULL;
  197. LPITEMIDLIST abs_pidl=NULL;
  198. LPITEMIDLIST new_abs_pidl=NULL;
  199.     for(int i=0;i < n && pidl && pidl->mkid.cb;i++)
  200.     {
  201. first_pidl = CopyItemID(pidl);
  202. new_abs_pidl = ConcatPidl(abs_pidl,first_pidl);
  203. if (abs_pidl)
  204. {
  205. m_pMalloc->Free(abs_pidl);
  206. }
  207. abs_pidl = new_abs_pidl;
  208. if (first_pidl)
  209. {
  210. m_pMalloc->Free(first_pidl);
  211. }
  212.         pidl = Next(pidl);
  213.     }
  214. return new_abs_pidl;
  215. }
  216. // Makes a copy of an ITEMIDLIST 
  217. LPITEMIDLIST CShellPidl::CopyItemIDList(LPITEMIDLIST pidl) 
  218. // Allocate a new item identifier list. 
  219. int nSize = GetSize(pidl);
  220. LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(nSize); 
  221. ZeroMemory(pidlNew,nSize);
  222. if (pidlNew == NULL) 
  223. return NULL; 
  224. // Copy the specified item identifier. 
  225. CopyMemory(pidlNew, pidl, nSize); 
  226. return pidlNew; 
  227. }
  228. bool CShellPidl::CompareMemPidls(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2) 
  229. // Allocate a new item identifier list. 
  230. if (pidl1 == NULL || pidl2 == NULL)
  231. return false;
  232. return memcmp(pidl1,pidl2,(size_t)GetSize(pidl1)) == 0;
  233. }
  234. // Returns true if lists are the same
  235. bool CShellPidl::ComparePidls(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2) 
  236. // Allocate a new item identifier list. 
  237. if (pFolder == NULL)
  238. pFolder = GetDesktopFolder();
  239. if (pidl1 == NULL || pidl2 == NULL)
  240. return false;
  241. return (short)pFolder->CompareIDs(0,pidl1,pidl2) == 0;
  242. }
  243. void CShellPidl::Free(void *pv)
  244. {
  245. if (m_pMalloc)
  246. m_pMalloc->Free(pv);
  247. }
  248. void CShellPidl::FreePidl(LPITEMIDLIST pidl)
  249. {
  250. if (m_pMalloc)
  251. m_pMalloc->Free(pidl);
  252. }
  253. UINT CShellPidl::GetCount(LPCITEMIDLIST pidl)
  254. {
  255.     UINT nCount = 0;
  256.     if (pidl)
  257.     {
  258.         while (pidl->mkid.cb)
  259.         {
  260.             pidl = Next(pidl);
  261. nCount++;
  262.         }
  263.     }
  264.     return nCount;
  265. }
  266. UINT CShellPidl::GetSize(LPCITEMIDLIST pidl)
  267. {
  268.     UINT cbTotal = 0;
  269.     if (pidl)
  270.     {
  271.         cbTotal += sizeof(pidl->mkid.cb);       // Null terminator
  272.         while (pidl->mkid.cb)
  273.         {
  274.             cbTotal += pidl->mkid.cb;
  275.             pidl = Next(pidl);
  276.         }
  277.     }
  278.     return cbTotal;
  279. }
  280. LPITEMIDLIST CShellPidl::Next(LPCITEMIDLIST pidl)
  281. {
  282.    LPSTR lpMem=(LPSTR)pidl;
  283.    lpMem+=pidl->mkid.cb;
  284.    return (LPITEMIDLIST)lpMem;
  285. }
  286. LPITEMIDLIST CShellPidl::ConcatPidl(LPITEMIDLIST pidlDest,LPITEMIDLIST pidlSrc) 
  287. // Get the size of the specified item identifier. 
  288.     UINT cbDest=0;
  289.     UINT cbSrc=0;
  290.     if (pidlDest)  //May be NULL
  291.        cbDest = GetSize(pidlDest) - sizeof(pidlDest->mkid.cb);
  292.     cbSrc = GetSize(pidlSrc);
  293. // Allocate a new item identifier list. 
  294. LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(cbSrc+cbDest); 
  295. if (pidlNew == NULL) 
  296. return NULL; 
  297. ZeroMemory(pidlNew,cbSrc+cbDest);
  298. // Copy the specified item identifier. 
  299. if (pidlDest)
  300. CopyMemory(pidlNew, pidlDest, cbDest); 
  301. CopyMemory(((USHORT*)(((LPBYTE)pidlNew)+cbDest)), pidlSrc, cbSrc); 
  302. return pidlNew; 
  303. }
  304. int CShellPidl::GetIcon(LPITEMIDLIST lpi, UINT uFlags)
  305. {
  306.    SHFILEINFO    sfi;
  307.    ZeroMemory(&sfi,sizeof(sfi));
  308.    if (uFlags == 0)
  309. uFlags |= (SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  310.    uFlags |= SHGFI_PIDL;
  311.    SHGetFileInfo((LPCTSTR)lpi, 0, &sfi, sizeof(SHFILEINFO), uFlags);
  312.    return sfi.iIcon;
  313. }
  314. STDMETHODIMP CShellPidl::SHPidlToPathEx(LPCITEMIDLIST pidl, CString &sPath, LPSHELLFOLDER pFolder, DWORD dwFlags)
  315. {
  316. STRRET StrRetFilePath;
  317. LPTSTR pszFilePath = NULL;
  318. HRESULT hr=E_FAIL;
  319. if (pFolder == NULL)
  320. pFolder = GetDesktopFolder();
  321. if (pFolder == NULL)
  322. return E_FAIL;
  323. hr = pFolder->GetDisplayNameOf(pidl, dwFlags, &StrRetFilePath);
  324. if (SUCCEEDED(hr))
  325. {
  326. StrRetToStr(StrRetFilePath, &pszFilePath, (LPITEMIDLIST)pidl);
  327. sPath = pszFilePath;
  328. }
  329. if (pszFilePath)
  330. m_pMalloc->Free(pszFilePath);
  331. return hr;
  332. }
  333. STDMETHODIMP CShellPidl::SHPathToPidlEx(LPCTSTR szPath, LPITEMIDLIST* ppidl, LPSHELLFOLDER pFolder)
  334. {
  335.    OLECHAR wszPath[MAX_PATH] = {0};
  336.    ULONG nCharsParsed = 0;
  337.    LPSHELLFOLDER pShellFolder = NULL;
  338.    BOOL bFreeOnExit = FALSE;
  339. #ifdef UNICODE
  340.    lstrcpy(wszPath,szPath);
  341. #else
  342.    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH);
  343. #endif
  344.    // Use the desktop's IShellFolder by default
  345.    if(pFolder == NULL)
  346.    {
  347.       SHGetDesktopFolder(&pShellFolder);
  348.       bFreeOnExit = TRUE;
  349.    }
  350.    else
  351.       pShellFolder = pFolder;
  352.    HRESULT hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharsParsed, ppidl, NULL);
  353.    if(bFreeOnExit)
  354.       pShellFolder->Release();
  355.    return hr;
  356. }
  357. void CShellPidl::GetTypeName(LPITEMIDLIST lpi,CString &sTypeName)
  358. {
  359.    SHFILEINFO    sfi;
  360.    ZeroMemory(&sfi,sizeof(sfi));
  361.    UINT uFlags = SHGFI_PIDL | SHGFI_TYPENAME;
  362.    SHGetFileInfo((LPCTSTR)lpi, 0, &sfi, sizeof(SHFILEINFO), uFlags);
  363.    sTypeName = sfi.szTypeName;
  364. }
  365. void CShellPidl::GetDisplayName(LPITEMIDLIST lpifq,CString &sDisplayName)
  366. {
  367.    SHFILEINFO    sfi;
  368.    ZeroMemory(&sfi,sizeof(sfi));
  369.    UINT uFlags = SHGFI_PIDL | SHGFI_DISPLAYNAME;
  370.    SHGetFileInfo((LPCTSTR)lpifq, 0, &sfi, sizeof(SHFILEINFO), uFlags);
  371.    sDisplayName = sfi.szDisplayName;
  372. }
  373. void CShellPidl::GetNormalAndSelectedIcons (
  374.    LPITEMIDLIST lpifq, int &iImage, int &iSelectedImage)
  375. {
  376.    // Don't check the return value here. 
  377.    // If IGetIcon() fails, you're in big trouble.
  378.    iImage = GetIcon (lpifq, 
  379.       SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  380.    
  381.    iSelectedImage = GetIcon (lpifq, 
  382.       SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON);
  383.    
  384.    return;
  385. }
  386. BOOL CShellPidl::HandleMenuMsg(HWND hwnd, LPSHELLFOLDER lpsfParent,
  387.      LPITEMIDLIST  lpi, UINT uMsg, WPARAM wParam, LPARAM lParam)
  388. {
  389.     LPCONTEXTMENU lpcm=NULL;
  390.     HRESULT hr=lpsfParent->GetUIObjectOf(hwnd,
  391.         1,  // get attributes for this many objects
  392.         (const struct _ITEMIDLIST **)&lpi,
  393.         IID_IContextMenu,
  394.         0,
  395.         (LPVOID *)&lpcm);
  396.     if (SUCCEEDED(hr))  
  397.     {
  398.     LPCONTEXTMENU2 lpcm2=NULL;
  399. hr = lpcm->QueryInterface(IID_IContextMenu2,(LPVOID*)&lpcm2);
  400. lpcm->Release();
  401. if (SUCCEEDED(hr))  
  402.     {
  403. lpcm2->HandleMenuMsg(uMsg,wParam,lParam);
  404. lpcm2->Release();
  405. }
  406. return TRUE;
  407. }
  408. return FALSE;
  409. }
  410. BOOL CShellPidl::PopupTheMenu(HWND hwnd, LPSHELLFOLDER lpsfParent,
  411.      LPITEMIDLIST  *plpi, UINT cidl, LPPOINT lppt)
  412. {
  413.   CMenu menu;
  414.     menu.CreatePopupMenu();
  415. g_CoolMenuManager.Install(CWnd::FromHandle(hwnd));
  416. CString sPath;
  417. if (lpsfParent == NULL)
  418. lpsfParent = GetDesktopFolder();
  419. SHPidlToPathEx(*plpi,sPath,lpsfParent);
  420. CShellContextMenu shell_menu(hwnd,sPath,plpi,cidl,lpsfParent);
  421. shell_menu.SetMenu(&menu);
  422.     int idCmd = menu.TrackPopupMenu(TPM_FLAGS, lppt->x, lppt->y, CWnd::FromHandle(hwnd));
  423. shell_menu.InvokeCommand(idCmd);
  424. g_CoolMenuManager.Uninstall();
  425. return TRUE;
  426. }
  427. /****************************************************************************
  428. *
  429. *    FUNCTION: GetName(LPSHELLFOLDER lpsf,LPITEMIDLIST  lpi,DWORD dwFlags,
  430. *             LPSTR         lpFriendlyName)
  431. *
  432. *    PURPOSE:  Gets the friendly name for the folder 
  433. *
  434. ****************************************************************************/
  435. BOOL CShellPidl::GetName (LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, 
  436.    DWORD dwFlags, CString &sFriendlyName)
  437. {
  438.    BOOL   bSuccess=TRUE;
  439.    STRRET str;
  440.    if (NOERROR==lpsf->GetDisplayNameOf(lpi,dwFlags, &str))
  441.    {
  442.       switch (str.uType)
  443.       {
  444.          case STRRET_WSTR:
  445. #ifdef UNICODE
  446.  _tcscpy(sFriendlyName.GetBuffer(MAX_PATH),str.pOleStr);
  447.  sFriendlyName.ReleaseBuffer();
  448. #else
  449.             WideCharToMultiByte(
  450.                CP_ACP,                 // code page
  451.                0,                // dwFlags
  452.                str.pOleStr,            // lpWideCharStr
  453.                -1,                     // cchWideCharStr
  454.                sFriendlyName.GetBuffer(_MAX_PATH),         // lpMultiByteStr
  455.                _MAX_PATH, // cchMultiByte
  456.                NULL,                   // lpDefaultChar
  457.                NULL);                  // lpUsedDefaultChar
  458. #endif
  459. sFriendlyName.ReleaseBuffer();
  460.              break;
  461.          case STRRET_OFFSET:
  462.              sFriendlyName = (LPTSTR)lpi+str.uOffset;
  463.              break;
  464.          case STRRET_CSTR:             
  465.              sFriendlyName = (LPTSTR)str.cStr;
  466.              break;
  467.          default:
  468.              bSuccess = FALSE;
  469.              break;
  470.       }
  471.    }
  472.    else
  473.       bSuccess = FALSE;
  474.    return bSuccess;
  475. }
  476. //
  477. // ResolveChannel: Resolves a Channel Shortcut to its URL
  478. //
  479. STDMETHODIMP CShellPidl::ResolveChannel(IShellFolder* pFolder, LPCITEMIDLIST pidl, LPTSTR* lpszURL)
  480. {
  481.    IShellLink* pShellLink;
  482.    *lpszURL = NULL;  // Assume failure
  483.    // Get a pointer to the IShellLink interface from the given folder
  484.    HRESULT hr = pFolder->GetUIObjectOf(NULL, 1, &pidl, IID_IShellLink, NULL, (LPVOID*)&pShellLink);
  485.    if (SUCCEEDED(hr))
  486.    {
  487.       LPITEMIDLIST pidlChannel;
  488.       // Convert the IShellLink pointer to a PIDL.
  489.       hr = pShellLink->GetIDList(&pidlChannel);
  490.       if (SUCCEEDED(hr))
  491.       {
  492.          IShellFolder* psfDesktop;
  493.          hr = SHGetDesktopFolder(&psfDesktop);
  494.          if (SUCCEEDED(hr))
  495.          {
  496.             STRRET strret;
  497.             hr = psfDesktop->GetDisplayNameOf(pidlChannel, 0, &strret);
  498.             if (SUCCEEDED(hr))
  499. StrRetToStr(strret, lpszURL, pidlChannel);
  500.             psfDesktop->Release();
  501.          }
  502.       }
  503.       pShellLink->Release();
  504.    }
  505.    return hr;
  506. }
  507. STDMETHODIMP CShellPidl::ResolveHistoryShortcut(LPSHELLFOLDER pFolder,LPCITEMIDLIST *ppidl,CString &sURL)
  508. {
  509. HRESULT hr=E_FAIL;
  510. IDataObject *pObj=NULL;
  511. hr = pFolder->GetUIObjectOf(NULL, 1, ppidl, IID_IDataObject, NULL, (LPVOID*)&pObj);
  512. if (SUCCEEDED(hr))
  513. {
  514. hr = GetURL(pObj,sURL);
  515. pObj->Release();
  516. }
  517. return hr;
  518. }
  519. STDMETHODIMP CShellPidl::GetURL(IDataObject *pDataObj,CString &sURL)
  520. {
  521. sURL.Empty();
  522. STGMEDIUM stgm;
  523. ZeroMemory(&stgm, sizeof(stgm));
  524.     FORMATETC fetc;
  525.     fetc.cfFormat = CF_SHELLURL;
  526.     fetc.ptd = NULL;
  527.     fetc.dwAspect = DVASPECT_CONTENT;
  528.     fetc.lindex = -1;
  529.     fetc.tymed = TYMED_HGLOBAL;
  530.     HRESULT hr = pDataObj->QueryGetData(&fetc);
  531. if (FAILED(hr))
  532. return hr;
  533.     hr = pDataObj->GetData(&fetc, &stgm);
  534. if (FAILED(hr))
  535. return hr;
  536.     LPCTSTR pData = (LPCTSTR)GlobalLock(stgm.hGlobal);
  537. sURL = pData;
  538. GlobalUnlock(stgm.hGlobal);
  539.     ReleaseStgMedium(&stgm);
  540. return S_OK;
  541. }
  542. //
  543. // ResolveInternetShortcut: Resolves an Internet Shortcut to its URL
  544. //
  545. STDMETHODIMP CShellPidl::ResolveInternetShortcut(LPCTSTR lpszLinkFile, LPTSTR* lpszURL)
  546. {
  547. IUniformResourceLocator* pUrlLink = NULL;
  548. *lpszURL=NULL;
  549. HRESULT hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  550.  IID_IUniformResourceLocator, (LPVOID*)&pUrlLink);
  551. if (FAILED(hr))
  552. return hr;
  553. IPersistFile* pPersistFile = NULL;
  554. hr = pUrlLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile);
  555. if (SUCCEEDED(hr))
  556. {
  557.  // Ensure that the string is Unicode. 
  558.  WORD wsz[MAX_PATH];  
  559. #ifdef UNICODE
  560.  _tcscpy(wsz,lpszLinkFile);
  561. #else
  562.  MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH);
  563. #endif
  564.  // Load the Internet Shortcut from persistent storage.
  565.  hr = pPersistFile->Load(wsz, STGM_READ);
  566.  if (SUCCEEDED(hr))
  567.  {
  568. hr = pUrlLink->GetURL(lpszURL);
  569.  }
  570.  pPersistFile->Release();
  571. }
  572. pUrlLink->Release();
  573. return hr;
  574. }  
  575. //
  576. // ResolveLink: Resolves a Shell Link to its actual folder location
  577. //
  578. STDMETHODIMP CShellPidl::ResolveLink(HWND hWnd,LPCTSTR lpszLinkFile, LPTSTR* lpszURL)
  579. {
  580.    IShellLink* pShellLink = NULL;
  581.    *lpszURL = NULL;   // Assume failure
  582.    HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  583.                                  IID_IShellLink, (LPVOID*)&pShellLink); 
  584.    if (SUCCEEDED(hr))
  585.    {
  586.       IPersistFile* pPersistFile = NULL;
  587.       hr = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile);
  588.       if (SUCCEEDED(hr))
  589.       {
  590.          // Ensure that the string is Unicode. 
  591.          WORD wsz[MAX_PATH];  
  592. #ifdef UNICODE
  593.  _tcscpy(wsz,lpszLinkFile);
  594. #else
  595.          MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH);
  596. #endif
  597.          // Load the shortcut.from persistent storage
  598.          hr = pPersistFile->Load(wsz, STGM_READ);
  599.          if (SUCCEEDED(hr))
  600.          {
  601.             WIN32_FIND_DATA wfd;      
  602.             hr = pShellLink->Resolve(hWnd, SLR_NO_UI); 
  603.             if (NOERROR == hr)
  604.             {
  605.                // Get the path to the link target. 
  606.        *lpszURL = (LPTSTR)m_pMalloc->Alloc(MAX_PATH);  // Must remember to Free later
  607.                hr = pShellLink->GetPath(*lpszURL, MAX_PATH - 1, (WIN32_FIND_DATA*)&wfd, SLGP_UNCPRIORITY);
  608.             }
  609.          }
  610.          pPersistFile->Release();
  611.       }
  612.       pShellLink->Release();
  613.    }
  614.    return hr;
  615. }
  616. //
  617. // This method converts a STRRET structure to a LPTSTR
  618. //
  619. #ifdef UNICODE
  620. STDMETHODIMP CShellPidl::StrRetToStr(STRRET StrRet, LPTSTR* str, LPITEMIDLIST pidl)
  621. {
  622. HRESULT hr = S_OK;
  623. int cch;
  624. LPSTR strOffset;
  625. *str = NULL;  // Assume failure
  626. switch (StrRet.uType)
  627.    {
  628. case STRRET_WSTR: 
  629. cch = wcslen(StrRet.pOleStr) + 1; // NULL terminator
  630. *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
  631. if (*str != NULL)
  632. lstrcpyn(*str, StrRet.pOleStr, cch);
  633. else
  634. hr = E_FAIL;
  635. break;
  636. case STRRET_OFFSET: 
  637. strOffset = (((char *) pidl) + StrRet.uOffset);
  638. cch = MultiByteToWideChar(CP_OEMCP, 0, strOffset, -1, NULL, 0); 
  639. *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
  640. if (*str != NULL)
  641. MultiByteToWideChar(CP_OEMCP, 0, strOffset, -1, *str, cch); 
  642. else
  643. hr = E_FAIL;
  644. break;
  645. case STRRET_CSTR: 
  646. cch = MultiByteToWideChar(CP_OEMCP, 0, StrRet.cStr, -1, NULL, 0); 
  647. *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR)); 
  648. if (*str != NULL)
  649. MultiByteToWideChar(CP_OEMCP, 0, StrRet.cStr, -1, *str, cch); 
  650. else
  651. hr = E_FAIL;
  652. break;
  653.  
  654. return hr;
  655. }
  656. #else // UNICODE not defined
  657. STDMETHODIMP CShellPidl::StrRetToStr(STRRET StrRet, LPTSTR* str, LPITEMIDLIST pidl)
  658. {
  659. HRESULT hr = S_OK;
  660. int cch;
  661. LPSTR strOffset;
  662. *str = NULL;  // Assume failure
  663. switch (StrRet.uType)
  664.    {
  665. case STRRET_WSTR: 
  666. cch = WideCharToMultiByte(CP_ACP, 0, StrRet.pOleStr, -1, NULL, 0, NULL, NULL); 
  667. *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR)); 
  668. if (*str != NULL)
  669. WideCharToMultiByte(CP_ACP, 0, StrRet.pOleStr, -1, *str, cch, NULL, NULL); 
  670. else
  671. hr = E_FAIL;
  672. break;
  673. case STRRET_OFFSET: 
  674. strOffset = (((char *) pidl) + StrRet.uOffset);
  675. cch = strlen(strOffset) + 1; // NULL terminator
  676. *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
  677. if (*str != NULL)
  678. strcpy(*str, strOffset);
  679. else
  680. hr = E_FAIL;
  681. break;
  682. case STRRET_CSTR: 
  683. cch = strlen(StrRet.cStr) + 1; // NULL terminator
  684. *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
  685. if (*str != NULL)
  686. strcpy(*str, StrRet.cStr);
  687. else
  688. hr = E_FAIL;
  689. break;
  690. return hr;
  691. }
  692. #endif