1 /*
2 * ReactOS Management Console
3 * Copyright (C) 2006 - 2007 Thomas Weidenmueller
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "precomp.h"
21 #include <shellapi.h>
22 #include <stdlib.h>
23 #include <strsafe.h>
24
25 #include "resource.h"
26
27 #define NDEBUG
28 #include <debug.h>
29
30 typedef struct _CONSOLE_MAINFRAME_WND
31 {
32 HWND hwnd;
33 HWND hwndMDIClient;
34
35 HMENU hMenuConsoleSmall;
36 HMENU hMenuConsoleLarge;
37 INT nConsoleCount;
38 union
39 {
40 DWORD Flags;
41 struct
42 {
43 DWORD AppAuthorMode : 1;
44 };
45 };
46 } CONSOLE_MAINFRAME_WND, *PCONSOLE_MAINFRAME_WND;
47
48 typedef struct _CONSOLE_CHILDFRM_WND
49 {
50 HWND hwnd;
51 PCONSOLE_MAINFRAME_WND MainFrame;
52 PTSTR pFileName;
53 } CONSOLE_CHILDFRM_WND, *PCONSOLE_CHILDFRM_WND;
54
55 static const TCHAR szMMCMainFrame[] = TEXT("MMCMainFrame");
56 static const TCHAR szMMCChildFrm[] = TEXT("MMCChildFrm");
57
58 static ULONG NewConsoleCount = 0;
59
60 PCONSOLE_CHILDFRM_WND
GetActiveChildInfo(VOID)61 GetActiveChildInfo(VOID)
62 {
63 HWND hWndMDIChild;
64
65 hWndMDIChild = (HWND)SendMessageW(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
66 if (hWndMDIChild == NULL)
67 return NULL;
68
69 return (PCONSOLE_CHILDFRM_WND)GetWindowLongPtr(hWndMDIChild, 0);
70 }
71
72
73 static LPTSTR
CreateNewConsoleTitle(VOID)74 CreateNewConsoleTitle(VOID)
75 {
76 LPTSTR lpTitle;
77
78 if (LoadAndFormatString(hAppInstance,
79 IDS_CONSOLETITLE,
80 &lpTitle,
81 ++NewConsoleCount) == 0)
82 {
83 lpTitle = NULL;
84 }
85
86 return lpTitle;
87 }
88
89 HWND
CreateNewMDIChild(PCONSOLE_MAINFRAME_WND Info,HWND hwndMDIClient)90 CreateNewMDIChild(PCONSOLE_MAINFRAME_WND Info,
91 HWND hwndMDIClient)
92 {
93 MDICREATESTRUCT mcs;
94 HWND hChild;
95
96 mcs.szTitle = CreateNewConsoleTitle();
97 mcs.szClass = szMMCChildFrm;
98 mcs.hOwner = GetModuleHandle(NULL);
99 mcs.x = mcs.cx = CW_USEDEFAULT;
100 mcs.y = mcs.cy = CW_USEDEFAULT;
101 mcs.style = MDIS_ALLCHILDSTYLES;
102
103 hChild = (HWND)SendMessage(hwndMDIClient, WM_MDICREATE, 0, (LPARAM)&mcs);
104 if (hChild)
105 {
106 Info->nConsoleCount++;
107 }
108
109 return hChild;
110 }
111
112
113 static LRESULT
FrameOnCreate(HWND hwnd,LPARAM lParam)114 FrameOnCreate(HWND hwnd,
115 LPARAM lParam)
116 {
117 PCONSOLE_MAINFRAME_WND Info;
118 CLIENTCREATESTRUCT ccs;
119 LPCTSTR lpFileName = (LPCTSTR)(((LPCREATESTRUCT)lParam)->lpCreateParams);
120
121 Info = HeapAlloc(hAppHeap,
122 HEAP_ZERO_MEMORY,
123 sizeof(CONSOLE_MAINFRAME_WND));
124 if (Info == NULL)
125 return -1;
126
127 Info->hwnd = hwnd;
128
129 SetWindowLongPtr(hwnd,
130 0,
131 (LONG_PTR)Info);
132
133 Info->hMenuConsoleSmall = LoadMenu(hAppInstance,
134 MAKEINTRESOURCE(IDM_CONSOLE_SMALL));
135
136 Info->hMenuConsoleLarge = LoadMenu(hAppInstance,
137 MAKEINTRESOURCE(IDM_CONSOLE_LARGE));
138
139 if (lpFileName == NULL)
140 {
141 /* FIXME */
142 Info->AppAuthorMode = TRUE;
143 // Info->lpConsoleTitle = TEXT("ReactOS Management Console");
144 }
145 else
146 {
147 Info->AppAuthorMode = TRUE;
148 // Info->lpConsoleTitle = CreateNewConsoleTitle();
149 }
150
151 SetMenu(Info->hwnd,
152 Info->hMenuConsoleSmall);
153
154 SetWindowText(Info->hwnd, TEXT("ReactOS Management Console"));
155
156 ccs.hWindowMenu = GetSubMenu(Info->hMenuConsoleLarge, 1);
157 ccs.idFirstChild = IDM_MDI_FIRSTCHILD;
158
159 /* Create the MDI client window */
160 hwndMDIClient = CreateWindowEx(WS_EX_CLIENTEDGE,
161 L"MDICLIENT",
162 (LPCTSTR)NULL,
163 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE | WS_BORDER,
164 CW_USEDEFAULT,
165 CW_USEDEFAULT,
166 CW_USEDEFAULT,
167 CW_USEDEFAULT,
168 hwnd,
169 (HMENU)0xCAC,
170 hAppInstance,
171 (LPVOID)&ccs);
172
173 ShowWindow(Info->hwndMDIClient, SW_SHOW);
174
175 return 0;
176 }
177
178
179 static VOID
SetFileName(PCONSOLE_CHILDFRM_WND Info,PWSTR pFileName)180 SetFileName(
181 PCONSOLE_CHILDFRM_WND Info,
182 PWSTR pFileName)
183 {
184 DPRINT1("SetFileName(&p \'%S\')\n", Info, pFileName);
185
186 if (Info->pFileName != NULL)
187 {
188 HeapFree(GetProcessHeap(), 0, Info->pFileName);
189 Info->pFileName = NULL;
190 }
191
192 if (pFileName != NULL)
193 {
194 Info->pFileName = HeapAlloc(GetProcessHeap(),
195 0,
196 (_tcslen(pFileName) + 1) * sizeof(TCHAR));
197 if (Info->pFileName != NULL)
198 _tcscpy(Info->pFileName, pFileName);
199 }
200 }
201
202 static BOOL
203 DoSaveFileAs(
204 HWND hWnd,
205 PCONSOLE_CHILDFRM_WND pChildInfo);
206
207 static BOOL
DoSaveFile(HWND hWnd,PCONSOLE_CHILDFRM_WND pChildInfo)208 DoSaveFile(
209 HWND hWnd,
210 PCONSOLE_CHILDFRM_WND pChildInfo)
211 {
212 DPRINT1("pChildInfo %p\n", pChildInfo);
213
214 DPRINT1("FileName %S\n", pChildInfo->pFileName);
215
216 if (pChildInfo->pFileName == NULL)
217 return DoSaveFileAs(hWnd, pChildInfo);
218
219 /* FIXME: Save the console here! */
220
221 return TRUE;
222 }
223
224 static BOOL
DoSaveFileAs(HWND hWnd,PCONSOLE_CHILDFRM_WND pChildInfo)225 DoSaveFileAs(
226 HWND hWnd,
227 PCONSOLE_CHILDFRM_WND pChildInfo)
228 {
229 OPENFILENAME saveas;
230 TCHAR szPath[MAX_PATH];
231
232 DPRINT1("pChildInfo %p\n", pChildInfo);
233 DPRINT1("FileName %S\n", pChildInfo->pFileName);
234
235 ZeroMemory(&saveas, sizeof(saveas));
236
237 if (pChildInfo->pFileName != NULL)
238 {
239 StringCbCopy(szPath, sizeof(szPath), pChildInfo->pFileName);
240 }
241 else
242 {
243 GetWindowText(pChildInfo->hwnd, szPath, _countof(szPath));
244 StringCbCat(szPath, sizeof(szPath), TEXT(".msc"));
245 }
246
247 saveas.lStructSize = sizeof(OPENFILENAME);
248 saveas.hwndOwner = hWnd;
249 saveas.hInstance = hAppInstance;
250 saveas.lpstrFilter = L"MSC Files\0*.msc\0";
251 saveas.lpstrFile = szPath;
252 saveas.nMaxFile = MAX_PATH;
253 saveas.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
254 saveas.lpstrDefExt = L"msc";
255
256 if (GetSaveFileName(&saveas))
257 {
258 /* HACK: Because in ROS, Save-As boxes don't check the validity
259 * of file names and thus, here, szPath can be invalid !! We only
260 * see its validity when we call DoSaveFile()... */
261 SetFileName(pChildInfo, szPath);
262
263 if (DoSaveFile(hWnd, pChildInfo))
264 {
265 // UpdateWindowCaption();
266 return TRUE;
267 }
268 else
269 {
270 SetFileName(pChildInfo, NULL);
271 return FALSE;
272 }
273 }
274 else
275 {
276 return FALSE;
277 }
278 }
279
280 static BOOL
FrameOnSave(HWND hWnd)281 FrameOnSave(
282 HWND hWnd)
283 {
284 PCONSOLE_CHILDFRM_WND pChildInfo;
285
286 pChildInfo = GetActiveChildInfo();
287 if (pChildInfo == NULL)
288 return FALSE;
289
290 return DoSaveFile(hWnd, pChildInfo);
291 }
292
293
294 static BOOL
FrameOnSaveAs(HWND hWnd)295 FrameOnSaveAs(
296 HWND hWnd)
297 {
298 PCONSOLE_CHILDFRM_WND pChildInfo;
299
300 pChildInfo = GetActiveChildInfo();
301 if (pChildInfo == NULL)
302 return FALSE;
303
304 return DoSaveFileAs(hWnd, pChildInfo);
305 }
306
307 static VOID
FrameOnCommand(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)308 FrameOnCommand(HWND hwnd,
309 UINT uMsg,
310 WPARAM wParam,
311 LPARAM lParam)
312 {
313 PCONSOLE_MAINFRAME_WND Info;
314 HWND hChild;
315 LPTSTR lpTitle;
316
317 Info = (PCONSOLE_MAINFRAME_WND)GetWindowLongPtr(hwnd, 0);
318
319 switch (LOWORD(wParam))
320 {
321 case IDM_FILE_NEW:
322 CreateNewMDIChild(Info, hwndMDIClient);
323 SetMenu(Info->hwnd,
324 Info->hMenuConsoleLarge);
325 break;
326
327 case IDM_FILE_SAVE:
328 FrameOnSave(hwnd);
329 break;
330
331 case IDM_FILE_SAVEAS:
332 FrameOnSaveAs(hwnd);
333 break;
334
335 case IDM_FILE_EXIT:
336 PostMessage(hwnd, WM_CLOSE, 0, 0);
337 break;
338
339 case IDM_HELP_ABOUT:
340 if (AllocAndLoadString(&lpTitle, hAppInstance, IDS_APPTITLE))
341 {
342 ShellAbout(hwnd, lpTitle, NULL,
343 LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_MAINAPP)));
344 LocalFree(lpTitle);
345 }
346 break;
347
348 default:
349 if (LOWORD(wParam) >= IDM_MDI_FIRSTCHILD)
350 {
351 DefFrameProc(hwnd, hwndMDIClient, uMsg, wParam, lParam);
352 }
353 else
354 {
355 hChild = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
356 if (hChild)
357 {
358 SendMessage(hChild, WM_COMMAND, wParam, lParam);
359 }
360 }
361 break;
362 }
363 }
364
365
366 static VOID
FrameOnSize(HWND hMainWnd,WORD cx,WORD cy)367 FrameOnSize(HWND hMainWnd,
368 WORD cx,
369 WORD cy)
370 {
371 RECT rcClient; //, rcTool, rcStatus;
372 // int lvHeight, iToolHeight, iStatusHeight;
373
374 /* Size toolbar and get height */
375 // SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
376 // GetWindowRect(Info->hTool, &rcTool);
377 // iToolHeight = rcTool.bottom - rcTool.top;
378
379 /* Size status bar and get height */
380 // SendMessage(Info->hStatus, WM_SIZE, 0, 0);
381 // GetWindowRect(Info->hStatus, &rcStatus);
382 // iStatusHeight = rcStatus.bottom - rcStatus.top;
383
384 /* Calculate remaining height and size list view */
385 GetClientRect(hMainWnd, &rcClient);
386 // lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
387 SetWindowPos(hwndMDIClient, //Info->hTreeView,
388 NULL,
389 0,
390 0, //iToolHeight,
391 rcClient.right,
392 rcClient.bottom, //lvHeight,
393 SWP_NOZORDER);
394 }
395
396
397 static LRESULT CALLBACK
ConsoleMainFrameWndProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)398 ConsoleMainFrameWndProc(IN HWND hwnd,
399 IN UINT uMsg,
400 IN WPARAM wParam,
401 IN LPARAM lParam)
402 {
403 PCONSOLE_MAINFRAME_WND Info;
404
405 Info = (PCONSOLE_MAINFRAME_WND)GetWindowLongPtr(hwnd,
406 0);
407
408 switch (uMsg)
409 {
410 case WM_CREATE:
411 return FrameOnCreate(hwnd,
412 lParam);
413
414 case WM_COMMAND:
415 FrameOnCommand(hwnd,
416 uMsg,
417 wParam,
418 lParam);
419 break;
420
421 case WM_SIZE:
422 FrameOnSize(hwnd,
423 LOWORD(lParam),
424 HIWORD(lParam));
425 break;
426
427 case WM_CLOSE:
428 DestroyWindow(hwnd);
429 break;
430
431 case WM_DESTROY:
432 if (Info != NULL)
433 {
434 SetMenu(Info->hwnd,
435 NULL);
436
437 if (Info->hMenuConsoleSmall != NULL)
438 {
439 DestroyMenu(Info->hMenuConsoleSmall);
440 Info->hMenuConsoleSmall = NULL;
441 }
442
443 if (Info->hMenuConsoleLarge != NULL)
444 {
445 DestroyMenu(Info->hMenuConsoleLarge);
446 Info->hMenuConsoleLarge = NULL;
447 }
448
449 HeapFree(hAppHeap,
450 0,
451 Info);
452 }
453
454 PostQuitMessage(0);
455 break;
456
457 case WM_USER_CLOSE_CHILD:
458 Info->nConsoleCount--;
459 if (Info->nConsoleCount == 0)
460 {
461 SetMenu(Info->hwnd,
462 Info->hMenuConsoleSmall);
463 }
464 break;
465
466 default:
467 return DefFrameProc(hwnd,
468 hwndMDIClient,
469 uMsg,
470 wParam,
471 lParam);
472 }
473
474 return 0;
475 }
476
477
478 static LRESULT CALLBACK
ConsoleChildFrmProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)479 ConsoleChildFrmProc(IN HWND hwnd,
480 IN UINT uMsg,
481 IN WPARAM wParam,
482 IN LPARAM lParam)
483 {
484 PCONSOLE_CHILDFRM_WND Info;
485
486 Info = (PCONSOLE_CHILDFRM_WND)GetWindowLongPtr(hwnd,
487 0);
488
489 switch (uMsg)
490 {
491 case WM_CREATE:
492 Info = HeapAlloc(hAppHeap,
493 HEAP_ZERO_MEMORY,
494 sizeof(CONSOLE_CHILDFRM_WND));
495 if (Info != NULL)
496 {
497 Info->hwnd = hwnd;
498
499 SetWindowLongPtr(hwnd,
500 0,
501 (LONG_PTR)Info);
502 }
503 break;
504
505 case WM_DESTROY:
506 if (Info != NULL)
507 {
508 if (Info->pFileName)
509 HeapFree(hAppHeap, 0, Info->pFileName);
510
511 HeapFree(hAppHeap, 0, Info);
512 }
513
514 PostMessage(hwndMainConsole, WM_USER_CLOSE_CHILD, 0, 0);
515 break;
516
517 default:
518 return DefMDIChildProc(hwnd, uMsg, wParam, lParam);
519 }
520
521 return 0;
522 }
523
524
525 BOOL
RegisterMMCWndClasses(VOID)526 RegisterMMCWndClasses(VOID)
527 {
528 WNDCLASSEX wc = {0};
529 BOOL Ret;
530
531 /* Register the MMCMainFrame window class */
532 wc.cbSize = sizeof(WNDCLASSEX);
533 wc.style = 0;
534 wc.lpfnWndProc = ConsoleMainFrameWndProc;
535 wc.cbClsExtra = 0;
536 wc.cbWndExtra = sizeof(PCONSOLE_MAINFRAME_WND);
537 wc.hInstance = hAppInstance;
538 wc.hIcon = LoadIcon(hAppInstance,
539 MAKEINTRESOURCE(IDI_MAINAPP));
540 wc.hCursor = LoadCursor(NULL,
541 MAKEINTRESOURCE(IDC_ARROW));
542 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
543 wc.lpszMenuName = NULL;
544 wc.lpszClassName = szMMCMainFrame;
545
546 Ret = (RegisterClassEx(&wc) != (ATOM)0);
547
548 if (Ret)
549 {
550 /* Register the MMCChildFrm window class */
551 wc.cbSize = sizeof(WNDCLASSEX);
552 wc.style = CS_HREDRAW | CS_VREDRAW;
553 wc.lpfnWndProc = ConsoleChildFrmProc;
554 wc.cbClsExtra = 0;
555 wc.cbWndExtra = sizeof(PCONSOLE_CHILDFRM_WND);
556 wc.hInstance = hAppInstance;
557 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
558 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
559 wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
560 wc.lpszMenuName = NULL;
561 wc.lpszClassName = szMMCChildFrm;
562 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
563
564 Ret = (RegisterClassEx(&wc) != (ATOM)0);
565 if (!Ret)
566 {
567 UnregisterClass(szMMCMainFrame,
568 hAppInstance);
569 }
570 }
571
572 return Ret;
573 }
574
575 VOID
UnregisterMMCWndClasses(VOID)576 UnregisterMMCWndClasses(VOID)
577 {
578 UnregisterClass(szMMCChildFrm,
579 hAppInstance);
580 UnregisterClass(szMMCMainFrame,
581 hAppInstance);
582 }
583
584 HWND
CreateConsoleWindow(IN LPCTSTR lpFileName OPTIONAL,int nCmdShow)585 CreateConsoleWindow(IN LPCTSTR lpFileName OPTIONAL,
586 int nCmdShow)
587 {
588 HWND hWndConsole;
589 LONG_PTR FileName = (LONG_PTR)lpFileName;
590
591 hWndConsole = CreateWindowEx(WS_EX_WINDOWEDGE,
592 szMMCMainFrame,
593 NULL,
594 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
595 CW_USEDEFAULT,
596 CW_USEDEFAULT,
597 CW_USEDEFAULT,
598 CW_USEDEFAULT,
599 NULL,
600 NULL,
601 hAppInstance,
602 (PVOID)FileName);
603
604 if (hWndConsole != NULL)
605 {
606 ShowWindow(hWndConsole, nCmdShow);
607 }
608
609 return hWndConsole;
610 }
611