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
}
HRESULT CContextMenuHelper::SHGetContextMenu(std::vector<LPCTSTR> files) {
    HRESULT hr;
    IMalloc *pm = NULL;
    IShellFolder *pDesktop = NULL;
    IShellFolder *psf = NULL;
    LPITEMIDLIST pidl = NULL;
    WCHAR fwname[MAX_PATH + 1];

    if (SUCCEEDED(hr = SHGetMalloc(&pm))) {
        if (SUCCEEDED(hr = SHGetDesktopFolder(&pDesktop))) {
            std::vector<LPITEMIDLIST> pidls;
            IShellFolder* psfFolder = NULL;
            for (UINT i = 0; SUCCEEDED(hr) && i < files.size(); i++) {
                LPCTSTR lpszFilePath = files[i];

                ULONG cch;
                ULONG attrs;

                // Convert to Unicode
                memset(fwname, L'\0', (MAX_PATH + 1) * sizeof(WCHAR));
                MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFilePath, -1, fwname, MAX_PATH);
                if (SUCCEEDED(hr = pDesktop->ParseDisplayName(m_hWnd, NULL, fwname, &cch, &pidl, &attrs))) {
                    LPITEMIDLIST pidlItem = NULL;
                    if (SUCCEEDED(hr = SHBindToParentEx((LPCITEMIDLIST)pidl, IID_IShellFolder, (void **)&psf, (LPCITEMIDLIST *) &pidlItem, pDesktop, pm))) {
                        pidls.push_back(CopyPIDL(pidlItem, pm));
                        pm->Free(pidlItem);
                        if (psfFolder == NULL) {
                            // Remember first folder and we wiil show menu for this one
                            // All other folder will be ignored
                            psfFolder = psf;
                        } else {
                            psf->Release();
                        }
                    }
                    pm->Free(pidl);
                }
            }
            if (SUCCEEDED(hr) && psfFolder != NULL) {
                hr = psfFolder->GetUIObjectOf(m_hWnd, pidls.size(), const_cast<LPCITEMIDLIST*>(pidls.begin()), IID_IContextMenu, NULL, (void**)&m_lpcm);
                psfFolder->Release();
            }
            FreeItemIDList(pidls, pm);
            pDesktop->Release();
        }
        pm->Release();
    }

    return hr;
}
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
}