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