Skip to content

Commit 8107ff8

Browse files
authored
[SHELL32][SHELL32_APITEST] Consolidate file type description handling (reactos#7485)
- Fixes the case where an extension exists in HKCR but has no ProgId (half of CORE-19355) - Fixes some cases where Wine hardcoded "File and "... file" strings are used instead of localized strings in SHGetFileInfo.
1 parent 997b179 commit 8107ff8

File tree

12 files changed

+288
-166
lines changed

12 files changed

+288
-166
lines changed

dll/win32/shell32/CQueryAssociations.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,56 @@
2222

2323
WINE_DEFAULT_DEBUG_CHANNEL(shell);
2424

25+
EXTERN_C HRESULT SHELL32_AssocGetFSDirectoryDescription(PWSTR Buf, UINT cchBuf)
26+
{
27+
static WCHAR cache[33] = {};
28+
if (!*cache)
29+
LoadStringW(shell32_hInstance, IDS_DIRECTORY, cache, _countof(cache));
30+
return StringCchCopyW(Buf, cchBuf, cache);
31+
}
32+
33+
static HRESULT GetExtensionDefaultDescription(PCWSTR DotExt, PWSTR Buf, UINT cchBuf)
34+
{
35+
static WCHAR fmt[33] = {};
36+
if (!*fmt)
37+
LoadStringW(shell32_hInstance, IDS_ANY_FILE, fmt, _countof(fmt));
38+
return StringCchPrintfW(Buf, cchBuf, fmt, DotExt);
39+
}
40+
41+
static HRESULT SHELL32_AssocGetExtensionDescription(PCWSTR DotExt, PWSTR Buf, UINT cchBuf)
42+
{
43+
HRESULT hr;
44+
if (!DotExt[0] || (!DotExt[1] && DotExt[0] == '.'))
45+
{
46+
if (SUCCEEDED(hr = GetExtensionDefaultDescription(L"", Buf, cchBuf)))
47+
StrTrimW(Buf, L" -"); // Remove the empty %s so we are left with "File"
48+
return hr;
49+
}
50+
HKEY hKey;
51+
if (SUCCEEDED(hr = HCR_GetProgIdKeyOfExtension(DotExt, &hKey, TRUE)))
52+
{
53+
DWORD err = RegLoadMUIStringW(hKey, L"FriendlyTypeName", Buf, cchBuf, NULL, 0, NULL);
54+
if (err && hr == S_OK) // ProgId default value fallback (but not if we only have a .ext key)
55+
{
56+
DWORD cb = cchBuf * sizeof(*Buf);
57+
err = RegGetValueW(hKey, NULL, NULL, RRF_RT_REG_SZ, NULL, Buf, &cb);
58+
}
59+
RegCloseKey(hKey);
60+
if (!err)
61+
return err;
62+
}
63+
// No information in the registry, default to "UPPERCASEEXT File"
64+
WCHAR ext[MAX_PATH + 33];
65+
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, ++DotExt, -1, ext, _countof(ext)))
66+
DotExt = ext;
67+
return GetExtensionDefaultDescription(DotExt, Buf, cchBuf);
68+
}
69+
70+
EXTERN_C HRESULT SHELL32_AssocGetFileDescription(PCWSTR Name, PWSTR Buf, UINT cchBuf)
71+
{
72+
return SHELL32_AssocGetExtensionDescription(PathFindExtensionW(Name), Buf, cchBuf);
73+
}
74+
2575
/**************************************************************************
2676
* IQueryAssociations
2777
*

dll/win32/shell32/dialogs/filetypes.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ typedef struct _FILE_TYPE_GLOBALS
8989
HICON hDefExtIconSmall;
9090
HBITMAP hOpenWithImage;
9191
HANDLE hHeap;
92-
WCHAR DefExtTypeNameFmt[TYPENAME_CCHMAX];
9392
WCHAR NoneString[42];
9493
INT8 SortCol, SortReverse;
9594
UINT Restricted;
@@ -298,12 +297,6 @@ GetTypeName(PFILE_TYPE_ENTRY Entry, PFILE_TYPE_GLOBALS pG)
298297
{
299298
StringCchCopyW(Entry->FileDescription, _countof(Entry->FileDescription), fi.szTypeName);
300299
}
301-
else
302-
{
303-
// FIXME: Remove this hack when SHGetFileInfo is able to handle extensions without a ProgId (.ASM etc)
304-
StringCchPrintfW(Entry->FileDescription, _countof(Entry->FileDescription),
305-
pG->DefExtTypeNameFmt, &Entry->FileExtension[1]);
306-
}
307300
}
308301
else
309302
{
@@ -1773,12 +1766,6 @@ FileTypesDlg_Initialize(HWND hwndDlg)
17731766
pG->himlSmall = ImageList_Create(pG->IconSize, pG->IconSize, ILC_COLOR32 | ILC_MASK, 256, 20);
17741767
pG->hHeap = GetProcessHeap();
17751768

1776-
if (!LoadStringW(shell32_hInstance, IDS_ANY_FILE,
1777-
pG->DefExtTypeNameFmt, _countof(pG->DefExtTypeNameFmt)))
1778-
{
1779-
LPCWSTR fallback = L"%s File"; // Default to English
1780-
StringCchCopyW(pG->DefExtTypeNameFmt, _countof(pG->DefExtTypeNameFmt), fallback);
1781-
}
17821769
pG->NoneString[0] = UNICODE_NULL;
17831770
LoadStringW(shell32_hInstance, IDS_NONE, pG->NoneString, _countof(pG->NoneString));
17841771

dll/win32/shell32/folders/CFSFolder.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ WINE_DEFAULT_DEBUG_CHANNEL (shell);
1414

1515
static HRESULT SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, LPCWSTR KeyName, CLSID* pclsidFolder);
1616

17+
static BOOL ItemIsFolder(PCUITEMID_CHILD pidl)
18+
{
19+
const BYTE mask = PT_FS | PT_FS_FOLDER_FLAG | PT_FS_FILE_FLAG;
20+
const BYTE type = _ILGetType(pidl);
21+
return (type & mask) == (PT_FS | PT_FS_FOLDER_FLAG) || (type == PT_FS && ILGetNext(pidl));
22+
}
23+
1724
static LPCWSTR GetItemFileName(PCUITEMID_CHILD pidl, LPWSTR Buf, UINT cchMax)
1825
{
1926
FileStructW* pDataW = _ILGetFileStructW(pidl);
@@ -34,6 +41,23 @@ static BOOL IsRealItem(const ITEMIDLIST &idl)
3441
return fsitem.dwFileSize | fsitem.uFileDate;
3542
}
3643

44+
static void GetItemDescription(PCUITEMID_CHILD pidl, LPWSTR Buf, UINT cchMax)
45+
{
46+
HRESULT hr = E_FAIL;
47+
if (ItemIsFolder(pidl))
48+
{
49+
hr = SHELL32_AssocGetFSDirectoryDescription(Buf, cchMax);
50+
}
51+
else
52+
{
53+
WCHAR temp[MAX_PATH];
54+
LPCWSTR name = GetItemFileName(pidl, temp, _countof(temp));
55+
hr = SHELL32_AssocGetFileDescription(name ? name : L"", Buf, cchMax);
56+
}
57+
if (FAILED(hr) && cchMax)
58+
Buf[0] = UNICODE_NULL;
59+
}
60+
3761
static HKEY OpenKeyFromFileType(LPCWSTR pExtension, LPCWSTR KeyName)
3862
{
3963
HKEY hkey;
@@ -1640,18 +1664,23 @@ HRESULT WINAPI CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl,
16401664
{
16411665
hr = S_OK;
16421666
psd->str.uType = STRRET_WSTR;
1643-
psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
1667+
if (iColumn != SHFSF_COL_NAME)
1668+
{
1669+
psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
1670+
if (!psd->str.pOleStr)
1671+
return E_OUTOFMEMORY;
1672+
}
16441673
/* the data from the pidl */
16451674
switch (iColumn)
16461675
{
16471676
case SHFSF_COL_NAME:
1648-
hr = GetDisplayNameOf (pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1677+
hr = GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
16491678
break;
16501679
case SHFSF_COL_SIZE:
16511680
_ILGetFileSize(pidl, psd->str.pOleStr, MAX_PATH);
16521681
break;
16531682
case SHFSF_COL_TYPE:
1654-
_ILGetFileType(pidl, psd->str.pOleStr, MAX_PATH);
1683+
GetItemDescription(pidl, psd->str.pOleStr, MAX_PATH);
16551684
break;
16561685
case SHFSF_COL_MDATE:
16571686
_ILGetFileDate(pidl, psd->str.pOleStr, MAX_PATH);

dll/win32/shell32/wine/classes.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,40 @@
4444

4545
WINE_DEFAULT_DEBUG_CHANNEL(shell);
4646

47-
#define MAX_EXTENSION_LENGTH 20
47+
#define MAX_EXTENSION_LENGTH 20 // FIXME: The limit is 254?
48+
49+
static LONG GetRegString(HKEY hKey, PCWSTR SubKey, PCWSTR Name, PWSTR Buffer, UINT cchBuf)
50+
{
51+
DWORD cb = sizeof(*Buffer) * cchBuf;
52+
return RegGetValueW(hKey, SubKey, Name, RRF_RT_REG_SZ, NULL, Buffer, &cb);
53+
}
54+
55+
HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback)
56+
{
57+
LONG err;
58+
WCHAR ext[max(1 + MAX_EXTENSION_LENGTH + 1, MAX_PATH)];
59+
WCHAR progid[MAX_PATH];
60+
if (szExtension[0] != '.')
61+
{
62+
ext[0] = '.';
63+
lstrcpynW(ext + 1, szExtension, _countof(ext) - 1);
64+
szExtension = ext;
65+
}
66+
err = GetRegString(HKEY_CLASSES_ROOT, szExtension, NULL, progid, _countof(progid));
67+
if (!err && progid[0] != UNICODE_NULL)
68+
{
69+
err = RegOpenKeyExW(HKEY_CLASSES_ROOT, progid, 0, KEY_READ, phKey);
70+
if (!err)
71+
return err; /* A real ProgId key, return S_OK */
72+
}
73+
if (AllowFallback)
74+
{
75+
err = RegOpenKeyExW(HKEY_CLASSES_ROOT, szExtension, 0, KEY_READ, phKey);
76+
if (!err)
77+
return S_FALSE;
78+
}
79+
return HRESULT_FROM_WIN32(err);
80+
}
4881

4982
BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot)
5083
{
@@ -67,14 +100,6 @@ BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL
67100
return FALSE;
68101
}
69102

70-
#ifdef __REACTOS__
71-
if (!RegLoadMUIStringW(hkey, L"FriendlyTypeName", szFileType, len, NULL, 0, NULL))
72-
{
73-
RegCloseKey(hkey);
74-
return TRUE;
75-
}
76-
#endif
77-
78103
if (RegQueryValueW(hkey, NULL, szFileType, &len))
79104
{
80105
RegCloseKey(hkey);
@@ -109,14 +134,6 @@ BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bP
109134
return FALSE;
110135
}
111136

112-
#ifdef __REACTOS__
113-
if (!RegLoadMUIStringA(hkey, "FriendlyTypeName", szFileType, len, NULL, 0, NULL))
114-
{
115-
RegCloseKey(hkey);
116-
return TRUE;
117-
}
118-
#endif
119-
120137
if (RegQueryValueA(hkey, NULL, szFileType, &len))
121138
{
122139
RegCloseKey(hkey);

dll/win32/shell32/wine/pidl.c

Lines changed: 8 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,14 @@ static HRESULT _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile,
11831183
return ret;
11841184
}
11851185

1186+
LPITEMIDLIST SHELL32_CreateSimpleIDListFromPath(LPCWSTR pszPath, DWORD dwAttributes)
1187+
{
1188+
WIN32_FIND_DATAW data = { dwAttributes };
1189+
LPITEMIDLIST pidl = NULL;
1190+
_ILParsePathW(pszPath, &data, TRUE, &pidl, NULL);
1191+
return pidl;
1192+
}
1193+
11861194
/*************************************************************************
11871195
* SHSimpleIDListFromPath [SHELL32.162]
11881196
*
@@ -2583,59 +2591,6 @@ BOOL _ILGetExtension(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
25832591
return TRUE;
25842592
}
25852593

2586-
/*************************************************************************
2587-
* _ILGetFileType
2588-
*
2589-
* Given the ItemIdList, get the file type description
2590-
*
2591-
* PARAMS
2592-
* pidl [I] The ItemIDList (simple)
2593-
* pOut [I] The buffer to save the result
2594-
* uOutsize [I] The size of the buffer
2595-
*
2596-
* RETURNS
2597-
* nothing
2598-
*
2599-
* NOTES
2600-
* This function copies as much as possible into the buffer.
2601-
*/
2602-
void _ILGetFileType(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
2603-
{
2604-
WCHAR sType[64], sTemp[64];
2605-
2606-
if(_ILIsValue(pidl))
2607-
{
2608-
if(uOutSize > 0)
2609-
pOut[0] = 0;
2610-
if (_ILGetExtension(pidl, sType, _countof(sType)))
2611-
{
2612-
if (HCR_MapTypeToValueW(sType, sTemp, _countof(sTemp), TRUE))
2613-
{
2614-
/* retrieve description */
2615-
if (HCR_MapTypeToValueW(sTemp, pOut, uOutSize, FALSE))
2616-
return;
2617-
}
2618-
2619-
/* display Ext-file as description */
2620-
CharUpperW(sType);
2621-
/* load localized file string */
2622-
sTemp[0] = UNICODE_NULL;
2623-
if (LoadStringW(shell32_hInstance, IDS_ANY_FILE, sTemp, _countof(sTemp)))
2624-
{
2625-
sTemp[_countof(sTemp) - 1] = UNICODE_NULL;
2626-
StringCchPrintfW(pOut, uOutSize, sTemp, sType);
2627-
}
2628-
}
2629-
}
2630-
else
2631-
{
2632-
pOut[0] = UNICODE_NULL;
2633-
LoadStringW(shell32_hInstance, IDS_DIRECTORY, pOut, uOutSize);
2634-
/* make sure its null terminated */
2635-
pOut[uOutSize - 1] = UNICODE_NULL;
2636-
}
2637-
}
2638-
26392594
/*************************************************************************
26402595
* _ILGetFileAttributes
26412596
*

dll/win32/shell32/wine/pidl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,6 @@ DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DEC
246246
BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
247247
DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
248248
BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
249-
void _ILGetFileType (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
250249
DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
251250
BOOL _ILGetFileDateTime (LPCITEMIDLIST pidl, FILETIME *ft) DECLSPEC_HIDDEN;
252251
DWORD _ILGetDrive (LPCITEMIDLIST, LPWSTR, UINT) DECLSPEC_HIDDEN;
@@ -291,6 +290,7 @@ LPITEMIDLIST _ILCreateGuidFromStrW(LPCWSTR szGUID) DECLSPEC_HIDDEN;
291290
LPITEMIDLIST _ILCreateDesktop (void) DECLSPEC_HIDDEN;
292291
LPITEMIDLIST _ILCreateFromFindDataW(const WIN32_FIND_DATAW *stffile) DECLSPEC_HIDDEN;
293292
HRESULT _ILCreateFromPathW (LPCWSTR szPath, LPITEMIDLIST* ppidl) DECLSPEC_HIDDEN;
293+
LPITEMIDLIST SHELL32_CreateSimpleIDListFromPath(LPCWSTR pszPath, DWORD dwAttributes);
294294

295295
/* Other helpers */
296296
LPITEMIDLIST _ILCreateMyComputer (void) DECLSPEC_HIDDEN;

0 commit comments

Comments
 (0)