mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[KERNEL32][CONSRV]: Implement a basic RegisterConsoleVDM (see revision 62371 for more details).
svn path=/branches/condrv_restructure/; revision=63849
This commit is contained in:
parent
636d4cf0ce
commit
cc85bc57af
7 changed files with 354 additions and 23 deletions
|
@ -1640,26 +1640,101 @@ GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
|
|||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented (undocumented)
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
RegisterConsoleVDM (
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1,
|
||||
DWORD Unknown2,
|
||||
DWORD Unknown3,
|
||||
DWORD Unknown4,
|
||||
DWORD Unknown5,
|
||||
DWORD Unknown6,
|
||||
DWORD Unknown7,
|
||||
DWORD Unknown8,
|
||||
DWORD Unknown9,
|
||||
DWORD Unknown10
|
||||
)
|
||||
RegisterConsoleVDM(IN DWORD dwRegisterFlags,
|
||||
IN HANDLE hStartHardwareEvent,
|
||||
IN HANDLE hEndHardwareEvent,
|
||||
IN HANDLE hErrorHardwareEvent,
|
||||
IN DWORD dwUnusedVar,
|
||||
OUT LPDWORD lpVideoStateLength,
|
||||
OUT PVOID* lpVideoState, // PVIDEO_HARDWARE_STATE_HEADER*
|
||||
IN PVOID lpUnusedBuffer,
|
||||
IN DWORD dwUnusedBufferLength,
|
||||
IN COORD dwVDMBufferSize,
|
||||
OUT PVOID* lpVDMBuffer)
|
||||
{
|
||||
STUB;
|
||||
return FALSE;
|
||||
BOOL Success;
|
||||
CONSOLE_API_MESSAGE ApiMessage;
|
||||
PCONSOLE_REGISTERVDM RegisterVDMRequest = &ApiMessage.Data.RegisterVDMRequest;
|
||||
PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
|
||||
|
||||
/* Set up the data to send to the Console Server */
|
||||
RegisterVDMRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
|
||||
RegisterVDMRequest->RegisterFlags = dwRegisterFlags;
|
||||
|
||||
if (dwRegisterFlags != 0)
|
||||
{
|
||||
RegisterVDMRequest->StartHardwareEvent = hStartHardwareEvent;
|
||||
RegisterVDMRequest->EndHardwareEvent = hEndHardwareEvent;
|
||||
RegisterVDMRequest->ErrorHardwareEvent = hErrorHardwareEvent;
|
||||
|
||||
RegisterVDMRequest->VDMBufferSize = dwVDMBufferSize;
|
||||
|
||||
#if 0
|
||||
RegisterVDMRequest->UnusedBufferLength = dwUnusedBufferLength;
|
||||
|
||||
/* Allocate a Capture Buffer */
|
||||
CaptureBuffer = CsrAllocateCaptureBuffer(1, dwUnusedBufferLength);
|
||||
if (CaptureBuffer == NULL)
|
||||
{
|
||||
DPRINT1("CsrAllocateCaptureBuffer failed!\n");
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Capture the buffer to write */
|
||||
CsrCaptureMessageBuffer(CaptureBuffer,
|
||||
(PVOID)lpUnusedBuffer,
|
||||
dwUnusedBufferLength,
|
||||
(PVOID*)&RegisterVDMRequest->UnusedBuffer);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// CaptureBuffer = NULL;
|
||||
}
|
||||
|
||||
/* Call the server */
|
||||
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
|
||||
CaptureBuffer,
|
||||
CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepRegisterVDM),
|
||||
sizeof(*RegisterVDMRequest));
|
||||
|
||||
/* Check for success */
|
||||
Success = NT_SUCCESS(ApiMessage.Status);
|
||||
|
||||
/* Release the capture buffer if needed */
|
||||
if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
|
||||
|
||||
/* Retrieve the results */
|
||||
if (Success)
|
||||
{
|
||||
if (dwRegisterFlags != 0)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
*lpVideoStateLength = RegisterVDMRequest->VideoStateLength;
|
||||
*lpVideoState = RegisterVDMRequest->VideoState;
|
||||
*lpVDMBuffer = RegisterVDMRequest->VDMBuffer;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_ACCESS);
|
||||
Success = FALSE;
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseSetLastNTError(ApiMessage.Status);
|
||||
}
|
||||
|
||||
/* Return success status */
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1756,9 +1831,8 @@ VDMOperationStarted(IN ULONG Unknown0)
|
|||
{
|
||||
DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
|
||||
|
||||
return
|
||||
BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler,
|
||||
NULL,
|
||||
0,
|
||||
Unknown0);
|
||||
return BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler,
|
||||
NULL,
|
||||
0,
|
||||
Unknown0);
|
||||
}
|
||||
|
|
|
@ -618,6 +618,12 @@ BOOL WINAPI CloseConsoleHandle(_In_ HANDLE);
|
|||
// BOOL WINAPI SetStdHandle(_In_ DWORD, _In_ HANDLE);
|
||||
/* Undocumented */
|
||||
BOOL WINAPI VerifyConsoleIoHandle(_In_ HANDLE);
|
||||
/* Undocumented */
|
||||
BOOL
|
||||
WINAPI
|
||||
RegisterConsoleVDM(_In_ DWORD, _In_ HANDLE, _In_ HANDLE, _In_ HANDLE, _In_ DWORD,
|
||||
_Out_ LPDWORD, _Out_ PVOID*, _In_ PVOID, _In_ DWORD, _In_ COORD,
|
||||
_Out_ PVOID*);
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
|
|
|
@ -806,6 +806,28 @@ typedef struct
|
|||
BOOL Ansi;
|
||||
} CONSOLE_GETKBDLAYOUTNAME, *PCONSOLE_GETKBDLAYOUTNAME;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE ConsoleHandle;
|
||||
ULONG RegisterFlags;
|
||||
HANDLE StartHardwareEvent;
|
||||
HANDLE EndHardwareEvent;
|
||||
HANDLE ErrorHardwareEvent;
|
||||
|
||||
/* Unused member */
|
||||
ULONG UnusedVar;
|
||||
|
||||
ULONG VideoStateLength;
|
||||
PVOID VideoState; // PVIDEO_HARDWARE_STATE_HEADER
|
||||
|
||||
/* Unused members */
|
||||
PVOID UnusedBuffer;
|
||||
ULONG UnusedBufferLength;
|
||||
|
||||
COORD VDMBufferSize;
|
||||
PVOID VDMBuffer;
|
||||
} CONSOLE_REGISTERVDM, *PCONSOLE_REGISTERVDM;
|
||||
|
||||
typedef struct _CONSOLE_API_MESSAGE
|
||||
{
|
||||
PORT_MESSAGE Header;
|
||||
|
@ -903,6 +925,9 @@ typedef struct _CONSOLE_API_MESSAGE
|
|||
CONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest;
|
||||
CONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest;
|
||||
CONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest;
|
||||
|
||||
/* Virtual DOS Machine */
|
||||
CONSOLE_REGISTERVDM RegisterVDMRequest;
|
||||
} Data;
|
||||
} CONSOLE_API_MESSAGE, *PCONSOLE_API_MESSAGE;
|
||||
|
||||
|
|
|
@ -207,6 +207,13 @@ ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
|
|||
|
||||
/* PUBLIC DRIVER APIS *********************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN PCHAR_CELL CharInfo/*Buffer*/,
|
||||
IN COORD CharInfoSize,
|
||||
IN OUT PSMALL_RECT WriteRegion,
|
||||
IN BOOLEAN DrawRegion);
|
||||
NTSTATUS NTAPI
|
||||
ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
|
||||
IN PCONSOLE_SCREEN_BUFFER Buffer,
|
||||
|
@ -218,6 +225,19 @@ ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
|
|||
/* Validity check */
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
|
||||
/* In text-mode only, draw the VDM buffer if present */
|
||||
if (GetType(Buffer) == TEXTMODE_BUFFER)
|
||||
{
|
||||
PTEXTMODE_SCREEN_BUFFER TextBuffer = (PTEXTMODE_SCREEN_BUFFER)Buffer;
|
||||
|
||||
/*Status =*/ ConDrvWriteConsoleOutputVDM(Buffer->Header.Console,
|
||||
TextBuffer,
|
||||
Console->VDMBuffer,
|
||||
Console->VDMBufferSize,
|
||||
Region,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
/* If the output buffer is the current one, redraw the correct portion of the screen */
|
||||
if (Buffer == Console->ActiveBuffer) TermDrawRegion(Console, Region);
|
||||
|
||||
|
|
|
@ -722,6 +722,68 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This function is strongly inspired by ConDrvWriteConsoleOutput...
|
||||
*/
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN PCHAR_CELL CharInfo/*Buffer*/,
|
||||
IN COORD CharInfoSize,
|
||||
IN OUT PSMALL_RECT WriteRegion,
|
||||
IN BOOLEAN DrawRegion)
|
||||
{
|
||||
SHORT X, Y;
|
||||
SMALL_RECT ScreenBuffer;
|
||||
PCHAR_CELL CurCharInfo;
|
||||
SMALL_RECT CapturedWriteRegion;
|
||||
PCHAR_INFO Ptr;
|
||||
|
||||
if (Console == NULL || Buffer == NULL || CharInfo == NULL || WriteRegion == NULL)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
|
||||
CapturedWriteRegion = *WriteRegion;
|
||||
|
||||
/* Make sure WriteRegion is inside the screen buffer */
|
||||
ConioInitRect(&ScreenBuffer, 0, 0,
|
||||
Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1);
|
||||
if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion))
|
||||
{
|
||||
/*
|
||||
* It is okay to have a WriteRegion completely outside
|
||||
* the screen buffer. No data is written then.
|
||||
*/
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// CurCharInfo = CharInfo;
|
||||
|
||||
for (Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; ++Y)
|
||||
{
|
||||
/**/CurCharInfo = CharInfo + Y * CharInfoSize.X + CapturedWriteRegion.Left;/**/
|
||||
|
||||
Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y);
|
||||
for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; ++X)
|
||||
{
|
||||
ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char);
|
||||
Ptr->Attributes = CurCharInfo->Attributes;
|
||||
++Ptr;
|
||||
++CurCharInfo;
|
||||
}
|
||||
}
|
||||
|
||||
if (DrawRegion) TermDrawRegion(Console, &CapturedWriteRegion);
|
||||
|
||||
*WriteRegion = CapturedWriteRegion;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsole(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
||||
|
|
|
@ -19,6 +19,15 @@
|
|||
#define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
|
||||
BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
|
||||
|
||||
/* VGA character cell */
|
||||
typedef struct _CHAR_CELL
|
||||
{
|
||||
CHAR Char;
|
||||
BYTE Attributes;
|
||||
} CHAR_CELL, *PCHAR_CELL;
|
||||
C_ASSERT(sizeof(CHAR_CELL) == 2);
|
||||
|
||||
|
||||
/* Object type magic numbers */
|
||||
typedef enum _CONSOLE_IO_OBJECT_TYPE
|
||||
{
|
||||
|
@ -300,6 +309,17 @@ typedef struct _CONSOLE
|
|||
PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
|
||||
UINT OutputCodePage;
|
||||
|
||||
/**** Per-console Virtual DOS Machine Text-mode Buffer ****/
|
||||
COORD VDMBufferSize; /* Real size of the VDM buffer, in units of ??? */
|
||||
HANDLE VDMBufferSection; /* Handle to the memory shared section for the VDM buffer */
|
||||
PVOID VDMBuffer; /* Our VDM buffer */
|
||||
PVOID ClientVDMBuffer; /* A copy of the client view of our VDM buffer */
|
||||
HANDLE VDMClientProcess; /* Handle to the client process who opened the buffer, to unmap the view */
|
||||
|
||||
HANDLE StartHardwareEvent;
|
||||
HANDLE EndHardwareEvent;
|
||||
HANDLE ErrorHardwareEvent;
|
||||
|
||||
/****************************** Other properties ******************************/
|
||||
UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */
|
||||
UNICODE_STRING Title; /* Title of console. Always NULL-terminated */
|
||||
|
|
|
@ -21,8 +21,132 @@
|
|||
|
||||
CSR_API(SrvRegisterConsoleVDM)
|
||||
{
|
||||
DPRINT1("%s not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_REGISTERVDM RegisterVDMRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.RegisterVDMRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
DPRINT1("SrvRegisterConsoleVDM(%d)\n", RegisterVDMRequest->RegisterFlags);
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
&Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (RegisterVDMRequest->RegisterFlags != 0)
|
||||
{
|
||||
LARGE_INTEGER SectionSize;
|
||||
ULONG Size, ViewSize = 0;
|
||||
HANDLE ProcessHandle;
|
||||
|
||||
/*
|
||||
* Remember the handle to the process so that we can close or unmap
|
||||
* correctly the allocated resources when the client releases the
|
||||
* screen buffer.
|
||||
*/
|
||||
ProcessHandle = CsrGetClientThread()->Process->ProcessHandle;
|
||||
Console->VDMClientProcess = ProcessHandle;
|
||||
|
||||
Console->VDMBufferSize = RegisterVDMRequest->VDMBufferSize;
|
||||
|
||||
Size = Console->VDMBufferSize.X * Console->VDMBufferSize.Y
|
||||
* sizeof(CHAR_CELL);
|
||||
|
||||
/*
|
||||
* Create a memory section for the VDM buffer, to share with the client.
|
||||
*/
|
||||
SectionSize.QuadPart = Size;
|
||||
Status = NtCreateSection(&Console->VDMBufferSection,
|
||||
SECTION_ALL_ACCESS,
|
||||
NULL,
|
||||
&SectionSize,
|
||||
PAGE_READWRITE,
|
||||
SEC_COMMIT,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a view for our needs.
|
||||
*/
|
||||
ViewSize = 0;
|
||||
Console->VDMBuffer = NULL;
|
||||
Status = NtMapViewOfSection(Console->VDMBufferSection,
|
||||
NtCurrentProcess(),
|
||||
(PVOID*)&Console->VDMBuffer,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&ViewSize,
|
||||
ViewUnmap,
|
||||
0,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
|
||||
NtClose(Console->VDMBufferSection);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a view for the client. We must keep a trace of it so that
|
||||
* we can unmap it when the client releases the VDM buffer.
|
||||
*/
|
||||
ViewSize = 0;
|
||||
Console->ClientVDMBuffer = NULL;
|
||||
Status = NtMapViewOfSection(Console->VDMBufferSection,
|
||||
ProcessHandle,
|
||||
(PVOID*)&Console->ClientVDMBuffer,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&ViewSize,
|
||||
ViewUnmap,
|
||||
0,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), Console->VDMBuffer);
|
||||
NtClose(Console->VDMBufferSection);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
// TODO: Duplicate the event handles.
|
||||
|
||||
RegisterVDMRequest->VDMBuffer = Console->ClientVDMBuffer;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RegisterFlags == 0 means we are unregistering the VDM */
|
||||
|
||||
// TODO: Close the duplicated handles.
|
||||
|
||||
if (Console->VDMBuffer)
|
||||
{
|
||||
/*
|
||||
* Uninitialize the graphics screen buffer
|
||||
* in the reverse way we initialized it.
|
||||
*/
|
||||
NtUnmapViewOfSection(Console->VDMClientProcess, Console->ClientVDMBuffer);
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), Console->VDMBuffer);
|
||||
NtClose(Console->VDMBufferSection);
|
||||
}
|
||||
Console->VDMBuffer = Console->ClientVDMBuffer = NULL;
|
||||
|
||||
Console->VDMBufferSize.X = Console->VDMBufferSize.Y = 0;
|
||||
}
|
||||
|
||||
Quit:
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvVDMConsoleOperation)
|
||||
|
|
Loading…
Reference in a new issue