mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 17:52:56 +00:00
[SHELL32] Implement DragDropHandlers shell extension context menus (#8143)
CORE-11240 CORE-11238
This commit is contained in:
parent
06414ac85a
commit
59e556f3f3
11 changed files with 234 additions and 13 deletions
|
@ -32,6 +32,112 @@ static BOOL InsertMenuItemAt(HMENU hMenu, UINT Pos, UINT Flags)
|
||||||
return InsertMenuItemW(hMenu, Pos, TRUE, &mii);
|
return InsertMenuItemW(hMenu, Pos, TRUE, &mii);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DCMA_DestroyEntry(DCMENTRY &dcme)
|
||||||
|
{
|
||||||
|
if (!dcme.pCM)
|
||||||
|
return;
|
||||||
|
IUnknown_SetSite(dcme.pCM, NULL);
|
||||||
|
dcme.pCM->Release();
|
||||||
|
dcme.pCM = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCMA_Destroy(HDCMA hDCMA)
|
||||||
|
{
|
||||||
|
UINT i = 0;
|
||||||
|
for (DCMENTRY *p; (p = DCMA_GetEntry(hDCMA, i)) != NULL; ++i)
|
||||||
|
DCMA_DestroyEntry(*p);
|
||||||
|
DSA_Destroy(hDCMA);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT DCMA_InsertMenuItems(
|
||||||
|
_In_ HDCMA hDCMA,
|
||||||
|
_In_ HDCIA hDCIA,
|
||||||
|
_In_opt_ LPCITEMIDLIST pidlFolder,
|
||||||
|
_In_opt_ IDataObject *pDO,
|
||||||
|
_In_opt_ HKEY *pKeys,
|
||||||
|
_In_opt_ UINT nKeys,
|
||||||
|
_In_ QCMINFO *pQCMI,
|
||||||
|
_In_opt_ UINT fCmf,
|
||||||
|
_In_opt_ IUnknown *pUnkSite)
|
||||||
|
{
|
||||||
|
UINT idCmdBase = pQCMI->idCmdFirst, idCmdFirst = idCmdBase;
|
||||||
|
UINT nOffset = 0;
|
||||||
|
|
||||||
|
// Insert in reverse order
|
||||||
|
for (int iCls = DCIA_GetCount(hDCIA) - 1; iCls >= 0; --iCls)
|
||||||
|
{
|
||||||
|
REFCLSID clsid = *DCIA_GetEntry(hDCIA, iCls);
|
||||||
|
if (fCmf & CMF_DEFAULTONLY)
|
||||||
|
{
|
||||||
|
WCHAR szKey[MAX_PATH];
|
||||||
|
wcscpy(szKey, L"CLSID\\");
|
||||||
|
StringFromGUID2(clsid, szKey + _countof(L"CLSID\\") - 1, CHARS_IN_GUID);
|
||||||
|
wcscpy(szKey + _countof(L"CLSID\\") - 1 + CHARS_IN_GUID - 1, L"\\shellex\\MayChangeDefaultMenu");
|
||||||
|
if (!RegKeyExists(HKEY_CLASSES_ROOT, szKey))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UINT iKey = 0; iKey < nKeys; ++iKey)
|
||||||
|
{
|
||||||
|
CComPtr<IShellExtInit> pInit;
|
||||||
|
HRESULT hr = SHExtCoCreateInstance(NULL, &clsid, NULL, IID_PPV_ARG(IShellExtInit, &pInit));
|
||||||
|
if (FAILED(hr))
|
||||||
|
break;
|
||||||
|
if (FAILED(hr = pInit->Initialize(pidlFolder, pDO, pKeys[iKey])))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IContextMenu *pCM;
|
||||||
|
if (FAILED(hr = pInit->QueryInterface(IID_PPV_ARG(IContextMenu, &pCM))))
|
||||||
|
break;
|
||||||
|
IUnknown_SetSite(pCM, pUnkSite);
|
||||||
|
|
||||||
|
hr = pCM->QueryContextMenu(pQCMI->hmenu, pQCMI->indexMenu + nOffset, idCmdFirst, pQCMI->idCmdLast, fCmf);
|
||||||
|
const UINT nCount = HRESULT_CODE(hr);
|
||||||
|
const UINT idThisFirst = idCmdFirst - idCmdBase;
|
||||||
|
DCMENTRY dcme = { pCM, idThisFirst, idThisFirst + nCount - 1 };
|
||||||
|
if (hr > 0)
|
||||||
|
{
|
||||||
|
idCmdFirst += nCount;
|
||||||
|
if (DSA_AppendItem(hDCMA, &dcme) >= 0)
|
||||||
|
{
|
||||||
|
if (nOffset == 0 && GetMenuDefaultItem(pQCMI->hmenu, TRUE, 0) == 0)
|
||||||
|
nOffset++; // Insert new items below the default
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DCMA_DestroyEntry(dcme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idCmdFirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT DCMA_InvokeCommand(HDCMA hDCMA, CMINVOKECOMMANDINFO *pICI)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_FALSE;
|
||||||
|
for (UINT i = 0;; ++i)
|
||||||
|
{
|
||||||
|
DCMENTRY *p = DCMA_GetEntry(hDCMA, i);
|
||||||
|
if (!p)
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
UINT id = LOWORD(pICI->lpVerb);
|
||||||
|
if (!IS_INTRESOURCE(pICI->lpVerb))
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(hr = p->pCM->InvokeCommand(pICI)))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
else if (id >= p->idCmdFirst && id <= p->idCmdLast)
|
||||||
|
{
|
||||||
|
CMINVOKECOMMANDINFOEX ici;
|
||||||
|
CopyMemory(&ici, pICI, min(sizeof(ici), pICI->cbSize));
|
||||||
|
ici.cbSize = min(sizeof(ici), pICI->cbSize);
|
||||||
|
ici.lpVerb = MAKEINTRESOURCEA(id - p->idCmdFirst);
|
||||||
|
ici.lpVerbW = (PWSTR)ici.lpVerb;
|
||||||
|
return p->pCM->InvokeCommand((CMINVOKECOMMANDINFO*)&ici);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _DynamicShellEntry_
|
typedef struct _DynamicShellEntry_
|
||||||
{
|
{
|
||||||
UINT iIdCmdFirst;
|
UINT iIdCmdFirst;
|
||||||
|
|
|
@ -237,7 +237,6 @@ HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, D
|
||||||
HMENU hmenu = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(IDM_DRAGFILE));
|
HMENU hmenu = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(IDM_DRAGFILE));
|
||||||
if (!hmenu)
|
if (!hmenu)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
HMENU hpopupmenu = GetSubMenu(hmenu, 0);
|
HMENU hpopupmenu = GetSubMenu(hmenu, 0);
|
||||||
|
|
||||||
SHELL_LimitDropEffectToItemAttributes(pDataObject, &dwAvailableEffects);
|
SHELL_LimitDropEffectToItemAttributes(pDataObject, &dwAvailableEffects);
|
||||||
|
@ -256,7 +255,19 @@ HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, D
|
||||||
else if (dwAvailableEffects & DROPEFFECT_LINK)
|
else if (dwAvailableEffects & DROPEFFECT_LINK)
|
||||||
SetMenuDefaultItem(hpopupmenu, IDM_LINKHERE, FALSE);
|
SetMenuDefaultItem(hpopupmenu, IDM_LINKHERE, FALSE);
|
||||||
|
|
||||||
/* FIXME: We need to support shell extensions here */
|
CRegKeyHandleArray keys;
|
||||||
|
HDCIA hDCIA = DCIA_Create();
|
||||||
|
HDCMA hDCMA = DCMA_Create();
|
||||||
|
CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlFolder(SHELL32_CreateSimpleIDListFromPath(m_sPathTarget, FILE_ATTRIBUTE_DIRECTORY));
|
||||||
|
if (hDCMA && hDCIA && pidlFolder)
|
||||||
|
{
|
||||||
|
AddPidlClassKeysToArray(pidlFolder, keys, keys);
|
||||||
|
for (UINT i = 0; i < keys; ++i)
|
||||||
|
DCIA_AddShellExSubkey(hDCIA, keys[i], L"DragDropHandlers");
|
||||||
|
|
||||||
|
QCMINFO qcmi = { hpopupmenu, 0, DROPIDM_EXTFIRST, DROPIDM_EXTLAST };
|
||||||
|
DCMA_InsertMenuItems(hDCMA, hDCIA, pidlFolder, pDataObject, keys, keys, &qcmi, 0, m_site);
|
||||||
|
}
|
||||||
|
|
||||||
/* We shouldn't use the site window here because the menu should work even when we don't have a site */
|
/* We shouldn't use the site window here because the menu should work even when we don't have a site */
|
||||||
HWND hwndDummy = CreateWindowEx(0,
|
HWND hwndDummy = CreateWindowEx(0,
|
||||||
|
@ -279,16 +290,39 @@ HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, D
|
||||||
|
|
||||||
DestroyWindow(hwndDummy);
|
DestroyWindow(hwndDummy);
|
||||||
|
|
||||||
if (uCommand == 0)
|
HRESULT hr = S_FALSE; // S_FALSE means we did not handle the command
|
||||||
return S_FALSE;
|
C_ASSERT(IDM_COPYHERE < DROPIDM_EXTFIRST && IDM_MOVEHERE < DROPIDM_EXTFIRST &&
|
||||||
|
IDM_LINKHERE < DROPIDM_EXTFIRST && DROPIDM_EXTFIRST > 0);
|
||||||
|
if (uCommand >= DROPIDM_EXTFIRST && uCommand <= DROPIDM_EXTLAST)
|
||||||
|
{
|
||||||
|
CMINVOKECOMMANDINFO ici = { sizeof(ici), 0, m_hwndSite, MAKEINTRESOURCEA(uCommand - DROPIDM_EXTFIRST) };
|
||||||
|
ici.nShow = SW_SHOW;
|
||||||
|
if (m_grfKeyState & MK_SHIFT)
|
||||||
|
ici.fMask |= CMIC_MASK_SHIFT_DOWN;
|
||||||
|
if (m_grfKeyState & MK_CONTROL)
|
||||||
|
ici.fMask |= CMIC_MASK_CONTROL_DOWN;
|
||||||
|
DCMA_InvokeCommand(hDCMA, &ici);
|
||||||
|
hr = S_OK;
|
||||||
|
*pdwEffect = DROPEFFECT_NONE;
|
||||||
|
}
|
||||||
|
else if (uCommand == 0)
|
||||||
|
{
|
||||||
|
hr = S_OK;
|
||||||
|
*pdwEffect = DROPEFFECT_NONE;
|
||||||
|
}
|
||||||
else if (uCommand == IDM_COPYHERE)
|
else if (uCommand == IDM_COPYHERE)
|
||||||
*pdwEffect = DROPEFFECT_COPY;
|
*pdwEffect = DROPEFFECT_COPY;
|
||||||
else if (uCommand == IDM_MOVEHERE)
|
else if (uCommand == IDM_MOVEHERE)
|
||||||
*pdwEffect = DROPEFFECT_MOVE;
|
*pdwEffect = DROPEFFECT_MOVE;
|
||||||
else if (uCommand == IDM_LINKHERE)
|
else if (uCommand == IDM_LINKHERE)
|
||||||
*pdwEffect = DROPEFFECT_LINK;
|
*pdwEffect = DROPEFFECT_LINK;
|
||||||
|
else
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
|
||||||
return S_OK;
|
DCMA_Destroy(hDCMA);
|
||||||
|
DCIA_Destroy(hDCIA);
|
||||||
|
DestroyMenu(hmenu);
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CFSDropTarget::_RepositionItems(IShellFolderView *psfv, IDataObject *pdtobj, POINTL pt)
|
HRESULT CFSDropTarget::_RepositionItems(IShellFolderView *psfv, IDataObject *pdtobj, POINTL pt)
|
||||||
|
@ -461,7 +495,7 @@ HRESULT WINAPI CFSDropTarget::Drop(IDataObject *pDataObject,
|
||||||
if (m_grfKeyState & MK_RBUTTON)
|
if (m_grfKeyState & MK_RBUTTON)
|
||||||
{
|
{
|
||||||
HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect, dwAvailableEffects);
|
HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect, dwAvailableEffects);
|
||||||
if (FAILED_UNEXPECTEDLY(hr) || hr == S_FALSE)
|
if (FAILED_UNEXPECTEDLY(hr) || hr == S_OK)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#ifndef _CFSDROPTARGET_H_
|
#ifndef _CFSDROPTARGET_H_
|
||||||
#define _CFSDROPTARGET_H_
|
#define _CFSDROPTARGET_H_
|
||||||
|
|
||||||
|
#define DROPIDM_EXTFIRST 100
|
||||||
|
#define DROPIDM_EXTLAST 0x7fff
|
||||||
|
|
||||||
class CFSDropTarget :
|
class CFSDropTarget :
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
public IDropTarget,
|
public IDropTarget,
|
||||||
|
|
|
@ -179,6 +179,30 @@ SHELL32_ShowShellExtensionProperties(const CLSID *pClsid, IDataObject *pDO);
|
||||||
HRESULT
|
HRESULT
|
||||||
SHELL_ShowItemIDListProperties(LPCITEMIDLIST pidl);
|
SHELL_ShowItemIDListProperties(LPCITEMIDLIST pidl);
|
||||||
|
|
||||||
|
typedef HDSA HDCMA; // DynamicContextMenuArray
|
||||||
|
typedef struct _DCMENTRY
|
||||||
|
{
|
||||||
|
IContextMenu *pCM;
|
||||||
|
UINT idCmdFirst;
|
||||||
|
UINT idCmdLast;
|
||||||
|
} DCMENTRY;
|
||||||
|
#define DCMA_Create() ( (HDCMA)DSA_Create(sizeof(DCMENTRY), 4) )
|
||||||
|
void DCMA_Destroy(HDCMA hDCMA);
|
||||||
|
#define DCMA_GetEntry(hDCMA, iItem) ( (DCMENTRY*)DSA_GetItemPtr((HDSA)(hDCMA), (iItem)) )
|
||||||
|
HRESULT DCMA_InvokeCommand(HDCMA hDCMA, CMINVOKECOMMANDINFO *pICI);
|
||||||
|
|
||||||
|
UINT
|
||||||
|
DCMA_InsertMenuItems(
|
||||||
|
_In_ HDCMA hDCMA,
|
||||||
|
_In_ HDCIA hDCIA,
|
||||||
|
_In_opt_ LPCITEMIDLIST pidlFolder,
|
||||||
|
_In_opt_ IDataObject *pDO,
|
||||||
|
_In_opt_ HKEY *pKeys,
|
||||||
|
_In_opt_ UINT nKeys,
|
||||||
|
_In_ QCMINFO *pQCMI,
|
||||||
|
_In_opt_ UINT fCmf,
|
||||||
|
_In_opt_ IUnknown *pUnkSite);
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
SHELL32_DefaultContextMenuCallBack(IShellFolder *psf, IDataObject *pdo, UINT msg);
|
SHELL32_DefaultContextMenuCallBack(IShellFolder *psf, IDataObject *pdo, UINT msg);
|
||||||
UINT
|
UINT
|
||||||
|
|
|
@ -9,17 +9,17 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
static HRESULT
|
HRESULT
|
||||||
SHELL_GetShellExtensionRegCLSID(HKEY hKey, LPCWSTR KeyName, CLSID &clsid)
|
SHELL_GetShellExtensionRegCLSID(HKEY hKey, LPCWSTR KeyName, CLSID *pClsId)
|
||||||
{
|
{
|
||||||
// First try the key name
|
// First try the key name
|
||||||
if (SUCCEEDED(SHCLSIDFromStringW(KeyName, &clsid)))
|
if (SUCCEEDED(SHCLSIDFromStringW(KeyName, pClsId)))
|
||||||
return S_OK;
|
return S_OK;
|
||||||
WCHAR buf[42];
|
WCHAR buf[42];
|
||||||
DWORD cb = sizeof(buf);
|
DWORD cb = sizeof(buf);
|
||||||
// and then the default value
|
// and then the default value
|
||||||
DWORD err = RegGetValueW(hKey, KeyName, NULL, RRF_RT_REG_SZ, NULL, buf, &cb);
|
DWORD err = RegGetValueW(hKey, KeyName, NULL, RRF_RT_REG_SZ, NULL, buf, &cb);
|
||||||
return !err ? SHCLSIDFromStringW(buf, &clsid) : HRESULT_FROM_WIN32(err);
|
return !err ? SHCLSIDFromStringW(buf, pClsId) : HRESULT_FROM_WIN32(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT
|
static HRESULT
|
||||||
|
@ -148,7 +148,7 @@ SHELL32_OpenPropSheet(LPCWSTR pszCaption, HKEY *ahKeys, UINT cKeys,
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
CLSID clsid;
|
CLSID clsid;
|
||||||
if (SUCCEEDED(SHELL_GetShellExtensionRegCLSID(hKey, KeyName, clsid)))
|
if (SUCCEEDED(SHELL_GetShellExtensionRegCLSID(hKey, KeyName, &clsid)))
|
||||||
AddPropSheetHandlerPages(clsid, pDO, hKeyProgID, psh);
|
AddPropSheetHandlerPages(clsid, pDO, hKeyProgID, psh);
|
||||||
}
|
}
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
|
|
|
@ -466,5 +466,5 @@
|
||||||
754 stub -noname SHLimitInputEditWithFlags
|
754 stub -noname SHLimitInputEditWithFlags
|
||||||
755 stdcall -noname PathIsEqualOrSubFolder(wstr wstr)
|
755 stdcall -noname PathIsEqualOrSubFolder(wstr wstr)
|
||||||
756 stub -noname DeleteFileThumbnail
|
756 stub -noname DeleteFileThumbnail
|
||||||
757 stdcall -version=0x600+ DisplayNameOfW(ptr ptr long ptr long)
|
757 stdcall -noname -version=0x600+ DisplayNameOfW(ptr ptr long ptr long)
|
||||||
866 stdcall -version=0x600+ SHExtCoCreateInstance(wstr ptr ptr ptr ptr)
|
866 stdcall -noname -version=0x600+ SHExtCoCreateInstance(wstr ptr ptr ptr ptr)
|
||||||
|
|
|
@ -184,6 +184,7 @@ void CloseRegKeyArray(HKEY* array, UINT cKeys);
|
||||||
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys);
|
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys);
|
||||||
LSTATUS AddClsidKeyToArray(REFCLSID clsid, HKEY* array, UINT* cKeys);
|
LSTATUS AddClsidKeyToArray(REFCLSID clsid, HKEY* array, UINT* cKeys);
|
||||||
void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array, UINT* cKeys);
|
void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array, UINT* cKeys);
|
||||||
|
void AddPidlClassKeysToArray(LPCITEMIDLIST pidl, HKEY* array, UINT* cKeys);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
|
|
@ -490,12 +490,23 @@ void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array,
|
||||||
AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
|
AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
|
||||||
AddClassKeyToArray(L"Directory", array, cKeys);
|
AddClassKeyToArray(L"Directory", array, cKeys);
|
||||||
}
|
}
|
||||||
|
else if (_ILIsDrive(pidl))
|
||||||
|
{
|
||||||
|
AddClassKeyToArray(L"Drive", array, cKeys);
|
||||||
|
AddClassKeyToArray(L"Folder", array, cKeys);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERR("Got non FS pidl\n");
|
ERR("Got non FS pidl\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddPidlClassKeysToArray(LPCITEMIDLIST pidl, HKEY* array, UINT* cKeys)
|
||||||
|
{
|
||||||
|
if ((pidl = ILFindLastID(pidl)) != NULL)
|
||||||
|
AddFSClassKeysToArray(1, &pidl, array, cKeys);
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
|
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
|
||||||
{
|
{
|
||||||
CDataObjectHIDA cida(pDataObject);
|
CDataObjectHIDA cida(pDataObject);
|
||||||
|
|
|
@ -1836,6 +1836,35 @@ SHELL_CreateShell32DefaultExtractIcon(int IconIndex, REFIID riid, LPVOID *ppvOut
|
||||||
return initIcon->QueryInterface(riid, ppvOut);
|
return initIcon->QueryInterface(riid, ppvOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DCIA_AddEntry(HDCIA hDCIA, REFCLSID rClsId)
|
||||||
|
{
|
||||||
|
for (UINT i = 0;; ++i)
|
||||||
|
{
|
||||||
|
const CLSID *pClsId = DCIA_GetEntry(hDCIA, i);
|
||||||
|
if (!pClsId)
|
||||||
|
break;
|
||||||
|
if (IsEqualGUID(*pClsId, rClsId))
|
||||||
|
return i; // Don't allow duplicates
|
||||||
|
}
|
||||||
|
return DSA_AppendItem((HDSA)hDCIA, const_cast<CLSID*>(&rClsId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCIA_AddShellExSubkey(HDCIA hDCIA, HKEY hProgId, PCWSTR pszSubkey)
|
||||||
|
{
|
||||||
|
WCHAR szKey[200];
|
||||||
|
PathCombineW(szKey, L"shellex", pszSubkey);
|
||||||
|
HKEY hEnum;
|
||||||
|
if (RegOpenKeyExW(hProgId, szKey, 0, KEY_READ, &hEnum) != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
for (UINT i = 0; RegEnumKeyW(hEnum, i++, szKey, _countof(szKey)) == ERROR_SUCCESS;)
|
||||||
|
{
|
||||||
|
CLSID clsid;
|
||||||
|
if (SUCCEEDED(SHELL_GetShellExtensionRegCLSID(hEnum, szKey, &clsid)))
|
||||||
|
DCIA_AddEntry(hDCIA, clsid);
|
||||||
|
}
|
||||||
|
RegCloseKey(hEnum);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* SHIsBadInterfacePtr [SHELL32.84]
|
* SHIsBadInterfacePtr [SHELL32.84]
|
||||||
*
|
*
|
||||||
|
|
|
@ -120,6 +120,14 @@ SHELL_CreateFallbackExtractIconForNoAssocFile(REFIID riid, LPVOID *ppvOut)
|
||||||
return SHELL_CreateShell32DefaultExtractIcon(id > 1 ? -id : 0, riid, ppvOut);
|
return SHELL_CreateShell32DefaultExtractIcon(id > 1 ? -id : 0, riid, ppvOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef HDSA HDCIA; // DynamicClassIdArray
|
||||||
|
#define DCIA_Create() ( (HDCIA)DSA_Create(sizeof(CLSID), 4) )
|
||||||
|
#define DCIA_Destroy(hDCIA) DSA_Destroy((HDSA)(hDCIA))
|
||||||
|
#define DCIA_GetCount(hDCIA) DSA_GetItemCount((HDSA)(hDCIA))
|
||||||
|
#define DCIA_GetEntry(hDCIA, iItem) ( (const CLSID*)DSA_GetItemPtr((HDSA)(hDCIA), (iItem)) )
|
||||||
|
int DCIA_AddEntry(HDCIA hDCIA, REFCLSID rClsId);
|
||||||
|
void DCIA_AddShellExSubkey(HDCIA hDCIA, HKEY hProgId, PCWSTR pszSubkey);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
struct ClipboardViewerChain
|
struct ClipboardViewerChain
|
||||||
{
|
{
|
||||||
|
|
|
@ -133,6 +133,11 @@ HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cid
|
||||||
HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECLSPEC_HIDDEN;
|
HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECLSPEC_HIDDEN;
|
||||||
HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECLSPEC_HIDDEN;
|
HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
HRESULT SHELL_GetShellExtensionRegCLSID(
|
||||||
|
HKEY hKey,
|
||||||
|
LPCWSTR KeyName,
|
||||||
|
CLSID *pClsId);
|
||||||
|
|
||||||
/* Change Notification */
|
/* Change Notification */
|
||||||
void InitChangeNotifications(void) DECLSPEC_HIDDEN;
|
void InitChangeNotifications(void) DECLSPEC_HIDDEN;
|
||||||
void FreeChangeNotifications(void) DECLSPEC_HIDDEN;
|
void FreeChangeNotifications(void) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue