[0.4.11][SHELL32][SHLWAPI][COMDLG32][SDK] Unable to select a Zip file for sending with Common Open Dialog CORE-16908

It "regressed" by 0.4.9-dev-632-g da6a46c6ac when zipfldr.dll got registered.
Ftr: Even without this complex fix it was possible to workaround this bug by 'regsvr32 /u zipfldr.dll'.

by porting back:
0.4.15-dev-279-g 83a9f71690 CORE-16908 [SHELL32] Allow creation of an empty CFileSysEnum
0.4.15-dev-254-g 332889b8d7 CORE-16908 [COMDLG32] Differentiate between real and virtual folders
0.4.15-dev-252-g f379a29606 CORE-16908 [SHELL32][SDK] Properly enumerate virtual shell folders (on files) as fake folders
0.4.15-dev-251-g b1003ae909 CORE-16908 [SHELL32] Update CFileSysEnum to be maintaineable
0.4.15-dev-250-g ac215455bb CORE-16908 [SHLWAPI] Fix SHRegGetCLSIDKeyW
and we also need:
0.4.14-dev-73-g 5d54b65ceb CORE-16271 [SHELL32] Add support for custom View objects defined with UICLSID
This commit is contained in:
Joachim Henze 2022-02-26 23:54:38 +01:00
parent 990abadd40
commit f663d176a5
6 changed files with 357 additions and 178 deletions

View file

@ -2526,12 +2526,12 @@ int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
PathAddBackslashW(lpwstrTemp); PathAddBackslashW(lpwstrTemp);
} }
dwAttributes = SFGAO_FOLDER; dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSANCESTOR;
if(SUCCEEDED(IShellFolder_ParseDisplayName(*ppsf, hwnd, NULL, lpwstrTemp, &dwEaten, &pidl, &dwAttributes))) if(SUCCEEDED(IShellFolder_ParseDisplayName(*ppsf, hwnd, NULL, lpwstrTemp, &dwEaten, &pidl, &dwAttributes)))
{ {
/* the path component is valid, we have a pidl of the next path component */ /* the path component is valid, we have a pidl of the next path component */
TRACE("parse OK attr=0x%08x pidl=%p\n", dwAttributes, pidl); TRACE("parse OK attr=0x%08x pidl=%p\n", dwAttributes, pidl);
if(dwAttributes & SFGAO_FOLDER) if((dwAttributes & (SFGAO_FOLDER | SFGAO_FILESYSANCESTOR)) == (SFGAO_FOLDER | SFGAO_FILESYSANCESTOR))
{ {
if(FAILED(IShellFolder_BindToObject(*ppsf, pidl, 0, &IID_IShellFolder, (LPVOID*)&lpsfChild))) if(FAILED(IShellFolder_BindToObject(*ppsf, pidl, 0, &IID_IShellFolder, (LPVOID*)&lpsfChild)))
{ {
@ -4112,7 +4112,7 @@ static LPITEMIDLIST GetPidlFromName(IShellFolder *lpsf,LPWSTR lpcstrFileName)
*/ */
static BOOL IsPidlFolder (LPSHELLFOLDER psf, LPCITEMIDLIST pidl) static BOOL IsPidlFolder (LPSHELLFOLDER psf, LPCITEMIDLIST pidl)
{ {
ULONG uAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER; ULONG uAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR;
HRESULT ret; HRESULT ret;
TRACE("%p, %p\n", psf, pidl); TRACE("%p, %p\n", psf, pidl);
@ -4121,7 +4121,7 @@ static BOOL IsPidlFolder (LPSHELLFOLDER psf, LPCITEMIDLIST pidl)
TRACE("-- 0x%08x 0x%08x\n", uAttr, ret); TRACE("-- 0x%08x 0x%08x\n", uAttr, ret);
/* see documentation shell 4.1*/ /* see documentation shell 4.1*/
return uAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER); return (uAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER)) && (uAttr & SFGAO_FILESYSANCESTOR);
} }
/*********************************************************************** /***********************************************************************

View file

@ -774,9 +774,9 @@ static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDl
{ {
HRESULT hRes; HRESULT hRes;
ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER; ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR;
IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr); IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr);
if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) ) if ((ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER)) && (ulAttr & SFGAO_FILESYSANCESTOR))
{ {
hRes = IShellBrowser_BrowseObject(&This->IShellBrowser_iface,pidl,SBSP_RELATIVE); hRes = IShellBrowser_BrowseObject(&This->IShellBrowser_iface,pidl,SBSP_RELATIVE);
if(fodInfos->ofnInfos->Flags & OFN_EXPLORER) if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)

View file

@ -1,53 +1,24 @@
/* /*
* file system folder * PROJECT: shell32
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* Copyright 1997 Marcus Meissner * PURPOSE: file system folder
* Copyright 1998, 1999, 2002 Juergen Schmied * COPYRIGHT: Copyright 1997 Marcus Meissner
* * Copyright 1998, 1999, 2002 Juergen Schmied
* This library is free software; you can redistribute it and/or * Copyright 2019 Katayama Hirofumi MZ
* modify it under the terms of the GNU Lesser General Public * Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <precomp.h> #include <precomp.h>
WINE_DEFAULT_DEBUG_CHANNEL (shell); WINE_DEFAULT_DEBUG_CHANNEL (shell);
HKEY OpenKeyFromFileType(PCUIDLIST_RELATIVE pidl, LPCWSTR KeyName) static HRESULT SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, LPCWSTR KeyName, CLSID* pclsidFolder);
HKEY OpenKeyFromFileType(LPWSTR pExtension, LPCWSTR KeyName)
{ {
HKEY hkey; HKEY hkey;
if (!_ILIsValue(pidl))
{
ERR("Invalid pidl!\n");
return NULL;
}
FileStructW* pDataW = _ILGetFileStructW(pidl);
if (!pDataW)
{
ERR("Invalid pidl!\n");
return NULL;
}
LPWSTR pExtension = PathFindExtensionW(pDataW->wszName);
if (!pExtension || *pExtension == NULL)
{
WARN("No extension for %S!\n", pDataW->wszName);
return NULL;
}
WCHAR FullName[MAX_PATH]; WCHAR FullName[MAX_PATH];
DWORD dwSize = sizeof(FullName); DWORD dwSize = sizeof(FullName);
wsprintf(FullName, L"%s\\%s", pExtension, KeyName); wsprintf(FullName, L"%s\\%s", pExtension, KeyName);
@ -59,7 +30,7 @@ HKEY OpenKeyFromFileType(PCUIDLIST_RELATIVE pidl, LPCWSTR KeyName)
res = RegGetValueW(HKEY_CLASSES_ROOT, pExtension, NULL, RRF_RT_REG_SZ, NULL, FullName, &dwSize); res = RegGetValueW(HKEY_CLASSES_ROOT, pExtension, NULL, RRF_RT_REG_SZ, NULL, FullName, &dwSize);
if (res) if (res)
{ {
WARN("Failed to get progid for file %S, extension %S (%x), address %x, pidl: %x, error %d\n", pDataW->wszName, pExtension, pExtension, &dwSize, pidl, res); WARN("Failed to get progid for extension %S (%x), error %d\n", pExtension, pExtension, res);
return NULL; return NULL;
} }
@ -74,9 +45,33 @@ HKEY OpenKeyFromFileType(PCUIDLIST_RELATIVE pidl, LPCWSTR KeyName)
return hkey; return hkey;
} }
HRESULT GetCLSIDForFileType(PCUIDLIST_RELATIVE pidl, LPCWSTR KeyName, CLSID* pclsid) LPWSTR ExtensionFromPidl(PCUIDLIST_RELATIVE pidl)
{ {
HKEY hkeyProgId = OpenKeyFromFileType(pidl, KeyName); if (!_ILIsValue(pidl))
{
ERR("Invalid pidl!\n");
return NULL;
}
FileStructW* pDataW = _ILGetFileStructW(pidl);
if (!pDataW)
{
ERR("Invalid pidl!\n");
return NULL;
}
LPWSTR pExtension = PathFindExtensionW(pDataW->wszName);
if (!pExtension || *pExtension == UNICODE_NULL)
{
WARN("No extension for %S!\n", pDataW->wszName);
return NULL;
}
return pExtension;
}
HRESULT GetCLSIDForFileTypeFromExtension(LPWSTR pExtension, LPCWSTR KeyName, CLSID* pclsid)
{
HKEY hkeyProgId = OpenKeyFromFileType(pExtension, KeyName);
if (!hkeyProgId) if (!hkeyProgId)
{ {
WARN("OpenKeyFromFileType failed for key %S\n", KeyName); WARN("OpenKeyFromFileType failed for key %S\n", KeyName);
@ -129,6 +124,15 @@ HRESULT GetCLSIDForFileType(PCUIDLIST_RELATIVE pidl, LPCWSTR KeyName, CLSID* pcl
return S_OK; return S_OK;
} }
HRESULT GetCLSIDForFileType(PCUIDLIST_RELATIVE pidl, LPCWSTR KeyName, CLSID* pclsid)
{
LPWSTR pExtension = ExtensionFromPidl(pidl);
if (!pExtension)
return S_FALSE;
return GetCLSIDForFileTypeFromExtension(pExtension, KeyName, pclsid);
}
static HRESULT static HRESULT
getDefaultIconLocation(LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT uFlags) getDefaultIconLocation(LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT uFlags)
{ {
@ -292,7 +296,8 @@ HRESULT CFSExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, RE
} }
else else
{ {
HKEY hkey = OpenKeyFromFileType(pidl, L"DefaultIcon"); LPWSTR pExtension = ExtensionFromPidl(pidl);
HKEY hkey = pExtension ? OpenKeyFromFileType(pExtension, L"DefaultIcon") : NULL;
if (!hkey) if (!hkey)
WARN("Could not open DefaultIcon key!\n"); WARN("Could not open DefaultIcon key!\n");
@ -334,92 +339,166 @@ including formatting a drive, reconnecting a network share drive, and requesting
be inserted in a removable drive. be inserted in a removable drive.
*/ */
/***********************************************************************
* IShellFolder implementation
*/
class CFileSysEnum : class CFileSysEnum :
public CEnumIDListBase public CEnumIDListBase
{ {
private: private:
public: HRESULT _AddFindResult(LPWSTR sParentDir, const WIN32_FIND_DATAW& FindData, DWORD dwFlags)
CFileSysEnum();
~CFileSysEnum();
HRESULT WINAPI Initialize(LPWSTR sPathTarget, DWORD dwFlags);
BEGIN_COM_MAP(CFileSysEnum)
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
END_COM_MAP()
};
CFileSysEnum::CFileSysEnum()
{
}
CFileSysEnum::~CFileSysEnum()
{
}
HRESULT WINAPI CFileSysEnum::Initialize(LPWSTR lpszPath, DWORD dwFlags)
{
WIN32_FIND_DATAW stffile;
HANDLE hFile;
WCHAR szPath[MAX_PATH];
BOOL succeeded = TRUE;
static const WCHAR stars[] = { '*','.','*',0 };
static const WCHAR dot[] = { '.',0 };
static const WCHAR dotdot[] = { '.','.',0 };
TRACE("(%p)->(path=%s flags=0x%08x)\n", this, debugstr_w(lpszPath), dwFlags);
if(!lpszPath || !lpszPath[0]) return FALSE;
wcscpy(szPath, lpszPath);
PathAddBackslashW(szPath);
wcscat(szPath,stars);
hFile = FindFirstFileW(szPath,&stffile);
if ( hFile != INVALID_HANDLE_VALUE )
{ {
BOOL findFinished = FALSE; // Does it need special handling because it is hidden?
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
{
// Is it hidden, but are we not asked to include hidden?
if (!(dwFlags & SHCONTF_INCLUDEHIDDEN))
return S_OK;
}
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)
{
if (dwFlags & SHCONTF_FOLDERS)
{
TRACE("(%p)-> (folder=%s)\n", this, debugstr_w(FindData.cFileName));
pidl = _ILCreateFromFindDataW(&FindData);
}
}
else
{
if (dwFlags & SHCONTF_NONFOLDERS)
{
TRACE("(%p)-> (file =%s)\n", this, debugstr_w(FindData.cFileName));
pidl = _ILCreateFromFindDataW(&FindData);
}
}
if (pidl && !AddToEnumList(pidl))
{
FAILED_UNEXPECTEDLY(E_FAIL);
return E_FAIL;
}
return S_OK;
}
public:
CFileSysEnum()
{
}
~CFileSysEnum()
{
}
HRESULT WINAPI Initialize(LPWSTR sPathTarget, DWORD dwFlags)
{
TRACE("(%p)->(path=%s flags=0x%08x)\n", this, debugstr_w(sPathTarget), dwFlags);
if (!sPathTarget || !sPathTarget[0])
{
WARN("No path for CFileSysEnum, empty result!\n");
return S_FALSE;
}
WCHAR szFindPattern[MAX_PATH];
HRESULT hr = StringCchCopyW(szFindPattern, _countof(szFindPattern), sPathTarget);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
/* FIXME: UNSAFE CRAP */
PathAddBackslashW(szFindPattern);
hr = StringCchCatW(szFindPattern, _countof(szFindPattern), L"*.*");
if (FAILED_UNEXPECTEDLY(hr))
return hr;
WIN32_FIND_DATAW FindData;
HANDLE hFind = FindFirstFileW(szFindPattern, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
return HRESULT_FROM_WIN32(GetLastError());
do do
{ {
if ( !(stffile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) hr = _AddFindResult(sPathTarget, FindData, dwFlags);
|| (dwFlags & SHCONTF_INCLUDEHIDDEN) )
{
LPITEMIDLIST pidl = NULL;
if ( (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && if (FAILED_UNEXPECTEDLY(hr))
dwFlags & SHCONTF_FOLDERS && break;
strcmpW(stffile.cFileName, dot) && strcmpW(stffile.cFileName, dotdot))
{ } while(FindNextFileW(hFind, &FindData));
pidl = _ILCreateFromFindDataW(&stffile);
succeeded = succeeded && AddToEnumList(pidl); if (SUCCEEDED(hr))
} {
else if (!(stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) DWORD dwError = GetLastError();
&& dwFlags & SHCONTF_NONFOLDERS) if (dwError != ERROR_NO_MORE_FILES)
{
pidl = _ILCreateFromFindDataW(&stffile);
succeeded = succeeded && AddToEnumList(pidl);
}
}
if (succeeded)
{ {
if (!FindNextFileW(hFile, &stffile)) hr = HRESULT_FROM_WIN32(dwError);
{ FAILED_UNEXPECTEDLY(hr);
if (GetLastError() == ERROR_NO_MORE_FILES)
findFinished = TRUE;
else
succeeded = FALSE;
}
} }
} while (succeeded && !findFinished); }
FindClose(hFile); TRACE("(%p)->(hr=0x%08x)\n", this, hr);
FindClose(hFind);
return hr;
} }
return succeeded; BEGIN_COM_MAP(CFileSysEnum)
} COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
END_COM_MAP()
};
/***********************************************************************
* IShellFolder implementation
*/
CFSFolder::CFSFolder() CFSFolder::CFSFolder()
{ {
@ -489,7 +568,7 @@ LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path)
return pidl; return pidl;
} }
void SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, CLSID* pclsidFolder) static HRESULT SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, LPCWSTR KeyName, CLSID* pclsidFolder)
{ {
WCHAR wszCLSIDValue[CHARS_IN_GUID]; WCHAR wszCLSIDValue[CHARS_IN_GUID];
WCHAR wszDesktopIni[MAX_PATH]; WCHAR wszDesktopIni[MAX_PATH];
@ -497,14 +576,15 @@ void SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, CLSID* pclsidFolder)
StringCchCatW(wszDesktopIni, MAX_PATH, L"\\desktop.ini"); StringCchCatW(wszDesktopIni, MAX_PATH, L"\\desktop.ini");
if (GetPrivateProfileStringW(L".ShellClassInfo", if (GetPrivateProfileStringW(L".ShellClassInfo",
L"CLSID", KeyName,
L"", L"",
wszCLSIDValue, wszCLSIDValue,
CHARS_IN_GUID, CHARS_IN_GUID,
wszDesktopIni)) wszDesktopIni))
{ {
CLSIDFromString (wszCLSIDValue, pclsidFolder); return CLSIDFromString(wszCLSIDValue, pclsidFolder);
} }
return E_FAIL;
} }
HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes) HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
@ -524,10 +604,60 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW
dwShellAttributes = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK | SFGAO_CANRENAME | SFGAO_CANDELETE | dwShellAttributes = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK | SFGAO_CANRENAME | SFGAO_CANDELETE |
SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | SFGAO_FILESYSTEM; SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | SFGAO_FILESYSTEM;
if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) BOOL bDirectory = (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
dwShellAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR | SFGAO_STORAGEANCESTOR | SFGAO_STORAGE);
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)
{
TRACE("Augmenting '%S' with dwAttributes=0x%x\n", szFileName, dwAttributes);
dwShellAttributes |= dwAttributes;
}
::RegCloseKey(hkey);
// This should be presented as directory!
bDirectory = TRUE;
TRACE("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 else
{
dwShellAttributes |= SFGAO_STREAM; dwShellAttributes |= SFGAO_STREAM;
}
if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
dwShellAttributes |= SFGAO_HIDDEN; dwShellAttributes |= SFGAO_HIDDEN;
@ -741,7 +871,7 @@ HRESULT WINAPI CFSFolder::BindToObject(
clsidFolder = CLSID_ShellFSFolder; clsidFolder = CLSID_ShellFSFolder;
if ((pData->uFileAttribs & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0) if ((pData->uFileAttribs & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0)
SHELL32_GetCLSIDForDirectory(pfti.szTargetParsingName, &clsidFolder); SHELL32_GetCLSIDForDirectory(pfti.szTargetParsingName, L"CLSID", &clsidFolder);
} }
else else
{ {
@ -856,30 +986,73 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner,
{ {
*ppvOut = NULL; *ppvOut = NULL;
if (IsEqualIID (riid, IID_IDropTarget)) BOOL bIsDropTarget = IsEqualIID (riid, IID_IDropTarget);
hr = CFSDropTarget_CreateInstance(sPathTarget, riid, ppvOut); BOOL bIsShellView = !bIsDropTarget && IsEqualIID (riid, IID_IShellView);
else if (IsEqualIID (riid, IID_IContextMenu))
{
HKEY hKeys[16];
UINT cKeys = 0;
AddClassKeyToArray(L"Directory\\Background", hKeys, &cKeys);
DEFCONTEXTMENU dcm; if (bIsDropTarget || bIsShellView)
dcm.hwnd = hwndOwner;
dcm.pcmcb = this;
dcm.pidlFolder = pidlRoot;
dcm.psf = this;
dcm.cidl = 0;
dcm.apidl = NULL;
dcm.cKeys = cKeys;
dcm.aKeys = hKeys;
dcm.punkAssociationInfo = NULL;
hr = SHCreateDefaultContextMenu (&dcm, riid, ppvOut);
}
else if (IsEqualIID (riid, IID_IShellView))
{ {
SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this}; DWORD dwDirAttributes = _ILGetFileAttributes(ILFindLastID(pidlRoot), NULL, 0);
hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
if ((dwDirAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0)
{
CLSID clsidFolder;
hr = SHELL32_GetCLSIDForDirectory(sPathTarget, L"UICLSID", &clsidFolder);
if (SUCCEEDED(hr))
{
CComPtr<IPersistFolder> spFolder;
hr = SHCoCreateInstance(NULL, &clsidFolder, NULL, IID_PPV_ARG(IPersistFolder, &spFolder));
if (!FAILED_UNEXPECTEDLY(hr))
{
hr = spFolder->Initialize(pidlRoot);
if (!FAILED_UNEXPECTEDLY(hr))
{
hr = spFolder->QueryInterface(riid, ppvOut);
}
}
}
else
{
// No desktop.ini, or no UICLSID present, continue as if nothing happened
hr = E_INVALIDARG;
}
}
}
if (!SUCCEEDED(hr))
{
// No UICLSID handler found, continue to the default handlers
if (bIsDropTarget)
{
hr = CFSDropTarget_CreateInstance(sPathTarget, riid, ppvOut);
}
else if (IsEqualIID (riid, IID_IContextMenu))
{
HKEY hKeys[16];
UINT cKeys = 0;
AddClassKeyToArray(L"Directory\\Background", hKeys, &cKeys);
DEFCONTEXTMENU dcm;
dcm.hwnd = hwndOwner;
dcm.pcmcb = this;
dcm.pidlFolder = pidlRoot;
dcm.psf = this;
dcm.cidl = 0;
dcm.apidl = NULL;
dcm.cKeys = cKeys;
dcm.aKeys = hKeys;
dcm.punkAssociationInfo = NULL;
hr = SHCreateDefaultContextMenu (&dcm, riid, ppvOut);
}
else if (bIsShellView)
{
SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this};
hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
}
else
{
hr = E_INVALIDARG;
}
} }
} }
TRACE("-- (%p)->(interface=%p)\n", this, ppvOut); TRACE("-- (%p)->(interface=%p)\n", this, ppvOut);

View file

@ -1,23 +1,11 @@
/* /*
* file system folder * PROJECT: shell32
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* Copyright 1997 Marcus Meissner * PURPOSE: file system folder
* Copyright 1998, 1999, 2002 Juergen Schmied * COPYRIGHT: Copyright 1997 Marcus Meissner
* Copyright 2009 Andrew Hill * Copyright 1998, 1999, 2002 Juergen Schmied
* * Copyright 2009 Andrew Hill
* This library is free software; you can redistribute it and/or * Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#ifndef _CFSFOLDER_H_ #ifndef _CFSFOLDER_H_
@ -84,19 +72,19 @@ class CFSFolder :
// IContextMenuCB // IContextMenuCB
virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam); virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam);
DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER) DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER)
DECLARE_NOT_AGGREGATABLE(CFSFolder) DECLARE_NOT_AGGREGATABLE(CFSFolder)
DECLARE_PROTECT_FINAL_CONSTRUCT() DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CFSFolder) BEGIN_COM_MAP(CFSFolder)
COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2) COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder) COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder3, IPersistFolder3) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder3, IPersistFolder3)
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
END_COM_MAP() END_COM_MAP()
}; };
#endif /* _CFSFOLDER_H_ */ #endif /* _CFSFOLDER_H_ */

View file

@ -2422,16 +2422,32 @@ HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU,
HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU, HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
BOOL bCreate, PHKEY phKey) BOOL bCreate, PHKEY phKey)
{ {
#ifndef __REACTOS__
static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\', static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' }; 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
#endif
#define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR)) #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
WCHAR szKey[MAX_PATH]; WCHAR szKey[MAX_PATH];
DWORD dwRet; DWORD dwRet;
HKEY hkey; HKEY hkey;
/* Create the key string */ /* Create the key string */
#ifdef __REACTOS__
// https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/reg/reggetclsidkey.htm
WCHAR* ptr;
wcscpy(szKey, bUseHKCU ? L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\" : L"CLSID\\");
ptr = szKey + wcslen(szKey);
SHStringFromGUIDW(guid, ptr, 39); /* Append guid */
if (lpszValue)
{
ptr = szKey + wcslen(szKey);
wcscat(ptr, L"\\");
wcscat(++ptr, lpszValue);
}
#else
memcpy(szKey, szClassIdKey, sizeof(szClassIdKey)); memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */ SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
@ -2440,6 +2456,7 @@ HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
szKey[szClassIdKeyLen + 39] = '\\'; szKey[szClassIdKeyLen + 39] = '\\';
strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */ strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
} }
#endif
hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT; hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;

View file

@ -53,6 +53,7 @@ HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds);
BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild); BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild);
HRESULT WINAPI SHForwardContextMenuMsg(IUnknown* pUnk, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult, BOOL useIContextMenu2); 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 SHAddDataBlock(LPDBLIST* lppList, const DATABLOCK_HEADER *lpNewItem);
BOOL WINAPI SHRemoveDataBlock(LPDBLIST* lppList, DWORD dwSignature); BOOL WINAPI SHRemoveDataBlock(LPDBLIST* lppList, DWORD dwSignature);