[KSPROXY]
[reactos.git] / reactos / dll / cpl / desk / desk.c
index 45f3b6c..eb13607 100644 (file)
@@ -4,25 +4,28 @@
  * PROJECT:         ReactOS Display Control Panel
  * FILE:            lib/cpl/desk/desk.c
  * PURPOSE:         ReactOS Display Control Panel
- * 
+ *
  * PROGRAMMERS:     Trevor McCort (lycan359@gmail.com)
  */
 
 #include "desk.h"
+#include "preview.h"
 
 #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,
@@ -32,67 +35,159 @@ APPLET Applets[NUM_APPLETS] =
     }
 };
 
-static VOID InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc)
+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 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];
-    
-    UNREFERENCED_PARAMETER(lParam)
-    UNREFERENCED_PARAMETER(wParam)
-    UNREFERENCED_PARAMETER(uMsg)
-    UNREFERENCED_PARAMETER(hwnd)
+    LONG ret;
+    UINT i;
+
+    UNREFERENCED_PARAMETER(lParam);
+    UNREFERENCED_PARAMETER(wParam);
+    UNREFERENCED_PARAMETER(uMsg);
+    UNREFERENCED_PARAMETER(hwnd);
 
     LoadString(hApplet, IDS_CPLNAME, Caption, sizeof(Caption) / sizeof(TCHAR));
-    
+
     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;
-    
-    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);
-    
-    return (LONG)(PropertySheet(&psh) != -1);
+    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);
+
+    if (hpsxa != NULL)
+        SHDestroyPropSheetExtArray(hpsxa);
+
+    return ret;
 }
 
 
 /* Control Panel Callback */
-LONG CALLBACK CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
+LONG CALLBACK
+CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
 {
     int i = (int)lParam1;
-    
-    switch(uMsg)
+
+    switch (uMsg)
     {
         case CPL_INIT:
-            {
-                return TRUE;
-            }
-        
+            return TRUE;
+
         case CPL_GETCOUNT:
-            {
-                return NUM_APPLETS;
-            }
-        
+            return NUM_APPLETS;
+
         case CPL_INQUIRE:
             {
                 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
@@ -100,29 +195,38 @@ LONG CALLBACK CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
                 CPlInfo->idIcon = Applets[i].idIcon;
                 CPlInfo->idName = Applets[i].idName;
                 CPlInfo->idInfo = Applets[i].idDescription;
-            } break;
-        
+            }
+            break;
+
         case CPL_DBLCLK:
-            {
-                Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
-            break;
+            hCPLWindow = hwndCPl;
+            Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
+            break;
     }
-    
+
     return FALSE;
 }
 
 
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
+BOOL WINAPI
+DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
 {
-    switch(dwReason)
+    UNREFERENCED_PARAMETER(lpvReserved);
+
+    switch (dwReason)
     {
         case DLL_PROCESS_ATTACH:
-        case DLL_THREAD_ATTACH:
-            {
-                hApplet = hinstDLL;
-            } break;
+            CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+            RegisterPreviewControl(hInstDLL);
+//        case DLL_THREAD_ATTACH:
+            hApplet = hInstDLL;
+            break;
+
+        case DLL_PROCESS_DETACH:
+            UnregisterPreviewControl(hInstDLL);
+            CoUninitialize();
+            break;
     }
-    
+
     return TRUE;
 }
-