Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

592 lines
17 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
menu.c
Abstract:
This file implements the system menu management.
Author:
Therese Stowell (thereses) Jan-24-1992 (swiped from Win3.1)
--*/
#include "precomp.h"
#pragma hdrstop
LPTHREAD_START_ROUTINE PropRoutine; // client side properties routine
VOID
MyModifyMenuItem(
IN PCONSOLE_INFORMATION Console,
IN UINT ItemId
)
/*++
This routine edits the indicated control to one word. This is used to
trim the Accelerator key text off of the end of the standard menu
items because we don't support the accelerators.
--*/
{
WCHAR ItemString[30];
int ItemLength;
ItemLength = LoadString(ghInstance,ItemId,ItemString,30);
if (ItemLength == 0) {
//DbgPrint("LoadString in MyModifyMenu failed %d\n",GetLastError());
return;
}
ModifyMenu(Console->hMenu,
ItemId,
MF_STRING | MF_BYCOMMAND,
ItemId,
ItemString
);
}
VOID
InitSystemMenu(
IN PCONSOLE_INFORMATION Console
)
{
WCHAR ItemString[30];
int ItemLength;
HMENU hHeirMenu;
//
// load the clipboard menu.
//
Console->hHeirMenu = hHeirMenu = LoadMenu(ghInstance, MAKEINTRESOURCE(ID_WOMENU));
if (Console->hHeirMenu) {
ItemLength = LoadString(ghInstance,cmEdit,ItemString,30);
if (ItemLength == 0)
KdPrint(("LoadString 1 failed %d\n",GetLastError()));
}
else
KdPrint(("LoadMenu 1 failed %d\n",GetLastError()));
//
// edit the accelerators off of the standard items.
//
MyModifyMenuItem(Console,SC_RESTORE);
MyModifyMenuItem(Console,SC_MOVE);
MyModifyMenuItem(Console,SC_SIZE);
MyModifyMenuItem(Console,SC_MINIMIZE);
MyModifyMenuItem(Console,SC_MAXIMIZE);
MyModifyMenuItem(Console,SC_CLOSE);
//
// Append the clipboard menu to system menu
//
if (!AppendMenu(Console->hMenu,
MF_POPUP | MF_STRING,
(UINT)Console->hHeirMenu,
//"Edit"
ItemString
)) {
KdPrint(("AppendMenu 1 failed %d\n",GetLastError()));
}
//
// Add other items to system menu
//
ItemLength = LoadString(ghInstance,cmControl,ItemString,30);
if (ItemLength == 0)
KdPrint(("LoadString %d failed %d\n",cmControl,GetLastError()));
if (ItemLength) {
if (!AppendMenu(Console->hMenu, MF_STRING, cmControl, ItemString)) {
KdPrint(("AppendMenu %d failed %d\n",cmControl,GetLastError()));
}
}
}
VOID
InitializeMenu(
IN PCONSOLE_INFORMATION Console
)
/*++
this initializes the system menu when a WM_INITMENU message
is read.
--*/
{
HMENU hMenu = Console->hMenu;
HMENU hHeirMenu = Console->hHeirMenu;
//
// if we're in graphics mode, disable size menu
//
if (!(Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER)) {
EnableMenuItem(hMenu,SC_SIZE,MF_GRAYED);
}
//
// if the console is iconic, disable Mark and Scroll.
//
if (Console->Flags & CONSOLE_IS_ICONIC) {
EnableMenuItem(hHeirMenu,cmMark,MF_GRAYED);
EnableMenuItem(hHeirMenu,cmScroll,MF_GRAYED);
} else {
//
// if the console is not iconic
// if there are no scroll bars
// or we're in mark mode
// disable scroll
// else
// enable scroll
//
// if we're in scroll mode
// disable mark
// else
// enable mark
if ((Console->CurrentScreenBuffer->WindowMaximizedX &&
Console->CurrentScreenBuffer->WindowMaximizedY) ||
Console->Flags & CONSOLE_SELECTING) {
EnableMenuItem(hHeirMenu,cmScroll,MF_GRAYED);
} else {
EnableMenuItem(hHeirMenu,cmScroll,MF_ENABLED);
}
if (Console->Flags & CONSOLE_SCROLLING) {
EnableMenuItem(hHeirMenu,cmMark,MF_GRAYED);
} else {
EnableMenuItem(hHeirMenu,cmMark,MF_ENABLED);
}
}
//
// if we're selecting or scrolling, disable Paste.
// otherwise enable it.
//
if (Console->Flags & (CONSOLE_SELECTING | CONSOLE_SCROLLING)) {
EnableMenuItem(hHeirMenu,cmPaste,MF_GRAYED);
} else {
EnableMenuItem(hHeirMenu,cmPaste,MF_ENABLED);
}
//
// if app has active selection, enable copy; else disabled
//
if (Console->Flags & CONSOLE_SELECTING &&
Console->SelectionFlags & CONSOLE_SELECTION_NOT_EMPTY) {
EnableMenuItem(hHeirMenu,cmCopy,MF_ENABLED);
} else {
EnableMenuItem(hHeirMenu,cmCopy,MF_GRAYED);
}
//
// disable close
//
if (Console->Flags & CONSOLE_DISABLE_CLOSE)
EnableMenuItem(hMenu,SC_CLOSE,MF_GRAYED);
else
EnableMenuItem(hMenu,SC_CLOSE,MF_ENABLED);
//
// enable Move if not iconic
//
if (Console->Flags & CONSOLE_IS_ICONIC) {
EnableMenuItem(hMenu,SC_MOVE,MF_GRAYED);
} else {
EnableMenuItem(hMenu,SC_MOVE,MF_ENABLED);
}
//
// enable Settings if not already doing it
//
if (Console->hWndProperties && IsWindow(Console->hWndProperties)) {
EnableMenuItem(hMenu,cmControl,MF_GRAYED);
} else {
EnableMenuItem(hMenu,cmControl,MF_ENABLED);
Console->hWndProperties = NULL;
}
}
VOID
SetWinText(
IN PCONSOLE_INFORMATION Console,
IN UINT wID,
IN BOOL Add
)
/*++
This routine adds or removes the name to or from the
beginning of the window title. The possible names
are "Scroll", "Mark", "Paste", and "Copy".
--*/
{
WCHAR TextBuf[256];
PWCHAR TextBufPtr;
int TextLength;
int NameLength;
WCHAR NameString[20];
NameLength = LoadString(ghInstance,wID,NameString,
sizeof(NameString)/sizeof(WCHAR));
if (Add) {
RtlCopyMemory(TextBuf,NameString,NameLength*sizeof(WCHAR));
TextBuf[NameLength] = ' ';
TextBufPtr = TextBuf + NameLength + 1;
} else {
TextBufPtr = TextBuf;
}
TextLength = GetWindowText(Console->hWnd,
TextBufPtr,
sizeof(TextBuf)/sizeof(WCHAR)-NameLength-1);
if (TextLength == 0)
return;
if (Add) {
TextBufPtr = TextBuf;
} else {
/*
* The window title might have already been reset, so make sure
* the name is there before trying to remove it.
*/
if (wcsncmp(NameString, TextBufPtr, NameLength) != 0)
return;
TextBufPtr = TextBuf + NameLength + 1;
}
SetWindowText(Console->hWnd,TextBufPtr);
}
VOID
PropertiesDlgShow(
IN PCONSOLE_INFORMATION Console
)
/*++
Displays the properties dialog and updates the window state,
if necessary.
--*/
{
HANDLE hSection = NULL;
HANDLE hClientSection = NULL;
HANDLE hThread;
ULONG ulViewSize;
LARGE_INTEGER li;
NTSTATUS Status;
PCONSOLE_STATE_INFO pStateInfo;
PCONSOLE_PROCESS_HANDLE ProcessHandleRecord;
PSCREEN_INFORMATION ScreenInfo;
LPTHREAD_START_ROUTINE MyPropRoutine;
/*
* Create a shared memory block.
*/
li.QuadPart = sizeof(CONSOLE_STATE_INFO) + Console->OriginalTitleLength;
Status = NtCreateSection(&hSection,
SECTION_ALL_ACCESS,
NULL,
&li,
PAGE_READWRITE,
SEC_COMMIT,
NULL);
if (!NT_SUCCESS(Status)) {
KdPrint(("CONSRV: error %x creating file mapping\n", Status));
return;
}
/*
* Get a pointer to the shared memory block.
*/
pStateInfo = NULL;
ulViewSize = 0;
Status = NtMapViewOfSection(hSection,
NtCurrentProcess(),
&pStateInfo,
0,
0,
NULL,
&ulViewSize,
ViewUnmap,
0,
PAGE_READWRITE);
if (!NT_SUCCESS(Status)) {
KdPrint(("CONSRV: error %x mapping view of file\n", Status));
NtClose(hSection);
return;
}
/*
* Fill in the shared memory block with the current values.
*/
ScreenInfo = Console->CurrentScreenBuffer;
pStateInfo->Length = li.LowPart;
pStateInfo->ScreenBufferSize = ScreenInfo->ScreenBufferSize;
pStateInfo->WindowSize.X = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
pStateInfo->WindowSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
pStateInfo->WindowPosX = Console->WindowRect.left;
pStateInfo->WindowPosY = Console->WindowRect.top;
if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
pStateInfo->FontSize = SCR_FONTSIZE(ScreenInfo);
pStateInfo->FontFamily = SCR_FAMILY(ScreenInfo);
pStateInfo->FontWeight = SCR_FONTWEIGHT(ScreenInfo);
wcscpy(pStateInfo->FaceName, SCR_FACENAME(ScreenInfo));
pStateInfo->CursorSize = ScreenInfo->BufferInfo.TextInfo.CursorSize;
}
pStateInfo->FullScreen = Console->FullScreenFlags & CONSOLE_FULLSCREEN;
pStateInfo->QuickEdit = Console->Flags & CONSOLE_QUICK_EDIT_MODE;
pStateInfo->AutoPosition = Console->Flags & CONSOLE_AUTO_POSITION;
pStateInfo->InsertMode = Console->InsertMode;
pStateInfo->ScreenAttributes = ScreenInfo->Attributes;
pStateInfo->PopupAttributes = ScreenInfo->PopupAttributes;
pStateInfo->HistoryBufferSize = Console->CommandHistorySize;
pStateInfo->NumberOfHistoryBuffers = Console->MaxCommandHistories;
pStateInfo->HistoryNoDup = Console->Flags & CONSOLE_HISTORY_NODUP;
RtlCopyMemory(pStateInfo->ColorTable,
Console->ColorTable,
sizeof(Console->ColorTable));
pStateInfo->hWnd = Console->hWnd;
wcscpy(pStateInfo->ConsoleTitle, Console->OriginalTitle);
NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo);
/*
* Map the shared memory block handle into the client side process's
* address space.
*/
ProcessHandleRecord = CONTAINING_RECORD(Console->ProcessHandleList.Blink,
CONSOLE_PROCESS_HANDLE,
ListLink);
Status = NtDuplicateObject(NtCurrentProcess(),
hSection,
ProcessHandleRecord->ProcessHandle,
&hClientSection,
0,
0,
DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status)) {
KdPrint(("CONSRV: error %x mapping handle to client\n", Status));
NtClose(hSection);
return;
}
/*
* Get a pointer to the client-side properties routine.
*/
if (ProcessHandleRecord->PropRoutine) {
MyPropRoutine = ProcessHandleRecord->PropRoutine;
} else {
MyPropRoutine = PropRoutine;
}
/*
* Call back into the client process to spawn the properties dialog.
*/
UnlockConsole(Console);
hThread = InternalCreateCallbackThread(ProcessHandleRecord->ProcessHandle,
(DWORD)MyPropRoutine,
(DWORD)hClientSection);
if (!hThread) {
KdPrint(("CONSRV: CreateRemoteThread failed %d\n", GetLastError()));
}
LockConsole(Console);
/*
* Close any open handles and free allocated memory.
*/
if (hThread)
NtClose(hThread);
if (hSection)
NtClose(hSection);
return;
}
VOID
PropertiesUpdate(
IN PCONSOLE_INFORMATION Console,
IN HANDLE hClientSection
)
/*++
Updates the console state from information sent by the properties
dialog box.
--*/
{
HANDLE hSection;
ULONG ulViewSize;
NTSTATUS Status;
PCONSOLE_STATE_INFO pStateInfo;
PCONSOLE_PROCESS_HANDLE ProcessHandleRecord;
PSCREEN_INFORMATION ScreenInfo;
ULONG FontIndex;
WINDOWPLACEMENT wp;
COORD NewSize;
/*
* Map the shared memory block handle into our address space.
*/
ProcessHandleRecord = CONTAINING_RECORD(Console->ProcessHandleList.Blink,
CONSOLE_PROCESS_HANDLE,
ListLink);
Status = NtDuplicateObject(ProcessHandleRecord->ProcessHandle,
hClientSection,
NtCurrentProcess(),
&hSection,
0,
0,
DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status)) {
KdPrint(("CONSRV: error %x mapping client handle\n", Status));
return;
}
/*
* Get a pointer to the shared memory block.
*/
pStateInfo = NULL;
ulViewSize = 0;
Status = NtMapViewOfSection(hSection,
NtCurrentProcess(),
&pStateInfo,
0,
0,
NULL,
&ulViewSize,
ViewUnmap,
0,
PAGE_READONLY);
if (!NT_SUCCESS(Status)) {
KdPrint(("CONSRV: error %x mapping view of file\n", Status));
NtClose(hSection);
return;
}
/*
* Verify the size of the shared memory block.
*/
if (ulViewSize < sizeof(CONSOLE_STATE_INFO)) {
KdPrint(("CONSRV: sizeof(hSection) < sizeof(CONSOLE_STATE_INFO)\n"));
NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo);
NtClose(hSection);
return;
}
/*
* Update the console state from the supplied values.
*/
ScreenInfo = Console->CurrentScreenBuffer;
if (!(Console->Flags & CONSOLE_VDM_REGISTERED) &&
(pStateInfo->ScreenBufferSize.X != ScreenInfo->ScreenBufferSize.X ||
pStateInfo->ScreenBufferSize.Y != ScreenInfo->ScreenBufferSize.Y)) {
ResizeScreenBuffer(ScreenInfo,
pStateInfo->ScreenBufferSize,
TRUE);
}
FontIndex = FindCreateFont(pStateInfo->FontFamily,
pStateInfo->FaceName,
pStateInfo->FontSize,
pStateInfo->FontWeight);
SetScreenBufferFont(ScreenInfo, FontIndex);
SetCursorInformation(ScreenInfo,
pStateInfo->CursorSize,
ScreenInfo->BufferInfo.TextInfo.CursorVisible);
NewSize.X = min(pStateInfo->WindowSize.X, ScreenInfo->MaximumWindowSize.X);
NewSize.Y = min(pStateInfo->WindowSize.Y, ScreenInfo->MaximumWindowSize.Y);
if (NewSize.X != CONSOLE_WINDOW_SIZE_X(ScreenInfo) ||
NewSize.Y != CONSOLE_WINDOW_SIZE_Y(ScreenInfo)) {
wp.length = sizeof(wp);
GetWindowPlacement(Console->hWnd, &wp);
wp.rcNormalPosition.right += (NewSize.X - CONSOLE_WINDOW_SIZE_X(ScreenInfo)) *
SCR_FONTSIZE(ScreenInfo).X;
wp.rcNormalPosition.bottom += (NewSize.Y - CONSOLE_WINDOW_SIZE_Y(ScreenInfo)) *
SCR_FONTSIZE(ScreenInfo).Y;
SetWindowPlacement(Console->hWnd, &wp);
}
#ifdef i386
if (FullScreenInitialized) {
if (pStateInfo->FullScreen == FALSE) {
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
ConvertToWindowed(Console);
ASSERT(!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE));
Console->FullScreenFlags = 0;
ChangeDispSettings(Console, Console->hWnd, 0);
}
} else {
if (Console->FullScreenFlags == 0) {
ConvertToFullScreen(Console);
Console->FullScreenFlags |= CONSOLE_FULLSCREEN;
ChangeDispSettings(Console, Console->hWnd, CDS_FULLSCREEN);
}
}
}
#endif
if (pStateInfo->QuickEdit) {
Console->Flags |= CONSOLE_QUICK_EDIT_MODE;
} else {
Console->Flags &= ~CONSOLE_QUICK_EDIT_MODE;
}
if (pStateInfo->AutoPosition) {
Console->Flags |= CONSOLE_AUTO_POSITION;
} else {
Console->Flags &= ~CONSOLE_AUTO_POSITION;
SetWindowPos(Console->hWnd, NULL,
pStateInfo->WindowPosX,
pStateInfo->WindowPosY,
0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
if (Console->InsertMode != pStateInfo->InsertMode) {
SetCursorMode(ScreenInfo, FALSE);
Console->InsertMode = pStateInfo->InsertMode;
}
RtlCopyMemory(Console->ColorTable,
pStateInfo->ColorTable,
sizeof(Console->ColorTable));
SetScreenColors(ScreenInfo,
pStateInfo->ScreenAttributes,
pStateInfo->PopupAttributes,
TRUE);
Console->CommandHistorySize = pStateInfo->HistoryBufferSize;
Console->MaxCommandHistories = pStateInfo->NumberOfHistoryBuffers;
if (pStateInfo->HistoryNoDup) {
Console->Flags |= CONSOLE_HISTORY_NODUP;
} else {
Console->Flags &= ~CONSOLE_HISTORY_NODUP;
}
NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo);
NtClose(hSection);
return;
}