std::wstring OsShell::toolTip(std::wstring itemPath) { ComInitializer comInitializer; std::replace(itemPath.begin(), itemPath.end(), '/', '\\'); std::wstring tipString; ITEMIDLIST * id = 0; HRESULT result = SHParseDisplayName(itemPath.c_str(), 0, &id, 0, 0); if (!SUCCEEDED(result) || !id) return tipString; CItemIdListReleaser idReleaser (id); LPCITEMIDLIST child = 0; IShellFolder * ifolder = 0; result = SHBindToParent(id, IID_IShellFolder, (void**)&ifolder, &child); if (!SUCCEEDED(result) || !child) return tipString; IQueryInfo* iQueryInfo = 0; if (SUCCEEDED(ifolder->GetUIObjectOf(NULL, 1, &child, IID_IQueryInfo, 0, (void**)&iQueryInfo)) && iQueryInfo) { LPWSTR lpszTip = 0; CComInterfaceReleaser releaser (iQueryInfo); if (SUCCEEDED(iQueryInfo->GetInfoTip(0, &lpszTip)) && lpszTip) { tipString = lpszTip; CoTaskMemFree(lpszTip); } } std::replace(tipString.begin(), tipString.end(), '\r', '\n'); return tipString; }
HRESULT GetDisplayName(LPCITEMIDLIST pidlDirectory,TCHAR *szDisplayName,UINT cchMax,DWORD uFlags) { if(pidlDirectory == NULL || szDisplayName == NULL) { return E_FAIL; } IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlRelative = NULL; STRRET str; HRESULT hr; hr = SHBindToParent(pidlDirectory, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { hr = pShellFolder->GetDisplayNameOf(pidlRelative,uFlags,&str); if(SUCCEEDED(hr)) { hr = StrRetToBuf(&str,pidlDirectory,szDisplayName,cchMax); } pShellFolder->Release(); } return hr; }
// 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 }
static HRESULT pidl_to_shellfolder(LPITEMIDLIST pidl, LPWSTR *displayname, IShellFolder **out_folder) { IShellFolder* parent_folder=NULL; LPCITEMIDLIST relative_pidl=NULL; STRRET strret; HRESULT hr; hr = SHBindToParent(pidl, &IID_IShellFolder, (void**)&parent_folder, &relative_pidl); if (displayname) { if (SUCCEEDED(hr)) hr = IShellFolder_GetDisplayNameOf(parent_folder, relative_pidl, SHGDN_INFOLDER, &strret); if (SUCCEEDED(hr)) hr = StrRetToStrW(&strret, NULL, displayname); } if (SUCCEEDED(hr)) hr = IShellFolder_BindToObject(parent_folder, relative_pidl, NULL, &IID_IShellFolder, (void**)out_folder); if (parent_folder) IShellFolder_Release(parent_folder); return hr; }
static void update_shell_folder_listview(HWND dialog) { int i; LVITEMW item; LONG lSelected = SendDlgItemMessageW(dialog, IDC_LIST_SFPATHS, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED,0)); SendDlgItemMessageW(dialog, IDC_LIST_SFPATHS, LVM_DELETEALLITEMS, 0, 0); for (i=0; i<NUM_ELEMS(asfiInfo); i++) { WCHAR buffer[MAX_PATH]; HRESULT hr; LPITEMIDLIST pidlCurrent; /* Some acrobatic to get the localized name of the shell folder */ hr = SHGetFolderLocation(dialog, asfiInfo[i].nFolder, NULL, 0, &pidlCurrent); if (SUCCEEDED(hr)) { LPSHELLFOLDER psfParent; LPCITEMIDLIST pidlLast; hr = SHBindToParent(pidlCurrent, &IID_IShellFolder, (LPVOID*)&psfParent, &pidlLast); if (SUCCEEDED(hr)) { STRRET strRet; hr = IShellFolder_GetDisplayNameOf(psfParent, pidlLast, SHGDN_FORADDRESSBAR, &strRet); if (SUCCEEDED(hr)) { hr = StrRetToBufW(&strRet, pidlLast, buffer, MAX_PATH); } IShellFolder_Release(psfParent); } ILFree(pidlCurrent); } /* If there's a dangling symlink for the current shell folder, SHGetFolderLocation * will fail above. We fall back to the (non-verified) path of the shell folder. */ if (FAILED(hr)) { hr = SHGetFolderPathW(dialog, asfiInfo[i].nFolder|CSIDL_FLAG_DONT_VERIFY, NULL, SHGFP_TYPE_CURRENT, buffer); } item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = i; item.iSubItem = 0; item.pszText = buffer; item.lParam = (LPARAM)&asfiInfo[i]; SendDlgItemMessageW(dialog, IDC_LIST_SFPATHS, LVM_INSERTITEMW, 0, (LPARAM)&item); item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 1; item.pszText = strdupU2W(asfiInfo[i].szLinkTarget); SendDlgItemMessageW(dialog, IDC_LIST_SFPATHS, LVM_SETITEMW, 0, (LPARAM)&item); HeapFree(GetProcessHeap(), 0, item.pszText); } /* Ensure that the previously selected item is selected again. */ if (lSelected >= 0) { item.mask = LVIF_STATE; item.state = LVIS_SELECTED; item.stateMask = LVIS_SELECTED; SendDlgItemMessageW(dialog, IDC_LIST_SFPATHS, LVM_SETITEMSTATE, lSelected, (LPARAM)&item); } }
void GetExplorerWindows(std::vector<PairHwndPath>& windows, BOOL needPaths) { IShellWindows *psw; if(SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_IShellWindows, (void**)&psw))) { VARIANT v; V_VT(&v) = VT_I4; IDispatch* pdisp; for(V_I4(&v) = 0; psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) { IWebBrowserApp *pwba; if(SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) { PairHwndPath pair; if(SUCCEEDED(pwba->get_HWND((LONG_PTR*)&pair.hwnd))) { IServiceProvider *psp; if(needPaths && SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) { IShellBrowser *psb; if(SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void**)&psb))) { IShellView *psv; if(SUCCEEDED(psb->QueryActiveShellView(&psv))) { IFolderView *pfv; if(SUCCEEDED(psv->QueryInterface(IID_IFolderView, (void**)&pfv))) { IPersistFolder2 *ppf2; if(SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2, (void**)&ppf2))) { LPITEMIDLIST pidlFolder; if(SUCCEEDED(ppf2->GetCurFolder(&pidlFolder))) { if(!SHGetPathFromIDList(pidlFolder, pair.path)) { IShellFolder* psf; LPCITEMIDLIST pidlLast; if(SUCCEEDED(SHBindToParent(pidlFolder, IID_IShellFolder, (void**)&psf, &pidlLast))) { STRRET strret; if(SUCCEEDED(psf->GetDisplayNameOf(pidlLast, 0x8000, &strret))) { StrRetToBuf(&strret, pidlLast, pair.path, MAX_PATH); } else { pair.path[0] = 0; } psf->Release(); } } CoTaskMemFree(pidlFolder); } ppf2->Release(); } pfv->Release(); } psv->Release(); } psb->Release(); } psp->Release(); } windows.push_back(pair); } pwba->Release(); } pdisp->Release(); } psw->Release(); } }
/* TODO: These groups have changed as of Windows Vista. */ void CShellBrowser::DetermineItemTotalSizeGroup(int iItemInternal,TCHAR *szGroupHeader,int cchMax) const { IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlComplete = NULL; LPITEMIDLIST pidlDirectory = NULL; LPITEMIDLIST pidlRelative = NULL; TCHAR *SizeGroups[] = {_T("Unspecified"),_T("Small"),_T("Medium"),_T("Huge"),_T("Gigantic")}; TCHAR szItem[MAX_PATH]; STRRET str; ULARGE_INTEGER nTotalBytes; ULARGE_INTEGER nFreeBytes; BOOL bRoot; BOOL bRes = FALSE; ULARGE_INTEGER TotalSizeGroupLimits[6]; int nGroups = 5; int iSize = 0; int i; TotalSizeGroupLimits[0].QuadPart = 0; TotalSizeGroupLimits[1].QuadPart = 0; TotalSizeGroupLimits[2].QuadPart = GBYTE; TotalSizeGroupLimits[3].QuadPart = 20 * TotalSizeGroupLimits[2].QuadPart; TotalSizeGroupLimits[4].QuadPart = 100 * TotalSizeGroupLimits[2].QuadPart; GetIdlFromParsingName(m_CurDir,&pidlDirectory); pidlComplete = ILCombine(pidlDirectory,m_pExtraItemInfo[iItemInternal].pridl); SHBindToParent(pidlComplete, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *) &pidlRelative); pShellFolder->GetDisplayNameOf(pidlRelative,SHGDN_FORPARSING,&str); StrRetToBuf(&str,pidlRelative,szItem,SIZEOF_ARRAY(szItem)); bRoot = PathIsRoot(szItem); if(bRoot) { bRes = GetDiskFreeSpaceEx(szItem,NULL,&nTotalBytes,&nFreeBytes); CoTaskMemFree(pidlDirectory); CoTaskMemFree(pidlComplete); pShellFolder->Release(); i = nGroups - 1; while(nTotalBytes.QuadPart < TotalSizeGroupLimits[i].QuadPart && i > 0) i--; iSize = i; } if(!bRoot || !bRes) { iSize = 0; } StringCchCopy(szGroupHeader,cchMax,SizeGroups[iSize]); }
/* TODO: Need to sort based on percentage free. */ void CShellBrowser::DetermineItemFreeSpaceGroup(int iItemInternal,TCHAR *szGroupHeader,int cchMax) const { std::list<TypeGroup_t>::iterator itr; LPITEMIDLIST pidlComplete = NULL; LPITEMIDLIST pidlDirectory = NULL; TCHAR szFreeSpace[MAX_PATH]; IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlRelative = NULL; STRRET str; TCHAR szItem[MAX_PATH]; ULARGE_INTEGER nTotalBytes; ULARGE_INTEGER nFreeBytes; BOOL bRoot; BOOL bRes = FALSE; GetIdlFromParsingName(m_CurDir,&pidlDirectory); pidlComplete = ILCombine(pidlDirectory,m_pExtraItemInfo[iItemInternal].pridl); SHBindToParent(pidlComplete, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); pShellFolder->GetDisplayNameOf(pidlRelative,SHGDN_FORPARSING,&str); StrRetToBuf(&str,pidlRelative,szItem,SIZEOF_ARRAY(szItem)); CoTaskMemFree(pidlDirectory); CoTaskMemFree(pidlComplete); pShellFolder->Release(); bRoot = PathIsRoot(szItem); if(bRoot) { bRes = GetDiskFreeSpaceEx(szItem,NULL,&nTotalBytes,&nFreeBytes); LARGE_INTEGER lDiv1; LARGE_INTEGER lDiv2; lDiv1.QuadPart = 100; lDiv2.QuadPart = 10; /* Divide by 10 to remove the one's digit, then multiply by 10 so that only the ten's digit rmains. */ StringCchPrintf(szFreeSpace,SIZEOF_ARRAY(szFreeSpace), _T("%I64d%% free"),(((nFreeBytes.QuadPart * lDiv1.QuadPart) / nTotalBytes.QuadPart) / lDiv2.QuadPart) * lDiv2.QuadPart); } if(!bRoot || !bRes) { StringCchCopy(szFreeSpace,SIZEOF_ARRAY(szFreeSpace),_T("Unspecified")); } StringCchCopy(szGroupHeader,cchMax,szFreeSpace); }
bool prepareContextMenuForObjects(std::vector<std::wstring> objects, void * parentWindow, HMENU& hmenu, IContextMenu*& imenu) { ComInitializer comInitializer; if (objects.empty()) return false; std::vector<ITEMIDLIST*> ids; std::vector<LPCITEMIDLIST> relativeIds; IShellFolder * ifolder = 0; for (size_t i = 0; i < objects.size(); ++i) { std::replace(objects[i].begin(), objects[i].end(), '/', '\\'); ids.push_back(0); HRESULT result = SHParseDisplayName(objects[i].c_str(), 0, &ids.back(), 0, 0); if (!SUCCEEDED(result) || !ids.back()) { ids.pop_back(); continue; } relativeIds.push_back(0); result = SHBindToParent(ids.back(), IID_IShellFolder, (void**)&ifolder, &relativeIds.back()); if (!SUCCEEDED(result) || !relativeIds.back()) relativeIds.pop_back(); else if (i < objects.size() - 1 && ifolder) { ifolder->Release(); ifolder = nullptr; } } CItemIdArrayReleaser arrayReleaser(ids); assert_r(parentWindow); assert_and_return_message_r(ifolder, "Error getting ifolder", false); assert_and_return_message_r(!relativeIds.empty(), "RelativeIds is empty", false); imenu = 0; HRESULT result = ifolder->GetUIObjectOf((HWND)parentWindow, (UINT)relativeIds.size(), (const ITEMIDLIST **)relativeIds.data(), IID_IContextMenu, 0, (void**)&imenu); if (!SUCCEEDED(result) || !imenu) return false; hmenu = CreatePopupMenu(); if (!hmenu) return false; return (SUCCEEDED(imenu->QueryContextMenu(hmenu, 0, 1, 0x7FFF, CMF_NORMAL))); }
/************************************************************************** * ISF_NetworkPlaces_fnGetAttributesOf */ static HRESULT WINAPI ISF_NetworkPlaces_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) { IGenericSFImpl *This = impl_from_IShellFolder2(iface); HRESULT hr = S_OK; TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); if (!rgfInOut) return E_INVALIDARG; if (cidl && !apidl) return E_INVALIDARG; if (*rgfInOut == 0) *rgfInOut = ~0; if (cidl == 0) { IShellFolder *psfParent = NULL; LPCITEMIDLIST rpidl = NULL; hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder, (void**)&psfParent, &rpidl); if(SUCCEEDED(hr)) { SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut); IShellFolder_Release(psfParent); } } else { while (cidl > 0 && *apidl) { pdump (*apidl); SHELL32_GetItemAttributes ((IShellFolder *)&This->IShellFolder2_iface, *apidl, rgfInOut); apidl++; cidl--; } } /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */ *rgfInOut &= ~SFGAO_VALIDATE; TRACE ("-- result=0x%08x\n", *rgfInOut); return hr; }
void CShellBrowser::DetermineItemFileSystemGroup(int iItemInternal,TCHAR *szGroupHeader,int cchMax) const { LPITEMIDLIST pidlComplete = NULL; IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlRelative = NULL; TCHAR szFileSystemName[MAX_PATH]; TCHAR szItem[MAX_PATH]; STRRET str; BOOL bRoot; BOOL bRes; pidlComplete = ILCombine(m_pidlDirectory,m_pExtraItemInfo[iItemInternal].pridl); SHBindToParent(pidlComplete, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); pShellFolder->GetDisplayNameOf(pidlRelative,SHGDN_FORPARSING,&str); StrRetToBuf(&str,pidlRelative,szItem,SIZEOF_ARRAY(szItem)); bRoot = PathIsRoot(szItem); if(bRoot) { bRes = GetVolumeInformation(szItem,NULL,0,NULL,NULL,NULL,szFileSystemName, SIZEOF_ARRAY(szFileSystemName)); if(!bRes || *szFileSystemName == '\0') { /* TODO: Move into string table. */ StringCchCopy(szFileSystemName,SIZEOF_ARRAY(szFileSystemName),_T("Unspecified")); } } else { /* TODO: Move into string table. */ StringCchCopy(szFileSystemName,SIZEOF_ARRAY(szFileSystemName),_T("Unspecified")); } StringCchCopy(szGroupHeader,cchMax,szFileSystemName); pShellFolder->Release(); CoTaskMemFree(pidlComplete); }
bool OsShell::recycleBinContextMenu(int xPos, int yPos, void *parentWindow) { ComInitializer comInitializer; PIDLIST_ABSOLUTE idlist = 0; if (!SUCCEEDED(SHGetFolderLocation(0, CSIDL_BITBUCKET, 0, 0, &idlist))) return false; IShellFolder * iFolder = 0; LPCITEMIDLIST list; HRESULT result = SHBindToParent(idlist, IID_IShellFolder, (void**)&iFolder, &list); if (!SUCCEEDED(result) || !list || !iFolder) return false; IContextMenu * imenu = 0; result = iFolder->GetUIObjectOf((HWND)parentWindow, 1u, &list, IID_IContextMenu, 0, (void**)&imenu); CoTaskMemFree(idlist); if (!SUCCEEDED(result) || !imenu) return false; CComInterfaceReleaser menuReleaser(imenu); HMENU hMenu = CreatePopupMenu(); if (!hMenu) return false; if (SUCCEEDED(imenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_NORMAL))) { int iCmd = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, xPos, yPos, (HWND)parentWindow, NULL); if (iCmd > 0) { CMINVOKECOMMANDINFOEX info = { 0 }; info.cbSize = sizeof(info); info.fMask = CMIC_MASK_UNICODE; info.hwnd = (HWND)parentWindow; info.lpVerb = MAKEINTRESOURCEA(iCmd - 1); info.lpVerbW = MAKEINTRESOURCEW(iCmd - 1); info.nShow = SW_SHOWNORMAL; imenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); } } DestroyMenu(hMenu); return true; }
/************************************************************************** * CFontsFolder::GetAttributesOf */ HRESULT WINAPI CFontsFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) { HRESULT hr = S_OK; TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); if (!rgfInOut) return E_INVALIDARG; if (cidl && !apidl) return E_INVALIDARG; if (*rgfInOut == 0) *rgfInOut = ~0; if (cidl == 0) { CComPtr<IShellFolder> psfParent; LPCITEMIDLIST rpidl = NULL; hr = SHBindToParent(pidlRoot, IID_PPV_ARG(IShellFolder, &psfParent), (LPCITEMIDLIST *)&rpidl); if (SUCCEEDED(hr)) SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut); } else { while (cidl > 0 && *apidl) { pdump (*apidl); SHELL32_GetItemAttributes (this, *apidl, rgfInOut); apidl++; cidl--; } } /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */ *rgfInOut &= ~SFGAO_VALIDATE; TRACE ("-- result=0x%08x\n", *rgfInOut); return hr; }
/* adapted from http://blogs.msdn.com/oldnewthing/archive/2004/09/20/231739.aspx */ IDataObject* GetDataObjectForFile(WCHAR* filePath, HWND hwnd) { ScopedComPtr<IShellFolder> pDesktopFolder; HRESULT hr = SHGetDesktopFolder(&pDesktopFolder); if (FAILED(hr)) return NULL; IDataObject* pDataObject = NULL; ScopedMem<WCHAR> lpWPath(str::Dup(filePath)); LPITEMIDLIST pidl; hr = pDesktopFolder->ParseDisplayName(NULL, NULL, lpWPath, NULL, &pidl, NULL); if (SUCCEEDED(hr)) { ScopedComPtr<IShellFolder> pShellFolder; LPCITEMIDLIST pidlChild; hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&pShellFolder, &pidlChild); if (SUCCEEDED(hr)) pShellFolder->GetUIObjectOf(hwnd, 1, &pidlChild, IID_IDataObject, NULL, (void **)&pDataObject); CoTaskMemFree(pidl); } return pDataObject; }
void GetExplorerWindows(std::vector<PairHwndPath>& windows, BOOL needPaths) { CComPtr<IShellWindows> psw; if(!psw.Create(CLSID_ShellWindows, CLSCTX_ALL)) return; VARIANT v; V_VT(&v) = VT_I4; CComPtr<IDispatch> pdisp; for(V_I4(&v) = 0; psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) { CComPtr<IWebBrowserApp> pwba; if(!pwba.QueryFrom(pdisp)) continue; PairHwndPath pair; if(!SUCCEEDED(pwba->get_HWND((LONG_PTR*)&pair.hwnd))) continue; pair.path[0] = 0; CComPtr<IServiceProvider> psp; CComPtr<IShellBrowser> psb; CComPtr<IShellView> psv; CComPtr<IFolderView> pfv; CComPtr<IPersistFolder2> ppf2; CComPtr<IShellFolder> psf; LPITEMIDLIST pidlFolder = NULL; LPCITEMIDLIST pidlLast = NULL; STRRET strret; if(needPaths && psp.QueryFrom(pwba) && SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void**)&psb)) && SUCCEEDED(psb->QueryActiveShellView(&psv)) && pfv.QueryFrom(psv) && SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2, (void**)&ppf2)) && SUCCEEDED(ppf2->GetCurFolder(&pidlFolder)) && !SHGetPathFromIDList(pidlFolder, pair.path) && SUCCEEDED(SHBindToParent(pidlFolder, IID_IShellFolder, (void**)&psf, &pidlLast)) && SUCCEEDED(psf->GetDisplayNameOf(pidlLast, 0x8000, &strret))) { StrRetToBuf(&strret, pidlLast, pair.path, MAX_PATH); } if(pidlFolder != NULL) CoTaskMemFree(pidlFolder); windows.push_back(pair); } }
BOOL GetThumbNail(HDC hDC, LPCTSTR lpszFilePath,LPCTSTR lpszSavepath) { bool bFileExit = PathFileExists(lpszSavepath); if(bFileExit) return TRUE; IShellFolder * pShellFolder = NULL; if( SHGetDesktopFolder( &pShellFolder) == S_OK ) { LPITEMIDLIST pidl = NULL; HRESULT hRes = pShellFolder->ParseDisplayName( NULL, NULL, (LPTSTR)(LPCTSTR)lpszFilePath, NULL, &pidl, NULL); if( hRes == S_OK ) { LPCITEMIDLIST pidlLast = NULL; IShellFolder * pParentFolder = NULL; HRESULT hRes = SHBindToParent( pidl, IID_IShellFolder, (void**)&pParentFolder, &pidlLast ); if( hRes == S_OK ) { HBITMAP hBmpImage = ExtractThumb(pParentFolder, pidlLast ); if( hBmpImage ) { SaveImage(hDC,hBmpImage,lpszSavepath); //HBITMAP hbmpOld = hBmpImage; //if( hbmpOld ) // DeleteObject(hbmpOld); } else return false; pParentFolder->Release(); } } pShellFolder->Release(); return true; } return false; }
HRESULT GetItemAttributes(LPCITEMIDLIST pidl,SFGAOF *pItemAttributes) { if(pidl == NULL || pItemAttributes == NULL) { return E_FAIL; } IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlRelative = NULL; HRESULT hr; hr = SHBindToParent(pidl, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { hr = pShellFolder->GetAttributesOf(1,(LPCITEMIDLIST *)&pidlRelative,pItemAttributes); pShellFolder->Release(); } return hr; }
STDMETHODIMP CShareOverlay::IsMemberOf( LPCWSTR pwszPath, DWORD dwAttrib ) { // must use IShellFolder::GetAttributesOf to get the correct attributes instead of SHGetFileInfo or IShellFolder::ParseDisplayName // SHGetFileInfo gives the wrong result for some system folders like %userprofile%\Desktop (on Windows7 and Vista) // IShellFolder::ParseDisplayName returns the wrong attributes for the contents of the Recycle Bin (on Windows7 only) PIDLIST_ABSOLUTE pidl=NULL; HRESULT res=S_FALSE; if (pwszPath && m_pDesktop) { if (SUCCEEDED(m_pDesktop->ParseDisplayName(NULL,NULL,(LPWSTR)pwszPath,NULL,(PIDLIST_RELATIVE*)&pidl,NULL))) { CComPtr<IShellFolder> pFolder; PCUITEMID_CHILD child; if (SUCCEEDED(SHBindToParent(pidl,IID_IShellFolder,(void**)&pFolder,&child))) { ULONG attrib=SFGAO_SHARE; if (SUCCEEDED(pFolder->GetAttributesOf(1,&child,&attrib)) && (attrib&SFGAO_SHARE)) res=S_OK; } ILFree(pidl); } } return res; }
void CMyTreeView::AddItemInternal(HTREEITEM hParent,const TCHAR *szFullFileName) { IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlComplete = NULL; LPITEMIDLIST pidlRelative = NULL; HTREEITEM hItem; TVITEMEX tvItem; TVINSERTSTRUCT tvis; SHFILEINFO shfi; SFGAOF Attributes; TCHAR szDisplayName[MAX_PATH]; HRESULT hr; BOOL res; int iItemId; int nChildren = 0; hr = GetIdlFromParsingName(szFullFileName,&pidlComplete); if(!SUCCEEDED(hr)) return; tvItem.mask = TVIF_CHILDREN | TVIF_STATE; tvItem.hItem = hParent; res = TreeView_GetItem(m_hTreeView,&tvItem); if(res) { /* If the parent node is currently collapsed, simply indicate that it has children (i.e. a plus sign will be shown next to the parent node). */ if((tvItem.cChildren == 0) || ((tvItem.state & TVIS_EXPANDED) != TVIS_EXPANDED)) { tvItem.mask = TVIF_CHILDREN; tvItem.hItem = hParent; tvItem.cChildren = 1; TreeView_SetItem(m_hTreeView,&tvItem); } else { SHGetFileInfo(szFullFileName,NULL,&shfi, sizeof(shfi),SHGFI_SYSICONINDEX); hr = SHBindToParent(pidlComplete, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { Attributes = SFGAO_HASSUBFOLDER; /* Only retrieve the attributes for this item. */ hr = pShellFolder->GetAttributesOf(1, (LPCITEMIDLIST *)&pidlRelative,&Attributes); if(SUCCEEDED(hr)) { if((Attributes & SFGAO_HASSUBFOLDER) != SFGAO_HASSUBFOLDER) nChildren = 0; else nChildren = 1; iItemId = GenerateUniqueItemId(); m_pItemInfo[iItemId].pidl = ILClone(pidlComplete); m_pItemInfo[iItemId].pridl = ILClone(pidlRelative); GetDisplayName(szFullFileName,szDisplayName,SIZEOF_ARRAY(szDisplayName),SHGDN_NORMAL); tvItem.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM|TVIF_CHILDREN; tvItem.pszText = szDisplayName; tvItem.iImage = shfi.iIcon; tvItem.iSelectedImage = shfi.iIcon; tvItem.lParam = (LPARAM)iItemId; tvItem.cChildren = nChildren; if(hParent != NULL) { tvis.hParent = hParent; tvis.hInsertAfter = DetermineItemSortedPosition(hParent,szFullFileName); tvis.itemex = tvItem; hItem = TreeView_InsertItem(m_hTreeView,&tvis); } } pShellFolder->Release(); } } } CoTaskMemFree(pidlComplete); }
bool CFileSelectList::AddFileItem(LPITEMIDLIST pFullIDLS,int nOption) { bool res = false; SHFILEINFO fileInfo={0}; if(SHGetFileInfo((LPCTSTR)pFullIDLS,0,&fileInfo,sizeof(fileInfo),SHGFI_PIDL |SHGFI_DISPLAYNAME|SHGFI_ATTRIBUTES|SHGFI_ICON|SHGFI_SMALLICON) != 0) { if(fileInfo.dwAttributes & SFGAO_FILESYSTEM) { bool bIsFile = false; if(fileInfo.dwAttributes & SFGAO_FOLDER)//判断是否是文件系统对象文件夹,排除zip文件 { if(fileInfo.dwAttributes & SFGAO_STREAM) { int nSysID = GetWindowsSystemID(); if(nSysID == WINDOWS_XP || nSysID == WINDOWS_VISTA || nSysID == WINDOWS_2003) { bIsFile = true;//zip文件 } } } else { bIsFile = true; } if(!bIsFile) //是文件夹,但不是.zip文件 { IShellFolder *pIParentFolder,*pICurFolder; LPITEMIDLIST pLocalIDLS; if(nOption & UNIFOLDER_PIG)//作为整体归档 { goto PIG_FILE; } else//归档下面的文件 { if(S_OK == SHBindToParent(pFullIDLS,IID_IShellFolder,(void**)&pIParentFolder,(LPCITEMIDLIST*)&pLocalIDLS)) { if(S_OK == pIParentFolder->BindToObject(pLocalIDLS,NULL,IID_IShellFolder,(void**)&pICurFolder)) { IEnumIDList* pIEnum; SHCONTF enumFlag = (nOption&FOLDER_RECURSIVEG_PIG)?(SHCONTF_FOLDERS|SHCONTF_NONFOLDERS):SHCONTF_NONFOLDERS; if(S_OK == pICurFolder->EnumObjects(NULL,enumFlag,&pIEnum)) { for(HRESULT call_res = pIEnum->Next(1,&pLocalIDLS,NULL);call_res == S_OK;call_res = pIEnum->Next(1,&pLocalIDLS,NULL)) { LPITEMIDLIST pFullChildIDLST = ILCombine(pFullIDLS,pLocalIDLS); if(pFullChildIDLST != NULL) { AddFileItem(pFullChildIDLST,nOption); ILFree(pFullChildIDLST); } CoTaskMemFree(pLocalIDLS); } pIEnum->Release(); } pICurFolder->Release(); } pIParentFolder->Release(); } } } else //is file { PIG_FILE: TCHAR tcbufPath[MAX_PATH]; if(SHGetPathFromIDList(pFullIDLS,tcbufPath)) { if(!IsAlreayIn(FilePath2Url(CString(tcbufPath)))) { CString strPathFolder,strFName,strDriver,strExt; SplitFilePath(CString(tcbufPath),strPathFolder,strDriver,strFName,strExt); LVITEM lvit = {0}; lvit.mask = LVIF_IMAGE|LVIF_TEXT; lvit.iItem = GetItemCount(); lvit.pszText = (LPWSTR)(LPCTSTR)strFName; lvit.cchTextMax = strFName.GetLength(); int iImg; if(!m_iSys2Self.Lookup(fileInfo.iIcon,iImg)) { //CImageList *pImgLs = GetImageList(LVSIL_SMALL); iImg = GetImageList(LVSIL_SMALL)->Add(fileInfo.hIcon); m_iSys2Self.SetAt(fileInfo.iIcon,iImg); } lvit.iImage = iImg; int iItem = InsertItem(&lvit); //SetItem(iItem,1,LVIF_TEXT,strPathFolder+L"\\",0,0,0,0); SetItemText(iItem,1,tcbufPath); ItemDataType* pItemData = new ItemDataType; pItemData->strItemUrl = FilePath2Url(tcbufPath); SetItemData(iItem,(DWORD_PTR)pItemData); } } } } DestroyIcon(fileInfo.hIcon); } return res; }
HRESULT STDMETHODCALLTYPE CAddressEditBox::Execute(long paramC) { HRESULT hr; /* * Parse the path is it wasn't parsed */ if (!pidlLastParsed) ParseNow(0); if (!pidlLastParsed) return E_FAIL; /* * Get the IShellBrowser and IBrowserService interfaces of the shell browser */ CComPtr<IShellBrowser> pisb; hr = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pisb)); if (FAILED(hr)) return hr; CComPtr<IBrowserService> pbs; pisb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs)); if (FAILED(hr)) return hr; /* * Get the current pidl of the shellbrowser and check if it is the same with the parsed one */ PIDLIST_ABSOLUTE pidl; hr = pbs->GetPidl(&pidl); if (FAILED(hr)) return hr; CComPtr<IShellFolder> psf; hr = SHGetDesktopFolder(&psf); if (FAILED(hr)) return hr; hr = psf->CompareIDs(0, pidl, pidlLastParsed); SHFree(pidl); if (hr == 0) return S_OK; /* * Attempt to browse to the parsed pidl */ hr = pisb->BrowseObject(pidlLastParsed, 0); if (SUCCEEDED(hr)) return hr; /* * Browsing to the pidl failed so it's not a folder. So invoke its defaule command. */ HWND topLevelWindow; hr = IUnknown_GetWindow(pisb, &topLevelWindow); if (FAILED(hr)) return hr; LPCITEMIDLIST pidlChild; CComPtr<IShellFolder> sf; hr = SHBindToParent(pidlLastParsed, IID_PPV_ARG(IShellFolder, &sf), &pidlChild); if (FAILED(hr)) return hr; hr = SHInvokeDefaultCommand(topLevelWindow, sf, pidlChild); if (FAILED(hr)) return hr; return hr; }
bool SelectFolder(HWND hOwner) { BROWSEINFO info; LPITEMIDLIST pidlist; TCHAR path[MAX_PATH]; if (FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { return false; } info.hwndOwner = hOwner; info.pidlRoot = NULL; info.pszDisplayName = path; info.lpszTitle = _T("Select a game/mod folder"); info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; info.lpfn = NULL; info.lParam = 0; info.iImage = 0; if ((pidlist = SHBrowseForFolder(&info)) == NULL) { CoUninitialize(); return false; } /* This hellish code is from MSDN and translate shortcuts to real targets. * God almighty, I wish Window used real symlinks. */ bool acquire_success = false; bool is_link = false; IShellFolder *psf = NULL; LPCITEMIDLIST new_item_list; HRESULT hr; hr = SHBindToParent(pidlist, IID_IShellFolder, (void **)&psf, &new_item_list); if (SUCCEEDED(hr)) { IShellLink *psl = NULL; hr = psf->GetUIObjectOf(hOwner, 1, &new_item_list, IID_IShellLink, NULL, (void **)&psl); if (SUCCEEDED(hr)) { LPITEMIDLIST new_item_list; hr = psl->GetIDList(&new_item_list); if (SUCCEEDED(hr)) { is_link = true; hr = SHGetPathFromIDList(new_item_list, method_path); if (SUCCEEDED(hr)) { acquire_success = true; } CoTaskMemFree(new_item_list); } psl->Release(); } psf->Release(); } if (!acquire_success && !is_link) { hr = SHGetPathFromIDList(pidlist, method_path); if (SUCCEEDED(hr)) { acquire_success = true; } } /* That was awful. shoo, shoo, COM */ CoTaskMemFree(pidlist); CoUninitialize(); return acquire_success; }
void CShellBrowser::OnFileActionAdded(const TCHAR *szFileName) { IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlFull = NULL; LPITEMIDLIST pidlRelative = NULL; Added_t Added; TCHAR FullFileName[MAX_PATH]; TCHAR szDisplayName[MAX_PATH]; STRRET str; BOOL bFileAdded = FALSE; HRESULT hr; StringCchCopy(FullFileName,SIZEOF_ARRAY(FullFileName),m_CurDir); PathAppend(FullFileName,szFileName); hr = GetIdlFromParsingName(FullFileName,&pidlFull); /* It is possible that by the time a file is registered here, it will have already been renamed. In this the following check will fail. If the file is not added, store its filename. */ if(SUCCEEDED(hr)) { hr = SHBindToParent(pidlFull, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { /* If this is a virtual folder, only use SHGDN_INFOLDER. If this is a real folder, combine SHGDN_INFOLDER with SHGDN_FORPARSING. This is so that items in real folders can still be shown with extensions, even if the global, Explorer option is disabled. */ if(m_bVirtualFolder) hr = pShellFolder->GetDisplayNameOf(pidlRelative,SHGDN_INFOLDER,&str); else hr = pShellFolder->GetDisplayNameOf(pidlRelative,SHGDN_INFOLDER|SHGDN_FORPARSING,&str); if(SUCCEEDED(hr)) { StrRetToBuf(&str,pidlRelative,szDisplayName,SIZEOF_ARRAY(szDisplayName)); std::list<DroppedFile_t>::iterator itr; BOOL bDropped = FALSE; if(!m_DroppedFileNameList.empty()) { for(itr = m_DroppedFileNameList.begin();itr != m_DroppedFileNameList.end();itr++) { if(lstrcmp(szDisplayName,itr->szFileName) == 0) { bDropped = TRUE; break; } } } /* Only insert the item in its sorted position if it wasn't dropped in. */ if(m_bInsertSorted && !bDropped) { int iItemId; int iSorted; iItemId = SetItemInformation(m_pidlDirectory,pidlRelative,szDisplayName); iSorted = DetermineItemSortedPosition(iItemId); AddItemInternal(iSorted,iItemId,TRUE); } else { /* Just add the item to the end of the list. */ AddItemInternal(m_pidlDirectory,pidlRelative,szDisplayName,-1,FALSE); } InsertAwaitingItems(m_bShowInGroups); bFileAdded = TRUE; } pShellFolder->Release(); } CoTaskMemFree(pidlFull); } if(!bFileAdded) { /* The file does not exist. However, it is possible that is was simply renamed shortly after been created. Record the filename temporarily (so that it can later be added). */ StringCchCopy(Added.szFileName,SIZEOF_ARRAY(Added.szFileName),szFileName); m_FilesAdded.push_back(Added); } }
/* TODO: This code should be coalesced with the code that adds items as well as the code that finds their icons. ALL changes to an items name/internal properties/icon/overlay icon should go through a central function. */ void CFolderView::RenameItem(int iItemInternal,TCHAR *szNewFileName) { IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlFull = NULL; LPITEMIDLIST pidlRelative = NULL; SHFILEINFO shfi; LVFINDINFO lvfi; TCHAR szDisplayName[MAX_PATH]; LVITEM lvItem; TCHAR szFullFileName[MAX_PATH]; DWORD_PTR res; HRESULT hr; int iItem; if(iItemInternal == -1) return; StringCchCopy(szFullFileName,MAX_PATH,m_CurDir); PathAppend(szFullFileName,szNewFileName); hr = GetIdlFromParsingName(szFullFileName,&pidlFull); if(SUCCEEDED(hr)) { hr = SHBindToParent(pidlFull,IID_IShellFolder,(void **)&pShellFolder,(LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { hr = GetDisplayName(szFullFileName,szDisplayName,SHGDN_INFOLDER|SHGDN_FORPARSING); if(SUCCEEDED(hr)) { m_pExtraItemInfo[iItemInternal].pridl = ILClone(pidlRelative); StringCchCopy(m_pExtraItemInfo[iItemInternal].szDisplayName, SIZEOF_ARRAY(m_pExtraItemInfo[iItemInternal].szDisplayName), szDisplayName); /* Need to update internal storage for the item, since it's name has now changed. */ StringCchCopy(m_pwfdFiles[iItemInternal].cFileName, SIZEOF_ARRAY(m_pwfdFiles[iItemInternal].cFileName), szNewFileName); /* The files' type may have changed, so retrieve the files' icon again. */ res = SHGetFileInfo((LPTSTR)pidlFull,0,&shfi, sizeof(SHFILEINFO),SHGFI_PIDL|SHGFI_ICON| SHGFI_OVERLAYINDEX); if(res != 0) { /* Locate the item within the listview. */ lvfi.flags = LVFI_PARAM; lvfi.lParam = iItemInternal; iItem = ListView_FindItem(m_hListView,-1,&lvfi); if(iItem != -1) { lvItem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_STATE; lvItem.iItem = iItem; lvItem.iSubItem = 0; lvItem.iImage = shfi.iIcon; lvItem.pszText = ProcessItemFileName(iItemInternal); lvItem.stateMask = LVIS_OVERLAYMASK; /* As well as resetting the items icon, we'll also set it's overlay again (the overlay could change, for example, if the file is changed to a shortcut). */ lvItem.state = INDEXTOOVERLAYMASK(shfi.iIcon >> 24); /* Update the item in the listview. */ ListView_SetItem(m_hListView,&lvItem); /* TODO: Does the file need to be filtered out? */ if(IsFileFiltered(iItemInternal)) { RemoveFilteredItem(iItem,iItemInternal); } } DestroyIcon(shfi.hIcon); } } pShellFolder->Release(); }
HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { CComPtr<IBrowserService> isb; CComPtr<IShellFolder> sf; HRESULT hr; INT indexClosed, indexOpen, itemExists, oldIndex; DWORD result; COMBOBOXEXITEMW item; PIDLIST_ABSOLUTE absolutePIDL; LPCITEMIDLIST pidlChild; LPITEMIDLIST pidlPrevious; STRRET ret; WCHAR buf[4096]; if (pDispParams == NULL) return E_INVALIDARG; switch (dispIdMember) { case DISPID_NAVIGATECOMPLETE2: case DISPID_DOCUMENTCOMPLETE: pidlLastParsed = NULL; oldIndex = fCombobox.SendMessage(CB_GETCURSEL, 0, 0); itemExists = FALSE; pidlPrevious = NULL; ZeroMemory(&item, sizeof(item)); item.mask = CBEIF_LPARAM; item.iItem = 0; if (fCombobox.SendMessage(CBEM_GETITEM, 0, reinterpret_cast<LPARAM>(&item))) { pidlPrevious = reinterpret_cast<LPITEMIDLIST>(item.lParam); if (pidlPrevious) itemExists = TRUE; } hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb)); if (FAILED_UNEXPECTEDLY(hr)) return hr; hr = isb->GetPidl(&absolutePIDL); if (FAILED_UNEXPECTEDLY(hr)) return hr; hr = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild); if (FAILED_UNEXPECTEDLY(hr)) return hr; hr = sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR | SHGDN_FORPARSING, &ret); if (FAILED_UNEXPECTEDLY(hr)) return hr; hr = StrRetToBufW(&ret, pidlChild, buf, 4095); if (FAILED_UNEXPECTEDLY(hr)) return hr; indexClosed = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen); item.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM; item.iItem = 0; item.iImage = indexClosed; item.iSelectedImage = indexOpen; item.pszText = buf; item.lParam = reinterpret_cast<LPARAM>(absolutePIDL); if (itemExists) { result = fCombobox.SendMessage(CBEM_SETITEM, 0, reinterpret_cast<LPARAM>(&item)); oldIndex = 0; if (result) { ILFree(pidlPrevious); } } else { oldIndex = fCombobox.SendMessage(CBEM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&item)); if (oldIndex < 0) DbgPrint("ERROR %d\n", GetLastError()); } fCombobox.SendMessage(CB_SETCURSEL, -1, 0); fCombobox.SendMessage(CB_SETCURSEL, oldIndex, 0); //fAddressEditBox->SetCurrentDir(index); } return S_OK; }
/************************************************************************* * SHGetFileInfoW [SHELL32.@] * */ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags ) { WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH]; int iIndex; DWORD_PTR ret = TRUE; DWORD dwAttributes = 0; IShellFolder * psfParent = NULL; IExtractIconW * pei = NULL; LPITEMIDLIST pidlLast = NULL, pidl = NULL; HRESULT hr = S_OK; BOOL IconNotYetLoaded=TRUE; UINT uGilFlags = 0; HIMAGELIST big_icons, small_icons; TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n", (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags); if (!path) return FALSE; /* windows initializes these values regardless of the flags */ if (psfi != NULL) { psfi->szDisplayName[0] = '\0'; psfi->szTypeName[0] = '\0'; psfi->iIcon = 0; } if (!(flags & SHGFI_PIDL)) { /* SHGetFileInfo should work with absolute and relative paths */ if (PathIsRelativeW(path)) { GetCurrentDirectoryW(MAX_PATH, szLocation); PathCombineW(szFullPath, szLocation, path); } else { lstrcpynW(szFullPath, path, MAX_PATH); } } if (flags & SHGFI_EXETYPE) { if (flags != SHGFI_EXETYPE) return 0; return shgfi_get_exe_type(szFullPath); } /* * psfi is NULL normally to query EXE type. If it is NULL, none of the * below makes sense anyway. Windows allows this and just returns FALSE */ if (psfi == NULL) return FALSE; /* * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES * is not specified. * The pidl functions fail on not existing file names */ if (flags & SHGFI_PIDL) { pidl = ILClone((LPCITEMIDLIST)path); } else if (!(flags & SHGFI_USEFILEATTRIBUTES)) { hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes); } if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES)) { /* get the parent shellfolder */ if (pidl) { hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&pidlLast ); if (SUCCEEDED(hr)) pidlLast = ILClone(pidlLast); ILFree(pidl); } else { ERR("pidl is null!\n"); return FALSE; } } /* get the attributes of the child */ if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES)) { if (!(flags & SHGFI_ATTR_SPECIFIED)) { psfi->dwAttributes = 0xffffffff; } if (psfParent) IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast, &(psfi->dwAttributes) ); } /* get the displayname */ if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME)) { if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) { lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath)); } else { STRRET str; hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast, SHGDN_INFOLDER, &str); StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast); } } /* get the type name */ if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME)) { static const WCHAR szFile[] = { 'F','i','l','e',0 }; static const WCHAR szDashFile[] = { '-','f','i','l','e',0 }; if (!(flags & SHGFI_USEFILEATTRIBUTES) || (flags & SHGFI_PIDL)) { char ftype[80]; _ILGetFileType(pidlLast, ftype, 80); MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 ); } else { if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) strcatW (psfi->szTypeName, szFile); else { WCHAR sTemp[64]; lstrcpyW(sTemp,PathFindExtensionW(szFullPath)); if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) && HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE ))) { lstrcpynW (psfi->szTypeName, sTemp, 64); strcatW (psfi->szTypeName, szDashFile); } } } } /* ### icons ###*/ Shell_GetImageLists( &big_icons, &small_icons ); if (flags & SHGFI_OPENICON) uGilFlags |= GIL_OPENICON; if (flags & SHGFI_LINKOVERLAY) uGilFlags |= GIL_FORSHORTCUT; else if ((flags&SHGFI_ADDOVERLAYS) || (flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON) { if (SHELL_IsShortcut(pidlLast)) uGilFlags |= GIL_FORSHORTCUT; } if (flags & SHGFI_OVERLAYINDEX) FIXME("SHGFI_OVERLAYINDEX unhandled\n"); if (flags & SHGFI_SELECTED) FIXME("set icon to selected, stub\n"); if (flags & SHGFI_SHELLICONSIZE) FIXME("set icon to shell size, stub\n"); /* get the iconlocation */ if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION )) { UINT uDummy,uFlags; if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) { if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { lstrcpyW(psfi->szDisplayName, swShell32Name); psfi->iIcon = -IDI_SHELL_FOLDER; } else { WCHAR* szExt; static const WCHAR p1W[] = {'%','1',0}; WCHAR sTemp [MAX_PATH]; szExt = PathFindExtensionW(szFullPath); TRACE("szExt=%s\n", debugstr_w(szExt)); if ( szExt && HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) && HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &psfi->iIcon)) { if (lstrcmpW(p1W, sTemp)) strcpyW(psfi->szDisplayName, sTemp); else { /* the icon is in the file */ strcpyW(psfi->szDisplayName, szFullPath); } } else ret = FALSE; } } else { hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW, &uDummy, (LPVOID*)&pei); if (SUCCEEDED(hr)) { hr = IExtractIconW_GetIconLocation(pei, uGilFlags, szLocation, MAX_PATH, &iIndex, &uFlags); if (uFlags & GIL_NOTFILENAME) ret = FALSE; else { lstrcpyW (psfi->szDisplayName, szLocation); psfi->iIcon = iIndex; } IExtractIconW_Release(pei); } } } /* get icon index (or load icon)*/ if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX))) { if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) { WCHAR sTemp [MAX_PATH]; WCHAR * szExt; int icon_idx=0; lstrcpynW(sTemp, szFullPath, MAX_PATH); if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0); else { static const WCHAR p1W[] = {'%','1',0}; psfi->iIcon = 0; szExt = PathFindExtensionW(sTemp); if ( szExt && HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) && HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &icon_idx)) { if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */ strcpyW(sTemp, szFullPath); if (flags & SHGFI_SYSICONINDEX) { psfi->iIcon = SIC_GetIconIndex(sTemp,icon_idx,0); if (psfi->iIcon == -1) psfi->iIcon = 0; } else { UINT ret; if (flags & SHGFI_SMALLICON) ret = PrivateExtractIconsW( sTemp,icon_idx, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), &psfi->hIcon, 0, 1, 0); else ret = PrivateExtractIconsW( sTemp, icon_idx, GetSystemMetrics( SM_CXICON), GetSystemMetrics( SM_CYICON), &psfi->hIcon, 0, 1, 0); if (ret != 0 && ret != (UINT)-1) { IconNotYetLoaded=FALSE; psfi->iIcon = icon_idx; } } } } } else { if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON), uGilFlags, &(psfi->iIcon)))) { ret = FALSE; } } if (ret && (flags & SHGFI_SYSICONINDEX)) { if (flags & SHGFI_SMALLICON) ret = (DWORD_PTR)small_icons; else ret = (DWORD_PTR)big_icons; } } /* icon handle */ if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded) { if (flags & SHGFI_SMALLICON) psfi->hIcon = ImageList_GetIcon( small_icons, psfi->iIcon, ILD_NORMAL); else psfi->hIcon = ImageList_GetIcon( big_icons, psfi->iIcon, ILD_NORMAL); } if (flags & ~SHGFI_KNOWN_FLAGS) FIXME("unknown flags %08x\n", flags & ~SHGFI_KNOWN_FLAGS); if (psfParent) IShellFolder_Release(psfParent); if (hr != S_OK) ret = FALSE; SHFree(pidlLast); TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n", psfi->hIcon, psfi->iIcon, psfi->dwAttributes, debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret); return ret; }
void FileDialog::FilterFiles(HWND hDlg) { HWND parent = ::GetParent(hDlg); IShellFolder *ishell = NULL; LPMALLOC imalloc = NULL; HRESULT hr; // Get pointer to the ListView control HWND lv = ::GetDlgItem(::GetDlgItem(parent, lst2), 1); if (lv == NULL) { wxASSERT(lv != NULL); return; } // Get shell's memory allocation interface (must be Release()'d) hr = SHGetMalloc(&imalloc); if ((hr != NOERROR) || (imalloc == NULL)) { wxASSERT((hr == NOERROR) && (imalloc != NULL)); return; } // Init LVITEM lvi; wxZeroMemory(lvi); // Process all items int fltcnt = m_Filters.GetCount(); int itmcnt = ::SendMessage(lv, LVM_GETITEMCOUNT, 0, 0); for (int itm = 0; itm < itmcnt; itm++) { // Retrieve the file IDL lvi.iItem = itm; lvi.mask = LVIF_PARAM; if (ListView_GetItem(lv, &lvi) != TRUE) { wxASSERT(FALSE); break; } LPCITEMIDLIST fidl = (LPCITEMIDLIST) lvi.lParam; // Retrieve the IShellFolder interface of the parent (must be Release()'d) if (ishell == NULL) { hr = SHBindToParent(fidl, IID_IShellFolder, (void **)&ishell, NULL); if (!SUCCEEDED(hr)) { wxASSERT(SUCCEEDED(hr)); break; } } // Get the attributes of the object DWORD attr = SFGAO_FOLDER | SFGAO_STREAM; hr = ishell->GetAttributesOf(1, &fidl, &attr); if (!SUCCEEDED(hr)) { wxASSERT(SUCCEEDED(hr)); break; } // Allow all folders (things like zip files get filtered below) if (attr == SFGAO_FOLDER) { continue; } // Retrieve the parsable name of the object (includes extension) STRRET str; hr = ishell->GetDisplayNameOf(fidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str); if (hr != NOERROR) { // For some objects, we get back an error of 80070057. I'm assuming this // means there is no way to represent the name (like some sort of virtual name) // or I've not used the correct PIDL. But, in either case, it "probably" // represents some sort of folder (at least in all cases I've seen), so we // simply allow it to display. continue; } // Convert result to wxString wxString filename; switch (str.uType) { case STRRET_WSTR: filename = str.pOleStr; imalloc->Free(str.pOleStr); break; case STRRET_OFFSET: filename = wxString(((char *)fidl) + str.uOffset, wxConvISO8859_1); break; case STRRET_CSTR: filename = wxString(str.cStr, wxConvISO8859_1); break; } // Attempt to match it to all of our filters bool match = false; for (int flt = 0; flt < fltcnt; flt++) { if (wxMatchWild(m_Filters[flt], filename, false)) { match = true; break; } } // Remove it from the display if it didn't match any of the filters. if (!match) { ListView_DeleteItem(lv, itm); itm--; itmcnt--; } } done: // Release the interface if (ishell) { ishell->Release(); } // Release the interface if (imalloc) { imalloc->Release(); } }
void Explorerplusplus::OnTreeViewRightClick(WPARAM wParam,LPARAM lParam) { LPITEMIDLIST pidl = NULL; POINT *ppt = NULL; HTREEITEM hItem; HTREEITEM hPrevItem; IShellFolder *pShellParentFolder = NULL; LPITEMIDLIST pidlRelative = NULL; HRESULT hr; hItem = (HTREEITEM)wParam; ppt = (POINT *)lParam; m_bTreeViewRightClick = TRUE; hPrevItem = TreeView_GetSelection(m_hTreeView); TreeView_SelectItem(m_hTreeView,hItem); pidl = m_pMyTreeView->BuildPath(hItem); hr = SHBindToParent(pidl, IID_PPV_ARGS(&pShellParentFolder), (LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { HTREEITEM hParent; LPITEMIDLIST pidlParent = NULL; hParent = TreeView_GetParent(m_hTreeView,hItem); /* If we right-click on the "Desktop" item in the treeview, there is no parent. In such case, use "Desktop" as parent item as well, to allow the context menu to be shown. */ if(hParent == NULL) { hParent = hItem; } if(hParent != NULL) { pidlParent = m_pMyTreeView->BuildPath(hParent); if(pidlParent != NULL) { m_bTreeViewOpenInNewTab = FALSE; std::list<LPITEMIDLIST> pidlList; pidlList.push_back(pidlRelative); CFileContextMenuManager fcmm(m_hContainer,pidlParent, pidlList); FileContextMenuInfo_t fcmi; fcmi.uFrom = FROM_TREEVIEW; CStatusBar StatusBar(m_hStatusBar); fcmm.ShowMenu(this,MIN_SHELL_MENU_ID,MAX_SHELL_MENU_ID,ppt,&StatusBar, reinterpret_cast<DWORD_PTR>(&fcmi),TRUE,GetKeyState(VK_SHIFT) & 0x80); CoTaskMemFree(pidlParent); } } pShellParentFolder->Release(); } /* Don't switch back to the previous folder if the folder that was right-clicked was opened in a new tab (i.e. can just keep the selection the same). */ if(!m_bTreeViewOpenInNewTab) TreeView_SelectItem(m_hTreeView,hPrevItem); m_bTreeViewRightClick = FALSE; CoTaskMemFree(pidl); }
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 }