[APPLICATIONS] Improve the FILE header section. Brought to you by Adam Stachowicz...
[reactos.git] / reactos / base / applications / msconfig_new / msconfig.c
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
10 #include "precomp.h"
11 #include "utils.h"
12
13 #include "toolspage.h"
14 #include "srvpage.h"
15 #include "startuppage.h"
16 #include "freeldrpage.h"
17 #include "systempage.h"
18 #include "generalpage.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 bIsOSVersionLessThanVista = TRUE;
33
34 HINSTANCE hInst = NULL;
35 LPWSTR szAppName = NULL;
36 HWND hMainWnd; /* Main Window */
37
38 HWND hTabWnd; /* Tab Control Window */
39 // HICON hDialogIcon = NULL;
40 HICON hIcon = NULL;
41 WNDPROC wpOrigEditProc = NULL;
42
43
44 ////////////////////////////////////////////////////////////////////////////////
45 // Taken from WinSpy++ 1.7
46 // http://www.catch22.net/software/winspy
47 // Copyright (c) 2002 by J Brown
48 //
49
50 //
51 // Copied from uxtheme.h
52 // If you have this new header, then delete these and
53 // #include <uxtheme.h> instead!
54 //
55 #define ETDT_DISABLE 0x00000001
56 #define ETDT_ENABLE 0x00000002
57 #define ETDT_USETABTEXTURE 0x00000004
58 #define ETDT_ENABLETAB (ETDT_ENABLE | ETDT_USETABTEXTURE)
59
60 //
61 typedef HRESULT (WINAPI * ETDTProc) (HWND, DWORD);
62
63 //
64 // Try to call EnableThemeDialogTexture, if uxtheme.dll is present
65 //
66 BOOL EnableDialogTheme(HWND hwnd)
67 {
68 HMODULE hUXTheme;
69 ETDTProc fnEnableThemeDialogTexture;
70
71 hUXTheme = LoadLibrary(_T("uxtheme.dll"));
72
73 if(hUXTheme)
74 {
75 fnEnableThemeDialogTexture =
76 (ETDTProc)GetProcAddress(hUXTheme, "EnableThemeDialogTexture");
77
78 if(fnEnableThemeDialogTexture)
79 {
80 fnEnableThemeDialogTexture(hwnd, ETDT_ENABLETAB);
81
82 FreeLibrary(hUXTheme);
83 return TRUE;
84 }
85 else
86 {
87 // Failed to locate API!
88 FreeLibrary(hUXTheme);
89 return FALSE;
90 }
91 }
92 else
93 {
94 // Not running under XP? Just fail gracefully
95 return FALSE;
96 }
97 }
98
99 /* About Box dialog */
100 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
101 {
102 UNREFERENCED_PARAMETER(lParam);
103 switch (message)
104 {
105 case WM_INITDIALOG:
106 return (INT_PTR)TRUE;
107
108 case WM_COMMAND:
109 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
110 {
111 EndDialog(hDlg, LOWORD(wParam));
112 return (INT_PTR)TRUE;
113 }
114 break;
115 }
116 return (INT_PTR)FALSE;
117 }
118
119
120 /* Message handler for dialog box. */
121 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
122 {
123 switch (uMessage)
124 {
125 case WM_SYSCOMMAND:
126 {
127 switch (LOWORD(wParam) /*GET_WM_COMMAND_ID(wParam, lParam)*/)
128 {
129 case IDM_ABOUT:
130 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
131 // break;
132 return TRUE;
133 }
134
135 // break;
136 return FALSE;
137 }
138
139 case WM_COMMAND:
140 {
141 switch (LOWORD(wParam) /*GET_WM_COMMAND_ID(wParam, lParam)*/)
142 {
143 case IDM_ABOUT:
144 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
145 // break;
146 return TRUE;
147 }
148
149 break;
150 // return FALSE;
151 }
152
153 #if 0
154 case WM_SYSCOLORCHANGE:
155 /* Forward WM_SYSCOLORCHANGE to common controls */
156 SendMessage(hServicesListCtrl, WM_SYSCOLORCHANGE, 0, 0);
157 SendMessage(hStartupListCtrl, WM_SYSCOLORCHANGE, 0, 0);
158 SendMessage(hToolsListCtrl, WM_SYSCOLORCHANGE, 0, 0);
159 break;
160 #endif
161
162 case WM_DESTROY:
163 {
164 if (hIcon)
165 DestroyIcon(hIcon);
166
167 if (wpOrigEditProc)
168 SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)wpOrigEditProc);
169 }
170
171 default:
172 break;
173 }
174
175 /* Return */
176 if (wpOrigEditProc)
177 return CallWindowProc(wpOrigEditProc, hWnd, uMessage, wParam, lParam);
178 else
179 return FALSE;
180 }
181
182
183 #include <pshpack1.h>
184 typedef struct DLGTEMPLATEEX
185 {
186 WORD dlgVer;
187 WORD signature;
188 DWORD helpID;
189 DWORD exStyle;
190 DWORD style;
191 WORD cDlgItems;
192 short x;
193 short y;
194 short cx;
195 short cy;
196 } DLGTEMPLATEEX, *LPDLGTEMPLATEEX;
197 #include <poppack.h>
198
199
200 VOID ModifySystemMenu(HWND hWnd)
201 {
202 WCHAR szMenuString[255];
203
204 /* Customize the window's system menu, add items before the "Close" item */
205 HMENU hSysMenu = GetSystemMenu(hWnd, FALSE);
206 assert(hSysMenu);
207
208 /* New entries... */
209 if (LoadStringW(hInst,
210 IDS_ABOUT,
211 szMenuString,
212 ARRAYSIZE(szMenuString)) > 0)
213 {
214 /* "About" menu */
215 InsertMenuW(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED | MF_STRING, IDM_ABOUT, szMenuString);
216 /* Separator */
217 InsertMenuW(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_SEPARATOR , 0 , NULL);
218 }
219
220 DrawMenuBar(hWnd);
221 return;
222 }
223
224 int CALLBACK PropSheetCallback(HWND hDlg, UINT message, LPARAM lParam)
225 {
226 switch (message)
227 {
228 case PSCB_PRECREATE:
229 {
230 LPDLGTEMPLATE dlgTemplate = (LPDLGTEMPLATE)lParam;
231 LPDLGTEMPLATEEX dlgTemplateEx = (LPDLGTEMPLATEEX)lParam;
232
233 /* Set the styles of the property sheet dialog */
234 if (dlgTemplateEx->signature == 0xFFFF)
235 {
236 //// MFC : DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION;
237
238 dlgTemplateEx->style = DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU;
239 // dlgTemplateEx->style = DS_SHELLFONT | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
240 dlgTemplateEx->exStyle = WS_EX_CONTROLPARENT | WS_EX_APPWINDOW;
241 }
242 else
243 {
244 dlgTemplate->style = DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU;
245 // dlgTemplate->style = DS_SHELLFONT | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
246 dlgTemplate->dwExtendedStyle = WS_EX_CONTROLPARENT | WS_EX_APPWINDOW;
247 }
248
249 break;
250 }
251
252 case PSCB_INITIALIZED:
253 {
254 /* Modify the system menu of the property sheet dialog */
255 ModifySystemMenu(hDlg);
256
257 /* Set the dialog icons */
258 hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
259 SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
260 SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
261
262 /* Sub-class the property sheet window procedure */
263 wpOrigEditProc = (WNDPROC)SetWindowLongPtr(hDlg, DWLP_DLGPROC, (LONG_PTR)MainWndProc);
264
265 break;
266 }
267
268 default:
269 break;
270 }
271
272 return FALSE;
273 }
274
275 HWND CreatePropSheet(HINSTANCE hInstance, HWND hwndOwner, LPCTSTR lpszTitle)
276 {
277 HWND hPropSheet;
278 PROPSHEETHEADER psh;
279 PROPSHEETPAGE psp[7];
280 unsigned int nPages = 0;
281
282 /* Header */
283 psh.dwSize = sizeof(PROPSHEETHEADER);
284 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS | /*PSH_USEICONID |*/ PSH_HASHELP | /*PSH_NOCONTEXTHELP |*/ PSH_USECALLBACK;
285 psh.hInstance = hInstance;
286 psh.hwndParent = hwndOwner;
287 //psh.pszIcon = MAKEINTRESOURCE(IDI_APPICON); // It's crap... Only works for the small icon and not the big...
288 psh.pszCaption = lpszTitle;
289 psh.nStartPage = 0;
290 psh.ppsp = psp;
291 psh.pfnCallback = (PFNPROPSHEETCALLBACK)PropSheetCallback;
292
293 /* General page */
294 psp[nPages].dwSize = sizeof(PROPSHEETPAGE);
295 psp[nPages].dwFlags = PSP_HASHELP;
296 psp[nPages].hInstance = hInstance;
297 psp[nPages].pszTemplate = MAKEINTRESOURCE(IDD_GENERAL_PAGE);
298 psp[nPages].pfnDlgProc = (DLGPROC)GeneralPageWndProc;
299 ++nPages;
300
301 #if 0
302 if (bIsWindows && bIsOSVersionLessThanVista)
303 {
304 /* SYSTEM.INI page */
305 if (MyFileExists(lpszSystemIni, NULL))
306 {
307 psp[nPages].dwSize = sizeof(PROPSHEETPAGE);
308 psp[nPages].dwFlags = PSP_HASHELP | PSP_USETITLE;
309 psp[nPages].hInstance = hInstance;
310 psp[nPages].pszTitle = MAKEINTRESOURCE(IDS_TAB_SYSTEM);
311 psp[nPages].pszTemplate = MAKEINTRESOURCE(IDD_SYSTEM_PAGE);
312 psp[nPages].pfnDlgProc = (DLGPROC)SystemPageWndProc;
313 psp[nPages].lParam = (LPARAM)lpszSystemIni;
314 ++nPages;
315
316 BackupIniFile(lpszSystemIni);
317 }
318
319 /* WIN.INI page */
320 if (MyFileExists(lpszWinIni, NULL))
321 {
322 psp[nPages].dwSize = sizeof(PROPSHEETPAGE);
323 psp[nPages].dwFlags = PSP_HASHELP | PSP_USETITLE;
324 psp[nPages].hInstance = hInstance;
325 psp[nPages].pszTitle = MAKEINTRESOURCE(IDS_TAB_WIN);
326 psp[nPages].pszTemplate = MAKEINTRESOURCE(IDD_SYSTEM_PAGE);
327 psp[nPages].pfnDlgProc = (DLGPROC)WinPageWndProc;
328 psp[nPages].lParam = (LPARAM)lpszWinIni;
329 ++nPages;
330
331 BackupIniFile(lpszWinIni);
332 }
333 }
334
335 /* FreeLdr page */
336 // TODO: Program the interface for Vista : "light" BCD editor...
337 if (!bIsWindows || (bIsWindows && bIsOSVersionLessThanVista))
338 {
339 LPCTSTR lpszLoaderIniFile = NULL;
340 DWORD dwTabNameId = 0;
341 if (bIsWindows)
342 {
343 lpszLoaderIniFile = lpszBootIni;
344 dwTabNameId = IDS_TAB_BOOT;
345 }
346 else
347 {
348 lpszLoaderIniFile = lpszFreeLdrIni;
349 dwTabNameId = IDS_TAB_FREELDR;
350 }
351
352 if (MyFileExists(lpszLoaderIniFile, NULL))
353 {
354 psp[nPages].dwSize = sizeof(PROPSHEETPAGE);
355 psp[nPages].dwFlags = PSP_HASHELP | PSP_USETITLE;
356 psp[nPages].hInstance = hInstance;
357 psp[nPages].pszTitle = MAKEINTRESOURCE(dwTabNameId);
358 psp[nPages].pszTemplate = MAKEINTRESOURCE(IDD_FREELDR_PAGE);
359 psp[nPages].pfnDlgProc = (DLGPROC)FreeLdrPageWndProc;
360 psp[nPages].lParam = (LPARAM)lpszLoaderIniFile;
361 ++nPages;
362
363 BackupIniFile(lpszLoaderIniFile);
364 }
365 }
366
367 /* Services page */
368 psp[nPages].dwSize = sizeof(PROPSHEETPAGE);
369 psp[nPages].dwFlags = PSP_HASHELP;
370 psp[nPages].hInstance = hInstance;
371 psp[nPages].pszTemplate = MAKEINTRESOURCE(IDD_SERVICES_PAGE);
372 psp[nPages].pfnDlgProc = (DLGPROC)ServicesPageWndProc;
373 ++nPages;
374
375 /* Startup page */
376 psp[nPages].dwSize = sizeof(PROPSHEETPAGE);
377 psp[nPages].dwFlags = PSP_HASHELP;
378 psp[nPages].hInstance = hInstance;
379 psp[nPages].pszTemplate = MAKEINTRESOURCE(IDD_STARTUP_PAGE);
380 psp[nPages].pfnDlgProc = (DLGPROC)StartupPageWndProc;
381 ++nPages;
382
383 /* Tools page */
384 psp[nPages].dwSize = sizeof(PROPSHEETPAGE);
385 psp[nPages].dwFlags = PSP_HASHELP;
386 psp[nPages].hInstance = hInstance;
387 psp[nPages].pszTemplate = MAKEINTRESOURCE(IDD_TOOLS_PAGE);
388 psp[nPages].pfnDlgProc = (DLGPROC)ToolsPageWndProc;
389 ++nPages;
390 #endif
391
392 /* Set the total number of created pages */
393 psh.nPages = nPages;
394
395 /* Create the property sheet */
396 hPropSheet = (HWND)PropertySheet(&psh);
397 if (hPropSheet)
398 {
399 /* Center the property sheet on the desktop */
400 //ShowWindow(hPropSheet, SW_HIDE);
401 ClipOrCenterWindowToMonitor(hPropSheet, MONITOR_WORKAREA | MONITOR_CENTER);
402 //ShowWindow(hPropSheet, SW_SHOWNORMAL);
403 }
404
405 return hPropSheet;
406 }
407
408 BOOL Initialize(HINSTANCE hInstance)
409 {
410 BOOL Success = TRUE;
411 LPWSTR lpszVistaAppName = NULL;
412 HANDLE hSemaphore;
413 INITCOMMONCONTROLSEX InitControls;
414
415 /* Initialize our global version flags */
416 bIsWindows = TRUE; /* IsWindowsOS(); */ // TODO: Commented for testing purposes...
417 bIsOSVersionLessThanVista = TRUE; /* IsOSVersionLessThanVista(); */ // TODO: Commented for testing purposes...
418
419 /* Initialize global strings */
420 szAppName = LoadResourceString(hInstance, IDS_MSCONFIG);
421 if (!bIsOSVersionLessThanVista)
422 lpszVistaAppName = LoadResourceString(hInstance, IDS_MSCONFIG_2);
423
424 /* We use a semaphore in order to have a single-instance application */
425 hSemaphore = CreateSemaphoreW(NULL, 0, 1, L"MSConfigRunning");
426 if (!hSemaphore || GetLastError() == ERROR_ALREADY_EXISTS)
427 {
428 CloseHandle(hSemaphore);
429
430 /*
431 * A semaphore with the same name already exist. It should have been
432 * created by another instance of MSConfig. Try to find its window
433 * and bring it to front.
434 */
435 if ( (hSingleWnd && IsWindow(hSingleWnd)) ||
436 ( (hSingleWnd = FindWindowW(L"#32770", szAppName)) != NULL ) ||
437 (!bIsOSVersionLessThanVista ? ( (hSingleWnd = FindWindowW(L"#32770", lpszVistaAppName)) != NULL ) : FALSE) )
438 {
439 /* Found it. Show the window. */
440 ShowWindow(hSingleWnd, SW_SHOWNORMAL);
441 SetForegroundWindow(hSingleWnd);
442 }
443
444 /* Quit this instance of MSConfig */
445 Success = FALSE;
446 }
447 if (!bIsOSVersionLessThanVista) MemFree(lpszVistaAppName);
448
449 /* Quit now if we failed */
450 if (!Success)
451 {
452 MemFree(szAppName);
453 return FALSE;
454 }
455
456 /* Initialize the common controls */
457 InitControls.dwSize = sizeof(INITCOMMONCONTROLSEX);
458 InitControls.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS /* | ICC_PROGRESS_CLASS | ICC_HOTKEY_CLASS*/;
459 InitCommonControlsEx(&InitControls);
460
461 hInst = hInstance;
462
463 return Success;
464 }
465
466 VOID Cleanup(VOID)
467 {
468 MemFree(szAppName);
469
470 // // Close the sentry semaphore.
471 // CloseHandle(hSemaphore);
472 }
473
474 int APIENTRY _tWinMain(HINSTANCE hInstance,
475 HINSTANCE hPrevInstance,
476 LPTSTR lpCmdLine,
477 int nCmdShow)
478 {
479 MSG msg;
480 HACCEL hAccelTable;
481
482 UNREFERENCED_PARAMETER(hPrevInstance);
483 UNREFERENCED_PARAMETER(lpCmdLine);
484 UNREFERENCED_PARAMETER(nCmdShow);
485
486 /*
487 * Initialize this instance of MSConfig. Quit if we have
488 * another instance already running.
489 */
490 if (!Initialize(hInstance))
491 return -1;
492
493 // hInst = hInstance;
494
495 hMainWnd = CreatePropSheet(hInstance, NULL, szAppName);
496 if (!hMainWnd)
497 {
498 /* We failed, cleanup and bail out */
499 Cleanup();
500 return -1;
501 }
502
503 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_MSCONFIG));
504
505 /* Message loop */
506 while (IsWindow(hMainWnd) && GetMessage(&msg, NULL, 0, 0))
507 {
508 /*
509 * PropSheet_GetCurrentPageHwnd returns NULL when the user clicks the OK or Cancel button
510 * and after all of the pages have been notified. Apply button doesn't cause this to happen.
511 * We can then use the DestroyWindow function to destroy the property sheet.
512 */
513 if (PropSheet_GetCurrentPageHwnd(hMainWnd) == NULL)
514 break;
515
516 /* Process the accelerator table */
517 if (!TranslateAccelerator(hMainWnd, hAccelTable, &msg))
518 {
519 /*
520 * If e.g. an item on the tree view is being edited,
521 * we cannot pass the event to PropSheet_IsDialogMessage.
522 * Doing so causes the property sheet to be closed at Enter press
523 * (instead of completing edit operation).
524 */
525 if (/*g_bDisableDialogDispatch ||*/ !PropSheet_IsDialogMessage(hMainWnd, &msg))
526 {
527 TranslateMessage(&msg);
528 DispatchMessage(&msg);
529 }
530 }
531 }
532
533 // FIXME: Process the results of MSConfig !!
534
535 /* Destroy the accelerator table and the window */
536 if (hAccelTable != NULL)
537 DestroyAcceleratorTable(hAccelTable);
538
539 DestroyWindow(hMainWnd);
540
541 /* Finish cleanup and return */
542 Cleanup();
543 return (int)msg.wParam;
544 }
545
546 /* EOF */