[SHELL32]

- Implement filling in needed keys passed to CDefFolderMenu_Create2.
- CDefaultContextMenu: Remove the code that filled the array of keys as this is now moved to the implementation of the shell folder.

svn path=/trunk/; revision=73237
This commit is contained in:
Giannis Adamopoulos 2016-11-15 20:14:56 +00:00
parent 46512f3a37
commit 6cf2a9fc0e
8 changed files with 149 additions and 102 deletions

View file

@ -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;

View file

@ -486,7 +486,7 @@ HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner,
if (bHasCpl)
hr = ShellObjectCreatorInit<CCPLItemMenu>(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)) {

View file

@ -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<IShellFolder*>(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;
}

View file

@ -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<IDefaultExtractIconInit> 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<IShellFolder*>(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;

View file

@ -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<IShellFolder*>(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<IShellFolder*>(this), NULL, cKeys, hKeys, &pCm);
pObj = pCm;
}
else if (IsEqualIID (riid, IID_IDataObject))

View file

@ -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<IDefaultExtractIconInit> 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<IShellFolder*>(this), (IContextMenu**)&pObj);
}
else
{
hr = E_NOINTERFACE;
}
*ppvOut = pObj;
return hr;

View file

@ -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}",

View file

@ -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
*