[KSPROXY]
[reactos.git] / reactos / dll / cpl / desk / desk.c
index c22e20e..eb13607 100644 (file)
@@ -4,7 +4,7 @@
  * PROJECT:         ReactOS Display Control Panel
  * FILE:            lib/cpl/desk/desk.c
  * PURPOSE:         ReactOS Display Control Panel
- * 
+ *
  * PROGRAMMERS:     Trevor McCort (lycan359@gmail.com)
  */
 
 
 #define NUM_APPLETS    (1)
 
-LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LONG wParam, LONG lParam);
+static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
 
-extern INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-extern INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-extern INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-extern INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+UINT CALLBACK SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
 
 HINSTANCE hApplet = 0;
+HWND hCPLWindow;
 
 /* Applets */
-APPLET Applets[NUM_APPLETS] = 
+APPLET Applets[NUM_APPLETS] =
 {
     {
         IDC_DESK_ICON,
@@ -33,26 +35,97 @@ APPLET Applets[NUM_APPLETS] =
     }
 };
 
+HMENU
+LoadPopupMenu(IN HINSTANCE hInstance,
+              IN LPCTSTR lpMenuName)
+{
+    HMENU hMenu, hSubMenu = NULL;
+
+    hMenu = LoadMenu(hInstance,
+                     lpMenuName);
+
+    if (hMenu != NULL)
+    {
+        hSubMenu = GetSubMenu(hMenu,
+                              0);
+        if (hSubMenu != NULL &&
+            !RemoveMenu(hMenu,
+                        0,
+                        MF_BYPOSITION))
+        {
+            hSubMenu = NULL;
+        }
+
+        DestroyMenu(hMenu);
+    }
+
+    return hSubMenu;
+}
 
-static VOID
-InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc)
+static BOOL CALLBACK
+PropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam)
 {
-    ZeroMemory(psp, sizeof(PROPSHEETPAGE));
-    psp->dwSize = sizeof(PROPSHEETPAGE);
-    psp->dwFlags = PSP_DEFAULT;
-    psp->hInstance = hApplet;
-    psp->pszTemplate = MAKEINTRESOURCE(idDlg);
-    psp->pfnDlgProc = DlgProc;
+    PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
+    if (ppsh != NULL && ppsh->nPages < MAX_DESK_PAGES)
+    {
+        ppsh->phpage[ppsh->nPages++] = hpage;
+        return TRUE;
+    }
+
+    return FALSE;
 }
 
+static BOOL
+InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc, LPFNPSPCALLBACK pfnCallback)
+{
+    HPROPSHEETPAGE hPage;
+    PROPSHEETPAGE psp;
+
+    if (ppsh->nPages < MAX_DESK_PAGES)
+    {
+        ZeroMemory(&psp, sizeof(psp));
+        psp.dwSize = sizeof(psp);
+        psp.dwFlags = PSP_DEFAULT;
+        if (pfnCallback != NULL)
+            psp.dwFlags |= PSP_USECALLBACK;
+        psp.hInstance = hApplet;
+        psp.pszTemplate = MAKEINTRESOURCE(idDlg);
+        psp.pfnDlgProc = DlgProc;
+        psp.pfnCallback = pfnCallback;
+
+        hPage = CreatePropertySheetPage(&psp);
+        if (hPage != NULL)
+        {
+            return PropSheetAddPage(hPage, (LPARAM)ppsh);
+        }
+    }
+
+    return FALSE;
+}
+
+static const struct
+{
+    WORD idDlg;
+    DLGPROC DlgProc;
+    LPFNPSPCALLBACK Callback;
+} PropPages[] =
+{
+    { IDD_BACKGROUND, BackgroundPageProc, NULL },
+    { IDD_SCREENSAVER, ScreenSaverPageProc, NULL },
+    { IDD_APPEARANCE, AppearancePageProc, NULL },
+    { IDD_SETTINGS, SettingsPageProc, SettingsPageCallbackProc },
+};
 
 /* Display Applet */
-LONG APIENTRY
-DisplayApplet(HWND hwnd, UINT uMsg, LONG wParam, LONG lParam)
+static LONG APIENTRY
+DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
 {
-    PROPSHEETPAGE psp[4];
+    HPROPSHEETPAGE hpsp[MAX_DESK_PAGES];
     PROPSHEETHEADER psh;
+    HPSXA hpsxa;
     TCHAR Caption[1024];
+    LONG ret;
+    UINT i;
 
     UNREFERENCED_PARAMETER(lParam);
     UNREFERENCED_PARAMETER(wParam);
@@ -63,21 +136,41 @@ DisplayApplet(HWND hwnd, UINT uMsg, LONG wParam, LONG lParam)
 
     ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
     psh.dwSize = sizeof(PROPSHEETHEADER);
-    psh.dwFlags =  PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_PROPTITLE;
-    psh.hwndParent = NULL;
+    psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
+    psh.hwndParent = hCPLWindow;
     psh.hInstance = hApplet;
     psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_DESK_ICON));
     psh.pszCaption = Caption;
-    psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
+    psh.nPages = 0;
     psh.nStartPage = 0;
-    psh.ppsp = psp;
+    psh.phpage = hpsp;
+
+    /* Allow shell extensions to replace the background page */
+    hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_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].idDlg == IDD_BACKGROUND && hpsxa != NULL &&
+            SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, 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, PropPages[i].Callback);
+    }
+
+    /* NOTE: Don't call SHAddFromPropSheetExtArray here because this applet only allows
+             replacing the background page but not extending the applet by more pages */
+
+    ret = (LONG)(PropertySheet(&psh) != -1);
 
-    InitPropSheetPage(&psp[0], IDD_BACKGROUND, (DLGPROC) BackgroundPageProc);
-    InitPropSheetPage(&psp[1], IDD_SCREENSAVER, (DLGPROC) ScreenSaverPageProc);
-    InitPropSheetPage(&psp[2], IDD_APPEARANCE, (DLGPROC) AppearancePageProc);
-    InitPropSheetPage(&psp[3], IDD_SETTINGS, (DLGPROC) SettingsPageProc);
+    if (hpsxa != NULL)
+        SHDestroyPropSheetExtArray(hpsxa);
 
-    return (LONG)(PropertySheet(&psh) != -1);
+    return ret;
 }
 
 
@@ -106,6 +199,7 @@ CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
             break;
 
         case CPL_DBLCLK:
+            hCPLWindow = hwndCPl;
             Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
             break;
     }
@@ -122,6 +216,7 @@ DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
     switch (dwReason)
     {
         case DLL_PROCESS_ATTACH:
+            CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
             RegisterPreviewControl(hInstDLL);
 //        case DLL_THREAD_ATTACH:
             hApplet = hInstDLL;
@@ -129,6 +224,7 @@ DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
 
         case DLL_PROCESS_DETACH:
             UnregisterPreviewControl(hInstDLL);
+            CoUninitialize();
             break;
     }