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 BOOL create_combobox_item(IShellFolder *folder, LPCITEMIDLIST pidl, IImageList *icon_list, COMBOBOXEXITEMW *item) { STRRET strret; HRESULT hres; IExtractIconW *extract_icon; UINT reserved; WCHAR icon_file[MAX_PATH]; INT icon_index; UINT icon_flags; HICON icon; strret.uType=STRRET_WSTR; hres = IShellFolder_GetDisplayNameOf(folder,pidl,SHGDN_FORADDRESSBAR,&strret); if(SUCCEEDED(hres)) hres = StrRetToStrW(&strret, pidl, &item->pszText); if(FAILED(hres)) { WINE_WARN("Could not get name for pidl\n"); return FALSE; } hres = IShellFolder_GetUIObjectOf(folder,NULL,1,&pidl,&IID_IExtractIconW, &reserved,(void**)&extract_icon); if(SUCCEEDED(hres)) { item->mask |= CBEIF_IMAGE; IExtractIconW_GetIconLocation(extract_icon,GIL_FORSHELL,icon_file, sizeof(icon_file)/sizeof(WCHAR), &icon_index,&icon_flags); IExtractIconW_Extract(extract_icon,icon_file,icon_index,NULL,&icon,20); item->iImage = ImageList_AddIcon((HIMAGELIST)icon_list,icon); IExtractIconW_Release(extract_icon); } else { item->mask &= ~CBEIF_IMAGE; WINE_WARN("Could not get an icon for %s\n",wine_dbgstr_w(item->pszText)); } return TRUE; }
/* add an individual file or folder to the menu, takes ownership of pidl */ static struct menu_item* add_shell_item(struct menu_item* parent, LPITEMIDLIST pidl) { struct menu_item* item; MENUITEMINFOW mii; HMENU parent_menu; int existing_item_count, i; BOOL match = FALSE; SFGAOF flags; item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct menu_item)); if (parent->pidl == NULL) { pidl_to_shellfolder(pidl, &item->displayname, &item->folder); } else { STRRET strret; IShellFolder_GetDisplayNameOf(parent->folder, pidl, SHGDN_INFOLDER, &strret); StrRetToStrW(&strret, NULL, &item->displayname); flags = SFGAO_FOLDER; IShellFolder_GetAttributesOf(parent->folder, 1, (LPCITEMIDLIST*)&pidl, &flags); if (flags & SFGAO_FOLDER) IShellFolder_BindToObject(parent->folder, pidl, NULL, &IID_IShellFolder, (void *)&item->folder); } parent_menu = parent->menuhandle; item->parent = parent; item->pidl = pidl; existing_item_count = GetMenuItemCount(parent_menu); mii.cbSize = sizeof(mii); mii.fMask = MIIM_SUBMENU|MIIM_DATA; /* search for an existing menu item with this name or the spot to insert this item */ if (parent->pidl != NULL) { for (i=0; i<existing_item_count; i++) { struct menu_item* existing_item; int cmp; GetMenuItemInfoW(parent_menu, i, TRUE, &mii); existing_item = ((struct menu_item*)mii.dwItemData); if (!existing_item) continue; /* folders before files */ if (existing_item->folder && !item->folder) continue; if (!existing_item->folder && item->folder) break; cmp = CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, item->displayname, -1, existing_item->displayname, -1); if (cmp == CSTR_LESS_THAN) break; if (cmp == CSTR_EQUAL) { match = TRUE; break; } } } else /* This item manually added to the root menu, so put it at the end */ i = existing_item_count; if (!match) { /* no existing item with the same name; just add it */ mii.fMask = MIIM_STRING|MIIM_DATA; mii.dwTypeData = item->displayname; mii.dwItemData = (ULONG_PTR)item; if (item->folder) { MENUINFO mi; item->menuhandle = CreatePopupMenu(); mii.fMask |= MIIM_SUBMENU; mii.hSubMenu = item->menuhandle; mi.cbSize = sizeof(mi); mi.fMask = MIM_MENUDATA; mi.dwMenuData = (ULONG_PTR)item; SetMenuInfo(item->menuhandle, &mi); } InsertMenuItemW(parent->menuhandle, i, TRUE, &mii); list_add_tail(&items, &item->entry); } else if (item->folder) { /* there is an existing folder with the same name, combine them */ MENUINFO mi; item->base = (struct menu_item*)mii.dwItemData; item->menuhandle = item->base->menuhandle; mii.dwItemData = (ULONG_PTR)item; SetMenuItemInfoW(parent_menu, i, TRUE, &mii); mi.cbSize = sizeof(mi); mi.fMask = MIM_MENUDATA; mi.dwMenuData = (ULONG_PTR)item; SetMenuInfo(item->menuhandle, &mi); list_add_tail(&items, &item->entry); } else { /* duplicate shortcut, do nothing */ HeapFree(GetProcessHeap(), 0, item->displayname); HeapFree(GetProcessHeap(), 0, item); CoTaskMemFree(pidl); item = NULL; } return item; }
void SearchFolder(IShellFolder* pSearchFolder, CDoubleList<FILE_ITEM> &Items, LARGE_INTEGER& liSize) { //getting the enumerator object to enumerate the items of the search folder IEnumIDList* pEnumIDList = NULL; HRESULT hr = pSearchFolder->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &pEnumIDList); if (FAILED(hr)) { if (hr != E_ACCESSDENIED) DisplayError(hr); return; } if (hr == S_FALSE) return; //getting pidl to each child item ITEMIDLIST* pidlChild = NULL; HRESULT hrEnum; do { hrEnum = pEnumIDList->Next(1, &pidlChild, NULL); if (FAILED(hrEnum)) { pEnumIDList->Release(); _ASSERT(0); DisplayError(hrEnum); return; } if (S_FALSE == hrEnum) break; //we need to know whether this is a folder or a file, and if it is a system item ULONG ulFlags = 0xFFFFFFFF; hr = pSearchFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidlChild, &ulFlags); if (FAILED(hr)) { CoTaskMemFree(pidlChild); pidlChild = NULL; pEnumIDList->Release(); _ASSERT(0); MessageBox(0, L"Could not get the attributes of the item: pSearchFolder->GetAttributesOf", 0, 0); return; } if (ulFlags & SFGAO_FILESYSTEM) { if (ulFlags & SFGAO_FOLDER && ulFlags & SFGAO_FILESYSANCESTOR && ulFlags & SFGAO_STORAGE) { //we need to search it IShellFolder* pNewSearchFolder = NULL; hr = pSearchFolder->BindToObject(pidlChild, NULL, IID_IShellFolder, (void**)&pNewSearchFolder); if (FAILED(hr)) { CoTaskMemFree(pidlChild); pidlChild = NULL; pEnumIDList->Release(); _ASSERT(0); MessageBox(0, L"Could not bind to new folder: pSearchFolder->BindToObject", 0, 0); return; } //it is a folder!! //get its full name STRRET strret; pSearchFolder->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strret); WCHAR* wsFullName; StrRetToStrW(&strret, NULL, &wsFullName); FILE_ITEM item; item.size = 0; item.wsFullName = wsFullName; item.type = ItemType::Folder; Items.push_back(item); SearchFolder(pNewSearchFolder, Items, liSize); pNewSearchFolder->Release(); } else if (ulFlags & SFGAO_STREAM) { //it is a file!! //get its full name STRRET strret; pSearchFolder->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strret); WCHAR* wsFullName; StrRetToStrW(&strret, NULL, &wsFullName); FILE_ITEM item; LARGE_INTEGER li; CalcFileSize(wsFullName, li); item.size = li.QuadPart; liSize.QuadPart += item.size; item.wsFullName = wsFullName; item.type = ItemType::File; Items.push_back(item); } } CoTaskMemFree(pidlChild); pidlChild = NULL; #pragma warning(suppress: 4127) }while (1); if (pidlChild) CoTaskMemFree(pidlChild); pEnumIDList->Release(); }