1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Display Control Panel 4 * FILE: dll/cpl/desk/desk.c 5 * PURPOSE: ReactOS Display Control Panel 6 * 7 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) 8 */ 9 10 #include "desk.h" 11 #include <shellapi.h> 12 #include <cplext.h> 13 #include <debug.h> 14 15 #define NUM_APPLETS (1) 16 17 static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam); 18 19 INT_PTR CALLBACK ThemesPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 20 INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 21 INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 22 INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 23 INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 24 UINT CALLBACK SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp); 25 26 HINSTANCE hApplet = 0; 27 HWND hCPLWindow; 28 29 /* Applets */ 30 APPLET Applets[NUM_APPLETS] = 31 { 32 { 33 IDC_DESK_ICON, 34 IDS_CPLNAME, 35 IDS_CPLDESCRIPTION, 36 DisplayApplet 37 } 38 }; 39 40 HMENU 41 LoadPopupMenu(IN HINSTANCE hInstance, 42 IN LPCTSTR lpMenuName) 43 { 44 HMENU hMenu, hSubMenu = NULL; 45 46 hMenu = LoadMenu(hInstance, 47 lpMenuName); 48 49 if (hMenu != NULL) 50 { 51 hSubMenu = GetSubMenu(hMenu, 52 0); 53 if (hSubMenu != NULL && 54 !RemoveMenu(hMenu, 55 0, 56 MF_BYPOSITION)) 57 { 58 hSubMenu = NULL; 59 } 60 61 DestroyMenu(hMenu); 62 } 63 64 return hSubMenu; 65 } 66 67 static BOOL CALLBACK 68 DisplayAppletPropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam) 69 { 70 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam; 71 if (ppsh != NULL && ppsh->nPages < MAX_DESK_PAGES) 72 { 73 ppsh->phpage[ppsh->nPages++] = hpage; 74 return TRUE; 75 } 76 77 return FALSE; 78 } 79 80 static BOOL 81 InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc, LPFNPSPCALLBACK pfnCallback) 82 { 83 HPROPSHEETPAGE hPage; 84 PROPSHEETPAGE psp; 85 86 if (ppsh->nPages < MAX_DESK_PAGES) 87 { 88 ZeroMemory(&psp, sizeof(psp)); 89 psp.dwSize = sizeof(psp); 90 psp.dwFlags = PSP_DEFAULT; 91 if (pfnCallback != NULL) 92 psp.dwFlags |= PSP_USECALLBACK; 93 psp.hInstance = hApplet; 94 psp.pszTemplate = MAKEINTRESOURCE(idDlg); 95 psp.pfnDlgProc = DlgProc; 96 psp.pfnCallback = pfnCallback; 97 98 hPage = CreatePropertySheetPage(&psp); 99 if (hPage != NULL) 100 { 101 return DisplayAppletPropSheetAddPage(hPage, (LPARAM)ppsh); 102 } 103 } 104 105 return FALSE; 106 } 107 108 static const struct 109 { 110 WORD idDlg; 111 DLGPROC DlgProc; 112 LPFNPSPCALLBACK Callback; 113 LPWSTR Name; 114 } PropPages[] = 115 { 116 /* { IDD_THEMES, ThemesPageProc, NULL, L"Themes" }, */ /* TODO: */ 117 { IDD_BACKGROUND, BackgroundPageProc, NULL, L"Desktop" }, 118 { IDD_SCREENSAVER, ScreenSaverPageProc, NULL, L"Screen Saver" }, 119 { IDD_APPEARANCE, AppearancePageProc, NULL, L"Appearance" }, 120 { IDD_SETTINGS, SettingsPageProc, SettingsPageCallbackProc, L"Settings" }, 121 }; 122 123 static int CALLBACK 124 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) 125 { 126 // NOTE: This callback is needed to set large icon correctly. 127 HICON hIcon; 128 switch (uMsg) 129 { 130 case PSCB_INITIALIZED: 131 { 132 hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_DESK_ICON)); 133 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 134 break; 135 } 136 } 137 return 0; 138 } 139 140 /* Display Applet */ 141 static LONG APIENTRY 142 DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam) 143 { 144 HPROPSHEETPAGE hpsp[MAX_DESK_PAGES]; 145 PROPSHEETHEADER psh; 146 HPSXA hpsxa = NULL; 147 UINT i; 148 LPWSTR *argv = NULL; 149 LPCWSTR pwszSelectedTab = NULL; 150 LPCWSTR pwszFile = NULL; 151 LPCWSTR pwszAction = NULL; 152 INT nPage = 0; 153 BITMAP bitmap; 154 155 UNREFERENCED_PARAMETER(wParam); 156 157 hCPLWindow = hwnd; 158 159 if (uMsg == CPL_STARTWPARMSW && lParam) 160 { 161 int argc; 162 int i; 163 164 nPage = _wtoi((PWSTR)lParam); 165 166 #if 0 167 argv = CommandLineToArgvW((LPCWSTR)lParam, &argc); 168 #else 169 argv = CommandLineToArgvW(GetCommandLineW(), &argc); 170 #endif 171 172 if (argv && argc) 173 { 174 for (i = 0; i<argc; i++) 175 { 176 #if 0 177 if (argv[i][0] == L'@') 178 pwszSelectedTab = &argv[i][1]; 179 #else 180 if (wcsncmp(argv[i], L"desk,@", 6) == 0) 181 pwszSelectedTab = &argv[i][6]; 182 #endif 183 else if (wcsncmp(argv[i], L"/Action:", 8) == 0) 184 pwszAction = &argv[i][8]; 185 else if (wcsncmp(argv[i], L"/file:", 6) == 0) 186 pwszFile = &argv[i][6]; 187 } 188 } 189 } 190 191 if(pwszAction && wcsncmp(pwszAction, L"ActivateMSTheme", 15) == 0) 192 { 193 ActivateThemeFile(pwszFile); 194 goto cleanup; 195 } 196 197 g_GlobalData.pwszFile = pwszFile; 198 g_GlobalData.pwszAction = pwszAction; 199 g_GlobalData.desktop_color = GetSysColor(COLOR_DESKTOP); 200 201 /* Initialize the monitor preview bitmap, used on multiple pages */ 202 g_GlobalData.hMonitorBitmap = LoadBitmapW(hApplet, MAKEINTRESOURCEW(IDC_MONITOR)); 203 if (g_GlobalData.hMonitorBitmap != NULL) 204 { 205 GetObjectW(g_GlobalData.hMonitorBitmap, sizeof(bitmap), &bitmap); 206 207 g_GlobalData.bmMonWidth = bitmap.bmWidth; 208 g_GlobalData.bmMonHeight = bitmap.bmHeight; 209 } 210 211 ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); 212 psh.dwSize = sizeof(PROPSHEETHEADER); 213 psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE | PSH_USEICONID; 214 psh.hwndParent = hCPLWindow; 215 psh.hInstance = hApplet; 216 psh.pszIcon = MAKEINTRESOURCEW(IDC_DESK_ICON); 217 psh.pszCaption = MAKEINTRESOURCEW(IDS_CPLNAME); 218 psh.nPages = 0; 219 psh.nStartPage = 0; 220 psh.phpage = hpsp; 221 psh.pfnCallback = PropSheetProc; 222 223 /* Allow shell extensions to replace the background page */ 224 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages); 225 226 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++) 227 { 228 if (pwszSelectedTab && wcsicmp(pwszSelectedTab, PropPages[i].Name) == 0) 229 psh.nStartPage = i; 230 231 /* Override the background page if requested by a shell extension */ 232 if (PropPages[i].idDlg == IDD_BACKGROUND && hpsxa != NULL && 233 SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, DisplayAppletPropSheetAddPage, (LPARAM)&psh) != 0) 234 { 235 /* The shell extension added one or more pages to replace the background page. 236 Don't create the built-in page anymore! */ 237 continue; 238 } 239 240 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc, PropPages[i].Callback); 241 } 242 243 /* NOTE: Don't call SHAddFromPropSheetExtArray here because this applet only allows 244 replacing the background page but not extending the applet by more pages */ 245 246 if (nPage != 0 && psh.nStartPage == 0) 247 psh.nStartPage = nPage; 248 249 PropertySheet(&psh); 250 251 cleanup: 252 DeleteObject(g_GlobalData.hMonitorBitmap); 253 254 if (hpsxa != NULL) 255 SHDestroyPropSheetExtArray(hpsxa); 256 257 if (argv) 258 LocalFree(argv); 259 260 return TRUE; 261 } 262 263 264 /* Control Panel Callback */ 265 LONG CALLBACK 266 CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2) 267 { 268 UINT i = (UINT)lParam1; 269 270 switch (uMsg) 271 { 272 case CPL_INIT: 273 return TRUE; 274 275 case CPL_GETCOUNT: 276 return NUM_APPLETS; 277 278 case CPL_INQUIRE: 279 if (i < NUM_APPLETS) 280 { 281 CPLINFO *CPlInfo = (CPLINFO*)lParam2; 282 CPlInfo->lData = 0; 283 CPlInfo->idIcon = Applets[i].idIcon; 284 CPlInfo->idName = Applets[i].idName; 285 CPlInfo->idInfo = Applets[i].idDescription; 286 } 287 else 288 { 289 return TRUE; 290 } 291 break; 292 293 case CPL_DBLCLK: 294 if (i < NUM_APPLETS) 295 Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2); 296 else 297 return TRUE; 298 break; 299 300 case CPL_STARTWPARMSW: 301 if (i < NUM_APPLETS) 302 return Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2); 303 break; 304 } 305 306 return FALSE; 307 } 308 309 void 310 WINAPI 311 InstallScreenSaverW( 312 IN HWND hWindow, 313 IN HANDLE hInstance, 314 IN LPCWSTR pszFile, 315 IN UINT nCmdShow) 316 { 317 WCHAR pszSystemDir[MAX_PATH]; 318 WCHAR pszDrive[3]; 319 WCHAR pszPath[MAX_PATH]; 320 WCHAR pszFilename[MAX_PATH]; 321 WCHAR pszExt[MAX_PATH]; 322 LPWSTR pszOutName; 323 UINT uCompressionType=FILE_COMPRESSION_NONE; 324 DWORD dwSourceSize; 325 DWORD dwTargetSize; 326 DWORD rc; 327 328 if (!pszFile) 329 { 330 DPRINT("InstallScreenSaver() null file\n"); 331 SetLastError(ERROR_INVALID_PARAMETER); 332 return; 333 } 334 DPRINT("InstallScreenSaver() Installing screensaver %ls\n", pszFile); 335 336 rc = SetupGetFileCompressionInfoW(pszFile, &pszOutName, &dwSourceSize, &dwTargetSize, &uCompressionType); 337 if (ERROR_SUCCESS != rc) 338 { 339 DPRINT("InstallScreenSaver() SetupGetFileCompressionInfo failed with error 0x%lx\n", rc); 340 SetLastError(rc); 341 return; 342 } 343 if (!GetSystemDirectoryW((LPWSTR)pszSystemDir, sizeof(pszSystemDir)/sizeof(WCHAR))) 344 { 345 MyFree(pszOutName); 346 DPRINT("InstallScreenSaver() GetSystemDirectory failed with error 0x%lx\n", GetLastError()); 347 return; 348 } 349 _wsplitpath(pszOutName, pszDrive, pszPath, pszFilename, pszExt); 350 MyFree(pszOutName); 351 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), L"\\"); 352 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszFilename); 353 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszExt); 354 rc = SetupDecompressOrCopyFileW(pszFile, pszSystemDir, &uCompressionType); 355 DPRINT("InstallScreenSaver() Copying to %ls, compression type %d return 0x%lx\n", pszFile, uCompressionType, rc); 356 } 357 358 void 359 WINAPI 360 InstallScreenSaverA( 361 IN HWND hWindow, 362 IN HANDLE hInstance, 363 IN LPCSTR pszFile, 364 IN UINT nCmdShow) 365 { 366 LPWSTR lpwString; 367 368 if (!pszFile) 369 { 370 DPRINT("InstallScreenSaver() null file\n"); 371 SetLastError(ERROR_INVALID_PARAMETER); 372 return; 373 } 374 DPRINT("InstallScreenSaver() Install from file %s\n", pszFile); 375 lpwString = pSetupMultiByteToUnicode(pszFile, 0); 376 if (!lpwString) 377 { 378 DPRINT("InstallScreenSaver() not enough memory to convert string to unicode\n"); 379 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 380 return; 381 } 382 InstallScreenSaverW(hWindow, hInstance, lpwString, nCmdShow); 383 MyFree(lpwString); 384 } 385 386 BOOL WINAPI 387 DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved) 388 { 389 UNREFERENCED_PARAMETER(lpvReserved); 390 391 switch (dwReason) 392 { 393 case DLL_PROCESS_ATTACH: 394 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 395 RegisterPreviewControl(hInstDLL); 396 // case DLL_THREAD_ATTACH: 397 hApplet = hInstDLL; 398 break; 399 400 case DLL_PROCESS_DETACH: 401 UnregisterPreviewControl(hInstDLL); 402 CoUninitialize(); 403 break; 404 } 405 406 return TRUE; 407 } 408