shell32: Implement the property sheet extension array functions.
Implement the SHAddFromPropSheetExtArray, SHCreatePropSheetExtArray, SHReplaceFromPropSheetExtArray and SHDestroyPropSheetExtArray functions that are used to extend/replace property sheets by shell extensions.
This commit is contained in:
parent
8333cf88d8
commit
fb5c516dfd
|
@ -1513,13 +1513,68 @@ DWORD WINAPI SHELL32_714(LPVOID x)
|
|||
return 0;
|
||||
}
|
||||
|
||||
typedef struct _PSXA
|
||||
{
|
||||
UINT uiCount;
|
||||
UINT uiAllocated;
|
||||
IShellPropSheetExt *pspsx[1];
|
||||
} PSXA, *PPSXA;
|
||||
|
||||
typedef struct _PSXA_CALL
|
||||
{
|
||||
LPFNADDPROPSHEETPAGE lpfnAddReplaceWith;
|
||||
LPARAM lParam;
|
||||
BOOL bCalled;
|
||||
BOOL bMultiple;
|
||||
UINT uiCount;
|
||||
} PSXA_CALL, *PPSXA_CALL;
|
||||
|
||||
static BOOL CALLBACK PsxaCall(HPROPSHEETPAGE hpage, LPARAM lParam)
|
||||
{
|
||||
PPSXA_CALL Call = (PPSXA_CALL)lParam;
|
||||
|
||||
if (Call != NULL)
|
||||
{
|
||||
if ((Call->bMultiple || !Call->bCalled) &&
|
||||
Call->lpfnAddReplaceWith(hpage, Call->lParam))
|
||||
{
|
||||
Call->bCalled = TRUE;
|
||||
Call->uiCount++;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHAddFromPropSheetExtArray [SHELL32.167]
|
||||
*/
|
||||
UINT WINAPI SHAddFromPropSheetExtArray(HPSXA hpsxa, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
|
||||
{
|
||||
FIXME("(%p,%p,%08lx)stub\n", hpsxa, lpfnAddPage, lParam);
|
||||
return 0;
|
||||
PSXA_CALL Call;
|
||||
UINT i;
|
||||
PPSXA psxa = (PPSXA)hpsxa;
|
||||
|
||||
TRACE("(%p,%p,%08lx)\n", hpsxa, lpfnAddPage, lParam);
|
||||
|
||||
if (psxa)
|
||||
{
|
||||
ZeroMemory(&Call, sizeof(Call));
|
||||
Call.lpfnAddReplaceWith = lpfnAddPage;
|
||||
Call.lParam = lParam;
|
||||
Call.bMultiple = TRUE;
|
||||
|
||||
/* Call the AddPage method of all registered IShellPropSheetExt interfaces */
|
||||
for (i = 0; i != psxa->uiCount; i++)
|
||||
{
|
||||
psxa->pspsx[i]->lpVtbl->AddPages(psxa->pspsx[i], PsxaCall, (LPARAM)&Call);
|
||||
}
|
||||
|
||||
return Call.uiCount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1527,8 +1582,102 @@ UINT WINAPI SHAddFromPropSheetExtArray(HPSXA hpsxa, LPFNADDPROPSHEETPAGE lpfnAdd
|
|||
*/
|
||||
HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface)
|
||||
{
|
||||
FIXME("(%p,%s,%u)stub\n", hKey, debugstr_w(pszSubKey), max_iface);
|
||||
return NULL;
|
||||
static const WCHAR szPropSheetSubKey[] = {'s','h','e','l','l','e','x','\\','P','r','o','p','e','r','t','y','S','h','e','e','t','H','a','n','d','l','e','r','s',0};
|
||||
WCHAR szHandler[64];
|
||||
DWORD dwHandlerLen;
|
||||
WCHAR szClsidHandler[39];
|
||||
DWORD dwClsidSize;
|
||||
CLSID clsid;
|
||||
LONG lRet;
|
||||
DWORD dwIndex;
|
||||
IShellExtInit *psxi;
|
||||
IShellPropSheetExt *pspsx;
|
||||
HKEY hkBase, hkPropSheetHandlers;
|
||||
PPSXA psxa = NULL;
|
||||
|
||||
TRACE("(%p,%s,%u)\n", hKey, debugstr_w(pszSubKey), max_iface);
|
||||
|
||||
if (max_iface == 0)
|
||||
return NULL;
|
||||
|
||||
/* Open the registry key */
|
||||
lRet = RegOpenKeyW(hKey, pszSubKey, &hkBase);
|
||||
if (lRet != ERROR_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
lRet = RegOpenKeyExW(hkBase, szPropSheetSubKey, 0, KEY_ENUMERATE_SUB_KEYS, &hkPropSheetHandlers);
|
||||
RegCloseKey(hkBase);
|
||||
if (lRet == ERROR_SUCCESS)
|
||||
{
|
||||
/* Create and initialize the Property Sheet Extensions Array */
|
||||
psxa = (PPSXA)LocalAlloc(LMEM_FIXED, FIELD_OFFSET(PSXA, pspsx[max_iface]));
|
||||
if (psxa)
|
||||
{
|
||||
ZeroMemory(psxa, FIELD_OFFSET(PSXA, pspsx[max_iface]));
|
||||
psxa->uiAllocated = max_iface;
|
||||
|
||||
/* Enumerate all subkeys and attempt to load the shell extensions */
|
||||
dwIndex = 0;
|
||||
do
|
||||
{
|
||||
dwHandlerLen = sizeof(szHandler) / sizeof(szHandler[0]);
|
||||
lRet = RegEnumKeyExW(hkPropSheetHandlers, dwIndex++, szHandler, &dwHandlerLen, NULL, NULL, NULL, NULL);
|
||||
if (lRet != ERROR_SUCCESS)
|
||||
{
|
||||
if (lRet == ERROR_MORE_DATA)
|
||||
continue;
|
||||
|
||||
if (lRet == ERROR_NO_MORE_ITEMS)
|
||||
lRet = ERROR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
dwClsidSize = sizeof(szClsidHandler);
|
||||
if (SHGetValueW(hkPropSheetHandlers, szHandler, NULL, NULL, szClsidHandler, &dwClsidSize) == ERROR_SUCCESS)
|
||||
{
|
||||
/* Force a NULL-termination and convert the string */
|
||||
szClsidHandler[(sizeof(szClsidHandler) / sizeof(szClsidHandler[0])) - 1] = 0;
|
||||
if (SUCCEEDED(SHCLSIDFromStringW(szClsidHandler, &clsid)))
|
||||
{
|
||||
/* Attempt to get an IShellPropSheetExt and an IShellExtInit instance.
|
||||
Only if both interfaces are supported it's a real shell extension.
|
||||
Then call IShellExtInit's Initialize method. */
|
||||
if (SUCCEEDED(CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER/* | CLSCTX_NO_CODE_DOWNLOAD */, &IID_IShellPropSheetExt, (LPVOID *)&pspsx)))
|
||||
{
|
||||
if (SUCCEEDED(pspsx->lpVtbl->QueryInterface(pspsx, &IID_IShellExtInit, (PVOID *)&psxi)))
|
||||
{
|
||||
if (SUCCEEDED(psxi->lpVtbl->Initialize(psxi, NULL, NULL, hKey)))
|
||||
{
|
||||
/* Add the IShellPropSheetExt instance to the array */
|
||||
psxa->pspsx[psxa->uiCount++] = pspsx;
|
||||
}
|
||||
else
|
||||
{
|
||||
psxi->lpVtbl->Release(psxi);
|
||||
pspsx->lpVtbl->Release(pspsx);
|
||||
}
|
||||
}
|
||||
else
|
||||
pspsx->lpVtbl->Release(pspsx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (psxa->uiCount != psxa->uiAllocated);
|
||||
}
|
||||
else
|
||||
lRet = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
RegCloseKey(hkPropSheetHandlers);
|
||||
}
|
||||
|
||||
if (lRet != ERROR_SUCCESS && psxa)
|
||||
{
|
||||
SHDestroyPropSheetExtArray((HPSXA)psxa);
|
||||
psxa = NULL;
|
||||
}
|
||||
|
||||
return (HPSXA)psxa;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1536,8 +1685,30 @@ HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_if
|
|||
*/
|
||||
UINT WINAPI SHReplaceFromPropSheetExtArray(HPSXA hpsxa, UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
|
||||
{
|
||||
FIXME("(%p,%u,%p,%08lx)stub\n", hpsxa, uPageID, lpfnReplaceWith, lParam);
|
||||
return 0;
|
||||
PSXA_CALL Call;
|
||||
UINT i;
|
||||
PPSXA psxa = (PPSXA)hpsxa;
|
||||
|
||||
TRACE("(%p,%u,%p,%08lx)\n", hpsxa, uPageID, lpfnReplaceWith, lParam);
|
||||
|
||||
if (psxa)
|
||||
{
|
||||
ZeroMemory(&Call, sizeof(Call));
|
||||
Call.lpfnAddReplaceWith = lpfnReplaceWith;
|
||||
Call.lParam = lParam;
|
||||
|
||||
/* Call the ReplacePage method of all registered IShellPropSheetExt interfaces.
|
||||
Each shell extension is only allowed to call the callback once during the callback. */
|
||||
for (i = 0; i != psxa->uiCount; i++)
|
||||
{
|
||||
Call.bCalled = FALSE;
|
||||
psxa->pspsx[i]->lpVtbl->ReplacePage(psxa->pspsx[i], uPageID, PsxaCall, (LPARAM)&Call);
|
||||
}
|
||||
|
||||
return Call.uiCount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1545,7 +1716,20 @@ UINT WINAPI SHReplaceFromPropSheetExtArray(HPSXA hpsxa, UINT uPageID, LPFNADDPRO
|
|||
*/
|
||||
void WINAPI SHDestroyPropSheetExtArray(HPSXA hpsxa)
|
||||
{
|
||||
FIXME("(%p)stub\n", hpsxa);
|
||||
UINT i;
|
||||
PPSXA psxa = (PPSXA)hpsxa;
|
||||
|
||||
TRACE("(%p)\n", hpsxa);
|
||||
|
||||
if (psxa)
|
||||
{
|
||||
for (i = 0; i != psxa->uiCount; i++)
|
||||
{
|
||||
psxa->pspsx[i]->lpVtbl->Release(psxa->pspsx[i]);
|
||||
}
|
||||
|
||||
LocalFree((HLOCAL)psxa);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
|
|
@ -41,7 +41,6 @@ DEFINE_SHLGUID(CGID_ShellServiceObject, 0x000214D2L, 0, 0);
|
|||
DEFINE_SHLGUID(CGID_ExplorerBarDoc, 0x000214D3L, 0, 0);
|
||||
|
||||
DEFINE_SHLGUID(IID_IShellIcon, 0x000214E5L, 0, 0);
|
||||
DEFINE_SHLGUID(IID_IShellPropSheetExt, 0x000214E9L, 0, 0);
|
||||
DEFINE_SHLGUID(IID_IShellDetails, 0x000214ECL, 0, 0);
|
||||
DEFINE_SHLGUID(IID_IDelayedRelease, 0x000214EDL, 0, 0);
|
||||
DEFINE_SHLGUID(IID_IShellCopyHookA, 0x000214EFL, 0, 0);
|
||||
|
@ -54,6 +53,7 @@ DEFINE_SHLGUID(IID_IRemoteComputer, 0x000214FEL, 0, 0);
|
|||
DEFINE_SHLGUID(IID_IQueryInfo, 0x00021500L, 0, 0);
|
||||
|
||||
/* avoid duplicate definitions with shobjidl.h (FIXME) */
|
||||
/* DEFINE_SHLGUID(IID_IShellPropSheetExt, 0x000214E9L, 0, 0); */
|
||||
/* DEFINE_SHLGUID(IID_IExtractIconA, 0x000214EBL, 0, 0); */
|
||||
/* DEFINE_SHLGUID(IID_IExtractIconW, 0x000214FAL, 0, 0); */
|
||||
/* DEFINE_SHLGUID(IID_IContextMenu, 0x000214E4L, 0, 0); */
|
||||
|
|
|
@ -84,6 +84,38 @@ interface IEnumIDList : IUnknown
|
|||
HRESULT Clone( [out] IEnumIDList **ppenum );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* IShellPropSheetExt interface
|
||||
*/
|
||||
cpp_quote("#if 0")
|
||||
typedef LPARAM LPFNSVADDPROPSHEETPAGE;
|
||||
cpp_quote("#else")
|
||||
cpp_quote("#include <prsht.h>")
|
||||
cpp_quote("typedef LPFNADDPROPSHEETPAGE LPFNSVADDPROPSHEETPAGE;")
|
||||
cpp_quote("#endif")
|
||||
|
||||
[
|
||||
object,
|
||||
uuid(000214E9-0000-0000-C000-000000000046),
|
||||
pointer_default(unique)
|
||||
]
|
||||
interface IShellPropSheetExt : IUnknown
|
||||
{
|
||||
enum tagSHELLPROPSHEETEXTPAGEID {
|
||||
EXPPS_FILETYPES = 0x1
|
||||
};
|
||||
|
||||
typedef UINT EXPPS;
|
||||
|
||||
HRESULT AddPages(
|
||||
[in] LPFNSVADDPROPSHEETPAGE pfnAddPage,
|
||||
[in] LPARAM lParam);
|
||||
HRESULT ReplacePage(
|
||||
[in] EXPPS uPageID,
|
||||
[in] LPFNSVADDPROPSHEETPAGE pfnReplaceWith,
|
||||
[in] LPARAM lParam);
|
||||
}
|
||||
typedef IShellPropSheetExt *LPSHELLPROPSHEETEXT;
|
||||
|
||||
/*****************************************************************************
|
||||
* IShellFolder interface
|
||||
|
@ -394,13 +426,6 @@ interface IShellView : IOleWindow
|
|||
SVUIA_INPLACEACTIVATE = 3
|
||||
} SVUIA_STATUS;
|
||||
|
||||
cpp_quote("#if 0")
|
||||
typedef LPARAM LPFNSVADDPROPSHEETPAGE;
|
||||
cpp_quote("#else")
|
||||
cpp_quote("#include <prsht.h>")
|
||||
cpp_quote("typedef LPFNADDPROPSHEETPAGE LPFNSVADDPROPSHEETPAGE;")
|
||||
cpp_quote("#endif")
|
||||
|
||||
HRESULT TranslateAccelerator( [in] MSG *pmsg );
|
||||
HRESULT EnableModeless( [in] BOOL fEnable );
|
||||
HRESULT UIActivate( [in] UINT uState );
|
||||
|
|
Loading…
Reference in New Issue