mirror of
https://github.com/reactos/reactos.git
synced 2024-11-23 03:23:34 +08:00
[SHELL32][SHELL32_APITEST] Consolidate file type description handling (#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.
This commit is contained in:
parent
997b1797f4
commit
8107ff8636
@ -22,6 +22,56 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
EXTERN_C HRESULT SHELL32_AssocGetFSDirectoryDescription(PWSTR Buf, UINT cchBuf)
|
||||
{
|
||||
static WCHAR cache[33] = {};
|
||||
if (!*cache)
|
||||
LoadStringW(shell32_hInstance, IDS_DIRECTORY, cache, _countof(cache));
|
||||
return StringCchCopyW(Buf, cchBuf, cache);
|
||||
}
|
||||
|
||||
static HRESULT GetExtensionDefaultDescription(PCWSTR DotExt, PWSTR Buf, UINT cchBuf)
|
||||
{
|
||||
static WCHAR fmt[33] = {};
|
||||
if (!*fmt)
|
||||
LoadStringW(shell32_hInstance, IDS_ANY_FILE, fmt, _countof(fmt));
|
||||
return StringCchPrintfW(Buf, cchBuf, fmt, DotExt);
|
||||
}
|
||||
|
||||
static HRESULT SHELL32_AssocGetExtensionDescription(PCWSTR DotExt, PWSTR Buf, UINT cchBuf)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (!DotExt[0] || (!DotExt[1] && DotExt[0] == '.'))
|
||||
{
|
||||
if (SUCCEEDED(hr = GetExtensionDefaultDescription(L"", Buf, cchBuf)))
|
||||
StrTrimW(Buf, L" -"); // Remove the empty %s so we are left with "File"
|
||||
return hr;
|
||||
}
|
||||
HKEY hKey;
|
||||
if (SUCCEEDED(hr = HCR_GetProgIdKeyOfExtension(DotExt, &hKey, TRUE)))
|
||||
{
|
||||
DWORD err = RegLoadMUIStringW(hKey, L"FriendlyTypeName", Buf, cchBuf, NULL, 0, NULL);
|
||||
if (err && hr == S_OK) // ProgId default value fallback (but not if we only have a .ext key)
|
||||
{
|
||||
DWORD cb = cchBuf * sizeof(*Buf);
|
||||
err = RegGetValueW(hKey, NULL, NULL, RRF_RT_REG_SZ, NULL, Buf, &cb);
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
if (!err)
|
||||
return err;
|
||||
}
|
||||
// No information in the registry, default to "UPPERCASEEXT File"
|
||||
WCHAR ext[MAX_PATH + 33];
|
||||
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, ++DotExt, -1, ext, _countof(ext)))
|
||||
DotExt = ext;
|
||||
return GetExtensionDefaultDescription(DotExt, Buf, cchBuf);
|
||||
}
|
||||
|
||||
EXTERN_C HRESULT SHELL32_AssocGetFileDescription(PCWSTR Name, PWSTR Buf, UINT cchBuf)
|
||||
{
|
||||
return SHELL32_AssocGetExtensionDescription(PathFindExtensionW(Name), Buf, cchBuf);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* IQueryAssociations
|
||||
*
|
||||
|
@ -89,7 +89,6 @@ typedef struct _FILE_TYPE_GLOBALS
|
||||
HICON hDefExtIconSmall;
|
||||
HBITMAP hOpenWithImage;
|
||||
HANDLE hHeap;
|
||||
WCHAR DefExtTypeNameFmt[TYPENAME_CCHMAX];
|
||||
WCHAR NoneString[42];
|
||||
INT8 SortCol, SortReverse;
|
||||
UINT Restricted;
|
||||
@ -298,12 +297,6 @@ GetTypeName(PFILE_TYPE_ENTRY Entry, PFILE_TYPE_GLOBALS pG)
|
||||
{
|
||||
StringCchCopyW(Entry->FileDescription, _countof(Entry->FileDescription), fi.szTypeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Remove this hack when SHGetFileInfo is able to handle extensions without a ProgId (.ASM etc)
|
||||
StringCchPrintfW(Entry->FileDescription, _countof(Entry->FileDescription),
|
||||
pG->DefExtTypeNameFmt, &Entry->FileExtension[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1773,12 +1766,6 @@ FileTypesDlg_Initialize(HWND hwndDlg)
|
||||
pG->himlSmall = ImageList_Create(pG->IconSize, pG->IconSize, ILC_COLOR32 | ILC_MASK, 256, 20);
|
||||
pG->hHeap = GetProcessHeap();
|
||||
|
||||
if (!LoadStringW(shell32_hInstance, IDS_ANY_FILE,
|
||||
pG->DefExtTypeNameFmt, _countof(pG->DefExtTypeNameFmt)))
|
||||
{
|
||||
LPCWSTR fallback = L"%s File"; // Default to English
|
||||
StringCchCopyW(pG->DefExtTypeNameFmt, _countof(pG->DefExtTypeNameFmt), fallback);
|
||||
}
|
||||
pG->NoneString[0] = UNICODE_NULL;
|
||||
LoadStringW(shell32_hInstance, IDS_NONE, pG->NoneString, _countof(pG->NoneString));
|
||||
|
||||
|
@ -14,6 +14,13 @@ WINE_DEFAULT_DEBUG_CHANNEL (shell);
|
||||
|
||||
static HRESULT SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, LPCWSTR KeyName, CLSID* pclsidFolder);
|
||||
|
||||
static BOOL ItemIsFolder(PCUITEMID_CHILD pidl)
|
||||
{
|
||||
const BYTE mask = PT_FS | PT_FS_FOLDER_FLAG | PT_FS_FILE_FLAG;
|
||||
const BYTE type = _ILGetType(pidl);
|
||||
return (type & mask) == (PT_FS | PT_FS_FOLDER_FLAG) || (type == PT_FS && ILGetNext(pidl));
|
||||
}
|
||||
|
||||
static LPCWSTR GetItemFileName(PCUITEMID_CHILD pidl, LPWSTR Buf, UINT cchMax)
|
||||
{
|
||||
FileStructW* pDataW = _ILGetFileStructW(pidl);
|
||||
@ -34,6 +41,23 @@ static BOOL IsRealItem(const ITEMIDLIST &idl)
|
||||
return fsitem.dwFileSize | fsitem.uFileDate;
|
||||
}
|
||||
|
||||
static void GetItemDescription(PCUITEMID_CHILD pidl, LPWSTR Buf, UINT cchMax)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
if (ItemIsFolder(pidl))
|
||||
{
|
||||
hr = SHELL32_AssocGetFSDirectoryDescription(Buf, cchMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR temp[MAX_PATH];
|
||||
LPCWSTR name = GetItemFileName(pidl, temp, _countof(temp));
|
||||
hr = SHELL32_AssocGetFileDescription(name ? name : L"", Buf, cchMax);
|
||||
}
|
||||
if (FAILED(hr) && cchMax)
|
||||
Buf[0] = UNICODE_NULL;
|
||||
}
|
||||
|
||||
static HKEY OpenKeyFromFileType(LPCWSTR pExtension, LPCWSTR KeyName)
|
||||
{
|
||||
HKEY hkey;
|
||||
@ -1640,18 +1664,23 @@ HRESULT WINAPI CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl,
|
||||
{
|
||||
hr = S_OK;
|
||||
psd->str.uType = STRRET_WSTR;
|
||||
psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
|
||||
if (iColumn != SHFSF_COL_NAME)
|
||||
{
|
||||
psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
|
||||
if (!psd->str.pOleStr)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
/* the data from the pidl */
|
||||
switch (iColumn)
|
||||
{
|
||||
case SHFSF_COL_NAME:
|
||||
hr = GetDisplayNameOf (pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
|
||||
hr = GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
|
||||
break;
|
||||
case SHFSF_COL_SIZE:
|
||||
_ILGetFileSize(pidl, psd->str.pOleStr, MAX_PATH);
|
||||
break;
|
||||
case SHFSF_COL_TYPE:
|
||||
_ILGetFileType(pidl, psd->str.pOleStr, MAX_PATH);
|
||||
GetItemDescription(pidl, psd->str.pOleStr, MAX_PATH);
|
||||
break;
|
||||
case SHFSF_COL_MDATE:
|
||||
_ILGetFileDate(pidl, psd->str.pOleStr, MAX_PATH);
|
||||
|
@ -44,7 +44,40 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
#define MAX_EXTENSION_LENGTH 20
|
||||
#define MAX_EXTENSION_LENGTH 20 // FIXME: The limit is 254?
|
||||
|
||||
static LONG GetRegString(HKEY hKey, PCWSTR SubKey, PCWSTR Name, PWSTR Buffer, UINT cchBuf)
|
||||
{
|
||||
DWORD cb = sizeof(*Buffer) * cchBuf;
|
||||
return RegGetValueW(hKey, SubKey, Name, RRF_RT_REG_SZ, NULL, Buffer, &cb);
|
||||
}
|
||||
|
||||
HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback)
|
||||
{
|
||||
LONG err;
|
||||
WCHAR ext[max(1 + MAX_EXTENSION_LENGTH + 1, MAX_PATH)];
|
||||
WCHAR progid[MAX_PATH];
|
||||
if (szExtension[0] != '.')
|
||||
{
|
||||
ext[0] = '.';
|
||||
lstrcpynW(ext + 1, szExtension, _countof(ext) - 1);
|
||||
szExtension = ext;
|
||||
}
|
||||
err = GetRegString(HKEY_CLASSES_ROOT, szExtension, NULL, progid, _countof(progid));
|
||||
if (!err && progid[0] != UNICODE_NULL)
|
||||
{
|
||||
err = RegOpenKeyExW(HKEY_CLASSES_ROOT, progid, 0, KEY_READ, phKey);
|
||||
if (!err)
|
||||
return err; /* A real ProgId key, return S_OK */
|
||||
}
|
||||
if (AllowFallback)
|
||||
{
|
||||
err = RegOpenKeyExW(HKEY_CLASSES_ROOT, szExtension, 0, KEY_READ, phKey);
|
||||
if (!err)
|
||||
return S_FALSE;
|
||||
}
|
||||
return HRESULT_FROM_WIN32(err);
|
||||
}
|
||||
|
||||
BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot)
|
||||
{
|
||||
@ -67,14 +100,6 @@ BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
if (!RegLoadMUIStringW(hkey, L"FriendlyTypeName", szFileType, len, NULL, 0, NULL))
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (RegQueryValueW(hkey, NULL, szFileType, &len))
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
@ -109,14 +134,6 @@ BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bP
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
if (!RegLoadMUIStringA(hkey, "FriendlyTypeName", szFileType, len, NULL, 0, NULL))
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (RegQueryValueA(hkey, NULL, szFileType, &len))
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
|
@ -1183,6 +1183,14 @@ static HRESULT _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile,
|
||||
return ret;
|
||||
}
|
||||
|
||||
LPITEMIDLIST SHELL32_CreateSimpleIDListFromPath(LPCWSTR pszPath, DWORD dwAttributes)
|
||||
{
|
||||
WIN32_FIND_DATAW data = { dwAttributes };
|
||||
LPITEMIDLIST pidl = NULL;
|
||||
_ILParsePathW(pszPath, &data, TRUE, &pidl, NULL);
|
||||
return pidl;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHSimpleIDListFromPath [SHELL32.162]
|
||||
*
|
||||
@ -2583,59 +2591,6 @@ BOOL _ILGetExtension(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* _ILGetFileType
|
||||
*
|
||||
* Given the ItemIdList, get the file type description
|
||||
*
|
||||
* PARAMS
|
||||
* pidl [I] The ItemIDList (simple)
|
||||
* pOut [I] The buffer to save the result
|
||||
* uOutsize [I] The size of the buffer
|
||||
*
|
||||
* RETURNS
|
||||
* nothing
|
||||
*
|
||||
* NOTES
|
||||
* This function copies as much as possible into the buffer.
|
||||
*/
|
||||
void _ILGetFileType(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
|
||||
{
|
||||
WCHAR sType[64], sTemp[64];
|
||||
|
||||
if(_ILIsValue(pidl))
|
||||
{
|
||||
if(uOutSize > 0)
|
||||
pOut[0] = 0;
|
||||
if (_ILGetExtension(pidl, sType, _countof(sType)))
|
||||
{
|
||||
if (HCR_MapTypeToValueW(sType, sTemp, _countof(sTemp), TRUE))
|
||||
{
|
||||
/* retrieve description */
|
||||
if (HCR_MapTypeToValueW(sTemp, pOut, uOutSize, FALSE))
|
||||
return;
|
||||
}
|
||||
|
||||
/* display Ext-file as description */
|
||||
CharUpperW(sType);
|
||||
/* load localized file string */
|
||||
sTemp[0] = UNICODE_NULL;
|
||||
if (LoadStringW(shell32_hInstance, IDS_ANY_FILE, sTemp, _countof(sTemp)))
|
||||
{
|
||||
sTemp[_countof(sTemp) - 1] = UNICODE_NULL;
|
||||
StringCchPrintfW(pOut, uOutSize, sTemp, sType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pOut[0] = UNICODE_NULL;
|
||||
LoadStringW(shell32_hInstance, IDS_DIRECTORY, pOut, uOutSize);
|
||||
/* make sure its null terminated */
|
||||
pOut[uOutSize - 1] = UNICODE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* _ILGetFileAttributes
|
||||
*
|
||||
|
@ -246,7 +246,6 @@ DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DEC
|
||||
BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
|
||||
DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
|
||||
BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
|
||||
void _ILGetFileType (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
|
||||
DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize) DECLSPEC_HIDDEN;
|
||||
BOOL _ILGetFileDateTime (LPCITEMIDLIST pidl, FILETIME *ft) DECLSPEC_HIDDEN;
|
||||
DWORD _ILGetDrive (LPCITEMIDLIST, LPWSTR, UINT) DECLSPEC_HIDDEN;
|
||||
@ -291,6 +290,7 @@ LPITEMIDLIST _ILCreateGuidFromStrW(LPCWSTR szGUID) DECLSPEC_HIDDEN;
|
||||
LPITEMIDLIST _ILCreateDesktop (void) DECLSPEC_HIDDEN;
|
||||
LPITEMIDLIST _ILCreateFromFindDataW(const WIN32_FIND_DATAW *stffile) DECLSPEC_HIDDEN;
|
||||
HRESULT _ILCreateFromPathW (LPCWSTR szPath, LPITEMIDLIST* ppidl) DECLSPEC_HIDDEN;
|
||||
LPITEMIDLIST SHELL32_CreateSimpleIDListFromPath(LPCWSTR pszPath, DWORD dwAttributes);
|
||||
|
||||
/* Other helpers */
|
||||
LPITEMIDLIST _ILCreateMyComputer (void) DECLSPEC_HIDDEN;
|
||||
|
@ -310,6 +310,28 @@ LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
|
||||
return argv;
|
||||
}
|
||||
|
||||
static HRESULT SHELL_GetDetailsOfToBuffer(IShellFolder *psf, PCUITEMID_CHILD pidl,
|
||||
UINT col, LPWSTR Buf, UINT cchBuf)
|
||||
{
|
||||
IShellFolder2 *psf2;
|
||||
IShellDetails *psd;
|
||||
SHELLDETAILS details;
|
||||
HRESULT hr = IShellFolder_QueryInterface(psf, &IID_IShellFolder2, (void**)&psf2);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IShellFolder2_GetDetailsOf(psf2, pidl, col, &details);
|
||||
IShellFolder2_Release(psf2);
|
||||
}
|
||||
else if (SUCCEEDED(hr = IShellFolder_QueryInterface(psf, &IID_IShellDetails, (void**)&psd)))
|
||||
{
|
||||
hr = IShellDetails_GetDetailsOf(psd, pidl, col, &details);
|
||||
IShellDetails_Release(psd);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
hr = StrRetToStrNW(Buf, cchBuf, &details.str, pidl) ? S_OK : E_FAIL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static DWORD shgfi_get_exe_type(LPCWSTR szFullPath)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
@ -386,17 +408,11 @@ BOOL SHELL_IsShortcut(LPCITEMIDLIST pidlLast)
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (_ILGetExtension(pidlLast, szTemp, _countof(szTemp)) &&
|
||||
HCR_MapTypeToValueW(szTemp, szTemp, _countof(szTemp), TRUE))
|
||||
SUCCEEDED(HCR_GetProgIdKeyOfExtension(szTemp, &keyCls, FALSE)))
|
||||
{
|
||||
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, KEY_QUERY_VALUE, &keyCls))
|
||||
{
|
||||
if (ERROR_SUCCESS == RegQueryValueExW(keyCls, L"IsShortcut", NULL, NULL, NULL, NULL))
|
||||
ret = TRUE;
|
||||
|
||||
RegCloseKey(keyCls);
|
||||
}
|
||||
ret = RegQueryValueExW(keyCls, L"IsShortcut", NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
|
||||
RegCloseKey(keyCls);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -420,7 +436,7 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
|
||||
DWORD dwAttributes = 0;
|
||||
IShellFolder * psfParent = NULL;
|
||||
IExtractIconW * pei = NULL;
|
||||
LPITEMIDLIST pidlLast = NULL, pidl = NULL;
|
||||
LPITEMIDLIST pidlLast = NULL, pidl = NULL, pidlFree = NULL;
|
||||
HRESULT hr = S_OK;
|
||||
BOOL IconNotYetLoaded=TRUE;
|
||||
UINT uGilFlags = 0;
|
||||
@ -453,6 +469,27 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
|
||||
{
|
||||
lstrcpynW(szFullPath, path, MAX_PATH);
|
||||
}
|
||||
|
||||
if ((flags & SHGFI_TYPENAME) && !PathIsRootW(szFullPath))
|
||||
{
|
||||
HRESULT hr2;
|
||||
if (!(flags & SHGFI_USEFILEATTRIBUTES))
|
||||
{
|
||||
dwFileAttributes = GetFileAttributesW(szFullPath);
|
||||
if (dwFileAttributes == INVALID_FILE_ATTRIBUTES)
|
||||
dwFileAttributes = 0;
|
||||
}
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
hr2 = SHELL32_AssocGetFSDirectoryDescription(psfi->szTypeName, _countof(psfi->szTypeName));
|
||||
else
|
||||
hr2 = SHELL32_AssocGetFileDescription(path, psfi->szTypeName, _countof(psfi->szTypeName));
|
||||
if (SUCCEEDED(hr2))
|
||||
{
|
||||
flags &= ~SHGFI_TYPENAME;
|
||||
if (!(flags & ~SHGFI_USEFILEATTRIBUTES))
|
||||
return ret; /* Bail out early if this was our only operation */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -489,31 +526,26 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
|
||||
|
||||
if (flags & SHGFI_PIDL)
|
||||
{
|
||||
pidl = ILClone((LPCITEMIDLIST)path);
|
||||
pidl = (LPITEMIDLIST)path;
|
||||
hr = pidl ? S_OK : E_FAIL;
|
||||
}
|
||||
else if (!(flags & SHGFI_USEFILEATTRIBUTES))
|
||||
else
|
||||
{
|
||||
hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes);
|
||||
}
|
||||
|
||||
if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES))
|
||||
{
|
||||
/* get the parent shellfolder */
|
||||
if (pidl)
|
||||
if (flags & SHGFI_USEFILEATTRIBUTES)
|
||||
{
|
||||
hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent,
|
||||
(LPCITEMIDLIST*)&pidlLast );
|
||||
if (SUCCEEDED(hr))
|
||||
pidlLast = ILClone(pidlLast);
|
||||
else
|
||||
hr = S_OK;
|
||||
ILFree(pidl);
|
||||
pidl = SHELL32_CreateSimpleIDListFromPath(szFullPath, dwFileAttributes);
|
||||
hr = pidl ? S_OK : E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("pidl is null!\n");
|
||||
return FALSE;
|
||||
hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes);
|
||||
}
|
||||
pidlFree = pidl;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = SHBindToParent(pidl, &IID_IShellFolder, (void**)&psfParent, (LPCITEMIDLIST*)&pidlLast);
|
||||
}
|
||||
|
||||
/* get the attributes of the child */
|
||||
@ -523,11 +555,7 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
|
||||
{
|
||||
psfi->dwAttributes = 0xffffffff;
|
||||
}
|
||||
if (psfParent)
|
||||
{
|
||||
IShellFolder_GetAttributesOf(psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
|
||||
&(psfi->dwAttributes));
|
||||
}
|
||||
hr = IShellFolder_GetAttributesOf(psfParent, 1, (LPCITEMIDLIST*)&pidlLast, &psfi->dwAttributes);
|
||||
}
|
||||
|
||||
if (flags & SHGFI_USEFILEATTRIBUTES)
|
||||
@ -541,55 +569,20 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
|
||||
/* get the displayname */
|
||||
if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
|
||||
{
|
||||
if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
|
||||
{
|
||||
lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath));
|
||||
}
|
||||
else if (psfParent)
|
||||
{
|
||||
STRRET str;
|
||||
hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast,
|
||||
SHGDN_INFOLDER, &str);
|
||||
StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
|
||||
}
|
||||
STRRET str;
|
||||
psfi->szDisplayName[0] = UNICODE_NULL;
|
||||
hr = IShellFolder_GetDisplayNameOf(psfParent, pidlLast, SHGDN_INFOLDER, &str);
|
||||
if (SUCCEEDED(hr))
|
||||
StrRetToStrNW(psfi->szDisplayName, _countof(psfi->szDisplayName), &str, pidlLast);
|
||||
}
|
||||
|
||||
/* get the type name */
|
||||
if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
|
||||
{
|
||||
if (!(flags & SHGFI_USEFILEATTRIBUTES) || (flags & SHGFI_PIDL))
|
||||
{
|
||||
_ILGetFileType(pidlLast, psfi->szTypeName, _countof(psfi->szTypeName));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
strcatW (psfi->szTypeName, L"Folder");
|
||||
else
|
||||
{
|
||||
WCHAR sTemp[64];
|
||||
|
||||
lstrcpyW(sTemp,PathFindExtensionW(szFullPath));
|
||||
if (sTemp[0] == 0 || (sTemp[0] == '.' && sTemp[1] == 0))
|
||||
{
|
||||
/* "name" or "name." => "File" */
|
||||
lstrcpynW (psfi->szTypeName, L"File", 64);
|
||||
}
|
||||
else if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) &&
|
||||
HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE )))
|
||||
{
|
||||
if (sTemp[0])
|
||||
{
|
||||
lstrcpynW (psfi->szTypeName, sTemp, 64);
|
||||
strcatW (psfi->szTypeName, L" file");
|
||||
}
|
||||
else
|
||||
{
|
||||
lstrcpynW (psfi->szTypeName, L"File", 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* FIXME: Use IShellFolder2::GetDetailsEx */
|
||||
UINT col = _ILIsDrive(pidlLast) ? 1 : 2; /* SHFSF_COL_TYPE */
|
||||
psfi->szTypeName[0] = UNICODE_NULL;
|
||||
hr = SHELL_GetDetailsOfToBuffer(psfParent, pidlLast, col, psfi->szTypeName, _countof(psfi->szTypeName));
|
||||
}
|
||||
|
||||
/* ### icons ###*/
|
||||
@ -757,12 +750,11 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
|
||||
|
||||
if (psfParent)
|
||||
IShellFolder_Release(psfParent);
|
||||
SHFree(pidlFree);
|
||||
|
||||
if (hr != S_OK)
|
||||
ret = FALSE;
|
||||
|
||||
SHFree(pidlLast);
|
||||
|
||||
TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n",
|
||||
psfi->hIcon, psfi->iIcon, psfi->dwAttributes,
|
||||
debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret);
|
||||
|
@ -46,6 +46,7 @@ BOOL PidlToSicIndex (IShellFolder * sh, LPCITEMIDLIST pidl, BOOL bBigIcon, UINT
|
||||
INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Classes Root */
|
||||
HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback);
|
||||
BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot) DECLSPEC_HIDDEN;
|
||||
BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) DECLSPEC_HIDDEN;
|
||||
BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) DECLSPEC_HIDDEN;
|
||||
@ -67,6 +68,12 @@ BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len) DECLSPEC_HIDDEN;
|
||||
|
||||
BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD dwAttributes) DECLSPEC_HIDDEN;
|
||||
|
||||
/* File associations */
|
||||
#define SHELL32_AssocGetFolderDescription SHELL32_AssocGetFSDirectoryDescription
|
||||
HRESULT SHELL32_AssocGetFSDirectoryDescription(PWSTR Buf, UINT cchBuf);
|
||||
HRESULT SHELL32_AssocGetFileDescription(PCWSTR Name, PWSTR Buf, UINT cchBuf);
|
||||
|
||||
|
||||
DWORD WINAPI ParseFieldA(LPCSTR src, DWORD nField, LPSTR dst, DWORD len) DECLSPEC_HIDDEN;
|
||||
DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len) DECLSPEC_HIDDEN;
|
||||
|
||||
|
@ -38,6 +38,7 @@ list(APPEND SOURCE
|
||||
ShellExecuteEx.cpp
|
||||
ShellExecuteW.cpp
|
||||
ShellHook.cpp
|
||||
ShellInfo.cpp
|
||||
ShellState.cpp
|
||||
SHGetAttributesFromDataObject.cpp
|
||||
SHLimitInputEdit.cpp
|
||||
|
@ -148,6 +148,12 @@ START_TEST(SHSimpleIDListFromPath)
|
||||
ok_long(item->mkid.abID[0] & 0x70, 0x20); // Something in My Computer
|
||||
ok_char(item->mkid.abID[1] | 32, 'x' | 32); // x:
|
||||
}
|
||||
|
||||
LPITEMIDLIST pidl;
|
||||
ok_int((pidl = SHSimpleIDListFromPath(L"c:")) != NULL, TRUE);
|
||||
ILFree(pidl);
|
||||
ok_int((pidl = SHSimpleIDListFromPath(L"c:\\")) != NULL, TRUE);
|
||||
ILFree(pidl);
|
||||
}
|
||||
|
||||
START_TEST(ILCreateFromPath)
|
||||
|
76
modules/rostests/apitests/shell32/ShellInfo.cpp
Normal file
76
modules/rostests/apitests/shell32/ShellInfo.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* PROJECT: ReactOS API tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Test for SHGetFileInfo
|
||||
* COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
|
||||
*/
|
||||
|
||||
#include "shelltest.h"
|
||||
#include <shellutils.h>
|
||||
|
||||
#define UNIQUEEXT L"ABC123XYZ"
|
||||
#define my_ok_all_flags(val, flags) ok_eq_hex((val) & (flags), (flags))
|
||||
|
||||
static DWORD_PTR SHGFI(PCWSTR Path, SHFILEINFOW &Info, UINT Flags, UINT Attributes = 0)
|
||||
{
|
||||
return SHGetFileInfoW(Path, Attributes, &Info, sizeof(Info), Flags);
|
||||
}
|
||||
|
||||
static DWORD_PTR SHGFI(LPCITEMIDLIST Pidl, SHFILEINFOW &Info, UINT Flags, UINT Attributes = 0)
|
||||
{
|
||||
return SHGFI((PCWSTR)Pidl, Info, Flags | SHGFI_PIDL, Attributes);
|
||||
}
|
||||
|
||||
START_TEST(SHGetFileInfo)
|
||||
{
|
||||
CCoInit ComInit;
|
||||
LPITEMIDLIST pidl;
|
||||
SHFILEINFOW info;
|
||||
UINT flags;
|
||||
WCHAR buf[MAX_PATH];
|
||||
|
||||
ok_int(SHGFI((PCWSTR)NULL, info, 0), FALSE);
|
||||
ok_int(SHGFI((PCWSTR)NULL, info, SHGFI_DISPLAYNAME), FALSE);
|
||||
ok_int(SHGFI((PCWSTR)NULL, info, SHGFI_TYPENAME), FALSE);
|
||||
ok_int(SHGFI((PCWSTR)NULL, info, SHGFI_ICONLOCATION), FALSE);
|
||||
ok_int(SHGFI((PCWSTR)NULL, info, SHGFI_SYSICONINDEX), FALSE);
|
||||
ok_int(SHGFI(UNIQUEEXT, info, SHGFI_USEFILEATTRIBUTES), TRUE); // Success when asking for no info
|
||||
ok_int(SHGetFileInfoW(UNIQUEEXT, 0, NULL, 0, SHGFI_DISPLAYNAME | SHGFI_USEFILEATTRIBUTES), FALSE); // NULL pointer
|
||||
ok_int(SHGFI(UNIQUEEXT, info, SHGFI_EXETYPE | SHGFI_USEFILEATTRIBUTES), TRUE); // Invalid combination, returns TRUE!
|
||||
|
||||
GetModuleFileNameW(NULL, buf, _countof(buf));
|
||||
ok_int(LOWORD(SHGFI(buf, info, SHGFI_EXETYPE)), 0x4550); // 'PE'
|
||||
|
||||
flags = SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES | SHGFI_ATTRIBUTES;
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
info.dwAttributes = ~SFGAO_VALIDATE;
|
||||
ok_int(SHGFI(UNIQUEEXT, info, flags | SHGFI_ATTR_SPECIFIED), TRUE);
|
||||
ok_ptr(StrStrIW(info.szTypeName, UNIQUEEXT), NULL); // A file without extension (not "EXT File")
|
||||
my_ok_all_flags(info.dwAttributes, SFGAO_FILESYSTEM | SFGAO_STREAM);
|
||||
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
info.dwAttributes = ~SFGAO_VALIDATE;
|
||||
ok_int(SHGFI(UNIQUEEXT, info, flags | SHGFI_ATTR_SPECIFIED, FILE_ATTRIBUTE_DIRECTORY), TRUE);
|
||||
ok_ptr(StrStrIW(info.szTypeName, UNIQUEEXT), NULL); // A directory (not "EXT File")
|
||||
my_ok_all_flags(info.dwAttributes, SFGAO_FILESYSTEM | SFGAO_FOLDER);
|
||||
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
info.dwAttributes = ~SFGAO_VALIDATE;
|
||||
ok_int(SHGFI(L"." UNIQUEEXT, info, flags | SHGFI_ATTR_SPECIFIED), TRUE);
|
||||
ok_bool_true(StrStrIW(info.szTypeName, UNIQUEEXT) != NULL, ".ext is treated as extension");
|
||||
my_ok_all_flags(info.dwAttributes, SFGAO_FILESYSTEM | SFGAO_STREAM);
|
||||
|
||||
info.dwAttributes = ~SFGAO_VALIDATE;
|
||||
ok_int(SHGFI(L"c:", info, flags | SHGFI_ATTR_SPECIFIED), TRUE); // ROS fails this, a parsing bug in CDrivesFolder?
|
||||
my_ok_all_flags(info.dwAttributes, SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR);
|
||||
|
||||
info.dwAttributes = ~SFGAO_VALIDATE;
|
||||
ok_int(SHGFI(L"c:\\", info, flags | SHGFI_ATTR_SPECIFIED), TRUE);
|
||||
my_ok_all_flags(info.dwAttributes, SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR);
|
||||
|
||||
pidl = SHSimpleIDListFromPath(L"c:\\foo");
|
||||
info.iIcon = -1;
|
||||
ok_int(SHGFI(pidl, info, SHGFI_SYSICONINDEX) > TRUE, TRUE);
|
||||
ok_int(info.iIcon != -1, TRUE);
|
||||
ILFree(pidl);
|
||||
}
|
@ -41,6 +41,7 @@ extern void func_ShellExecuteW(void);
|
||||
extern void func_ShellHook(void);
|
||||
extern void func_ShellState(void);
|
||||
extern void func_SHGetAttributesFromDataObject(void);
|
||||
extern void func_SHGetFileInfo(void);
|
||||
extern void func_SHLimitInputEdit(void);
|
||||
extern void func_SHParseDisplayName(void);
|
||||
extern void func_SHSimpleIDListFromPath(void);
|
||||
@ -86,6 +87,7 @@ const struct test winetest_testlist[] =
|
||||
{ "ShellHook", func_ShellHook },
|
||||
{ "ShellState", func_ShellState },
|
||||
{ "SHGetAttributesFromDataObject", func_SHGetAttributesFromDataObject },
|
||||
{ "SHGetFileInfo", func_SHGetFileInfo },
|
||||
{ "SHLimitInputEdit", func_SHLimitInputEdit },
|
||||
{ "SHParseDisplayName", func_SHParseDisplayName },
|
||||
{ "SHSimpleIDListFromPath", func_SHSimpleIDListFromPath },
|
||||
|
Loading…
Reference in New Issue
Block a user