1 /* 2 * PROJECT: ReactOS Applications 3 * LICENSE: LGPL - See COPYING in the top level directory 4 * FILE: base/applications/msconfig_new/msconfig.c 5 * PURPOSE: MSConfig main dialog 6 * COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de> 7 */ 8 9 #include "precomp.h" 10 #include "fileutils.h" 11 #include "utils.h" 12 13 #include "generalpage.h" 14 #include "systempage.h" 15 #include "freeldrpage.h" 16 #include "srvpage.h" 17 // #include "startuppage.h" 18 #include "toolspage.h" 19 20 /* Allow only for a single instance of MSConfig */ 21 #ifdef _MSC_VER 22 #pragma data_seg("MSConfigInstance") 23 HWND hSingleWnd = NULL; 24 #pragma data_seg() 25 #pragma comment(linker, "/SECTION:MSConfigInstance,RWS") 26 #else 27 HWND hSingleWnd __attribute__((section ("MSConfigInstance"), shared)) = NULL; 28 #endif 29 30 /* Defaults for ReactOS */ 31 BOOL bIsWindows = FALSE; 32 BOOL bIsPreVistaOSVersion = TRUE; 33 34 /* Language-independent Vendor strings */ 35 const LPCWSTR IDS_REACTOS = L"ReactOS"; 36 const LPCWSTR IDS_MICROSOFT = L"Microsoft"; 37 const LPCWSTR IDS_WINDOWS = L"Windows"; 38 39 HINSTANCE hInst = NULL; 40 LPWSTR szAppName = NULL; 41 HWND hMainWnd; /* Main Window */ 42 43 HWND hTabWnd; /* Tab Control Window */ 44 HICON hIcon = NULL, hIconSm = NULL; 45 WNDPROC wpOrigEditProc = NULL; 46 47 48 /* About Box dialog */ 49 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 50 { 51 UNREFERENCED_PARAMETER(lParam); 52 switch (message) 53 { 54 case WM_INITDIALOG: 55 return (INT_PTR)TRUE; 56 57 case WM_COMMAND: 58 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 59 { 60 EndDialog(hDlg, LOWORD(wParam)); 61 return (INT_PTR)TRUE; 62 } 63 break; 64 } 65 return (INT_PTR)FALSE; 66 } 67 68 69 /* Message handler for dialog box */ 70 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) 71 { 72 switch (uMessage) 73 { 74 case WM_SYSCOMMAND: 75 { 76 switch (LOWORD(wParam) /*GET_WM_COMMAND_ID(wParam, lParam)*/) 77 { 78 case IDM_ABOUT: 79 DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_ABOUTBOX), hWnd, About); 80 // break; 81 return TRUE; 82 } 83 84 // break; 85 return FALSE; 86 } 87 88 case WM_COMMAND: 89 { 90 switch (LOWORD(wParam) /*GET_WM_COMMAND_ID(wParam, lParam)*/) 91 { 92 case IDM_ABOUT: 93 DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_ABOUTBOX), hWnd, About); 94 // break; 95 return TRUE; 96 } 97 98 break; 99 // return FALSE; 100 } 101 102 case WM_DESTROY: 103 { 104 if (wpOrigEditProc) 105 SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)wpOrigEditProc); 106 107 if (hIcon) DestroyIcon(hIcon); 108 if (hIconSm) DestroyIcon(hIconSm); 109 } 110 111 default: 112 break; 113 } 114 115 /* Return */ 116 if (wpOrigEditProc) 117 return CallWindowProc(wpOrigEditProc, hWnd, uMessage, wParam, lParam); 118 else 119 return FALSE; 120 } 121 122 123 #include <pshpack1.h> 124 typedef struct DLGTEMPLATEEX 125 { 126 WORD dlgVer; 127 WORD signature; 128 DWORD helpID; 129 DWORD exStyle; 130 DWORD style; 131 WORD cDlgItems; 132 short x; 133 short y; 134 short cx; 135 short cy; 136 } DLGTEMPLATEEX, *LPDLGTEMPLATEEX; 137 #include <poppack.h> 138 139 int CALLBACK PropSheetCallback(HWND hDlg, UINT message, LPARAM lParam) 140 { 141 switch (message) 142 { 143 case PSCB_PRECREATE: 144 { 145 LPDLGTEMPLATE dlgTemplate = (LPDLGTEMPLATE)lParam; 146 LPDLGTEMPLATEEX dlgTemplateEx = (LPDLGTEMPLATEEX)lParam; 147 148 // MFC : DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION; 149 DWORD style = DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU; 150 // DS_SHELLFONT | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME; 151 DWORD exStyle = WS_EX_CONTROLPARENT | WS_EX_APPWINDOW; 152 153 /* Hide the dialog by default; we will center it on screen later, and then show it */ 154 style &= ~WS_VISIBLE; 155 156 /* Set the styles of the property sheet dialog */ 157 if (dlgTemplateEx->signature == 0xFFFF) 158 { 159 dlgTemplateEx->style = style; 160 dlgTemplateEx->exStyle = exStyle; 161 } 162 else 163 { 164 dlgTemplate->style = style; 165 dlgTemplate->dwExtendedStyle = exStyle; 166 } 167 168 break; 169 } 170 171 case PSCB_INITIALIZED: 172 { 173 /* Customize the window's system menu, add items before the "Close" item */ 174 LPWSTR szMenuString; 175 HMENU hSysMenu = GetSystemMenu(hDlg, FALSE); 176 assert(hSysMenu); 177 178 szMenuString = LoadResourceString(hInst, IDS_ABOUT); 179 if (szMenuString) 180 { 181 /* "About" menu */ 182 InsertMenuW(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED | MF_STRING, IDM_ABOUT, szMenuString); 183 /* Separator */ 184 InsertMenuW(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_SEPARATOR , 0 , NULL); 185 186 MemFree(szMenuString); 187 } 188 DrawMenuBar(hDlg); 189 190 /* Set the dialog icons */ 191 hIcon = (HICON)LoadImageW(hInst, MAKEINTRESOURCEW(IDI_APPICON), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE); 192 hIconSm = (HICON)CopyImage(hIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_COPYFROMRESOURCE); 193 SendMessageW(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 194 SendMessageW(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm); 195 196 /* Sub-class the property sheet window procedure */ 197 wpOrigEditProc = (WNDPROC)SetWindowLongPtr(hDlg, DWLP_DLGPROC, (LONG_PTR)MainWndProc); 198 199 break; 200 } 201 202 default: 203 break; 204 } 205 206 return FALSE; 207 } 208 209 HWND CreatePropSheet(HINSTANCE hInstance, HWND hwndOwner, LPCTSTR lpszTitle) 210 { 211 HWND hPropSheet; 212 PROPSHEETHEADERW psh; 213 PROPSHEETPAGEW psp[7]; 214 unsigned int nPages = 0; 215 216 /* Header */ 217 psh.dwSize = sizeof(psh); 218 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS | /*PSH_USEICONID |*/ PSH_HASHELP | /*PSH_NOCONTEXTHELP |*/ PSH_USECALLBACK; 219 psh.hInstance = hInstance; 220 psh.hwndParent = hwndOwner; 221 // psh.pszIcon = MAKEINTRESOURCEW(IDI_APPICON); // Disabled because it only sets the small icon; the big icon is a stretched version of the small one. 222 psh.pszCaption = lpszTitle; 223 psh.nStartPage = 0; 224 psh.ppsp = psp; 225 psh.pfnCallback = PropSheetCallback; 226 227 /* General page */ 228 psp[nPages].dwSize = sizeof(PROPSHEETPAGEW); 229 psp[nPages].dwFlags = PSP_HASHELP; 230 psp[nPages].hInstance = hInstance; 231 psp[nPages].pszTemplate = MAKEINTRESOURCEW(IDD_GENERAL_PAGE); 232 psp[nPages].pfnDlgProc = GeneralPageWndProc; 233 ++nPages; 234 235 // if (bIsPreVistaOSVersion) 236 { 237 /* SYSTEM.INI page */ 238 if (MyFileExists(lpszSystemIni, NULL)) 239 { 240 psp[nPages].dwSize = sizeof(PROPSHEETPAGEW); 241 psp[nPages].dwFlags = PSP_HASHELP | PSP_USETITLE; 242 psp[nPages].hInstance = hInstance; 243 psp[nPages].pszTitle = MAKEINTRESOURCEW(IDS_TAB_SYSTEM); 244 psp[nPages].pszTemplate = MAKEINTRESOURCEW(IDD_SYSTEM_PAGE); 245 psp[nPages].pfnDlgProc = SystemPageWndProc; 246 psp[nPages].lParam = (LPARAM)lpszSystemIni; 247 ++nPages; 248 249 BackupIniFile(lpszSystemIni); 250 } 251 252 /* WIN.INI page */ 253 if (MyFileExists(lpszWinIni, NULL)) 254 { 255 psp[nPages].dwSize = sizeof(PROPSHEETPAGEW); 256 psp[nPages].dwFlags = PSP_HASHELP | PSP_USETITLE; 257 psp[nPages].hInstance = hInstance; 258 psp[nPages].pszTitle = MAKEINTRESOURCEW(IDS_TAB_WIN); 259 psp[nPages].pszTemplate = MAKEINTRESOURCEW(IDD_SYSTEM_PAGE); 260 psp[nPages].pfnDlgProc = WinPageWndProc; 261 psp[nPages].lParam = (LPARAM)lpszWinIni; 262 ++nPages; 263 264 BackupIniFile(lpszWinIni); 265 } 266 } 267 268 /* FreeLdr page */ 269 // TODO: Program the interface for Vista: "light" BCD editor... 270 if (!bIsWindows || (bIsWindows && bIsPreVistaOSVersion)) 271 { 272 LPCWSTR lpszLoaderIniFile = NULL; 273 DWORD dwTabNameId = 0; 274 if (bIsWindows) 275 { 276 lpszLoaderIniFile = lpszBootIni; 277 dwTabNameId = IDS_TAB_BOOT; 278 } 279 else 280 { 281 lpszLoaderIniFile = lpszFreeLdrIni; 282 dwTabNameId = IDS_TAB_FREELDR; 283 } 284 285 if (MyFileExists(lpszLoaderIniFile, NULL)) 286 { 287 psp[nPages].dwSize = sizeof(PROPSHEETPAGEW); 288 psp[nPages].dwFlags = PSP_HASHELP | PSP_USETITLE; 289 psp[nPages].hInstance = hInstance; 290 psp[nPages].pszTitle = MAKEINTRESOURCEW(dwTabNameId); 291 psp[nPages].pszTemplate = MAKEINTRESOURCEW(IDD_FREELDR_PAGE); 292 psp[nPages].pfnDlgProc = FreeLdrPageWndProc; 293 psp[nPages].lParam = (LPARAM)lpszLoaderIniFile; 294 ++nPages; 295 296 BackupIniFile(lpszLoaderIniFile); 297 } 298 } 299 300 /* Services page */ 301 psp[nPages].dwSize = sizeof(PROPSHEETPAGEW); 302 psp[nPages].dwFlags = PSP_HASHELP; 303 psp[nPages].hInstance = hInstance; 304 psp[nPages].pszTemplate = MAKEINTRESOURCEW(IDD_SERVICES_PAGE); 305 psp[nPages].pfnDlgProc = ServicesPageWndProc; 306 ++nPages; 307 308 #if 0 309 /* Startup page */ 310 psp[nPages].dwSize = sizeof(PROPSHEETPAGEW); 311 psp[nPages].dwFlags = PSP_HASHELP; 312 psp[nPages].hInstance = hInstance; 313 psp[nPages].pszTemplate = MAKEINTRESOURCEW(IDD_STARTUP_PAGE); 314 psp[nPages].pfnDlgProc = StartupPageWndProc; 315 ++nPages; 316 #endif 317 318 /* Tools page */ 319 psp[nPages].dwSize = sizeof(PROPSHEETPAGEW); 320 psp[nPages].dwFlags = PSP_HASHELP; 321 psp[nPages].hInstance = hInstance; 322 psp[nPages].pszTemplate = MAKEINTRESOURCEW(IDD_TOOLS_PAGE); 323 psp[nPages].pfnDlgProc = ToolsPageWndProc; 324 ++nPages; 325 326 /* Set the total number of created pages */ 327 psh.nPages = nPages; 328 329 /* Create the property sheet */ 330 hPropSheet = (HWND)PropertySheetW(&psh); 331 if (hPropSheet) 332 { 333 /* Center the property sheet on the desktop and show it */ 334 ClipOrCenterWindowToMonitor(hPropSheet, MONITOR_WORKAREA | MONITOR_CENTER); 335 ShowWindow(hPropSheet, SW_SHOWNORMAL); 336 } 337 338 return hPropSheet; 339 } 340 341 BOOL Initialize(HINSTANCE hInstance) 342 { 343 BOOL Success = TRUE; 344 LPWSTR lpszVistaAppName = NULL; 345 HANDLE hSemaphore; 346 INITCOMMONCONTROLSEX InitControls; 347 348 /* Initialize our global version flags */ 349 bIsWindows = IsWindowsOS(); 350 bIsPreVistaOSVersion = IsPreVistaOSVersion(); 351 352 /* Initialize global strings */ 353 szAppName = LoadResourceString(hInstance, IDS_MSCONFIG); 354 if (!bIsPreVistaOSVersion) 355 lpszVistaAppName = LoadResourceString(hInstance, IDS_MSCONFIG_2); 356 357 /* We use a semaphore in order to have a single-instance application */ 358 hSemaphore = CreateSemaphoreW(NULL, 0, 1, L"MSConfigRunning"); 359 if (!hSemaphore || GetLastError() == ERROR_ALREADY_EXISTS) 360 { 361 CloseHandle(hSemaphore); 362 363 /* 364 * A semaphore with the same name already exist. It should have been 365 * created by another instance of MSConfig. Try to find its window 366 * and bring it to front. 367 */ 368 if ( (hSingleWnd && IsWindow(hSingleWnd)) || 369 ( (hSingleWnd = FindWindowW(L"#32770", szAppName)) != NULL ) || 370 (!bIsPreVistaOSVersion ? ( (hSingleWnd = FindWindowW(L"#32770", lpszVistaAppName)) != NULL ) : FALSE) ) 371 { 372 /* Found it. Show the window. */ 373 ShowWindow(hSingleWnd, SW_SHOWNORMAL); 374 SetForegroundWindow(hSingleWnd); 375 } 376 377 /* Quit this instance of MSConfig */ 378 Success = FALSE; 379 } 380 if (!bIsPreVistaOSVersion) MemFree(lpszVistaAppName); 381 382 /* Quit now if we failed */ 383 if (!Success) 384 { 385 MemFree(szAppName); 386 return FALSE; 387 } 388 389 /* Initialize the common controls */ 390 InitControls.dwSize = sizeof(INITCOMMONCONTROLSEX); 391 InitControls.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS /* | ICC_PROGRESS_CLASS | ICC_HOTKEY_CLASS*/; 392 InitCommonControlsEx(&InitControls); 393 394 hInst = hInstance; 395 396 return Success; 397 } 398 399 VOID Cleanup(VOID) 400 { 401 MemFree(szAppName); 402 403 // // Close the sentry semaphore. 404 // CloseHandle(hSemaphore); 405 } 406 407 int APIENTRY _tWinMain(HINSTANCE hInstance, 408 HINSTANCE hPrevInstance, 409 LPTSTR lpCmdLine, 410 int nCmdShow) 411 { 412 MSG msg; 413 HACCEL hAccelTable; 414 415 UNREFERENCED_PARAMETER(hPrevInstance); 416 UNREFERENCED_PARAMETER(lpCmdLine); 417 UNREFERENCED_PARAMETER(nCmdShow); 418 419 /* 420 * Initialize this instance of MSConfig. Quit if we have 421 * another instance already running. 422 */ 423 if (!Initialize(hInstance)) 424 return -1; 425 426 // hInst = hInstance; 427 428 hMainWnd = CreatePropSheet(hInstance, NULL, szAppName); 429 if (!hMainWnd) 430 { 431 /* We failed, cleanup and bail out */ 432 Cleanup(); 433 return -1; 434 } 435 436 hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDR_MSCONFIG)); 437 438 /* Message loop */ 439 while (IsWindow(hMainWnd) && GetMessageW(&msg, NULL, 0, 0)) 440 { 441 /* 442 * PropSheet_GetCurrentPageHwnd returns NULL when the user clicks the OK or Cancel button 443 * and after all of the pages have been notified. Apply button doesn't cause this to happen. 444 * We can then use the DestroyWindow function to destroy the property sheet. 445 */ 446 if (PropSheet_GetCurrentPageHwnd(hMainWnd) == NULL) 447 break; 448 449 /* Process the accelerator table */ 450 if (!TranslateAcceleratorW(hMainWnd, hAccelTable, &msg)) 451 { 452 /* 453 * If e.g. an item on the tree view is being edited, 454 * we cannot pass the event to PropSheet_IsDialogMessage. 455 * Doing so causes the property sheet to be closed at Enter press 456 * (instead of completing edit operation). 457 */ 458 if (/*g_bDisableDialogDispatch ||*/ !PropSheet_IsDialogMessage(hMainWnd, &msg)) 459 { 460 TranslateMessage(&msg); 461 DispatchMessageW(&msg); 462 } 463 } 464 } 465 466 // FIXME: Process the results of MSConfig !! 467 468 /* Destroy the accelerator table and the window */ 469 if (hAccelTable != NULL) 470 DestroyAcceleratorTable(hAccelTable); 471 472 DestroyWindow(hMainWnd); 473 474 /* Finish cleanup and return */ 475 Cleanup(); 476 return (int)msg.wParam; 477 } 478 479 /* EOF */ 480