From aec725dce4c39d54578d7dfe28bc56fddac64d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 4 Oct 2004 19:41:31 +0000 Subject: [PATCH] Reapply winehq change: Robert Shearman - Simplify getting custom icons for a folder by utilising the new SHELL32_GetCustomFolderAttribute function. - Add support for custom shell folders, such as the History folder. - Always try to initialize folder using IPersistFolder3 interface and then fall back on IPersistFolder if not supported. Ge van Geldorp - Can't pass NULL as default value to GetPrivateProfileString. svn path=/trunk/; revision=11190 --- reactos/lib/shell32/folders.c | 84 ++++++++-------------- reactos/lib/shell32/shfldr.h | 8 +-- reactos/lib/shell32/shlfolder.c | 124 +++++++++++++++++++------------- 3 files changed, 107 insertions(+), 109 deletions(-) diff --git a/reactos/lib/shell32/folders.c b/reactos/lib/shell32/folders.c index 233c7c5fead..3deab4acf20 100644 --- a/reactos/lib/shell32/folders.c +++ b/reactos/lib/shell32/folders.c @@ -27,6 +27,7 @@ #include "windef.h" #include "winbase.h" +#include "winerror.h" #include "objbase.h" #include "undocshell.h" #include "shlguid.h" @@ -34,10 +35,11 @@ #include "shlwapi.h" #include "wine/debug.h" -#include "winerror.h" +#include "wine/unicode.h" #include "pidl.h" #include "shell32_main.h" +#include "shfldr.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); @@ -156,64 +158,36 @@ static HRESULT getIconLocationForFolder(IExtractIconW *iface, UINT uFlags, LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags) { IExtractIconWImpl *This = (IExtractIconWImpl *)iface; - - WCHAR path[MAX_PATH]; - BOOL found = FALSE; DWORD dwNr; + WCHAR wszPath[MAX_PATH]; + WCHAR wszCLSIDValue[CHARS_IN_GUID]; + static const WCHAR shellClassInfo[] = { '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 }; + static const WCHAR iconFile[] = { 'I','c','o','n','F','i','l','e',0 }; + static const WCHAR clsid[] = { 'C','L','S','I','D',0 }; + static const WCHAR clsid2[] = { 'C','L','S','I','D','2',0 }; + static const WCHAR iconIndex[] = { 'I','c','o','n','I','n','d','e','x',0 }; - if (SUCCEEDED(SHGetPathFromIDListW(This->pidl, path))) + if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, iconFile, + wszPath, MAX_PATH)) { - static const WCHAR desktopIni[] = { 'D','e','s','k','t','o','p','.', - 'i','n','i',0 }; - HANDLE hFile; - - PathAppendW(path, desktopIni); - if ((hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) - { - static const WCHAR shellClassInfo[] = { '.','S','h','e','l','l', - 'C','l','a','s','s','I','n','f','o',0 }; - static const WCHAR iconFile[] = - { 'I','c','o','n','F','i','l','e',0 }; - static const WCHAR clsid[] = { 'C','L','S','I','D',0 }; - static const WCHAR clsid2[] = { 'C','L','S','I','D','2',0 }; - static const WCHAR defStr[] = { 0 }; - WCHAR clsidStr[39]; - - CloseHandle(hFile); - if (GetPrivateProfileStringW(shellClassInfo, iconFile, defStr, - szIconFile, cchMax, path) && strlenW(szIconFile)) - { - static const WCHAR iconIndex[] = { 'I','c','o','n', - 'I','n','d','e','x',0 }; - - found = TRUE; - *piIndex = (int)GetPrivateProfileIntW(shellClassInfo, iconIndex, - 0, path); - } - else if (GetPrivateProfileStringW(shellClassInfo, clsid, defStr, - clsidStr, sizeof(clsidStr) / sizeof(WCHAR), path) && - strlenW(clsidStr)) - { - if (HCR_GetDefaultIconW(clsidStr, szIconFile, cchMax, &dwNr)) - { - *piIndex = dwNr; - found = TRUE; - } - } - else if (GetPrivateProfileStringW(shellClassInfo, clsid2, defStr, - clsidStr, sizeof(clsidStr) / sizeof(WCHAR), path) && - strlenW(clsidStr)) - { - if (HCR_GetDefaultIconW(clsidStr, szIconFile, cchMax, &dwNr)) - { - *piIndex = dwNr; - found = TRUE; - } - } - } + WCHAR wszIconIndex[10]; + SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, iconIndex, + wszIconIndex, 10); + *piIndex = atoiW(wszIconIndex); } - if (!found) + else if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, clsid, + wszCLSIDValue, CHARS_IN_GUID) && + HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &dwNr)) + { + *piIndex = dwNr; + } + else if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, clsid2, + wszCLSIDValue, CHARS_IN_GUID) && + HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &dwNr)) + { + *piIndex = dwNr; + } + else { static const WCHAR folder[] = { 'F','o','l','d','e','r',0 }; diff --git a/reactos/lib/shell32/shfldr.h b/reactos/lib/shell32/shfldr.h index cb455686616..5666f0d7cc3 100644 --- a/reactos/lib/shell32/shfldr.h +++ b/reactos/lib/shell32/shfldr.h @@ -21,6 +21,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define CHARS_IN_GUID 39 + typedef struct { int colnameid; int pcsFlags; @@ -31,14 +33,12 @@ typedef struct { #define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00) #define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF) +BOOL SHELL32_GetCustomFolderAttribute (LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, LPWSTR pwszValue, DWORD cchValue); + LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut); HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut, LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes); -HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidlChild, REFCLSID clsid, REFIID iid, - LPVOID * ppvOut); -HRESULT SHELL32_CoCreateInitSFEx (LPCITEMIDLIST pidlRoot, LPCSTR pathRoot, LPCITEMIDLIST pidlChild, REFCLSID clsid, - REFIID iid, LPVOID * ppvOut); HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTR szOut, DWORD dwOutLen); diff --git a/reactos/lib/shell32/shlfolder.c b/reactos/lib/shell32/shlfolder.c index 5c86b92d6e7..316341f8136 100644 --- a/reactos/lib/shell32/shlfolder.c +++ b/reactos/lib/shell32/shlfolder.c @@ -64,6 +64,54 @@ WINE_DEFAULT_DEBUG_CHANNEL (shell); #define _CALL_TRACE #endif +static const WCHAR wszDotShellClassInfo[] = {'.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0}; + +/*************************************************************************** + * SHELL32_GetCustomFolderAttribute (internal function) + * + * Gets a value from the folder's desktop.ini file, if one exists. + * + * PARAMETERS + * pidl [I] Folder containing the desktop.ini file. + * pwszHeading [I] Heading in .ini file. + * pwszAttribute [I] Attribute in .ini file. + * pwszValue [O] Buffer to store value into. + * cchValue [I] Size in characters including NULL of buffer pointed to + * by pwszValue. + * + * RETURNS + * TRUE if returned non-NULL value. + * FALSE otherwise. + */ +BOOL SHELL32_GetCustomFolderAttribute( + LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, + LPWSTR pwszValue, DWORD cchValue) +{ +#if 0 /* Hack around not having system attribute on non-Windows file systems */ + DWORD dwAttrib = _ILGetFileAttributes(pidl, NULL, 0); +#else + DWORD dwAttrib = FILE_ATTRIBUTE_SYSTEM; +#endif + if (dwAttrib & FILE_ATTRIBUTE_SYSTEM) + { + DWORD ret; + WCHAR wszDesktopIniPath[MAX_PATH]; + static const WCHAR wszDesktopIni[] = + {'d','e','s','k','t','o','p','.','i','n','i',0}; + static const WCHAR wszDefault[] = + {0}; + if (!SHGetPathFromIDListW(pidl, wszDesktopIniPath)) + return FALSE; + PathAppendW(wszDesktopIniPath, wszDesktopIni); + ret = GetPrivateProfileStringW(pwszHeading, pwszAttribute, + wszDefault, pwszValue, cchValue, wszDesktopIniPath); + if (!ret) return FALSE; + return TRUE; + } + return FALSE; +} + + /*************************************************************************** * GetNextElement (internal function) * @@ -143,68 +191,31 @@ HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, /*********************************************************************** * SHELL32_CoCreateInitSF * - * Creates a shell folder and initializes it with a pidl via IPersistFolder. - * This function is meant for virtual folders not backed by a file system - * folder. - */ -HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, - LPCITEMIDLIST pidlChild, REFCLSID clsid, REFIID iid, LPVOID * ppvOut) -{ - HRESULT hr; - - TRACE ("%p %p\n", pidlRoot, pidlChild); - - if (SUCCEEDED ((hr = SHCoCreateInstance (NULL, clsid, NULL, iid, ppvOut)))) { - IPersistFolder *pPF; - - if (SUCCEEDED ((hr = IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder, (LPVOID *) & pPF)))) { - LPITEMIDLIST pidlAbsolute; - - pidlAbsolute = ILCombine (pidlRoot, pidlChild); - IPersistFolder_Initialize (pPF, pidlAbsolute); - IPersistFolder_Release (pPF); - SHFree (pidlAbsolute); - - if (!pidlAbsolute) - hr = E_OUTOFMEMORY; - } - } - - TRACE ("-- (%p) ret=0x%08lx\n", *ppvOut, hr); - return hr; -} - -/*********************************************************************** - * SHELL32_CoCreateInitSFEx - * * Creates a shell folder and initializes it with a pidl and a root folder - * via IPersistFolder3. - * This function is meant for virtual folders backed by a file system - * folder. + * via IPersistFolder3 or IPersistFolder. * * NOTES * pathRoot can be NULL for Folders beeing a drive. * In this case the absolute path is build from pidlChild (eg. C:) */ -HRESULT SHELL32_CoCreateInitSFEx (LPCITEMIDLIST pidlRoot, - LPCSTR pathRoot, LPCITEMIDLIST pidlChild, REFCLSID clsid, REFIID riid, LPVOID * ppvOut) +HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCSTR pathRoot, + LPCITEMIDLIST pidlChild, REFCLSID clsid, REFIID riid, LPVOID * ppvOut) { HRESULT hr; - IPersistFolder3 *ppf; TRACE ("%p %s %p\n", pidlRoot, pathRoot, pidlChild); - if (SUCCEEDED ((hr = SHCoCreateInstance (NULL, &CLSID_ShellFSFolder, NULL, riid, ppvOut)))) { + if (SUCCEEDED ((hr = SHCoCreateInstance (NULL, clsid, NULL, riid, ppvOut)))) { + LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); + IPersistFolder *pPF; + IPersistFolder3 *ppf; + if (SUCCEEDED (IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder3, (LPVOID *) & ppf))) { PERSIST_FOLDER_TARGET_INFO ppfti; - LPITEMIDLIST pidlAbsolute; char szDestPath[MAX_PATH]; ZeroMemory (&ppfti, sizeof (ppfti)); - /* combine pidls */ - pidlAbsolute = ILCombine (pidlRoot, pidlChild); - /* build path */ if (pathRoot) { lstrcpyA (szDestPath, pathRoot); @@ -229,8 +240,12 @@ HRESULT SHELL32_CoCreateInitSFEx (LPCITEMIDLIST pidlRoot, IPersistFolder3_InitializeEx (ppf, NULL, pidlAbsolute, &ppfti); IPersistFolder3_Release (ppf); - ILFree (pidlAbsolute); } + else if (SUCCEEDED ((hr = IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder, (LPVOID *) & pPF)))) { + IPersistFolder_Initialize (pPF, pidlAbsolute); + IPersistFolder_Release (pPF); + } + ILFree (pidlAbsolute); } TRACE ("-- (%p) ret=0x%08lx\n", *ppvOut, hr); return hr; @@ -259,11 +274,20 @@ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, if ((clsid = _ILGetGUIDPointer (pidlChild))) { /* virtual folder */ - hr = SHELL32_CoCreateInitSF (pidlRoot, pidlChild, clsid, &IID_IShellFolder, (LPVOID *) & pSF); + hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsid, &IID_IShellFolder, (LPVOID *) & pSF); } else { - /* file system folder */ - hr = SHELL32_CoCreateInitSFEx (pidlRoot, pathRoot, pidlChild, &CLSID_ShellFSFolder, &IID_IShellFolder, - (LPVOID *) & pSF); + /* file system folder */ + CLSID clsidFolder = CLSID_ShellFSFolder; + static const WCHAR wszCLSID[] = {'C','L','S','I','D',0}; + WCHAR wszCLSIDValue[CHARS_IN_GUID]; + LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); + /* see if folder CLSID should be overridden by desktop.ini file */ + if (SHELL32_GetCustomFolderAttribute (pidlAbsolute, + wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID)) + CLSIDFromString (wszCLSIDValue, &clsidFolder); + ILFree (pidlAbsolute); + hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, + &clsidFolder, &IID_IShellFolder, (LPVOID *)&pSF); } ILFree (pidlChild);