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