SHELL32: Implement the property sheet extension array functions
Thomas Weidenmueller
wine-patches at reactsoft.com
Fri Jan 19 06:52:33 CST 2007
Implements the SHAddFromPropSheetExtArray, SHCreatePropSheetExtArray,
SHReplaceFromPropSheetExtArray and SHDestroyPropSheetExtArray functions
that are used to extend/replace property sheets by shell extensions.
- Thomas
-------------- next part --------------
Index: dlls/shell32/shellord.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shellord.c,v
retrieving revision 1.146
diff -u -r1.146 shellord.c
--- dlls/shell32/shellord.c 19 Jan 2007 12:30:58 -0000 1.146
+++ dlls/shell32/shellord.c 19 Jan 2007 12:42:56 -0000
@@ -1513,13 +1513,68 @@
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,%08x)\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 @@
*/
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,%ws,%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 @@
*/
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,%08x)\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 @@
*/
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);
+ }
}
/*************************************************************************
Index: include/shobjidl.idl
===================================================================
RCS file: /home/wine/wine/include/shobjidl.idl,v
retrieving revision 1.10
diff -u -r1.10 shobjidl.idl
--- include/shobjidl.idl 20 Jul 2006 11:22:17 -0000 1.10
+++ include/shobjidl.idl 19 Jan 2007 12:47:52 -0000
@@ -29,6 +29,13 @@
/*import "prsht.idl";*/
/*import "msxml.idl";*/
+cpp_quote("#if 0")
+ typedef LPARAM LPFNSVADDPROPSHEETPAGE;
+cpp_quote("#else")
+cpp_quote("#include <prsht.h>")
+cpp_quote("typedef LPFNADDPROPSHEETPAGE LPFNSVADDPROPSHEETPAGE;")
+cpp_quote("#endif")
+
/*****************************************************************************
* IPersistFolder interface
@@ -84,6 +91,38 @@
HRESULT Clone( [out] IEnumIDList **ppenum );
}
+/*****************************************************************************
+ * IShellPropSheetExt interface
+ */
+[
+ object,
+ uuid(000214E9-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+interface IShellPropSheetExt : IUnknown
+{
+cpp_quote("#if 0")
+ typedef LPARAM LPFNSVADDPROPSHEETPAGE;
+cpp_quote("#else")
+cpp_quote("#include <prsht.h>")
+cpp_quote("typedef LPFNADDPROPSHEETPAGE LPFNSVADDPROPSHEETPAGE;")
+cpp_quote("#endif")
+
+ 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 +433,6 @@
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 );
More information about the wine-patches
mailing list