static LRESULT BrsFolder_Treeview_Expand( browse_info *info, NMTREEVIEWW *pnmtv ) { IShellFolder *lpsf2 = NULL; LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam; HRESULT r; TRACE("TVN_ITEMEXPANDINGA/W\n"); if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE)) return 0; if (!_ILIsEmpty(lptvid->lpi)) { r = IShellFolder_BindToObject( lptvid->lpsfParent, lptvid->lpi, 0, &IID_IShellFolder, (void**)&lpsf2 ); } else { lpsf2 = lptvid->lpsfParent; IShellFolder_AddRef(lpsf2); r = S_OK; } if (SUCCEEDED(r)) { FillTreeView( info, lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, lptvid->pEnumIL); IShellFolder_Release( lpsf2 ); } /* My Computer is already sorted and trying to do a simple text * sort will only mess things up */ if (!_ILIsMyComputer(lptvid->lpi)) SendMessageW( info->hwndTreeView, TVM_SORTCHILDREN, FALSE, (LPARAM)pnmtv->itemNew.hItem ); return 0; }
static BOOL BrsFolder_OnSetExpanded(browse_info *info, LPVOID selection, BOOL is_str, HTREEITEM *pItem) { LPITEMIDLIST pidlSelection = (LPITEMIDLIST)selection; LPCITEMIDLIST pidlCurrent, pidlRoot; TVITEMEXW item; BOOL bResult = FALSE; /* If 'selection' is a string, convert to a Shell ID List. */ if (is_str) { IShellFolder *psfDesktop; HRESULT hr; hr = SHGetDesktopFolder(&psfDesktop); if (FAILED(hr)) goto done; hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, (LPOLESTR)selection, NULL, &pidlSelection, NULL); IShellFolder_Release(psfDesktop); if (FAILED(hr)) goto done; } /* Move pidlCurrent behind the SHITEMIDs in pidlSelection, which are the root of * the sub-tree currently displayed. */ pidlRoot = info->lpBrowseInfo->pidlRoot; pidlCurrent = pidlSelection; while (!_ILIsEmpty(pidlRoot) && _ILIsEqualSimple(pidlRoot, pidlCurrent)) { pidlRoot = ILGetNext(pidlRoot); pidlCurrent = ILGetNext(pidlCurrent); } /* The given ID List is not part of the SHBrowseForFolder's current sub-tree. */ if (!_ILIsEmpty(pidlRoot)) goto done; /* Initialize item to point to the first child of the root folder. */ memset(&item, 0, sizeof(item)); item.mask = TVIF_PARAM; item.hItem = TreeView_GetRoot(info->hwndTreeView); if (item.hItem) item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem); /* Walk the tree along the nodes corresponding to the remaining ITEMIDLIST */ while (item.hItem && !_ILIsEmpty(pidlCurrent)) { LPTV_ITEMDATA pItemData; SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item); pItemData = (LPTV_ITEMDATA)item.lParam; if (_ILIsEqualSimple(pItemData->lpi, pidlCurrent)) { pidlCurrent = ILGetNext(pidlCurrent); if (!_ILIsEmpty(pidlCurrent)) { /* Only expand current node and move on to it's first child, * if we didn't already reach the last SHITEMID */ SendMessageW(info->hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)item.hItem); item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem); } } else { item.hItem = TreeView_GetNextSibling(info->hwndTreeView, item.hItem); } } if (_ILIsEmpty(pidlCurrent) && item.hItem) bResult = TRUE; done: if (pidlSelection && pidlSelection != (LPITEMIDLIST)selection) ILFree(pidlSelection); if (pItem) *pItem = item.hItem; return bResult; }
/****************************************************************************** * InitializeTreeView [Internal] * * Called from WM_INITDIALOG handler. * * PARAMS * hwndParent [I] The BrowseForFolder dialog * root [I] ITEMIDLIST of the root shell folder */ static void InitializeTreeView( browse_info *info ) { LPITEMIDLIST pidlParent, pidlChild; HIMAGELIST hImageList; HRESULT hr; IShellFolder *lpsfParent, *lpsfRoot; IEnumIDList * pEnumChildren = NULL; HTREEITEM item; DWORD flags; LPCITEMIDLIST root = info->lpBrowseInfo->pidlRoot; TRACE("%p\n", info ); Shell_GetImageLists(NULL, &hImageList); if (hImageList) SendMessageW( info->hwndTreeView, TVM_SETIMAGELIST, 0, (LPARAM)hImageList ); /* We want to call InsertTreeViewItem down the code, in order to insert * the root item of the treeview. Due to InsertTreeViewItem's signature, * we need the following to do this: * * + An ITEMIDLIST corresponding to _the parent_ of root. * + An ITEMIDLIST, which is a relative path from root's parent to root * (containing a single SHITEMID). * + An IShellFolder interface pointer of root's parent folder. * * If root is 'Desktop', then root's parent is also 'Desktop'. */ pidlParent = ILClone(root); ILRemoveLastID(pidlParent); pidlChild = ILClone(ILFindLastID(root)); if (_ILIsDesktop(pidlParent)) { hr = SHGetDesktopFolder(&lpsfParent); } else { IShellFolder *lpsfDesktop; hr = SHGetDesktopFolder(&lpsfDesktop); if (FAILED(hr)) { WARN("SHGetDesktopFolder failed! hr = %08x\n", hr); ILFree(pidlChild); ILFree(pidlParent); return; } hr = IShellFolder_BindToObject(lpsfDesktop, pidlParent, 0, &IID_IShellFolder, (LPVOID*)&lpsfParent); IShellFolder_Release(lpsfDesktop); } if (FAILED(hr)) { WARN("Could not bind to parent shell folder! hr = %08x\n", hr); ILFree(pidlChild); ILFree(pidlParent); return; } if (!_ILIsEmpty(pidlChild)) { hr = IShellFolder_BindToObject(lpsfParent, pidlChild, 0, &IID_IShellFolder, (LPVOID*)&lpsfRoot); } else { lpsfRoot = lpsfParent; hr = IShellFolder_AddRef(lpsfParent); } if (FAILED(hr)) { WARN("Could not bind to root shell folder! hr = %08x\n", hr); IShellFolder_Release(lpsfParent); ILFree(pidlChild); ILFree(pidlParent); return; } flags = BrowseFlagsToSHCONTF( info->lpBrowseInfo->ulFlags ); hr = IShellFolder_EnumObjects( lpsfRoot, info->hWnd, flags, &pEnumChildren ); if (FAILED(hr)) { WARN("Could not get child iterator! hr = %08x\n", hr); IShellFolder_Release(lpsfParent); IShellFolder_Release(lpsfRoot); ILFree(pidlChild); ILFree(pidlParent); return; } SendMessageW( info->hwndTreeView, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT ); item = InsertTreeViewItem( info, lpsfParent, pidlChild, pidlParent, pEnumChildren, TVI_ROOT ); SendMessageW( info->hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)item ); ILFree(pidlChild); ILFree(pidlParent); IShellFolder_Release(lpsfRoot); IShellFolder_Release(lpsfParent); }
/*********************************************************************** * SHELL32_BindToChild [Internal] * * Common code for IShellFolder_BindToObject. * * PARAMS * pidlRoot [I] The parent shell folder's absolute pidl. * pathRoot [I] Absolute dos path of the parent shell folder. * pidlComplete [I] PIDL of the child. Relative to pidlRoot. * riid [I] GUID of the interface, which ppvOut shall be bound to. * ppvOut [O] A reference to the child's interface (riid). * * NOTES * pidlComplete has to contain at least one non empty SHITEMID. * This function makes special assumptions on the shell namespace, which * means you probably can't use it for your IShellFolder implementation. */ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut) { GUID const *clsid; IShellFolder *pSF; HRESULT hr; LPITEMIDLIST pidlChild; TRACE("(%p %s %p %s %p)\n", pidlRoot, debugstr_w(pathRoot), pidlComplete, debugstr_guid(riid), ppvOut); if (!pidlRoot || !ppvOut || _ILIsEmpty(pidlComplete)) return E_INVALIDARG; *ppvOut = NULL; pidlChild = ILCloneFirst (pidlComplete); if ((clsid = _ILGetGUIDPointer (pidlChild))) { /* virtual folder */ hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsid, (LPVOID *)&pSF); } else if (_ILIsValue(pidlChild)) { /* Don't bind to files */ hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } else { /* file system folder */ CLSID clsidFolder = CLSID_ShellFSFolder; static const WCHAR wszCLSID[] = {'C','L','S','I','D',0}; WCHAR wszCLSIDValue[CHARS_IN_GUID], wszFolderPath[MAX_PATH], *pwszPathTail = wszFolderPath; /* see if folder CLSID should be overridden by desktop.ini file */ if (pathRoot) { lstrcpynW(wszFolderPath, pathRoot, MAX_PATH); pwszPathTail = PathAddBackslashW(wszFolderPath); } _ILSimpleGetTextW(pidlChild,pwszPathTail,MAX_PATH - (int)(pwszPathTail - wszFolderPath)); if (SHELL32_GetCustomFolderAttributeFromPath (wszFolderPath, wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID)) CLSIDFromString (wszCLSIDValue, &clsidFolder); hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, &clsidFolder, (LPVOID *)&pSF); } ILFree (pidlChild); if (SUCCEEDED (hr)) { if (_ILIsPidlSimple (pidlComplete)) { /* no sub folders */ hr = IShellFolder_QueryInterface (pSF, riid, ppvOut); } else { /* go deeper */ hr = IShellFolder_BindToObject (pSF, ILGetNext (pidlComplete), NULL, riid, ppvOut); } IShellFolder_Release (pSF); } TRACE ("-- returning (%p) 0x%08x\n", *ppvOut, hr); return hr; }