int Entry::extract_icon(ICONCACHE_FLAGS flags) { TCHAR path[MAX_PATH]; ICON_ID icon_id = ICID_NONE; if (_etype!=ET_SHELL && get_path(path, COUNTOF(path))) // not for ET_SHELL to display the correct desktop icon if (!(flags & ICF_MIDDLE)) // not for ICF_MIDDLE to extract 24x24 icons because SHGetFileInfo() doesn't support this icon size icon_id = g_Globals._icon_cache.extract(path, flags); if (icon_id == ICID_NONE) { if (!(flags & ICF_OVERLAYS)) { IExtractIcon* pExtract; if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) { unsigned gil_flags = 0; int idx; if (flags & ICF_OPEN) gil_flags |= GIL_OPENICON; if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, COUNTOF(path), &idx, &gil_flags))) { if (gil_flags & GIL_NOTFILENAME) icon_id = g_Globals._icon_cache.extract(pExtract, path, idx, flags); else { if (idx == -1) idx = 0; // special case for some control panel applications ("System") icon_id = g_Globals._icon_cache.extract(path, idx, flags); } /* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets (NVidia display driver). if (icon_id == ICID_NONE) { SHFILEINFO sfi; if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id; } */ /* if (icon_id == ICID_NONE) { LPBYTE b = (LPBYTE) alloca(0x10000); SHFILEINFO sfi; FILE* file = fopen(path, "rb"); if (file) { int l = fread(b, 1, 0x10000, file); fclose(file); if (l) icon_id = g_Globals._icon_cache.add(CreateIconFromResourceEx(b, l, TRUE, 0x00030000, 16, 16, LR_DEFAULTCOLOR)); } } */ } } } if (icon_id == ICID_NONE) { const ShellPath& pidl_abs = create_absolute_pidl(); LPCITEMIDLIST pidl = pidl_abs; icon_id = g_Globals._icon_cache.extract(pidl, flags); } } return icon_id; }
BOOL ShellEntry::launch_entry(HWND hwnd, UINT nCmdShow) { CONTEXT("ShellEntry::launch_entry()"); SHELLEXECUTEINFO shexinfo; shexinfo.cbSize = sizeof(SHELLEXECUTEINFO); shexinfo.fMask = SEE_MASK_INVOKEIDLIST; // SEE_MASK_IDLIST is also possible. shexinfo.hwnd = hwnd; shexinfo.lpVerb = NULL; shexinfo.lpFile = NULL; shexinfo.lpParameters = NULL; shexinfo.lpDirectory = NULL; shexinfo.nShow = nCmdShow; ShellPath shell_path = create_absolute_pidl(); shexinfo.lpIDList = &*shell_path; // add PIDL to the recent file list SHAddToRecentDocs(SHARD_PIDL, shexinfo.lpIDList); BOOL ret = TRUE; if (!ShellExecuteEx(&shexinfo)) { display_error(hwnd, GetLastError()); ret = FALSE; } return ret; }
HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos, CtxMenuInterfaces& cm_ifs) { ShellPath shell_path = create_absolute_pidl(); LPCITEMIDLIST pidl_abs = shell_path; if (!pidl_abs) return S_FALSE; // no action for registry entries, etc. #ifdef USE_MY_SHBINDTOPARENT IShellFolder* parentFolder; LPCITEMIDLIST pidlLast; // get and use the parent folder to display correct context menu in all cases -> correct "Properties" dialog for directories, ... HRESULT hr = my_SHBindToParent(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast); if (SUCCEEDED(hr)) { hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y, cm_ifs); parentFolder->Release(); } return hr; #else static DynamicFct<HRESULT(WINAPI*)(LPCITEMIDLIST, REFIID, LPVOID*, LPCITEMIDLIST*)> SHBindToParent(TEXT("SHELL32"), "SHBindToParent"); if (SHBindToParent) { IShellFolder* parentFolder; LPCITEMIDLIST pidlLast; // get and use the parent folder to display correct context menu in all cases -> correct "Properties" dialog for directories, ... HRESULT hr = (*SHBindToParent)(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast); if (SUCCEEDED(hr)) { hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y, cm_ifs); parentFolder->Release(); } return hr; } else { /**@todo use parent folder instead of desktop folder Entry* dir = _up; ShellPath parent_path; if (dir) parent_path = dir->create_absolute_pidl(); else parent_path = DesktopFolderPath(); ShellPath shell_path = create_relative_pidl(parent_path); LPCITEMIDLIST pidl = shell_path; ShellFolder parent_folder = parent_path; return ShellFolderContextMenu(parent_folder, hwnd, 1, &pidl, pos.x, pos.y); */ return ShellFolderContextMenu(GetDesktopFolder(), hwnd, 1, &pidl_abs, pos.x, pos.y, cm_ifs); } #endif }
// get full path of a shell entry bool ShellEntry::get_path(PTSTR path, size_t path_count) const { /* path[0] = TEXT('\0'); if (FAILED(path_from_pidl(get_parent_folder(), &*_pidl, path, MAX_PATH))) return false; */ FileSysShellPath fs_path(create_absolute_pidl()); LPCTSTR ret = fs_path; if (ret) { lstrcpyn(path, ret, path_count); return true; } else return false; }
int ShellEntry::extract_icon() { TCHAR path[MAX_PATH]; ICON_ID icon_id = ICID_NONE; if (get_path(path, COUNTOF(path))) icon_id = g_Globals._icon_cache.extract(path); if (icon_id == ICID_NONE) { IExtractIcon* pExtract; if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) { unsigned flags; int idx; if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, MAX_PATH, &idx, &flags))) { if (flags & GIL_NOTFILENAME) icon_id = g_Globals._icon_cache.extract(pExtract, path, idx); else { if (idx == -1) idx = 0; // special case for some control panel applications ("System") icon_id = g_Globals._icon_cache.extract(path, idx); } /* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets ("NVidia"). if (icon_id == ICID_NONE) { SHFILEINFO sfi; if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id; } */ /* if (icon_id == ICID_NONE) { LPBYTE b = (LPBYTE) alloca(0x10000); SHFILEINFO sfi; FILE* file = fopen(path, "rb"); if (file) { int l = fread(b, 1, 0x10000, file); fclose(file); if (l) icon_id = g_Globals._icon_cache.add(CreateIconFromResourceEx(b, l, TRUE, 0x00030000, 16, 16, LR_DEFAULTCOLOR)); } } */ } } if (icon_id == ICID_NONE) { SHFILEINFO sfi; const ShellPath& pidl_abs = create_absolute_pidl(); LPCITEMIDLIST pidl = pidl_abs; HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_PIDL|SHGFI_SMALLICON); if (himlSys) icon_id = g_Globals._icon_cache.add(sfi.iIcon); /* if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON)) icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id; */ } } return icon_id; }
ShellFolder Entry::get_shell_folder() const { return ShellFolder(create_absolute_pidl()); }