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:
Thomas Weidenmueller 2007-01-19 14:15:45 +01:00 committed by Alexandre Julliard
parent 8333cf88d8
commit fb5c516dfd
3 changed files with 224 additions and 15 deletions

View File

@ -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);
}
}
/*************************************************************************

View File

@ -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); */

View File

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