HRESULT WINAPI CDesktopFolder::FinalConstruct() { WCHAR szMyPath[MAX_PATH]; HRESULT hr; /* Create the root pidl */ pidlRoot = _ILCreateDesktop(); if (!pidlRoot) return E_OUTOFMEMORY; /* Create the inner fs folder */ hr = SHELL32_CoCreateInitSF(pidlRoot, NULL, NULL, &CLSID_ShellFSFolder, CSIDL_DESKTOPDIRECTORY, IID_PPV_ARG(IShellFolder2, &m_DesktopFSFolder)); if (FAILED_UNEXPECTEDLY(hr)) return hr; /* Create the inner shared fs folder. Dont fail on failure. */ hr = SHELL32_CoCreateInitSF(pidlRoot, NULL, NULL, &CLSID_ShellFSFolder, CSIDL_COMMON_DESKTOPDIRECTORY, IID_PPV_ARG(IShellFolder2, &m_SharedDesktopFSFolder)); if (FAILED_UNEXPECTEDLY(hr)) return hr; /* Create the inner reg folder */ hr = CRegFolder_CreateInstance(&CLSID_ShellDesktop, pidlRoot, L"", IID_PPV_ARG(IShellFolder2, &m_regFolder)); if (FAILED_UNEXPECTEDLY(hr)) return hr; /* Cache the path to the user desktop directory */ if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE )) return E_UNEXPECTED; sPathTarget = (LPWSTR)SHAlloc((wcslen(szMyPath) + 1) * sizeof(WCHAR)); if (!sPathTarget) return E_OUTOFMEMORY; wcscpy(sPathTarget, szMyPath); return S_OK; }
HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, const GUID* clsid, int csidl, REFIID riid, LPVOID *ppvOut) { /* fill the PERSIST_FOLDER_TARGET_INFO */ PERSIST_FOLDER_TARGET_INFO pfti = {0}; pfti.dwAttributes = -1; pfti.csidl = csidl; return SHELL32_CoCreateInitSF(pidlRoot, &pfti, NULL, clsid, riid, ppvOut); }
/*********************************************************************** * SHELL32_BindToFS [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_BindToFS (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut) { CComPtr<IShellFolder> pSF; HRESULT hr; LPCITEMIDLIST pidlChild; if (!pidlRoot || !ppvOut || !pidlComplete || !pidlComplete->mkid.cb) return E_INVALIDARG; if (_ILIsValue(pidlComplete)) { ERR("Binding to file is unimplemented\n"); return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } if (!_ILIsFolder(pidlComplete) && !_ILIsDrive(pidlComplete)) { ERR("Got an unknown type of pidl!\n"); return E_FAIL; } *ppvOut = NULL; pidlChild = (_ILIsPidlSimple (pidlComplete)) ? pidlComplete : ILCloneFirst (pidlComplete); CLSID clsidFolder = CLSID_ShellFSFolder; DWORD attributes = _ILGetFileAttributes(ILFindLastID(pidlChild), NULL, 0); if ((attributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0) SHELL32_GetCLSIDForDirectory(pathRoot, pidlChild, &clsidFolder); hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsidFolder, &pSF); if (pidlChild != pidlComplete) ILFree ((LPITEMIDLIST)pidlChild); if (SUCCEEDED (hr)) { if (_ILIsPidlSimple (pidlComplete)) { /* no sub folders */ hr = pSF->QueryInterface(riid, ppvOut); } else { /* go deeper */ hr = pSF->BindToObject(ILGetNext (pidlComplete), NULL, riid, ppvOut); } } TRACE ("-- returning (%p) %08x\n", *ppvOut, hr); return hr; }
HRESULT SHELL32_BindToSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti, LPCITEMIDLIST pidl, const GUID* clsid, REFIID riid, LPVOID *ppvOut) { PITEMID_CHILD pidlChild = ILCloneFirst (pidl); if (!pidlChild) return E_FAIL; CComPtr<IShellFolder> psf; HRESULT hr = SHELL32_CoCreateInitSF(pidlRoot, ppfti, pidlChild, clsid, IID_PPV_ARG(IShellFolder, &psf)); ILFree(pidlChild); if (FAILED_UNEXPECTEDLY(hr)) return hr; if (_ILIsPidlSimple (pidl)) return psf->QueryInterface(riid, ppvOut); else return psf->BindToObject(ILGetNext (pidl), NULL, riid, ppvOut); }
HRESULT WINAPI CRegFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) { CComPtr<IPersistFolder> pFolder; HRESULT hr; if (!ppvOut || !pidl || !pidl->mkid.cb) return E_INVALIDARG; *ppvOut = NULL; GUID *pGUID = _ILGetGUIDPointer(pidl); if (!pGUID) { ERR("CRegFolder::BindToObject called for non guid item!\n"); return E_INVALIDARG; } LPITEMIDLIST pidlChild = ILCloneFirst (pidl); if (!pidlChild) return E_OUTOFMEMORY; CComPtr<IShellFolder> psf; hr = SHELL32_CoCreateInitSF(m_pidlRoot, NULL, pidlChild, pGUID, -1, IID_PPV_ARG(IShellFolder, &psf)); ILFree(pidlChild); if (FAILED(hr)) return hr; if (_ILIsPidlSimple (pidl)) { return psf->QueryInterface(riid, ppvOut); } else { return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut); } }
/*********************************************************************** * 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; }