xref: /reactos/base/applications/mmc/console.c (revision 8ee308d7)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
576 UnregisterMMCWndClasses(VOID)
577 {
578     UnregisterClass(szMMCChildFrm,
579                     hAppInstance);
580     UnregisterClass(szMMCMainFrame,
581                     hAppInstance);
582 }
583 
584 HWND
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