// only one full qualified PIDL has been passed void CShellContextMenu::SetObjects(LPITEMIDLIST pidl) { // free all allocated datas if (m_psfFolder && bDelete) m_psfFolder->Release (); m_psfFolder = NULL; FreePIDLArray (m_pidlArray); m_pidlArray = NULL; // full qualified PIDL is passed so we need // its parent IShellFolder interface and its relative PIDL to that LPITEMIDLIST pidlItem = NULL; SHBindToParent ((LPCITEMIDLIST) pidl, IID_IShellFolder, (void **) &m_psfFolder, (LPCITEMIDLIST *) &pidlItem); m_pidlArray = (LPITEMIDLIST *) malloc (sizeof (LPITEMIDLIST)); // allocate ony for one elemnt m_pidlArray[0] = CopyPIDL (pidlItem); // now free pidlItem via IMalloc interface (but not m_psfFolder, that we need later LPMALLOC lpMalloc = NULL; SHGetMalloc (&lpMalloc); lpMalloc->Free (pidlItem); lpMalloc->Release(); nItems = 1; bDelete = TRUE; // indicates that m_psfFolder should be deleted by CShellContextMenu }
void CShellContextMenu::SetObjects(const QStringList &strList) { // free all allocated datas if (m_psfFolder && bDelete) m_psfFolder->Release (); m_psfFolder = NULL; FreePIDLArray (m_pidlArray); m_pidlArray = NULL; // get IShellFolder interface of Desktop (root of shell namespace) IShellFolder * psfDesktop = NULL; SHGetDesktopFolder (&psfDesktop); // needed to obtain full qualified pidl // ParseDisplayName creates a PIDL from a file system path relative to the IShellFolder interface // but since we use the Desktop as our interface and the Desktop is the namespace root // that means that it's a fully qualified PIDL, which is what we need LPITEMIDLIST pidl = NULL; psfDesktop->ParseDisplayName (NULL, 0, (LPOLESTR)strList[0].utf16(), NULL, &pidl, NULL); // now we need the parent IShellFolder interface of pidl, and the relative PIDL to that interface LPITEMIDLIST pidlItem = NULL; // relative pidl SHBindToParentEx (pidl, IID_IShellFolder, (void **) &m_psfFolder, NULL); free (pidlItem); // get interface to IMalloc (need to free the PIDLs allocated by the shell functions) LPMALLOC lpMalloc = NULL; SHGetMalloc (&lpMalloc); lpMalloc->Free (pidl); // now we have the IShellFolder interface to the parent folder specified in the first element in strArray // since we assume that all objects are in the same folder (as it's stated in the MSDN) // we now have the IShellFolder interface to every objects parent folder IShellFolder * psfFolder = NULL; nItems = strList.size (); for (int i = 0; i < nItems; i++) { pidl=0; psfDesktop->ParseDisplayName (NULL, 0, (LPOLESTR)strList[i].utf16(), NULL, &pidl, NULL); if (pidl) { m_pidlArray = (LPITEMIDLIST *) realloc (m_pidlArray, (i + 1) * sizeof (LPITEMIDLIST)); // get relative pidl via SHBindToParent SHBindToParentEx (pidl, IID_IShellFolder, (void **) &psfFolder, (LPCITEMIDLIST *) &pidlItem); m_pidlArray[i] = CopyPIDL (pidlItem); // copy relative pidl to pidlArray free (pidlItem); lpMalloc->Free (pidl); // free pidl allocated by ParseDisplayName psfFolder->Release (); } } lpMalloc->Release (); psfDesktop->Release (); bDelete = TRUE; // indicates that m_psfFolder should be deleted by CShellContextMenu }
CShellContextMenu::~CShellContextMenu() { // free all allocated datas if (m_psfFolder && bDelete) m_psfFolder->Release (); m_psfFolder = NULL; FreePIDLArray (m_pidlArray); m_pidlArray = NULL; if (m_Menu) delete m_Menu; }
CShellContextMenu::~CShellContextMenu() { // free all allocated datas if (m_psfFolder && m_bDelete) m_psfFolder->Release(); m_psfFolder = NULL; FreePIDLArray(m_pidlArray); if (m_hMenu) DestroyMenu(m_hMenu); }
// IShellFolder interface with a relative pidl has been passed void CShellContextMenu::SetObjects(IShellFolder *psfFolder, LPITEMIDLIST pidlItem) { // free all allocated datas if (m_psfFolder && bDelete) m_psfFolder->Release (); m_psfFolder = NULL; FreePIDLArray (m_pidlArray); m_pidlArray = NULL; m_psfFolder = psfFolder; m_pidlArray = (LPITEMIDLIST *) malloc (sizeof (LPITEMIDLIST)); m_pidlArray[0] = CopyPIDL (pidlItem); nItems = 1; bDelete = FALSE; // indicates wheter m_psfFolder should be deleted by CShellContextMenu }
void CShellContextMenu::SetObjects(IShellFolder * psfFolder, LPITEMIDLIST *pidlArray, int nItemCount) { // free all allocated datas if (m_psfFolder && bDelete) m_psfFolder->Release (); m_psfFolder = NULL; FreePIDLArray (m_pidlArray); m_pidlArray = NULL; m_psfFolder = psfFolder; m_pidlArray = (LPITEMIDLIST *) malloc (nItemCount * sizeof (LPITEMIDLIST)); for (int i = 0; i < nItemCount; i++) m_pidlArray[i] = CopyPIDL (pidlArray[i]); nItems = nItemCount; bDelete = FALSE; // indicates wheter m_psfFolder should be deleted by CShellContextMenu }
void CShellContextMenu::SetObjects(CString &strArray) { // free all allocated datas if (m_psfFolder && bDelete) m_psfFolder->Release (); m_psfFolder = NULL; FreePIDLArray (m_pidlArray); m_pidlArray = NULL; // get IShellFolder interface of Desktop (root of shell namespace) IShellFolder * psfDesktop = NULL; SHGetDesktopFolder (&psfDesktop); // needed to obtain full qualified pidl // ParseDisplayName creates a PIDL from a file system path relative to the IShellFolder interface // but since we use the Desktop as our interface and the Desktop is the namespace root // that means that it's a fully qualified PIDL, which is what we need LPITEMIDLIST pidl = NULL; #ifndef _UNICODE OLECHAR * olePath = (OLECHAR *) calloc (strArray.GetLength () + 1, sizeof (OLECHAR)); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)strArray, -1, olePath, strArray.GetLength () + 1); psfDesktop->ParseDisplayName (NULL, 0, olePath, NULL, &pidl, NULL); free (olePath); #else psfDesktop->ParseDisplayName (NULL, 0, strArray.GetBuffer (0), NULL, &pidl, NULL); #endif // now we need the parent IShellFolder interface of pidl, and the relative PIDL to that interface LPITEMIDLIST pidlItem = NULL; // relative pidl SHBindToParentEx (pidl, IID_IShellFolder, (void **) &m_psfFolder, NULL); free (pidlItem); // get interface to IMalloc (need to free the PIDLs allocated by the shell functions) LPMALLOC lpMalloc = NULL; SHGetMalloc (&lpMalloc); lpMalloc->Free (pidl); // now we have the IShellFolder interface to the parent folder specified in the first element in strArray // since we assume that all objects are in the same folder (as it's stated in the MSDN) // we now have the IShellFolder interface to every objects parent folder IShellFolder * psfFolder = NULL; nItems = 1; for (int i = 0; i < nItems; i++) { #ifndef _UNICODE olePath = (OLECHAR *) calloc (strArray.GetLength () + 1, sizeof (OLECHAR)); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (strArray), -1, olePath, strArray.GetLength () + 1); psfDesktop->ParseDisplayName (NULL, 0, olePath, NULL, &pidl, NULL); free (olePath); #else psfDesktop->ParseDisplayName (NULL, 0, strArray.GetBuffer (0), NULL, &pidl, NULL); #endif m_pidlArray = (LPITEMIDLIST *) realloc (m_pidlArray, (i + 1) * sizeof (LPITEMIDLIST)); // get relative pidl via SHBindToParent SHBindToParentEx (pidl, IID_IShellFolder, (void **) &psfFolder, (LPCITEMIDLIST *) &pidlItem); m_pidlArray[i] = CopyPIDL (pidlItem); // copy relative pidl to pidlArray free (pidlItem); lpMalloc->Free (pidl); // free pidl allocated by ParseDisplayName psfFolder->Release (); } lpMalloc->Release (); psfDesktop->Release (); bDelete = TRUE; // indicates that m_psfFolder should be deleted by CShellContextMenu }
void CShellContextMenu::SetPath(const tstring& strPath) { // free all allocated datas if(m_psfFolder && bDelete) m_psfFolder->Release(); m_psfFolder = NULL; FreePIDLArray(m_pidlArray); m_pidlArray = NULL; // get IShellFolder interface of Desktop(root of shell namespace) IShellFolder* psfDesktop = NULL; SHGetDesktopFolder(&psfDesktop); // ParseDisplayName creates a PIDL from a file system path relative to the IShellFolder interface // but since we use the Desktop as our interface and the Desktop is the namespace root // that means that it's a fully qualified PIDL, which is what we need LPITEMIDLIST pidl = NULL; psfDesktop->ParseDisplayName(NULL, 0, (LPOLESTR)const_cast<TCHAR*>(strPath.c_str()), NULL, &pidl, NULL); // now we need the parent IShellFolder interface of pidl, and the relative PIDL to that interface typedef HRESULT (CALLBACK* LPFUNC)(LPCITEMIDLIST pidl, REFIID riid, void **ppv, LPCITEMIDLIST *ppidlLast); LPFUNC MySHBindToParent = (LPFUNC)GetProcAddress(LoadLibrary(_T("shell32")), "SHBindToParent"); if(MySHBindToParent == NULL) return; MySHBindToParent(pidl, IID_IShellFolder, (LPVOID*)&m_psfFolder, NULL); // get interface to IMalloc (need to free the PIDLs allocated by the shell functions) LPMALLOC lpMalloc = NULL; SHGetMalloc(&lpMalloc); lpMalloc->Free(pidl); // now we need the relative pidl IShellFolder* psfFolder = NULL; HRESULT res = psfDesktop->ParseDisplayName (NULL, 0, (LPOLESTR)const_cast<TCHAR*>(strPath.c_str()), NULL, &pidl, NULL); if(res != S_OK) return; LPITEMIDLIST pidlItem = NULL; SHBindToParent(pidl, IID_IShellFolder, (LPVOID*)&psfFolder, (LPCITEMIDLIST*)&pidlItem); // copy pidlItem to m_pidlArray m_pidlArray = (LPITEMIDLIST *) realloc(m_pidlArray, sizeof (LPITEMIDLIST)); int nSize = 0; LPITEMIDLIST pidlTemp = pidlItem; if(pidlTemp) //[+]PPA http://iceberg.leschat.net/forum/index.php?s=&showtopic=265&view=findpost&p=26331 while(pidlTemp->mkid.cb) { nSize += pidlTemp->mkid.cb; pidlTemp = (LPITEMIDLIST) (((LPBYTE) pidlTemp) + pidlTemp->mkid.cb); } LPITEMIDLIST pidlRet = (LPITEMIDLIST) calloc(nSize + sizeof (USHORT), sizeof (BYTE)); CopyMemory(pidlRet, pidlItem, nSize); m_pidlArray[0] = pidlRet; //free(pidlItem); lpMalloc->Free(pidl); lpMalloc->Release(); if(psfFolder) //[+]PPA http://iceberg.leschat.net/forum/index.php?showtopic=265&st=2320&# psfFolder->Release(); psfDesktop->Release(); bDelete = true; // indicates that m_psfFolder should be deleted by CShellContextMenu }