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