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