ShellPidl.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:21k
- //*******************************************************************************
- // COPYRIGHT NOTES
- // ---------------
- // You may use this source code, compile or redistribute it as part of your application
- // for free. You cannot redistribute it as a part of a software development
- // library without the agreement of the author. If the sources are
- // distributed along with the application, you should leave the original
- // copyright notes in the source code without any changes.
- // This code can be used WITHOUT ANY WARRANTIES at your own risk.
- //
- // For the latest updates to this code, check this site:
- // http://www.masmex.com
- // after Sept 2000
- //
- // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
- //*******************************************************************************
- // ShellPidl.cpp: implementation of the CShellPidl class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "ShellPidl.h"
- #include "UIMessages.h"
- #include <intshcut.h>
- #include <subsmgr.h>
- #include <ExDisp.h>
- #include "ShellContextMenu.h"
- #include "UICoolMenu.h"
- #include "cbformats.h"
- #define SF_DRAGDROP_FLAGS SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK;
- UINT CF_IDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
- UINT CF_SHELLURL = RegisterClipboardFormat(CFSTR_SHELLURL);
- #define TPM_FLAGS (TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD)
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CShellPidl::CShellPidl()
- {
- SHGetMalloc(&m_pMalloc);
- SHGetDesktopFolder(&m_psfDesktop);
- ZeroMemory(&m_EmptyPidl,sizeof(ITEMIDLIST));
- }
- CShellPidl::~CShellPidl()
- {
- if (m_pMalloc)
- m_pMalloc->Release();
- if (m_psfDesktop)
- m_psfDesktop->Release();
- }
- IMalloc *CShellPidl::GetMalloc()
- {
- return m_pMalloc;
- }
- DWORD CShellPidl::GetDragDropAttributes(LPLVITEMDATA plvid)
- {
- return GetDragDropAttributes(plvid->lpsfParent,plvid->lpi);
- }
- DWORD CShellPidl::GetDragDropAttributes(LPTVITEMDATA ptvid)
- {
- return GetDragDropAttributes(ptvid->lpsfParent,ptvid->lpi);
- }
- DWORD CShellPidl::GetDragDropAttributes(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl)
- {
- if (pFolder == NULL)
- pFolder = m_psfDesktop;
- DWORD dwAttrs=SF_DRAGDROP_FLAGS;
- HRESULT hr = pFolder->GetAttributesOf(1,(LPCITEMIDLIST*)&pidl,&dwAttrs);
- if (FAILED(hr))
- dwAttrs = SF_DRAGDROP_FLAGS;
- return dwAttrs;
- }
- DWORD CShellPidl::GetDragDropAttributes(COleDataObject *pDataObject)
- {
- IDataObject *pDataObj = pDataObject->m_lpDataObject;
- STGMEDIUM stgm;
- ZeroMemory(&stgm, sizeof(stgm));
- FORMATETC fetc;
- fetc.cfFormat = CF_IDLIST;
- fetc.ptd = NULL;
- fetc.dwAspect = DVASPECT_CONTENT;
- fetc.lindex = -1;
- fetc.tymed = TYMED_HGLOBAL;
- DWORD dwAttrs=DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
- HRESULT hr = pDataObj->QueryGetData(&fetc);
- if (FAILED(hr))
- return dwAttrs;
- hr = pDataObj->GetData(&fetc, &stgm);
- if (FAILED(hr))
- return dwAttrs;
- DWORD pData = (DWORD)GlobalLock(stgm.hGlobal);
- LPIDA pIDList = (LPIDA)pData;
- UINT nFolderOffset = pIDList->aoffset[0];
- TRACE2("PIDL(%u) offfset=%un",0,nFolderOffset);
- DWORD pFolder = pData+nFolderOffset;
- LPITEMIDLIST pidl = (LPITEMIDLIST)pFolder;
- LPSHELLFOLDER psfParent = GetFolder(pidl);
- if (psfParent)
- {
- // get attributes for the children
- TRACE1("PIDL count=%un",pIDList->cidl);
- for(UINT i=1;i < (pIDList->cidl+1);i++)
- {
- UINT nListOffset = pIDList->aoffset[i];
- TRACE2("PIDL(%u) offfset=%un",i,nListOffset);
- ULONG ulAttrs = SF_DRAGDROP_FLAGS;
- DWORD dwPidl = pData+nListOffset;
- LPITEMIDLIST pidlist = (LPITEMIDLIST)dwPidl;
- psfParent->GetAttributesOf(1,(LPCITEMIDLIST*)&pidlist,&ulAttrs);
- #ifdef _DEBUG
- CString sPath;
- SHPidlToPathEx(pidlist,sPath,psfParent);
- TRACE2("Drag drop source path=%s Attributes=%un",sPath,ulAttrs);
- #endif
- if (ulAttrs)
- dwAttrs = dwAttrs & ulAttrs;
- }
- psfParent->Release();
- }
- GlobalUnlock(stgm.hGlobal);
- ReleaseStgMedium(&stgm);
- return dwAttrs;
- }
- LPCITEMIDLIST CShellPidl::GetEmptyPidl()
- {
- return &m_EmptyPidl;
- }
- bool CShellPidl::IsDesktopFolder(LPSHELLFOLDER psFolder)
- {
- return psFolder == NULL || psFolder == m_psfDesktop;
- }
- LPSHELLFOLDER CShellPidl::GetDesktopFolder()
- {
- return m_psfDesktop;
- }
- LPSHELLFOLDER CShellPidl::GetFolder(LPITEMIDLIST pidl)
- {
- if (pidl == NULL || pidl->mkid.cb == 0)
- return m_psfDesktop;
- LPSHELLFOLDER pFolder=NULL;
- if (FAILED(m_psfDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pFolder)))
- return NULL;
- return pFolder;
- }
- // CopyItemID - creates an item identifier list containing the first
- // item identifier in the specified list.
- // Returns a PIDL if successful, or NULL if out of memory.
- LPITEMIDLIST CShellPidl::CopyItemID(LPITEMIDLIST pidl,int n)
- {
- // Get the size of the specified item identifier.
- ASSERT(pidl);
- if (n == 0)
- {
- int cb = pidl->mkid.cb;
- int nSize = cb + sizeof(pidl->mkid.cb);
- // Allocate a new item identifier list.
- LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(nSize);
- ZeroMemory(pidlNew,nSize);
- if (pidlNew == NULL)
- return NULL;
- // Copy the specified item identifier.
- CopyMemory(pidlNew, pidl, nSize-sizeof(pidl->mkid.cb));
- return pidlNew;
- }
- else
- {
- LPITEMIDLIST pidl_index=NULL;
- for(int i=0;i < n && pidl->mkid.cb;i++)
- {
- pidl_index = pidl;
- pidl = Next(pidl);
- }
- return pidl_index ? CopyItemID(pidl_index,0) : NULL;
- }
- return NULL;
- }
- // Returns a PIDL if successful, or NULL if out of memory.
- LPITEMIDLIST CShellPidl::CopyLastItemID(LPITEMIDLIST pidl)
- {
- // Get the size of the specified item identifier.
- ASSERT(pidl);
- if (pidl == NULL)
- return NULL;
- LPITEMIDLIST last_pidl=pidl;
- while (pidl->mkid.cb)
- {
- last_pidl = pidl;
- pidl = Next(pidl);
- }
- if (last_pidl == NULL)
- return NULL;
- return CopyItemID(last_pidl);
- }
- // copies the absolute pidl up till n
- LPITEMIDLIST CShellPidl::CopyAbsItemID(LPITEMIDLIST pidl,int n)
- {
- // Get the size of the specified item identifier.
- ASSERT(pidl);
- if (pidl == NULL)
- return NULL;
- LPITEMIDLIST first_pidl=NULL;
- LPITEMIDLIST abs_pidl=NULL;
- LPITEMIDLIST new_abs_pidl=NULL;
- for(int i=0;i < n && pidl && pidl->mkid.cb;i++)
- {
- first_pidl = CopyItemID(pidl);
- new_abs_pidl = ConcatPidl(abs_pidl,first_pidl);
- if (abs_pidl)
- {
- m_pMalloc->Free(abs_pidl);
- }
- abs_pidl = new_abs_pidl;
- if (first_pidl)
- {
- m_pMalloc->Free(first_pidl);
- }
- pidl = Next(pidl);
- }
- return new_abs_pidl;
- }
- // Makes a copy of an ITEMIDLIST
- LPITEMIDLIST CShellPidl::CopyItemIDList(LPITEMIDLIST pidl)
- {
- // Allocate a new item identifier list.
- int nSize = GetSize(pidl);
- LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(nSize);
- ZeroMemory(pidlNew,nSize);
- if (pidlNew == NULL)
- return NULL;
- // Copy the specified item identifier.
- CopyMemory(pidlNew, pidl, nSize);
- return pidlNew;
- }
- bool CShellPidl::CompareMemPidls(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
- {
- // Allocate a new item identifier list.
- if (pidl1 == NULL || pidl2 == NULL)
- return false;
- return memcmp(pidl1,pidl2,(size_t)GetSize(pidl1)) == 0;
- }
- // Returns true if lists are the same
- bool CShellPidl::ComparePidls(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
- {
- // Allocate a new item identifier list.
- if (pFolder == NULL)
- pFolder = GetDesktopFolder();
- if (pidl1 == NULL || pidl2 == NULL)
- return false;
- return (short)pFolder->CompareIDs(0,pidl1,pidl2) == 0;
- }
- void CShellPidl::Free(void *pv)
- {
- if (m_pMalloc)
- m_pMalloc->Free(pv);
- }
- void CShellPidl::FreePidl(LPITEMIDLIST pidl)
- {
- if (m_pMalloc)
- m_pMalloc->Free(pidl);
- }
- UINT CShellPidl::GetCount(LPCITEMIDLIST pidl)
- {
- UINT nCount = 0;
- if (pidl)
- {
- while (pidl->mkid.cb)
- {
- pidl = Next(pidl);
- nCount++;
- }
- }
- return nCount;
- }
- UINT CShellPidl::GetSize(LPCITEMIDLIST pidl)
- {
- UINT cbTotal = 0;
- if (pidl)
- {
- cbTotal += sizeof(pidl->mkid.cb); // Null terminator
- while (pidl->mkid.cb)
- {
- cbTotal += pidl->mkid.cb;
- pidl = Next(pidl);
- }
- }
- return cbTotal;
- }
- LPITEMIDLIST CShellPidl::Next(LPCITEMIDLIST pidl)
- {
- LPSTR lpMem=(LPSTR)pidl;
- lpMem+=pidl->mkid.cb;
- return (LPITEMIDLIST)lpMem;
- }
- LPITEMIDLIST CShellPidl::ConcatPidl(LPITEMIDLIST pidlDest,LPITEMIDLIST pidlSrc)
- {
- // Get the size of the specified item identifier.
- UINT cbDest=0;
- UINT cbSrc=0;
- if (pidlDest) //May be NULL
- cbDest = GetSize(pidlDest) - sizeof(pidlDest->mkid.cb);
- cbSrc = GetSize(pidlSrc);
- // Allocate a new item identifier list.
- LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(cbSrc+cbDest);
- if (pidlNew == NULL)
- return NULL;
- ZeroMemory(pidlNew,cbSrc+cbDest);
- // Copy the specified item identifier.
- if (pidlDest)
- CopyMemory(pidlNew, pidlDest, cbDest);
- CopyMemory(((USHORT*)(((LPBYTE)pidlNew)+cbDest)), pidlSrc, cbSrc);
- return pidlNew;
- }
- int CShellPidl::GetIcon(LPITEMIDLIST lpi, UINT uFlags)
- {
- SHFILEINFO sfi;
- ZeroMemory(&sfi,sizeof(sfi));
- if (uFlags == 0)
- uFlags |= (SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
- uFlags |= SHGFI_PIDL;
- SHGetFileInfo((LPCTSTR)lpi, 0, &sfi, sizeof(SHFILEINFO), uFlags);
- return sfi.iIcon;
- }
- STDMETHODIMP CShellPidl::SHPidlToPathEx(LPCITEMIDLIST pidl, CString &sPath, LPSHELLFOLDER pFolder, DWORD dwFlags)
- {
- STRRET StrRetFilePath;
- LPTSTR pszFilePath = NULL;
- HRESULT hr=E_FAIL;
- if (pFolder == NULL)
- pFolder = GetDesktopFolder();
- if (pFolder == NULL)
- return E_FAIL;
- hr = pFolder->GetDisplayNameOf(pidl, dwFlags, &StrRetFilePath);
- if (SUCCEEDED(hr))
- {
- StrRetToStr(StrRetFilePath, &pszFilePath, (LPITEMIDLIST)pidl);
- sPath = pszFilePath;
- }
- if (pszFilePath)
- m_pMalloc->Free(pszFilePath);
- return hr;
- }
- STDMETHODIMP CShellPidl::SHPathToPidlEx(LPCTSTR szPath, LPITEMIDLIST* ppidl, LPSHELLFOLDER pFolder)
- {
- OLECHAR wszPath[MAX_PATH] = {0};
- ULONG nCharsParsed = 0;
- LPSHELLFOLDER pShellFolder = NULL;
- BOOL bFreeOnExit = FALSE;
- #ifdef UNICODE
- lstrcpy(wszPath,szPath);
- #else
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH);
- #endif
- // Use the desktop's IShellFolder by default
- if(pFolder == NULL)
- {
- SHGetDesktopFolder(&pShellFolder);
- bFreeOnExit = TRUE;
- }
- else
- pShellFolder = pFolder;
- HRESULT hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharsParsed, ppidl, NULL);
- if(bFreeOnExit)
- pShellFolder->Release();
- return hr;
- }
- void CShellPidl::GetTypeName(LPITEMIDLIST lpi,CString &sTypeName)
- {
- SHFILEINFO sfi;
- ZeroMemory(&sfi,sizeof(sfi));
- UINT uFlags = SHGFI_PIDL | SHGFI_TYPENAME;
- SHGetFileInfo((LPCTSTR)lpi, 0, &sfi, sizeof(SHFILEINFO), uFlags);
- sTypeName = sfi.szTypeName;
- }
- void CShellPidl::GetDisplayName(LPITEMIDLIST lpifq,CString &sDisplayName)
- {
- SHFILEINFO sfi;
- ZeroMemory(&sfi,sizeof(sfi));
- UINT uFlags = SHGFI_PIDL | SHGFI_DISPLAYNAME;
- SHGetFileInfo((LPCTSTR)lpifq, 0, &sfi, sizeof(SHFILEINFO), uFlags);
- sDisplayName = sfi.szDisplayName;
- }
- void CShellPidl::GetNormalAndSelectedIcons (
- LPITEMIDLIST lpifq, int &iImage, int &iSelectedImage)
- {
- // Don't check the return value here.
- // If IGetIcon() fails, you're in big trouble.
- iImage = GetIcon (lpifq,
- SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
-
- iSelectedImage = GetIcon (lpifq,
- SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON);
-
- return;
- }
- BOOL CShellPidl::HandleMenuMsg(HWND hwnd, LPSHELLFOLDER lpsfParent,
- LPITEMIDLIST lpi, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- LPCONTEXTMENU lpcm=NULL;
- HRESULT hr=lpsfParent->GetUIObjectOf(hwnd,
- 1, // get attributes for this many objects
- (const struct _ITEMIDLIST **)&lpi,
- IID_IContextMenu,
- 0,
- (LPVOID *)&lpcm);
- if (SUCCEEDED(hr))
- {
- LPCONTEXTMENU2 lpcm2=NULL;
- hr = lpcm->QueryInterface(IID_IContextMenu2,(LPVOID*)&lpcm2);
- lpcm->Release();
- if (SUCCEEDED(hr))
- {
- lpcm2->HandleMenuMsg(uMsg,wParam,lParam);
- lpcm2->Release();
- }
- return TRUE;
- }
- return FALSE;
- }
- BOOL CShellPidl::PopupTheMenu(HWND hwnd, LPSHELLFOLDER lpsfParent,
- LPITEMIDLIST *plpi, UINT cidl, LPPOINT lppt)
- {
- CMenu menu;
- menu.CreatePopupMenu();
- g_CoolMenuManager.Install(CWnd::FromHandle(hwnd));
- CString sPath;
- if (lpsfParent == NULL)
- lpsfParent = GetDesktopFolder();
- SHPidlToPathEx(*plpi,sPath,lpsfParent);
- CShellContextMenu shell_menu(hwnd,sPath,plpi,cidl,lpsfParent);
- shell_menu.SetMenu(&menu);
- int idCmd = menu.TrackPopupMenu(TPM_FLAGS, lppt->x, lppt->y, CWnd::FromHandle(hwnd));
- shell_menu.InvokeCommand(idCmd);
- g_CoolMenuManager.Uninstall();
- return TRUE;
- }
- /****************************************************************************
- *
- * FUNCTION: GetName(LPSHELLFOLDER lpsf,LPITEMIDLIST lpi,DWORD dwFlags,
- * LPSTR lpFriendlyName)
- *
- * PURPOSE: Gets the friendly name for the folder
- *
- ****************************************************************************/
- BOOL CShellPidl::GetName (LPSHELLFOLDER lpsf, LPITEMIDLIST lpi,
- DWORD dwFlags, CString &sFriendlyName)
- {
- BOOL bSuccess=TRUE;
- STRRET str;
- if (NOERROR==lpsf->GetDisplayNameOf(lpi,dwFlags, &str))
- {
- switch (str.uType)
- {
- case STRRET_WSTR:
- #ifdef UNICODE
- _tcscpy(sFriendlyName.GetBuffer(MAX_PATH),str.pOleStr);
- sFriendlyName.ReleaseBuffer();
- #else
- WideCharToMultiByte(
- CP_ACP, // code page
- 0, // dwFlags
- str.pOleStr, // lpWideCharStr
- -1, // cchWideCharStr
- sFriendlyName.GetBuffer(_MAX_PATH), // lpMultiByteStr
- _MAX_PATH, // cchMultiByte
- NULL, // lpDefaultChar
- NULL); // lpUsedDefaultChar
- #endif
- sFriendlyName.ReleaseBuffer();
- break;
- case STRRET_OFFSET:
- sFriendlyName = (LPTSTR)lpi+str.uOffset;
- break;
- case STRRET_CSTR:
- sFriendlyName = (LPTSTR)str.cStr;
- break;
- default:
- bSuccess = FALSE;
- break;
- }
- }
- else
- bSuccess = FALSE;
- return bSuccess;
- }
- //
- // ResolveChannel: Resolves a Channel Shortcut to its URL
- //
- STDMETHODIMP CShellPidl::ResolveChannel(IShellFolder* pFolder, LPCITEMIDLIST pidl, LPTSTR* lpszURL)
- {
- IShellLink* pShellLink;
- *lpszURL = NULL; // Assume failure
- // Get a pointer to the IShellLink interface from the given folder
- HRESULT hr = pFolder->GetUIObjectOf(NULL, 1, &pidl, IID_IShellLink, NULL, (LPVOID*)&pShellLink);
- if (SUCCEEDED(hr))
- {
- LPITEMIDLIST pidlChannel;
- // Convert the IShellLink pointer to a PIDL.
- hr = pShellLink->GetIDList(&pidlChannel);
- if (SUCCEEDED(hr))
- {
- IShellFolder* psfDesktop;
- hr = SHGetDesktopFolder(&psfDesktop);
- if (SUCCEEDED(hr))
- {
- STRRET strret;
- hr = psfDesktop->GetDisplayNameOf(pidlChannel, 0, &strret);
- if (SUCCEEDED(hr))
- StrRetToStr(strret, lpszURL, pidlChannel);
- psfDesktop->Release();
- }
- }
- pShellLink->Release();
- }
- return hr;
- }
- STDMETHODIMP CShellPidl::ResolveHistoryShortcut(LPSHELLFOLDER pFolder,LPCITEMIDLIST *ppidl,CString &sURL)
- {
- HRESULT hr=E_FAIL;
- IDataObject *pObj=NULL;
- hr = pFolder->GetUIObjectOf(NULL, 1, ppidl, IID_IDataObject, NULL, (LPVOID*)&pObj);
- if (SUCCEEDED(hr))
- {
- hr = GetURL(pObj,sURL);
- pObj->Release();
- }
- return hr;
- }
- STDMETHODIMP CShellPidl::GetURL(IDataObject *pDataObj,CString &sURL)
- {
- sURL.Empty();
- STGMEDIUM stgm;
- ZeroMemory(&stgm, sizeof(stgm));
- FORMATETC fetc;
- fetc.cfFormat = CF_SHELLURL;
- fetc.ptd = NULL;
- fetc.dwAspect = DVASPECT_CONTENT;
- fetc.lindex = -1;
- fetc.tymed = TYMED_HGLOBAL;
- HRESULT hr = pDataObj->QueryGetData(&fetc);
- if (FAILED(hr))
- return hr;
- hr = pDataObj->GetData(&fetc, &stgm);
- if (FAILED(hr))
- return hr;
- LPCTSTR pData = (LPCTSTR)GlobalLock(stgm.hGlobal);
- sURL = pData;
- GlobalUnlock(stgm.hGlobal);
- ReleaseStgMedium(&stgm);
- return S_OK;
- }
- //
- // ResolveInternetShortcut: Resolves an Internet Shortcut to its URL
- //
- STDMETHODIMP CShellPidl::ResolveInternetShortcut(LPCTSTR lpszLinkFile, LPTSTR* lpszURL)
- {
- IUniformResourceLocator* pUrlLink = NULL;
- *lpszURL=NULL;
- HRESULT hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
- IID_IUniformResourceLocator, (LPVOID*)&pUrlLink);
- if (FAILED(hr))
- return hr;
- IPersistFile* pPersistFile = NULL;
- hr = pUrlLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile);
- if (SUCCEEDED(hr))
- {
- // Ensure that the string is Unicode.
- WORD wsz[MAX_PATH];
- #ifdef UNICODE
- _tcscpy(wsz,lpszLinkFile);
- #else
- MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH);
- #endif
- // Load the Internet Shortcut from persistent storage.
- hr = pPersistFile->Load(wsz, STGM_READ);
- if (SUCCEEDED(hr))
- {
- hr = pUrlLink->GetURL(lpszURL);
- }
- pPersistFile->Release();
- }
- pUrlLink->Release();
- return hr;
- }
- //
- // ResolveLink: Resolves a Shell Link to its actual folder location
- //
- STDMETHODIMP CShellPidl::ResolveLink(HWND hWnd,LPCTSTR lpszLinkFile, LPTSTR* lpszURL)
- {
- IShellLink* pShellLink = NULL;
- *lpszURL = NULL; // Assume failure
- HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
- IID_IShellLink, (LPVOID*)&pShellLink);
- if (SUCCEEDED(hr))
- {
- IPersistFile* pPersistFile = NULL;
- hr = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile);
- if (SUCCEEDED(hr))
- {
- // Ensure that the string is Unicode.
- WORD wsz[MAX_PATH];
- #ifdef UNICODE
- _tcscpy(wsz,lpszLinkFile);
- #else
- MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH);
- #endif
- // Load the shortcut.from persistent storage
- hr = pPersistFile->Load(wsz, STGM_READ);
- if (SUCCEEDED(hr))
- {
- WIN32_FIND_DATA wfd;
- hr = pShellLink->Resolve(hWnd, SLR_NO_UI);
- if (NOERROR == hr)
- {
- // Get the path to the link target.
- *lpszURL = (LPTSTR)m_pMalloc->Alloc(MAX_PATH); // Must remember to Free later
- hr = pShellLink->GetPath(*lpszURL, MAX_PATH - 1, (WIN32_FIND_DATA*)&wfd, SLGP_UNCPRIORITY);
- }
- }
- pPersistFile->Release();
- }
- pShellLink->Release();
- }
- return hr;
- }
- //
- // This method converts a STRRET structure to a LPTSTR
- //
- #ifdef UNICODE
- STDMETHODIMP CShellPidl::StrRetToStr(STRRET StrRet, LPTSTR* str, LPITEMIDLIST pidl)
- {
- HRESULT hr = S_OK;
- int cch;
- LPSTR strOffset;
- *str = NULL; // Assume failure
- switch (StrRet.uType)
- {
- case STRRET_WSTR:
- cch = wcslen(StrRet.pOleStr) + 1; // NULL terminator
- *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
- if (*str != NULL)
- lstrcpyn(*str, StrRet.pOleStr, cch);
- else
- hr = E_FAIL;
- break;
- case STRRET_OFFSET:
- strOffset = (((char *) pidl) + StrRet.uOffset);
- cch = MultiByteToWideChar(CP_OEMCP, 0, strOffset, -1, NULL, 0);
- *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
- if (*str != NULL)
- MultiByteToWideChar(CP_OEMCP, 0, strOffset, -1, *str, cch);
- else
- hr = E_FAIL;
- break;
- case STRRET_CSTR:
- cch = MultiByteToWideChar(CP_OEMCP, 0, StrRet.cStr, -1, NULL, 0);
- *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
- if (*str != NULL)
- MultiByteToWideChar(CP_OEMCP, 0, StrRet.cStr, -1, *str, cch);
- else
- hr = E_FAIL;
- break;
- }
-
- return hr;
- }
- #else // UNICODE not defined
- STDMETHODIMP CShellPidl::StrRetToStr(STRRET StrRet, LPTSTR* str, LPITEMIDLIST pidl)
- {
- HRESULT hr = S_OK;
- int cch;
- LPSTR strOffset;
- *str = NULL; // Assume failure
- switch (StrRet.uType)
- {
- case STRRET_WSTR:
- cch = WideCharToMultiByte(CP_ACP, 0, StrRet.pOleStr, -1, NULL, 0, NULL, NULL);
- *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
- if (*str != NULL)
- WideCharToMultiByte(CP_ACP, 0, StrRet.pOleStr, -1, *str, cch, NULL, NULL);
- else
- hr = E_FAIL;
- break;
- case STRRET_OFFSET:
- strOffset = (((char *) pidl) + StrRet.uOffset);
- cch = strlen(strOffset) + 1; // NULL terminator
- *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
- if (*str != NULL)
- strcpy(*str, strOffset);
- else
- hr = E_FAIL;
- break;
- case STRRET_CSTR:
- cch = strlen(StrRet.cStr) + 1; // NULL terminator
- *str = (LPTSTR)m_pMalloc->Alloc(cch * sizeof(TCHAR));
- if (*str != NULL)
- strcpy(*str, StrRet.cStr);
- else
- hr = E_FAIL;
- break;
- }
- return hr;
- }
- #endif