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