diff --git a/reactos/dll/win32/shell32/CDefaultContextMenu.cpp b/reactos/dll/win32/shell32/CDefaultContextMenu.cpp index 46d71c8658e..d6b8ba936ce 100644 --- a/reactos/dll/win32/shell32/CDefaultContextMenu.cpp +++ b/reactos/dll/win32/shell32/CDefaultContextMenu.cpp @@ -1571,96 +1571,10 @@ CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, REFIID riid, void * */ -static void AddClassKey(const WCHAR * szClass, HKEY* buffer, UINT* cKeys) -{ - LSTATUS result; - HKEY hkey; - result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ | KEY_QUERY_VALUE, &hkey); - if (result != ERROR_SUCCESS) - return; - - buffer[*cKeys] = hkey; - *cKeys +=1; -} - -void HackFillKeys(DEFCONTEXTMENU *pdcm, HKEY* buffer) -{ - PCUITEMID_CHILD pidl = pdcm->apidl[0]; - pdcm->cKeys = 0; - pdcm->aKeys = buffer; - - if (_ILIsValue(pidl)) - { - FileStructW* pFileData = _ILGetFileStructW(pidl); - LPWSTR extension = PathFindExtension(pFileData->wszName); - - if (extension) - { - AddClassKey(extension, buffer, &pdcm->cKeys); - - WCHAR wszClass[40], wszClass2[40]; - DWORD dwSize = sizeof(wszClass); - if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS) - { - swprintf(wszClass2, L"%s//%s", extension, wszClass); - - AddClassKey(wszClass, buffer, &pdcm->cKeys); - AddClassKey(wszClass2, buffer, &pdcm->cKeys); - } - - swprintf(wszClass2, L"SystemFileAssociations//%s", extension); - AddClassKey(wszClass2, buffer, &pdcm->cKeys); - - if (RegGetValueW(HKEY_CLASSES_ROOT, extension, L"PerceivedType ", RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS) - { - swprintf(wszClass2, L"SystemFileAssociations//%s", wszClass); - AddClassKey(wszClass2, buffer, &pdcm->cKeys); - } - } - - AddClassKey(L"AllFilesystemObjects", buffer, &pdcm->cKeys); - AddClassKey(L"*", buffer, &pdcm->cKeys); - } - else if (_ILIsSpecialFolder(pidl)) - { - GUID *pGuid = _ILGetGUIDPointer(pidl); - if (pGuid) - { - LPOLESTR pwszCLSID; - WCHAR key[60]; - - wcscpy(key, L"CLSID\\"); - HRESULT hr = StringFromCLSID(*pGuid, &pwszCLSID); - if (hr == S_OK) - { - wcscpy(&key[6], pwszCLSID); - AddClassKey(key, buffer, &pdcm->cKeys); - } - } - AddClassKey(L"Folder", buffer, &pdcm->cKeys); - } - else if (_ILIsFolder(pidl)) - { - AddClassKey(L"AllFilesystemObjects", buffer, &pdcm->cKeys); - AddClassKey(L"Directory", buffer, &pdcm->cKeys); - AddClassKey(L"Folder", buffer, &pdcm->cKeys); - } - else if (_ILIsDrive(pidl)) - { - AddClassKey(L"Drive", buffer, &pdcm->cKeys); - AddClassKey(L"Folder", buffer, &pdcm->cKeys); - } -} - HRESULT WINAPI SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv) { - /* HACK: move to the shell folders implementation */ - HKEY hkeyHack[16]; - if (!pdcm->aKeys && pdcm->cidl) - HackFillKeys((DEFCONTEXTMENU *)pdcm, hkeyHack); - HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, riid, ppv); if (FAILED_UNEXPECTEDLY(hr)) return hr; diff --git a/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp b/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp index cadf7c3e336..e9dba76f543 100644 --- a/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp @@ -486,7 +486,7 @@ HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner, if (bHasCpl) hr = ShellObjectCreatorInit(cidl, apidl, riid, &pObj); else - hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)this, NULL, 0, NULL, (IContextMenu**)&pObj); + hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj); } else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) { hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj); } else if ((IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && (cidl == 1)) { diff --git a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp index 0630ea5f065..6ab512d1899 100644 --- a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp @@ -639,7 +639,21 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf( if (IsEqualIID (riid, IID_IContextMenu)) { - hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder *)this, NULL, 0, NULL, (IContextMenu **)&pObj); + if (_ILIsSpecialFolder(apidl[0])) + { + hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj); + } + else + { + /* Do not use the context menu of the CFSFolder here. */ + /* We need to pass a pointer of the CDesktopFolder so as the data object that the context menu gets is rooted to the desktop */ + /* Otherwise operations like that involve items from both user and shared desktop will not work */ + IContextMenu * pCm = NULL; + HKEY hKeys[16]; + UINT cKeys = 0; + AddFSClassKeysToArray(apidl[0], hKeys, &cKeys); + hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast(this), NULL, cKeys, hKeys, &pCm); + } } else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1)) { @@ -817,14 +831,15 @@ HRESULT WINAPI CDesktopFolder::Initialize(LPCITEMIDLIST pidl) { TRACE ("(%p)->(%p)\n", this, pidl); - return E_NOTIMPL; + return E_INVALIDARG; } HRESULT WINAPI CDesktopFolder::GetCurFolder(LPITEMIDLIST * pidl) { TRACE ("(%p)->(%p)\n", this, pidl); - if (!pidl) return E_POINTER; + if (!pidl) + return E_INVALIDARG; /* xp doesn't have this check and crashes on NULL */ *pidl = ILClone (pidlRoot); return S_OK; } diff --git a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp index 73d13cd6e43..d2008c69b95 100644 --- a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -39,6 +39,22 @@ CDrivesFolderEnum is only responsible for returning the physical items. * IShellFolder implementation */ +HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, + HWND hwnd, + UINT cidl, + PCUITEMID_CHILD_ARRAY apidl, + IShellFolder *psf, + IContextMenu **ppcm) +{ + HKEY hKeys[2]; + UINT cKeys = 0; + AddClassKeyToArray(L"Drive", hKeys, &cKeys); + AddClassKeyToArray(L"Folder", hKeys, &cKeys); + + /* TODO: also pass a callback here */ + return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm); +} + HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut) { CComPtr initIcon; @@ -536,7 +552,10 @@ HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner, if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1)) { - hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)this, NULL, 0, NULL, (IContextMenu**)&pObj); + if (_ILIsDrive(apidl[0])) + hr = CDrivesContextMenu_CreateInstance(pidlRoot, hwndOwner, cidl, apidl, static_cast(this), (IContextMenu**)&pObj); + else + hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj); } else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1)) { @@ -812,12 +831,6 @@ HRESULT WINAPI CDrivesFolder::GetClassID(CLSID *lpClassId) */ HRESULT WINAPI CDrivesFolder::Initialize(LPCITEMIDLIST pidl) { - TRACE ("(%p)->(%p)\n", this, pidl); - - if (pidlRoot) - SHFree((LPVOID)pidlRoot); - - pidlRoot = ILClone(pidl); return S_OK; } @@ -829,7 +842,7 @@ HRESULT WINAPI CDrivesFolder::GetCurFolder(LPITEMIDLIST *pidl) TRACE("(%p)->(%p)\n", this, pidl); if (!pidl) - return E_POINTER; + return E_INVALIDARG; /* xp doesn't have this check and crashes on NULL */ *pidl = ILClone(pidlRoot); return S_OK; diff --git a/reactos/dll/win32/shell32/folders/CFSFolder.cpp b/reactos/dll/win32/shell32/folders/CFSFolder.cpp index 20bc73b82d3..19a2d7466ba 100644 --- a/reactos/dll/win32/shell32/folders/CFSFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CFSFolder.cpp @@ -490,7 +490,10 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner, if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) { IContextMenu * pCm = NULL; - hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast(this), NULL, 0, NULL, &pCm); + HKEY hKeys[16]; + UINT cKeys = 0; + AddFSClassKeysToArray(apidl[0], hKeys, &cKeys); + hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast(this), NULL, cKeys, hKeys, &pCm); pObj = pCm; } else if (IsEqualIID (riid, IID_IDataObject)) diff --git a/reactos/dll/win32/shell32/folders/CRegFolder.cpp b/reactos/dll/win32/shell32/folders/CRegFolder.cpp index a6f9452355a..e595d375865 100644 --- a/reactos/dll/win32/shell32/folders/CRegFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CRegFolder.cpp @@ -22,6 +22,35 @@ WINE_DEFAULT_DEBUG_CHANNEL (shell); +HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, + HWND hwnd, + UINT cidl, + PCUITEMID_CHILD_ARRAY apidl, + IShellFolder *psf, + IContextMenu **ppcm) +{ + HKEY hKeys[10]; + UINT cKeys = 0; + + GUID *pGuid = _ILGetGUIDPointer(apidl[0]); + if (pGuid) + { + LPOLESTR pwszCLSID; + WCHAR key[60]; + + wcscpy(key, L"CLSID\\"); + HRESULT hr = StringFromCLSID(*pGuid, &pwszCLSID); + if (hr == S_OK) + { + wcscpy(&key[6], pwszCLSID); + AddClassKeyToArray(key, hKeys, &cKeys); + } + } + AddClassKeyToArray(L"Folder", hKeys, &cKeys); + + return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm); +} + HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut) { CComPtr initIcon; @@ -175,13 +204,26 @@ HRESULT WINAPI CRegFolder::Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, HRESULT CRegFolder::GetGuidItemAttributes (LPCITEMIDLIST pidl, LPDWORD pdwAttributes) { + DWORD dwAttributes = *pdwAttributes; + /* First try to get them from the registry */ - if (HCR_GetFolderAttributes(pidl, pdwAttributes) && *pdwAttributes) + if (!HCR_GetFolderAttributes(pidl, pdwAttributes)) { - return S_OK; + /* We couldn't get anything */ + *pdwAttributes = 0; } - *pdwAttributes &= SFGAO_CANLINK; + /* Items have more attributes when on desktop */ + if (_ILIsDesktop(m_pidlRoot)) + { + *pdwAttributes |= (dwAttributes & (SFGAO_CANLINK|SFGAO_CANDELETE|SFGAO_CANRENAME|SFGAO_HASPROPSHEET)); + } + + /* In any case, links can be created */ + if (*pdwAttributes == NULL) + { + *pdwAttributes |= (dwAttributes & SFGAO_CANLINK); + } return S_OK; } @@ -346,8 +388,20 @@ HRESULT WINAPI CRegFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH { hr = CGuidItemExtractIcon_CreateInstance(apidl[0], riid, &pObj); } + else if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1)) + { + if (!_ILGetGUIDPointer (apidl[0])) + { + ERR("Got non guid item!\n"); + return E_FAIL; + } + + hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast(this), (IContextMenu**)&pObj); + } else + { hr = E_NOINTERFACE; + } *ppvOut = pObj; return hr; diff --git a/reactos/dll/win32/shell32/shfldr.h b/reactos/dll/win32/shell32/shfldr.h index d43c92aa93f..bc373af0cfa 100644 --- a/reactos/dll/win32/shell32/shfldr.h +++ b/reactos/dll/win32/shell32/shfldr.h @@ -61,6 +61,8 @@ HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, extern "C" BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey); +void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys); + 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/reactos/dll/win32/shell32/shlfolder.cpp b/reactos/dll/win32/shell32/shlfolder.cpp index 59b4e05b43d..114504f815b 100644 --- a/reactos/dll/win32/shell32/shlfolder.cpp +++ b/reactos/dll/win32/shell32/shlfolder.cpp @@ -501,6 +501,52 @@ void AddClassKeyToArray(const WCHAR * szClass, HKEY* array, UINT* cKeys) *cKeys += 1; } +void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys) +{ + if (_ILIsValue(pidl)) + { + FileStructW* pFileData = _ILGetFileStructW(pidl); + LPWSTR extension = PathFindExtension(pFileData->wszName); + + if (extension) + { + AddClassKeyToArray(extension, array, cKeys); + + WCHAR wszClass[40], wszClass2[40]; + DWORD dwSize = sizeof(wszClass); + if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS) + { + swprintf(wszClass2, L"%s//%s", extension, wszClass); + + AddClassKeyToArray(wszClass, array, cKeys); + AddClassKeyToArray(wszClass2, array, cKeys); + } + + swprintf(wszClass2, L"SystemFileAssociations//%s", extension); + AddClassKeyToArray(wszClass2, array, cKeys); + + if (RegGetValueW(HKEY_CLASSES_ROOT, extension, L"PerceivedType ", RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS) + { + swprintf(wszClass2, L"SystemFileAssociations//%s", wszClass); + AddClassKeyToArray(wszClass2, array, cKeys); + } + } + + AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys); + AddClassKeyToArray(L"*", array, cKeys); + } + else if (_ILIsFolder(pidl)) + { + AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys); + AddClassKeyToArray(L"Directory", array, cKeys); + AddClassKeyToArray(L"Folder", array, cKeys); + } + else + { + ERR("Got non FS pidl\n"); + } +} + /*********************************************************************** * SHCreateLinks *