Module: wine Branch: master Commit: e062d4a6fffd6ee2806919aea7109bffa9a73408 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e062d4a6fffd6ee2806919aea7...
Author: Piotr Caban piotr@codeweavers.com Date: Wed Nov 10 14:19:29 2010 +0100
shell32: Improved IShellFolder_GetUIObjectOf implementation.
---
dlls/shell32/shell32_main.h | 2 + dlls/shell32/shfldr.h | 2 + dlls/shell32/shfldr_fs.c | 90 ++++++++++++++++++++++++++++++++++++++++++ dlls/shell32/shfldr_unixfs.c | 7 +++ 4 files changed, 101 insertions(+), 0 deletions(-)
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h index af83fe4..77fd42a 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -69,6 +69,8 @@ BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD dwAttributes); DWORD WINAPI ParseFieldA(LPCSTR src, DWORD nField, LPSTR dst, DWORD len); DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len);
+BOOL WINAPI GUIDFromStringW(LPCWSTR, LPGUID); + /**************************************************************************** * Class constructors */ diff --git a/dlls/shell32/shfldr.h b/dlls/shell32/shfldr.h index 38e0a0b..56833d1 100644 --- a/dlls/shell32/shfldr.h +++ b/dlls/shell32/shfldr.h @@ -49,6 +49,8 @@ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path);
+HRESULT SHELL32_CreateExtensionUIObject(IShellFolder2 *iface, LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut); + static inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str) { return sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", diff --git a/dlls/shell32/shfldr_fs.c b/dlls/shell32/shfldr_fs.c index 305902c..850424d 100644 --- a/dlls/shell32/shfldr_fs.c +++ b/dlls/shell32/shfldr_fs.c @@ -611,6 +611,90 @@ IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, }
/************************************************************************** + * SHELL32_CreateExtensionUIObject (internal) + */ +HRESULT SHELL32_CreateExtensionUIObject(IShellFolder2 *iface, + LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut) +{ + static const WCHAR reg_blockedW[] = {'S','o','f','t','w','a','r','e','\', + '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','\', + 'S','h','e','l','l',' ','E','x','t','e','n','s','i','o','n','s','\', + 'B','l','o','c','k','e','d',0}; + static const WCHAR formatW[] = {'.','%','s','\','S','h','e','l','l','E','x','\', + '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-', + '%','0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x', + '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0}; + + IPersistFile *persist_file; + char extensionA[20]; + WCHAR extensionW[20], buf[MAX_PATH]; + DWORD size = MAX_PATH; + STRRET path; + WCHAR *file; + GUID guid; + HKEY key; + HRESULT hr; + + + if(!_ILGetExtension(pidl, extensionA, 20)) + return S_FALSE; + + MultiByteToWideChar(CP_ACP, 0, extensionA, -1, extensionW, 20); + + sprintfW(buf, formatW, extensionW, riid->Data1, riid->Data2, riid->Data3, + riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], + riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]); + + if(RegGetValueW(HKEY_CLASSES_ROOT, buf, NULL, RRF_RT_REG_SZ, + NULL, buf, &size) != ERROR_SUCCESS) + return S_FALSE; + + if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, reg_blockedW, 0, 0, 0, + KEY_READ, NULL, &key, NULL) != ERROR_SUCCESS) + return E_FAIL; + if(RegQueryValueExW(key, buf, 0, NULL, NULL, NULL) + != ERROR_FILE_NOT_FOUND) + return E_ACCESSDENIED; + RegCloseKey(key); + + if(RegCreateKeyExW(HKEY_CURRENT_USER, reg_blockedW, 0, 0, 0, + KEY_READ, NULL, &key, NULL) != ERROR_SUCCESS) + return E_FAIL; + if(RegQueryValueExW(key, buf, 0, NULL, NULL, NULL) + != ERROR_FILE_NOT_FOUND) + return E_ACCESSDENIED; + RegCloseKey(key); + + if(!GUIDFromStringW(buf, &guid)) + return E_FAIL; + + hr = CoCreateInstance(&guid, NULL, CLSCTX_INPROC_SERVER, + &IID_IPersistFile, (void**)&persist_file); + if(FAILED(hr)) + return hr; + + hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_FORPARSING, &path); + if(SUCCEEDED(hr)) + hr = StrRetToStrW(&path, NULL, &file); + if(FAILED(hr)) { + IPersistFile_Release(persist_file); + return hr; + } + + hr = IPersistFile_Load(persist_file, file, STGM_READ); + CoTaskMemFree(file); + if(FAILED(hr)) { + IPersistFile_Release(persist_file); + return hr; + } + + hr = IPersistFile_QueryInterface(persist_file, riid, ppvOut); + IPersistFile_Release(persist_file); + return hr; +} + +/************************************************************************** * IShellFolder_fnGetUIObjectOf * * PARAMETERS @@ -651,6 +735,12 @@ IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface, if (ppvOut) { *ppvOut = NULL;
+ if(cidl == 1) { + hr = SHELL32_CreateExtensionUIObject(iface, *apidl, riid, ppvOut); + if(hr != S_FALSE) + return hr; + } + if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) { pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c index e02399a..11f3686 100644 --- a/dlls/shell32/shfldr_unixfs.c +++ b/dlls/shell32/shfldr_unixfs.c @@ -1115,6 +1115,7 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetUIObjectOf(IShellFolder2* ifac { UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface); UINT i; + HRESULT hr;
TRACE("(iface=%p, hwndOwner=%p, cidl=%d, apidl=%p, riid=%s, prgfInOut=%p, ppv=%p)\n", iface, hwndOwner, cidl, apidl, debugstr_guid(riid), prgfInOut, ppvOut); @@ -1125,6 +1126,12 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetUIObjectOf(IShellFolder2* ifac for (i=0; i<cidl; i++) if (!apidl[i]) return E_INVALIDARG; + + if(cidl == 1) { + hr = SHELL32_CreateExtensionUIObject(iface, *apidl, riid, ppvOut); + if(hr != S_FALSE) + return hr; + }
if (IsEqualIID(&IID_IContextMenu, riid)) { *ppvOut = ISvItemCm_Constructor((IShellFolder*)iface, This->m_pidlLocation, apidl, cidl);