Allow loading shell extensions
authorThomas Bluemel <thomas@reactsoft.com>
Wed, 26 Sep 2007 04:30:57 +0000 (04:30 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Wed, 26 Sep 2007 04:30:57 +0000 (04:30 +0000)
svn path=/trunk/; revision=29207

reactos/dll/cpl/main/keyboard.c
reactos/dll/cpl/main/main.c
reactos/dll/cpl/main/main.h
reactos/dll/cpl/main/main.rbuild
reactos/dll/cpl/main/mouse.c

index a3db0bb..5e724f6 100644 (file)
 #include <devguid.h>
 #include <commctrl.h>
 #include <prsht.h>
+#include <shlobj.h>
 #include <cpl.h>
+#include <regstr.h>
 
 #include "main.h"
 #include "resource.h"
 
 #define ID_BLINK_TIMER 345
 
-
 typedef struct _SPEED_DATA
 {
     INT nKeyboardDelay;
@@ -48,7 +49,6 @@ typedef struct _SPEED_DATA
     RECT rcCursor;
 } SPEED_DATA, *PSPEED_DATA;
 
-
 /* Property page dialog callback */
 static INT_PTR CALLBACK
 KeyboardSpeedProc(IN HWND hwndDlg,
@@ -296,9 +296,11 @@ KeybHardwareProc(IN HWND hwndDlg,
 LONG APIENTRY
 KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
 {
-    PROPSHEETPAGE psp[2];
+    HPROPSHEETPAGE hpsp[MAX_CPL_PAGES];
     PROPSHEETHEADER psh;
+    HPSXA hpsxa;
     TCHAR szCaption[256];
+    LONG ret;
 
     UNREFERENCED_PARAMETER(lParam);
     UNREFERENCED_PARAMETER(wParam);
@@ -309,19 +311,31 @@ KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
 
     ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
     psh.dwSize = sizeof(PROPSHEETHEADER);
-    psh.dwFlags =  PSH_PROPSHEETPAGE | PSH_PROPTITLE;
+    psh.dwFlags =  PSH_PROPTITLE;
     psh.hwndParent = NULL;
     psh.hInstance = hApplet;
     psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_2));
     psh.pszCaption = szCaption;
-    psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
     psh.nStartPage = 0;
-    psh.ppsp = psp;
+    psh.phpage = hpsp;
+
+    /* Load additional pages provided by shell extensions */
+    hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Keyboard"), MAX_CPL_PAGES - psh.nPages);
+
+    /* NOTE: The speed page (CPLPAGE_KEYBOARD_SPEED) cannot be replaced by
+             shell extensions since Win2k! */
+    InitPropSheetPage(&psh, IDD_KEYBSPEED, KeyboardSpeedProc);
+    InitPropSheetPage(&psh, IDD_HARDWARE, KeybHardwareProc);
+
+    if (hpsxa != NULL)
+        SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh);
+
+    ret = (LONG)(PropertySheet(&psh) != -1);
 
-    InitPropSheetPage(&psp[0], IDD_KEYBSPEED, KeyboardSpeedProc);
-    InitPropSheetPage(&psp[1], IDD_HARDWARE, KeybHardwareProc);
+    if (hpsxa != NULL)
+        SHDestroyPropSheetExtArray(hpsxa);
 
-    return (LONG)(PropertySheet(&psh) != -1);
+    return ret;
 }
 
 /* EOF */
index a0bc9f5..928f077 100644 (file)
@@ -30,6 +30,7 @@
 #include <devguid.h>
 #include <commctrl.h>
 #include <cpl.h>
+#include <cplext.h>
 
 #include "main.h"
 #include "resource.h"
@@ -49,15 +50,42 @@ APPLET Applets[NUM_APPLETS] =
 };
 
 
-VOID
-InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc)
+BOOL
+InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc)
 {
-    ZeroMemory(psp, sizeof(PROPSHEETPAGE));
-    psp->dwSize = sizeof(PROPSHEETPAGE);
-    psp->dwFlags = PSP_DEFAULT;
-    psp->hInstance = hApplet;
-    psp->pszTemplate = MAKEINTRESOURCE(idDlg);
-    psp->pfnDlgProc = DlgProc;
+    HPROPSHEETPAGE hPage;
+    PROPSHEETPAGE psp;
+
+    if (ppsh->nPages < MAX_CPL_PAGES)
+    {
+        ZeroMemory(&psp, sizeof(psp));
+        psp.dwSize = sizeof(psp);
+        psp.dwFlags = PSP_DEFAULT;
+        psp.hInstance = hApplet;
+        psp.pszTemplate = MAKEINTRESOURCE(idDlg);
+        psp.pfnDlgProc = DlgProc;
+
+        hPage = CreatePropertySheetPage(&psp);
+        if (hPage != NULL)
+        {
+            return PropSheetAddPage(hPage, (LPARAM)ppsh);
+        }
+    }
+
+    return FALSE;
+}
+
+BOOL CALLBACK
+PropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam)
+{
+    PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
+    if (ppsh != NULL && ppsh->nPages < MAX_CPL_PAGES)
+    {
+        ppsh->phpage[ppsh->nPages++] = hpage;
+        return TRUE;
+    }
+
+    return FALSE;
 }
 
 
index 53e938c..18d713c 100644 (file)
@@ -26,6 +26,7 @@ typedef struct _APPLET
 
 extern HINSTANCE hApplet;
 
+#define MAX_CPL_PAGES   32
 
 /* keyboard.c */
 
@@ -34,11 +35,11 @@ KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
 
 /* main.c */
 
-VOID
-InitPropSheetPage(PROPSHEETPAGE *psp,
-                 WORD idDlg,
-                 DLGPROC DlgProc);
+BOOL
+InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc);
 
+BOOL CALLBACK
+PropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam);
 
 /* mouse.c */
 
index 79932ec..440f6fe 100644 (file)
@@ -13,6 +13,7 @@
        <library>comctl32</library>
        <library>devmgr</library>
        <library>comdlg32</library>
+       <library>shell32</library>
        <library>gdi32</library>
        <library>msvcrt</library>
        <file>keyboard.c</file>
index ebceac2..d748d50 100644 (file)
@@ -38,6 +38,9 @@
 #include <tchar.h>
 #include <math.h>
 #include <limits.h>
+#include <shlobj.h>
+#include <cplext.h>
+#include <regstr.h>
 
 #include <stdio.h>
 
@@ -54,7 +57,6 @@
 #define MAX_DOUBLE_CLICK_SPEED         900
 #define DEFAULT_WHEEL_SCROLL_LINES     3
 
-
 typedef struct _BUTTON_DATA
 {
     ULONG g_SwapMouseButtons;
@@ -1794,13 +1796,29 @@ WheelProc(IN HWND hwndDlg,
     return FALSE;
 }
 
+static const struct
+{
+    WORD idDlg;
+    DLGPROC DlgProc;
+    UINT uiReplaceWith;
+} PropPages[] =
+{
+    { IDD_PAGE_BUTTON, ButtonProc, CPLPAGE_MOUSE_BUTTONS },
+    { IDD_PAGE_POINTER, PointerProc, 0 },
+    { IDD_PAGE_OPTION, OptionProc, CPLPAGE_MOUSE_PTRMOTION },
+    { IDD_PAGE_WHEEL, WheelProc, CPLPAGE_MOUSE_WHEEL },
+    { IDD_HARDWARE, MouseHardwareProc, 0 },
+};
 
 LONG APIENTRY
 MouseApplet(HWND hwnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
 {
-    PROPSHEETPAGE psp[5];
+    HPROPSHEETPAGE hpsp[MAX_CPL_PAGES];
     PROPSHEETHEADER psh;
+    HPSXA hpsxa;
     TCHAR Caption[256];
+    UINT i;
+    LONG ret;
 
     UNREFERENCED_PARAMETER(lParam1);
     UNREFERENCED_PARAMETER(lParam2);
@@ -1811,21 +1829,40 @@ MouseApplet(HWND hwnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
 
     ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
     psh.dwSize = sizeof(PROPSHEETHEADER);
-    psh.dwFlags =  PSH_PROPSHEETPAGE | PSH_PROPTITLE;
+    psh.dwFlags = PSH_PROPTITLE;
     psh.hwndParent = NULL;
     psh.hInstance = hApplet;
     psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_1));
     psh.pszCaption = Caption;
-    psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
     psh.nStartPage = 0;
-    psh.ppsp = psp;
-
-    InitPropSheetPage(&psp[0], IDD_PAGE_BUTTON, ButtonProc);
-    InitPropSheetPage(&psp[1], IDD_PAGE_POINTER, PointerProc);
-    InitPropSheetPage(&psp[2], IDD_PAGE_OPTION, OptionProc);
-    InitPropSheetPage(&psp[3], IDD_PAGE_WHEEL, WheelProc);
-    InitPropSheetPage(&psp[4], IDD_HARDWARE, MouseHardwareProc);
-    return (LONG)(PropertySheet(&psh) != -1);
+    psh.phpage = hpsp;
+
+    /* Load additional pages provided by shell extensions */
+    hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Mouse"), MAX_CPL_PAGES - psh.nPages);
+
+    for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
+    {
+        /* Override the background page if requested by a shell extension */
+        if (PropPages[i].uiReplaceWith != 0 && hpsxa != NULL &&
+            SHReplaceFromPropSheetExtArray(hpsxa, PropPages[i].uiReplaceWith, PropSheetAddPage, (LPARAM)&psh) != 0)
+        {
+            /* The shell extension added one or more pages to replace the background page.
+               Don't create the built-in page anymore! */
+            continue;
+        }
+
+        InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc);
+    }
+
+    if (hpsxa != NULL)
+        SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh);
+
+    ret = (LONG)(PropertySheet(&psh) != -1);
+
+    if (hpsxa != NULL)
+        SHDestroyPropSheetExtArray(hpsxa);
+
+    return ret;
 }
 
 /* EOF */