[CLASS2]
[reactos.git] / 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 #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 */