mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[SHELL32] Fix FS folder assoc array class order (#6047)
Fixes the reg class key order for FS items. The existing code was close, but for some reason used `//` as the path separator for SystemFileAssociations! - Fixed SystemFileAssociations. - Swapped the order of `*` and `AllFilesystemObjects`. This is the documented order and can also be observed in Process Monitor. https://learn.microsoft.com/en-us/windows/win32/shell/fa-associationarray#about-association-arrays - Removed `(..., L"%s//%s", extension, wszClass)`, this does not seem to be a valid thing (`.TestAAExtWeird` in my tests). - Adds the `Unknown` class when appropriate. Not adding the `openas` verb to `Unknown` rgs registration now to mimic Windows, because ROS `CDefaultContextMenu` lacks verb de-duplication and the menu would end up with two "Open With" entries. This just uses `(cidl == 1)` to simulate Windows, while Windows on NT6 uses `MultiSelectModel=Single`, a NT6 feature not implemented in ROS. - The class order for folders was wrong and is still "wrong" in this PR, but I chose to use the Windows menu display order until the exact mechanics required in `CDefaultContextMenu` can be understood. - Extracts the extension from ANSI PIDLs.
This commit is contained in:
parent
f6cf6954eb
commit
a83e40f6d1
4 changed files with 50 additions and 26 deletions
|
@ -624,7 +624,7 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
|
||||||
UINT cKeys = 0;
|
UINT cKeys = 0;
|
||||||
if (cidl > 0)
|
if (cidl > 0)
|
||||||
{
|
{
|
||||||
AddFSClassKeysToArray(apidl[0], hKeys, &cKeys);
|
AddFSClassKeysToArray(cidl, apidl, hKeys, &cKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFCONTEXTMENU dcm;
|
DEFCONTEXTMENU dcm;
|
||||||
|
|
|
@ -1207,7 +1207,7 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
|
||||||
{
|
{
|
||||||
HKEY hKeys[16];
|
HKEY hKeys[16];
|
||||||
UINT cKeys = 0;
|
UINT cKeys = 0;
|
||||||
AddFSClassKeysToArray(apidl[0], hKeys, &cKeys);
|
AddFSClassKeysToArray(cidl, apidl, hKeys, &cKeys);
|
||||||
|
|
||||||
DEFCONTEXTMENU dcm;
|
DEFCONTEXTMENU dcm;
|
||||||
dcm.hwnd = hwndOwner;
|
dcm.hwnd = hwndOwner;
|
||||||
|
|
|
@ -64,7 +64,7 @@ HRESULT SHELL32_BindToSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* pp
|
||||||
extern "C"
|
extern "C"
|
||||||
BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey);
|
BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey);
|
||||||
|
|
||||||
void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys);
|
void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array, UINT* cKeys);
|
||||||
|
|
||||||
HRESULT CDefViewBckgrndMenu_CreateInstance(IShellFolder* psf, REFIID riid, void **ppv);
|
HRESULT CDefViewBckgrndMenu_CreateInstance(IShellFolder* psf, REFIID riid, void **ppv);
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ static __inline int SHELL32_GUIDToStringW (REFGUID guid, LPWSTR str)
|
||||||
void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags);
|
void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags);
|
||||||
BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath);
|
BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath);
|
||||||
|
|
||||||
void AddClassKeyToArray(const WCHAR * szClass, HKEY* array, UINT* cKeys);
|
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
|
|
@ -265,59 +265,83 @@ HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST
|
||||||
return MAKE_COMPARE_HRESULT(ret);
|
return MAKE_COMPARE_HRESULT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddClassKeyToArray(const WCHAR * szClass, HKEY* array, UINT* cKeys)
|
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys)
|
||||||
{
|
{
|
||||||
if (*cKeys >= 16)
|
if (*cKeys >= 16)
|
||||||
return;
|
return ERROR_MORE_DATA;
|
||||||
|
|
||||||
HKEY hkey;
|
HKEY hkey;
|
||||||
LSTATUS result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ | KEY_QUERY_VALUE, &hkey);
|
LSTATUS result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ | KEY_QUERY_VALUE, &hkey);
|
||||||
if (result != ERROR_SUCCESS)
|
if (result == ERROR_SUCCESS)
|
||||||
return;
|
{
|
||||||
|
array[*cKeys] = hkey;
|
||||||
array[*cKeys] = hkey;
|
*cKeys += 1;
|
||||||
*cKeys += 1;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys)
|
void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array, UINT* cKeys)
|
||||||
{
|
{
|
||||||
|
// This function opens the association array keys in canonical order for filesystem items.
|
||||||
|
// The order is documented: learn.microsoft.com/en-us/windows/win32/shell/fa-associationarray
|
||||||
|
|
||||||
|
ASSERT(cidl >= 1 && apidl);
|
||||||
|
PCUITEMID_CHILD pidl = apidl[0];
|
||||||
if (_ILIsValue(pidl))
|
if (_ILIsValue(pidl))
|
||||||
{
|
{
|
||||||
|
WCHAR buf[MAX_PATH];
|
||||||
|
PWSTR name;
|
||||||
FileStructW* pFileData = _ILGetFileStructW(pidl);
|
FileStructW* pFileData = _ILGetFileStructW(pidl);
|
||||||
LPWSTR extension = PathFindExtension(pFileData->wszName);
|
if (pFileData)
|
||||||
|
{
|
||||||
|
name = pFileData->wszName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ILSimpleGetTextW(pidl, buf, _countof(buf));
|
||||||
|
name = buf;
|
||||||
|
}
|
||||||
|
LPCWSTR extension = PathFindExtension(name);
|
||||||
|
|
||||||
if (extension)
|
if (extension)
|
||||||
{
|
{
|
||||||
AddClassKeyToArray(extension, array, cKeys);
|
WCHAR wszClass[MAX_PATH], wszSFA[23 + _countof(wszClass)];
|
||||||
|
|
||||||
WCHAR wszClass[MAX_PATH], wszClass2[MAX_PATH];
|
|
||||||
DWORD dwSize = sizeof(wszClass);
|
DWORD dwSize = sizeof(wszClass);
|
||||||
if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS)
|
if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) != ERROR_SUCCESS ||
|
||||||
|
!*wszClass || AddClassKeyToArray(wszClass, array, cKeys) != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
swprintf(wszClass2, L"%s//%s", extension, wszClass);
|
// Only add the extension key if the ProgId is not valid
|
||||||
|
AddClassKeyToArray(extension, array, cKeys);
|
||||||
|
|
||||||
AddClassKeyToArray(wszClass, array, cKeys);
|
// "Open With" becomes the default when there are no verbs in the above keys
|
||||||
AddClassKeyToArray(wszClass2, array, cKeys);
|
if (cidl == 1)
|
||||||
|
AddClassKeyToArray(L"Unknown", array, cKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
swprintf(wszClass2, L"SystemFileAssociations//%s", extension);
|
swprintf(wszSFA, L"SystemFileAssociations\\%s", extension);
|
||||||
AddClassKeyToArray(wszClass2, array, cKeys);
|
AddClassKeyToArray(wszSFA, array, cKeys);
|
||||||
|
|
||||||
|
dwSize = sizeof(wszClass);
|
||||||
if (RegGetValueW(HKEY_CLASSES_ROOT, extension, L"PerceivedType ", RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS)
|
if (RegGetValueW(HKEY_CLASSES_ROOT, extension, L"PerceivedType ", RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
swprintf(wszClass2, L"SystemFileAssociations//%s", wszClass);
|
swprintf(wszSFA, L"SystemFileAssociations\\%s", wszClass);
|
||||||
AddClassKeyToArray(wszClass2, array, cKeys);
|
AddClassKeyToArray(wszSFA, array, cKeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
|
|
||||||
AddClassKeyToArray(L"*", array, cKeys);
|
AddClassKeyToArray(L"*", array, cKeys);
|
||||||
|
AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
|
||||||
}
|
}
|
||||||
else if (_ILIsFolder(pidl))
|
else if (_ILIsFolder(pidl))
|
||||||
{
|
{
|
||||||
|
// FIXME: Directory > Folder > AFO is the correct order and it's
|
||||||
|
// the order Windows reports in its undocumented association array
|
||||||
|
// but it is somehow not the order Windows adds the items to its menu!
|
||||||
|
// Until the correct algorithm in CDefaultContextMenu can be determined,
|
||||||
|
// we add the folder keys in "menu order".
|
||||||
|
AddClassKeyToArray(L"Folder", array, cKeys);
|
||||||
AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
|
AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
|
||||||
AddClassKeyToArray(L"Directory", array, cKeys);
|
AddClassKeyToArray(L"Directory", array, cKeys);
|
||||||
AddClassKeyToArray(L"Folder", array, cKeys);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue