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