xref: /reactos/base/applications/mmc/console.c (revision c994ba79)
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