reactos/base/applications/mmc/console.c
Kyle Katarn c994ba79d1
[MMC] Implement standard "About" menu action (#4639)
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>
2022-09-15 16:56:31 +03:00

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;
}