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 TCHAR Caption[1024]; 148 UINT i; 149 LPWSTR *argv = NULL; 150 LPCWSTR pwszSelectedTab = NULL; 151 LPCWSTR pwszFile = NULL; 152 LPCWSTR pwszAction = NULL; 153 INT nPage = 0; 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 LoadString(hApplet, IDS_CPLNAME, Caption, sizeof(Caption) / sizeof(TCHAR)); 202 203 ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); 204 psh.dwSize = sizeof(PROPSHEETHEADER); 205 psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE | PSH_USEICONID; 206 psh.hwndParent = hCPLWindow; 207 psh.hInstance = hApplet; 208 psh.pszIcon = MAKEINTRESOURCEW(IDC_DESK_ICON); 209 psh.pszCaption = Caption; 210 psh.nPages = 0; 211 psh.nStartPage = 0; 212 psh.phpage = hpsp; 213 psh.pfnCallback = PropSheetProc; 214 215 /* Allow shell extensions to replace the background page */ 216 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages); 217 218 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++) 219 { 220 if (pwszSelectedTab && wcsicmp(pwszSelectedTab, PropPages[i].Name) == 0) 221 psh.nStartPage = i; 222 223 /* Override the background page if requested by a shell extension */ 224 if (PropPages[i].idDlg == IDD_BACKGROUND && hpsxa != NULL && 225 SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, DisplayAppletPropSheetAddPage, (LPARAM)&psh) != 0) 226 { 227 /* The shell extension added one or more pages to replace the background page. 228 Don't create the built-in page anymore! */ 229 continue; 230 } 231 232 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc, PropPages[i].Callback); 233 } 234 235 /* NOTE: Don't call SHAddFromPropSheetExtArray here because this applet only allows 236 replacing the background page but not extending the applet by more pages */ 237 238 if (nPage != 0 && psh.nStartPage == 0) 239 psh.nStartPage = nPage; 240 241 PropertySheet(&psh); 242 243 cleanup: 244 if (hpsxa != NULL) 245 SHDestroyPropSheetExtArray(hpsxa); 246 247 if (argv) 248 LocalFree(argv); 249 250 return TRUE; 251 } 252 253 254 /* Control Panel Callback */ 255 LONG CALLBACK 256 CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2) 257 { 258 int i = (int)lParam1; 259 260 switch (uMsg) 261 { 262 case CPL_INIT: 263 return TRUE; 264 265 case CPL_GETCOUNT: 266 return NUM_APPLETS; 267 268 case CPL_INQUIRE: 269 { 270 CPLINFO *CPlInfo = (CPLINFO*)lParam2; 271 CPlInfo->lData = 0; 272 CPlInfo->idIcon = Applets[i].idIcon; 273 CPlInfo->idName = Applets[i].idName; 274 CPlInfo->idInfo = Applets[i].idDescription; 275 } 276 break; 277 278 case CPL_DBLCLK: 279 Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2); 280 break; 281 282 case CPL_STARTWPARMSW: 283 return Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2); 284 } 285 286 return FALSE; 287 } 288 289 void 290 WINAPI 291 InstallScreenSaverW( 292 IN HWND hWindow, 293 IN HANDLE hInstance, 294 IN LPCWSTR pszFile, 295 IN UINT nCmdShow) 296 { 297 WCHAR pszSystemDir[MAX_PATH]; 298 WCHAR pszDrive[3]; 299 WCHAR pszPath[MAX_PATH]; 300 WCHAR pszFilename[MAX_PATH]; 301 WCHAR pszExt[MAX_PATH]; 302 LPWSTR pszOutName; 303 UINT uCompressionType=FILE_COMPRESSION_NONE; 304 DWORD dwSourceSize; 305 DWORD dwTargetSize; 306 DWORD rc; 307 308 if (!pszFile) 309 { 310 DPRINT("InstallScreenSaver() null file\n"); 311 SetLastError(ERROR_INVALID_PARAMETER); 312 return; 313 } 314 DPRINT("InstallScreenSaver() Installing screensaver %ls\n", pszFile); 315 316 rc = SetupGetFileCompressionInfoW(pszFile, &pszOutName, &dwSourceSize, &dwTargetSize, &uCompressionType); 317 if (ERROR_SUCCESS != rc) 318 { 319 DPRINT("InstallScreenSaver() SetupGetFileCompressionInfo failed with error 0x%lx\n", rc); 320 SetLastError(rc); 321 return; 322 } 323 if (!GetSystemDirectoryW((LPWSTR)pszSystemDir, sizeof(pszSystemDir)/sizeof(WCHAR))) 324 { 325 MyFree(pszOutName); 326 DPRINT("InstallScreenSaver() GetSystemDirectory failed with error 0x%lx\n", GetLastError()); 327 return; 328 } 329 _wsplitpath(pszOutName, pszDrive, pszPath, pszFilename, pszExt); 330 MyFree(pszOutName); 331 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), L"\\"); 332 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszFilename); 333 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszExt); 334 rc = SetupDecompressOrCopyFileW(pszFile, pszSystemDir, &uCompressionType); 335 DPRINT("InstallScreenSaver() Copying to %ls, compression type %d return 0x%lx\n", pszFile, uCompressionType, rc); 336 } 337 338 void 339 WINAPI 340 InstallScreenSaverA( 341 IN HWND hWindow, 342 IN HANDLE hInstance, 343 IN LPCSTR pszFile, 344 IN UINT nCmdShow) 345 { 346 LPWSTR lpwString; 347 348 if (!pszFile) 349 { 350 DPRINT("InstallScreenSaver() null file\n"); 351 SetLastError(ERROR_INVALID_PARAMETER); 352 return; 353 } 354 DPRINT("InstallScreenSaver() Install from file %s\n", pszFile); 355 lpwString = pSetupMultiByteToUnicode(pszFile, 0); 356 if (!lpwString) 357 { 358 DPRINT("InstallScreenSaver() not enough memory to convert string to unicode\n"); 359 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 360 return; 361 } 362 InstallScreenSaverW(hWindow, hInstance, lpwString, nCmdShow); 363 MyFree(lpwString); 364 } 365 366 BOOL WINAPI 367 DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved) 368 { 369 UNREFERENCED_PARAMETER(lpvReserved); 370 371 switch (dwReason) 372 { 373 case DLL_PROCESS_ATTACH: 374 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 375 RegisterPreviewControl(hInstDLL); 376 // case DLL_THREAD_ATTACH: 377 hApplet = hInstDLL; 378 break; 379 380 case DLL_PROCESS_DETACH: 381 UnregisterPreviewControl(hInstDLL); 382 CoUninitialize(); 383 break; 384 } 385 386 return TRUE; 387 } 388