/*********************************************************************** * 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; }
static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) { IGenericSFImpl *This = (IGenericSFImpl *)iface; HRESULT hr = S_OK; TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS) return E_INVALIDARG; if (!pidl) { psd->fmt = DesktopSFHeader[iColumn].fmt; psd->cxChar = DesktopSFHeader[iColumn].cxChar; psd->str.uType = STRRET_CSTR; LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); return S_OK; } /* the data from the pidl */ psd->str.uType = STRRET_CSTR; switch (iColumn) { case 0: /* name */ hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); break; case 1: /* size */ _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH); break; case 2: /* type */ _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); break; case 3: /* date */ _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH); break; case 4: /* attributes */ _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH); break; } return hr; }
BOOL SHELL32_GetCustomFolderAttribute( LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, LPWSTR pwszValue, DWORD cchValue) { DWORD dwAttrib = FILE_ATTRIBUTE_SYSTEM; WCHAR wszFolderPath[MAX_PATH]; /* Hack around not having system attribute on non-Windows file systems */ if (0) dwAttrib = _ILGetFileAttributes(pidl, NULL, 0); if (dwAttrib & FILE_ATTRIBUTE_SYSTEM) { if (!SHGetPathFromIDListW(pidl, wszFolderPath)) return FALSE; return SHELL32_GetCustomFolderAttributeFromPath(wszFolderPath, pwszHeading, pwszAttribute, pwszValue, cchValue); } return FALSE; }
static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) { IDesktopFolderImpl *This = impl_from_IShellFolder2(iface); HRESULT hr = S_OK; TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS) return E_INVALIDARG; if (!pidl) return SHELL32_GetColumnDetails(desktop_header, iColumn, psd); /* the data from the pidl */ psd->str.uType = STRRET_CSTR; switch (iColumn) { case 0: /* name */ hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); break; case 1: /* size */ _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH); break; case 2: /* type */ _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); break; case 3: /* date */ _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH); break; case 4: /* attributes */ _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH); break; } return hr; }
/*********************************************************************** * SHELL32_GetItemAttributes * * NOTES * Observed values: * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER * file: 0x40000177 FILESYSTEM * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR * (seems to be default for shell extensions if no registry entry exists) * * win2k: * folder: 0xF0400177 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER * file: 0x40400177 FILESYSTEM | CANMONIKER * drive 0xF0400154 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER | CANRENAME (LABEL) * * According to the MSDN documentation this function should not set flags. It claims only to reset flags when necessary. * However it turns out the native shell32.dll _sets_ flags in several cases - so do we. */ HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes) { DWORD dwAttributes; BOOL has_guid; static const DWORD dwSupportedAttr= SFGAO_CANCOPY | /*0x00000001 */ SFGAO_CANMOVE | /*0x00000002 */ SFGAO_CANLINK | /*0x00000004 */ SFGAO_CANRENAME | /*0x00000010 */ SFGAO_CANDELETE | /*0x00000020 */ SFGAO_HASPROPSHEET | /*0x00000040 */ SFGAO_DROPTARGET | /*0x00000100 */ SFGAO_LINK | /*0x00010000 */ SFGAO_READONLY | /*0x00040000 */ SFGAO_HIDDEN | /*0x00080000 */ SFGAO_FILESYSANCESTOR | /*0x10000000 */ SFGAO_FOLDER | /*0x20000000 */ SFGAO_FILESYSTEM | /*0x40000000 */ SFGAO_HASSUBFOLDER; /*0x80000000 */ TRACE ("0x%08x\n", *pdwAttributes); if (*pdwAttributes & ~dwSupportedAttr) { WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes & ~dwSupportedAttr)); *pdwAttributes &= dwSupportedAttr; } has_guid = _ILGetGUIDPointer(pidl) != NULL; dwAttributes = *pdwAttributes; if (_ILIsDrive (pidl)) { *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FILESYSTEM|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR| SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANLINK; } else if (has_guid && HCR_GetFolderAttributes(pidl, &dwAttributes)) { *pdwAttributes = dwAttributes; } else if (_ILGetDataPointer (pidl)) { dwAttributes = _ILGetFileAttributes (pidl, NULL, 0); if (!dwAttributes && has_guid) { WCHAR path[MAX_PATH]; STRRET strret; /* File attributes are not present in the internal PIDL structure, so get them from the file system. */ HRESULT hr = IShellFolder_GetDisplayNameOf(psf, pidl, SHGDN_FORPARSING, &strret); if (SUCCEEDED(hr)) { hr = StrRetToBufW(&strret, pidl, path, MAX_PATH); /* call GetFileAttributes() only for file system paths, not for parsing names like "::{...}" */ if (SUCCEEDED(hr) && path[0]!=':') dwAttributes = GetFileAttributesW(path); } } /* Set common attributes */ *pdwAttributes |= SFGAO_FILESYSTEM | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANCOPY; if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) *pdwAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); else *pdwAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); if (dwAttributes & FILE_ATTRIBUTE_HIDDEN) *pdwAttributes |= SFGAO_HIDDEN; else *pdwAttributes &= ~SFGAO_HIDDEN; if (dwAttributes & FILE_ATTRIBUTE_READONLY) *pdwAttributes |= SFGAO_READONLY; else *pdwAttributes &= ~SFGAO_READONLY; if (SFGAO_LINK & *pdwAttributes) { char ext[MAX_PATH]; if (!_ILGetExtension(pidl, ext, MAX_PATH) || lstrcmpiA(ext, "lnk")) *pdwAttributes &= ~SFGAO_LINK; } } else { *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME|SFGAO_CANLINK; } TRACE ("-- 0x%08x\n", *pdwAttributes); return S_OK; }
HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes) { DWORD dwFileAttributes, dwShellAttributes; if (!_ILIsFolder(pidl) && !_ILIsValue(pidl)) { ERR("Got wrong type of pidl!\n"); *pdwAttributes &= SFGAO_CANLINK; return S_OK; } if (*pdwAttributes & ~dwSupportedAttr) { WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes & ~dwSupportedAttr)); *pdwAttributes &= dwSupportedAttr; } dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0); /* Set common attributes */ dwShellAttributes = *pdwAttributes; dwShellAttributes |= SFGAO_FILESYSTEM | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANCOPY; if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { dwShellAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); } else dwShellAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) dwShellAttributes |= SFGAO_HIDDEN; else dwShellAttributes &= ~SFGAO_HIDDEN; if (dwFileAttributes & FILE_ATTRIBUTE_READONLY) dwShellAttributes |= SFGAO_READONLY; else dwShellAttributes &= ~SFGAO_READONLY; if (SFGAO_LINK & *pdwAttributes) { char ext[MAX_PATH]; if (!_ILGetExtension(pidl, ext, MAX_PATH) || lstrcmpiA(ext, "lnk")) dwShellAttributes &= ~SFGAO_LINK; } if (SFGAO_HASSUBFOLDER & *pdwAttributes) { CComPtr<IShellFolder> psf2; if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_PPV_ARG(IShellFolder, &psf2)))) { CComPtr<IEnumIDList> pEnumIL; if (SUCCEEDED(psf2->EnumObjects(0, SHCONTF_FOLDERS, &pEnumIL))) { if (pEnumIL->Skip(1) != S_OK) dwShellAttributes &= ~SFGAO_HASSUBFOLDER; } } } *pdwAttributes &= dwShellAttributes; TRACE ("-- 0x%08x\n", *pdwAttributes); return S_OK; }