mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
c994ba79d1
Reviewed-by: Serge Gautherie <reactos-git_serge_171003@gautherie.fr> Reviewed-by: Mark Jansen <mark.jansen@reactos.org> Reviewed-by: Stanislav Motylkov <x86corez@gmail.com>
610 lines
16 KiB
C
610 lines
16 KiB
C
/*
|
|
* ReactOS Management Console
|
|
* Copyright (C) 2006 - 2007 Thomas Weidenmueller
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#include <shellapi.h>
|
|
#include <stdlib.h>
|
|
#include <strsafe.h>
|
|
|
|
#include "resource.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
typedef struct _CONSOLE_MAINFRAME_WND
|
|
{
|
|
HWND hwnd;
|
|
HWND hwndMDIClient;
|
|
|
|
HMENU hMenuConsoleSmall;
|
|
HMENU hMenuConsoleLarge;
|
|
INT nConsoleCount;
|
|
union
|
|
{
|
|
DWORD Flags;
|
|
struct
|
|
{
|
|
DWORD AppAuthorMode : 1;
|
|
};
|
|
};
|
|
} CONSOLE_MAINFRAME_WND, *PCONSOLE_MAINFRAME_WND;
|
|
|
|
typedef struct _CONSOLE_CHILDFRM_WND
|
|
{
|
|
HWND hwnd;
|
|
PCONSOLE_MAINFRAME_WND MainFrame;
|
|
PTSTR pFileName;
|
|
} CONSOLE_CHILDFRM_WND, *PCONSOLE_CHILDFRM_WND;
|
|
|
|
static const TCHAR szMMCMainFrame[] = TEXT("MMCMainFrame");
|
|
static const TCHAR szMMCChildFrm[] = TEXT("MMCChildFrm");
|
|
|
|
static ULONG NewConsoleCount = 0;
|
|
|
|
PCONSOLE_CHILDFRM_WND
|
|
GetActiveChildInfo(VOID)
|
|
{
|
|
HWND hWndMDIChild;
|
|
|
|
hWndMDIChild = (HWND)SendMessageW(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
|
|
if (hWndMDIChild == NULL)
|
|
return NULL;
|
|
|
|
return (PCONSOLE_CHILDFRM_WND)GetWindowLongPtr(hWndMDIChild, 0);
|
|
}
|
|
|
|
|
|
static LPTSTR
|
|
CreateNewConsoleTitle(VOID)
|
|
{
|
|
LPTSTR lpTitle;
|
|
|
|
if (LoadAndFormatString(hAppInstance,
|
|
IDS_CONSOLETITLE,
|
|
&lpTitle,
|
|
++NewConsoleCount) == 0)
|
|
{
|
|
lpTitle = NULL;
|
|
}
|
|
|
|
return lpTitle;
|
|
}
|
|
|
|
HWND
|
|
CreateNewMDIChild(PCONSOLE_MAINFRAME_WND Info,
|
|
HWND hwndMDIClient)
|
|
{
|
|
MDICREATESTRUCT mcs;
|
|
HWND hChild;
|
|
|
|
mcs.szTitle = CreateNewConsoleTitle();
|
|
mcs.szClass = szMMCChildFrm;
|
|
mcs.hOwner = GetModuleHandle(NULL);
|
|
mcs.x = mcs.cx = CW_USEDEFAULT;
|
|
mcs.y = mcs.cy = CW_USEDEFAULT;
|
|
mcs.style = MDIS_ALLCHILDSTYLES;
|
|
|
|
hChild = (HWND)SendMessage(hwndMDIClient, WM_MDICREATE, 0, (LPARAM)&mcs);
|
|
if (hChild)
|
|
{
|
|
Info->nConsoleCount++;
|
|
}
|
|
|
|
return hChild;
|
|
}
|
|
|
|
|
|
static LRESULT
|
|
FrameOnCreate(HWND hwnd,
|
|
LPARAM lParam)
|
|
{
|
|
PCONSOLE_MAINFRAME_WND Info;
|
|
CLIENTCREATESTRUCT ccs;
|
|
LPCTSTR lpFileName = (LPCTSTR)(((LPCREATESTRUCT)lParam)->lpCreateParams);
|
|
|
|
Info = HeapAlloc(hAppHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(CONSOLE_MAINFRAME_WND));
|
|
if (Info == NULL)
|
|
return -1;
|
|
|
|
Info->hwnd = hwnd;
|
|
|
|
SetWindowLongPtr(hwnd,
|
|
0,
|
|
(LONG_PTR)Info);
|
|
|
|
Info->hMenuConsoleSmall = LoadMenu(hAppInstance,
|
|
MAKEINTRESOURCE(IDM_CONSOLE_SMALL));
|
|
|
|
Info->hMenuConsoleLarge = LoadMenu(hAppInstance,
|
|
MAKEINTRESOURCE(IDM_CONSOLE_LARGE));
|
|
|
|
if (lpFileName == NULL)
|
|
{
|
|
/* FIXME */
|
|
Info->AppAuthorMode = TRUE;
|
|
// Info->lpConsoleTitle = TEXT("ReactOS Management Console");
|
|
}
|
|
else
|
|
{
|
|
Info->AppAuthorMode = TRUE;
|
|
// Info->lpConsoleTitle = CreateNewConsoleTitle();
|
|
}
|
|
|
|
SetMenu(Info->hwnd,
|
|
Info->hMenuConsoleSmall);
|
|
|
|
SetWindowText(Info->hwnd, TEXT("ReactOS Management Console"));
|
|
|
|
ccs.hWindowMenu = GetSubMenu(Info->hMenuConsoleLarge, 1);
|
|
ccs.idFirstChild = IDM_MDI_FIRSTCHILD;
|
|
|
|
/* Create the MDI client window */
|
|
hwndMDIClient = CreateWindowEx(WS_EX_CLIENTEDGE,
|
|
L"MDICLIENT",
|
|
(LPCTSTR)NULL,
|
|
WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE | WS_BORDER,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
hwnd,
|
|
(HMENU)0xCAC,
|
|
hAppInstance,
|
|
(LPVOID)&ccs);
|
|
|
|
ShowWindow(Info->hwndMDIClient, SW_SHOW);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static VOID
|
|
SetFileName(
|
|
PCONSOLE_CHILDFRM_WND Info,
|
|
PWSTR pFileName)
|
|
{
|
|
DPRINT1("SetFileName(&p \'%S\')\n", Info, pFileName);
|
|
|
|
if (Info->pFileName != NULL)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, Info->pFileName);
|
|
Info->pFileName = NULL;
|
|
}
|
|
|
|
if (pFileName != NULL)
|
|
{
|
|
Info->pFileName = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
(_tcslen(pFileName) + 1) * sizeof(TCHAR));
|
|
if (Info->pFileName != NULL)
|
|
_tcscpy(Info->pFileName, pFileName);
|
|
}
|
|
}
|
|
|
|
static BOOL
|
|
DoSaveFileAs(
|
|
HWND hWnd,
|
|
PCONSOLE_CHILDFRM_WND pChildInfo);
|
|
|
|
static BOOL
|
|
DoSaveFile(
|
|
HWND hWnd,
|
|
PCONSOLE_CHILDFRM_WND pChildInfo)
|
|
{
|
|
DPRINT1("pChildInfo %p\n", pChildInfo);
|
|
|
|
DPRINT1("FileName %S\n", pChildInfo->pFileName);
|
|
|
|
if (pChildInfo->pFileName == NULL)
|
|
return DoSaveFileAs(hWnd, pChildInfo);
|
|
|
|
/* FIXME: Save the console here! */
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL
|
|
DoSaveFileAs(
|
|
HWND hWnd,
|
|
PCONSOLE_CHILDFRM_WND pChildInfo)
|
|
{
|
|
OPENFILENAME saveas;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
DPRINT1("pChildInfo %p\n", pChildInfo);
|
|
DPRINT1("FileName %S\n", pChildInfo->pFileName);
|
|
|
|
ZeroMemory(&saveas, sizeof(saveas));
|
|
|
|
if (pChildInfo->pFileName != NULL)
|
|
{
|
|
StringCbCopy(szPath, sizeof(szPath), pChildInfo->pFileName);
|
|
}
|
|
else
|
|
{
|
|
GetWindowText(pChildInfo->hwnd, szPath, _countof(szPath));
|
|
StringCbCat(szPath, sizeof(szPath), TEXT(".msc"));
|
|
}
|
|
|
|
saveas.lStructSize = sizeof(OPENFILENAME);
|
|
saveas.hwndOwner = hWnd;
|
|
saveas.hInstance = hAppInstance;
|
|
saveas.lpstrFilter = L"MSC Files\0*.msc\0";
|
|
saveas.lpstrFile = szPath;
|
|
saveas.nMaxFile = MAX_PATH;
|
|
saveas.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
|
|
saveas.lpstrDefExt = L"msc";
|
|
|
|
if (GetSaveFileName(&saveas))
|
|
{
|
|
/* HACK: Because in ROS, Save-As boxes don't check the validity
|
|
* of file names and thus, here, szPath can be invalid !! We only
|
|
* see its validity when we call DoSaveFile()... */
|
|
SetFileName(pChildInfo, szPath);
|
|
|
|
if (DoSaveFile(hWnd, pChildInfo))
|
|
{
|
|
// UpdateWindowCaption();
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
SetFileName(pChildInfo, NULL);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static BOOL
|
|
FrameOnSave(
|
|
HWND hWnd)
|
|
{
|
|
PCONSOLE_CHILDFRM_WND pChildInfo;
|
|
|
|
pChildInfo = GetActiveChildInfo();
|
|
if (pChildInfo == NULL)
|
|
return FALSE;
|
|
|
|
return DoSaveFile(hWnd, pChildInfo);
|
|
}
|
|
|
|
|
|
static BOOL
|
|
FrameOnSaveAs(
|
|
HWND hWnd)
|
|
{
|
|
PCONSOLE_CHILDFRM_WND pChildInfo;
|
|
|
|
pChildInfo = GetActiveChildInfo();
|
|
if (pChildInfo == NULL)
|
|
return FALSE;
|
|
|
|
return DoSaveFileAs(hWnd, pChildInfo);
|
|
}
|
|
|
|
static VOID
|
|
FrameOnCommand(HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PCONSOLE_MAINFRAME_WND Info;
|
|
HWND hChild;
|
|
LPTSTR lpTitle;
|
|
|
|
Info = (PCONSOLE_MAINFRAME_WND)GetWindowLongPtr(hwnd, 0);
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDM_FILE_NEW:
|
|
CreateNewMDIChild(Info, hwndMDIClient);
|
|
SetMenu(Info->hwnd,
|
|
Info->hMenuConsoleLarge);
|
|
break;
|
|
|
|
case IDM_FILE_SAVE:
|
|
FrameOnSave(hwnd);
|
|
break;
|
|
|
|
case IDM_FILE_SAVEAS:
|
|
FrameOnSaveAs(hwnd);
|
|
break;
|
|
|
|
case IDM_FILE_EXIT:
|
|
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case IDM_HELP_ABOUT:
|
|
if (AllocAndLoadString(&lpTitle, hAppInstance, IDS_APPTITLE))
|
|
{
|
|
ShellAbout(hwnd, lpTitle, NULL,
|
|
LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_MAINAPP)));
|
|
LocalFree(lpTitle);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (LOWORD(wParam) >= IDM_MDI_FIRSTCHILD)
|
|
{
|
|
DefFrameProc(hwnd, hwndMDIClient, uMsg, wParam, lParam);
|
|
}
|
|
else
|
|
{
|
|
hChild = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
|
|
if (hChild)
|
|
{
|
|
SendMessage(hChild, WM_COMMAND, wParam, lParam);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static VOID
|
|
FrameOnSize(HWND hMainWnd,
|
|
WORD cx,
|
|
WORD cy)
|
|
{
|
|
RECT rcClient; //, rcTool, rcStatus;
|
|
// int lvHeight, iToolHeight, iStatusHeight;
|
|
|
|
/* Size toolbar and get height */
|
|
// SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
|
|
// GetWindowRect(Info->hTool, &rcTool);
|
|
// iToolHeight = rcTool.bottom - rcTool.top;
|
|
|
|
/* Size status bar and get height */
|
|
// SendMessage(Info->hStatus, WM_SIZE, 0, 0);
|
|
// GetWindowRect(Info->hStatus, &rcStatus);
|
|
// iStatusHeight = rcStatus.bottom - rcStatus.top;
|
|
|
|
/* Calculate remaining height and size list view */
|
|
GetClientRect(hMainWnd, &rcClient);
|
|
// lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
|
|
SetWindowPos(hwndMDIClient, //Info->hTreeView,
|
|
NULL,
|
|
0,
|
|
0, //iToolHeight,
|
|
rcClient.right,
|
|
rcClient.bottom, //lvHeight,
|
|
SWP_NOZORDER);
|
|
}
|
|
|
|
|
|
static LRESULT CALLBACK
|
|
ConsoleMainFrameWndProc(IN HWND hwnd,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PCONSOLE_MAINFRAME_WND Info;
|
|
|
|
Info = (PCONSOLE_MAINFRAME_WND)GetWindowLongPtr(hwnd,
|
|
0);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
return FrameOnCreate(hwnd,
|
|
lParam);
|
|
|
|
case WM_COMMAND:
|
|
FrameOnCommand(hwnd,
|
|
uMsg,
|
|
wParam,
|
|
lParam);
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
FrameOnSize(hwnd,
|
|
LOWORD(lParam),
|
|
HIWORD(lParam));
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
DestroyWindow(hwnd);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
if (Info != NULL)
|
|
{
|
|
SetMenu(Info->hwnd,
|
|
NULL);
|
|
|
|
if (Info->hMenuConsoleSmall != NULL)
|
|
{
|
|
DestroyMenu(Info->hMenuConsoleSmall);
|
|
Info->hMenuConsoleSmall = NULL;
|
|
}
|
|
|
|
if (Info->hMenuConsoleLarge != NULL)
|
|
{
|
|
DestroyMenu(Info->hMenuConsoleLarge);
|
|
Info->hMenuConsoleLarge = NULL;
|
|
}
|
|
|
|
HeapFree(hAppHeap,
|
|
0,
|
|
Info);
|
|
}
|
|
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_USER_CLOSE_CHILD:
|
|
Info->nConsoleCount--;
|
|
if (Info->nConsoleCount == 0)
|
|
{
|
|
SetMenu(Info->hwnd,
|
|
Info->hMenuConsoleSmall);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return DefFrameProc(hwnd,
|
|
hwndMDIClient,
|
|
uMsg,
|
|
wParam,
|
|
lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static LRESULT CALLBACK
|
|
ConsoleChildFrmProc(IN HWND hwnd,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PCONSOLE_CHILDFRM_WND Info;
|
|
|
|
Info = (PCONSOLE_CHILDFRM_WND)GetWindowLongPtr(hwnd,
|
|
0);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
Info = HeapAlloc(hAppHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(CONSOLE_CHILDFRM_WND));
|
|
if (Info != NULL)
|
|
{
|
|
Info->hwnd = hwnd;
|
|
|
|
SetWindowLongPtr(hwnd,
|
|
0,
|
|
(LONG_PTR)Info);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
if (Info != NULL)
|
|
{
|
|
if (Info->pFileName)
|
|
HeapFree(hAppHeap, 0, Info->pFileName);
|
|
|
|
HeapFree(hAppHeap, 0, Info);
|
|
}
|
|
|
|
PostMessage(hwndMainConsole, WM_USER_CLOSE_CHILD, 0, 0);
|
|
break;
|
|
|
|
default:
|
|
return DefMDIChildProc(hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RegisterMMCWndClasses(VOID)
|
|
{
|
|
WNDCLASSEX wc = {0};
|
|
BOOL Ret;
|
|
|
|
/* Register the MMCMainFrame window class */
|
|
wc.cbSize = sizeof(WNDCLASSEX);
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = ConsoleMainFrameWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(PCONSOLE_MAINFRAME_WND);
|
|
wc.hInstance = hAppInstance;
|
|
wc.hIcon = LoadIcon(hAppInstance,
|
|
MAKEINTRESOURCE(IDI_MAINAPP));
|
|
wc.hCursor = LoadCursor(NULL,
|
|
MAKEINTRESOURCE(IDC_ARROW));
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = szMMCMainFrame;
|
|
|
|
Ret = (RegisterClassEx(&wc) != (ATOM)0);
|
|
|
|
if (Ret)
|
|
{
|
|
/* Register the MMCChildFrm window class */
|
|
wc.cbSize = sizeof(WNDCLASSEX);
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = ConsoleChildFrmProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(PCONSOLE_CHILDFRM_WND);
|
|
wc.hInstance = hAppInstance;
|
|
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = szMMCChildFrm;
|
|
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
|
|
|
Ret = (RegisterClassEx(&wc) != (ATOM)0);
|
|
if (!Ret)
|
|
{
|
|
UnregisterClass(szMMCMainFrame,
|
|
hAppInstance);
|
|
}
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
VOID
|
|
UnregisterMMCWndClasses(VOID)
|
|
{
|
|
UnregisterClass(szMMCChildFrm,
|
|
hAppInstance);
|
|
UnregisterClass(szMMCMainFrame,
|
|
hAppInstance);
|
|
}
|
|
|
|
HWND
|
|
CreateConsoleWindow(IN LPCTSTR lpFileName OPTIONAL,
|
|
int nCmdShow)
|
|
{
|
|
HWND hWndConsole;
|
|
LONG_PTR FileName = (LONG_PTR)lpFileName;
|
|
|
|
hWndConsole = CreateWindowEx(WS_EX_WINDOWEDGE,
|
|
szMMCMainFrame,
|
|
NULL,
|
|
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
NULL,
|
|
NULL,
|
|
hAppInstance,
|
|
(PVOID)FileName);
|
|
|
|
if (hWndConsole != NULL)
|
|
{
|
|
ShowWindow(hWndConsole, nCmdShow);
|
|
}
|
|
|
|
return hWndConsole;
|
|
}
|