From f379a29606aa03c74f521de5b9028eb623ed4055 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Mon, 27 Apr 2020 20:43:16 +0200 Subject: [PATCH] [SHELL32] Properly enumerate virtual shell folders (on files) as fake folders CORE-16908 --- dll/win32/shell32/folders/CFSFolder.cpp | 100 +++++++++++++++++++++++- sdk/include/reactos/shlwapi_undoc.h | 1 + 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/dll/win32/shell32/folders/CFSFolder.cpp b/dll/win32/shell32/folders/CFSFolder.cpp index 266a7478367..a97ad5d4980 100644 --- a/dll/win32/shell32/folders/CFSFolder.cpp +++ b/dll/win32/shell32/folders/CFSFolder.cpp @@ -371,6 +371,52 @@ private: BOOL bDirectory = (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + HRESULT hr; + if (bDirectory) + { + // Skip the current and parent directory nodes + if (!strcmpW(FindData.cFileName, L".") || !strcmpW(FindData.cFileName, L"..")) + return S_OK; + + // Does this directory need special handling? + if ((FindData.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0) + { + WCHAR Tmp[MAX_PATH]; + CLSID clsidFolder; + + PathCombineW(Tmp, sParentDir, FindData.cFileName); + + hr = SHELL32_GetCLSIDForDirectory(Tmp, L"CLSID", &clsidFolder); + if (SUCCEEDED(hr)) + { + ERR("SHOULD DO SOMETHING WITH CLSID?\n"); + } + } + } + else + { + CLSID clsidFile; + LPWSTR pExtension = PathFindExtensionW(FindData.cFileName); + if (pExtension) + { + // FIXME: Cache this? + hr = GetCLSIDForFileTypeFromExtension(pExtension, L"CLSID", &clsidFile); + if (hr == S_OK) + { + HKEY hkey; + hr = SHRegGetCLSIDKeyW(clsidFile, L"ShellFolder", FALSE, FALSE, &hkey); + if (SUCCEEDED(hr)) + { + ::RegCloseKey(hkey); + + // This should be presented as directory! + bDirectory = TRUE; + TRACE("Treating '%S' as directory!\n", FindData.cFileName); + } + } + } + } + LPITEMIDLIST pidl = NULL; if (bDirectory) { @@ -573,10 +619,60 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW dwShellAttributes = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK | SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | SFGAO_FILESYSTEM; - if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - dwShellAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR | SFGAO_STORAGEANCESTOR | SFGAO_STORAGE); + BOOL bDirectory = (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + + if (!bDirectory) + { + // https://git.reactos.org/?p=reactos.git;a=blob;f=dll/shellext/zipfldr/res/zipfldr.rgs;hb=032b5aacd233cd7b83ab6282aad638c161fdc400#l9 + WCHAR szFileName[MAX_PATH]; + LPWSTR pExtension; + + if (_ILSimpleGetTextW(pidl, szFileName, _countof(szFileName)) && (pExtension = PathFindExtensionW(szFileName))) + { + CLSID clsidFile; + // FIXME: Cache this? + HRESULT hr = GetCLSIDForFileTypeFromExtension(pExtension, L"CLSID", &clsidFile); + if (hr == S_OK) + { + HKEY hkey; + hr = SHRegGetCLSIDKeyW(clsidFile, L"ShellFolder", FALSE, FALSE, &hkey); + if (SUCCEEDED(hr)) + { + DWORD dwAttributes = 0; + DWORD dwSize = sizeof(dwAttributes); + LSTATUS Status; + + Status = SHRegGetValueW(hkey, NULL, L"Attributes", RRF_RT_REG_DWORD, NULL, &dwAttributes, &dwSize); + if (Status == STATUS_SUCCESS) + { + ERR("Augmenting '%S' with dwAttributes=0x%x\n", szFileName, dwAttributes); + dwShellAttributes |= dwAttributes; + } + ::RegCloseKey(hkey); + + // This should be presented as directory! + bDirectory = TRUE; + ERR("Treating '%S' as directory!\n", szFileName); + } + } + } + } + + // This is a directory + if (bDirectory) + { + dwShellAttributes |= (SFGAO_FOLDER | /*SFGAO_HASSUBFOLDER |*/ SFGAO_STORAGE); + + // Is this a real directory? + if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + dwShellAttributes |= (SFGAO_FILESYSANCESTOR | SFGAO_STORAGEANCESTOR); + } + } else + { dwShellAttributes |= SFGAO_STREAM; + } if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) dwShellAttributes |= SFGAO_HIDDEN; diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h index a90537fbd30..08af85972d7 100644 --- a/sdk/include/reactos/shlwapi_undoc.h +++ b/sdk/include/reactos/shlwapi_undoc.h @@ -53,6 +53,7 @@ HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds); BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild); HRESULT WINAPI SHForwardContextMenuMsg(IUnknown* pUnk, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult, BOOL useIContextMenu2); +HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey); BOOL WINAPI SHAddDataBlock(LPDBLIST* lppList, const DATABLOCK_HEADER *lpNewItem); BOOL WINAPI SHRemoveDataBlock(LPDBLIST* lppList, DWORD dwSignature); -- 2.17.1