mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
[CONSRV]
Create a new consrv_new to study its interfacing with the console driver (condrv). svn path=/trunk/; revision=59470
This commit is contained in:
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/alias.c
|
||||
* PURPOSE: Alias support functions
|
||||
* PROGRAMMERS: Christoph Wittich
|
||||
* Johannes Anderwald
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "console.h"
|
||||
#include "include/conio.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* TYPES **********************************************************************/
|
||||
|
||||
typedef struct _ALIAS_ENTRY
|
||||
{
|
||||
LPCWSTR lpSource;
|
||||
LPCWSTR lpTarget;
|
||||
struct _ALIAS_ENTRY* Next;
|
||||
} ALIAS_ENTRY, *PALIAS_ENTRY;
|
||||
|
||||
typedef struct _ALIAS_HEADER
|
||||
{
|
||||
LPCWSTR lpExeName;
|
||||
PALIAS_ENTRY Data;
|
||||
struct _ALIAS_HEADER* Next;
|
||||
} ALIAS_HEADER, *PALIAS_HEADER;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static
|
||||
PALIAS_HEADER
|
||||
IntFindAliasHeader(PALIAS_HEADER RootHeader, LPCWSTR lpExeName)
|
||||
{
|
||||
while (RootHeader)
|
||||
{
|
||||
INT diff = _wcsicmp(RootHeader->lpExeName, lpExeName);
|
||||
if (!diff) return RootHeader;
|
||||
if (diff > 0) break;
|
||||
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PALIAS_HEADER
|
||||
IntCreateAliasHeader(LPCWSTR lpExeName)
|
||||
{
|
||||
PALIAS_HEADER Entry;
|
||||
UINT dwLength = wcslen(lpExeName) + 1;
|
||||
|
||||
Entry = ConsoleAllocHeap(0, sizeof(ALIAS_HEADER) + sizeof(WCHAR) * dwLength);
|
||||
if (!Entry) return Entry;
|
||||
|
||||
Entry->lpExeName = (LPCWSTR)(Entry + 1);
|
||||
wcscpy((PWCHAR)Entry->lpExeName, lpExeName);
|
||||
Entry->Data = NULL;
|
||||
Entry->Next = NULL;
|
||||
return Entry;
|
||||
}
|
||||
|
||||
VOID
|
||||
IntInsertAliasHeader(PALIAS_HEADER * RootHeader, PALIAS_HEADER NewHeader)
|
||||
{
|
||||
PALIAS_HEADER CurrentHeader;
|
||||
PALIAS_HEADER *LastLink = RootHeader;
|
||||
|
||||
while ((CurrentHeader = *LastLink) != NULL)
|
||||
{
|
||||
INT Diff = _wcsicmp(NewHeader->lpExeName, CurrentHeader->lpExeName);
|
||||
if (Diff < 0) break;
|
||||
|
||||
LastLink = &CurrentHeader->Next;
|
||||
}
|
||||
|
||||
*LastLink = NewHeader;
|
||||
NewHeader->Next = CurrentHeader;
|
||||
}
|
||||
|
||||
PALIAS_ENTRY
|
||||
IntGetAliasEntry(PALIAS_HEADER Header, LPCWSTR lpSrcName)
|
||||
{
|
||||
PALIAS_ENTRY RootHeader;
|
||||
|
||||
if (Header == NULL) return NULL;
|
||||
|
||||
RootHeader = Header->Data;
|
||||
while (RootHeader)
|
||||
{
|
||||
INT diff;
|
||||
DPRINT("IntGetAliasEntry->lpSource %S\n", RootHeader->lpSource);
|
||||
diff = _wcsicmp(RootHeader->lpSource, lpSrcName);
|
||||
if (!diff) return RootHeader;
|
||||
if (diff > 0) break;
|
||||
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
IntInsertAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY NewEntry)
|
||||
{
|
||||
PALIAS_ENTRY CurrentEntry;
|
||||
PALIAS_ENTRY *LastLink = &Header->Data;
|
||||
|
||||
while ((CurrentEntry = *LastLink) != NULL)
|
||||
{
|
||||
INT Diff = _wcsicmp(NewEntry->lpSource, CurrentEntry->lpSource);
|
||||
if (Diff < 0) break;
|
||||
|
||||
LastLink = &CurrentEntry->Next;
|
||||
}
|
||||
|
||||
*LastLink = NewEntry;
|
||||
NewEntry->Next = CurrentEntry;
|
||||
}
|
||||
|
||||
PALIAS_ENTRY
|
||||
IntCreateAliasEntry(LPCWSTR lpSource, LPCWSTR lpTarget)
|
||||
{
|
||||
UINT dwSource;
|
||||
UINT dwTarget;
|
||||
PALIAS_ENTRY Entry;
|
||||
|
||||
dwSource = wcslen(lpSource) + 1;
|
||||
dwTarget = wcslen(lpTarget) + 1;
|
||||
|
||||
Entry = ConsoleAllocHeap(0, sizeof(ALIAS_ENTRY) + sizeof(WCHAR) * (dwSource + dwTarget));
|
||||
if (!Entry) return Entry;
|
||||
|
||||
Entry->lpSource = (LPCWSTR)(Entry + 1);
|
||||
wcscpy((LPWSTR)Entry->lpSource, lpSource);
|
||||
Entry->lpTarget = Entry->lpSource + dwSource;
|
||||
wcscpy((LPWSTR)Entry->lpTarget, lpTarget);
|
||||
Entry->Next = NULL;
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
UINT
|
||||
IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader)
|
||||
{
|
||||
UINT length = 0;
|
||||
|
||||
while (RootHeader)
|
||||
{
|
||||
length += (wcslen(RootHeader->lpExeName) + 1) * sizeof(WCHAR);
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
if (length)
|
||||
length += sizeof(WCHAR); // last entry entry is terminated with 2 zero bytes
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
UINT
|
||||
IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader, LPWSTR TargetBuffer, UINT TargetBufferSize)
|
||||
{
|
||||
UINT Offset = 0;
|
||||
UINT Length;
|
||||
|
||||
TargetBufferSize /= sizeof(WCHAR);
|
||||
while (RootHeader)
|
||||
{
|
||||
Length = wcslen(RootHeader->lpExeName) + 1;
|
||||
if (TargetBufferSize > Offset + Length)
|
||||
{
|
||||
wcscpy(&TargetBuffer[Offset], RootHeader->lpExeName);
|
||||
Offset += Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
Length = min(Offset+1, TargetBufferSize);
|
||||
TargetBuffer[Length] = L'\0';
|
||||
return Length * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
UINT
|
||||
IntGetAllConsoleAliasesLength(PALIAS_HEADER Header)
|
||||
{
|
||||
UINT Length = 0;
|
||||
PALIAS_ENTRY CurEntry = Header->Data;
|
||||
|
||||
while (CurEntry)
|
||||
{
|
||||
Length += wcslen(CurEntry->lpSource);
|
||||
Length += wcslen(CurEntry->lpTarget);
|
||||
Length += 2; // zero byte and '='
|
||||
CurEntry = CurEntry->Next;
|
||||
}
|
||||
|
||||
if (Length)
|
||||
{
|
||||
return (Length+1) * sizeof(WCHAR);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT
|
||||
IntGetAllConsoleAliases(PALIAS_HEADER Header, LPWSTR TargetBuffer, UINT TargetBufferLength)
|
||||
{
|
||||
PALIAS_ENTRY CurEntry = Header->Data;
|
||||
UINT Offset = 0;
|
||||
UINT SrcLength, TargetLength;
|
||||
|
||||
TargetBufferLength /= sizeof(WCHAR);
|
||||
while (CurEntry)
|
||||
{
|
||||
SrcLength = wcslen(CurEntry->lpSource) + 1;
|
||||
TargetLength = wcslen(CurEntry->lpTarget) + 1;
|
||||
if (Offset + TargetLength + SrcLength >= TargetBufferLength)
|
||||
break;
|
||||
|
||||
wcscpy(&TargetBuffer[Offset], CurEntry->lpSource);
|
||||
Offset += SrcLength;
|
||||
TargetBuffer[Offset] = L'=';
|
||||
wcscpy(&TargetBuffer[Offset], CurEntry->lpTarget);
|
||||
Offset += TargetLength;
|
||||
|
||||
CurEntry = CurEntry->Next;
|
||||
}
|
||||
TargetBuffer[Offset] = L'\0';
|
||||
return Offset * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
VOID
|
||||
IntDeleteAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY Entry)
|
||||
{
|
||||
PALIAS_ENTRY *LastLink = &Header->Data;
|
||||
PALIAS_ENTRY CurEntry;
|
||||
|
||||
while ((CurEntry = *LastLink) != NULL)
|
||||
{
|
||||
if (CurEntry == Entry)
|
||||
{
|
||||
*LastLink = Entry->Next;
|
||||
ConsoleFreeHeap(Entry);
|
||||
return;
|
||||
}
|
||||
LastLink = &CurEntry->Next;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
IntDeleteAllAliases(PCONSOLE Console)
|
||||
{
|
||||
PALIAS_HEADER Header, NextHeader;
|
||||
PALIAS_ENTRY Entry, NextEntry;
|
||||
|
||||
for (Header = Console->Aliases; Header; Header = NextHeader)
|
||||
{
|
||||
NextHeader = Header->Next;
|
||||
for (Entry = Header->Data; Entry; Entry = NextEntry)
|
||||
{
|
||||
NextEntry = Entry->Next;
|
||||
ConsoleFreeHeap(Entry);
|
||||
}
|
||||
ConsoleFreeHeap(Header);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
CSR_API(SrvAddConsoleAlias)
|
||||
{
|
||||
PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAliasRequest;
|
||||
PCONSOLE Console;
|
||||
PALIAS_HEADER Header;
|
||||
PALIAS_ENTRY Entry;
|
||||
LPWSTR lpSource, lpTarget, lpExeName;
|
||||
|
||||
DPRINT("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage);
|
||||
|
||||
if ( !CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ConsoleAliasRequest->Source,
|
||||
ConsoleAliasRequest->SourceLength,
|
||||
sizeof(BYTE)) ||
|
||||
!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ConsoleAliasRequest->Target,
|
||||
ConsoleAliasRequest->TargetLength,
|
||||
sizeof(BYTE)) ||
|
||||
!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ConsoleAliasRequest->Exe,
|
||||
ConsoleAliasRequest->ExeLength,
|
||||
sizeof(BYTE)) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
lpSource = ConsoleAliasRequest->Source;
|
||||
lpTarget = (ConsoleAliasRequest->TargetLength != 0 ? ConsoleAliasRequest->Target : NULL);
|
||||
lpExeName = ConsoleAliasRequest->Exe;
|
||||
|
||||
DPRINT("SrvAddConsoleAlias lpSource %p lpExeName %p lpTarget %p\n", lpSource, lpExeName, lpTarget);
|
||||
|
||||
if (lpExeName == NULL || lpSource == NULL)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(ApiMessage->Status))
|
||||
{
|
||||
return ApiMessage->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
|
||||
if (!Header && lpTarget != NULL)
|
||||
{
|
||||
Header = IntCreateAliasHeader(lpExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
IntInsertAliasHeader(&Console->Aliases, Header);
|
||||
}
|
||||
|
||||
if (lpTarget == NULL) // Delete the entry
|
||||
{
|
||||
Entry = IntGetAliasEntry(Header, lpSource);
|
||||
if (Entry)
|
||||
{
|
||||
IntDeleteAliasEntry(Header, Entry);
|
||||
ApiMessage->Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ApiMessage->Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return ApiMessage->Status;
|
||||
}
|
||||
|
||||
Entry = IntCreateAliasEntry(lpSource, lpTarget);
|
||||
|
||||
if (!Entry)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
IntInsertAliasEntry(Header, Entry);
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleAlias)
|
||||
{
|
||||
PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAliasRequest;
|
||||
PCONSOLE Console;
|
||||
PALIAS_HEADER Header;
|
||||
PALIAS_ENTRY Entry;
|
||||
UINT Length;
|
||||
LPWSTR lpSource, lpTarget, lpExeName;
|
||||
|
||||
DPRINT("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage);
|
||||
|
||||
if ( !CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ConsoleAliasRequest->Source,
|
||||
ConsoleAliasRequest->SourceLength,
|
||||
sizeof(BYTE)) ||
|
||||
!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ConsoleAliasRequest->Target,
|
||||
ConsoleAliasRequest->TargetLength,
|
||||
sizeof(BYTE)) ||
|
||||
!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ConsoleAliasRequest->Exe,
|
||||
ConsoleAliasRequest->ExeLength,
|
||||
sizeof(BYTE)) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
lpSource = ConsoleAliasRequest->Source;
|
||||
lpTarget = ConsoleAliasRequest->Target;
|
||||
lpExeName = ConsoleAliasRequest->Exe;
|
||||
|
||||
DPRINT("SrvGetConsoleAlias lpExeName %p lpSource %p TargetBuffer %p TargetLength %u\n",
|
||||
lpExeName, lpSource, lpTarget, ConsoleAliasRequest->TargetLength);
|
||||
|
||||
if (ConsoleAliasRequest->ExeLength == 0 || lpTarget == NULL ||
|
||||
ConsoleAliasRequest->TargetLength == 0 || ConsoleAliasRequest->SourceLength == 0)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(ApiMessage->Status))
|
||||
{
|
||||
return ApiMessage->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Entry = IntGetAliasEntry(Header, lpSource);
|
||||
if (!Entry)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Length = (wcslen(Entry->lpTarget) + 1) * sizeof(WCHAR);
|
||||
if (Length > ConsoleAliasRequest->TargetLength)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
wcscpy(lpTarget, Entry->lpTarget);
|
||||
ConsoleAliasRequest->TargetLength = Length;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleAliases)
|
||||
{
|
||||
PCONSOLE_GETALLALIASES GetAllAliasesRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllAliasesRequest;
|
||||
PCONSOLE Console;
|
||||
ULONG BytesWritten;
|
||||
PALIAS_HEADER Header;
|
||||
|
||||
if ( !CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&GetAllAliasesRequest->ExeName,
|
||||
GetAllAliasesRequest->ExeLength,
|
||||
sizeof(BYTE)) ||
|
||||
!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&GetAllAliasesRequest->AliasesBuffer,
|
||||
GetAllAliasesRequest->AliasesBufferLength,
|
||||
sizeof(BYTE)) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (GetAllAliasesRequest->ExeName == NULL)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(ApiMessage->Status))
|
||||
{
|
||||
return ApiMessage->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, GetAllAliasesRequest->ExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (IntGetAllConsoleAliasesLength(Header) > GetAllAliasesRequest->AliasesBufferLength)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
BytesWritten = IntGetAllConsoleAliases(Header,
|
||||
GetAllAliasesRequest->AliasesBuffer,
|
||||
GetAllAliasesRequest->AliasesBufferLength);
|
||||
|
||||
GetAllAliasesRequest->AliasesBufferLength = BytesWritten;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleAliasesLength)
|
||||
{
|
||||
PCONSOLE_GETALLALIASESLENGTH GetAllAliasesLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllAliasesLengthRequest;
|
||||
PCONSOLE Console;
|
||||
PALIAS_HEADER Header;
|
||||
UINT Length;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&GetAllAliasesLengthRequest->ExeName,
|
||||
GetAllAliasesLengthRequest->ExeLength,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (GetAllAliasesLengthRequest->ExeName == NULL)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(ApiMessage->Status))
|
||||
{
|
||||
return ApiMessage->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, GetAllAliasesLengthRequest->ExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Length = IntGetAllConsoleAliasesLength(Header);
|
||||
GetAllAliasesLengthRequest->Length = Length;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleAliasExes)
|
||||
{
|
||||
PCONSOLE_GETALIASESEXES GetAliasesExesRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAliasesExesRequest;
|
||||
PCONSOLE Console;
|
||||
UINT BytesWritten;
|
||||
UINT ExesLength;
|
||||
|
||||
DPRINT("SrvGetConsoleAliasExes entered\n");
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&GetAliasesExesRequest->ExeNames,
|
||||
GetAliasesExesRequest->Length,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(ApiMessage->Status))
|
||||
{
|
||||
return ApiMessage->Status;
|
||||
}
|
||||
|
||||
ExesLength = IntGetConsoleAliasesExesLength(Console->Aliases);
|
||||
|
||||
if (ExesLength > GetAliasesExesRequest->Length)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
if (GetAliasesExesRequest->ExeNames == NULL)
|
||||
{
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
BytesWritten = IntGetConsoleAliasesExes(Console->Aliases,
|
||||
GetAliasesExesRequest->ExeNames,
|
||||
GetAliasesExesRequest->Length);
|
||||
|
||||
GetAliasesExesRequest->Length = BytesWritten;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleAliasExesLength)
|
||||
{
|
||||
PCONSOLE_GETALIASESEXESLENGTH GetAliasesExesLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAliasesExesLengthRequest;
|
||||
PCONSOLE Console;
|
||||
DPRINT("SrvGetConsoleAliasExesLength entered\n");
|
||||
|
||||
ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (NT_SUCCESS(ApiMessage->Status))
|
||||
{
|
||||
GetAliasesExesLengthRequest->Length = IntGetConsoleAliasesExesLength(Console->Aliases);
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
return ApiMessage->Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/alias.h
|
||||
* PURPOSE: Alias support functions
|
||||
* PROGRAMMERS: Christoph Wittich
|
||||
* Johannes Anderwald
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
VOID IntDeleteAllAliases(PCONSOLE Console);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/api.h
|
||||
* PURPOSE: Public server APIs definitions
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* alias.c */
|
||||
CSR_API(SrvAddConsoleAlias);
|
||||
CSR_API(SrvGetConsoleAlias);
|
||||
CSR_API(SrvGetConsoleAliases);
|
||||
CSR_API(SrvGetConsoleAliasesLength);
|
||||
CSR_API(SrvGetConsoleAliasExes);
|
||||
CSR_API(SrvGetConsoleAliasExesLength);
|
||||
|
||||
/* coninput.c */
|
||||
CSR_API(SrvReadConsole);
|
||||
CSR_API(SrvGetConsoleInput);
|
||||
CSR_API(SrvWriteConsoleInput);
|
||||
CSR_API(SrvFlushConsoleInputBuffer);
|
||||
CSR_API(SrvGetConsoleNumberOfInputEvents);
|
||||
|
||||
/* conoutput.c */
|
||||
CSR_API(SrvInvalidateBitMapRect);
|
||||
CSR_API(SrvReadConsoleOutput);
|
||||
CSR_API(SrvWriteConsole);
|
||||
CSR_API(SrvWriteConsoleOutput);
|
||||
CSR_API(SrvReadConsoleOutputString);
|
||||
CSR_API(SrvWriteConsoleOutputString);
|
||||
CSR_API(SrvFillConsoleOutput);
|
||||
CSR_API(SrvGetConsoleCursorInfo);
|
||||
CSR_API(SrvSetConsoleCursorInfo);
|
||||
CSR_API(SrvSetConsoleCursorPosition);
|
||||
CSR_API(SrvSetConsoleTextAttribute);
|
||||
CSR_API(SrvCreateConsoleScreenBuffer);
|
||||
CSR_API(SrvGetConsoleScreenBufferInfo);
|
||||
CSR_API(SrvSetConsoleActiveScreenBuffer);
|
||||
CSR_API(SrvScrollConsoleScreenBuffer);
|
||||
CSR_API(SrvSetConsoleScreenBufferSize);
|
||||
|
||||
/* console.c */
|
||||
CSR_API(SrvAllocConsole);
|
||||
CSR_API(SrvAttachConsole);
|
||||
CSR_API(SrvFreeConsole);
|
||||
CSR_API(SrvGetConsoleMode);
|
||||
CSR_API(SrvSetConsoleMode);
|
||||
CSR_API(SrvGetConsoleTitle);
|
||||
CSR_API(SrvSetConsoleTitle);
|
||||
CSR_API(SrvGetConsoleHardwareState);
|
||||
CSR_API(SrvSetConsoleHardwareState);
|
||||
CSR_API(SrvGetConsoleDisplayMode);
|
||||
CSR_API(SrvSetConsoleDisplayMode);
|
||||
CSR_API(SrvGetLargestConsoleWindowSize);
|
||||
CSR_API(SrvShowConsoleCursor);
|
||||
CSR_API(SrvSetConsoleCursor);
|
||||
CSR_API(SrvConsoleMenuControl);
|
||||
CSR_API(SrvSetConsoleMenuClose);
|
||||
CSR_API(SrvSetConsoleWindowInfo);
|
||||
CSR_API(SrvGetConsoleWindow);
|
||||
CSR_API(SrvSetConsoleIcon);
|
||||
CSR_API(SrvGetConsoleCP);
|
||||
CSR_API(SrvSetConsoleCP);
|
||||
CSR_API(SrvGetConsoleProcessList);
|
||||
CSR_API(SrvGenerateConsoleCtrlEvent);
|
||||
CSR_API(SrvGetConsoleSelectionInfo);
|
||||
|
||||
/* handle.c */
|
||||
CSR_API(SrvOpenConsole);
|
||||
CSR_API(SrvCloseHandle);
|
||||
CSR_API(SrvVerifyConsoleIoHandle);
|
||||
CSR_API(SrvDuplicateHandle);
|
||||
|
||||
/* lineinput.c */
|
||||
CSR_API(SrvGetConsoleCommandHistory);
|
||||
CSR_API(SrvGetConsoleCommandHistoryLength);
|
||||
CSR_API(SrvExpungeConsoleCommandHistory);
|
||||
CSR_API(SrvSetConsoleNumberOfCommands);
|
||||
CSR_API(SrvGetConsoleHistory);
|
||||
CSR_API(SrvSetConsoleHistory);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Driver DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/condrv/coninput.c
|
||||
* PURPOSE: Console Input functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "handle.h"
|
||||
#include "lineinput.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
#define ConSrvGetInputBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
|
||||
(Access), (LockConsole), INPUT_BUFFER)
|
||||
#define ConSrvGetInputBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
|
||||
(Access), (LockConsole), INPUT_BUFFER)
|
||||
#define ConSrvReleaseInputBuffer(Buff, IsConsoleLocked) \
|
||||
ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked))
|
||||
|
||||
|
||||
#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
|
||||
WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
|
||||
|
||||
#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
|
||||
MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
|
||||
|
||||
typedef struct ConsoleInput_t
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
INPUT_RECORD InputEvent;
|
||||
} ConsoleInput;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static VOID FASTCALL
|
||||
ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
|
||||
{
|
||||
if (InputEvent->EventType == KEY_EVENT)
|
||||
{
|
||||
WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
|
||||
InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console,
|
||||
&InputEvent->Event.KeyEvent.uChar.AsciiChar,
|
||||
&UnicodeChar);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
ConioProcessInputEvent(PCONSOLE Console,
|
||||
PINPUT_RECORD InputEvent)
|
||||
{
|
||||
ConsoleInput *ConInRec;
|
||||
|
||||
/* Check for pause or unpause */
|
||||
if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
|
||||
if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
|
||||
{
|
||||
DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
|
||||
if (Console->InputBuffer.Mode & ENABLE_LINE_INPUT &&
|
||||
(vk == VK_PAUSE || (vk == 'S' &&
|
||||
(cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &&
|
||||
!(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
|
||||
{
|
||||
ConioPause(Console, PAUSED_FROM_KEYBOARD);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN &&
|
||||
vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
|
||||
{
|
||||
ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add event to the queue */
|
||||
ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput));
|
||||
if (ConInRec == NULL) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
ConInRec->InputEvent = *InputEvent;
|
||||
InsertTailList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry);
|
||||
|
||||
SetEvent(Console->InputBuffer.ActiveEvent);
|
||||
CsrNotifyWait(&Console->InputBuffer.ReadWaitQueue,
|
||||
WaitAny,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!IsListEmpty(&Console->InputBuffer.ReadWaitQueue))
|
||||
{
|
||||
CsrDereferenceWait(&Console->InputBuffer.ReadWaitQueue);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
PurgeInputBuffer(PCONSOLE Console)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput* Event;
|
||||
|
||||
while (!IsListEmpty(&Console->InputBuffer.InputEvents))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&Console->InputBuffer.InputEvents);
|
||||
Event = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
ConsoleFreeHeap(Event);
|
||||
}
|
||||
|
||||
CloseHandle(Console->InputBuffer.ActiveEvent);
|
||||
}
|
||||
|
||||
VOID NTAPI
|
||||
ConDrvProcessKey(IN PCONSOLE Console,
|
||||
IN BOOLEAN Down,
|
||||
IN UINT VirtualKeyCode,
|
||||
IN UINT VirtualScanCode,
|
||||
IN WCHAR UnicodeChar,
|
||||
IN ULONG ShiftState,
|
||||
IN BYTE KeyStateCtrl)
|
||||
{
|
||||
INPUT_RECORD er;
|
||||
|
||||
/* process Ctrl-C and Ctrl-Break */
|
||||
if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
|
||||
Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') &&
|
||||
(ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyStateCtrl & 0x80) )
|
||||
{
|
||||
DPRINT1("Console_Api Ctrl-C\n");
|
||||
ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT);
|
||||
|
||||
if (Console->LineBuffer && !Console->LineComplete)
|
||||
{
|
||||
/* Line input is in progress; end it */
|
||||
Console->LinePos = Console->LineSize = 0;
|
||||
Console->LineComplete = TRUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 &&
|
||||
(VK_UP == VirtualKeyCode || VK_DOWN == VirtualKeyCode) )
|
||||
{
|
||||
if (!Down) return;
|
||||
|
||||
/* scroll up or down */
|
||||
if (VK_UP == VirtualKeyCode)
|
||||
{
|
||||
/* only scroll up if there is room to scroll up into */
|
||||
if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1)
|
||||
{
|
||||
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
|
||||
Console->ActiveBuffer->ScreenBufferSize.Y - 1) %
|
||||
Console->ActiveBuffer->ScreenBufferSize.Y;
|
||||
Console->ActiveBuffer->CursorPosition.Y++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* only scroll down if there is room to scroll down into */
|
||||
if (Console->ActiveBuffer->CursorPosition.Y != 0)
|
||||
{
|
||||
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
|
||||
Console->ActiveBuffer->ScreenBufferSize.Y;
|
||||
Console->ActiveBuffer->CursorPosition.Y--;
|
||||
}
|
||||
}
|
||||
|
||||
ConioDrawConsole(Console);
|
||||
return;
|
||||
}
|
||||
|
||||
er.EventType = KEY_EVENT;
|
||||
er.Event.KeyEvent.bKeyDown = Down;
|
||||
er.Event.KeyEvent.wRepeatCount = 1;
|
||||
er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
|
||||
er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
|
||||
er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
|
||||
er.Event.KeyEvent.dwControlKeyState = ShiftState;
|
||||
|
||||
ConioProcessInputEvent(Console, &er);
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC DRIVER APIS *********************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvReadConsole(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PVOID Buffer,
|
||||
IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
|
||||
IN ULONG NumCharsToRead,
|
||||
OUT PULONG NumCharsRead OPTIONAL)
|
||||
{
|
||||
// STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
|
||||
NTSTATUS Status = STATUS_PENDING;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput *Input;
|
||||
ULONG i = ReadControl->nInitialChars;
|
||||
|
||||
if (Console == NULL || InputBuffer == NULL || /* Buffer == NULL || */
|
||||
ReadControl == NULL || ReadControl->nLength != sizeof(CONSOLE_READCONSOLE_CONTROL))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Validity checks */
|
||||
ASSERT(Console == InputBuffer->Header.Console);
|
||||
ASSERT( (Buffer != NULL && NumCharsToRead >= 0) ||
|
||||
(Buffer == NULL && NumCharsToRead == 0) );
|
||||
|
||||
/* We haven't read anything (yet) */
|
||||
|
||||
if (InputBuffer->Mode & ENABLE_LINE_INPUT)
|
||||
{
|
||||
if (Console->LineBuffer == NULL)
|
||||
{
|
||||
/* Starting a new line */
|
||||
Console->LineMaxSize = (WORD)max(256, NumCharsToRead);
|
||||
|
||||
Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR));
|
||||
if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY;
|
||||
|
||||
Console->LineComplete = FALSE;
|
||||
Console->LineUpPressed = FALSE;
|
||||
Console->LineInsertToggle = 0;
|
||||
Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask;
|
||||
Console->LineSize = ReadControl->nInitialChars;
|
||||
Console->LinePos = Console->LineSize;
|
||||
|
||||
/*
|
||||
* Pre-filling the buffer is only allowed in the Unicode API,
|
||||
* so we don't need to worry about ANSI <-> Unicode conversion.
|
||||
*/
|
||||
memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
|
||||
if (Console->LineSize == Console->LineMaxSize)
|
||||
{
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a complete line yet, process the pending input */
|
||||
while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
/* Remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* Only pay attention to key down */
|
||||
if (Input->InputEvent.EventType == KEY_EVENT &&
|
||||
Input->InputEvent.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
|
||||
ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
|
||||
}
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
|
||||
/* Check if we have a complete line to read from */
|
||||
if (Console->LineComplete)
|
||||
{
|
||||
while (i < NumCharsToRead && Console->LinePos != Console->LineSize)
|
||||
{
|
||||
WCHAR Char = Console->LineBuffer[Console->LinePos++];
|
||||
|
||||
if (Unicode)
|
||||
{
|
||||
((PWCHAR)Buffer)[i] = Char;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (Console->LinePos == Console->LineSize)
|
||||
{
|
||||
/* Entire line has been read */
|
||||
ConsoleFreeHeap(Console->LineBuffer);
|
||||
Console->LineBuffer = NULL;
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Character input */
|
||||
while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
/* Remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* Only pay attention to valid ASCII chars, on key down */
|
||||
if (Input->InputEvent.EventType == KEY_EVENT &&
|
||||
Input->InputEvent.Event.KeyEvent.bKeyDown &&
|
||||
Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0')
|
||||
{
|
||||
WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
|
||||
|
||||
if (Unicode)
|
||||
{
|
||||
((PWCHAR)Buffer)[i] = Char;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char);
|
||||
}
|
||||
++i;
|
||||
|
||||
/* Did read something */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
}
|
||||
|
||||
if (NumCharsRead) *NumCharsRead = i;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleInput(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN WaitForMoreEvents,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToRead,
|
||||
OUT PULONG NumEventsRead OPTIONAL)
|
||||
{
|
||||
PLIST_ENTRY CurrentInput;
|
||||
ConsoleInput* Input;
|
||||
ULONG i = 0;
|
||||
|
||||
if (Console == NULL || InputBuffer == NULL /* || InputRecord == NULL */)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity checks */
|
||||
ASSERT(Console == InputBuffer->Header.Console);
|
||||
ASSERT( (InputRecord != NULL && NumEventsToRead >= 0) ||
|
||||
(InputRecord == NULL && NumEventsToRead == 0) );
|
||||
|
||||
// Do NOT do that !! Use the existing number of events already read, if any...
|
||||
// if (NumEventsRead) *NumEventsRead = 0;
|
||||
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
/*
|
||||
* No input is available. Wait for more input if requested,
|
||||
* otherwise, we don't wait, so we return success.
|
||||
*/
|
||||
return (WaitForMoreEvents ? STATUS_PENDING : STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* Only get input if there is any */
|
||||
CurrentInput = InputBuffer->InputEvents.Flink;
|
||||
if (NumEventsRead) i = *NumEventsRead; // We will read the remaining events...
|
||||
|
||||
while ((CurrentInput != &InputBuffer->InputEvents) && (i < NumEventsToRead))
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
|
||||
|
||||
*InputRecord = Input->InputEvent;
|
||||
|
||||
if (!Unicode)
|
||||
{
|
||||
ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
|
||||
}
|
||||
|
||||
++InputRecord;
|
||||
++i;
|
||||
CurrentInput = CurrentInput->Flink;
|
||||
|
||||
if (WaitForMoreEvents) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs.
|
||||
{
|
||||
RemoveEntryList(&Input->ListEntry);
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
}
|
||||
|
||||
if (NumEventsRead) *NumEventsRead = i;
|
||||
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
|
||||
/* We read all the inputs available, we return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsoleInput(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToWrite,
|
||||
OUT PULONG NumEventsWritten OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
ULONG i;
|
||||
|
||||
if (Console == NULL || InputBuffer == NULL /* || InputRecord == NULL */)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity checks */
|
||||
ASSERT(Console == InputBuffer->Header.Console);
|
||||
ASSERT( (InputRecord != NULL && NumEventsToWrite >= 0) ||
|
||||
(InputRecord == NULL && NumEventsToWrite == 0) );
|
||||
|
||||
// Do NOT do that !! Use the existing number of events already written, if any...
|
||||
// if (NumEventsWritten) *NumEventsWritten = 0;
|
||||
|
||||
for (i = (NumEventsWritten ? *NumEventsWritten : 0); i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
|
||||
{
|
||||
if (InputRecord->EventType == KEY_EVENT && !Unicode)
|
||||
{
|
||||
CHAR AsciiChar = InputRecord->Event.KeyEvent.uChar.AsciiChar;
|
||||
ConsoleInputAnsiCharToUnicodeChar(Console,
|
||||
&InputRecord->Event.KeyEvent.uChar.UnicodeChar,
|
||||
&AsciiChar);
|
||||
}
|
||||
|
||||
Status = ConioProcessInputEvent(Console, InputRecord++);
|
||||
}
|
||||
|
||||
if (NumEventsWritten) *NumEventsWritten = i;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvFlushConsoleInputBuffer(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput* Event;
|
||||
|
||||
if (Console == NULL || InputBuffer == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == InputBuffer->Header.Console);
|
||||
|
||||
/* Discard all entries in the input event queue */
|
||||
while (!IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
Event = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
ConsoleFreeHeap(Event);
|
||||
}
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleNumberOfInputEvents(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
OUT PULONG NumEvents)
|
||||
{
|
||||
PLIST_ENTRY CurrentInput;
|
||||
|
||||
if (Console == NULL || InputBuffer == NULL || NumEvents == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == InputBuffer->Header.Console);
|
||||
|
||||
*NumEvents = 0;
|
||||
|
||||
/* If there are any events ... */
|
||||
CurrentInput = InputBuffer->InputEvents.Flink;
|
||||
while (CurrentInput != &InputBuffer->InputEvents)
|
||||
{
|
||||
CurrentInput = CurrentInput->Flink;
|
||||
(*NumEvents)++;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Driver DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/condrv/conoutput.c
|
||||
* PURPOSE: General Console Output Functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "console.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "conoutput.h"
|
||||
#include "handle.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
|
||||
IN OUT PCONSOLE Console,
|
||||
IN PTEXTMODE_BUFFER_INFO TextModeInfo);
|
||||
NTSTATUS
|
||||
GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
|
||||
IN OUT PCONSOLE Console,
|
||||
IN PGRAPHICS_BUFFER_INFO GraphicsInfo);
|
||||
|
||||
VOID
|
||||
TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
|
||||
VOID
|
||||
GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
|
||||
IN OUT PCONSOLE Console,
|
||||
IN SIZE_T Size)
|
||||
{
|
||||
if (Buffer == NULL || Console == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
*Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, max(sizeof(CONSOLE_SCREEN_BUFFER), Size));
|
||||
if (*Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Initialize the header with the default type */
|
||||
ConSrvInitObject(&(*Buffer)->Header, SCREEN_BUFFER, Console);
|
||||
(*Buffer)->Vtbl = NULL;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
if (Buffer->Header.Type == TEXTMODE_BUFFER)
|
||||
TEXTMODE_BUFFER_Destroy(Buffer);
|
||||
else if (Buffer->Header.Type == GRAPHICS_BUFFER)
|
||||
GRAPHICS_BUFFER_Destroy(Buffer);
|
||||
else if (Buffer->Header.Type == SCREEN_BUFFER)
|
||||
ConsoleFreeHeap(Buffer);
|
||||
// else
|
||||
// do_nothing;
|
||||
}
|
||||
|
||||
// ConDrvCreateConsoleScreenBuffer
|
||||
NTSTATUS FASTCALL
|
||||
ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
|
||||
IN OUT PCONSOLE Console,
|
||||
IN ULONG BufferType,
|
||||
IN PVOID ScreenBufferInfo)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if ( Console == NULL || Buffer == NULL ||
|
||||
(BufferType != CONSOLE_TEXTMODE_BUFFER && BufferType != CONSOLE_GRAPHICS_BUFFER) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (BufferType == CONSOLE_TEXTMODE_BUFFER)
|
||||
{
|
||||
Status = TEXTMODE_BUFFER_Initialize(Buffer,
|
||||
Console,
|
||||
(PTEXTMODE_BUFFER_INFO)ScreenBufferInfo);
|
||||
}
|
||||
else if (BufferType == CONSOLE_GRAPHICS_BUFFER)
|
||||
{
|
||||
Status = GRAPHICS_BUFFER_Initialize(Buffer,
|
||||
Console,
|
||||
(PGRAPHICS_BUFFER_INFO)ScreenBufferInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Never ever go there!! */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Insert the newly created screen buffer into the list, if succeeded */
|
||||
if (NT_SUCCESS(Status)) InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID
|
||||
ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
|
||||
|
||||
VOID WINAPI
|
||||
ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
PCONSOLE Console = Buffer->Header.Console;
|
||||
PCONSOLE_SCREEN_BUFFER NewBuffer;
|
||||
|
||||
RemoveEntryList(&Buffer->ListEntry);
|
||||
if (Buffer == Console->ActiveBuffer)
|
||||
{
|
||||
/* Delete active buffer; switch to most recently created */
|
||||
Console->ActiveBuffer = NULL;
|
||||
if (!IsListEmpty(&Console->BufferList))
|
||||
{
|
||||
NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink,
|
||||
CONSOLE_SCREEN_BUFFER,
|
||||
ListEntry);
|
||||
ConioSetActiveScreenBuffer(NewBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConioDrawConsole(PCONSOLE Console)
|
||||
{
|
||||
SMALL_RECT Region;
|
||||
PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
|
||||
|
||||
if (ActiveBuffer)
|
||||
{
|
||||
ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1);
|
||||
ConioDrawRegion(Console, &Region);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
PCONSOLE Console = Buffer->Header.Console;
|
||||
Console->ActiveBuffer = Buffer;
|
||||
ConioResizeTerminal(Console);
|
||||
// ConioDrawConsole(Console);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
|
||||
IN PCONSOLE_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
if (Console == NULL || Buffer == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
|
||||
if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS;
|
||||
|
||||
/* If old buffer has no handles, it's now unreferenced */
|
||||
if (Console->ActiveBuffer->Header.HandleCount == 0)
|
||||
{
|
||||
ConioDeleteScreenBuffer(Console->ActiveBuffer);
|
||||
}
|
||||
|
||||
/* Tie console to new buffer */
|
||||
ConioSetActiveScreenBuffer(Buffer);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PCONSOLE_SCREEN_BUFFER
|
||||
ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
|
||||
{
|
||||
return (Console ? Console->ActiveBuffer : NULL);
|
||||
}
|
||||
|
||||
/* PUBLIC DRIVER APIS *********************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
|
||||
IN PCONSOLE_SCREEN_BUFFER Buffer,
|
||||
IN PSMALL_RECT Region)
|
||||
{
|
||||
if (Console == NULL || Buffer == NULL || Region == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
|
||||
/* If the output buffer is the current one, redraw the correct portion of the screen */
|
||||
if (Buffer == Console->ActiveBuffer) ConioDrawRegion(Console, Region);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
OUT PCONSOLE_CURSOR_INFO CursorInfo)
|
||||
{
|
||||
if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
|
||||
*CursorInfo = Buffer->CursorInfo;
|
||||
// CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
|
||||
// CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN PCONSOLE_CURSOR_INFO CursorInfo)
|
||||
{
|
||||
ULONG Size;
|
||||
BOOLEAN Visible, Success = TRUE;
|
||||
|
||||
if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
|
||||
Size = min(max(CursorInfo->dwSize, 1), 100);
|
||||
Visible = CursorInfo->bVisible;
|
||||
|
||||
if ( (Size != Buffer->CursorInfo.dwSize) ||
|
||||
(Visible && !Buffer->CursorInfo.bVisible) ||
|
||||
(!Visible && Buffer->CursorInfo.bVisible) )
|
||||
{
|
||||
Buffer->CursorInfo.dwSize = Size;
|
||||
Buffer->CursorInfo.bVisible = Visible;
|
||||
|
||||
Success = ConioSetCursorInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer);
|
||||
}
|
||||
|
||||
return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN PCOORD Position)
|
||||
{
|
||||
SHORT OldCursorX, OldCursorY;
|
||||
|
||||
if (Console == NULL || Buffer == NULL || Position == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity check */
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
|
||||
if ( Position->X < 0 || Position->X >= Buffer->ScreenBufferSize.X ||
|
||||
Position->Y < 0 || Position->Y >= Buffer->ScreenBufferSize.Y )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldCursorX = Buffer->CursorPosition.X;
|
||||
OldCursorY = Buffer->CursorPosition.Y;
|
||||
Buffer->CursorPosition = *Position;
|
||||
// Buffer->CursorPosition.X = Position->X;
|
||||
// Buffer->CursorPosition.Y = Position->Y;
|
||||
if ( ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) &&
|
||||
(!ConioSetScreenInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer, OldCursorX, OldCursorY)) )
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/condrv/dummyfrontend.c
|
||||
* PURPOSE: Dummy Terminal Front-End used when no frontend
|
||||
* is attached to the specified console.
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
|
||||
|
||||
/* DUMMY FRONTEND INTERFACE ***************************************************/
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
DummyInitFrontEnd(IN OUT PFRONTEND This,
|
||||
IN PCONSOLE Console)
|
||||
{
|
||||
/* Load some settings ?? */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
DummyDeinitFrontEnd(IN OUT PFRONTEND This)
|
||||
{
|
||||
/* Free some settings ?? */
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
DummyDrawRegion(IN OUT PFRONTEND This,
|
||||
SMALL_RECT* Region)
|
||||
{
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
DummyWriteStream(IN OUT PFRONTEND This,
|
||||
SMALL_RECT* Region,
|
||||
SHORT CursorStartX,
|
||||
SHORT CursorStartY,
|
||||
UINT ScrolledLines,
|
||||
PWCHAR Buffer,
|
||||
UINT Length)
|
||||
{
|
||||
}
|
||||
|
||||
static BOOL NTAPI
|
||||
DummySetCursorInfo(IN OUT PFRONTEND This,
|
||||
PCONSOLE_SCREEN_BUFFER Buff)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL NTAPI
|
||||
DummySetScreenInfo(IN OUT PFRONTEND This,
|
||||
PCONSOLE_SCREEN_BUFFER Buff,
|
||||
SHORT OldCursorX,
|
||||
SHORT OldCursorY)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
DummyResizeTerminal(IN OUT PFRONTEND This)
|
||||
{
|
||||
}
|
||||
|
||||
static BOOL NTAPI
|
||||
DummyProcessKeyCallback(IN OUT PFRONTEND This,
|
||||
MSG* msg,
|
||||
BYTE KeyStateMenu,
|
||||
DWORD ShiftState,
|
||||
UINT VirtualKeyCode,
|
||||
BOOL Down)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
DummyRefreshInternalInfo(IN OUT PFRONTEND This)
|
||||
{
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
DummyChangeTitle(IN OUT PFRONTEND This)
|
||||
{
|
||||
}
|
||||
|
||||
static BOOL NTAPI
|
||||
DummyChangeIcon(IN OUT PFRONTEND This,
|
||||
HICON hWindowIcon)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HWND NTAPI
|
||||
DummyGetConsoleWindowHandle(IN OUT PFRONTEND This)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
DummyGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
|
||||
PCOORD pSize)
|
||||
{
|
||||
}
|
||||
|
||||
static ULONG NTAPI
|
||||
DummyGetDisplayMode(IN OUT PFRONTEND This)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL NTAPI
|
||||
DummySetDisplayMode(IN OUT PFRONTEND This,
|
||||
ULONG NewMode)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT NTAPI
|
||||
DummyShowMouseCursor(IN OUT PFRONTEND This,
|
||||
BOOL Show)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL NTAPI
|
||||
DummySetMouseCursor(IN OUT PFRONTEND This,
|
||||
HCURSOR hCursor)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HMENU NTAPI
|
||||
DummyMenuControl(IN OUT PFRONTEND This,
|
||||
UINT cmdIdLow,
|
||||
UINT cmdIdHigh)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL NTAPI
|
||||
DummySetMenuClose(IN OUT PFRONTEND This,
|
||||
BOOL Enable)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static FRONTEND_VTBL DummyVtbl =
|
||||
{
|
||||
DummyInitFrontEnd,
|
||||
DummyDeinitFrontEnd,
|
||||
DummyDrawRegion,
|
||||
DummyWriteStream,
|
||||
DummySetCursorInfo,
|
||||
DummySetScreenInfo,
|
||||
DummyResizeTerminal,
|
||||
DummyProcessKeyCallback,
|
||||
DummyRefreshInternalInfo,
|
||||
DummyChangeTitle,
|
||||
DummyChangeIcon,
|
||||
DummyGetConsoleWindowHandle,
|
||||
DummyGetLargestConsoleWindowSize,
|
||||
DummyGetDisplayMode,
|
||||
DummySetDisplayMode,
|
||||
DummyShowMouseCursor,
|
||||
DummySetMouseCursor,
|
||||
DummyMenuControl,
|
||||
DummySetMenuClose,
|
||||
};
|
||||
|
||||
VOID
|
||||
ResetFrontEnd(IN PCONSOLE Console)
|
||||
{
|
||||
if (!Console) return;
|
||||
|
||||
/* Reinitialize the frontend interface */
|
||||
RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
|
||||
Console->TermIFace.Vtbl = &DummyVtbl;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Driver DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/condrv/graphics.c
|
||||
* PURPOSE: Console Output Functions for graphics-mode screen-buffers
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*
|
||||
* NOTE: See http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/
|
||||
* for more information.
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "conoutput.h"
|
||||
#include "handle.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
CONSOLE_IO_OBJECT_TYPE
|
||||
GRAPHICS_BUFFER_GetType(PCONSOLE_SCREEN_BUFFER This)
|
||||
{
|
||||
// return This->Header.Type;
|
||||
return GRAPHICS_BUFFER;
|
||||
}
|
||||
|
||||
static CONSOLE_SCREEN_BUFFER_VTBL GraphicsVtbl =
|
||||
{
|
||||
GRAPHICS_BUFFER_GetType,
|
||||
};
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
|
||||
IN OUT PCONSOLE Console,
|
||||
IN SIZE_T Size);
|
||||
VOID
|
||||
CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
|
||||
|
||||
|
||||
NTSTATUS
|
||||
GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
|
||||
IN OUT PCONSOLE Console,
|
||||
IN PGRAPHICS_BUFFER_INFO GraphicsInfo)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PGRAPHICS_SCREEN_BUFFER NewBuffer = NULL;
|
||||
|
||||
LARGE_INTEGER SectionSize;
|
||||
ULONG ViewSize = 0;
|
||||
HANDLE ProcessHandle;
|
||||
|
||||
if (Buffer == NULL || Console == NULL || GraphicsInfo == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
*Buffer = NULL;
|
||||
|
||||
Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer,
|
||||
Console,
|
||||
sizeof(GRAPHICS_SCREEN_BUFFER));
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
NewBuffer->Header.Type = GRAPHICS_BUFFER;
|
||||
NewBuffer->Vtbl = &GraphicsVtbl;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
NewBuffer->ClientProcess = ProcessHandle;
|
||||
|
||||
/* Get infos from the graphics buffer information structure */
|
||||
NewBuffer->BitMapInfoLength = GraphicsInfo->Info.dwBitMapInfoLength;
|
||||
|
||||
NewBuffer->BitMapInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->BitMapInfoLength);
|
||||
if (NewBuffer->BitMapInfo == NULL)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Adjust the bitmap height if needed (bottom-top vs. top-bottom). Use always bottom-up. */
|
||||
if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight > 0)
|
||||
GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
|
||||
|
||||
/* We do not use anything else than uncompressed bitmaps */
|
||||
if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB)
|
||||
{
|
||||
DPRINT1("biCompression == %d != BI_RGB, correct that!\n", GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression);
|
||||
GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB;
|
||||
}
|
||||
|
||||
RtlCopyMemory(NewBuffer->BitMapInfo,
|
||||
GraphicsInfo->Info.lpBitMapInfo,
|
||||
GraphicsInfo->Info.dwBitMapInfoLength);
|
||||
|
||||
NewBuffer->BitMapUsage = GraphicsInfo->Info.dwUsage;
|
||||
|
||||
/* Set the screen buffer size. Fight against overflows. */
|
||||
if ( GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth <= 0xFFFF &&
|
||||
-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight <= 0xFFFF )
|
||||
{
|
||||
/* Be careful about the sign of biHeight */
|
||||
NewBuffer->ScreenBufferSize.X = (SHORT)GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth ;
|
||||
NewBuffer->ScreenBufferSize.Y = (SHORT)-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
|
||||
|
||||
NewBuffer->OldViewSize = NewBuffer->ViewSize =
|
||||
NewBuffer->OldScreenBufferSize = NewBuffer->ScreenBufferSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
ConsoleFreeHeap(NewBuffer->BitMapInfo);
|
||||
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a mutex to synchronize bitmap memory access
|
||||
* between ourselves and the client.
|
||||
*/
|
||||
Status = NtCreateMutant(&NewBuffer->Mutex, MUTANT_ALL_ACCESS, NULL, FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtCreateMutant() failed: %lu\n", Status);
|
||||
ConsoleFreeHeap(NewBuffer->BitMapInfo);
|
||||
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplicate the Mutex for the client. We must keep a trace of it
|
||||
* so that we can close it when the client releases the screen buffer.
|
||||
*/
|
||||
Status = NtDuplicateObject(NtCurrentProcess(),
|
||||
NewBuffer->Mutex,
|
||||
ProcessHandle,
|
||||
&NewBuffer->ClientMutex,
|
||||
0, 0, DUPLICATE_SAME_ACCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
|
||||
NtClose(NewBuffer->Mutex);
|
||||
ConsoleFreeHeap(NewBuffer->BitMapInfo);
|
||||
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a memory section for the bitmap area, to share with the client.
|
||||
*/
|
||||
SectionSize.QuadPart = NewBuffer->BitMapInfo->bmiHeader.biSizeImage;
|
||||
Status = NtCreateSection(&NewBuffer->hSection,
|
||||
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);
|
||||
NtClose(NewBuffer->ClientMutex);
|
||||
NtClose(NewBuffer->Mutex);
|
||||
ConsoleFreeHeap(NewBuffer->BitMapInfo);
|
||||
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a view for our needs.
|
||||
*/
|
||||
ViewSize = 0;
|
||||
NewBuffer->BitMap = NULL;
|
||||
Status = NtMapViewOfSection(NewBuffer->hSection,
|
||||
NtCurrentProcess(),
|
||||
(PVOID*)&NewBuffer->BitMap,
|
||||
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(NewBuffer->hSection);
|
||||
NtClose(NewBuffer->ClientMutex);
|
||||
NtClose(NewBuffer->Mutex);
|
||||
ConsoleFreeHeap(NewBuffer->BitMapInfo);
|
||||
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
|
||||
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 screen buffer.
|
||||
*/
|
||||
ViewSize = 0;
|
||||
NewBuffer->ClientBitMap = NULL;
|
||||
Status = NtMapViewOfSection(NewBuffer->hSection,
|
||||
ProcessHandle,
|
||||
(PVOID*)&NewBuffer->ClientBitMap,
|
||||
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(), NewBuffer->BitMap);
|
||||
NtClose(NewBuffer->hSection);
|
||||
NtClose(NewBuffer->ClientMutex);
|
||||
NtClose(NewBuffer->Mutex);
|
||||
ConsoleFreeHeap(NewBuffer->BitMapInfo);
|
||||
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0;
|
||||
NewBuffer->VirtualY = 0;
|
||||
|
||||
NewBuffer->CursorBlinkOn = FALSE;
|
||||
NewBuffer->ForceCursorOff = TRUE;
|
||||
NewBuffer->CursorInfo.bVisible = FALSE;
|
||||
NewBuffer->CursorInfo.dwSize = 0;
|
||||
NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0;
|
||||
|
||||
NewBuffer->Mode = 0;
|
||||
|
||||
*Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
Quit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
PGRAPHICS_SCREEN_BUFFER Buff = (PGRAPHICS_SCREEN_BUFFER)Buffer;
|
||||
|
||||
/*
|
||||
* IMPORTANT !! Reinitialize the type so that we don't enter a recursive
|
||||
* infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
|
||||
*/
|
||||
Buffer->Header.Type = SCREEN_BUFFER;
|
||||
|
||||
/*
|
||||
* Uninitialize the graphics screen buffer
|
||||
* in the reverse way we initialized it.
|
||||
*/
|
||||
NtUnmapViewOfSection(Buff->ClientProcess, Buff->ClientBitMap);
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), Buff->BitMap);
|
||||
NtClose(Buff->hSection);
|
||||
NtClose(Buff->ClientMutex);
|
||||
NtClose(Buff->Mutex);
|
||||
ConsoleFreeHeap(Buff->BitMapInfo);
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/coninput.c
|
||||
* PURPOSE: Console Input functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "handle.h"
|
||||
#include "lineinput.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
#define ConSrvGetInputBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
|
||||
(Access), (LockConsole), INPUT_BUFFER)
|
||||
#define ConSrvGetInputBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
|
||||
(Access), (LockConsole), INPUT_BUFFER)
|
||||
#define ConSrvReleaseInputBuffer(Buff, IsConsoleLocked) \
|
||||
ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked))
|
||||
|
||||
|
||||
typedef struct _GET_INPUT_INFO
|
||||
{
|
||||
PCSR_THREAD CallingThread; // The thread which called the input API.
|
||||
PVOID HandleEntry; // The handle data associated with the wait thread.
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer; // The input buffer corresponding to the handle.
|
||||
} GET_INPUT_INFO, *PGET_INPUT_INFO;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static NTSTATUS
|
||||
WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
if (CreateWaitBlock)
|
||||
{
|
||||
PGET_INPUT_INFO CapturedInputInfo;
|
||||
|
||||
CapturedInputInfo = ConsoleAllocHeap(0, sizeof(GET_INPUT_INFO));
|
||||
if (!CapturedInputInfo) return STATUS_NO_MEMORY;
|
||||
|
||||
RtlMoveMemory(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO));
|
||||
|
||||
if (!CsrCreateWait(&InputInfo->InputBuffer->ReadWaitQueue,
|
||||
WaitFunction,
|
||||
InputInfo->CallingThread,
|
||||
ApiMessage,
|
||||
CapturedInputInfo,
|
||||
NULL))
|
||||
{
|
||||
ConsoleFreeHeap(CapturedInputInfo);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for input */
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL);
|
||||
|
||||
// Wait function CSR_WAIT_FUNCTION
|
||||
static BOOLEAN
|
||||
ReadCharsThread(IN PLIST_ENTRY WaitList,
|
||||
IN PCSR_THREAD WaitThread,
|
||||
IN PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
|
||||
|
||||
PVOID InputHandle = WaitArgument2;
|
||||
|
||||
DPRINT("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
|
||||
|
||||
/*
|
||||
* If we are notified of the process termination via a call
|
||||
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
|
||||
* CsrDestroyThread, just return.
|
||||
*/
|
||||
if (WaitFlags & CsrProcessTerminating)
|
||||
{
|
||||
Status = STATUS_THREAD_IS_TERMINATING;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Somebody is closing a handle to this input buffer,
|
||||
* by calling ConSrvCloseHandleEntry.
|
||||
* See whether we are linked to that handle (ie. we
|
||||
* are a waiter for this handle), and if so, return.
|
||||
* Otherwise, ignore the call and continue waiting.
|
||||
*/
|
||||
if (InputHandle != NULL)
|
||||
{
|
||||
Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
|
||||
: STATUS_PENDING);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we go there, that means we are notified for some new input.
|
||||
* The console is therefore already locked.
|
||||
*/
|
||||
Status = ReadChars(InputInfo,
|
||||
WaitApiMessage,
|
||||
FALSE);
|
||||
|
||||
Quit:
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
WaitApiMessage->Status = Status;
|
||||
ConsoleFreeHeap(InputInfo);
|
||||
}
|
||||
|
||||
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvReadConsole(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PVOID Buffer,
|
||||
IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
|
||||
IN ULONG NumCharsToRead,
|
||||
OUT PULONG NumCharsRead OPTIONAL);
|
||||
static NTSTATUS
|
||||
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
|
||||
CONSOLE_READCONSOLE_CONTROL ReadControl;
|
||||
|
||||
ReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL);
|
||||
ReadControl.nInitialChars = ReadConsoleRequest->NrCharactersRead;
|
||||
ReadControl.dwCtrlWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
|
||||
ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState;
|
||||
|
||||
Status = ConDrvReadConsole(InputBuffer->Header.Console,
|
||||
InputBuffer,
|
||||
ReadConsoleRequest->Unicode,
|
||||
ReadConsoleRequest->Buffer,
|
||||
&ReadControl,
|
||||
ReadConsoleRequest->NrCharactersToRead,
|
||||
&ReadConsoleRequest->NrCharactersRead);
|
||||
|
||||
ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* We haven't completed a read, so start a wait */
|
||||
return WaitBeforeReading(InputInfo,
|
||||
ApiMessage,
|
||||
ReadCharsThread,
|
||||
CreateWaitBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We read all what we wanted, we return the error code we were given */
|
||||
return Status;
|
||||
// return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
|
||||
IN BOOL Wait,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL);
|
||||
|
||||
// Wait function CSR_WAIT_FUNCTION
|
||||
static BOOLEAN
|
||||
ReadInputBufferThread(IN PLIST_ENTRY WaitList,
|
||||
IN PCSR_THREAD WaitThread,
|
||||
IN PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetInputRequest;
|
||||
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
|
||||
|
||||
PVOID InputHandle = WaitArgument2;
|
||||
|
||||
DPRINT("ReadInputBufferThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
|
||||
|
||||
/*
|
||||
* If we are notified of the process termination via a call
|
||||
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
|
||||
* CsrDestroyThread, just return.
|
||||
*/
|
||||
if (WaitFlags & CsrProcessTerminating)
|
||||
{
|
||||
Status = STATUS_THREAD_IS_TERMINATING;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Somebody is closing a handle to this input buffer,
|
||||
* by calling ConSrvCloseHandleEntry.
|
||||
* See whether we are linked to that handle (ie. we
|
||||
* are a waiter for this handle), and if so, return.
|
||||
* Otherwise, ignore the call and continue waiting.
|
||||
*/
|
||||
if (InputHandle != NULL)
|
||||
{
|
||||
Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
|
||||
: STATUS_PENDING);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we go there, that means we are notified for some new input.
|
||||
* The console is therefore already locked.
|
||||
*/
|
||||
Status = ReadInputBuffer(InputInfo,
|
||||
GetInputRequest->bRead,
|
||||
WaitApiMessage,
|
||||
FALSE);
|
||||
|
||||
Quit:
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
WaitApiMessage->Status = Status;
|
||||
ConsoleFreeHeap(InputInfo);
|
||||
}
|
||||
|
||||
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleInput(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN WaitForMoreEvents,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToRead,
|
||||
OUT PULONG NumEventsRead);
|
||||
static NTSTATUS
|
||||
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
|
||||
IN BOOL Wait, // TRUE --> Read ; FALSE --> Peek
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
|
||||
|
||||
// GetInputRequest->InputsRead = 0;
|
||||
|
||||
Status = ConDrvGetConsoleInput(InputBuffer->Header.Console,
|
||||
InputBuffer,
|
||||
Wait,
|
||||
GetInputRequest->Unicode,
|
||||
GetInputRequest->InputRecord,
|
||||
GetInputRequest->Length,
|
||||
&GetInputRequest->InputsRead);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* We haven't completed a read, so start a wait */
|
||||
return WaitBeforeReading(InputInfo,
|
||||
ApiMessage,
|
||||
ReadInputBufferThread,
|
||||
CreateWaitBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We read all what we wanted, we return the error code we were given */
|
||||
return Status;
|
||||
// return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
CSR_API(SrvReadConsole)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PVOID HandleEntry;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer;
|
||||
GET_INPUT_INFO InputInfo;
|
||||
|
||||
DPRINT("SrvReadConsole\n");
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ReadConsoleRequest->Buffer,
|
||||
ReadConsoleRequest->BufferSize,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
// This member is set by the caller (IntReadConsole in kernel32)
|
||||
// ReadConsoleRequest->NrCharactersRead = 0;
|
||||
|
||||
InputInfo.CallingThread = CsrGetClientThread();
|
||||
InputInfo.HandleEntry = HandleEntry;
|
||||
InputInfo.InputBuffer = InputBuffer;
|
||||
|
||||
Status = ReadChars(&InputInfo,
|
||||
ApiMessage,
|
||||
TRUE);
|
||||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
|
||||
if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleInput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PVOID HandleEntry;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer;
|
||||
GET_INPUT_INFO InputInfo;
|
||||
|
||||
DPRINT("SrvGetConsoleInput\n");
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&GetInputRequest->InputRecord,
|
||||
GetInputRequest->Length,
|
||||
sizeof(INPUT_RECORD)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, GetInputRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
GetInputRequest->InputsRead = 0;
|
||||
|
||||
InputInfo.CallingThread = CsrGetClientThread();
|
||||
InputInfo.HandleEntry = HandleEntry;
|
||||
InputInfo.InputBuffer = InputBuffer;
|
||||
|
||||
Status = ReadInputBuffer(&InputInfo,
|
||||
GetInputRequest->bRead,
|
||||
ApiMessage,
|
||||
TRUE);
|
||||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
|
||||
if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsoleInput(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToWrite,
|
||||
OUT PULONG NumEventsWritten OPTIONAL);
|
||||
CSR_API(SrvWriteConsoleInput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_WRITEINPUT WriteInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteInputRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer;
|
||||
ULONG NumEventsWritten;
|
||||
|
||||
DPRINT("SrvWriteConsoleInput\n");
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&WriteInputRequest->InputRecord,
|
||||
WriteInputRequest->Length,
|
||||
sizeof(INPUT_RECORD)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
WriteInputRequest->InputHandle,
|
||||
&InputBuffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
NumEventsWritten = 0;
|
||||
Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,
|
||||
InputBuffer,
|
||||
WriteInputRequest->Unicode,
|
||||
WriteInputRequest->InputRecord,
|
||||
WriteInputRequest->Length,
|
||||
&NumEventsWritten);
|
||||
WriteInputRequest->Length = NumEventsWritten;
|
||||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvFlushConsoleInputBuffer(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer);
|
||||
CSR_API(SrvFlushConsoleInputBuffer)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer;
|
||||
|
||||
DPRINT("SrvFlushConsoleInputBuffer\n");
|
||||
|
||||
Status = ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
FlushInputBufferRequest->InputHandle,
|
||||
&InputBuffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvFlushConsoleInputBuffer(InputBuffer->Header.Console,
|
||||
InputBuffer);
|
||||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleNumberOfInputEvents(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
OUT PULONG NumEvents);
|
||||
CSR_API(SrvGetConsoleNumberOfInputEvents)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumInputEventsRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer;
|
||||
|
||||
DPRINT("SrvGetConsoleNumberOfInputEvents\n");
|
||||
|
||||
Status = ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
GetNumInputEventsRequest->InputHandle,
|
||||
&InputBuffer, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvGetConsoleNumberOfInputEvents(InputBuffer->Header.Console,
|
||||
InputBuffer,
|
||||
&GetNumInputEventsRequest->NumInputEvents);
|
||||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/coninput.h
|
||||
* PURPOSE: Console Input functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
VOID FASTCALL PurgeInputBuffer(PCONSOLE Console);
|
||||
|
||||
VOID NTAPI
|
||||
ConDrvProcessKey(IN PCONSOLE Console,
|
||||
IN BOOLEAN Down,
|
||||
IN UINT VirtualKeyCode,
|
||||
IN UINT VirtualScanCode,
|
||||
IN WCHAR UnicodeChar,
|
||||
IN ULONG ShiftState,
|
||||
IN BYTE KeyStateCtrl);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,793 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/conoutput.c
|
||||
* PURPOSE: General Console Output Functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "console.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "conoutput.h"
|
||||
#include "handle.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
|
||||
IN PCONSOLE_SCREEN_BUFFER Buffer,
|
||||
IN PSMALL_RECT Region);
|
||||
CSR_API(SrvInvalidateBitMapRect)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.InvalidateDIBitsRequest;
|
||||
PCONSOLE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvInvalidateBitMapRect\n");
|
||||
|
||||
Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
InvalidateDIBitsRequest->OutputHandle,
|
||||
&Buffer, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvInvalidateBitMapRect(Buffer->Header.Console,
|
||||
Buffer,
|
||||
&InvalidateDIBitsRequest->Region);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
OUT PCONSOLE_CURSOR_INFO CursorInfo);
|
||||
CSR_API(SrvGetConsoleCursorInfo)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvGetConsoleCursorInfo\n");
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
CursorInfoRequest->OutputHandle,
|
||||
&Buffer, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvGetConsoleCursorInfo(Buffer->Header.Console,
|
||||
Buffer,
|
||||
&CursorInfoRequest->Info);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN PCONSOLE_CURSOR_INFO CursorInfo);
|
||||
CSR_API(SrvSetConsoleCursorInfo)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvSetConsoleCursorInfo\n");
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
CursorInfoRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleCursorInfo(Buffer->Header.Console,
|
||||
Buffer,
|
||||
&CursorInfoRequest->Info);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN PCOORD Position);
|
||||
CSR_API(SrvSetConsoleCursorPosition)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorPositionRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvSetConsoleCursorPosition\n");
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
SetCursorPositionRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleCursorPosition(Buffer->Header.Console,
|
||||
Buffer,
|
||||
&SetCursorPositionRequest->Position);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvCreateConsoleScreenBuffer)
|
||||
{
|
||||
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
||||
PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
|
||||
PVOID ScreenBufferInfo = NULL;
|
||||
TEXTMODE_BUFFER_INFO TextModeInfo = {{80, 25},
|
||||
DEFAULT_SCREEN_ATTRIB,
|
||||
DEFAULT_POPUP_ATTRIB ,
|
||||
TRUE,
|
||||
CSR_DEFAULT_CURSOR_SIZE};
|
||||
GRAPHICS_BUFFER_INFO GraphicsInfo;
|
||||
GraphicsInfo.Info = CreateScreenBufferRequest->GraphicsBufferInfo; // HACK for MSVC
|
||||
|
||||
DPRINT("SrvCreateConsoleScreenBuffer\n");
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_TEXTMODE_BUFFER)
|
||||
{
|
||||
ScreenBufferInfo = &TextModeInfo;
|
||||
|
||||
/*
|
||||
if (Console->ActiveBuffer)
|
||||
{
|
||||
TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
|
||||
if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80;
|
||||
if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25;
|
||||
|
||||
TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib;
|
||||
TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib;
|
||||
|
||||
TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
|
||||
TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is Windows' behaviour
|
||||
*/
|
||||
|
||||
/* Use the current console size. Regularize it if needed. */
|
||||
TextModeInfo.ScreenBufferSize = Console->ConsoleSize;
|
||||
if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 1;
|
||||
if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 1;
|
||||
|
||||
/* If we have an active screen buffer, use its attributes as the new ones */
|
||||
if (Console->ActiveBuffer && GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
|
||||
{
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer;
|
||||
|
||||
TextModeInfo.ScreenAttrib = Buffer->ScreenDefaultAttrib;
|
||||
TextModeInfo.PopupAttrib = Buffer->PopupDefaultAttrib;
|
||||
|
||||
TextModeInfo.IsCursorVisible = Buffer->CursorInfo.bVisible;
|
||||
TextModeInfo.CursorSize = Buffer->CursorInfo.dwSize;
|
||||
}
|
||||
}
|
||||
else if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
|
||||
{
|
||||
/* Get infos from the graphics buffer information structure */
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo,
|
||||
1,
|
||||
CreateScreenBufferRequest->GraphicsBufferInfo.dwBitMapInfoLength))
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ScreenBufferInfo = &GraphicsInfo;
|
||||
|
||||
/* Initialize shared variables */
|
||||
CreateScreenBufferRequest->GraphicsBufferInfo.hMutex = GraphicsInfo.Info.hMutex = INVALID_HANDLE_VALUE;
|
||||
CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap = GraphicsInfo.Info.lpBitMap = NULL;
|
||||
|
||||
/* A graphics screen buffer is never inheritable */
|
||||
CreateScreenBufferRequest->Inheritable = FALSE;
|
||||
}
|
||||
|
||||
Status = ConDrvCreateScreenBuffer(&Buff,
|
||||
Console,
|
||||
CreateScreenBufferRequest->ScreenBufferType,
|
||||
ScreenBufferInfo);
|
||||
if (!NT_SUCCESS(Status)) goto Quit;
|
||||
|
||||
/* Insert the new handle inside the process handles table */
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&CreateScreenBufferRequest->OutputHandle,
|
||||
&Buff->Header,
|
||||
CreateScreenBufferRequest->Access,
|
||||
CreateScreenBufferRequest->Inheritable,
|
||||
CreateScreenBufferRequest->ShareMode);
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if (!NT_SUCCESS(Status)) goto Quit;
|
||||
|
||||
if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
|
||||
{
|
||||
PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)Buff;
|
||||
/*
|
||||
* Initialize the graphics buffer information structure
|
||||
* and give it back to the client.
|
||||
*/
|
||||
CreateScreenBufferRequest->GraphicsBufferInfo.hMutex = Buffer->ClientMutex;
|
||||
CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap = Buffer->ClientBitMap;
|
||||
}
|
||||
|
||||
Quit:
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
|
||||
IN PCONSOLE_SCREEN_BUFFER Buffer);
|
||||
CSR_API(SrvSetConsoleActiveScreenBuffer)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest;
|
||||
PCONSOLE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvSetConsoleActiveScreenBuffer\n");
|
||||
|
||||
Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
SetScreenBufferRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleActiveScreenBuffer(Buffer->Header.Console,
|
||||
Buffer);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/* CSR THREADS FOR WriteConsole ***********************************************/
|
||||
|
||||
static NTSTATUS
|
||||
DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN PCSR_THREAD ClientThread,
|
||||
IN BOOL CreateWaitBlock OPTIONAL);
|
||||
|
||||
// Wait function CSR_WAIT_FUNCTION
|
||||
static BOOLEAN
|
||||
WriteConsoleThread(IN PLIST_ENTRY WaitList,
|
||||
IN PCSR_THREAD WaitThread,
|
||||
IN PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
|
||||
|
||||
/*
|
||||
* If we are notified of the process termination via a call
|
||||
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
|
||||
* CsrDestroyThread, just return.
|
||||
*/
|
||||
if (WaitFlags & CsrProcessTerminating)
|
||||
{
|
||||
Status = STATUS_THREAD_IS_TERMINATING;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = DoWriteConsole(WaitApiMessage,
|
||||
WaitThread,
|
||||
FALSE);
|
||||
|
||||
Quit:
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
WaitApiMessage->Status = Status;
|
||||
}
|
||||
|
||||
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsole(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PVOID StringBuffer,
|
||||
IN ULONG NumCharsToWrite,
|
||||
OUT PULONG NumCharsWritten OPTIONAL);
|
||||
static NTSTATUS
|
||||
DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN PCSR_THREAD ClientThread,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
|
||||
WriteConsoleRequest->OutputHandle,
|
||||
&ScreenBuffer, GENERIC_WRITE, FALSE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
|
||||
ScreenBuffer,
|
||||
WriteConsoleRequest->Unicode,
|
||||
WriteConsoleRequest->Buffer,
|
||||
WriteConsoleRequest->NrCharactersToWrite,
|
||||
&WriteConsoleRequest->NrCharactersWritten);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
if (CreateWaitBlock)
|
||||
{
|
||||
if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue,
|
||||
WriteConsoleThread,
|
||||
ClientThread,
|
||||
ApiMessage,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until we un-pause the console */
|
||||
// Status = STATUS_PENDING;
|
||||
}
|
||||
|
||||
Quit:
|
||||
ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/* TEXT OUTPUT APIS ***********************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvReadConsoleOutput(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PCHAR_INFO CharInfo/*Buffer*/,
|
||||
IN PCOORD BufferSize,
|
||||
IN PCOORD BufferCoord,
|
||||
IN OUT PSMALL_RECT ReadRegion);
|
||||
CSR_API(SrvReadConsoleOutput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvReadConsoleOutput\n");
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ReadOutputRequest->CharInfo,
|
||||
ReadOutputRequest->BufferSize.X * ReadOutputRequest->BufferSize.Y,
|
||||
sizeof(CHAR_INFO)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
ReadOutputRequest->OutputHandle,
|
||||
&Buffer, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvReadConsoleOutput(Buffer->Header.Console,
|
||||
Buffer,
|
||||
ReadOutputRequest->Unicode,
|
||||
ReadOutputRequest->CharInfo,
|
||||
&ReadOutputRequest->BufferSize,
|
||||
&ReadOutputRequest->BufferCoord,
|
||||
&ReadOutputRequest->ReadRegion);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsoleOutput(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PCHAR_INFO CharInfo/*Buffer*/,
|
||||
IN PCOORD BufferSize,
|
||||
IN PCOORD BufferCoord,
|
||||
IN OUT PSMALL_RECT WriteRegion);
|
||||
CSR_API(SrvWriteConsoleOutput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvWriteConsoleOutput\n");
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&WriteOutputRequest->CharInfo,
|
||||
WriteOutputRequest->BufferSize.X * WriteOutputRequest->BufferSize.Y,
|
||||
sizeof(CHAR_INFO)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
WriteOutputRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvWriteConsoleOutput(Buffer->Header.Console,
|
||||
Buffer,
|
||||
WriteOutputRequest->Unicode,
|
||||
WriteOutputRequest->CharInfo,
|
||||
&WriteOutputRequest->BufferSize,
|
||||
&WriteOutputRequest->BufferCoord,
|
||||
&WriteOutputRequest->WriteRegion);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvWriteConsole)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
|
||||
|
||||
DPRINT("SrvWriteConsole\n");
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&WriteConsoleRequest->Buffer,
|
||||
WriteConsoleRequest->BufferSize,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = DoWriteConsole(ApiMessage,
|
||||
CsrGetClientThread(),
|
||||
TRUE);
|
||||
|
||||
if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN CODE_TYPE CodeType,
|
||||
OUT PVOID StringBuffer,
|
||||
IN ULONG NumCodesToRead,
|
||||
IN PCOORD ReadCoord,
|
||||
OUT PCOORD EndCoord,
|
||||
OUT PULONG CodesRead);
|
||||
CSR_API(SrvReadConsoleOutputString)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputCodeRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
ULONG CodeSize;
|
||||
|
||||
DPRINT("SrvReadConsoleOutputString\n");
|
||||
|
||||
switch (ReadOutputCodeRequest->CodeType)
|
||||
{
|
||||
case CODE_ASCII:
|
||||
CodeSize = sizeof(CHAR);
|
||||
break;
|
||||
|
||||
case CODE_UNICODE:
|
||||
CodeSize = sizeof(WCHAR);
|
||||
break;
|
||||
|
||||
case CODE_ATTRIBUTE:
|
||||
CodeSize = sizeof(WORD);
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ReadOutputCodeRequest->pCode.pCode,
|
||||
ReadOutputCodeRequest->NumCodesToRead,
|
||||
CodeSize))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
ReadOutputCodeRequest->OutputHandle,
|
||||
&Buffer, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvReadConsoleOutputString(Buffer->Header.Console,
|
||||
Buffer,
|
||||
ReadOutputCodeRequest->CodeType,
|
||||
ReadOutputCodeRequest->pCode.pCode,
|
||||
ReadOutputCodeRequest->NumCodesToRead,
|
||||
&ReadOutputCodeRequest->ReadCoord,
|
||||
&ReadOutputCodeRequest->EndCoord,
|
||||
&ReadOutputCodeRequest->CodesRead);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN CODE_TYPE CodeType,
|
||||
IN PVOID StringBuffer,
|
||||
IN ULONG NumCodesToWrite,
|
||||
IN PCOORD WriteCoord /*,
|
||||
OUT PCOORD EndCoord,
|
||||
OUT PULONG CodesWritten */);
|
||||
CSR_API(SrvWriteConsoleOutputString)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputCodeRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
ULONG CodeSize;
|
||||
|
||||
DPRINT("SrvWriteConsoleOutputString\n");
|
||||
|
||||
switch (WriteOutputCodeRequest->CodeType)
|
||||
{
|
||||
case CODE_ASCII:
|
||||
CodeSize = sizeof(CHAR);
|
||||
break;
|
||||
|
||||
case CODE_UNICODE:
|
||||
CodeSize = sizeof(WCHAR);
|
||||
break;
|
||||
|
||||
case CODE_ATTRIBUTE:
|
||||
CodeSize = sizeof(WORD);
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&WriteOutputCodeRequest->pCode.pCode,
|
||||
WriteOutputCodeRequest->Length,
|
||||
CodeSize))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
WriteOutputCodeRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvWriteConsoleOutputString(Buffer->Header.Console,
|
||||
Buffer,
|
||||
WriteOutputCodeRequest->CodeType,
|
||||
WriteOutputCodeRequest->pCode.pCode,
|
||||
WriteOutputCodeRequest->Length, // NumCodesToWrite,
|
||||
&WriteOutputCodeRequest->Coord /*, // WriteCoord,
|
||||
&WriteOutputCodeRequest->EndCoord,
|
||||
&WriteOutputCodeRequest->NrCharactersWritten */);
|
||||
|
||||
// WriteOutputCodeRequest->NrCharactersWritten = Written;
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN CODE_TYPE CodeType,
|
||||
IN PVOID Code,
|
||||
IN ULONG NumCodesToWrite,
|
||||
IN PCOORD WriteCoord /*,
|
||||
OUT PULONG CodesWritten */);
|
||||
CSR_API(SrvFillConsoleOutput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
USHORT CodeType = FillOutputRequest->CodeType;
|
||||
|
||||
DPRINT("SrvFillConsoleOutput\n");
|
||||
|
||||
if ( (CodeType != CODE_ASCII ) &&
|
||||
(CodeType != CODE_UNICODE ) &&
|
||||
(CodeType != CODE_ATTRIBUTE) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
FillOutputRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvFillConsoleOutput(Buffer->Header.Console,
|
||||
Buffer,
|
||||
CodeType,
|
||||
&FillOutputRequest->Code,
|
||||
FillOutputRequest->Length, // NumCodesToWrite,
|
||||
&FillOutputRequest->Coord /*, // WriteCoord,
|
||||
&FillOutputRequest->NrCharactersWritten */);
|
||||
|
||||
// FillOutputRequest->NrCharactersWritten = Written;
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
OUT PCONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo);
|
||||
CSR_API(SrvGetConsoleScreenBufferInfo)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvGetConsoleScreenBufferInfo\n");
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
ScreenBufferInfoRequest->OutputHandle,
|
||||
&Buffer, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvGetConsoleScreenBufferInfo(Buffer->Header.Console,
|
||||
Buffer,
|
||||
&ScreenBufferInfoRequest->Info);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleTextAttribute(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN WORD Attribute);
|
||||
CSR_API(SrvSetConsoleTextAttribute)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetTextAttribRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvSetConsoleTextAttribute\n");
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
SetTextAttribRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleTextAttribute(Buffer->Header.Console,
|
||||
Buffer,
|
||||
SetTextAttribRequest->Attrib);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN PCOORD Size);
|
||||
CSR_API(SrvSetConsoleScreenBufferSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferSizeRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvSetConsoleScreenBufferSize\n");
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
SetScreenBufferSizeRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleScreenBufferSize(Buffer->Header.Console,
|
||||
Buffer,
|
||||
&SetScreenBufferSizeRequest->Size);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PSMALL_RECT ScrollRectangle,
|
||||
IN BOOLEAN UseClipRectangle,
|
||||
IN PSMALL_RECT ClipRectangle OPTIONAL,
|
||||
IN PCOORD DestinationOrigin,
|
||||
IN CHAR_INFO FillChar);
|
||||
CSR_API(SrvScrollConsoleScreenBuffer)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScrollScreenBufferRequest;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT("SrvScrollConsoleScreenBuffer\n");
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
ScrollScreenBufferRequest->OutputHandle,
|
||||
&Buffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvScrollConsoleScreenBuffer(Buffer->Header.Console,
|
||||
Buffer,
|
||||
ScrollScreenBufferRequest->Unicode,
|
||||
&ScrollScreenBufferRequest->ScrollRectangle,
|
||||
ScrollScreenBufferRequest->UseClipRectangle,
|
||||
&ScrollScreenBufferRequest->ClipRectangle,
|
||||
&ScrollScreenBufferRequest->DestinationOrigin,
|
||||
ScrollScreenBufferRequest->Fill);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleWindowInfo(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
IN BOOLEAN Absolute,
|
||||
IN PSMALL_RECT WindowRect);
|
||||
CSR_API(SrvSetConsoleWindowInfo)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest;
|
||||
// PCONSOLE_SCREEN_BUFFER Buffer;
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer;
|
||||
|
||||
DPRINT1("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
|
||||
SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
|
||||
SetWindowInfoRequest->WindowRect.Left ,
|
||||
SetWindowInfoRequest->WindowRect.Top ,
|
||||
SetWindowInfoRequest->WindowRect.Right,
|
||||
SetWindowInfoRequest->WindowRect.Bottom);
|
||||
|
||||
// ConSrvGetScreenBuffer
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
SetWindowInfoRequest->OutputHandle,
|
||||
&Buffer, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleWindowInfo(Buffer->Header.Console,
|
||||
Buffer,
|
||||
SetWindowInfoRequest->Absolute,
|
||||
&SetWindowInfoRequest->WindowRect);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buffer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/conoutput.h
|
||||
* PURPOSE: Console Output functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ConSrvGetTextModeBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
|
||||
(Access), (LockConsole), TEXTMODE_BUFFER)
|
||||
#define ConSrvGetTextModeBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
|
||||
(Access), (LockConsole), TEXTMODE_BUFFER)
|
||||
|
||||
#define ConSrvGetGraphicsBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
|
||||
(Access), (LockConsole), GRAPHICS_BUFFER)
|
||||
#define ConSrvGetGraphicsBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
|
||||
(Access), (LockConsole), GRAPHICS_BUFFER)
|
||||
|
||||
#define ConSrvGetScreenBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
|
||||
(Access), (LockConsole), SCREEN_BUFFER)
|
||||
#define ConSrvGetScreenBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
|
||||
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
|
||||
(Access), (LockConsole), SCREEN_BUFFER)
|
||||
|
||||
#define ConSrvReleaseScreenBuffer(Buff, IsConsoleLocked) \
|
||||
ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked))
|
||||
|
||||
NTSTATUS FASTCALL ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
|
||||
IN OUT PCONSOLE Console,
|
||||
IN ULONG BufferType,
|
||||
IN PVOID ScreenBufferInfo);
|
||||
VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
|
||||
// VOID FASTCALL ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
|
||||
|
||||
PCONSOLE_SCREEN_BUFFER
|
||||
ConDrvGetActiveScreenBuffer(IN PCONSOLE Console);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,652 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/console.c
|
||||
* PURPOSE: Console Management Functions
|
||||
* PROGRAMMERS: Gé van Geldorp
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "handle.h"
|
||||
#include "procinit.h"
|
||||
#include "alias.h"
|
||||
#include "coninput.h"
|
||||
#include "conoutput.h"
|
||||
#include "lineinput.h"
|
||||
#include "include/settings.h"
|
||||
|
||||
#include "frontends/gui/guiterm.h"
|
||||
#ifdef TUITERM_COMPILE
|
||||
#include "frontends/tui/tuiterm.h"
|
||||
#endif
|
||||
|
||||
#include "include/console.h"
|
||||
#include "console.h"
|
||||
#include "resource.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/***************/
|
||||
#ifdef TUITERM_COMPILE
|
||||
NTSTATUS NTAPI
|
||||
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN OUT PVOID ExtraConsoleInfo,
|
||||
IN ULONG ProcessId);
|
||||
NTSTATUS NTAPI
|
||||
TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
|
||||
#endif
|
||||
|
||||
NTSTATUS NTAPI
|
||||
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN OUT PVOID ExtraConsoleInfo,
|
||||
IN ULONG ProcessId);
|
||||
NTSTATUS NTAPI
|
||||
GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
|
||||
/***************/
|
||||
|
||||
typedef
|
||||
NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
|
||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN OUT PVOID ExtraConsoleInfo,
|
||||
IN ULONG ProcessId);
|
||||
|
||||
typedef
|
||||
NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
|
||||
|
||||
/*
|
||||
* If we are not in GUI-mode, start the text-mode terminal emulator.
|
||||
* If we fail, try to start the GUI-mode terminal emulator.
|
||||
*
|
||||
* Try to open the GUI-mode terminal emulator. Two cases are possible:
|
||||
* - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
|
||||
* failed and we start GUI-mode terminal emulator.
|
||||
* - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
|
||||
* succeeded BUT we failed at starting text-mode terminal emulator.
|
||||
* Then GuiMode was switched to TRUE in order to try to open the GUI-mode
|
||||
* terminal emulator (Win32k will automatically switch to graphical mode,
|
||||
* therefore no additional code is needed).
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: Each entry of the table should be retrieved when loading a front-end
|
||||
* (examples of the CSR servers which register some data for CSRSS).
|
||||
*/
|
||||
struct
|
||||
{
|
||||
CHAR FrontEndName[80];
|
||||
FRONTEND_LOAD FrontEndLoad;
|
||||
FRONTEND_UNLOAD FrontEndUnload;
|
||||
} FrontEndLoadingMethods[] =
|
||||
{
|
||||
#ifdef TUITERM_COMPILE
|
||||
{"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd},
|
||||
#endif
|
||||
{"GUI", GuiLoadFrontEnd, GuiUnloadFrontEnd},
|
||||
|
||||
// {"Not found", 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
#if 0000
|
||||
VOID FASTCALL
|
||||
ConioPause(PCONSOLE Console, UINT Flags)
|
||||
{
|
||||
Console->PauseFlags |= Flags;
|
||||
if (!Console->UnpauseEvent)
|
||||
Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConioUnpause(PCONSOLE Console, UINT Flags)
|
||||
{
|
||||
Console->PauseFlags &= ~Flags;
|
||||
|
||||
// if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
|
||||
if (Console->PauseFlags == 0 && Console->UnpauseEvent)
|
||||
{
|
||||
SetEvent(Console->UnpauseEvent);
|
||||
CloseHandle(Console->UnpauseEvent);
|
||||
Console->UnpauseEvent = NULL;
|
||||
|
||||
CsrNotifyWait(&Console->WriteWaitQueue,
|
||||
WaitAll,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!IsListEmpty(&Console->WriteWaitQueue))
|
||||
{
|
||||
CsrDereferenceWait(&Console->WriteWaitQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
PCONSOLE* Console,
|
||||
BOOL LockConsole)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE ProcessConsole;
|
||||
|
||||
ASSERT(Console);
|
||||
*Console = NULL;
|
||||
|
||||
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
Status = ConDrvGetConsole(&ProcessConsole, ProcessData->ConsoleHandle, LockConsole);
|
||||
if (NT_SUCCESS(Status)) *Console = ProcessConsole;
|
||||
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConSrvReleaseConsole(PCONSOLE Console,
|
||||
BOOL WasConsoleLocked)
|
||||
{
|
||||
/* Just call the driver*/
|
||||
ConDrvReleaseConsole(Console, WasConsoleLocked);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS WINAPI
|
||||
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
||||
OUT PCONSOLE* NewConsole,
|
||||
IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
|
||||
IN ULONG ConsoleLeaderProcessId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE ConsoleHandle;
|
||||
PCONSOLE Console;
|
||||
CONSOLE_INFO ConsoleInfo;
|
||||
SIZE_T Length = 0;
|
||||
ULONG i = 0;
|
||||
FRONTEND FrontEnd;
|
||||
|
||||
if (NewConsole == NULL || ConsoleStartInfo == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
*NewConsole = NULL;
|
||||
|
||||
/*
|
||||
* Load the console settings
|
||||
*/
|
||||
|
||||
/* 1. Load the default settings */
|
||||
ConSrvGetDefaultSettings(&ConsoleInfo, ConsoleLeaderProcessId);
|
||||
|
||||
/* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
|
||||
Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
|
||||
sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1);
|
||||
wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
|
||||
ConsoleInfo.ConsoleTitle[Length] = L'\0';
|
||||
|
||||
|
||||
/*
|
||||
* Choose an adequate terminal front-end to load, and load it
|
||||
*/
|
||||
Status = STATUS_SUCCESS;
|
||||
for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i)
|
||||
{
|
||||
DPRINT("CONSRV: Trying to load %s terminal emulator...\n", FrontEndLoadingMethods[i].FrontEndName);
|
||||
Status = FrontEndLoadingMethods[i].FrontEndLoad(&FrontEnd,
|
||||
&ConsoleInfo,
|
||||
ConsoleStartInfo,
|
||||
ConsoleLeaderProcessId);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("CONSRV: %s terminal emulator loaded successfully\n", FrontEndLoadingMethods[i].FrontEndName);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("CONSRV: Loading %s terminal emulator failed, Status = 0x%08lx , continuing...\n", FrontEndLoadingMethods[i].FrontEndName, Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("CONSRV: Frontend initialized\n");
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* 4. Load the remaining console settings via the registry.
|
||||
*/
|
||||
if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
|
||||
{
|
||||
/*
|
||||
* Either we weren't created by an app launched via a shell-link,
|
||||
* or we failed to load shell-link console properties.
|
||||
* Therefore, load the console infos for the application from the registry.
|
||||
*/
|
||||
ConSrvReadUserSettings(&ConsoleInfo, ConsoleLeaderProcessId);
|
||||
|
||||
/*
|
||||
* Now, update them with the properties the user might gave to us
|
||||
* via the STARTUPINFO structure before calling CreateProcess
|
||||
* (and which was transmitted via the ConsoleStartInfo structure).
|
||||
* We therefore overwrite the values read in the registry.
|
||||
*/
|
||||
if (ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)
|
||||
{
|
||||
ConsoleInfo.ScreenAttrib = (USHORT)ConsoleStartInfo->FillAttribute;
|
||||
}
|
||||
if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
|
||||
{
|
||||
ConsoleInfo.ScreenBufferSize = ConsoleStartInfo->ScreenBufferSize;
|
||||
}
|
||||
if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
|
||||
{
|
||||
// ConsoleInfo.ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
|
||||
ConsoleInfo.ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx;
|
||||
ConsoleInfo.ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set-up the code page */
|
||||
ConsoleInfo.CodePage = GetOEMCP();
|
||||
/******************************************************************************/
|
||||
|
||||
Status = ConDrvInitConsole(&ConsoleHandle,
|
||||
&Console,
|
||||
&ConsoleInfo,
|
||||
ConsoleLeaderProcessId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status);
|
||||
FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ASSERT(Console);
|
||||
DPRINT("Console initialized\n");
|
||||
|
||||
Status = ConDrvRegisterFrontEnd(Console, &FrontEnd);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to register frontend to the given console, Status = 0x%08lx\n", Status);
|
||||
ConDrvDeleteConsole(Console);
|
||||
FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
|
||||
return Status;
|
||||
}
|
||||
DPRINT("FrontEnd registered\n");
|
||||
|
||||
/* Return the newly created console to the caller and a success code too */
|
||||
*NewConsoleHandle = ConsoleHandle;
|
||||
*NewConsole = Console;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConSrvDeleteConsole(PCONSOLE Console)
|
||||
{
|
||||
DPRINT("ConSrvDeleteConsole\n");
|
||||
|
||||
/* Just call the driver. ConSrvDeregisterFrontEnd is called on-demand. */
|
||||
ConDrvDeleteConsole(Console);
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
CSR_API(SrvAllocConsole)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
|
||||
PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
|
||||
|
||||
if (ProcessData->ConsoleHandle != NULL)
|
||||
{
|
||||
DPRINT1("Process already has a console\n");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&AllocConsoleRequest->ConsoleStartInfo,
|
||||
1,
|
||||
sizeof(CONSOLE_START_INFO)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Initialize a new Console owned by the Console Leader Process */
|
||||
Status = ConSrvAllocateConsole(ProcessData,
|
||||
&AllocConsoleRequest->InputHandle,
|
||||
&AllocConsoleRequest->OutputHandle,
|
||||
&AllocConsoleRequest->ErrorHandle,
|
||||
AllocConsoleRequest->ConsoleStartInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Console allocation failed\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Return the console handle and the input wait handle to the caller */
|
||||
AllocConsoleRequest->ConsoleHandle = ProcessData->ConsoleHandle;
|
||||
AllocConsoleRequest->InputWaitHandle = ProcessData->ConsoleEvent;
|
||||
|
||||
/* Set the Property-Dialog and Control-Dispatcher handlers */
|
||||
ProcessData->PropDispatcher = AllocConsoleRequest->PropDispatcher;
|
||||
ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvAttachConsole)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AttachConsoleRequest;
|
||||
PCSR_PROCESS SourceProcess = NULL; // The parent process.
|
||||
PCSR_PROCESS TargetProcess = CsrGetClientThread()->Process; // Ourselves.
|
||||
HANDLE ProcessId = ULongToHandle(AttachConsoleRequest->ProcessId);
|
||||
PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
|
||||
|
||||
TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
|
||||
|
||||
if (TargetProcessData->ConsoleHandle != NULL)
|
||||
{
|
||||
DPRINT1("Process already has a console\n");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Check whether we try to attach to the parent's console */
|
||||
if (ProcessId == ULongToHandle(ATTACH_PARENT_PROCESS))
|
||||
{
|
||||
PROCESS_BASIC_INFORMATION ProcessInfo;
|
||||
ULONG Length = sizeof(ProcessInfo);
|
||||
|
||||
/* Get the real parent's ID */
|
||||
|
||||
Status = NtQueryInformationProcess(TargetProcess->ProcessHandle,
|
||||
ProcessBasicInformation,
|
||||
&ProcessInfo,
|
||||
Length, &Length);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = %lu\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ProcessId = ULongToHandle(ProcessInfo.InheritedFromUniqueProcessId);
|
||||
}
|
||||
|
||||
/* Lock the source process via its PID */
|
||||
Status = CsrLockProcessByClientId(ProcessId, &SourceProcess);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
|
||||
|
||||
if (SourceProcessData->ConsoleHandle == NULL)
|
||||
{
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inherit the console from the parent,
|
||||
* if any, otherwise return an error.
|
||||
*/
|
||||
Status = ConSrvInheritConsole(TargetProcessData,
|
||||
SourceProcessData->ConsoleHandle,
|
||||
TRUE,
|
||||
&AttachConsoleRequest->InputHandle,
|
||||
&AttachConsoleRequest->OutputHandle,
|
||||
&AttachConsoleRequest->ErrorHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Console inheritance failed\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Return the console handle and the input wait handle to the caller */
|
||||
AttachConsoleRequest->ConsoleHandle = TargetProcessData->ConsoleHandle;
|
||||
AttachConsoleRequest->InputWaitHandle = TargetProcessData->ConsoleEvent;
|
||||
|
||||
/* Set the Property-Dialog and Control-Dispatcher handlers */
|
||||
TargetProcessData->PropDispatcher = AttachConsoleRequest->PropDispatcher;
|
||||
TargetProcessData->CtrlDispatcher = AttachConsoleRequest->CtrlDispatcher;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
Quit:
|
||||
/* Unlock the "source" process and exit */
|
||||
CsrUnlockProcess(SourceProcess);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvFreeConsole)
|
||||
{
|
||||
ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleMode(IN PCONSOLE Console,
|
||||
IN PCONSOLE_IO_OBJECT Object,
|
||||
OUT PULONG ConsoleMode);
|
||||
CSR_API(SrvGetConsoleMode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
|
||||
PCONSOLE_IO_OBJECT Object;
|
||||
|
||||
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
ConsoleModeRequest->ConsoleHandle,
|
||||
&Object, NULL, GENERIC_READ, TRUE, 0);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvGetConsoleMode(Object->Console, Object,
|
||||
&ConsoleModeRequest->ConsoleMode);
|
||||
|
||||
ConSrvReleaseObject(Object, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleMode(IN PCONSOLE Console,
|
||||
IN PCONSOLE_IO_OBJECT Object,
|
||||
IN ULONG ConsoleMode);
|
||||
CSR_API(SrvSetConsoleMode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
|
||||
PCONSOLE_IO_OBJECT Object;
|
||||
|
||||
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
ConsoleModeRequest->ConsoleHandle,
|
||||
&Object, NULL, GENERIC_WRITE, TRUE, 0);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleMode(Object->Console, Object,
|
||||
ConsoleModeRequest->ConsoleMode);
|
||||
|
||||
ConSrvReleaseObject(Object, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleTitle(IN PCONSOLE Console,
|
||||
IN OUT PWCHAR Title,
|
||||
IN OUT PULONG BufLength);
|
||||
CSR_API(SrvGetConsoleTitle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&TitleRequest->Title,
|
||||
TitleRequest->Length,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ConDrvGetConsoleTitle(Console,
|
||||
TitleRequest->Title,
|
||||
&TitleRequest->Length);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleTitle(IN PCONSOLE Console,
|
||||
IN PWCHAR Title,
|
||||
IN ULONG BufLength);
|
||||
CSR_API(SrvSetConsoleTitle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&TitleRequest->Title,
|
||||
TitleRequest->Length,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ConDrvSetConsoleTitle(Console,
|
||||
TitleRequest->Title,
|
||||
TitleRequest->Length);
|
||||
|
||||
if (NT_SUCCESS(Status)) ConioChangeTitle(Console);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleCP(IN PCONSOLE Console,
|
||||
OUT PUINT CodePage,
|
||||
IN BOOLEAN InputCP);
|
||||
CSR_API(SrvGetConsoleCP)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
|
||||
ConsoleCPRequest->InputCP ? "Input" : "Output");
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvGetConsoleCP(Console,
|
||||
&ConsoleCPRequest->CodePage,
|
||||
ConsoleCPRequest->InputCP);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvSetConsoleCP(IN PCONSOLE Console,
|
||||
IN UINT CodePage,
|
||||
IN BOOLEAN InputCP);
|
||||
CSR_API(SrvSetConsoleCP)
|
||||
{
|
||||
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
||||
PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
|
||||
ConsoleCPRequest->InputCP ? "Input" : "Output");
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvSetConsoleCP(Console,
|
||||
ConsoleCPRequest->CodePage,
|
||||
ConsoleCPRequest->InputCP);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleProcessList(IN PCONSOLE Console,
|
||||
IN OUT PULONG ProcessIdsList,
|
||||
IN ULONG MaxIdListItems,
|
||||
OUT PULONG ProcessIdsTotal);
|
||||
CSR_API(SrvGetConsoleProcessList)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETPROCESSLIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID)&GetProcessListRequest->pProcessIds,
|
||||
GetProcessListRequest->nMaxIds,
|
||||
sizeof(DWORD)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvGetConsoleProcessList(Console,
|
||||
GetProcessListRequest->pProcessIds,
|
||||
GetProcessListRequest->nMaxIds,
|
||||
&GetProcessListRequest->nProcessIdsTotal);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvGenerateConsoleCtrlEvent)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEventRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = ConDrvConsoleProcessCtrlEvent(Console,
|
||||
GenerateCtrlEventRequest->ProcessGroup,
|
||||
GenerateCtrlEventRequest->Event);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/console.h
|
||||
* PURPOSE: Console Initialization Functions
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// FIXME: Fix compilation
|
||||
struct _CONSOLE;
|
||||
|
||||
NTSTATUS WINAPI
|
||||
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
||||
OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole,
|
||||
IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
|
||||
IN ULONG ConsoleLeaderProcessId);
|
||||
VOID WINAPI ConSrvDeleteConsole(struct _CONSOLE* /* PCONSOLE */ Console);
|
||||
|
||||
NTSTATUS FASTCALL ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
struct _CONSOLE** /* PCONSOLE* */ Console,
|
||||
BOOL LockConsole);
|
||||
VOID FASTCALL ConSrvReleaseConsole(struct _CONSOLE* /* PCONSOLE */ Console,
|
||||
BOOL WasConsoleLocked);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/consrv.h
|
||||
* PURPOSE: Main header - Definitions
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#ifndef __CONSRV_H__
|
||||
#define __CONSRV_H__
|
||||
|
||||
#pragma once
|
||||
|
||||
/* PSDK/NDK Headers */
|
||||
#include <stdarg.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#define _INC_WINDOWS
|
||||
#define COM_NO_WINDOWS_H
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <wingdi.h>
|
||||
#include <winnls.h>
|
||||
#include <winreg.h>
|
||||
#include <wincon.h>
|
||||
#include <winuser.h>
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/exfuncs.h>
|
||||
#include <ndk/iofuncs.h>
|
||||
#include <ndk/mmfuncs.h>
|
||||
#include <ndk/obfuncs.h>
|
||||
#include <ndk/psfuncs.h>
|
||||
#include <ndk/setypes.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
|
||||
/* Public Win32K Headers */
|
||||
#include <ntuser.h>
|
||||
|
||||
/* PSEH for SEH Support */
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
/* CSRSS Header */
|
||||
#include <csr/csrsrv.h>
|
||||
|
||||
/* CONSOLE Headers */
|
||||
#include <win/console.h>
|
||||
#include <win/conmsg.h>
|
||||
|
||||
|
||||
/* Heap Helpers */
|
||||
#include "heap.h"
|
||||
|
||||
/* Globals */
|
||||
extern HINSTANCE ConSrvDllInstance;
|
||||
|
||||
#define ConsoleGetPerProcessData(Process) \
|
||||
((PCONSOLE_PROCESS_DATA)((Process)->ServerData[CONSRV_SERVERDLL_INDEX]))
|
||||
|
||||
typedef struct _CONSOLE_PROCESS_DATA
|
||||
{
|
||||
LIST_ENTRY ConsoleLink;
|
||||
PCSR_PROCESS Process; // Process owning this structure.
|
||||
HANDLE ConsoleEvent;
|
||||
|
||||
HANDLE ConsoleHandle;
|
||||
HANDLE ParentConsoleHandle;
|
||||
|
||||
BOOL ConsoleApp; // TRUE if it is a CUI app, FALSE otherwise.
|
||||
|
||||
RTL_CRITICAL_SECTION HandleTableLock;
|
||||
ULONG HandleTableSize;
|
||||
struct _CONSOLE_IO_HANDLE* /* PCONSOLE_IO_HANDLE */ HandleTable; // Length-varying table
|
||||
|
||||
LPTHREAD_START_ROUTINE CtrlDispatcher;
|
||||
LPTHREAD_START_ROUTINE PropDispatcher; // We hold the property dialog handler there, till all the GUI thingie moves out from CSRSS.
|
||||
} CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA;
|
||||
|
||||
#endif // __CONSRV_H__
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <windef.h>
|
||||
#include <winuser.h>
|
||||
#include "resource.h"
|
||||
|
||||
#include "rsrc.rc"
|
||||
#include "frontends/frontends.rc"
|
||||
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontendctl.c
|
||||
* PURPOSE: Terminal Front-Ends Control
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "conoutput.h"
|
||||
#include "console.h"
|
||||
#include "handle.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* HardwareStateProperty
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Set/Get the value of the HardwareState and switch
|
||||
* between direct video buffer ouput and GDI windowed
|
||||
* output.
|
||||
* ARGUMENTS
|
||||
* Client hands us a CONSOLE_GETSETHWSTATE object.
|
||||
* We use the same object to Request.
|
||||
* NOTE
|
||||
* ConsoleHwState has the correct size to be compatible
|
||||
* with NT's, but values are not.
|
||||
*/
|
||||
#if 0
|
||||
static NTSTATUS FASTCALL
|
||||
SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState)
|
||||
{
|
||||
DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
|
||||
|
||||
if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
|
||||
||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
|
||||
{
|
||||
if (Console->HardwareState != ConsoleHwState)
|
||||
{
|
||||
/* TODO: implement switching from full screen to windowed mode */
|
||||
/* TODO: or back; now simply store the hardware state */
|
||||
Console->HardwareState = ConsoleHwState;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
|
||||
}
|
||||
#endif
|
||||
|
||||
CSR_API(SrvGetConsoleHardwareState)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
HardwareStateRequest->OutputHandle,
|
||||
&Buff,
|
||||
GENERIC_READ,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
HardwareStateRequest->State = Console->HardwareState;
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, TRUE);
|
||||
return Status;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
CSR_API(SrvSetConsoleHardwareState)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
HardwareStateRequest->OutputHandle,
|
||||
&Buff,
|
||||
GENERIC_WRITE,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Setting console hardware state.\n");
|
||||
Console = Buff->Header.Console;
|
||||
Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, TRUE);
|
||||
return Status;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleDisplayMode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
&Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
GetDisplayModeRequest->DisplayMode = ConioGetDisplayMode(Console);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvSetConsoleDisplayMode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
|
||||
PCONSOLE Console;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
|
||||
Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
SetDisplayModeRequest->OutputHandle,
|
||||
&Buff,
|
||||
GENERIC_WRITE,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
|
||||
if (ConioSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
|
||||
{
|
||||
SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetLargestConsoleWindowSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
GetLargestWindowSizeRequest->OutputHandle,
|
||||
&Buff,
|
||||
GENERIC_READ,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
ConioGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvShowConsoleCursor)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
|
||||
PCONSOLE Console;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
|
||||
Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
ShowCursorRequest->OutputHandle,
|
||||
&Buff,
|
||||
GENERIC_WRITE,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
|
||||
ShowCursorRequest->RefCount = ConioShowMouseCursor(Console, ShowCursorRequest->Show);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvSetConsoleCursor)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOL Success;
|
||||
PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
|
||||
PCONSOLE Console;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
|
||||
// FIXME: Tests show that this function is used only for graphics screen buffers
|
||||
// and otherwise it returns false + set last error to invalid handle.
|
||||
// NOTE: I find that behaviour is ridiculous but ok, let's accept that at the moment...
|
||||
Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
SetCursorRequest->OutputHandle,
|
||||
&Buff,
|
||||
GENERIC_WRITE,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
|
||||
Success = ConioSetMouseCursor(Console, SetCursorRequest->hCursor);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, TRUE);
|
||||
return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
CSR_API(SrvConsoleMenuControl)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_MENUCONTROL MenuControlRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.MenuControlRequest;
|
||||
PCONSOLE Console;
|
||||
PCONSOLE_SCREEN_BUFFER Buff;
|
||||
|
||||
Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
MenuControlRequest->OutputHandle,
|
||||
&Buff,
|
||||
GENERIC_WRITE,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
|
||||
MenuControlRequest->hMenu = ConioMenuControl(Console,
|
||||
MenuControlRequest->dwCmdIdLow,
|
||||
MenuControlRequest->dwCmdIdHigh);
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvSetConsoleMenuClose)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOL Success;
|
||||
PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetMenuCloseRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
&Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Success = ConioSetMenuClose(Console, SetMenuCloseRequest->Enable);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleWindow)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
GetWindowRequest->WindowHandle = ConioGetConsoleWindowHandle(Console);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(SrvSetConsoleIcon)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = (ConioChangeIcon(Console, SetIconRequest->WindowIcon)
|
||||
? STATUS_SUCCESS
|
||||
: STATUS_UNSUCCESSFUL);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleSelectionInfo)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
memset(&GetSelectionInfoRequest->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
|
||||
if (Console->Selection.dwFlags != 0)
|
||||
GetSelectionInfoRequest->Info = Console->Selection;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#include "gui/guiterm.rc"
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/consolecpl.h
|
||||
* PURPOSE: GUI front-end settings management - Header for console.dll
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "include/settings.h"
|
||||
#include "guisettings.h"
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontends/gui/graphics.c
|
||||
* PURPOSE: GUI Terminal Front-End - Support for graphics-mode screen-buffers
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/settings.h"
|
||||
#include "guisettings.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
/*
|
||||
* This function supposes that the system clipboard was opened.
|
||||
*/
|
||||
|
||||
// PCONSOLE Console = Buffer->Header.Console;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
/*
|
||||
* This function supposes that the system clipboard was opened.
|
||||
*/
|
||||
|
||||
// PCONSOLE Console = Buffer->Header.Console;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
|
||||
PGUI_CONSOLE_DATA GuiData,
|
||||
HDC hDC,
|
||||
PRECT rc)
|
||||
{
|
||||
if (Buffer->BitMap == NULL) return;
|
||||
|
||||
/* Grab the mutex */
|
||||
NtWaitForSingleObject(Buffer->Mutex, FALSE, NULL);
|
||||
|
||||
/*
|
||||
* The seventh parameter (YSrc) of SetDIBitsToDevice always designates
|
||||
* the Y-coordinate of the "lower-left corner" of the image, be the DIB
|
||||
* in bottom-up or top-down mode.
|
||||
*/
|
||||
SetDIBitsToDevice(hDC,
|
||||
/* Coordinates / size of the repainted rectangle, in the view's frame */
|
||||
rc->left,
|
||||
rc->top,
|
||||
rc->right - rc->left,
|
||||
rc->bottom - rc->top,
|
||||
/* Coordinates / size of the corresponding image portion, in the graphics screen-buffer's frame */
|
||||
Buffer->ViewOrigin.X + rc->left,
|
||||
Buffer->ViewOrigin.Y + rc->top,
|
||||
0,
|
||||
Buffer->ScreenBufferSize.Y, // == Buffer->BitMapInfo->bmiHeader.biHeight
|
||||
Buffer->BitMap,
|
||||
Buffer->BitMapInfo,
|
||||
Buffer->BitMapUsage);
|
||||
|
||||
/* Release the mutex */
|
||||
NtReleaseMutant(Buffer->Mutex, NULL);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,541 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
|
||||
* PURPOSE: GUI Terminal Front-End Settings Management
|
||||
* PROGRAMMERS: Johannes Anderwald
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/settings.h"
|
||||
#include "guisettings.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
VOID GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData);
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOL
|
||||
GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
|
||||
IN LPCWSTR ConsoleTitle,
|
||||
IN DWORD ProcessId)
|
||||
{
|
||||
/*****************************************************
|
||||
* Adapted from ConSrvReadUserSettings in settings.c *
|
||||
*****************************************************/
|
||||
|
||||
BOOL RetVal = FALSE;
|
||||
HKEY hKey;
|
||||
DWORD dwNumSubKeys = 0;
|
||||
DWORD dwIndex;
|
||||
DWORD dwType;
|
||||
WCHAR szValueName[MAX_PATH];
|
||||
DWORD dwValueName;
|
||||
WCHAR szValue[LF_FACESIZE] = L"\0";
|
||||
DWORD Value;
|
||||
DWORD dwValue;
|
||||
|
||||
if (!ConSrvOpenUserSettings(ProcessId,
|
||||
ConsoleTitle,
|
||||
&hKey, KEY_READ,
|
||||
FALSE))
|
||||
{
|
||||
DPRINT("ConSrvOpenUserSettings failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&dwNumSubKeys, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
|
||||
RegCloseKey(hKey);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys);
|
||||
|
||||
for (dwIndex = 0; dwIndex < dwNumSubKeys; dwIndex++)
|
||||
{
|
||||
dwValue = sizeof(Value);
|
||||
dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
|
||||
|
||||
if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, &dwType, (BYTE*)&Value, &dwValue) != ERROR_SUCCESS)
|
||||
{
|
||||
if (dwType == REG_SZ)
|
||||
{
|
||||
/*
|
||||
* Retry in case of string value
|
||||
*/
|
||||
dwValue = sizeof(szValue);
|
||||
dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
|
||||
if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wcscmp(szValueName, L"FaceName"))
|
||||
{
|
||||
SIZE_T Length = min(wcslen(szValue) + 1, LF_FACESIZE); // wcsnlen
|
||||
wcsncpy(TermInfo->FaceName, szValue, LF_FACESIZE);
|
||||
TermInfo->FaceName[Length] = L'\0';
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"FontFamily"))
|
||||
{
|
||||
TermInfo->FontFamily = Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"FontSize"))
|
||||
{
|
||||
TermInfo->FontSize = Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"FontWeight"))
|
||||
{
|
||||
TermInfo->FontWeight = Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"FullScreen"))
|
||||
{
|
||||
TermInfo->FullScreen = Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"WindowPosition"))
|
||||
{
|
||||
TermInfo->AutoPosition = FALSE;
|
||||
TermInfo->WindowOrigin.x = LOWORD(Value);
|
||||
TermInfo->WindowOrigin.y = HIWORD(Value);
|
||||
RetVal = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
BOOL
|
||||
GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
|
||||
IN LPCWSTR ConsoleTitle,
|
||||
IN DWORD ProcessId)
|
||||
{
|
||||
/******************************************************
|
||||
* Adapted from ConSrvWriteUserSettings in settings.c *
|
||||
******************************************************/
|
||||
|
||||
BOOL GlobalSettings = (ConsoleTitle[0] == L'\0');
|
||||
HKEY hKey;
|
||||
DWORD Storage = 0;
|
||||
|
||||
#define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
|
||||
do { \
|
||||
if (GlobalSettings || (!GlobalSettings && (*(Setting) != (DefaultValue)))) \
|
||||
{ \
|
||||
RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegDeleteValue(hKey, (SettingName)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
if (!ConSrvOpenUserSettings(ProcessId,
|
||||
ConsoleTitle,
|
||||
&hKey, KEY_WRITE,
|
||||
TRUE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0'); // wcsnlen
|
||||
SetConsoleSetting(L"FontFamily", REG_DWORD, sizeof(DWORD), &TermInfo->FontFamily, FF_DONTCARE);
|
||||
SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &TermInfo->FontSize, 0);
|
||||
SetConsoleSetting(L"FontWeight", REG_DWORD, sizeof(DWORD), &TermInfo->FontWeight, FW_DONTCARE);
|
||||
|
||||
Storage = TermInfo->FullScreen;
|
||||
SetConsoleSetting(L"FullScreen", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
|
||||
|
||||
if (TermInfo->AutoPosition == FALSE)
|
||||
{
|
||||
Storage = MAKELONG(TermInfo->WindowOrigin.x, TermInfo->WindowOrigin.y);
|
||||
RegSetValueExW(hKey, L"WindowPosition", 0, REG_DWORD, (PBYTE)&Storage, sizeof(DWORD));
|
||||
}
|
||||
else
|
||||
{
|
||||
RegDeleteValue(hKey, L"WindowPosition");
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
|
||||
IN DWORD ProcessId)
|
||||
{
|
||||
/*******************************************************
|
||||
* Adapted from ConSrvGetDefaultSettings in settings.c *
|
||||
*******************************************************/
|
||||
|
||||
if (TermInfo == NULL) return;
|
||||
|
||||
/*
|
||||
* 1. Load the default values
|
||||
*/
|
||||
// wcsncpy(TermInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
|
||||
// TermInfo->FontSize = MAKELONG(12, 8); // 0x0008000C; // font is 8x12
|
||||
// TermInfo->FontSize = MAKELONG(16, 16); // font is 16x16
|
||||
// TermInfo->FontWeight = FW_NORMAL;
|
||||
|
||||
wcsncpy(TermInfo->FaceName, L"Fixedsys", LF_FACESIZE); // HACK: !!
|
||||
// TermInfo->FaceName[0] = L'\0';
|
||||
TermInfo->FontFamily = FF_DONTCARE;
|
||||
TermInfo->FontSize = 0;
|
||||
TermInfo->FontWeight = FW_DONTCARE;
|
||||
TermInfo->UseRasterFonts = TRUE;
|
||||
|
||||
TermInfo->FullScreen = FALSE;
|
||||
TermInfo->ShowWindow = SW_SHOWNORMAL;
|
||||
TermInfo->AutoPosition = TRUE;
|
||||
TermInfo->WindowOrigin.x = 0;
|
||||
TermInfo->WindowOrigin.y = 0;
|
||||
|
||||
/*
|
||||
* 2. Overwrite them with the ones stored in HKCU\Console.
|
||||
* If the HKCU\Console key doesn't exist, create it
|
||||
* and store the default values inside.
|
||||
*/
|
||||
if (!GuiConsoleReadUserSettings(TermInfo, L"", ProcessId))
|
||||
{
|
||||
GuiConsoleWriteUserSettings(TermInfo, L"", ProcessId);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
|
||||
BOOL Defaults)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
|
||||
PCONSOLE_PROCESS_DATA ProcessData;
|
||||
HANDLE hSection = NULL, hClientSection = NULL;
|
||||
LARGE_INTEGER SectionSize;
|
||||
ULONG ViewSize = 0;
|
||||
SIZE_T Length = 0;
|
||||
PCONSOLE_PROPS pSharedInfo = NULL;
|
||||
PGUI_CONSOLE_INFO GuiInfo = NULL;
|
||||
|
||||
DPRINT("GuiConsoleShowConsoleProperties entered\n");
|
||||
|
||||
/*
|
||||
* Create a memory section to share with the applet, and map it.
|
||||
*/
|
||||
/* Holds data for console.dll + console info + terminal-specific info */
|
||||
SectionSize.QuadPart = sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO);
|
||||
Status = NtCreateSection(&hSection,
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
Status = NtMapViewOfSection(hSection,
|
||||
NtCurrentProcess(),
|
||||
(PVOID*)&pSharedInfo,
|
||||
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(hSection);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup the shared console properties structure.
|
||||
*/
|
||||
|
||||
/* Header */
|
||||
pSharedInfo->hConsoleWindow = GuiData->hWindow;
|
||||
pSharedInfo->ShowDefaultParams = Defaults;
|
||||
|
||||
/*
|
||||
* We fill-in the fields only if we display
|
||||
* our properties, not the default ones.
|
||||
*/
|
||||
if (!Defaults)
|
||||
{
|
||||
/* Console information */
|
||||
pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize;
|
||||
pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
|
||||
pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup;
|
||||
pSharedInfo->ci.QuickEdit = Console->QuickEdit;
|
||||
pSharedInfo->ci.InsertMode = Console->InsertMode;
|
||||
pSharedInfo->ci.InputBufferSize = 0;
|
||||
pSharedInfo->ci.ScreenBufferSize = ActiveBuffer->ScreenBufferSize;
|
||||
pSharedInfo->ci.ConsoleSize = ActiveBuffer->ViewSize;
|
||||
pSharedInfo->ci.CursorBlinkOn;
|
||||
pSharedInfo->ci.ForceCursorOff;
|
||||
pSharedInfo->ci.CursorSize = ActiveBuffer->CursorInfo.dwSize;
|
||||
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
|
||||
{
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
|
||||
|
||||
pSharedInfo->ci.ScreenAttrib = Buffer->ScreenDefaultAttrib;
|
||||
pSharedInfo->ci.PopupAttrib = Buffer->PopupDefaultAttrib;
|
||||
}
|
||||
else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
|
||||
{
|
||||
// PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer;
|
||||
DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n");
|
||||
|
||||
// FIXME: Gather defaults from the registry ?
|
||||
pSharedInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
|
||||
pSharedInfo->ci.PopupAttrib = DEFAULT_POPUP_ATTRIB ;
|
||||
}
|
||||
pSharedInfo->ci.CodePage;
|
||||
|
||||
/* GUI Information */
|
||||
pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
|
||||
GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1);
|
||||
Length = min(wcslen(GuiData->GuiInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
|
||||
wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE);
|
||||
GuiInfo->FaceName[Length] = L'\0';
|
||||
GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily;
|
||||
GuiInfo->FontSize = GuiData->GuiInfo.FontSize;
|
||||
GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight;
|
||||
GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts;
|
||||
GuiInfo->FullScreen = GuiData->GuiInfo.FullScreen;
|
||||
/// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition;
|
||||
GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
|
||||
GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin;
|
||||
/* Offsetize */
|
||||
pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo);
|
||||
|
||||
/* Palette */
|
||||
memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors));
|
||||
|
||||
/* Title of the console, original one corresponding to the one set by the console leader */
|
||||
Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1,
|
||||
Console->OriginalTitle.Length / sizeof(WCHAR));
|
||||
wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Length = 0;
|
||||
// FIXME: Load the default parameters from the registry.
|
||||
}
|
||||
|
||||
/* Null-terminate the title */
|
||||
pSharedInfo->ci.ConsoleTitle[Length] = L'\0';
|
||||
|
||||
|
||||
/* Unmap the view */
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo);
|
||||
|
||||
/* Get the console leader process, our client */
|
||||
ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink,
|
||||
CONSOLE_PROCESS_DATA,
|
||||
ConsoleLink);
|
||||
|
||||
/* Duplicate the section handle for the client */
|
||||
Status = NtDuplicateObject(NtCurrentProcess(),
|
||||
hSection,
|
||||
ProcessData->Process->ProcessHandle,
|
||||
&hClientSection,
|
||||
0, 0, DUPLICATE_SAME_ACCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error: Impossible to duplicate section handle for client ; Status = %lu\n", Status);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Start the properties dialog */
|
||||
if (ProcessData->PropDispatcher)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
HANDLE Thread = NULL;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
|
||||
ProcessData->PropDispatcher,
|
||||
(PVOID)hClientSection, 0, NULL);
|
||||
if (NULL == Thread)
|
||||
{
|
||||
DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("ProcessData->PropDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
|
||||
/// WaitForSingleObject(Thread, INFINITE);
|
||||
}
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
CloseHandle(Thread);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = %08X\n", Status);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
Quit:
|
||||
/* We have finished, close the section handle */
|
||||
NtClose(hSection);
|
||||
return;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
|
||||
HANDLE hClientSection,
|
||||
BOOL SaveSettings)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
PCONSOLE_PROCESS_DATA ProcessData;
|
||||
HANDLE hSection = NULL;
|
||||
ULONG ViewSize = 0;
|
||||
PCONSOLE_PROPS pConInfo = NULL;
|
||||
PCONSOLE_INFO ConInfo = NULL;
|
||||
PTERMINAL_INFO TermInfo = NULL;
|
||||
PGUI_CONSOLE_INFO GuiInfo = NULL;
|
||||
|
||||
/* Get the console leader process, our client */
|
||||
ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink,
|
||||
CONSOLE_PROCESS_DATA,
|
||||
ConsoleLink);
|
||||
|
||||
/* Duplicate the section handle for ourselves */
|
||||
Status = NtDuplicateObject(ProcessData->Process->ProcessHandle,
|
||||
hClientSection,
|
||||
NtCurrentProcess(),
|
||||
&hSection,
|
||||
0, 0, DUPLICATE_SAME_ACCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error when mapping client handle, Status = %lu\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get a view of the shared section */
|
||||
Status = NtMapViewOfSection(hSection,
|
||||
NtCurrentProcess(),
|
||||
(PVOID*)&pConInfo,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&ViewSize,
|
||||
ViewUnmap,
|
||||
0,
|
||||
PAGE_READONLY);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error when mapping view of file, Status = %lu\n", Status);
|
||||
NtClose(hSection);
|
||||
return Status;
|
||||
}
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Check that the section is well-sized */
|
||||
if ( (ViewSize < sizeof(CONSOLE_PROPS)) ||
|
||||
(pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) ||
|
||||
(ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) )
|
||||
{
|
||||
DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n");
|
||||
Status = STATUS_INVALID_VIEW_SIZE;
|
||||
_SEH2_YIELD(goto Quit);
|
||||
}
|
||||
|
||||
// TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
|
||||
|
||||
/* Retrieve terminal informations */
|
||||
ConInfo = &pConInfo->ci;
|
||||
TermInfo = &pConInfo->TerminalInfo;
|
||||
GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo);
|
||||
|
||||
/*
|
||||
* If we don't set the default parameters,
|
||||
* apply them, otherwise just save them.
|
||||
*/
|
||||
if (pConInfo->ShowDefaultParams == FALSE)
|
||||
{
|
||||
/* Set the console informations */
|
||||
ConSrvApplyUserSettings(Console, ConInfo);
|
||||
|
||||
/* Set the terminal informations */
|
||||
|
||||
// memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO));
|
||||
|
||||
/* Move the window to the user's values */
|
||||
GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition;
|
||||
GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin;
|
||||
GuiConsoleMoveWindow(GuiData);
|
||||
|
||||
InvalidateRect(GuiData->hWindow, NULL, TRUE);
|
||||
|
||||
/*
|
||||
* Apply full-screen mode.
|
||||
*/
|
||||
GuiData->GuiInfo.FullScreen = GuiInfo->FullScreen;
|
||||
// TODO: Apply it really
|
||||
}
|
||||
|
||||
/*
|
||||
* Save settings if needed
|
||||
*/
|
||||
// FIXME: Do it in the console properties applet ??
|
||||
if (SaveSettings)
|
||||
{
|
||||
DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess);
|
||||
ConSrvWriteUserSettings(ConInfo, ProcessId);
|
||||
GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId);
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
DPRINT1("GuiApplyUserSettings - Caught an exception, Status = %08X\n", Status);
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
Quit:
|
||||
/* Finally, close the section and return */
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), pConInfo);
|
||||
NtClose(hSection);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/guisettings.h
|
||||
* PURPOSE: GUI front-end settings management
|
||||
* PROGRAMMERS: Johannes Anderwald
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*
|
||||
* NOTE: Also used by console.dll
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WM_APP
|
||||
#define WM_APP 0x8000
|
||||
#endif
|
||||
#define PM_APPLY_CONSOLE_INFO (WM_APP + 100)
|
||||
|
||||
/* STRUCTURES *****************************************************************/
|
||||
|
||||
typedef struct _GUI_CONSOLE_INFO
|
||||
{
|
||||
// FONTSIGNATURE FontSignature;
|
||||
WCHAR FaceName[LF_FACESIZE];
|
||||
UINT FontFamily;
|
||||
DWORD FontSize;
|
||||
DWORD FontWeight;
|
||||
BOOL UseRasterFonts;
|
||||
|
||||
BOOL FullScreen; /* Whether the console is displayed in full-screen or windowed mode */
|
||||
// ULONG HardwareState; /* _GDI_MANAGED, _DIRECT */
|
||||
|
||||
WORD ShowWindow;
|
||||
BOOL AutoPosition;
|
||||
POINT WindowOrigin;
|
||||
} GUI_CONSOLE_INFO, *PGUI_CONSOLE_INFO;
|
||||
|
||||
#ifndef CONSOLE_H__ // If we aren't included by console.dll
|
||||
|
||||
typedef struct _GUI_CONSOLE_DATA
|
||||
{
|
||||
CRITICAL_SECTION Lock;
|
||||
HANDLE hGuiInitEvent;
|
||||
BOOL WindowSizeLock;
|
||||
POINT OldCursor;
|
||||
|
||||
HWND hWindow; /* Handle to the console's window */
|
||||
HICON hIcon; /* Handle to the console's icon (big) */
|
||||
HICON hIconSm; /* Handle to the console's icon (small) */
|
||||
|
||||
HCURSOR hCursor; /* Handle to the mouse cursor */
|
||||
INT MouseCursorRefCount; /* The reference counter associated with the mouse cursor. >= 0 and the cursor is shown; < 0 and the cursor is hidden. */
|
||||
BOOL IgnoreNextMouseSignal; /* Used in cases where we don't want to treat a mouse signal */
|
||||
|
||||
BOOL IsCloseButtonEnabled; /* TRUE if the Close button and the corresponding system menu item are enabled (default), FALSE otherwise */
|
||||
UINT cmdIdLow ; /* Lowest menu id of the user-reserved menu id range */
|
||||
UINT cmdIdHigh; /* Highest menu id of the user-reserved menu id range */
|
||||
|
||||
// COLORREF Colors[16];
|
||||
|
||||
// PVOID ScreenBuffer; /* Hardware screen buffer */
|
||||
|
||||
HFONT Font;
|
||||
UINT CharWidth;
|
||||
UINT CharHeight;
|
||||
|
||||
PCONSOLE Console; /* Pointer to the owned console */
|
||||
GUI_CONSOLE_INFO GuiInfo; /* GUI terminal settings */
|
||||
} GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOL
|
||||
GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
|
||||
IN LPCWSTR ConsoleTitle,
|
||||
IN DWORD ProcessId);
|
||||
BOOL
|
||||
GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
|
||||
IN LPCWSTR ConsoleTitle,
|
||||
IN DWORD ProcessId);
|
||||
VOID
|
||||
GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
|
||||
IN DWORD ProcessId);
|
||||
VOID
|
||||
GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
|
||||
BOOL Defaults);
|
||||
NTSTATUS
|
||||
GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
|
||||
HANDLE hClientSection,
|
||||
BOOL SaveSettings);
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontends/gui/guiterm.h
|
||||
* PURPOSE: GUI Terminal Front-End
|
||||
* PROGRAMMERS: Gé van Geldorp
|
||||
* Johannes Anderwald
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CONGUI_MIN_WIDTH 10
|
||||
#define CONGUI_MIN_HEIGHT 10
|
||||
#define CONGUI_UPDATE_TIME 0
|
||||
#define CONGUI_UPDATE_TIMER 1
|
||||
|
||||
#define CURSOR_BLINK_TIME 500
|
||||
|
||||
NTSTATUS FASTCALL GuiInitConsole(PCONSOLE Console,
|
||||
/*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
|
||||
PCONSOLE_INFO ConsoleInfo,
|
||||
DWORD ProcessId,
|
||||
LPCWSTR IconPath,
|
||||
INT IconIndex);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <windef.h>
|
||||
#include <winuser.h>
|
||||
#include "resource.h"
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
|
||||
// #define REACTOS_VERSION_DLL
|
||||
// #define REACTOS_STR_FILE_DESCRIPTION "ReactOS Console Server & Terminal Emulator DLL"
|
||||
// #define REACTOS_STR_INTERNAL_NAME "consrv"
|
||||
// #define REACTOS_STR_ORIGINAL_FILENAME "consrv.dll"
|
||||
// #include <reactos/version.rc>
|
||||
|
||||
// IDI_TERMINAL ICON DISCARDABLE "res/terminal.ico"
|
||||
IDI_TERMINAL ICON DISCARDABLE "frontends/gui/res/terminal.ico"
|
||||
|
||||
#include "rsrc.rc"
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS subsystem
|
||||
* FILE: win32ss/user/winsrv/consrv/lang/bg-BG.rc
|
||||
* PURPOSE: Bulgarian resource file
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Обработка"
|
||||
IDS_MARK "Отбелязване"
|
||||
IDS_COPY "Запомняне\tEnter"
|
||||
IDS_PASTE "Поставяне"
|
||||
IDS_SELECTALL "Избор на всичко"
|
||||
IDS_SCROLL "Прелистване"
|
||||
IDS_FIND "Търсене..."
|
||||
IDS_DEFAULTS "Подразбирани"
|
||||
IDS_PROPERTIES "Свойства"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Прелистване тук"
|
||||
IDS_SCROLLTOP "Прелистване до горе"
|
||||
IDS_SCROLLBOTTOM "Прелистване до долу"
|
||||
IDS_SCROLLPAGE_UP "Горна страница"
|
||||
IDS_SCROLLPAGE_DOWN "Долна страница"
|
||||
IDS_SCROLLUP "Прелистване нагоре"
|
||||
IDS_SCROLLDOWN "Прелистване надолу"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* FILE: win32ss/user/winsrv/consrv/lang/cs-CZ.rc
|
||||
* TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
|
||||
* UPDATED: 2011-04-09
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Upravit"
|
||||
IDS_MARK "Označit"
|
||||
IDS_COPY "Kopírovat\tEnter"
|
||||
IDS_PASTE "Vložit"
|
||||
IDS_SELECTALL "Označit vše"
|
||||
IDS_SCROLL "Posunout"
|
||||
IDS_FIND "Najít..."
|
||||
IDS_DEFAULTS "Výchozí"
|
||||
IDS_PROPERTIES "Vlastnosti"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Posunout sem"
|
||||
IDS_SCROLLTOP "Posunout na začátek"
|
||||
IDS_SCROLLBOTTOM "Posunout na konec"
|
||||
IDS_SCROLLPAGE_UP "O stránku výše"
|
||||
IDS_SCROLLPAGE_DOWN "O stránku níže"
|
||||
IDS_SCROLLUP "Posunout nahoru"
|
||||
IDS_SCROLLDOWN "Posunout dolů"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Bearbeiten"
|
||||
IDS_MARK "Markieren"
|
||||
IDS_COPY "Kopieren\tEnter"
|
||||
IDS_PASTE "Einfügen"
|
||||
IDS_SELECTALL "Alles auswählen"
|
||||
IDS_SCROLL "Scrollen"
|
||||
IDS_FIND "Suchen..."
|
||||
IDS_DEFAULTS "Standardwerte"
|
||||
IDS_PROPERTIES "Eigenschaften"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Hier scrollen"
|
||||
IDS_SCROLLTOP "Ganz nach oben scrollen"
|
||||
IDS_SCROLLBOTTOM "Ganz nach unten scrollen"
|
||||
IDS_SCROLLPAGE_UP "Seite nach oben"
|
||||
IDS_SCROLLPAGE_DOWN "Seite nach unten"
|
||||
IDS_SCROLLUP "Nach oben scrollen"
|
||||
IDS_SCROLLDOWN "Nach unten scrollen"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Eingabeaufforderung"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_GREEK, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Επεξεργασία"
|
||||
IDS_MARK "Μαρκάρισμα"
|
||||
IDS_COPY "Αντιγραφή\tEnter"
|
||||
IDS_PASTE "Επικόλληση"
|
||||
IDS_SELECTALL "Επιλογή όλων"
|
||||
IDS_SCROLL "Κύλιση"
|
||||
IDS_FIND "Εύρεση..."
|
||||
IDS_DEFAULTS "Προεπιλογή"
|
||||
IDS_PROPERTIES "Ιδιότητες"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Κύλιση εδώ"
|
||||
IDS_SCROLLTOP "Αρχή"
|
||||
IDS_SCROLLBOTTOM "Τέλος"
|
||||
IDS_SCROLLPAGE_UP "Προηγούμενη σελίδα"
|
||||
IDS_SCROLLPAGE_DOWN "Επόμενη σελίδα"
|
||||
IDS_SCROLLUP "Κύλιση πάνω"
|
||||
IDS_SCROLLDOWN "Κύλιση κάτω"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Edit"
|
||||
IDS_MARK "Mark"
|
||||
IDS_COPY "Copy\tEnter"
|
||||
IDS_PASTE "Paste"
|
||||
IDS_SELECTALL "Select All"
|
||||
IDS_SCROLL "Scroll"
|
||||
IDS_FIND "Find..."
|
||||
IDS_DEFAULTS "Defaults"
|
||||
IDS_PROPERTIES "Properties"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Scroll here"
|
||||
IDS_SCROLLTOP "Scroll top"
|
||||
IDS_SCROLLBOTTOM "Scroll bottom"
|
||||
IDS_SCROLLPAGE_UP "Page up"
|
||||
IDS_SCROLLPAGE_DOWN "Page down"
|
||||
IDS_SCROLLUP "Scroll up"
|
||||
IDS_SCROLLDOWN "Scroll down"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Spanish Language resource file
|
||||
* Traducido por: Javier Remacha 2008-26-01
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Editar"
|
||||
IDS_MARK "Marcar"
|
||||
IDS_COPY "Copiar\tIntroducir"
|
||||
IDS_PASTE "Pegar"
|
||||
IDS_SELECTALL "Seleccionar Todo"
|
||||
IDS_SCROLL "Desplazar"
|
||||
IDS_FIND "Buscar..."
|
||||
IDS_DEFAULTS "Por defecto"
|
||||
IDS_PROPERTIES "Propiedades"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Desplazar aquí"
|
||||
IDS_SCROLLTOP "Desplazar hasta arriba"
|
||||
IDS_SCROLLBOTTOM "Desplazar hasta abajo"
|
||||
IDS_SCROLLPAGE_UP "Subir página"
|
||||
IDS_SCROLLPAGE_DOWN "Bajar página"
|
||||
IDS_SCROLLUP "Desplazar arriba"
|
||||
IDS_SCROLLDOWN "Desplazar abajo"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,28 @@
|
||||
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||
|
||||
/* Fixme : Translation could be really improved, with context
|
||||
La traduction pourrait réellement être améliorée grâce au contexte */
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Éditer"
|
||||
IDS_MARK "Marquer"
|
||||
IDS_COPY "Copier\tEntrée"
|
||||
IDS_PASTE "Coller"
|
||||
IDS_SELECTALL "Tout sélectionner"
|
||||
IDS_SCROLL "Défiler"
|
||||
IDS_FIND "Trouver..."
|
||||
IDS_DEFAULTS "Défauts"
|
||||
IDS_PROPERTIES "Propriétés"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Défiler ici"
|
||||
IDS_SCROLLTOP "Défiler tout en haut"
|
||||
IDS_SCROLLBOTTOM "Défiler tout en bas"
|
||||
IDS_SCROLLPAGE_UP "Page précédente"
|
||||
IDS_SCROLLPAGE_DOWN "Page suivante"
|
||||
IDS_SCROLLUP "Défiler en haut"
|
||||
IDS_SCROLLDOWN "Défiler en bas"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "ערוך"
|
||||
IDS_MARK "סמן"
|
||||
IDS_COPY "העתק\tEnter"
|
||||
IDS_PASTE "הדבק"
|
||||
IDS_SELECTALL "בחר הכל"
|
||||
IDS_SCROLL "גלול"
|
||||
IDS_FIND "מצא..."
|
||||
IDS_DEFAULTS "ברירת מחדל"
|
||||
IDS_PROPERTIES "מאפיינים"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "גלול לכאן"
|
||||
IDS_SCROLLTOP "גלול למעלה"
|
||||
IDS_SCROLLBOTTOM "גלול למטה"
|
||||
IDS_SCROLLPAGE_UP "עמוד מעלה"
|
||||
IDS_SCROLLPAGE_DOWN "עמוד מטה"
|
||||
IDS_SCROLLUP "גלול מעלה"
|
||||
IDS_SCROLLDOWN "גלול מטה"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Edit"
|
||||
IDS_MARK "Tandai"
|
||||
IDS_COPY "Copy\tEnter"
|
||||
IDS_PASTE "Paste"
|
||||
IDS_SELECTALL "Pilih Semua"
|
||||
IDS_SCROLL "Gulung"
|
||||
IDS_FIND "Cari..."
|
||||
IDS_DEFAULTS "Standar"
|
||||
IDS_PROPERTIES "Properti"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Gulung ke Sini"
|
||||
IDS_SCROLLTOP "Gulung ke Atas"
|
||||
IDS_SCROLLBOTTOM "Gulung ke Bawah"
|
||||
IDS_SCROLLPAGE_UP "Halaman Naik"
|
||||
IDS_SCROLLPAGE_DOWN "Halaman Turun"
|
||||
IDS_SCROLLUP "Gulung Naik"
|
||||
IDS_SCROLLDOWN "Gulung Turun"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Client/Server Runtime subsystem
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: win32ss/user/winsrv/consrv/lang/it-IT.rc
|
||||
* PURPOSE: Italian Translation
|
||||
* PROGRAMMERS:
|
||||
* Copyright (C) 2007 Daniele Forsi (dforsi at gmail.com) Italian Translation
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Modifica"
|
||||
IDS_MARK "Seleziona"
|
||||
IDS_COPY "Copia\tInvio"
|
||||
IDS_PASTE "Incolla"
|
||||
IDS_SELECTALL "Seleziona tutto"
|
||||
IDS_SCROLL "Scorri"
|
||||
IDS_FIND "Trova..."
|
||||
IDS_DEFAULTS "Impostazioni predefinite"
|
||||
IDS_PROPERTIES "Proprietà"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Scorri qui"
|
||||
IDS_SCROLLTOP "Scorri in cima"
|
||||
IDS_SCROLLBOTTOM "Scorri in fondo"
|
||||
IDS_SCROLLPAGE_UP "Pagina sù"
|
||||
IDS_SCROLLPAGE_DOWN "Pagina giù"
|
||||
IDS_SCROLLUP "Scorri sù"
|
||||
IDS_SCROLLDOWN "Scorri giù"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "編集"
|
||||
IDS_MARK "範囲指定"
|
||||
IDS_COPY "コピー\tEnter"
|
||||
IDS_PASTE "貼り付け"
|
||||
IDS_SELECTALL "すべて選択"
|
||||
IDS_SCROLL "スクロール"
|
||||
IDS_FIND "検索..."
|
||||
IDS_DEFAULTS "規定値"
|
||||
IDS_PROPERTIES "プロパティ"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "ここにスクロール"
|
||||
IDS_SCROLLTOP "一番上にスクロール"
|
||||
IDS_SCROLLBOTTOM "一番下にスクロール"
|
||||
IDS_SCROLLPAGE_UP "Page up"
|
||||
IDS_SCROLLPAGE_DOWN "Page down"
|
||||
IDS_SCROLLUP "上にスクロール"
|
||||
IDS_SCROLLDOWN "下にスクロール"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Rediger"
|
||||
IDS_MARK "Merk"
|
||||
IDS_COPY "Kopier\tEnter"
|
||||
IDS_PASTE "Lim inn"
|
||||
IDS_SELECTALL "Velg alt"
|
||||
IDS_SCROLL "Rull"
|
||||
IDS_FIND "Finn..."
|
||||
IDS_DEFAULTS "Standard"
|
||||
IDS_PROPERTIES "Egenskaper"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Rull her"
|
||||
IDS_SCROLLTOP "Rull til toppen"
|
||||
IDS_SCROLLBOTTOM "Rull knapp"
|
||||
IDS_SCROLLPAGE_UP "Side opp"
|
||||
IDS_SCROLLPAGE_DOWN "Side ned"
|
||||
IDS_SCROLLUP "Rull opp"
|
||||
IDS_SCROLLDOWN "Rull ned"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* translated by xrogers
|
||||
* [email protected]
|
||||
* https://sourceforge.net/projects/reactospl
|
||||
* translation update by Olaf Siejka (Caemyr), Apr 2011
|
||||
* UTF-8 conversion by Caemyr (May, 2011)
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Edytuj"
|
||||
IDS_MARK "Zaznacz"
|
||||
IDS_COPY "Kopiuj\tWejdź"
|
||||
IDS_PASTE "Wklej"
|
||||
IDS_SELECTALL "Zaznacz wszystko"
|
||||
IDS_SCROLL "Przewiń"
|
||||
IDS_FIND "Znajdź..."
|
||||
IDS_DEFAULTS "Ustawienia domyślne"
|
||||
IDS_PROPERTIES "Właściwości"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Przewiń tutaj"
|
||||
IDS_SCROLLTOP "Przewiń na początek"
|
||||
IDS_SCROLLBOTTOM "Przewiń na koniec"
|
||||
IDS_SCROLLPAGE_UP "Poprzednia strona"
|
||||
IDS_SCROLLPAGE_DOWN "Następna strona"
|
||||
IDS_SCROLLUP "Przewiń do góry"
|
||||
IDS_SCROLLDOWN "Przewiń na dół"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "Konsola ReactOS"
|
||||
END
|
||||
@@ -0,0 +1,28 @@
|
||||
/* Translation and UTF-8 Conversion by mkbu95 <[email protected]> (May, 2012) */
|
||||
|
||||
LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Editar"
|
||||
IDS_MARK "Marcar"
|
||||
IDS_COPY "Copiar\tEnter"
|
||||
IDS_PASTE "Colar"
|
||||
IDS_SELECTALL "Selecionar Tudo"
|
||||
IDS_SCROLL "Rolar"
|
||||
IDS_FIND "Procurar..."
|
||||
IDS_DEFAULTS "Padrões"
|
||||
IDS_PROPERTIES "Propriedades"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Rolar aqui"
|
||||
IDS_SCROLLTOP "Rolar até o topo"
|
||||
IDS_SCROLLBOTTOM "Rolar até o fim"
|
||||
IDS_SCROLLPAGE_UP "Page up"
|
||||
IDS_SCROLLPAGE_DOWN "Page down"
|
||||
IDS_SCROLLUP "Scroll up"
|
||||
IDS_SCROLLDOWN "Scroll down"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* FILE: win32ss/user/winsrv/consrv/lang/ro-RO.rc
|
||||
* ReactOS Project (http://www.reactos.org)
|
||||
* TRANSLATOR: Fulea Ștefan (PM on ReactOS Forum at fulea.stefan)
|
||||
* CHANGE LOG: 2011-10-16 initial translation
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Editare"
|
||||
IDS_MARK "Marchează"
|
||||
IDS_COPY "Copiază\tEnter"
|
||||
IDS_PASTE "Lipește"
|
||||
IDS_SELECTALL "Selectează tot"
|
||||
IDS_SCROLL "Derulează"
|
||||
IDS_FIND "Găsire…"
|
||||
IDS_DEFAULTS "Implicite"
|
||||
IDS_PROPERTIES "Proprietăți"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Derulează aici"
|
||||
IDS_SCROLLTOP "Derulează la început"
|
||||
IDS_SCROLLBOTTOM "Derulează la sfârșit"
|
||||
IDS_SCROLLPAGE_UP "Pagina anterioară"
|
||||
IDS_SCROLLPAGE_DOWN "Pagina următoare"
|
||||
IDS_SCROLLUP "Derulează în sus"
|
||||
IDS_SCROLLDOWN "Derulează în jos"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Изменить"
|
||||
IDS_MARK "Пометить"
|
||||
IDS_COPY "Копировать\tEnter"
|
||||
IDS_PASTE "Вставить"
|
||||
IDS_SELECTALL "Выделить все"
|
||||
IDS_SCROLL "Прокрутить"
|
||||
IDS_FIND "Искать..."
|
||||
IDS_DEFAULTS "Умолчания"
|
||||
IDS_PROPERTIES "Свойства"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Scroll Here"
|
||||
IDS_SCROLLTOP "Scroll Top"
|
||||
IDS_SCROLLBOTTOM "Прокрутить вниз"
|
||||
IDS_SCROLLPAGE_UP "Вверх страницы"
|
||||
IDS_SCROLLPAGE_DOWN "Вниз страницы"
|
||||
IDS_SCROLLUP "Прокрутить вверх"
|
||||
IDS_SCROLLDOWN "Scroll Down"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,31 @@
|
||||
/* TRANSLATOR: Mário Kačmár /Mario Kacmar/ aka Kario ([email protected])
|
||||
* DATE OF TR: 29-05-2008
|
||||
* LastChange: 12-04-2011
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Upraviť"
|
||||
IDS_MARK "Označiť"
|
||||
IDS_COPY "Kopírovať\tEnter"
|
||||
IDS_PASTE "Vložiť"
|
||||
IDS_SELECTALL "Vybrať všetko"
|
||||
IDS_SCROLL "Rolovať"
|
||||
IDS_FIND "Nájsť..." // Find
|
||||
IDS_DEFAULTS "Predvolené" // Defaults
|
||||
IDS_PROPERTIES "Vlastnosti"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Rolovať sem"
|
||||
IDS_SCROLLTOP "K hornému okraju"
|
||||
IDS_SCROLLBOTTOM "K dolnému okraju"
|
||||
IDS_SCROLLPAGE_UP "O stránku vyššie"
|
||||
IDS_SCROLLPAGE_DOWN "O stránku nižšie"
|
||||
IDS_SCROLLUP "Rolovať nahor"
|
||||
IDS_SCROLLDOWN "Rolovať nadol"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS subsystem
|
||||
* FILE: win32ss/user/winsrv/consrv/lang/sv-SE.rc
|
||||
* PURPOSE: Swedish resource file
|
||||
* Translation: Jaix Bly
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Redigera"
|
||||
IDS_MARK "Markera"
|
||||
IDS_COPY "Kopiera\tEnter"
|
||||
IDS_PASTE "Klistra in"
|
||||
IDS_SELECTALL "Markera Allt"
|
||||
IDS_SCROLL "Skrolla"
|
||||
IDS_FIND "Sök..."
|
||||
IDS_DEFAULTS "Ursprunglig"
|
||||
IDS_PROPERTIES "Egenskaper"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Skrolla hit"
|
||||
IDS_SCROLLTOP "Skrolla till topp"
|
||||
IDS_SCROLLBOTTOM "Skrolla till botten"
|
||||
IDS_SCROLLPAGE_UP "Sida upp"
|
||||
IDS_SCROLLPAGE_DOWN "Sida ner"
|
||||
IDS_SCROLLUP "Skrolla upp"
|
||||
IDS_SCROLLDOWN "Skrolla ner"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Turkish resources
|
||||
*
|
||||
* Copyright 2012 Arda Tanrikulu <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Düzenle"
|
||||
IDS_MARK "İşaretle"
|
||||
IDS_COPY "Kopyala\tEnter"
|
||||
IDS_PASTE "Yapıştır"
|
||||
IDS_SELECTALL "Tümünü Seç"
|
||||
IDS_SCROLL "Yuvarla"
|
||||
IDS_FIND "Bul..."
|
||||
IDS_DEFAULTS "Varsayılanlar"
|
||||
IDS_PROPERTIES "Özellikler"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Buraya yuvarla"
|
||||
IDS_SCROLLTOP "Üste yuvarla"
|
||||
IDS_SCROLLBOTTOM "Alta yuvarla"
|
||||
IDS_SCROLLPAGE_UP "Sayfa yukarı"
|
||||
IDS_SCROLLPAGE_DOWN "Sayfa aşağı"
|
||||
IDS_SCROLLUP "Yukarı yuvarla"
|
||||
IDS_SCROLLDOWN "Aşağı yuvarla"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS subsystem
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: win32ss/user/winsrv/consrv/lang/uk-UA.rc
|
||||
* PURPOSE: Ukraianian resource file
|
||||
* TRANSLATOR: Artem Reznikov
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Редагувати"
|
||||
IDS_MARK "Виділити"
|
||||
IDS_COPY "Копіювати\tEnter"
|
||||
IDS_PASTE "Вставити"
|
||||
IDS_SELECTALL "Виділити все"
|
||||
IDS_SCROLL "Прокрутити"
|
||||
IDS_FIND "Знайти..."
|
||||
IDS_DEFAULTS "Замовчування"
|
||||
IDS_PROPERTIES "Властивості"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "Прокрутити сюди"
|
||||
IDS_SCROLLTOP "Прокрутити на початок"
|
||||
IDS_SCROLLBOTTOM "Прокрутити на кінець"
|
||||
IDS_SCROLLPAGE_UP "Попередня сотрінка"
|
||||
IDS_SCROLLPAGE_DOWN "Наступна сторінка"
|
||||
IDS_SCROLLUP "Прокрутити догори"
|
||||
IDS_SCROLLDOWN "Прокрутити донизу"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "编辑"
|
||||
IDS_MARK "标记"
|
||||
IDS_COPY "复制\tEnter"
|
||||
IDS_PASTE "黏贴"
|
||||
IDS_SELECTALL "全部选择"
|
||||
IDS_SCROLL "滚动"
|
||||
IDS_FIND "查找..."
|
||||
IDS_DEFAULTS "默认"
|
||||
IDS_PROPERTIES "属性"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "滚动到此"
|
||||
IDS_SCROLLTOP "滚动至顶端"
|
||||
IDS_SCROLLBOTTOM "滚动至末端"
|
||||
IDS_SCROLLPAGE_UP "上一页"
|
||||
IDS_SCROLLPAGE_DOWN "下一页"
|
||||
IDS_SCROLLUP "向上滚动"
|
||||
IDS_SCROLLDOWN "向下滚动"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,26 @@
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "編輯"
|
||||
IDS_MARK "標記"
|
||||
IDS_COPY "複製\tEnter"
|
||||
IDS_PASTE "黏貼"
|
||||
IDS_SELECTALL "全部選擇"
|
||||
IDS_SCROLL "滾動"
|
||||
IDS_FIND "尋找..."
|
||||
IDS_DEFAULTS "預設"
|
||||
IDS_PROPERTIES "屬性"
|
||||
|
||||
/*
|
||||
IDS_SCROLLHERE "滾動到此 "
|
||||
IDS_SCROLLTOP "滾動到頂置"
|
||||
IDS_SCROLLBOTTOM "滾動到末端"
|
||||
IDS_SCROLLPAGE_UP "上一頁"
|
||||
IDS_SCROLLPAGE_DOWN "下一頁"
|
||||
IDS_SCROLLUP "向上滾動"
|
||||
IDS_SCROLLDOWN "向下滾動"
|
||||
*/
|
||||
|
||||
IDS_TERMINAL_TITLE "ReactOS Console"
|
||||
END
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 231 KiB |
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/resource.h
|
||||
* PURPOSE: Resource #defines
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ID_SYSTEM_EDIT_MARK 1001
|
||||
#define ID_SYSTEM_EDIT_COPY 1002
|
||||
#define ID_SYSTEM_EDIT_PASTE 1003
|
||||
#define ID_SYSTEM_EDIT_SELECTALL 1004
|
||||
#define ID_SYSTEM_EDIT_SCROLL 1005
|
||||
#define ID_SYSTEM_EDIT_FIND 1006
|
||||
#define ID_SYSTEM_DEFAULTS 1007
|
||||
#define ID_SYSTEM_PROPERTIES 1008
|
||||
|
||||
#define NCPOPUP_MENU 103
|
||||
|
||||
#define IDS_EDIT 204
|
||||
#define IDS_MARK 205
|
||||
#define IDS_COPY 206
|
||||
#define IDS_PASTE 207
|
||||
#define IDS_SELECTALL 208
|
||||
#define IDS_SCROLL 209
|
||||
#define IDS_FIND 210
|
||||
#define IDS_DEFAULTS 211
|
||||
#define IDS_PROPERTIES 212
|
||||
|
||||
// Scrollbar resource ids. Unused.
|
||||
/*
|
||||
#define IDS_SCROLLHERE 304
|
||||
#define IDS_SCROLLTOP 305
|
||||
#define IDS_SCROLLBOTTOM 306
|
||||
#define IDS_SCROLLPAGE_UP 307
|
||||
#define IDS_SCROLLPAGE_DOWN 308
|
||||
#define IDS_SCROLLUP 309
|
||||
#define IDS_SCROLLDOWN 310
|
||||
*/
|
||||
|
||||
#define IDI_TERMINAL 1
|
||||
#define IDS_TERMINAL_TITLE 400
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,70 @@
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
|
||||
// UTF-8
|
||||
#pragma code_page(65001)
|
||||
#ifdef LANGUAGE_BG_BG
|
||||
#include "lang/bg-BG.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_CS_CZ
|
||||
#include "lang/cs-CZ.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_DE_DE
|
||||
#include "lang/de-DE.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_EL_GR
|
||||
#include "lang/el-GR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_EN_US
|
||||
#include "lang/en-US.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ES_ES
|
||||
#include "lang/es-ES.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_FR_FR
|
||||
#include "lang/fr-FR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_HE_IL
|
||||
#include "lang/he-IL.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ID_ID
|
||||
#include "lang/id-ID.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_IT_IT
|
||||
#include "lang/it-IT.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_JA_JP
|
||||
#include "lang/ja-JP.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_NB_NO
|
||||
#include "lang/no-NO.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_PL_PL
|
||||
#include "lang/pl-PL.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_PT_BR
|
||||
#include "lang/pt-BR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_RO_RO
|
||||
#include "lang/ro-RO.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_RU_RU
|
||||
#include "lang/ru-RU.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_SK_SK
|
||||
#include "lang/sk-SK.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_SV_SE
|
||||
#include "lang/sv-SE.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_TR_TR
|
||||
#include "lang/tr-TR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_UK_UA
|
||||
#include "lang/uk-UA.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ZH_CN
|
||||
#include "lang/zh-CN.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ZH_TW
|
||||
#include "lang/zh-TW.rc"
|
||||
#endif
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontends/gui/text.c
|
||||
* PURPOSE: GUI Terminal Front-End - Support for text-mode screen-buffers
|
||||
* PROGRAMMERS: Gé van Geldorp
|
||||
* Johannes Anderwald
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/settings.h"
|
||||
#include "guisettings.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
/*
|
||||
* This function supposes that the system clipboard was opened.
|
||||
*/
|
||||
|
||||
PCONSOLE Console = Buffer->Header.Console;
|
||||
|
||||
/*
|
||||
* Pressing the Shift key while copying text, allows us to copy
|
||||
* text without newline characters (inline-text copy mode).
|
||||
*/
|
||||
BOOL InlineCopyMode = (GetKeyState(VK_SHIFT) & 0x8000);
|
||||
|
||||
HANDLE hData;
|
||||
PCHAR_INFO ptr;
|
||||
LPWSTR data, dstPos;
|
||||
ULONG selWidth, selHeight;
|
||||
ULONG xPos, yPos, size;
|
||||
|
||||
selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
|
||||
selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
|
||||
DPRINT("Selection is (%d|%d) to (%d|%d)\n",
|
||||
Console->Selection.srSelection.Left,
|
||||
Console->Selection.srSelection.Top,
|
||||
Console->Selection.srSelection.Right,
|
||||
Console->Selection.srSelection.Bottom);
|
||||
|
||||
/* Basic size for one line... */
|
||||
size = selWidth;
|
||||
/* ... and for the other lines, add newline characters if needed. */
|
||||
if (selHeight > 0)
|
||||
{
|
||||
/*
|
||||
* If we are not in inline-text copy mode, each selected line must
|
||||
* finish with \r\n . Otherwise, the lines will be just concatenated.
|
||||
*/
|
||||
size += (selWidth + (!InlineCopyMode ? 2 : 0)) * (selHeight - 1);
|
||||
}
|
||||
size += 1; /* Null-termination */
|
||||
size *= sizeof(WCHAR);
|
||||
|
||||
/* Allocate memory, it will be passed to the system and may not be freed here */
|
||||
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
|
||||
if (hData == NULL) return;
|
||||
|
||||
data = GlobalLock(hData);
|
||||
if (data == NULL) return;
|
||||
|
||||
DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
|
||||
dstPos = data;
|
||||
|
||||
for (yPos = 0; yPos < selHeight; yPos++)
|
||||
{
|
||||
ptr = ConioCoordToPointer(Buffer,
|
||||
Console->Selection.srSelection.Left,
|
||||
yPos + Console->Selection.srSelection.Top);
|
||||
/* Copy only the characters, leave attributes alone */
|
||||
for (xPos = 0; xPos < selWidth; xPos++)
|
||||
{
|
||||
/*
|
||||
* Sometimes, applications can put NULL chars into the screen-buffer
|
||||
* (this behaviour is allowed). Detect this and replace by a space.
|
||||
* FIXME - HACK: Improve the way we're doing that (i.e., put spaces
|
||||
* instead of NULLs (or even, nothing) only if it exists a non-null
|
||||
* char *after* those NULLs, before the end-of-line of the selection.
|
||||
* Do the same concerning spaces -- i.e. trailing spaces --).
|
||||
*/
|
||||
dstPos[xPos] = (ptr[xPos].Char.UnicodeChar ? ptr[xPos].Char.UnicodeChar : L' ');
|
||||
}
|
||||
dstPos += selWidth;
|
||||
|
||||
/* Add newline characters if we are not in inline-text copy mode */
|
||||
if (!InlineCopyMode)
|
||||
{
|
||||
if (yPos != (selHeight - 1))
|
||||
{
|
||||
wcscat(data, L"\r\n");
|
||||
dstPos += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("Setting data <%S> to clipboard\n", data);
|
||||
GlobalUnlock(hData);
|
||||
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_UNICODETEXT, hData);
|
||||
}
|
||||
|
||||
VOID
|
||||
GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
/*
|
||||
* This function supposes that the system clipboard was opened.
|
||||
*/
|
||||
|
||||
PCONSOLE Console = Buffer->Header.Console;
|
||||
|
||||
HANDLE hData;
|
||||
LPWSTR str;
|
||||
WCHAR CurChar = 0;
|
||||
|
||||
SHORT VkKey; // MAKEWORD(low = vkey_code, high = shift_state);
|
||||
INPUT_RECORD er;
|
||||
|
||||
hData = GetClipboardData(CF_UNICODETEXT);
|
||||
if (hData == NULL) return;
|
||||
|
||||
str = GlobalLock(hData);
|
||||
if (str == NULL) return;
|
||||
|
||||
DPRINT("Got data <%S> from clipboard\n", str);
|
||||
|
||||
er.EventType = KEY_EVENT;
|
||||
er.Event.KeyEvent.wRepeatCount = 1;
|
||||
while (*str)
|
||||
{
|
||||
/* \r or \n characters. Go to the line only if we get "\r\n" sequence. */
|
||||
if (CurChar == L'\r' && *str == L'\n')
|
||||
{
|
||||
str++;
|
||||
continue;
|
||||
}
|
||||
CurChar = *str++;
|
||||
|
||||
/* Get the key code (+ shift state) corresponding to the character */
|
||||
VkKey = VkKeyScanW(CurChar);
|
||||
if (VkKey == 0xFFFF)
|
||||
{
|
||||
DPRINT1("VkKeyScanW failed - Should simulate the key...\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Pressing some control keys */
|
||||
|
||||
/* Pressing the character key, with the control keys maintained pressed */
|
||||
er.Event.KeyEvent.bKeyDown = TRUE;
|
||||
er.Event.KeyEvent.wVirtualKeyCode = LOBYTE(VkKey);
|
||||
er.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyW(LOBYTE(VkKey), MAPVK_VK_TO_CHAR);
|
||||
er.Event.KeyEvent.uChar.UnicodeChar = CurChar;
|
||||
er.Event.KeyEvent.dwControlKeyState = 0;
|
||||
if (HIBYTE(VkKey) & 1)
|
||||
er.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
|
||||
if (HIBYTE(VkKey) & 2)
|
||||
er.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; // RIGHT_CTRL_PRESSED;
|
||||
if (HIBYTE(VkKey) & 4)
|
||||
er.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; // RIGHT_ALT_PRESSED;
|
||||
|
||||
ConioProcessInputEvent(Console, &er);
|
||||
|
||||
/* Up all the character and control keys */
|
||||
er.Event.KeyEvent.bKeyDown = FALSE;
|
||||
ConioProcessInputEvent(Console, &er);
|
||||
}
|
||||
|
||||
GlobalUnlock(hData);
|
||||
}
|
||||
|
||||
VOID
|
||||
GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
PGUI_CONSOLE_DATA GuiData,
|
||||
HDC hDC,
|
||||
PRECT rc)
|
||||
{
|
||||
PCONSOLE Console = Buffer->Header.Console;
|
||||
// ASSERT(Console == GuiData->Console);
|
||||
|
||||
ULONG TopLine, BottomLine, LeftChar, RightChar;
|
||||
ULONG Line, Char, Start;
|
||||
PCHAR_INFO From;
|
||||
PWCHAR To;
|
||||
WORD LastAttribute, Attribute;
|
||||
ULONG CursorX, CursorY, CursorHeight;
|
||||
HBRUSH CursorBrush, OldBrush;
|
||||
HFONT OldFont;
|
||||
|
||||
if (Buffer->Buffer == NULL) return;
|
||||
|
||||
TopLine = rc->top / GuiData->CharHeight + Buffer->ViewOrigin.Y;
|
||||
BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buffer->ViewOrigin.Y;
|
||||
LeftChar = rc->left / GuiData->CharWidth + Buffer->ViewOrigin.X;
|
||||
RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buffer->ViewOrigin.X;
|
||||
|
||||
LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)->Attributes;
|
||||
|
||||
SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
|
||||
SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
|
||||
|
||||
if (BottomLine >= Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1;
|
||||
if (RightChar >= Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1;
|
||||
|
||||
OldFont = SelectObject(hDC, GuiData->Font);
|
||||
|
||||
for (Line = TopLine; Line <= BottomLine; Line++)
|
||||
{
|
||||
WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
|
||||
From = ConioCoordToPointer(Buffer, LeftChar, Line); // Get the first code of the line
|
||||
Start = LeftChar;
|
||||
To = LineBuffer;
|
||||
|
||||
for (Char = LeftChar; Char <= RightChar; Char++)
|
||||
{
|
||||
/*
|
||||
* We flush the buffer if the new attribute is different
|
||||
* from the current one, or if the buffer is full.
|
||||
*/
|
||||
if (From->Attributes != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
|
||||
{
|
||||
TextOutW(hDC,
|
||||
(Start - Buffer->ViewOrigin.X) * GuiData->CharWidth ,
|
||||
(Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
|
||||
LineBuffer,
|
||||
Char - Start);
|
||||
Start = Char;
|
||||
To = LineBuffer;
|
||||
Attribute = From->Attributes;
|
||||
if (Attribute != LastAttribute)
|
||||
{
|
||||
SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
|
||||
SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(Attribute)));
|
||||
LastAttribute = Attribute;
|
||||
}
|
||||
}
|
||||
|
||||
*(To++) = (From++)->Char.UnicodeChar;
|
||||
}
|
||||
|
||||
TextOutW(hDC,
|
||||
(Start - Buffer->ViewOrigin.X) * GuiData->CharWidth ,
|
||||
(Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
|
||||
LineBuffer,
|
||||
RightChar - Start + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the caret
|
||||
*/
|
||||
if (Buffer->CursorInfo.bVisible &&
|
||||
Buffer->CursorBlinkOn &&
|
||||
!Buffer->ForceCursorOff)
|
||||
{
|
||||
CursorX = Buffer->CursorPosition.X;
|
||||
CursorY = Buffer->CursorPosition.Y;
|
||||
if (LeftChar <= CursorX && CursorX <= RightChar &&
|
||||
TopLine <= CursorY && CursorY <= BottomLine)
|
||||
{
|
||||
CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
|
||||
Attribute = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y)->Attributes;
|
||||
|
||||
if (Attribute != DEFAULT_SCREEN_ATTRIB)
|
||||
{
|
||||
CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Attribute));
|
||||
}
|
||||
else
|
||||
{
|
||||
CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Buffer->ScreenDefaultAttrib));
|
||||
}
|
||||
|
||||
OldBrush = SelectObject(hDC, CursorBrush);
|
||||
PatBlt(hDC,
|
||||
(CursorX - Buffer->ViewOrigin.X) * GuiData->CharWidth,
|
||||
(CursorY - Buffer->ViewOrigin.Y) * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
|
||||
GuiData->CharWidth,
|
||||
CursorHeight,
|
||||
PATCOPY);
|
||||
SelectObject(hDC, OldBrush);
|
||||
DeleteObject(CursorBrush);
|
||||
}
|
||||
}
|
||||
|
||||
SelectObject(hDC, OldFont);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontends/input.c
|
||||
* PURPOSE: Common Front-Ends Input functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "coninput.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static DWORD FASTCALL
|
||||
ConioGetShiftState(PBYTE KeyState, LPARAM lParam)
|
||||
{
|
||||
DWORD ssOut = 0;
|
||||
|
||||
if (KeyState[VK_CAPITAL] & 0x01)
|
||||
ssOut |= CAPSLOCK_ON;
|
||||
|
||||
if (KeyState[VK_NUMLOCK] & 0x01)
|
||||
ssOut |= NUMLOCK_ON;
|
||||
|
||||
if (KeyState[VK_SCROLL] & 0x01)
|
||||
ssOut |= SCROLLLOCK_ON;
|
||||
|
||||
if (KeyState[VK_SHIFT] & 0x80)
|
||||
ssOut |= SHIFT_PRESSED;
|
||||
|
||||
if (KeyState[VK_LCONTROL] & 0x80)
|
||||
ssOut |= LEFT_CTRL_PRESSED;
|
||||
if (KeyState[VK_RCONTROL] & 0x80)
|
||||
ssOut |= RIGHT_CTRL_PRESSED;
|
||||
|
||||
if (KeyState[VK_LMENU] & 0x80)
|
||||
ssOut |= LEFT_ALT_PRESSED;
|
||||
if (KeyState[VK_RMENU] & 0x80)
|
||||
ssOut |= RIGHT_ALT_PRESSED;
|
||||
|
||||
/* See WM_CHAR MSDN documentation for instance */
|
||||
if (lParam & 0x01000000)
|
||||
ssOut |= ENHANCED_KEY;
|
||||
|
||||
return ssOut;
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConioProcessKey(PCONSOLE Console, MSG* msg)
|
||||
{
|
||||
static BYTE KeyState[256] = { 0 };
|
||||
/* MSDN mentions that you should use the last virtual key code received
|
||||
* when putting a virtual key identity to a WM_CHAR message since multiple
|
||||
* or translated keys may be involved. */
|
||||
static UINT LastVirtualKey = 0;
|
||||
DWORD ShiftState;
|
||||
WCHAR UnicodeChar;
|
||||
UINT VirtualKeyCode;
|
||||
UINT VirtualScanCode;
|
||||
BOOL Down = FALSE;
|
||||
BOOLEAN Fake; // synthesized, not a real event
|
||||
BOOLEAN NotChar; // message should not be used to return a character
|
||||
|
||||
if (NULL == Console)
|
||||
{
|
||||
DPRINT1("No Active Console!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
VirtualScanCode = HIWORD(msg->lParam) & 0xFF;
|
||||
Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
|
||||
msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
|
||||
|
||||
GetKeyboardState(KeyState);
|
||||
ShiftState = ConioGetShiftState(KeyState, msg->lParam);
|
||||
|
||||
if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
|
||||
{
|
||||
VirtualKeyCode = LastVirtualKey;
|
||||
UnicodeChar = msg->wParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR Chars[2];
|
||||
INT RetChars = 0;
|
||||
|
||||
VirtualKeyCode = msg->wParam;
|
||||
RetChars = ToUnicodeEx(VirtualKeyCode,
|
||||
VirtualScanCode,
|
||||
KeyState,
|
||||
Chars,
|
||||
2,
|
||||
0,
|
||||
NULL);
|
||||
UnicodeChar = (1 == RetChars ? Chars[0] : 0);
|
||||
}
|
||||
|
||||
if (ConioProcessKeyCallback(Console,
|
||||
msg,
|
||||
KeyState[VK_MENU],
|
||||
ShiftState,
|
||||
VirtualKeyCode,
|
||||
Down))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Fake = UnicodeChar &&
|
||||
(msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
|
||||
msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
|
||||
NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
|
||||
if (NotChar) LastVirtualKey = msg->wParam;
|
||||
|
||||
DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
|
||||
Down ? "down" : "up ",
|
||||
(msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
|
||||
"char" : "key ",
|
||||
Fake ? "fake" : "real",
|
||||
NotChar ? "notc" : "char",
|
||||
VirtualScanCode,
|
||||
VirtualKeyCode,
|
||||
(UnicodeChar >= L' ') ? UnicodeChar : L'.',
|
||||
ShiftState);
|
||||
|
||||
if (Fake) return;
|
||||
|
||||
/* Send the key press to the console driver */
|
||||
ConDrvProcessKey(Console,
|
||||
Down,
|
||||
VirtualKeyCode,
|
||||
VirtualScanCode,
|
||||
UnicodeChar,
|
||||
ShiftState,
|
||||
KeyState[VK_CONTROL]);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,861 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c
|
||||
* PURPOSE: TUI Terminal Front-End - Virtual Consoles...
|
||||
* PROGRAMMERS: David Welch
|
||||
* Gé van Geldorp
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#ifdef TUITERM_COMPILE
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/console.h"
|
||||
#include "include/settings.h"
|
||||
#include "tuiterm.h"
|
||||
#include <drivers/blue/ntddblue.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
#define GetNextConsole(Console) \
|
||||
CONTAINING_RECORD(Console->Entry.Flink, TUI_CONSOLE_DATA, Entry)
|
||||
|
||||
#define GetPrevConsole(Console) \
|
||||
CONTAINING_RECORD(Console->Entry.Blink, TUI_CONSOLE_DATA, Entry)
|
||||
|
||||
|
||||
/* TUI Console Window Class name */
|
||||
#define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass"
|
||||
|
||||
typedef struct _TUI_CONSOLE_DATA
|
||||
{
|
||||
CRITICAL_SECTION Lock;
|
||||
LIST_ENTRY Entry; /* Entry in the list of virtual consoles */
|
||||
// HANDLE hTuiInitEvent;
|
||||
|
||||
HWND hWindow; /* Handle to the console's window (used for the window's procedure */
|
||||
|
||||
PCONSOLE Console; /* Pointer to the owned console */
|
||||
// TUI_CONSOLE_INFO TuiInfo; /* TUI terminal settings */
|
||||
} TUI_CONSOLE_DATA, *PTUI_CONSOLE_DATA;
|
||||
|
||||
/* List of the maintained virtual consoles and its lock */
|
||||
static LIST_ENTRY VirtConsList;
|
||||
static PTUI_CONSOLE_DATA ActiveConsole; /* The active console on screen */
|
||||
static CRITICAL_SECTION ActiveVirtConsLock;
|
||||
|
||||
static COORD PhysicalConsoleSize;
|
||||
static HANDLE ConsoleDeviceHandle;
|
||||
|
||||
static BOOL ConsInitialized = FALSE;
|
||||
|
||||
/******************************************************************************\
|
||||
|** BlueScreen Driver management **|
|
||||
\**/
|
||||
/* Code taken and adapted from base/system/services/driver.c */
|
||||
static DWORD
|
||||
ScmLoadDriver(LPCWSTR lpServiceName)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOLEAN WasPrivilegeEnabled = FALSE;
|
||||
PWSTR pszDriverPath;
|
||||
UNICODE_STRING DriverPath;
|
||||
|
||||
/* Build the driver path */
|
||||
/* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
|
||||
pszDriverPath = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
|
||||
(52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
|
||||
if (pszDriverPath == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
wcscpy(pszDriverPath,
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
|
||||
wcscat(pszDriverPath,
|
||||
lpServiceName);
|
||||
|
||||
RtlInitUnicodeString(&DriverPath,
|
||||
pszDriverPath);
|
||||
|
||||
DPRINT(" Path: %wZ\n", &DriverPath);
|
||||
|
||||
/* Acquire driver-loading privilege */
|
||||
Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
&WasPrivilegeEnabled);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* We encountered a failure, exit properly */
|
||||
DPRINT1("CONSRV: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
Status = NtLoadDriver(&DriverPath);
|
||||
|
||||
/* Release driver-loading privilege */
|
||||
RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
||||
WasPrivilegeEnabled,
|
||||
FALSE,
|
||||
&WasPrivilegeEnabled);
|
||||
|
||||
done:
|
||||
ConsoleFreeHeap(pszDriverPath);
|
||||
return RtlNtStatusToDosError(Status);
|
||||
}
|
||||
|
||||
#ifdef BLUESCREEN_DRIVER_UNLOADING
|
||||
static DWORD
|
||||
ScmUnloadDriver(LPCWSTR lpServiceName)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOLEAN WasPrivilegeEnabled = FALSE;
|
||||
PWSTR pszDriverPath;
|
||||
UNICODE_STRING DriverPath;
|
||||
|
||||
/* Build the driver path */
|
||||
/* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
|
||||
pszDriverPath = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
|
||||
(52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
|
||||
if (pszDriverPath == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
wcscpy(pszDriverPath,
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
|
||||
wcscat(pszDriverPath,
|
||||
lpServiceName);
|
||||
|
||||
RtlInitUnicodeString(&DriverPath,
|
||||
pszDriverPath);
|
||||
|
||||
DPRINT(" Path: %wZ\n", &DriverPath);
|
||||
|
||||
/* Acquire driver-unloading privilege */
|
||||
Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
&WasPrivilegeEnabled);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* We encountered a failure, exit properly */
|
||||
DPRINT1("CONSRV: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
Status = NtUnloadDriver(&DriverPath);
|
||||
|
||||
/* Release driver-unloading privilege */
|
||||
RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
||||
WasPrivilegeEnabled,
|
||||
FALSE,
|
||||
&WasPrivilegeEnabled);
|
||||
|
||||
done:
|
||||
ConsoleFreeHeap(pszDriverPath);
|
||||
return RtlNtStatusToDosError(Status);
|
||||
}
|
||||
#endif
|
||||
/**\
|
||||
\******************************************************************************/
|
||||
|
||||
static BOOL FASTCALL
|
||||
TuiSwapConsole(INT Next)
|
||||
{
|
||||
static PTUI_CONSOLE_DATA SwapConsole = NULL; /* Console we are thinking about swapping with */
|
||||
DWORD BytesReturned;
|
||||
ANSI_STRING Title;
|
||||
PVOID Buffer;
|
||||
PCOORD pos;
|
||||
|
||||
if (0 != Next)
|
||||
{
|
||||
/*
|
||||
* Alt-Tab, swap consoles.
|
||||
* move SwapConsole to next console, and print its title.
|
||||
*/
|
||||
EnterCriticalSection(&ActiveVirtConsLock);
|
||||
if (!SwapConsole) SwapConsole = ActiveConsole;
|
||||
|
||||
SwapConsole = (0 < Next ? GetNextConsole(SwapConsole) : GetPrevConsole(SwapConsole));
|
||||
Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Console->Title);
|
||||
Title.Length = 0;
|
||||
Buffer = ConsoleAllocHeap(0, sizeof(COORD) + Title.MaximumLength);
|
||||
pos = (PCOORD)Buffer;
|
||||
Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(COORD));
|
||||
|
||||
RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Console->Title, FALSE);
|
||||
pos->X = (PhysicalConsoleSize.X - Title.Length) / 2;
|
||||
pos->Y = PhysicalConsoleSize.Y / 2;
|
||||
/* Redraw the console to clear off old title */
|
||||
ConioDrawConsole(ActiveConsole->Console);
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
|
||||
NULL, 0, Buffer, sizeof(COORD) + Title.Length,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1( "Error writing to console\n" );
|
||||
}
|
||||
ConsoleFreeHeap(Buffer);
|
||||
LeaveCriticalSection(&ActiveVirtConsLock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (NULL != SwapConsole)
|
||||
{
|
||||
EnterCriticalSection(&ActiveVirtConsLock);
|
||||
if (SwapConsole != ActiveConsole)
|
||||
{
|
||||
/* First remove swapconsole from the list */
|
||||
SwapConsole->Entry.Blink->Flink = SwapConsole->Entry.Flink;
|
||||
SwapConsole->Entry.Flink->Blink = SwapConsole->Entry.Blink;
|
||||
/* Now insert before activeconsole */
|
||||
SwapConsole->Entry.Flink = &ActiveConsole->Entry;
|
||||
SwapConsole->Entry.Blink = ActiveConsole->Entry.Blink;
|
||||
ActiveConsole->Entry.Blink->Flink = &SwapConsole->Entry;
|
||||
ActiveConsole->Entry.Blink = &SwapConsole->Entry;
|
||||
}
|
||||
ActiveConsole = SwapConsole;
|
||||
SwapConsole = NULL;
|
||||
ConioDrawConsole(ActiveConsole->Console);
|
||||
LeaveCriticalSection(&ActiveVirtConsLock);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID FASTCALL
|
||||
TuiCopyRect(PCHAR Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
|
||||
{
|
||||
UINT SrcDelta, DestDelta;
|
||||
LONG i;
|
||||
PCHAR_INFO Src, SrcEnd;
|
||||
|
||||
Src = ConioCoordToPointer(Buff, Region->Left, Region->Top);
|
||||
SrcDelta = Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
|
||||
SrcEnd = Buff->Buffer + Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
|
||||
DestDelta = ConioRectWidth(Region) * 2 /* 2 == sizeof(CHAR) + sizeof(BYTE) */;
|
||||
for (i = Region->Top; i <= Region->Bottom; i++)
|
||||
{
|
||||
ConsoleUnicodeCharToAnsiChar(Buff->Header.Console, (PCHAR)Dest, &Src->Char.UnicodeChar);
|
||||
*(PBYTE)(Dest + 1) = (BYTE)Src->Attributes;
|
||||
|
||||
Src += SrcDelta;
|
||||
if (SrcEnd <= Src)
|
||||
{
|
||||
Src -= Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
|
||||
}
|
||||
Dest += DestDelta;
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
/*
|
||||
PTUI_CONSOLE_DATA TuiData = NULL;
|
||||
PCONSOLE Console = NULL;
|
||||
|
||||
TuiData = TuiGetGuiData(hWnd);
|
||||
if (TuiData == NULL) return 0;
|
||||
*/
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CHAR:
|
||||
case WM_SYSCHAR:
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
MSG Message;
|
||||
Message.hwnd = hWnd;
|
||||
Message.message = msg;
|
||||
Message.wParam = wParam;
|
||||
Message.lParam = lParam;
|
||||
|
||||
ConioProcessKey(ActiveConsole->Console, &Message);
|
||||
LeaveCriticalSection(&ActiveConsole->Console->Lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
if (LOWORD(wParam) != WA_INACTIVE)
|
||||
{
|
||||
SetFocus(hWnd);
|
||||
ConioDrawConsole(ActiveConsole->Console);
|
||||
}
|
||||
LeaveCriticalSection(&ActiveConsole->Console->Lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
TuiConsoleThread(PVOID Data)
|
||||
{
|
||||
PTUI_CONSOLE_DATA TuiData = (PTUI_CONSOLE_DATA)Data;
|
||||
PCONSOLE Console = TuiData->Console;
|
||||
HWND NewWindow;
|
||||
MSG msg;
|
||||
|
||||
NewWindow = CreateWindowW(TUI_CONSOLE_WINDOW_CLASS,
|
||||
Console->Title.Buffer,
|
||||
0,
|
||||
-32000, -32000, 0, 0,
|
||||
NULL, NULL,
|
||||
ConSrvDllInstance,
|
||||
(PVOID)Console);
|
||||
if (NULL == NewWindow)
|
||||
{
|
||||
DPRINT1("CONSRV: Unable to create console window\n");
|
||||
return 1;
|
||||
}
|
||||
TuiData->hWindow = NewWindow;
|
||||
|
||||
SetForegroundWindow(TuiData->hWindow);
|
||||
NtUserConsoleControl(ConsoleAcquireDisplayOwnership, NULL, 0);
|
||||
|
||||
while (GetMessageW(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
TuiInit(DWORD OemCP)
|
||||
{
|
||||
BOOL Ret = FALSE;
|
||||
CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
|
||||
DWORD BytesReturned;
|
||||
WNDCLASSEXW wc;
|
||||
ATOM ConsoleClassAtom;
|
||||
USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||||
|
||||
/* Exit if we were already initialized */
|
||||
if (ConsInitialized) return TRUE;
|
||||
|
||||
/*
|
||||
* Initialize the TUI front-end:
|
||||
* - load the console driver,
|
||||
* - set default screen attributes,
|
||||
* - grab the console size.
|
||||
*/
|
||||
ScmLoadDriver(L"Blue");
|
||||
|
||||
ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen",
|
||||
FILE_ALL_ACCESS,
|
||||
0, NULL,
|
||||
OPEN_EXISTING,
|
||||
0, NULL);
|
||||
if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle)
|
||||
{
|
||||
DPRINT1("Failed to open BlueScreen.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT,
|
||||
&OemCP, sizeof(OemCP), NULL, 0,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to load the font for codepage %d\n", OemCP);
|
||||
/* Let's suppose the font is good enough to continue */
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
|
||||
&TextAttribute, sizeof(TextAttribute), NULL, 0,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to set text attribute\n");
|
||||
}
|
||||
|
||||
ActiveConsole = NULL;
|
||||
InitializeListHead(&VirtConsList);
|
||||
InitializeCriticalSection(&ActiveVirtConsLock);
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
|
||||
NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to get console info\n");
|
||||
Ret = FALSE;
|
||||
goto Quit;
|
||||
}
|
||||
PhysicalConsoleSize = ScrInfo.dwSize;
|
||||
|
||||
/* Register the TUI notification window class */
|
||||
RtlZeroMemory(&wc, sizeof(WNDCLASSEXW));
|
||||
wc.cbSize = sizeof(WNDCLASSEXW);
|
||||
wc.lpszClassName = TUI_CONSOLE_WINDOW_CLASS;
|
||||
wc.lpfnWndProc = TuiConsoleWndProc;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = ConSrvDllInstance;
|
||||
|
||||
ConsoleClassAtom = RegisterClassExW(&wc);
|
||||
if (ConsoleClassAtom == 0)
|
||||
{
|
||||
DPRINT1("Failed to register TUI console wndproc\n");
|
||||
Ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ret = TRUE;
|
||||
}
|
||||
|
||||
Quit:
|
||||
if (Ret == FALSE)
|
||||
{
|
||||
DeleteCriticalSection(&ActiveVirtConsLock);
|
||||
CloseHandle(ConsoleDeviceHandle);
|
||||
}
|
||||
|
||||
ConsInitialized = Ret;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* TUI Console Driver *
|
||||
******************************************************************************/
|
||||
|
||||
static VOID WINAPI
|
||||
TuiDeinitFrontEnd(IN OUT PFRONTEND This /*,
|
||||
IN PCONSOLE Console */);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
TuiInitFrontEnd(IN OUT PFRONTEND This,
|
||||
IN PCONSOLE Console)
|
||||
{
|
||||
PTUI_CONSOLE_DATA TuiData;
|
||||
HANDLE ThreadHandle;
|
||||
|
||||
if (This == NULL || Console == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
// if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
|
||||
// return STATUS_INVALID_PARAMETER;
|
||||
|
||||
// /* Initialize the console */
|
||||
// Console->TermIFace.Vtbl = &TuiVtbl;
|
||||
|
||||
TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA));
|
||||
if (!TuiData)
|
||||
{
|
||||
DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
// Console->TermIFace.Data = (PVOID)TuiData;
|
||||
TuiData->Console = Console;
|
||||
TuiData->hWindow = NULL;
|
||||
|
||||
InitializeCriticalSection(&TuiData->Lock);
|
||||
|
||||
/*
|
||||
* HACK: Resize the console since we don't support for now changing
|
||||
* the console size when we display it with the hardware.
|
||||
*/
|
||||
// Console->ConsoleSize = PhysicalConsoleSize;
|
||||
// ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
|
||||
|
||||
// /* The console cannot be resized anymore */
|
||||
// Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
|
||||
// // ConioResizeTerminal(Console);
|
||||
|
||||
/*
|
||||
* Contrary to what we do in the GUI front-end, here we create
|
||||
* an input thread for each console. It will dispatch all the
|
||||
* input messages to the proper console (on the GUI it is done
|
||||
* via the default GUI dispatch thread).
|
||||
*/
|
||||
ThreadHandle = CreateThread(NULL,
|
||||
0,
|
||||
TuiConsoleThread,
|
||||
(PVOID)TuiData,
|
||||
0,
|
||||
NULL);
|
||||
if (NULL == ThreadHandle)
|
||||
{
|
||||
DPRINT1("CONSRV: Unable to create console thread\n");
|
||||
// TuiDeinitFrontEnd(Console);
|
||||
TuiDeinitFrontEnd(This);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
CloseHandle(ThreadHandle);
|
||||
|
||||
/*
|
||||
* Insert the newly created console in the list of virtual consoles
|
||||
* and activate it (give it the focus).
|
||||
*/
|
||||
EnterCriticalSection(&ActiveVirtConsLock);
|
||||
InsertTailList(&VirtConsList, &TuiData->Entry);
|
||||
ActiveConsole = TuiData;
|
||||
LeaveCriticalSection(&ActiveVirtConsLock);
|
||||
|
||||
/* Finally, initialize the frontend structure */
|
||||
This->Data = TuiData;
|
||||
This->OldData = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiDeinitFrontEnd(IN OUT PFRONTEND This)
|
||||
{
|
||||
// PCONSOLE Console = This->Console;
|
||||
PTUI_CONSOLE_DATA TuiData = This->Data; // Console->TermIFace.Data;
|
||||
|
||||
/* Close the notification window */
|
||||
DestroyWindow(TuiData->hWindow);
|
||||
|
||||
/*
|
||||
* Set the active console to the next one
|
||||
* and remove the console from the list.
|
||||
*/
|
||||
EnterCriticalSection(&ActiveVirtConsLock);
|
||||
ActiveConsole = GetNextConsole(TuiData);
|
||||
RemoveEntryList(&TuiData->Entry);
|
||||
|
||||
// /* Switch to next console */
|
||||
// if (ActiveConsole == TuiData)
|
||||
// if (ActiveConsole->Console == Console)
|
||||
// {
|
||||
// ActiveConsole = (TuiData->Entry.Flink != TuiData->Entry ? GetNextConsole(TuiData) : NULL);
|
||||
// }
|
||||
|
||||
// if (GetNextConsole(TuiData) != TuiData)
|
||||
// {
|
||||
// TuiData->Entry.Blink->Flink = TuiData->Entry.Flink;
|
||||
// TuiData->Entry.Flink->Blink = TuiData->Entry.Blink;
|
||||
// }
|
||||
|
||||
LeaveCriticalSection(&ActiveVirtConsLock);
|
||||
|
||||
/* Switch to the next console */
|
||||
if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console);
|
||||
|
||||
// Console->TermIFace.Data = NULL;
|
||||
This->Data = NULL;
|
||||
DeleteCriticalSection(&TuiData->Lock);
|
||||
ConsoleFreeHeap(TuiData);
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiDrawRegion(IN OUT PFRONTEND This,
|
||||
SMALL_RECT* Region)
|
||||
{
|
||||
DWORD BytesReturned;
|
||||
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
|
||||
PCONSOLE_DRAW ConsoleDraw;
|
||||
UINT ConsoleDrawSize;
|
||||
|
||||
if (ActiveConsole->Console != Console || GetType(Buff) != TEXTMODE_BUFFER) return;
|
||||
|
||||
ConsoleDrawSize = sizeof(CONSOLE_DRAW) +
|
||||
(ConioRectWidth(Region) * ConioRectHeight(Region)) * 2;
|
||||
ConsoleDraw = ConsoleAllocHeap(0, ConsoleDrawSize);
|
||||
if (NULL == ConsoleDraw)
|
||||
{
|
||||
DPRINT1("ConsoleAllocHeap failed\n");
|
||||
return;
|
||||
}
|
||||
ConsoleDraw->X = Region->Left;
|
||||
ConsoleDraw->Y = Region->Top;
|
||||
ConsoleDraw->SizeX = ConioRectWidth(Region);
|
||||
ConsoleDraw->SizeY = ConioRectHeight(Region);
|
||||
ConsoleDraw->CursorX = Buff->CursorPosition.X;
|
||||
ConsoleDraw->CursorY = Buff->CursorPosition.Y;
|
||||
|
||||
TuiCopyRect((PCHAR)(ConsoleDraw + 1), (PTEXTMODE_SCREEN_BUFFER)Buff, Region);
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW,
|
||||
NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to draw console\n");
|
||||
ConsoleFreeHeap(ConsoleDraw);
|
||||
return;
|
||||
}
|
||||
|
||||
ConsoleFreeHeap(ConsoleDraw);
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiWriteStream(IN OUT PFRONTEND This,
|
||||
SMALL_RECT* Region,
|
||||
SHORT CursorStartX,
|
||||
SHORT CursorStartY,
|
||||
UINT ScrolledLines,
|
||||
PWCHAR Buffer,
|
||||
UINT Length)
|
||||
{
|
||||
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
|
||||
PCHAR NewBuffer;
|
||||
ULONG NewLength;
|
||||
DWORD BytesWritten;
|
||||
|
||||
if (ActiveConsole->Console->ActiveBuffer != Buff) return;
|
||||
|
||||
NewLength = WideCharToMultiByte(Console->OutputCodePage, 0,
|
||||
Buffer, Length,
|
||||
NULL, 0, NULL, NULL);
|
||||
NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewLength * sizeof(CHAR));
|
||||
if (!NewBuffer) return;
|
||||
|
||||
WideCharToMultiByte(Console->OutputCodePage, 0,
|
||||
Buffer, Length,
|
||||
NewBuffer, NewLength, NULL, NULL);
|
||||
|
||||
if (!WriteFile(ConsoleDeviceHandle, NewBuffer, NewLength * sizeof(CHAR), &BytesWritten, NULL))
|
||||
{
|
||||
DPRINT1("Error writing to BlueScreen\n");
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiSetCursorInfo(IN OUT PFRONTEND This,
|
||||
PCONSOLE_SCREEN_BUFFER Buff)
|
||||
{
|
||||
CONSOLE_CURSOR_INFO Info;
|
||||
DWORD BytesReturned;
|
||||
|
||||
if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE;
|
||||
|
||||
Info.dwSize = ConioEffectiveCursorSize(Console, 100);
|
||||
Info.bVisible = Buff->CursorInfo.bVisible;
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO,
|
||||
&Info, sizeof(Info), NULL, 0, &BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1( "Failed to set cursor info\n" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiSetScreenInfo(IN OUT PFRONTEND This,
|
||||
PCONSOLE_SCREEN_BUFFER Buff,
|
||||
SHORT OldCursorX,
|
||||
SHORT OldCursorY)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO Info;
|
||||
DWORD BytesReturned;
|
||||
|
||||
if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE;
|
||||
if (GetType(Buff) != TEXTMODE_BUFFER) return FALSE;
|
||||
|
||||
Info.dwCursorPosition = Buff->CursorPosition;
|
||||
Info.wAttributes = ((PTEXTMODE_SCREEN_BUFFER)Buff)->ScreenDefaultAttrib;
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
|
||||
&Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1( "Failed to set cursor position\n" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiResizeTerminal(IN OUT PFRONTEND This)
|
||||
{
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiProcessKeyCallback(IN OUT PFRONTEND This,
|
||||
MSG* msg,
|
||||
BYTE KeyStateMenu,
|
||||
DWORD ShiftState,
|
||||
UINT VirtualKeyCode,
|
||||
BOOL Down)
|
||||
{
|
||||
if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) &&
|
||||
VK_TAB == VirtualKeyCode)
|
||||
{
|
||||
if (Down)
|
||||
{
|
||||
TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (VK_MENU == VirtualKeyCode && !Down)
|
||||
{
|
||||
return TuiSwapConsole(0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiRefreshInternalInfo(IN OUT PFRONTEND This)
|
||||
{
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiChangeTitle(IN OUT PFRONTEND This)
|
||||
{
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiChangeIcon(IN OUT PFRONTEND This,
|
||||
HICON hWindowIcon)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HWND WINAPI
|
||||
TuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
|
||||
{
|
||||
PTUI_CONSOLE_DATA TuiData = This->Data;
|
||||
return TuiData->hWindow;
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
|
||||
PCOORD pSize)
|
||||
{
|
||||
if (!pSize) return;
|
||||
*pSize = PhysicalConsoleSize;
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
TuiGetDisplayMode(IN OUT PFRONTEND This)
|
||||
{
|
||||
return CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiSetDisplayMode(IN OUT PFRONTEND This,
|
||||
ULONG NewMode)
|
||||
{
|
||||
// if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
|
||||
// return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT WINAPI
|
||||
TuiShowMouseCursor(IN OUT PFRONTEND This,
|
||||
BOOL Show)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiSetMouseCursor(IN OUT PFRONTEND This,
|
||||
HCURSOR hCursor)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HMENU WINAPI
|
||||
TuiMenuControl(IN OUT PFRONTEND This,
|
||||
UINT cmdIdLow,
|
||||
UINT cmdIdHigh)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiSetMenuClose(IN OUT PFRONTEND This,
|
||||
BOOL Enable)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static FRONTEND_VTBL TuiVtbl =
|
||||
{
|
||||
TuiInitFrontEnd,
|
||||
TuiDeinitFrontEnd,
|
||||
TuiDrawRegion,
|
||||
TuiWriteStream,
|
||||
TuiSetCursorInfo,
|
||||
TuiSetScreenInfo,
|
||||
TuiResizeTerminal,
|
||||
TuiProcessKeyCallback,
|
||||
TuiRefreshInternalInfo,
|
||||
TuiChangeTitle,
|
||||
TuiChangeIcon,
|
||||
TuiGetConsoleWindowHandle,
|
||||
TuiGetLargestConsoleWindowSize,
|
||||
TuiGetDisplayMode,
|
||||
TuiSetDisplayMode,
|
||||
TuiShowMouseCursor,
|
||||
TuiSetMouseCursor,
|
||||
TuiMenuControl,
|
||||
TuiSetMenuClose,
|
||||
};
|
||||
|
||||
// static BOOL
|
||||
// DtbgIsDesktopVisible(VOID)
|
||||
// {
|
||||
// return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
|
||||
// }
|
||||
static BOOLEAN
|
||||
IsConsoleMode(VOID)
|
||||
{
|
||||
return (BOOLEAN)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN OUT PVOID ExtraConsoleInfo,
|
||||
IN ULONG ProcessId)
|
||||
{
|
||||
if (FrontEnd == NULL || ConsoleInfo == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* We must be in console mode already */
|
||||
if (!IsConsoleMode()) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* Initialize the TUI terminal emulator */
|
||||
if (!TuiInit(ConsoleInfo->CodePage)) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* Finally, initialize the frontend structure */
|
||||
FrontEnd->Vtbl = &TuiVtbl;
|
||||
FrontEnd->Data = NULL;
|
||||
FrontEnd->OldData = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
|
||||
{
|
||||
if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
|
||||
if (FrontEnd->Data) TuiDeinitFrontEnd(FrontEnd);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/frontends/tui/tuiterm.h
|
||||
* PURPOSE: TUI Terminal Front-End
|
||||
* PROGRAMMERS: David Welch
|
||||
* Gé van Geldorp
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
NTSTATUS FASTCALL TuiInitConsole(PCONSOLE Console,
|
||||
/*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
|
||||
PCONSOLE_INFO ConsoleInfo,
|
||||
DWORD ProcessId);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,866 @@
|
||||
/*
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/handle.c
|
||||
* PURPOSE: Console I/O Handles functions
|
||||
* PROGRAMMERS: David Welch
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "handle.h"
|
||||
#include "include/console.h"
|
||||
#include "console.h"
|
||||
#include "conoutput.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
typedef struct _CONSOLE_IO_HANDLE
|
||||
{
|
||||
PCONSOLE_IO_OBJECT Object; /* The object on which the handle points to */
|
||||
DWORD Access;
|
||||
BOOL Inheritable;
|
||||
DWORD ShareMode;
|
||||
} CONSOLE_IO_HANDLE, *PCONSOLE_IO_HANDLE;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static INT
|
||||
AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry, INT Change)
|
||||
{
|
||||
PCONSOLE_IO_OBJECT Object = Entry->Object;
|
||||
|
||||
DPRINT("AdjustHandleCounts(0x%p, %d), Object = 0x%p\n", Entry, Change, Object);
|
||||
DPRINT("\tAdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type);
|
||||
|
||||
if (Entry->Access & GENERIC_READ) Object->AccessRead += Change;
|
||||
if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change;
|
||||
if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change;
|
||||
if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
|
||||
|
||||
Object->HandleCount += Change;
|
||||
|
||||
return Object->HandleCount;
|
||||
}
|
||||
|
||||
static VOID
|
||||
ConSrvCreateHandleEntry(PCONSOLE_IO_HANDLE Entry)
|
||||
{
|
||||
/// LOCK /// PCONSOLE_IO_OBJECT Object = Entry->Object;
|
||||
/// LOCK /// EnterCriticalSection(&Object->Console->Lock);
|
||||
AdjustHandleCounts(Entry, +1);
|
||||
/// LOCK /// LeaveCriticalSection(&Object->Console->Lock);
|
||||
}
|
||||
|
||||
static VOID
|
||||
ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
|
||||
{
|
||||
PCONSOLE_IO_OBJECT Object = Entry->Object;
|
||||
if (Object != NULL)
|
||||
{
|
||||
/// LOCK /// PCONSOLE Console = Object->Console;
|
||||
/// LOCK /// EnterCriticalSection(&Console->Lock);
|
||||
|
||||
/*
|
||||
* If this is a input handle, notify and dereference
|
||||
* all the waits related to this handle.
|
||||
*/
|
||||
if (Object->Type == INPUT_BUFFER)
|
||||
{
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
|
||||
|
||||
/*
|
||||
* Wake up all the writing waiters related to this handle for this
|
||||
* input buffer, if any, then dereference them and purge them all
|
||||
* from the list.
|
||||
* To select them amongst all the waiters for this input buffer,
|
||||
* pass the handle pointer to the waiters, then they will check
|
||||
* whether or not they are related to this handle and if so, they
|
||||
* return.
|
||||
*/
|
||||
CsrNotifyWait(&InputBuffer->ReadWaitQueue,
|
||||
WaitAll,
|
||||
NULL,
|
||||
(PVOID)Entry);
|
||||
if (!IsListEmpty(&InputBuffer->ReadWaitQueue))
|
||||
{
|
||||
CsrDereferenceWait(&InputBuffer->ReadWaitQueue);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the last handle to a screen buffer is closed, delete it... */
|
||||
if (AdjustHandleCounts(Entry, -1) == 0)
|
||||
{
|
||||
if (Object->Type == TEXTMODE_BUFFER || Object->Type == GRAPHICS_BUFFER)
|
||||
{
|
||||
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
|
||||
/* ...unless it's the only buffer left. Windows allows deletion
|
||||
* even of the last buffer, but having to deal with a lack of
|
||||
* any active buffer might be error-prone. */
|
||||
if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
|
||||
ConioDeleteScreenBuffer(Buffer);
|
||||
}
|
||||
else if (Object->Type == INPUT_BUFFER)
|
||||
{
|
||||
DPRINT("Closing the input buffer\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Invalid object type %d\n", Object->Type);
|
||||
}
|
||||
}
|
||||
|
||||
/// LOCK /// LeaveCriticalSection(&Console->Lock);
|
||||
|
||||
/* Invalidate (zero-out) this handle entry */
|
||||
// Entry->Object = NULL;
|
||||
// RtlZeroMemory(Entry, sizeof(*Entry));
|
||||
}
|
||||
RtlZeroMemory(Entry, sizeof(*Entry)); // Be sure the whole entry is invalidated.
|
||||
}
|
||||
|
||||
|
||||
/* Forward declaration, used in ConSrvInitHandlesTable */
|
||||
static VOID ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData);
|
||||
|
||||
static NTSTATUS
|
||||
ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
|
||||
IN PCONSOLE Console,
|
||||
OUT PHANDLE pInputHandle,
|
||||
OUT PHANDLE pOutputHandle,
|
||||
OUT PHANDLE pErrorHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE InputHandle = INVALID_HANDLE_VALUE,
|
||||
OutputHandle = INVALID_HANDLE_VALUE,
|
||||
ErrorHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
/*
|
||||
* Initialize the handles table. Use temporary variables to store
|
||||
* the handles values in such a way that, if we fail, we don't
|
||||
* return to the caller invalid handle values.
|
||||
*
|
||||
* Insert the IO handles.
|
||||
*/
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
/* Insert the Input handle */
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&InputHandle,
|
||||
&Console->InputBuffer.Header,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
TRUE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to insert the input handle\n");
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Insert the Output handle */
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&OutputHandle,
|
||||
&Console->ActiveBuffer->Header,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
TRUE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to insert the output handle\n");
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Insert the Error handle */
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&ErrorHandle,
|
||||
&Console->ActiveBuffer->Header,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
TRUE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to insert the error handle\n");
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Return the newly created handles */
|
||||
*pInputHandle = InputHandle;
|
||||
*pOutputHandle = OutputHandle;
|
||||
*pErrorHandle = ErrorHandle;
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
|
||||
IN PCONSOLE_PROCESS_DATA TargetProcessData)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
ULONG i, j;
|
||||
|
||||
RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
|
||||
|
||||
/* Inherit a handles table only if there is no already */
|
||||
if (TargetProcessData->HandleTable != NULL /* || TargetProcessData->HandleTableSize != 0 */)
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Allocate a new handle table for the child process */
|
||||
TargetProcessData->HandleTable = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
|
||||
SourceProcessData->HandleTableSize
|
||||
* sizeof(CONSOLE_IO_HANDLE));
|
||||
if (TargetProcessData->HandleTable == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
|
||||
|
||||
/*
|
||||
* Parse the parent process' handles table and, for each handle,
|
||||
* do a copy of it and reference it, if the handle is inheritable.
|
||||
*/
|
||||
for (i = 0, j = 0; i < SourceProcessData->HandleTableSize; i++)
|
||||
{
|
||||
if (SourceProcessData->HandleTable[i].Object != NULL &&
|
||||
SourceProcessData->HandleTable[i].Inheritable)
|
||||
{
|
||||
/*
|
||||
* Copy the handle data and increment the reference count of the
|
||||
* pointed object (via the call to ConSrvCreateHandleEntry).
|
||||
*/
|
||||
TargetProcessData->HandleTable[j] = SourceProcessData->HandleTable[i];
|
||||
ConSrvCreateHandleEntry(&TargetProcessData->HandleTable[j]);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
Quit:
|
||||
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID
|
||||
ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData)
|
||||
{
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if (ProcessData->HandleTable != NULL)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
/*
|
||||
* ProcessData->ConsoleHandle is NULL (and the assertion fails) when
|
||||
* ConSrvFreeHandlesTable is called in ConSrvConnect during the
|
||||
* allocation of a new console.
|
||||
*/
|
||||
// ASSERT(ProcessData->ConsoleHandle);
|
||||
if (ProcessData->ConsoleHandle != NULL)
|
||||
{
|
||||
/* Close all the console handles */
|
||||
for (i = 0; i < ProcessData->HandleTableSize; i++)
|
||||
{
|
||||
ConSrvCloseHandleEntry(&ProcessData->HandleTable[i]);
|
||||
}
|
||||
}
|
||||
/* Free the handles table memory */
|
||||
ConsoleFreeHeap(ProcessData->HandleTable);
|
||||
ProcessData->HandleTable = NULL;
|
||||
}
|
||||
|
||||
ProcessData->HandleTableSize = 0;
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object,
|
||||
IN CONSOLE_IO_OBJECT_TYPE Type,
|
||||
IN PCONSOLE Console)
|
||||
{
|
||||
ASSERT(Object);
|
||||
// if (!Object) return;
|
||||
|
||||
Object->Type = Type;
|
||||
Object->Console = Console;
|
||||
Object->AccessRead = Object->AccessWrite = 0;
|
||||
Object->ExclusiveRead = Object->ExclusiveWrite = 0;
|
||||
Object->HandleCount = 0;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
PHANDLE Handle,
|
||||
PCONSOLE_IO_OBJECT Object,
|
||||
DWORD Access,
|
||||
BOOL Inheritable,
|
||||
DWORD ShareMode)
|
||||
{
|
||||
#define IO_HANDLES_INCREMENT 2 * 3
|
||||
|
||||
ULONG i = 0;
|
||||
PCONSOLE_IO_HANDLE Block;
|
||||
|
||||
// NOTE: Commented out because calling code always lock HandleTableLock before.
|
||||
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
|
||||
(ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
|
||||
|
||||
if (ProcessData->HandleTable)
|
||||
{
|
||||
for (i = 0; i < ProcessData->HandleTableSize; i++)
|
||||
{
|
||||
if (ProcessData->HandleTable[i].Object == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= ProcessData->HandleTableSize)
|
||||
{
|
||||
/* Allocate a new handles table */
|
||||
Block = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
|
||||
(ProcessData->HandleTableSize +
|
||||
IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE));
|
||||
if (Block == NULL)
|
||||
{
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* If we previously had a handles table, free it and use the new one */
|
||||
if (ProcessData->HandleTable)
|
||||
{
|
||||
/* Copy the handles from the old table to the new one */
|
||||
RtlCopyMemory(Block,
|
||||
ProcessData->HandleTable,
|
||||
ProcessData->HandleTableSize * sizeof(CONSOLE_IO_HANDLE));
|
||||
ConsoleFreeHeap(ProcessData->HandleTable);
|
||||
}
|
||||
ProcessData->HandleTable = Block;
|
||||
ProcessData->HandleTableSize += IO_HANDLES_INCREMENT;
|
||||
}
|
||||
|
||||
ProcessData->HandleTable[i].Object = Object;
|
||||
ProcessData->HandleTable[i].Access = Access;
|
||||
ProcessData->HandleTable[i].Inheritable = Inheritable;
|
||||
ProcessData->HandleTable[i].ShareMode = ShareMode;
|
||||
ConSrvCreateHandleEntry(&ProcessData->HandleTable[i]);
|
||||
*Handle = ULongToHandle((i << 2) | 0x3);
|
||||
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
HANDLE Handle)
|
||||
{
|
||||
ULONG Index = HandleToULong(Handle) >> 2;
|
||||
PCONSOLE_IO_OBJECT Object;
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
ASSERT(ProcessData->HandleTable);
|
||||
|
||||
if (Index >= ProcessData->HandleTableSize ||
|
||||
(Object = ProcessData->HandleTable[Index].Object) == NULL)
|
||||
{
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
ASSERT(ProcessData->ConsoleHandle);
|
||||
ConSrvCloseHandleEntry(&ProcessData->HandleTable[Index]);
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
HANDLE Handle,
|
||||
PCONSOLE_IO_OBJECT* Object,
|
||||
PVOID* Entry OPTIONAL,
|
||||
DWORD Access,
|
||||
BOOL LockConsole,
|
||||
CONSOLE_IO_OBJECT_TYPE Type)
|
||||
{
|
||||
// NTSTATUS Status;
|
||||
ULONG Index = HandleToULong(Handle) >> 2;
|
||||
PCONSOLE_IO_HANDLE HandleEntry = NULL;
|
||||
PCONSOLE_IO_OBJECT ObjectEntry = NULL;
|
||||
// PCONSOLE ObjectConsole;
|
||||
|
||||
ASSERT(Object);
|
||||
if (Entry) *Entry = NULL;
|
||||
|
||||
DPRINT("ConSrvGetObject -- Object: 0x%x, Handle: 0x%x\n", Object, Handle);
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if ( IsConsoleHandle(Handle) &&
|
||||
Index < ProcessData->HandleTableSize )
|
||||
{
|
||||
HandleEntry = &ProcessData->HandleTable[Index];
|
||||
ObjectEntry = HandleEntry->Object;
|
||||
}
|
||||
|
||||
if ( HandleEntry == NULL ||
|
||||
ObjectEntry == NULL ||
|
||||
(HandleEntry->Access & Access) == 0 ||
|
||||
/*(Type != 0 && ObjectEntry->Type != Type)*/
|
||||
(Type != 0 && (ObjectEntry->Type & Type) == 0) )
|
||||
{
|
||||
DPRINT1("ConSrvGetObject -- Invalid handle 0x%x of type %lu with access %lu ; retrieved object 0x%x (handle 0x%x) of type %lu with access %lu\n",
|
||||
Handle, Type, Access, ObjectEntry, HandleEntry, (ObjectEntry ? ObjectEntry->Type : 0), (HandleEntry ? HandleEntry->Access : 0));
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
// Status = ConDrvGetConsole(&ObjectConsole, ProcessData->ConsoleHandle, LockConsole);
|
||||
// if (NT_SUCCESS(Status))
|
||||
if (ConDrvValidateConsoleUnsafe(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
|
||||
{
|
||||
_InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
|
||||
|
||||
/* Return the objects to the caller */
|
||||
*Object = ObjectEntry;
|
||||
if (Entry) *Entry = HandleEntry;
|
||||
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object,
|
||||
BOOL IsConsoleLocked)
|
||||
{
|
||||
ConSrvReleaseConsole(Object->Console, IsConsoleLocked);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
PHANDLE pInputHandle,
|
||||
PHANDLE pOutputHandle,
|
||||
PHANDLE pErrorHandle,
|
||||
PCONSOLE_START_INFO ConsoleStartInfo)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
HANDLE ConsoleHandle;
|
||||
PCONSOLE Console;
|
||||
|
||||
/*
|
||||
* We are about to create a new console. However when ConSrvNewProcess
|
||||
* was called, we didn't know that we wanted to create a new console and
|
||||
* therefore, we by default inherited the handles table from our parent
|
||||
* process. It's only now that we notice that in fact we do not need
|
||||
* them, because we've created a new console and thus we must use it.
|
||||
*
|
||||
* Therefore, free the handles table so that we can recreate
|
||||
* a new one later on.
|
||||
*/
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
|
||||
/* Initialize a new Console owned by this process */
|
||||
Status = ConSrvInitConsole(&ConsoleHandle,
|
||||
&Console,
|
||||
ConsoleStartInfo,
|
||||
HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Console initialization failed\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Assign the new console handle */
|
||||
ProcessData->ConsoleHandle = ConsoleHandle;
|
||||
|
||||
/* Initialize the handles table */
|
||||
Status = ConSrvInitHandlesTable(ProcessData,
|
||||
Console,
|
||||
pInputHandle,
|
||||
pOutputHandle,
|
||||
pErrorHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to initialize the handles table\n");
|
||||
ConSrvDeleteConsole(Console);
|
||||
ProcessData->ConsoleHandle = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Duplicate the Input Event */
|
||||
Status = NtDuplicateObject(NtCurrentProcess(),
|
||||
Console->InputBuffer.ActiveEvent,
|
||||
ProcessData->Process->ProcessHandle,
|
||||
&ProcessData->ConsoleEvent,
|
||||
EVENT_ALL_ACCESS, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
ConSrvDeleteConsole(Console);
|
||||
ProcessData->ConsoleHandle = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Insert the process into the processes list of the console */
|
||||
InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
|
||||
|
||||
/* Add a reference count because the process is tied to the console */
|
||||
_InterlockedIncrement(&Console->ReferenceCount);
|
||||
|
||||
/* Update the internal info of the terminal */
|
||||
ConioRefreshInternalInfo(Console);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
HANDLE ConsoleHandle,
|
||||
BOOL CreateNewHandlesTable,
|
||||
PHANDLE pInputHandle,
|
||||
PHANDLE pOutputHandle,
|
||||
PHANDLE pErrorHandle)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE Console;
|
||||
|
||||
/* Validate and lock the console */
|
||||
if (!ConDrvValidateConsole(&Console,
|
||||
ConsoleHandle,
|
||||
CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
// FIXME: Find another status code
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Inherit the console */
|
||||
ProcessData->ConsoleHandle = ConsoleHandle;
|
||||
|
||||
if (CreateNewHandlesTable)
|
||||
{
|
||||
/*
|
||||
* We are about to create a new console. However when ConSrvNewProcess
|
||||
* was called, we didn't know that we wanted to create a new console and
|
||||
* therefore, we by default inherited the handles table from our parent
|
||||
* process. It's only now that we notice that in fact we do not need
|
||||
* them, because we've created a new console and thus we must use it.
|
||||
*
|
||||
* Therefore, free the handles table so that we can recreate
|
||||
* a new one later on.
|
||||
*/
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
|
||||
/* Initialize the handles table */
|
||||
Status = ConSrvInitHandlesTable(ProcessData,
|
||||
Console,
|
||||
pInputHandle,
|
||||
pOutputHandle,
|
||||
pErrorHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to initialize the handles table\n");
|
||||
ProcessData->ConsoleHandle = NULL;
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Duplicate the Input Event */
|
||||
Status = NtDuplicateObject(NtCurrentProcess(),
|
||||
Console->InputBuffer.ActiveEvent,
|
||||
ProcessData->Process->ProcessHandle,
|
||||
&ProcessData->ConsoleEvent,
|
||||
EVENT_ALL_ACCESS, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
|
||||
ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table.
|
||||
ProcessData->ConsoleHandle = NULL;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Insert the process into the processes list of the console */
|
||||
InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
|
||||
|
||||
/* Add a reference count because the process is tied to the console */
|
||||
_InterlockedIncrement(&Console->ReferenceCount);
|
||||
|
||||
/* Update the internal info of the terminal */
|
||||
ConioRefreshInternalInfo(Console);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
Quit:
|
||||
/* Unlock the console and return */
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
|
||||
{
|
||||
PCONSOLE Console;
|
||||
|
||||
DPRINT("ConSrvRemoveConsole\n");
|
||||
|
||||
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
/* Validate and lock the console */
|
||||
if (ConDrvValidateConsole(&Console,
|
||||
ProcessData->ConsoleHandle,
|
||||
CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
DPRINT("ConSrvRemoveConsole - Locking OK\n");
|
||||
|
||||
/* Close all console handles and free the handles table */
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
|
||||
/* Detach the process from the console */
|
||||
ProcessData->ConsoleHandle = NULL;
|
||||
|
||||
/* Remove ourselves from the console's list of processes */
|
||||
RemoveEntryList(&ProcessData->ConsoleLink);
|
||||
|
||||
/* Update the internal info of the terminal */
|
||||
ConioRefreshInternalInfo(Console);
|
||||
|
||||
/* Release the console */
|
||||
DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount);
|
||||
ConDrvReleaseConsole(Console, TRUE);
|
||||
//CloseHandle(ProcessData->ConsoleEvent);
|
||||
//ProcessData->ConsoleEvent = NULL;
|
||||
}
|
||||
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
CSR_API(SrvOpenConsole)
|
||||
{
|
||||
/*
|
||||
* This API opens a handle to either the input buffer or to
|
||||
* a screen-buffer of the console of the current process.
|
||||
*/
|
||||
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_OPENCONSOLE OpenConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.OpenConsoleRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
|
||||
DWORD DesiredAccess = OpenConsoleRequest->Access;
|
||||
DWORD ShareMode = OpenConsoleRequest->ShareMode;
|
||||
PCONSOLE_IO_OBJECT Object;
|
||||
|
||||
OpenConsoleRequest->ConsoleHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
/*
|
||||
* Open a handle to either the active screen buffer or the input buffer.
|
||||
*/
|
||||
if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
|
||||
{
|
||||
Object = &Console->ActiveBuffer->Header;
|
||||
}
|
||||
else // HANDLE_INPUT
|
||||
{
|
||||
Object = &Console->InputBuffer.Header;
|
||||
}
|
||||
|
||||
if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) ||
|
||||
((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0))
|
||||
{
|
||||
DPRINT1("Sharing violation\n");
|
||||
Status = STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&OpenConsoleRequest->ConsoleHandle,
|
||||
Object,
|
||||
DesiredAccess,
|
||||
OpenConsoleRequest->Inheritable,
|
||||
ShareMode);
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvCloseHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_CLOSEHANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ConSrvRemoveObject(ProcessData, CloseHandleRequest->ConsoleHandle);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvVerifyConsoleIoHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
|
||||
HANDLE ConsoleHandle = VerifyHandleRequest->ConsoleHandle;
|
||||
ULONG Index = HandleToULong(ConsoleHandle) >> 2;
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if (!IsConsoleHandle(ConsoleHandle) ||
|
||||
Index >= ProcessData->HandleTableSize ||
|
||||
ProcessData->HandleTable[Index].Object == NULL)
|
||||
{
|
||||
DPRINT("SrvVerifyConsoleIoHandle failed\n");
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvDuplicateHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
|
||||
HANDLE ConsoleHandle = DuplicateHandleRequest->ConsoleHandle;
|
||||
ULONG Index = HandleToULong(ConsoleHandle) >> 2;
|
||||
PCONSOLE_IO_HANDLE Entry;
|
||||
DWORD DesiredAccess;
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if ( /** !IsConsoleHandle(ConsoleHandle) || **/
|
||||
Index >= ProcessData->HandleTableSize ||
|
||||
(Entry = &ProcessData->HandleTable[Index])->Object == NULL)
|
||||
{
|
||||
DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle);
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (DuplicateHandleRequest->Options & DUPLICATE_SAME_ACCESS)
|
||||
{
|
||||
DesiredAccess = Entry->Access;
|
||||
}
|
||||
else
|
||||
{
|
||||
DesiredAccess = DuplicateHandleRequest->Access;
|
||||
/* Make sure the source handle has all the desired flags */
|
||||
if ((Entry->Access & DesiredAccess) == 0)
|
||||
{
|
||||
DPRINT1("Handle %p only has access %X; requested %X\n",
|
||||
ConsoleHandle, Entry->Access, DesiredAccess);
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert the new handle inside the process handles table */
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
|
||||
Entry->Object,
|
||||
DesiredAccess,
|
||||
DuplicateHandleRequest->Inheritable,
|
||||
Entry->ShareMode);
|
||||
if (NT_SUCCESS(Status) &&
|
||||
(DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE))
|
||||
{
|
||||
/* Close the original handle if needed */
|
||||
ConSrvCloseHandleEntry(Entry);
|
||||
}
|
||||
|
||||
Quit:
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/handle.h
|
||||
* PURPOSE: Console I/O Handles functions
|
||||
* PROGRAMMERS: David Welch
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
VOID FASTCALL ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object,
|
||||
IN CONSOLE_IO_OBJECT_TYPE Type,
|
||||
IN PCONSOLE Console);
|
||||
NTSTATUS FASTCALL ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
PHANDLE Handle,
|
||||
PCONSOLE_IO_OBJECT Object,
|
||||
DWORD Access,
|
||||
BOOL Inheritable,
|
||||
DWORD ShareMode);
|
||||
NTSTATUS FASTCALL ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
HANDLE Handle);
|
||||
NTSTATUS FASTCALL ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
HANDLE Handle,
|
||||
PCONSOLE_IO_OBJECT* Object,
|
||||
PVOID* Entry OPTIONAL,
|
||||
DWORD Access,
|
||||
BOOL LockConsole,
|
||||
CONSOLE_IO_OBJECT_TYPE Type);
|
||||
VOID FASTCALL ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object,
|
||||
BOOL IsConsoleLocked);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/heap.h
|
||||
* PURPOSE: Heap Helpers
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* See init.c */
|
||||
extern HANDLE ConSrvHeap;
|
||||
|
||||
#define ConsoleAllocHeap(Flags, Size) RtlAllocateHeap(ConSrvHeap, Flags, Size)
|
||||
#define ConsoleFreeHeap(HeapBase) RtlFreeHeap(ConSrvHeap, 0, HeapBase)
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/include/conio.h
|
||||
* PURPOSE: Public Console I/O Interface
|
||||
* PROGRAMMERS: Gé van Geldorp
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CSR_DEFAULT_CURSOR_SIZE 25
|
||||
|
||||
/* Default attributes */
|
||||
#define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
|
||||
#define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
|
||||
BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
|
||||
|
||||
/* Object type magic numbers */
|
||||
typedef enum _CONSOLE_IO_OBJECT_TYPE
|
||||
{
|
||||
// ANY_TYPE_BUFFER = 0x00, // --> Match any types of IO handles
|
||||
TEXTMODE_BUFFER = 0x01, // --> Output-type handles for text SBs
|
||||
GRAPHICS_BUFFER = 0x02, // --> Output-type handles for graphics SBs
|
||||
SCREEN_BUFFER = 0x03, // --> Any SB type
|
||||
INPUT_BUFFER = 0x04 // --> Input-type handles
|
||||
} CONSOLE_IO_OBJECT_TYPE;
|
||||
|
||||
typedef struct _CONSOLE_IO_OBJECT
|
||||
{
|
||||
CONSOLE_IO_OBJECT_TYPE Type;
|
||||
struct _CONSOLE* /* PCONSOLE */ Console;
|
||||
LONG AccessRead, AccessWrite;
|
||||
LONG ExclusiveRead, ExclusiveWrite;
|
||||
LONG HandleCount;
|
||||
} CONSOLE_IO_OBJECT, *PCONSOLE_IO_OBJECT;
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
|* *|
|
||||
|* Abstract "class" for screen-buffers, be they text-mode or graphics *|
|
||||
|* *|
|
||||
\******************************************************************************/
|
||||
|
||||
/*
|
||||
* See conoutput.c for the implementation
|
||||
*/
|
||||
|
||||
typedef struct _CONSOLE_SCREEN_BUFFER CONSOLE_SCREEN_BUFFER,
|
||||
*PCONSOLE_SCREEN_BUFFER;
|
||||
|
||||
typedef struct _CONSOLE_SCREEN_BUFFER_VTBL
|
||||
{
|
||||
CONSOLE_IO_OBJECT_TYPE (*GetType)(PCONSOLE_SCREEN_BUFFER This);
|
||||
} CONSOLE_SCREEN_BUFFER_VTBL, *PCONSOLE_SCREEN_BUFFER_VTBL;
|
||||
|
||||
#define GetType(This) (This)->Vtbl->GetType(This)
|
||||
|
||||
struct _CONSOLE_SCREEN_BUFFER
|
||||
{
|
||||
CONSOLE_IO_OBJECT Header; /* Object header - MUST BE IN FIRST PLACE */
|
||||
PCONSOLE_SCREEN_BUFFER_VTBL Vtbl; /* Virtual table */
|
||||
|
||||
LIST_ENTRY ListEntry; /* Entry in console's list of buffers */
|
||||
|
||||
COORD ScreenBufferSize; /* Size of this screen buffer. (Rows, Columns) for text-mode and (Width, Height) for graphics */
|
||||
COORD ViewSize; /* Associated "view" (i.e. console) size */
|
||||
|
||||
COORD OldScreenBufferSize; /* Old size of this screen buffer */
|
||||
COORD OldViewSize; /* Old associated view size */
|
||||
|
||||
COORD ViewOrigin; /* Beginning offset for the actual display area */
|
||||
|
||||
/***** Put that VV in TEXTMODE_SCREEN_BUFFER ?? *****/
|
||||
USHORT VirtualY; /* Top row of buffer being displayed, reported to callers */
|
||||
|
||||
COORD CursorPosition; /* Current cursor position */
|
||||
BOOLEAN CursorBlinkOn;
|
||||
BOOLEAN ForceCursorOff;
|
||||
// ULONG CursorSize;
|
||||
CONSOLE_CURSOR_INFO CursorInfo; // FIXME: Keep this member or not ??
|
||||
/*********************************************/
|
||||
|
||||
// WORD ScreenDefaultAttrib; /* Default screen char attribute */
|
||||
// WORD PopupDefaultAttrib; /* Default popup char attribute */
|
||||
USHORT Mode; /* Output buffer modes */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
|* *|
|
||||
|* Text-mode and graphics-mode screen-buffer "classes" *|
|
||||
|* *|
|
||||
\******************************************************************************/
|
||||
|
||||
/*
|
||||
* See text.c for the implementation
|
||||
*/
|
||||
|
||||
/************************************************************************
|
||||
* Screen buffer structure represents the win32 screen buffer object. *
|
||||
* Internally, the portion of the buffer being shown CAN loop past the *
|
||||
* bottom of the virtual buffer and wrap around to the top. Win32 does *
|
||||
* not do this. I decided to do this because it eliminates the need to *
|
||||
* do a massive memcpy() to scroll the contents of the buffer up to *
|
||||
* scroll the screen on output, instead I just shift down the position *
|
||||
* to be displayed, and let it wrap around to the top again. *
|
||||
* The VirtualY member keeps track of the top Y coord that win32 *
|
||||
* clients THINK is currently being displayed, because they think that *
|
||||
* when the display reaches the bottom of the buffer and another line *
|
||||
* being printed causes another line to scroll down, that the buffer IS *
|
||||
* memcpy()'s up, and the bottom of the buffer is still displayed, but *
|
||||
* internally, I just wrap back to the top of the buffer. *
|
||||
************************************************************************/
|
||||
|
||||
typedef struct _TEXTMODE_BUFFER_INFO
|
||||
{
|
||||
COORD ScreenBufferSize;
|
||||
USHORT ScreenAttrib;
|
||||
USHORT PopupAttrib;
|
||||
BOOLEAN IsCursorVisible;
|
||||
ULONG CursorSize;
|
||||
} TEXTMODE_BUFFER_INFO, *PTEXTMODE_BUFFER_INFO;
|
||||
|
||||
typedef struct _TEXTMODE_SCREEN_BUFFER
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER; /* Screen buffer base class - MUST BE IN FIRST PLACE */
|
||||
|
||||
PCHAR_INFO Buffer; /* Pointer to UNICODE screen buffer (Buffer->Char.UnicodeChar only is valid, not Char.AsciiChar) */
|
||||
|
||||
WORD ScreenDefaultAttrib; /* Default screen char attribute */
|
||||
WORD PopupDefaultAttrib; /* Default popup char attribute */
|
||||
} TEXTMODE_SCREEN_BUFFER, *PTEXTMODE_SCREEN_BUFFER;
|
||||
|
||||
|
||||
/*
|
||||
* See graphics.c for the implementation
|
||||
*/
|
||||
|
||||
typedef struct _GRAPHICS_BUFFER_INFO
|
||||
{
|
||||
CONSOLE_GRAPHICS_BUFFER_INFO Info;
|
||||
} GRAPHICS_BUFFER_INFO, *PGRAPHICS_BUFFER_INFO;
|
||||
|
||||
typedef struct _GRAPHICS_SCREEN_BUFFER
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER; /* Screen buffer base class - MUST BE IN FIRST PLACE */
|
||||
|
||||
ULONG BitMapInfoLength; /* Real size of the structure pointed by BitMapInfo */
|
||||
LPBITMAPINFO BitMapInfo; /* Information on the bitmap buffer */
|
||||
ULONG BitMapUsage; /* See the uUsage parameter of GetDIBits */
|
||||
HANDLE hSection; /* Handle to the memory shared section for the bitmap buffer */
|
||||
PVOID BitMap; /* Our bitmap buffer */
|
||||
PVOID ClientBitMap; /* A copy of the client view of our bitmap buffer */
|
||||
HANDLE Mutex; /* Our mutex, used to synchronize read / writes to the bitmap buffer */
|
||||
HANDLE ClientMutex; /* A copy of the client handle to our mutex */
|
||||
HANDLE ClientProcess; /* Handle to the client process who opened the buffer, to unmap the view */
|
||||
} GRAPHICS_SCREEN_BUFFER, *PGRAPHICS_SCREEN_BUFFER;
|
||||
|
||||
|
||||
|
||||
typedef struct _CONSOLE_INPUT_BUFFER
|
||||
{
|
||||
CONSOLE_IO_OBJECT Header; /* Object header - MUST BE IN FIRST PLACE */
|
||||
|
||||
ULONG InputBufferSize; /* Size of this input buffer */
|
||||
LIST_ENTRY InputEvents; /* List head for input event queue */
|
||||
HANDLE ActiveEvent; /* Event set when an input event is added in its queue */
|
||||
LIST_ENTRY ReadWaitQueue; /* List head for the queue of read wait blocks */
|
||||
|
||||
USHORT Mode; /* Input buffer modes */
|
||||
} CONSOLE_INPUT_BUFFER, *PCONSOLE_INPUT_BUFFER;
|
||||
|
||||
|
||||
typedef struct _FRONTEND FRONTEND, *PFRONTEND;
|
||||
/* HACK: */ typedef struct _CONSOLE_INFO *PCONSOLE_INFO;
|
||||
typedef struct _FRONTEND_VTBL
|
||||
{
|
||||
/*
|
||||
* Internal interface (functions called by the console server only)
|
||||
*/
|
||||
NTSTATUS (WINAPI *InitFrontEnd)(IN OUT PFRONTEND This,
|
||||
IN struct _CONSOLE* Console);
|
||||
VOID (WINAPI *DeinitFrontEnd)(IN OUT PFRONTEND This);
|
||||
|
||||
/* Interface used for both text-mode and graphics screen buffers */
|
||||
VOID (WINAPI *DrawRegion)(IN OUT PFRONTEND This,
|
||||
SMALL_RECT* Region);
|
||||
/* Interface used only for text-mode screen buffers */
|
||||
VOID (WINAPI *WriteStream)(IN OUT PFRONTEND This,
|
||||
SMALL_RECT* Block,
|
||||
SHORT CursorStartX,
|
||||
SHORT CursorStartY,
|
||||
UINT ScrolledLines,
|
||||
PWCHAR Buffer,
|
||||
UINT Length);
|
||||
BOOL (WINAPI *SetCursorInfo)(IN OUT PFRONTEND This,
|
||||
PCONSOLE_SCREEN_BUFFER ScreenBuffer);
|
||||
BOOL (WINAPI *SetScreenInfo)(IN OUT PFRONTEND This,
|
||||
PCONSOLE_SCREEN_BUFFER ScreenBuffer,
|
||||
SHORT OldCursorX,
|
||||
SHORT OldCursorY);
|
||||
VOID (WINAPI *ResizeTerminal)(IN OUT PFRONTEND This);
|
||||
BOOL (WINAPI *ProcessKeyCallback)(IN OUT PFRONTEND This,
|
||||
MSG* msg,
|
||||
BYTE KeyStateMenu,
|
||||
DWORD ShiftState,
|
||||
UINT VirtualKeyCode,
|
||||
BOOL Down);
|
||||
VOID (WINAPI *RefreshInternalInfo)(IN OUT PFRONTEND This);
|
||||
|
||||
/*
|
||||
* External interface (functions corresponding to the Console API)
|
||||
*/
|
||||
VOID (WINAPI *ChangeTitle)(IN OUT PFRONTEND This);
|
||||
BOOL (WINAPI *ChangeIcon)(IN OUT PFRONTEND This,
|
||||
HICON hWindowIcon);
|
||||
HWND (WINAPI *GetConsoleWindowHandle)(IN OUT PFRONTEND This);
|
||||
VOID (WINAPI *GetLargestConsoleWindowSize)(IN OUT PFRONTEND This,
|
||||
PCOORD pSize);
|
||||
ULONG (WINAPI *GetDisplayMode)(IN OUT PFRONTEND This);
|
||||
BOOL (WINAPI *SetDisplayMode)(IN OUT PFRONTEND This,
|
||||
ULONG NewMode);
|
||||
INT (WINAPI *ShowMouseCursor)(IN OUT PFRONTEND This,
|
||||
BOOL Show);
|
||||
BOOL (WINAPI *SetMouseCursor)(IN OUT PFRONTEND This,
|
||||
HCURSOR hCursor);
|
||||
HMENU (WINAPI *MenuControl)(IN OUT PFRONTEND This,
|
||||
UINT cmdIdLow,
|
||||
UINT cmdIdHigh);
|
||||
BOOL (WINAPI *SetMenuClose)(IN OUT PFRONTEND This,
|
||||
BOOL Enable);
|
||||
|
||||
#if 0 // Possible future front-end interface
|
||||
BOOL (WINAPI *GetFrontEndProperty)(IN OUT PFRONTEND This,
|
||||
ULONG Flag,
|
||||
PVOID Info,
|
||||
ULONG Size);
|
||||
BOOL (WINAPI *SetFrontEndProperty)(IN OUT PFRONTEND This,
|
||||
ULONG Flag,
|
||||
PVOID Info /*,
|
||||
ULONG Size */);
|
||||
#endif
|
||||
} FRONTEND_VTBL, *PFRONTEND_VTBL;
|
||||
|
||||
struct _FRONTEND
|
||||
{
|
||||
PFRONTEND_VTBL Vtbl; /* Virtual table */
|
||||
struct _CONSOLE* Console; /* Console to which the frontend is attached to */
|
||||
PVOID Data; /* Private data */
|
||||
PVOID OldData; /* Reserved */
|
||||
};
|
||||
|
||||
/*
|
||||
* WARNING: Change the state of the console ONLY when the console is locked !
|
||||
*/
|
||||
typedef enum _CONSOLE_STATE
|
||||
{
|
||||
CONSOLE_INITIALIZING, /* Console is initializing */
|
||||
CONSOLE_RUNNING , /* Console running */
|
||||
CONSOLE_TERMINATING , /* Console about to be destroyed (but still not) */
|
||||
CONSOLE_IN_DESTRUCTION /* Console in destruction */
|
||||
} CONSOLE_STATE, *PCONSOLE_STATE;
|
||||
|
||||
typedef struct _CONSOLE
|
||||
{
|
||||
LONG ReferenceCount; /* Is incremented each time a handle to something in the console (a screen-buffer or the input buffer of this console) gets referenced */
|
||||
CRITICAL_SECTION Lock;
|
||||
CONSOLE_STATE State; /* State of the console */
|
||||
|
||||
LIST_ENTRY ProcessList; /* List of processes owning the console. The first one is the so-called "Console Leader Process" */
|
||||
|
||||
FRONTEND TermIFace; /* Frontend-specific interface */
|
||||
|
||||
/**************************** Input buffer and data ***************************/
|
||||
CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */
|
||||
|
||||
/** Put those things in TEXTMODE_SCREEN_BUFFER ?? **/
|
||||
PWCHAR LineBuffer; /* Current line being input, in line buffered mode */
|
||||
WORD LineMaxSize; /* Maximum size of line in characters (including CR+LF) */
|
||||
WORD LineSize; /* Current size of line */
|
||||
WORD LinePos; /* Current position within line */
|
||||
BOOLEAN LineComplete; /* User pressed enter, ready to send back to client */
|
||||
BOOLEAN LineUpPressed;
|
||||
BOOLEAN LineInsertToggle; /* Replace character over cursor instead of inserting */
|
||||
ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */
|
||||
/***************************************************/
|
||||
|
||||
BOOLEAN QuickEdit;
|
||||
BOOLEAN InsertMode;
|
||||
UINT CodePage;
|
||||
|
||||
CONSOLE_SELECTION_INFO Selection; /* Contains information about the selection */
|
||||
COORD dwSelectionCursor; /* Selection cursor position, most of the time different from Selection.dwSelectionAnchor */
|
||||
|
||||
/******************************* Screen buffers *******************************/
|
||||
LIST_ENTRY BufferList; /* List of all screen buffers for this console */
|
||||
PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
|
||||
BYTE PauseFlags;
|
||||
HANDLE UnpauseEvent;
|
||||
LIST_ENTRY WriteWaitQueue; /* List head for the queue of write wait blocks */
|
||||
UINT OutputCodePage;
|
||||
|
||||
/**************************** Aliases and Histories ***************************/
|
||||
struct _ALIAS_HEADER *Aliases;
|
||||
LIST_ENTRY HistoryBuffers;
|
||||
ULONG HistoryBufferSize; /* Size for newly created history buffers */
|
||||
ULONG NumberOfHistoryBuffers; /* Maximum number of history buffers allowed */
|
||||
BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */
|
||||
|
||||
/****************************** 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 */
|
||||
|
||||
COORD ConsoleSize; /* The current size of the console, for text-mode only */
|
||||
BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
|
||||
|
||||
COLORREF Colors[16]; /* Colour palette */
|
||||
|
||||
} CONSOLE, *PCONSOLE;
|
||||
|
||||
/* PauseFlags values (internal only) */
|
||||
#define PAUSED_FROM_KEYBOARD 0x1
|
||||
#define PAUSED_FROM_SCROLLBAR 0x2
|
||||
#define PAUSED_FROM_SELECTION 0x4
|
||||
|
||||
/* console.c */
|
||||
VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags);
|
||||
VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
|
||||
IN ULONG ProcessGroupId,
|
||||
IN ULONG Event);
|
||||
|
||||
/* coninput.c */
|
||||
VOID WINAPI ConioProcessKey(PCONSOLE Console, MSG* msg);
|
||||
NTSTATUS FASTCALL ConioProcessInputEvent(PCONSOLE Console,
|
||||
PINPUT_RECORD InputEvent);
|
||||
|
||||
/* conoutput.c */
|
||||
#define ConioInitRect(Rect, top, left, bottom, right) \
|
||||
do { \
|
||||
((Rect)->Top) = top; \
|
||||
((Rect)->Left) = left; \
|
||||
((Rect)->Bottom) = bottom; \
|
||||
((Rect)->Right) = right; \
|
||||
} while (0)
|
||||
#define ConioIsRectEmpty(Rect) \
|
||||
(((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
|
||||
#define ConioRectHeight(Rect) \
|
||||
(((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1)
|
||||
#define ConioRectWidth(Rect) \
|
||||
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
|
||||
|
||||
#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
|
||||
WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
|
||||
|
||||
#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
|
||||
MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
|
||||
|
||||
PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y);
|
||||
VOID FASTCALL ConioDrawConsole(PCONSOLE Console);
|
||||
NTSTATUS ConioResizeBuffer(PCONSOLE Console,
|
||||
PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
||||
COORD Size);
|
||||
NTSTATUS ConioWriteConsole(PCONSOLE Console,
|
||||
PTEXTMODE_SCREEN_BUFFER Buff,
|
||||
PWCHAR Buffer,
|
||||
DWORD Length,
|
||||
BOOL Attrib);
|
||||
DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console,
|
||||
DWORD Scale);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/conio.h
|
||||
* PURPOSE: Internal Console I/O Interface
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Macros used to call functions in the FRONTEND_VTBL virtual table */
|
||||
|
||||
#define ConioDrawRegion(Console, Region) \
|
||||
(Console)->TermIFace.Vtbl->DrawRegion(&(Console)->TermIFace, (Region))
|
||||
#define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \
|
||||
(Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (Block), (CurStartX), (CurStartY), \
|
||||
(ScrolledLines), (Buffer), (Length))
|
||||
#define ConioSetCursorInfo(Console, Buff) \
|
||||
(Console)->TermIFace.Vtbl->SetCursorInfo(&(Console)->TermIFace, (Buff))
|
||||
#define ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY) \
|
||||
(Console)->TermIFace.Vtbl->SetScreenInfo(&(Console)->TermIFace, (Buff), (OldCursorX), (OldCursorY))
|
||||
#define ConioResizeTerminal(Console) \
|
||||
(Console)->TermIFace.Vtbl->ResizeTerminal(&(Console)->TermIFace)
|
||||
#define ConioProcessKeyCallback(Console, Msg, KeyStateMenu, ShiftState, VirtualKeyCode, Down) \
|
||||
(Console)->TermIFace.Vtbl->ProcessKeyCallback(&(Console)->TermIFace, (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down))
|
||||
#define ConioRefreshInternalInfo(Console) \
|
||||
(Console)->TermIFace.Vtbl->RefreshInternalInfo(&(Console)->TermIFace)
|
||||
|
||||
#define ConioChangeTitle(Console) \
|
||||
(Console)->TermIFace.Vtbl->ChangeTitle(&(Console)->TermIFace)
|
||||
#define ConioChangeIcon(Console, hWindowIcon) \
|
||||
(Console)->TermIFace.Vtbl->ChangeIcon(&(Console)->TermIFace, (hWindowIcon))
|
||||
#define ConioGetConsoleWindowHandle(Console) \
|
||||
(Console)->TermIFace.Vtbl->GetConsoleWindowHandle(&(Console)->TermIFace)
|
||||
#define ConioGetLargestConsoleWindowSize(Console, pSize) \
|
||||
(Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize(&(Console)->TermIFace, (pSize))
|
||||
#define ConioGetDisplayMode(Console) \
|
||||
(Console)->TermIFace.Vtbl->GetDisplayMode(&(Console)->TermIFace)
|
||||
#define ConioSetDisplayMode(Console, NewMode) \
|
||||
(Console)->TermIFace.Vtbl->SetDisplayMode(&(Console)->TermIFace, (NewMode))
|
||||
#define ConioShowMouseCursor(Console, Show) \
|
||||
(Console)->TermIFace.Vtbl->ShowMouseCursor(&(Console)->TermIFace, (Show))
|
||||
#define ConioSetMouseCursor(Console, hCursor) \
|
||||
(Console)->TermIFace.Vtbl->SetMouseCursor(&(Console)->TermIFace, (hCursor))
|
||||
#define ConioMenuControl(Console, CmdIdLow, CmdIdHigh) \
|
||||
(Console)->TermIFace.Vtbl->MenuControl(&(Console)->TermIFace, (CmdIdLow), (CmdIdHigh))
|
||||
#define ConioSetMenuClose(Console, Enable) \
|
||||
(Console)->TermIFace.Vtbl->SetMenuClose(&(Console)->TermIFace, (Enable))
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/include/console.h
|
||||
* PURPOSE: Public Console Management Interface
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
VOID NTAPI
|
||||
ConDrvInitConsoleSupport(VOID);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
||||
OUT PCONSOLE* NewConsole,
|
||||
IN PCONSOLE_INFO ConsoleInfo,
|
||||
IN ULONG ConsoleLeaderProcessId);
|
||||
NTSTATUS NTAPI
|
||||
ConDrvRegisterFrontEnd(IN PCONSOLE Console,
|
||||
IN PFRONTEND FrontEnd);
|
||||
NTSTATUS NTAPI
|
||||
ConDrvDeregisterFrontEnd(IN PCONSOLE Console);
|
||||
VOID NTAPI
|
||||
ConDrvDeleteConsole(IN PCONSOLE Console);
|
||||
|
||||
|
||||
|
||||
BOOLEAN NTAPI
|
||||
ConDrvValidateConsoleState(IN PCONSOLE Console,
|
||||
IN CONSOLE_STATE ExpectedState);
|
||||
|
||||
BOOLEAN NTAPI
|
||||
ConDrvValidateConsoleUnsafe(IN PCONSOLE Console,
|
||||
IN CONSOLE_STATE ExpectedState,
|
||||
IN BOOLEAN LockConsole);
|
||||
|
||||
BOOLEAN NTAPI
|
||||
ConDrvValidateConsole(OUT PCONSOLE* Console,
|
||||
IN HANDLE ConsoleHandle,
|
||||
IN CONSOLE_STATE ExpectedState,
|
||||
IN BOOLEAN LockConsole);
|
||||
|
||||
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsole(OUT PCONSOLE* Console,
|
||||
IN HANDLE ConsoleHandle,
|
||||
IN BOOLEAN LockConsole);
|
||||
VOID NTAPI
|
||||
ConDrvReleaseConsole(IN PCONSOLE Console,
|
||||
IN BOOLEAN WasConsoleLocked);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/include/settings.h
|
||||
* PURPOSE: Public Console Settings Management Interface
|
||||
* PROGRAMMERS: Johannes Anderwald
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* STRUCTURES *****************************************************************/
|
||||
|
||||
/*
|
||||
* Structure used to hold terminal-specific information
|
||||
*/
|
||||
typedef struct _TERMINAL_INFO
|
||||
{
|
||||
ULONG Size; /* Size of the memory buffer pointed by TermInfo */
|
||||
PVOID TermInfo; /* Address (or offset when talking to console.dll) of the memory buffer holding terminal information */
|
||||
} TERMINAL_INFO, *PTERMINAL_INFO;
|
||||
|
||||
/*
|
||||
* Structure used to hold console information
|
||||
*/
|
||||
typedef struct _CONSOLE_INFO
|
||||
{
|
||||
ULONG HistoryBufferSize;
|
||||
ULONG NumberOfHistoryBuffers;
|
||||
BOOLEAN HistoryNoDup;
|
||||
|
||||
BOOLEAN QuickEdit;
|
||||
BOOLEAN InsertMode;
|
||||
ULONG InputBufferSize;
|
||||
COORD ScreenBufferSize;
|
||||
COORD ConsoleSize; /* The size of the console */
|
||||
|
||||
BOOLEAN CursorBlinkOn;
|
||||
BOOLEAN ForceCursorOff;
|
||||
ULONG CursorSize;
|
||||
|
||||
USHORT ScreenAttrib; // CHAR_INFO ScreenFillAttrib
|
||||
USHORT PopupAttrib;
|
||||
|
||||
COLORREF Colors[16]; /* Color palette */
|
||||
|
||||
ULONG CodePage;
|
||||
|
||||
WCHAR ConsoleTitle[MAX_PATH + 1];
|
||||
} CONSOLE_INFO, *PCONSOLE_INFO;
|
||||
|
||||
#define RGBFromAttrib(Console, Attribute) ((Console)->Colors[(Attribute) & 0xF])
|
||||
#define TextAttribFromAttrib(Attribute) ((Attribute) & 0xF)
|
||||
#define BkgdAttribFromAttrib(Attribute) (((Attribute) >> 4) & 0xF)
|
||||
#define MakeAttrib(TextAttrib, BkgdAttrib) (DWORD)((((BkgdAttrib) & 0xF) << 4) | ((TextAttrib) & 0xF))
|
||||
|
||||
/*
|
||||
* Structure used to communicate with console.dll
|
||||
*/
|
||||
typedef struct _CONSOLE_PROPS
|
||||
{
|
||||
HWND hConsoleWindow;
|
||||
BOOL ShowDefaultParams;
|
||||
|
||||
BOOLEAN AppliedConfig;
|
||||
DWORD ActiveStaticControl;
|
||||
|
||||
CONSOLE_INFO ci; /* Console-specific informations */
|
||||
TERMINAL_INFO TerminalInfo; /* Frontend-specific parameters */
|
||||
} CONSOLE_PROPS, *PCONSOLE_PROPS;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
#ifndef CONSOLE_H__ // If we aren't included by console.dll
|
||||
|
||||
BOOL ConSrvOpenUserSettings(DWORD ProcessId,
|
||||
LPCWSTR ConsoleTitle,
|
||||
PHKEY hSubKey,
|
||||
REGSAM samDesired,
|
||||
BOOL bCreate);
|
||||
|
||||
BOOL ConSrvReadUserSettings(IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN DWORD ProcessId);
|
||||
BOOL ConSrvWriteUserSettings(IN PCONSOLE_INFO ConsoleInfo,
|
||||
IN DWORD ProcessId);
|
||||
VOID ConSrvGetDefaultSettings(IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN DWORD ProcessId);
|
||||
VOID ConSrvApplyUserSettings(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INFO ConsoleInfo);
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/init.c
|
||||
* PURPOSE: Initialization
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "api.h"
|
||||
#include "procinit.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/console.h"
|
||||
#include "console.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
HINSTANCE ConSrvDllInstance = NULL;
|
||||
|
||||
/* Memory */
|
||||
HANDLE ConSrvHeap = NULL; // Our own heap.
|
||||
|
||||
// Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
|
||||
// plus a little bit of Windows 7.
|
||||
PCSR_API_ROUTINE ConsoleServerApiDispatchTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
|
||||
{
|
||||
SrvOpenConsole,
|
||||
SrvGetConsoleInput,
|
||||
SrvWriteConsoleInput,
|
||||
SrvReadConsoleOutput,
|
||||
SrvWriteConsoleOutput,
|
||||
SrvReadConsoleOutputString,
|
||||
SrvWriteConsoleOutputString,
|
||||
SrvFillConsoleOutput,
|
||||
SrvGetConsoleMode,
|
||||
// SrvGetConsoleNumberOfFonts,
|
||||
SrvGetConsoleNumberOfInputEvents,
|
||||
SrvGetConsoleScreenBufferInfo,
|
||||
SrvGetConsoleCursorInfo,
|
||||
// SrvGetConsoleMouseInfo,
|
||||
// SrvGetConsoleFontInfo,
|
||||
// SrvGetConsoleFontSize,
|
||||
// SrvGetConsoleCurrentFont,
|
||||
SrvSetConsoleMode,
|
||||
SrvSetConsoleActiveScreenBuffer,
|
||||
SrvFlushConsoleInputBuffer,
|
||||
SrvGetLargestConsoleWindowSize,
|
||||
SrvSetConsoleScreenBufferSize,
|
||||
SrvSetConsoleCursorPosition,
|
||||
SrvSetConsoleCursorInfo,
|
||||
SrvSetConsoleWindowInfo,
|
||||
SrvScrollConsoleScreenBuffer,
|
||||
SrvSetConsoleTextAttribute,
|
||||
// SrvSetConsoleFont,
|
||||
SrvSetConsoleIcon,
|
||||
SrvReadConsole,
|
||||
SrvWriteConsole,
|
||||
SrvDuplicateHandle,
|
||||
// SrvGetHandleInformation,
|
||||
// SrvSetHandleInformation,
|
||||
SrvCloseHandle,
|
||||
SrvVerifyConsoleIoHandle,
|
||||
SrvAllocConsole,
|
||||
SrvFreeConsole,
|
||||
SrvGetConsoleTitle,
|
||||
SrvSetConsoleTitle,
|
||||
SrvCreateConsoleScreenBuffer,
|
||||
SrvInvalidateBitMapRect,
|
||||
// SrvVDMConsoleOperation,
|
||||
SrvSetConsoleCursor,
|
||||
SrvShowConsoleCursor,
|
||||
SrvConsoleMenuControl,
|
||||
// SrvSetConsolePalette,
|
||||
SrvSetConsoleDisplayMode,
|
||||
// SrvRegisterConsoleVDM,
|
||||
SrvGetConsoleHardwareState,
|
||||
SrvSetConsoleHardwareState,
|
||||
SrvGetConsoleDisplayMode,
|
||||
SrvAddConsoleAlias,
|
||||
SrvGetConsoleAlias,
|
||||
SrvGetConsoleAliasesLength,
|
||||
SrvGetConsoleAliasExesLength,
|
||||
SrvGetConsoleAliases,
|
||||
SrvGetConsoleAliasExes,
|
||||
SrvExpungeConsoleCommandHistory,
|
||||
SrvSetConsoleNumberOfCommands,
|
||||
SrvGetConsoleCommandHistoryLength,
|
||||
SrvGetConsoleCommandHistory,
|
||||
// SrvSetConsoleCommandHistoryMode,
|
||||
SrvGetConsoleCP,
|
||||
SrvSetConsoleCP,
|
||||
// SrvSetConsoleKeyShortcuts,
|
||||
SrvSetConsoleMenuClose,
|
||||
// SrvConsoleNotifyLastClose,
|
||||
SrvGenerateConsoleCtrlEvent,
|
||||
// SrvGetConsoleKeyboardLayoutName,
|
||||
SrvGetConsoleWindow,
|
||||
// SrvGetConsoleCharType,
|
||||
// SrvSetConsoleLocalEUDC,
|
||||
// SrvSetConsoleCursorMode,
|
||||
// SrvGetConsoleCursorMode,
|
||||
// SrvRegisterConsoleOS2,
|
||||
// SrvSetConsoleOS2OemFormat,
|
||||
// SrvGetConsoleNlsMode,
|
||||
// SrvSetConsoleNlsMode,
|
||||
// SrvRegisterConsoleIME,
|
||||
// SrvUnregisterConsoleIME,
|
||||
// SrvGetConsoleLangId,
|
||||
SrvAttachConsole,
|
||||
SrvGetConsoleSelectionInfo,
|
||||
SrvGetConsoleProcessList,
|
||||
SrvGetConsoleHistory,
|
||||
SrvSetConsoleHistory,
|
||||
};
|
||||
|
||||
BOOLEAN ConsoleServerApiServerValidTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
|
||||
{
|
||||
FALSE, // SrvOpenConsole,
|
||||
FALSE, // SrvGetConsoleInput,
|
||||
FALSE, // SrvWriteConsoleInput,
|
||||
FALSE, // SrvReadConsoleOutput,
|
||||
FALSE, // SrvWriteConsoleOutput,
|
||||
FALSE, // SrvReadConsoleOutputString,
|
||||
FALSE, // SrvWriteConsoleOutputString,
|
||||
FALSE, // SrvFillConsoleOutput,
|
||||
FALSE, // SrvGetConsoleMode,
|
||||
// FALSE, // SrvGetConsoleNumberOfFonts,
|
||||
FALSE, // SrvGetConsoleNumberOfInputEvents,
|
||||
FALSE, // SrvGetConsoleScreenBufferInfo,
|
||||
FALSE, // SrvGetConsoleCursorInfo,
|
||||
// FALSE, // SrvGetConsoleMouseInfo,
|
||||
// FALSE, // SrvGetConsoleFontInfo,
|
||||
// FALSE, // SrvGetConsoleFontSize,
|
||||
// FALSE, // SrvGetConsoleCurrentFont,
|
||||
FALSE, // SrvSetConsoleMode,
|
||||
FALSE, // SrvSetConsoleActiveScreenBuffer,
|
||||
FALSE, // SrvFlushConsoleInputBuffer,
|
||||
FALSE, // SrvGetLargestConsoleWindowSize,
|
||||
FALSE, // SrvSetConsoleScreenBufferSize,
|
||||
FALSE, // SrvSetConsoleCursorPosition,
|
||||
FALSE, // SrvSetConsoleCursorInfo,
|
||||
FALSE, // SrvSetConsoleWindowInfo,
|
||||
FALSE, // SrvScrollConsoleScreenBuffer,
|
||||
FALSE, // SrvSetConsoleTextAttribute,
|
||||
// FALSE, // SrvSetConsoleFont,
|
||||
FALSE, // SrvSetConsoleIcon,
|
||||
FALSE, // SrvReadConsole,
|
||||
FALSE, // SrvWriteConsole,
|
||||
FALSE, // SrvDuplicateHandle,
|
||||
// FALSE, // SrvGetHandleInformation,
|
||||
// FALSE, // SrvSetHandleInformation,
|
||||
FALSE, // SrvCloseHandle,
|
||||
FALSE, // SrvVerifyConsoleIoHandle,
|
||||
FALSE, // SrvAllocConsole,
|
||||
FALSE, // SrvFreeConsole,
|
||||
FALSE, // SrvGetConsoleTitle,
|
||||
FALSE, // SrvSetConsoleTitle,
|
||||
FALSE, // SrvCreateConsoleScreenBuffer,
|
||||
FALSE, // SrvInvalidateBitMapRect,
|
||||
// FALSE, // SrvVDMConsoleOperation,
|
||||
FALSE, // SrvSetConsoleCursor,
|
||||
FALSE, // SrvShowConsoleCursor,
|
||||
FALSE, // SrvConsoleMenuControl,
|
||||
// FALSE, // SrvSetConsolePalette,
|
||||
FALSE, // SrvSetConsoleDisplayMode,
|
||||
// FALSE, // SrvRegisterConsoleVDM,
|
||||
FALSE, // SrvGetConsoleHardwareState,
|
||||
FALSE, // SrvSetConsoleHardwareState,
|
||||
TRUE, // SrvGetConsoleDisplayMode,
|
||||
FALSE, // SrvAddConsoleAlias,
|
||||
FALSE, // SrvGetConsoleAlias,
|
||||
FALSE, // SrvGetConsoleAliasesLength,
|
||||
FALSE, // SrvGetConsoleAliasExesLength,
|
||||
FALSE, // SrvGetConsoleAliases,
|
||||
FALSE, // SrvGetConsoleAliasExes,
|
||||
FALSE, // SrvExpungeConsoleCommandHistory,
|
||||
FALSE, // SrvSetConsoleNumberOfCommands,
|
||||
FALSE, // SrvGetConsoleCommandHistoryLength,
|
||||
FALSE, // SrvGetConsoleCommandHistory,
|
||||
// FALSE, // SrvSetConsoleCommandHistoryMode,
|
||||
FALSE, // SrvGetConsoleCP,
|
||||
FALSE, // SrvSetConsoleCP,
|
||||
// FALSE, // SrvSetConsoleKeyShortcuts,
|
||||
FALSE, // SrvSetConsoleMenuClose,
|
||||
// FALSE, // SrvConsoleNotifyLastClose,
|
||||
FALSE, // SrvGenerateConsoleCtrlEvent,
|
||||
// FALSE, // SrvGetConsoleKeyboardLayoutName,
|
||||
FALSE, // SrvGetConsoleWindow,
|
||||
// FALSE, // SrvGetConsoleCharType,
|
||||
// FALSE, // SrvSetConsoleLocalEUDC,
|
||||
// FALSE, // SrvSetConsoleCursorMode,
|
||||
// FALSE, // SrvGetConsoleCursorMode,
|
||||
// FALSE, // SrvRegisterConsoleOS2,
|
||||
// FALSE, // SrvSetConsoleOS2OemFormat,
|
||||
// FALSE, // SrvGetConsoleNlsMode,
|
||||
// FALSE, // SrvSetConsoleNlsMode,
|
||||
// FALSE, // SrvRegisterConsoleIME,
|
||||
// FALSE, // SrvUnregisterConsoleIME,
|
||||
// FALSE, // SrvGetConsoleLangId,
|
||||
FALSE, // SrvAttachConsole,
|
||||
FALSE, // SrvGetConsoleSelectionInfo,
|
||||
FALSE, // SrvGetConsoleProcessList,
|
||||
FALSE, // SrvGetConsoleHistory,
|
||||
FALSE, // SrvSetConsoleHistory
|
||||
};
|
||||
|
||||
PCHAR ConsoleServerApiNameTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
|
||||
{
|
||||
"OpenConsole",
|
||||
"GetConsoleInput",
|
||||
"WriteConsoleInput",
|
||||
"ReadConsoleOutput",
|
||||
"WriteConsoleOutput",
|
||||
"ReadConsoleOutputString",
|
||||
"WriteConsoleOutputString",
|
||||
"FillConsoleOutput",
|
||||
"GetConsoleMode",
|
||||
// "GetConsoleNumberOfFonts",
|
||||
"GetConsoleNumberOfInputEvents",
|
||||
"GetConsoleScreenBufferInfo",
|
||||
"GetConsoleCursorInfo",
|
||||
// "GetConsoleMouseInfo",
|
||||
// "GetConsoleFontInfo",
|
||||
// "GetConsoleFontSize",
|
||||
// "GetConsoleCurrentFont",
|
||||
"SetConsoleMode",
|
||||
"SetConsoleActiveScreenBuffer",
|
||||
"FlushConsoleInputBuffer",
|
||||
"GetLargestConsoleWindowSize",
|
||||
"SetConsoleScreenBufferSize",
|
||||
"SetConsoleCursorPosition",
|
||||
"SetConsoleCursorInfo",
|
||||
"SetConsoleWindowInfo",
|
||||
"ScrollConsoleScreenBuffer",
|
||||
"SetConsoleTextAttribute",
|
||||
// "SetConsoleFont",
|
||||
"SetConsoleIcon",
|
||||
"ReadConsole",
|
||||
"WriteConsole",
|
||||
"DuplicateHandle",
|
||||
// "GetHandleInformation",
|
||||
// "SetHandleInformation",
|
||||
"CloseHandle",
|
||||
"VerifyConsoleIoHandle",
|
||||
"AllocConsole",
|
||||
"FreeConsole",
|
||||
"GetConsoleTitle",
|
||||
"SetConsoleTitle",
|
||||
"CreateConsoleScreenBuffer",
|
||||
"InvalidateBitMapRect",
|
||||
// "VDMConsoleOperation",
|
||||
"SetConsoleCursor",
|
||||
"ShowConsoleCursor",
|
||||
"ConsoleMenuControl",
|
||||
// "SetConsolePalette",
|
||||
"SetConsoleDisplayMode",
|
||||
// "RegisterConsoleVDM",
|
||||
"GetConsoleHardwareState",
|
||||
"SetConsoleHardwareState",
|
||||
"GetConsoleDisplayMode",
|
||||
"AddConsoleAlias",
|
||||
"GetConsoleAlias",
|
||||
"GetConsoleAliasesLength",
|
||||
"GetConsoleAliasExesLength",
|
||||
"GetConsoleAliases",
|
||||
"GetConsoleAliasExes",
|
||||
"ExpungeConsoleCommandHistory",
|
||||
"SetConsoleNumberOfCommands",
|
||||
"GetConsoleCommandHistoryLength",
|
||||
"GetConsoleCommandHistory",
|
||||
// "SetConsoleCommandHistoryMode",
|
||||
"GetConsoleCP",
|
||||
"SetConsoleCP",
|
||||
// "SetConsoleKeyShortcuts",
|
||||
"SetConsoleMenuClose",
|
||||
// "ConsoleNotifyLastClose",
|
||||
"GenerateConsoleCtrlEvent",
|
||||
// "GetConsoleKeyboardLayoutName",
|
||||
"GetConsoleWindow",
|
||||
// "GetConsoleCharType",
|
||||
// "SetConsoleLocalEUDC",
|
||||
// "SetConsoleCursorMode",
|
||||
// "GetConsoleCursorMode",
|
||||
// "RegisterConsoleOS2",
|
||||
// "SetConsoleOS2OemFormat",
|
||||
// "GetConsoleNlsMode",
|
||||
// "SetConsoleNlsMode",
|
||||
// "RegisterConsoleIME",
|
||||
// "UnregisterConsoleIME",
|
||||
// "GetConsoleLangId",
|
||||
"AttachConsole",
|
||||
"GetConsoleSelectionInfo",
|
||||
"GetConsoleProcessList",
|
||||
"GetConsoleHistory",
|
||||
"SetConsoleHistory",
|
||||
};
|
||||
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/* See handle.c */
|
||||
NTSTATUS
|
||||
ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
|
||||
IN PCONSOLE_PROCESS_DATA TargetProcessData);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConSrvNewProcess(PCSR_PROCESS SourceProcess,
|
||||
PCSR_PROCESS TargetProcess)
|
||||
{
|
||||
/**************************************************************************
|
||||
* This function is called whenever a new process (GUI or CUI) is created.
|
||||
*
|
||||
* Copy the parent's handles table here if both the parent and the child
|
||||
* processes are CUI. If we must actually create our proper console (and
|
||||
* thus do not inherit from the console handles of the parent's), then we
|
||||
* will clean this table in the next ConSrvConnect call. Why we are doing
|
||||
* this? It's because here, we still don't know whether or not we must create
|
||||
* a new console instead of inherit it from the parent, and, because in
|
||||
* ConSrvConnect we don't have any reference to the parent process anymore.
|
||||
**************************************************************************/
|
||||
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE_PROCESS_DATA TargetProcessData;
|
||||
|
||||
/* An empty target process is invalid */
|
||||
if (!TargetProcess) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
|
||||
|
||||
/* Initialize the new (target) process */
|
||||
RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
|
||||
TargetProcessData->Process = TargetProcess;
|
||||
TargetProcessData->ConsoleEvent = NULL;
|
||||
TargetProcessData->ConsoleHandle = TargetProcessData->ParentConsoleHandle = NULL;
|
||||
TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
|
||||
|
||||
/*
|
||||
* The handles table gets initialized either when inheriting from
|
||||
* another console process, or when creating a new console.
|
||||
*/
|
||||
TargetProcessData->HandleTableSize = 0;
|
||||
TargetProcessData->HandleTable = NULL;
|
||||
|
||||
RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
|
||||
|
||||
/* Do nothing if the source process is NULL */
|
||||
if (!SourceProcess) return STATUS_SUCCESS;
|
||||
|
||||
// SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
|
||||
|
||||
/*
|
||||
* If the child process is a console application and the parent process is
|
||||
* either a console application or just has a valid console (with a valid
|
||||
* handles table: this can happen if it is a GUI application having called
|
||||
* AllocConsole), then try to inherit handles from the parent process.
|
||||
*/
|
||||
if (TargetProcessData->ConsoleApp /* && SourceProcessData->ConsoleApp */)
|
||||
{
|
||||
PCONSOLE_PROCESS_DATA SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
|
||||
PCONSOLE SourceConsole;
|
||||
|
||||
/* Validate and lock the parent's console */
|
||||
if (ConDrvValidateConsole(&SourceConsole,
|
||||
SourceProcessData->ConsoleHandle,
|
||||
CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
/* Inherit the parent's handles table */
|
||||
Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Temporary save the parent's console too */
|
||||
TargetProcessData->ParentConsoleHandle = SourceProcessData->ConsoleHandle;
|
||||
}
|
||||
|
||||
/* Unlock the parent's console */
|
||||
LeaveCriticalSection(&SourceConsole->Lock);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConSrvConnect(IN PCSR_PROCESS CsrProcess,
|
||||
IN OUT PVOID ConnectionInfo,
|
||||
IN OUT PULONG ConnectionInfoLength)
|
||||
{
|
||||
/**************************************************************************
|
||||
* This function is called whenever a CUI new process is created.
|
||||
**************************************************************************/
|
||||
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
|
||||
|
||||
if ( ConnectionInfo == NULL ||
|
||||
ConnectionInfoLength == NULL ||
|
||||
*ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
|
||||
{
|
||||
DPRINT1("CONSRV: Connection failed\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* If we don't need a console, then get out of here */
|
||||
if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* If we don't have a console, then create a new one... */
|
||||
if (!ConnectInfo->ConsoleHandle ||
|
||||
ConnectInfo->ConsoleHandle != ProcessData->ParentConsoleHandle)
|
||||
{
|
||||
DPRINT("ConSrvConnect - Allocate a new console\n");
|
||||
|
||||
/*
|
||||
* We are about to create a new console. However when ConSrvNewProcess
|
||||
* was called, we didn't know that we wanted to create a new console and
|
||||
* therefore, we by default inherited the handles table from our parent
|
||||
* process. It's only now that we notice that in fact we do not need
|
||||
* them, because we've created a new console and thus we must use it.
|
||||
*
|
||||
* ConSrvAllocateConsole will free our old handles table
|
||||
* and recreate a new valid one.
|
||||
*/
|
||||
|
||||
/* Initialize a new Console owned by the Console Leader Process */
|
||||
Status = ConSrvAllocateConsole(ProcessData,
|
||||
&ConnectInfo->InputHandle,
|
||||
&ConnectInfo->OutputHandle,
|
||||
&ConnectInfo->ErrorHandle,
|
||||
&ConnectInfo->ConsoleStartInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Console allocation failed\n");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else /* We inherit it from the parent */
|
||||
{
|
||||
DPRINT("ConSrvConnect - Reuse current (parent's) console\n");
|
||||
|
||||
/* Reuse our current console */
|
||||
Status = ConSrvInheritConsole(ProcessData,
|
||||
ConnectInfo->ConsoleHandle,
|
||||
FALSE,
|
||||
NULL, // &ConnectInfo->InputHandle,
|
||||
NULL, // &ConnectInfo->OutputHandle,
|
||||
NULL); // &ConnectInfo->ErrorHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Console inheritance failed\n");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the console handle and the input wait handle to the caller */
|
||||
ConnectInfo->ConsoleHandle = ProcessData->ConsoleHandle;
|
||||
ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
|
||||
|
||||
/* Set the Property-Dialog and Control-Dispatcher handlers */
|
||||
ProcessData->PropDispatcher = ConnectInfo->PropDispatcher;
|
||||
ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ConSrvDisconnect(PCSR_PROCESS Process)
|
||||
{
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
|
||||
|
||||
/**************************************************************************
|
||||
* This function is called whenever a new process (GUI or CUI) is destroyed.
|
||||
**************************************************************************/
|
||||
|
||||
if ( ProcessData->ConsoleHandle != NULL ||
|
||||
ProcessData->HandleTable != NULL )
|
||||
{
|
||||
DPRINT("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
|
||||
ConSrvRemoveConsole(ProcessData);
|
||||
}
|
||||
|
||||
RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
|
||||
}
|
||||
|
||||
CSR_SERVER_DLL_INIT(ConServerDllInitialization)
|
||||
{
|
||||
/* Initialize the memory */
|
||||
ConSrvHeap = RtlGetProcessHeap();
|
||||
/*
|
||||
// We can use our own heap instead of the CSR heap to investigate heap corruptions :)
|
||||
ConSrvHeap = RtlCreateHeap(HEAP_GROWABLE |
|
||||
HEAP_PROTECTION_ENABLED |
|
||||
HEAP_FREE_CHECKING_ENABLED |
|
||||
HEAP_TAIL_CHECKING_ENABLED |
|
||||
HEAP_VALIDATE_ALL_ENABLED,
|
||||
NULL, 0, 0, NULL, NULL);
|
||||
if (!ConSrvHeap) return STATUS_NO_MEMORY;
|
||||
*/
|
||||
|
||||
ConDrvInitConsoleSupport();
|
||||
|
||||
/* Setup the DLL Object */
|
||||
LoadedServerDll->ApiBase = CONSRV_FIRST_API_NUMBER;
|
||||
LoadedServerDll->HighestApiSupported = ConsolepMaxApiNumber;
|
||||
LoadedServerDll->DispatchTable = ConsoleServerApiDispatchTable;
|
||||
LoadedServerDll->ValidTable = ConsoleServerApiServerValidTable;
|
||||
LoadedServerDll->NameTable = ConsoleServerApiNameTable;
|
||||
LoadedServerDll->SizeOfProcessData = sizeof(CONSOLE_PROCESS_DATA);
|
||||
LoadedServerDll->ConnectCallback = ConSrvConnect;
|
||||
LoadedServerDll->DisconnectCallback = ConSrvDisconnect;
|
||||
LoadedServerDll->NewProcessCallback = ConSrvNewProcess;
|
||||
// LoadedServerDll->HardErrorCallback = ConSrvHardError;
|
||||
LoadedServerDll->ShutdownProcessCallback = NULL;
|
||||
|
||||
ConSrvDllInstance = LoadedServerDll->ServerHandle;
|
||||
|
||||
/* All done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Eingabeaufforderung"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_GREEK, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "Konsola ReactOS"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,6 @@
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONSOLE_TITLE "ReactOS Console"
|
||||
END
|
||||
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/lineinput.c
|
||||
* PURPOSE: Console line input functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "console.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
typedef struct _HISTORY_BUFFER
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
UINT Position;
|
||||
UINT MaxEntries;
|
||||
UINT NumEntries;
|
||||
PUNICODE_STRING Entries;
|
||||
UNICODE_STRING ExeName;
|
||||
} HISTORY_BUFFER, *PHISTORY_BUFFER;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static PHISTORY_BUFFER
|
||||
HistoryCurrentBuffer(PCONSOLE Console)
|
||||
{
|
||||
/* TODO: use actual EXE name sent from process that called ReadConsole */
|
||||
UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" };
|
||||
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
|
||||
PHISTORY_BUFFER Hist;
|
||||
|
||||
for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
|
||||
{
|
||||
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
||||
if (RtlEqualUnicodeString(&ExeName, &Hist->ExeName, FALSE))
|
||||
return Hist;
|
||||
}
|
||||
|
||||
/* Couldn't find the buffer, create a new one */
|
||||
Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName.Length);
|
||||
if (!Hist) return NULL;
|
||||
Hist->MaxEntries = Console->HistoryBufferSize;
|
||||
Hist->NumEntries = 0;
|
||||
Hist->Entries = ConsoleAllocHeap(0, Hist->MaxEntries * sizeof(UNICODE_STRING));
|
||||
if (!Hist->Entries)
|
||||
{
|
||||
ConsoleFreeHeap(Hist);
|
||||
return NULL;
|
||||
}
|
||||
Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName.Length;
|
||||
Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
|
||||
memcpy(Hist->ExeName.Buffer, ExeName.Buffer, ExeName.Length);
|
||||
InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
|
||||
return Hist;
|
||||
}
|
||||
|
||||
static VOID
|
||||
HistoryAddEntry(PCONSOLE Console)
|
||||
{
|
||||
UNICODE_STRING NewEntry;
|
||||
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
|
||||
INT i;
|
||||
|
||||
if (!Hist) return;
|
||||
|
||||
NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR);
|
||||
NewEntry.Buffer = Console->LineBuffer;
|
||||
|
||||
/* Don't add blank or duplicate entries */
|
||||
if (NewEntry.Length == 0 || Hist->MaxEntries == 0 ||
|
||||
(Hist->NumEntries > 0 &&
|
||||
RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], &NewEntry, FALSE)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Console->HistoryNoDup)
|
||||
{
|
||||
/* Check if this line has been entered before */
|
||||
for (i = Hist->NumEntries - 1; i >= 0; i--)
|
||||
{
|
||||
if (RtlEqualUnicodeString(&Hist->Entries[i], &NewEntry, FALSE))
|
||||
{
|
||||
/* Just rotate the list to bring this entry to the end */
|
||||
NewEntry = Hist->Entries[i];
|
||||
memmove(&Hist->Entries[i], &Hist->Entries[i + 1],
|
||||
(Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING));
|
||||
Hist->Entries[Hist->NumEntries - 1] = NewEntry;
|
||||
Hist->Position = Hist->NumEntries - 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Hist->NumEntries == Hist->MaxEntries)
|
||||
{
|
||||
/* List is full, remove oldest entry */
|
||||
RtlFreeUnicodeString(&Hist->Entries[0]);
|
||||
memmove(&Hist->Entries[0], &Hist->Entries[1],
|
||||
--Hist->NumEntries * sizeof(UNICODE_STRING));
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry, &Hist->Entries[Hist->NumEntries])))
|
||||
Hist->NumEntries++;
|
||||
Hist->Position = Hist->NumEntries - 1;
|
||||
}
|
||||
|
||||
static VOID
|
||||
HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry)
|
||||
{
|
||||
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
|
||||
|
||||
if (!Hist || Hist->NumEntries == 0)
|
||||
Entry->Length = 0;
|
||||
else
|
||||
*Entry = Hist->Entries[Hist->Position];
|
||||
}
|
||||
|
||||
static PHISTORY_BUFFER
|
||||
HistoryFindBuffer(PCONSOLE Console, PUNICODE_STRING ExeName)
|
||||
{
|
||||
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
|
||||
while (Entry != &Console->HistoryBuffers)
|
||||
{
|
||||
/* For the history APIs, the caller is allowed to give only part of the name */
|
||||
PHISTORY_BUFFER Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
||||
if (RtlPrefixUnicodeString(ExeName, &Hist->ExeName, TRUE))
|
||||
return Hist;
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static VOID
|
||||
HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
|
||||
{
|
||||
if (!Hist) return;
|
||||
|
||||
while (Hist->NumEntries != 0)
|
||||
RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]);
|
||||
|
||||
ConsoleFreeHeap(Hist->Entries);
|
||||
RemoveEntryList(&Hist->ListEntry);
|
||||
ConsoleFreeHeap(Hist);
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
HistoryDeleteBuffers(PCONSOLE Console)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PHISTORY_BUFFER HistoryBuffer;
|
||||
|
||||
while (!IsListEmpty(&Console->HistoryBuffers))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&Console->HistoryBuffers);
|
||||
HistoryBuffer = CONTAINING_RECORD(CurrentEntry, HISTORY_BUFFER, ListEntry);
|
||||
HistoryDeleteBuffer(HistoryBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
LineInputSetPos(PCONSOLE Console, UINT Pos)
|
||||
{
|
||||
if (Pos != Console->LinePos && Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
|
||||
{
|
||||
PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
|
||||
SHORT OldCursorX = Buffer->CursorPosition.X;
|
||||
SHORT OldCursorY = Buffer->CursorPosition.Y;
|
||||
INT XY = OldCursorY * Buffer->ScreenBufferSize.X + OldCursorX;
|
||||
|
||||
XY += (Pos - Console->LinePos);
|
||||
if (XY < 0)
|
||||
XY = 0;
|
||||
else if (XY >= Buffer->ScreenBufferSize.Y * Buffer->ScreenBufferSize.X)
|
||||
XY = Buffer->ScreenBufferSize.Y * Buffer->ScreenBufferSize.X - 1;
|
||||
|
||||
Buffer->CursorPosition.X = XY % Buffer->ScreenBufferSize.X;
|
||||
Buffer->CursorPosition.Y = XY / Buffer->ScreenBufferSize.X;
|
||||
ConioSetScreenInfo(Console, Buffer, OldCursorX, OldCursorY);
|
||||
}
|
||||
|
||||
Console->LinePos = Pos;
|
||||
}
|
||||
|
||||
static VOID
|
||||
LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion)
|
||||
{
|
||||
PTEXTMODE_SCREEN_BUFFER ActiveBuffer;
|
||||
UINT Pos = Console->LinePos;
|
||||
UINT NewSize = Console->LineSize - NumToDelete + NumToInsert;
|
||||
UINT i;
|
||||
|
||||
if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER) return;
|
||||
ActiveBuffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer;
|
||||
|
||||
/* Make sure there's always enough room for ending \r\n */
|
||||
if (NewSize + 2 > Console->LineMaxSize)
|
||||
return;
|
||||
|
||||
memmove(&Console->LineBuffer[Pos + NumToInsert],
|
||||
&Console->LineBuffer[Pos + NumToDelete],
|
||||
(Console->LineSize - (Pos + NumToDelete)) * sizeof(WCHAR));
|
||||
memcpy(&Console->LineBuffer[Pos], Insertion, NumToInsert * sizeof(WCHAR));
|
||||
|
||||
if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
|
||||
{
|
||||
for (i = Pos; i < NewSize; i++)
|
||||
{
|
||||
ConioWriteConsole(Console, ActiveBuffer, &Console->LineBuffer[i], 1, TRUE);
|
||||
}
|
||||
for (; i < Console->LineSize; i++)
|
||||
{
|
||||
ConioWriteConsole(Console, ActiveBuffer, L" ", 1, TRUE);
|
||||
}
|
||||
Console->LinePos = i;
|
||||
}
|
||||
|
||||
Console->LineSize = NewSize;
|
||||
LineInputSetPos(Console, Pos + NumToInsert);
|
||||
}
|
||||
|
||||
static VOID
|
||||
LineInputRecallHistory(PCONSOLE Console, INT Offset)
|
||||
{
|
||||
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
|
||||
UINT Position = 0;
|
||||
|
||||
if (!Hist || Hist->NumEntries == 0) return;
|
||||
|
||||
Position = Hist->Position + Offset;
|
||||
Position = min(max(Position, 0), Hist->NumEntries - 1);
|
||||
Hist->Position = Position;
|
||||
|
||||
LineInputSetPos(Console, 0);
|
||||
LineInputEdit(Console, Console->LineSize,
|
||||
Hist->Entries[Hist->Position].Length / sizeof(WCHAR),
|
||||
Hist->Entries[Hist->Position].Buffer);
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
|
||||
{
|
||||
UINT Pos = Console->LinePos;
|
||||
PHISTORY_BUFFER Hist;
|
||||
UNICODE_STRING Entry;
|
||||
INT HistPos;
|
||||
|
||||
switch (KeyEvent->wVirtualKeyCode)
|
||||
{
|
||||
case VK_ESCAPE:
|
||||
/* Clear entire line */
|
||||
LineInputSetPos(Console, 0);
|
||||
LineInputEdit(Console, Console->LineSize, 0, NULL);
|
||||
return;
|
||||
case VK_HOME:
|
||||
/* Move to start of line. With ctrl, erase everything left of cursor */
|
||||
LineInputSetPos(Console, 0);
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
LineInputEdit(Console, Pos, 0, NULL);
|
||||
return;
|
||||
case VK_END:
|
||||
/* Move to end of line. With ctrl, erase everything right of cursor */
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
LineInputEdit(Console, Console->LineSize - Pos, 0, NULL);
|
||||
else
|
||||
LineInputSetPos(Console, Console->LineSize);
|
||||
return;
|
||||
case VK_LEFT:
|
||||
/* Move left. With ctrl, move to beginning of previous word */
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
{
|
||||
while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--;
|
||||
while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pos -= (Pos > 0);
|
||||
}
|
||||
LineInputSetPos(Console, Pos);
|
||||
return;
|
||||
case VK_RIGHT:
|
||||
case VK_F1:
|
||||
/* Move right. With ctrl, move to beginning of next word */
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
{
|
||||
while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++;
|
||||
while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++;
|
||||
LineInputSetPos(Console, Pos);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Recall one character (but don't overwrite current line) */
|
||||
HistoryGetCurrentEntry(Console, &Entry);
|
||||
if (Pos < Console->LineSize)
|
||||
LineInputSetPos(Console, Pos + 1);
|
||||
else if (Pos * sizeof(WCHAR) < Entry.Length)
|
||||
LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]);
|
||||
}
|
||||
return;
|
||||
case VK_INSERT:
|
||||
/* Toggle between insert and overstrike */
|
||||
Console->LineInsertToggle = !Console->LineInsertToggle;
|
||||
ConioSetCursorInfo(Console, Console->ActiveBuffer);
|
||||
return;
|
||||
case VK_DELETE:
|
||||
/* Remove character to right of cursor */
|
||||
if (Pos != Console->LineSize)
|
||||
LineInputEdit(Console, 1, 0, NULL);
|
||||
return;
|
||||
case VK_PRIOR:
|
||||
/* Recall first history entry */
|
||||
LineInputRecallHistory(Console, -((WORD)-1));
|
||||
return;
|
||||
case VK_NEXT:
|
||||
/* Recall last history entry */
|
||||
LineInputRecallHistory(Console, +((WORD)-1));
|
||||
return;
|
||||
case VK_UP:
|
||||
case VK_F5:
|
||||
/* Recall previous history entry. On first time, actually recall the
|
||||
* current (usually last) entry; on subsequent times go back. */
|
||||
LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0);
|
||||
Console->LineUpPressed = TRUE;
|
||||
return;
|
||||
case VK_DOWN:
|
||||
/* Recall next history entry */
|
||||
LineInputRecallHistory(Console, +1);
|
||||
return;
|
||||
case VK_F3:
|
||||
/* Recall remainder of current history entry */
|
||||
HistoryGetCurrentEntry(Console, &Entry);
|
||||
if (Pos * sizeof(WCHAR) < Entry.Length)
|
||||
{
|
||||
UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
|
||||
UINT DeleteSize = min(Console->LineSize - Pos, InsertSize);
|
||||
LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]);
|
||||
}
|
||||
return;
|
||||
case VK_F6:
|
||||
/* Insert a ^Z character */
|
||||
KeyEvent->uChar.UnicodeChar = 26;
|
||||
break;
|
||||
case VK_F7:
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
||||
HistoryDeleteBuffer(HistoryCurrentBuffer(Console));
|
||||
return;
|
||||
case VK_F8:
|
||||
/* Search for history entries starting with input. */
|
||||
Hist = HistoryCurrentBuffer(Console);
|
||||
if (!Hist || Hist->NumEntries == 0) return;
|
||||
|
||||
/* Like Up/F5, on first time start from current (usually last) entry,
|
||||
* but on subsequent times start at previous entry. */
|
||||
if (Console->LineUpPressed)
|
||||
Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1;
|
||||
Console->LineUpPressed = TRUE;
|
||||
|
||||
Entry.Length = Console->LinePos * sizeof(WCHAR);
|
||||
Entry.Buffer = Console->LineBuffer;
|
||||
|
||||
/* Keep going backwards, even wrapping around to the end,
|
||||
* until we get back to starting point */
|
||||
HistPos = Hist->Position;
|
||||
do
|
||||
{
|
||||
if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE))
|
||||
{
|
||||
Hist->Position = HistPos;
|
||||
LineInputEdit(Console, Console->LineSize - Pos,
|
||||
Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos,
|
||||
&Hist->Entries[HistPos].Buffer[Pos]);
|
||||
/* Cursor stays where it was */
|
||||
LineInputSetPos(Console, Pos);
|
||||
return;
|
||||
}
|
||||
if (--HistPos < 0) HistPos += Hist->NumEntries;
|
||||
} while (HistPos != Hist->Position);
|
||||
return;
|
||||
}
|
||||
|
||||
if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT)
|
||||
{
|
||||
/* backspace handling - if processed input enabled then we handle it here
|
||||
* otherwise we treat it like a normal char. */
|
||||
if (Pos > 0)
|
||||
{
|
||||
LineInputSetPos(Console, Pos - 1);
|
||||
LineInputEdit(Console, 1, 0, NULL);
|
||||
}
|
||||
}
|
||||
else if (KeyEvent->uChar.UnicodeChar == L'\r')
|
||||
{
|
||||
HistoryAddEntry(Console);
|
||||
|
||||
/* TODO: Expand aliases */
|
||||
|
||||
LineInputSetPos(Console, Console->LineSize);
|
||||
Console->LineBuffer[Console->LineSize++] = L'\r';
|
||||
if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
|
||||
{
|
||||
if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
|
||||
{
|
||||
ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add \n if processed input. There should usually be room for it,
|
||||
* but an exception to the rule exists: the buffer could have been
|
||||
* pre-filled with LineMaxSize - 1 characters. */
|
||||
if (Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
|
||||
Console->LineSize < Console->LineMaxSize)
|
||||
{
|
||||
Console->LineBuffer[Console->LineSize++] = L'\n';
|
||||
if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
|
||||
{
|
||||
if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
|
||||
{
|
||||
ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
else if (KeyEvent->uChar.UnicodeChar != L'\0')
|
||||
{
|
||||
if (KeyEvent->uChar.UnicodeChar < 0x20 &&
|
||||
Console->LineWakeupMask & (1 << KeyEvent->uChar.UnicodeChar))
|
||||
{
|
||||
/* Control key client wants to handle itself (e.g. for tab completion) */
|
||||
Console->LineBuffer[Console->LineSize++] = L' ';
|
||||
Console->LineBuffer[Console->LinePos] = KeyEvent->uChar.UnicodeChar;
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal character */
|
||||
BOOL Overstrike = Console->LineInsertToggle && Console->LinePos != Console->LineSize;
|
||||
LineInputEdit(Console, Overstrike, 1, &KeyEvent->uChar.UnicodeChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
CSR_API(SrvGetConsoleCommandHistory)
|
||||
{
|
||||
PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
PHISTORY_BUFFER Hist;
|
||||
PBYTE Buffer = (PBYTE)GetCommandHistoryRequest->History;
|
||||
ULONG BufferSize = GetCommandHistoryRequest->Length;
|
||||
UINT i;
|
||||
|
||||
if ( !CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&GetCommandHistoryRequest->History,
|
||||
GetCommandHistoryRequest->Length,
|
||||
sizeof(BYTE)) ||
|
||||
!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&GetCommandHistoryRequest->ExeName.Buffer,
|
||||
GetCommandHistoryRequest->ExeName.Length,
|
||||
sizeof(BYTE)) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &GetCommandHistoryRequest->ExeName);
|
||||
if (Hist)
|
||||
{
|
||||
for (i = 0; i < Hist->NumEntries; i++)
|
||||
{
|
||||
if (BufferSize < (Hist->Entries[i].Length + sizeof(WCHAR)))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
memcpy(Buffer, Hist->Entries[i].Buffer, Hist->Entries[i].Length);
|
||||
Buffer += Hist->Entries[i].Length;
|
||||
*(PWCHAR)Buffer = L'\0';
|
||||
Buffer += sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
GetCommandHistoryRequest->Length = Buffer - (PBYTE)GetCommandHistoryRequest->History;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleCommandHistoryLength)
|
||||
{
|
||||
PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
PHISTORY_BUFFER Hist;
|
||||
ULONG Length = 0;
|
||||
UINT i;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&GetCommandHistoryLengthRequest->ExeName.Buffer,
|
||||
GetCommandHistoryLengthRequest->ExeName.Length,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &GetCommandHistoryLengthRequest->ExeName);
|
||||
if (Hist)
|
||||
{
|
||||
for (i = 0; i < Hist->NumEntries; i++)
|
||||
Length += Hist->Entries[i].Length + sizeof(WCHAR);
|
||||
}
|
||||
GetCommandHistoryLengthRequest->Length = Length;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvExpungeConsoleCommandHistory)
|
||||
{
|
||||
PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ExpungeCommandHistoryRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
PHISTORY_BUFFER Hist;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ExpungeCommandHistoryRequest->ExeName.Buffer,
|
||||
ExpungeCommandHistoryRequest->ExeName.Length,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &ExpungeCommandHistoryRequest->ExeName);
|
||||
HistoryDeleteBuffer(Hist);
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvSetConsoleNumberOfCommands)
|
||||
{
|
||||
PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryNumberCommandsRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
PHISTORY_BUFFER Hist;
|
||||
NTSTATUS Status;
|
||||
UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands;
|
||||
PUNICODE_STRING OldEntryList, NewEntryList;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&SetHistoryNumberCommandsRequest->ExeName.Buffer,
|
||||
SetHistoryNumberCommandsRequest->ExeName.Length,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &SetHistoryNumberCommandsRequest->ExeName);
|
||||
if (Hist)
|
||||
{
|
||||
OldEntryList = Hist->Entries;
|
||||
NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING));
|
||||
if (!NewEntryList)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If necessary, shrink by removing oldest entries */
|
||||
for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--)
|
||||
{
|
||||
RtlFreeUnicodeString(Hist->Entries++);
|
||||
Hist->Position += (Hist->Position == 0);
|
||||
}
|
||||
|
||||
Hist->MaxEntries = MaxEntries;
|
||||
Hist->Entries = memcpy(NewEntryList, Hist->Entries,
|
||||
Hist->NumEntries * sizeof(UNICODE_STRING));
|
||||
ConsoleFreeHeap(OldEntryList);
|
||||
}
|
||||
}
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvGetConsoleHistory)
|
||||
{
|
||||
PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest;
|
||||
PCONSOLE Console;
|
||||
NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
HistoryInfoRequest->HistoryBufferSize = Console->HistoryBufferSize;
|
||||
HistoryInfoRequest->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
|
||||
HistoryInfoRequest->dwFlags = Console->HistoryNoDup;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvSetConsoleHistory)
|
||||
{
|
||||
PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest;
|
||||
PCONSOLE Console;
|
||||
NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Console->HistoryBufferSize = HistoryInfoRequest->HistoryBufferSize;
|
||||
Console->NumberOfHistoryBuffers = HistoryInfoRequest->NumberOfHistoryBuffers;
|
||||
Console->HistoryNoDup = HistoryInfoRequest->dwFlags & HISTORY_NO_DUP_FLAG;
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/lineinput.c
|
||||
* PURPOSE: Console line input functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
VOID FASTCALL HistoryDeleteBuffers(PCONSOLE Console);
|
||||
VOID FASTCALL LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/procinit.h
|
||||
* PURPOSE: Functions for console processes initialization
|
||||
* PROGRAMMERS: Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
NTSTATUS FASTCALL ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
PHANDLE pInputHandle,
|
||||
PHANDLE pOutputHandle,
|
||||
PHANDLE pErrorHandle,
|
||||
PCONSOLE_START_INFO ConsoleStartInfo);
|
||||
NTSTATUS FASTCALL ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
HANDLE ConsoleHandle,
|
||||
BOOL CreateNewHandlesTable,
|
||||
PHANDLE pInputHandle,
|
||||
PHANDLE pOutputHandle,
|
||||
PHANDLE pErrorHandle);
|
||||
VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/resource.h
|
||||
* PURPOSE: Resource #defines
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IDS_CONSOLE_TITLE 500
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,70 @@
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
|
||||
// UTF-8
|
||||
#pragma code_page(65001)
|
||||
#ifdef LANGUAGE_BG_BG
|
||||
#include "lang/bg-BG.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_CS_CZ
|
||||
#include "lang/cs-CZ.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_DE_DE
|
||||
#include "lang/de-DE.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_EL_GR
|
||||
#include "lang/el-GR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_EN_US
|
||||
#include "lang/en-US.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ES_ES
|
||||
#include "lang/es-ES.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_FR_FR
|
||||
#include "lang/fr-FR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_HE_IL
|
||||
#include "lang/he-IL.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ID_ID
|
||||
#include "lang/id-ID.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_IT_IT
|
||||
#include "lang/it-IT.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_JA_JP
|
||||
#include "lang/ja-JP.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_NB_NO
|
||||
#include "lang/no-NO.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_PL_PL
|
||||
#include "lang/pl-PL.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_PT_BR
|
||||
#include "lang/pt-BR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_RO_RO
|
||||
#include "lang/ro-RO.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_RU_RU
|
||||
#include "lang/ru-RU.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_SK_SK
|
||||
#include "lang/sk-SK.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_SV_SE
|
||||
#include "lang/sv-SE.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_TR_TR
|
||||
#include "lang/tr-TR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_UK_UA
|
||||
#include "lang/uk-UA.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ZH_CN
|
||||
#include "lang/zh-CN.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ZH_TW
|
||||
#include "lang/zh-TW.rc"
|
||||
#endif
|
||||
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/winsrv/consrv/settings.c
|
||||
* PURPOSE: Console settings management
|
||||
* PROGRAMMERS: Johannes Anderwald
|
||||
* Hermes Belusca-Maito ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "include/conio.h"
|
||||
#include "include/conio2.h"
|
||||
#include "include/settings.h"
|
||||
|
||||
#include <stdio.h> // for swprintf
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
extern const COLORREF s_Colors[16];
|
||||
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static VOID
|
||||
TranslateConsoleName(OUT LPWSTR DestString,
|
||||
IN LPCWSTR ConsoleName,
|
||||
IN UINT MaxStrLen)
|
||||
{
|
||||
#define PATH_SEPARATOR L'\\'
|
||||
|
||||
UINT wLength;
|
||||
|
||||
if ( DestString == NULL || ConsoleName == NULL ||
|
||||
*ConsoleName == L'\0' || MaxStrLen == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wLength = GetWindowsDirectoryW(DestString, MaxStrLen);
|
||||
if ((wLength > 0) && (_wcsnicmp(ConsoleName, DestString, wLength) == 0))
|
||||
{
|
||||
wcsncpy(DestString, L"%SystemRoot%", MaxStrLen);
|
||||
// FIXME: Fix possible buffer overflows there !!!!!
|
||||
wcsncat(DestString, ConsoleName + wLength, MaxStrLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcsncpy(DestString, ConsoleName, MaxStrLen);
|
||||
}
|
||||
|
||||
/* Replace path separators (backslashes) by underscores */
|
||||
while ((DestString = wcschr(DestString, PATH_SEPARATOR))) *DestString = L'_';
|
||||
}
|
||||
|
||||
static BOOL
|
||||
OpenUserRegistryPathPerProcessId(DWORD ProcessId,
|
||||
PHKEY hResult,
|
||||
REGSAM samDesired)
|
||||
{
|
||||
BOOL bRet = TRUE;
|
||||
HANDLE hProcessToken = NULL;
|
||||
HANDLE hProcess;
|
||||
BYTE Buffer[256];
|
||||
DWORD Length = 0;
|
||||
UNICODE_STRING SidName;
|
||||
PTOKEN_USER TokUser;
|
||||
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | READ_CONTROL, FALSE, ProcessId);
|
||||
if (!hProcess)
|
||||
{
|
||||
DPRINT1("Error: OpenProcess failed(0x%x)\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
|
||||
{
|
||||
DPRINT1("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
|
||||
CloseHandle(hProcess);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(hProcessToken, TokenUser, (PVOID)Buffer, sizeof(Buffer), &Length))
|
||||
{
|
||||
DPRINT1("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
|
||||
CloseHandle(hProcessToken);
|
||||
CloseHandle(hProcess);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TokUser = ((PTOKEN_USER)Buffer)->User.Sid;
|
||||
if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName, TokUser, TRUE)))
|
||||
{
|
||||
DPRINT1("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
|
||||
CloseHandle(hProcessToken);
|
||||
CloseHandle(hProcess);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Might fail for LiveCD... Why ? Because only HKU\.DEFAULT exists.
|
||||
*/
|
||||
bRet = (RegOpenKeyExW(HKEY_USERS,
|
||||
SidName.Buffer,
|
||||
0,
|
||||
samDesired,
|
||||
hResult) == ERROR_SUCCESS);
|
||||
|
||||
RtlFreeUnicodeString(&SidName);
|
||||
|
||||
CloseHandle(hProcessToken);
|
||||
CloseHandle(hProcess);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/*static*/ BOOL
|
||||
ConSrvOpenUserSettings(DWORD ProcessId,
|
||||
LPCWSTR ConsoleTitle,
|
||||
PHKEY hSubKey,
|
||||
REGSAM samDesired,
|
||||
BOOL bCreate)
|
||||
{
|
||||
BOOL bRet = TRUE;
|
||||
WCHAR szBuffer[MAX_PATH] = L"Console\\";
|
||||
WCHAR szBuffer2[MAX_PATH] = L"";
|
||||
HKEY hKey;
|
||||
|
||||
/*
|
||||
* Console properties are stored under the HKCU\Console\* key.
|
||||
*
|
||||
* We use the original console title as the subkey name for storing
|
||||
* console properties. We need to distinguish whether we were launched
|
||||
* via the console application directly or via a shortcut.
|
||||
*
|
||||
* If the title of the console corresponds to a path (more precisely,
|
||||
* if the title is of the form: C:\ReactOS\<some_path>\<some_app.exe>),
|
||||
* then use the corresponding unexpanded path and with the backslashes
|
||||
* replaced by underscores, to make the registry happy,
|
||||
* i.e. %SystemRoot%_<some_path>_<some_app.exe>
|
||||
*/
|
||||
|
||||
/* Open the registry key where we saved the console properties */
|
||||
if (!OpenUserRegistryPathPerProcessId(ProcessId, &hKey, samDesired))
|
||||
{
|
||||
DPRINT1("OpenUserRegistryPathPerProcessId failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to open properties via the console title:
|
||||
* to make the registry happy, replace all the
|
||||
* backslashes by underscores.
|
||||
*/
|
||||
TranslateConsoleName(szBuffer2, ConsoleTitle, MAX_PATH);
|
||||
|
||||
/* Create the registry path */
|
||||
wcsncat(szBuffer, szBuffer2, MAX_PATH);
|
||||
|
||||
/* Create or open the registry key */
|
||||
if (bCreate)
|
||||
{
|
||||
/* Create the key */
|
||||
bRet = (RegCreateKeyExW(hKey,
|
||||
szBuffer,
|
||||
0, NULL,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
samDesired,
|
||||
NULL,
|
||||
hSubKey,
|
||||
NULL) == ERROR_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Open the key */
|
||||
bRet = (RegOpenKeyExW(hKey,
|
||||
szBuffer,
|
||||
0,
|
||||
samDesired,
|
||||
hSubKey) == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
/* Close the parent key and return success or not */
|
||||
RegCloseKey(hKey);
|
||||
return bRet;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ConSrvReadUserSettings(IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN DWORD ProcessId)
|
||||
{
|
||||
BOOL RetVal = FALSE;
|
||||
HKEY hKey;
|
||||
DWORD dwNumSubKeys = 0;
|
||||
DWORD dwIndex;
|
||||
DWORD dwColorIndex = 0;
|
||||
DWORD dwType;
|
||||
WCHAR szValueName[MAX_PATH];
|
||||
DWORD dwValueName;
|
||||
WCHAR szValue[LF_FACESIZE] = L"\0";
|
||||
DWORD Value;
|
||||
DWORD dwValue;
|
||||
|
||||
if (!ConSrvOpenUserSettings(ProcessId,
|
||||
ConsoleInfo->ConsoleTitle,
|
||||
&hKey, KEY_READ,
|
||||
FALSE))
|
||||
{
|
||||
DPRINT("ConSrvOpenUserSettings failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&dwNumSubKeys, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT("ConSrvReadUserSettings: RegQueryInfoKey failed\n");
|
||||
RegCloseKey(hKey);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("ConSrvReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys);
|
||||
|
||||
for (dwIndex = 0; dwIndex < dwNumSubKeys; dwIndex++)
|
||||
{
|
||||
dwValue = sizeof(Value);
|
||||
dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
|
||||
|
||||
if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, &dwType, (BYTE*)&Value, &dwValue) != ERROR_SUCCESS)
|
||||
{
|
||||
if (dwType == REG_SZ)
|
||||
{
|
||||
/*
|
||||
* Retry in case of string value
|
||||
*/
|
||||
dwValue = sizeof(szValue);
|
||||
dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
|
||||
if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe it is UI-specific ?? */
|
||||
if (!wcsncmp(szValueName, L"ColorTable", wcslen(L"ColorTable")))
|
||||
{
|
||||
dwColorIndex = 0;
|
||||
swscanf(szValueName, L"ColorTable%2d", &dwColorIndex);
|
||||
if (dwColorIndex < sizeof(ConsoleInfo->Colors)/sizeof(ConsoleInfo->Colors[0]))
|
||||
{
|
||||
ConsoleInfo->Colors[dwColorIndex] = Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"HistoryBufferSize"))
|
||||
{
|
||||
ConsoleInfo->HistoryBufferSize = Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"NumberOfHistoryBuffers"))
|
||||
{
|
||||
ConsoleInfo->NumberOfHistoryBuffers = Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"HistoryNoDup"))
|
||||
{
|
||||
ConsoleInfo->HistoryNoDup = (BOOLEAN)Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"QuickEdit"))
|
||||
{
|
||||
ConsoleInfo->QuickEdit = (BOOLEAN)Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"InsertMode"))
|
||||
{
|
||||
ConsoleInfo->InsertMode = (BOOLEAN)Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"ScreenBufferSize"))
|
||||
{
|
||||
ConsoleInfo->ScreenBufferSize.X = LOWORD(Value);
|
||||
ConsoleInfo->ScreenBufferSize.Y = HIWORD(Value);
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"WindowSize"))
|
||||
{
|
||||
ConsoleInfo->ConsoleSize.X = LOWORD(Value);
|
||||
ConsoleInfo->ConsoleSize.Y = HIWORD(Value);
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"CursorSize"))
|
||||
{
|
||||
ConsoleInfo->CursorSize = min(max(Value, 0), 100);
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"ScreenColors"))
|
||||
{
|
||||
ConsoleInfo->ScreenAttrib = (USHORT)Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"PopupColors"))
|
||||
{
|
||||
ConsoleInfo->PopupAttrib = (USHORT)Value;
|
||||
RetVal = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ConSrvWriteUserSettings(IN PCONSOLE_INFO ConsoleInfo,
|
||||
IN DWORD ProcessId)
|
||||
{
|
||||
BOOL GlobalSettings = (ConsoleInfo->ConsoleTitle[0] == L'\0');
|
||||
HKEY hKey;
|
||||
DWORD Storage = 0;
|
||||
|
||||
#define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
|
||||
do { \
|
||||
if (GlobalSettings || (!GlobalSettings && (*(Setting) != (DefaultValue)))) \
|
||||
{ \
|
||||
RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegDeleteValue(hKey, (SettingName)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
WCHAR szValueName[15];
|
||||
UINT i;
|
||||
|
||||
if (!ConSrvOpenUserSettings(ProcessId,
|
||||
ConsoleInfo->ConsoleTitle,
|
||||
&hKey, KEY_WRITE,
|
||||
TRUE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < sizeof(ConsoleInfo->Colors)/sizeof(ConsoleInfo->Colors[0]) ; ++i)
|
||||
{
|
||||
/*
|
||||
* Write only the new value if we are saving the global settings
|
||||
* or we are saving settings for a particular console, which differs
|
||||
* from the default ones.
|
||||
*/
|
||||
swprintf(szValueName, L"ColorTable%02d", i);
|
||||
SetConsoleSetting(szValueName, REG_DWORD, sizeof(DWORD), &ConsoleInfo->Colors[i], s_Colors[i]);
|
||||
}
|
||||
|
||||
SetConsoleSetting(L"HistoryBufferSize", REG_DWORD, sizeof(DWORD), &ConsoleInfo->HistoryBufferSize, 50);
|
||||
SetConsoleSetting(L"NumberOfHistoryBuffers", REG_DWORD, sizeof(DWORD), &ConsoleInfo->NumberOfHistoryBuffers, 4);
|
||||
|
||||
Storage = ConsoleInfo->HistoryNoDup;
|
||||
SetConsoleSetting(L"HistoryNoDup", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
|
||||
|
||||
Storage = ConsoleInfo->QuickEdit;
|
||||
SetConsoleSetting(L"QuickEdit", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
|
||||
|
||||
Storage = ConsoleInfo->InsertMode;
|
||||
SetConsoleSetting(L"InsertMode", REG_DWORD, sizeof(DWORD), &Storage, TRUE);
|
||||
|
||||
Storage = MAKELONG(ConsoleInfo->ScreenBufferSize.X, ConsoleInfo->ScreenBufferSize.Y);
|
||||
SetConsoleSetting(L"ScreenBufferSize", REG_DWORD, sizeof(DWORD), &Storage, MAKELONG(80, 300));
|
||||
|
||||
Storage = MAKELONG(ConsoleInfo->ConsoleSize.X, ConsoleInfo->ConsoleSize.Y);
|
||||
SetConsoleSetting(L"WindowSize", REG_DWORD, sizeof(DWORD), &Storage, MAKELONG(80, 25));
|
||||
|
||||
SetConsoleSetting(L"CursorSize", REG_DWORD, sizeof(DWORD), &ConsoleInfo->CursorSize, CSR_DEFAULT_CURSOR_SIZE);
|
||||
|
||||
Storage = ConsoleInfo->ScreenAttrib;
|
||||
SetConsoleSetting(L"ScreenColors", REG_DWORD, sizeof(DWORD), &Storage, DEFAULT_SCREEN_ATTRIB);
|
||||
|
||||
Storage = ConsoleInfo->PopupAttrib;
|
||||
SetConsoleSetting(L"PopupColors", REG_DWORD, sizeof(DWORD), &Storage, DEFAULT_POPUP_ATTRIB);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
ConSrvGetDefaultSettings(IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
IN DWORD ProcessId)
|
||||
{
|
||||
if (ConsoleInfo == NULL) return;
|
||||
|
||||
/// HKCU,"Console","LoadConIme",0x00010003,1
|
||||
|
||||
/*
|
||||
* 1. Load the default values
|
||||
*/
|
||||
// #define DEFAULT_HISTORY_COMMANDS_NUMBER 50
|
||||
// #define DEFAULT_HISTORY_BUFFERS_NUMBER 4
|
||||
ConsoleInfo->HistoryBufferSize = 50;
|
||||
ConsoleInfo->NumberOfHistoryBuffers = 4;
|
||||
ConsoleInfo->HistoryNoDup = FALSE;
|
||||
|
||||
ConsoleInfo->QuickEdit = FALSE;
|
||||
ConsoleInfo->InsertMode = TRUE;
|
||||
// ConsoleInfo->InputBufferSize;
|
||||
|
||||
// Rule: ScreenBufferSize >= ConsoleSize
|
||||
ConsoleInfo->ScreenBufferSize.X = 80;
|
||||
ConsoleInfo->ScreenBufferSize.Y = 300;
|
||||
ConsoleInfo->ConsoleSize.X = 80;
|
||||
ConsoleInfo->ConsoleSize.Y = 25;
|
||||
|
||||
ConsoleInfo->CursorBlinkOn;
|
||||
ConsoleInfo->ForceCursorOff;
|
||||
ConsoleInfo->CursorSize = CSR_DEFAULT_CURSOR_SIZE; // #define SMALL_SIZE 25
|
||||
|
||||
ConsoleInfo->ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
|
||||
ConsoleInfo->PopupAttrib = DEFAULT_POPUP_ATTRIB;
|
||||
|
||||
memcpy(ConsoleInfo->Colors, s_Colors, sizeof(s_Colors));
|
||||
|
||||
// ConsoleInfo->CodePage;
|
||||
|
||||
ConsoleInfo->ConsoleTitle[0] = L'\0';
|
||||
|
||||
/*
|
||||
* 2. Overwrite them with the ones stored in HKCU\Console.
|
||||
* If the HKCU\Console key doesn't exist, create it
|
||||
* and store the default values inside.
|
||||
*/
|
||||
if (!ConSrvReadUserSettings(ConsoleInfo, ProcessId))
|
||||
{
|
||||
ConSrvWriteUserSettings(ConsoleInfo, ProcessId);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
ConSrvApplyUserSettings(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INFO ConsoleInfo)
|
||||
{
|
||||
PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
|
||||
|
||||
/*
|
||||
* Apply terminal-edition settings:
|
||||
* - QuickEdit and Insert modes,
|
||||
* - history settings.
|
||||
*/
|
||||
Console->QuickEdit = ConsoleInfo->QuickEdit;
|
||||
Console->InsertMode = ConsoleInfo->InsertMode;
|
||||
|
||||
/*
|
||||
* Apply foreground and background colors for both screen and popup
|
||||
* and copy the new palette.
|
||||
*/
|
||||
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
|
||||
{
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
|
||||
|
||||
Buffer->ScreenDefaultAttrib = ConsoleInfo->ScreenAttrib;
|
||||
Buffer->PopupDefaultAttrib = ConsoleInfo->PopupAttrib;
|
||||
}
|
||||
else // if (Console->ActiveBuffer->Header.Type == GRAPHICS_BUFFER)
|
||||
{
|
||||
}
|
||||
|
||||
// FIXME: Possible buffer overflow if s_colors is bigger than pConInfo->Colors.
|
||||
memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(s_Colors));
|
||||
|
||||
// TODO: Really update the screen attributes as FillConsoleOutputAttribute does.
|
||||
|
||||
/* Apply cursor size */
|
||||
ActiveBuffer->CursorInfo.bVisible = (ConsoleInfo->CursorSize != 0);
|
||||
ActiveBuffer->CursorInfo.dwSize = min(max(ConsoleInfo->CursorSize, 0), 100);
|
||||
|
||||
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
|
||||
{
|
||||
PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
|
||||
COORD BufSize;
|
||||
|
||||
/* Resize its active screen-buffer */
|
||||
BufSize = ConsoleInfo->ScreenBufferSize;
|
||||
|
||||
if (Console->FixedSize)
|
||||
{
|
||||
/*
|
||||
* The console is in fixed-size mode, so we cannot resize anything
|
||||
* at the moment. However, keep those settings somewhere so that
|
||||
* we can try to set them up when we will be allowed to do so.
|
||||
*/
|
||||
if (ConsoleInfo->ConsoleSize.X != Buffer->OldViewSize.X ||
|
||||
ConsoleInfo->ConsoleSize.Y != Buffer->OldViewSize.Y)
|
||||
{
|
||||
Buffer->OldViewSize = ConsoleInfo->ConsoleSize;
|
||||
}
|
||||
|
||||
/* Buffer size is not allowed to be smaller than the view size */
|
||||
if (BufSize.X >= Buffer->OldViewSize.X && BufSize.Y >= Buffer->OldViewSize.Y)
|
||||
{
|
||||
if (BufSize.X != Buffer->OldScreenBufferSize.X ||
|
||||
BufSize.Y != Buffer->OldScreenBufferSize.Y)
|
||||
{
|
||||
/*
|
||||
* The console is in fixed-size mode, so we cannot resize anything
|
||||
* at the moment. However, keep those settings somewhere so that
|
||||
* we can try to set them up when we will be allowed to do so.
|
||||
*/
|
||||
Buffer->OldScreenBufferSize = BufSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL SizeChanged = FALSE;
|
||||
|
||||
/* Resize the console */
|
||||
if (ConsoleInfo->ConsoleSize.X != Buffer->ViewSize.X ||
|
||||
ConsoleInfo->ConsoleSize.Y != Buffer->ViewSize.Y)
|
||||
{
|
||||
Buffer->ViewSize = ConsoleInfo->ConsoleSize;
|
||||
SizeChanged = TRUE;
|
||||
}
|
||||
|
||||
/* Resize the screen-buffer */
|
||||
if (BufSize.X != Buffer->ScreenBufferSize.X ||
|
||||
BufSize.Y != Buffer->ScreenBufferSize.Y)
|
||||
{
|
||||
if (NT_SUCCESS(ConioResizeBuffer(Console, Buffer, BufSize)))
|
||||
SizeChanged = TRUE;
|
||||
}
|
||||
|
||||
if (SizeChanged) ConioResizeTerminal(Console);
|
||||
}
|
||||
}
|
||||
else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
|
||||
{
|
||||
PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer;
|
||||
|
||||
/*
|
||||
* In any case we do NOT modify the size of the graphics screen-buffer.
|
||||
* We just allow resizing the view only if the new size is smaller
|
||||
* than the older one.
|
||||
*/
|
||||
|
||||
if (Console->FixedSize)
|
||||
{
|
||||
/*
|
||||
* The console is in fixed-size mode, so we cannot resize anything
|
||||
* at the moment. However, keep those settings somewhere so that
|
||||
* we can try to set them up when we will be allowed to do so.
|
||||
*/
|
||||
if (ConsoleInfo->ConsoleSize.X <= Buffer->ViewSize.X ||
|
||||
ConsoleInfo->ConsoleSize.Y <= Buffer->ViewSize.Y)
|
||||
{
|
||||
Buffer->OldViewSize = ConsoleInfo->ConsoleSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Resize the view if its size is bigger than the specified size */
|
||||
if (ConsoleInfo->ConsoleSize.X <= Buffer->ViewSize.X ||
|
||||
ConsoleInfo->ConsoleSize.Y <= Buffer->ViewSize.Y)
|
||||
{
|
||||
Buffer->ViewSize = ConsoleInfo->ConsoleSize;
|
||||
// SizeChanged = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
Reference in New Issue
Block a user