[SACDRV]: IReadLast returns WCHAR, not CHAR.

[SACDRV]: Implement VtUtf8 case in ChannelInitializeVTable.
[SACDRV]: Implement DoHelpCommand, reformat concmd.c to standards.
[SACDRV]: ConMgrInitialize shoudl setup the SAC channel as VtUtf8, not Raw. I guess it was set to Raw since VtUtf8 wasn't yet implemented, however this breaks the command parsing since it expects WCHAR's. Make a note of this, and temporarily hack ConMgrSerialPortConsumer to work with CHAR's from a Raw channel.
[SACDRV]: Implement ConMgrProcessInputLine, which calls out the appopriate helpers.
[SACDRV]: Fixes to parsing in ConMgrSerialPortConsumer
[SACDRV]: Document, reformat, and fix some of the bugs in the RawChannelI* commands.
[SACDRV]: Implement simple (ANSI) case of SacTranslateUtf8ToUnicode.
[SACDRV]: Implement SacFormatMessage and GetMessageLineCount.
[SACDRV]: Start implementing VT-UTF8 support. Input routines are done, output routines are still WIP.
[SACMSG]: Fix the messages in the .MC file. Stuff is now being output correctly. If using Putty, make sure to turn on "Implicit CR in every LF" in Settings->Terminal.

svn path=/trunk/; revision=59778
This commit is contained in:
Alex Ionescu 2013-08-19 03:32:39 +00:00
parent ed35b983f9
commit 519595d9c4
9 changed files with 1112 additions and 359 deletions

View file

@ -404,7 +404,6 @@ ChanMgrCreateChannel(OUT PSAC_CHANNEL *Channel,
if (i == SAC_MAX_CHANNELS)
{
/* Bail out */
SAC_DBG(SAC_DBG_INIT, "failing here: %d %lx\n", __LINE__, Status);
goto ReturnStatus;
}
@ -438,7 +437,6 @@ ChanMgrCreateChannel(OUT PSAC_CHANNEL *Channel,
else
{
/* We couldn't create it, free the buffer */
SAC_DBG(SAC_DBG_INIT, "failing here: %d %lx\n", __LINE__, Status);
SacFreePool(NewChannel);
}

View file

@ -147,11 +147,11 @@ ChannelIRead(IN PSAC_CHANNEL Channel,
return Status;
}
UCHAR
WCHAR
NTAPI
ChannelIReadLast(IN PSAC_CHANNEL Channel)
{
UCHAR LastChar;
WCHAR LastChar;
/* Read the last character while holding the lock */
ChannelLockIBuffer(Channel);
@ -410,9 +410,19 @@ ChannelInitializeVTable(IN PSAC_CHANNEL Channel)
switch (Channel->ChannelType)
{
case VtUtf8:
/* FIXME: TODO */
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
/* Setup the calls for a VT-UTF8 channel */
Channel->ChannelCreate = VTUTF8ChannelCreate;
Channel->ChannelDestroy = VTUTF8ChannelDestroy;
Channel->ChannelOutputFlush = VTUTF8ChannelOFlush;
Channel->ChannelOutputEcho = VTUTF8ChannelOEcho;
Channel->ChannelOutputWrite = VTUTF8ChannelOWrite;
Channel->ChannelOutputRead = VTUTF8ChannelORead;
Channel->ChannelInputWrite = VTUTF8ChannelIWrite;
Channel->ChannelInputRead = VTUTF8ChannelIRead;
Channel->ChannelInputReadLast = VTUTF8ChannelIReadLast;
Channel->ChannelInputBufferIsFull = VTUTF8ChannelIBufferIsFull;
Channel->ChannelInputBufferLength = VTUTF8ChannelIBufferLength;
break;
case Cmd:
/* FIXME: TODO */

View file

@ -17,58 +17,44 @@ ULONG GlobalBufferSize;
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
DoRebootCommand(IN BOOLEAN Reboot)
NTSTATUS
DoChannelListCommand(
VOID
)
{
LARGE_INTEGER Timeout, TickCount;
NTSTATUS Status;
KEVENT Event;
SAC_DBG(1, "SAC DoRebootCommand: Entering.\n");
return STATUS_NOT_IMPLEMENTED;
}
/* Get the current time now, and setup a timeout in 1 second */
KeQueryTickCount(&TickCount);
Timeout.QuadPart = TickCount.QuadPart / (10000000 / KeQueryTimeIncrement());
NTSTATUS
DoChannelCloseByNameCommand(
IN PCHAR Count
)
{
return STATUS_NOT_IMPLEMENTED;
}
/* Check if the timeout is small enough */
if (Timeout.QuadPart < 60 )
{
/* Show the prompt */
ConMgrSimpleEventMessage(Reboot ?
SAC_RESTART_PROMPT : SAC_SHUTDOWN_PROMPT,
TRUE);
NTSTATUS
DoChannelCloseByIndexCommand(
IN ULONG ChannelIndex
)
{
return STATUS_NOT_IMPLEMENTED;
}
/* Do the wait */
KeInitializeEvent(&Event, SynchronizationEvent, 0);
Timeout.QuadPart = -10000000 * (60 - Timeout.LowPart);
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &Timeout);
}
NTSTATUS
DoChannelSwitchByNameCommand(
IN PCHAR Count
)
{
return STATUS_NOT_IMPLEMENTED;
}
/* Do a shutdown or a reboot, based on the request */
Status = NtShutdownSystem(Reboot ? ShutdownReboot : ShutdownPowerOff);
/* Check if anyone in the command channel already allocated this */
if (!GlobalBuffer)
{
/* Allocate it */
GlobalBuffer = SacAllocatePool(PAGE_SIZE, GLOBAL_BLOCK_TAG);
if (!GlobalBuffer)
{
/* We need the global buffer, bail out without it*/
SacPutSimpleMessage(SAC_OUT_OF_MEMORY_PROMPT);
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC DoRebootCommand: Exiting (1).\n");
return;
}
/* Set the size of the buffer */
GlobalBufferSize = PAGE_SIZE;
}
/* We came back from a reboot, this doesn't make sense, tell the user */
SacPutSimpleMessage(Reboot ? SAC_RESTART_FAIL_PROMPT : SAC_SHUTDOWN_FAIL_PROMPT);
swprintf(GlobalBuffer, GetMessage(SAC_FAIL_PROMPT), Status);
SacPutString(GlobalBuffer);
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC DoRebootCommand: Exiting.\n");
NTSTATUS
DoChannelSwitchByIndexCommand(
IN ULONG ChannelIndex
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
@ -124,169 +110,201 @@ CallQueryIPIOCTL(
}
VOID
DoFullInfoCommand(
VOID
)
NTAPI
DoRebootCommand(IN BOOLEAN Reboot)
{
LARGE_INTEGER Timeout, TickCount;
NTSTATUS Status;
KEVENT Event;
SAC_DBG(1, "SAC DoRebootCommand: Entering.\n");
/* Get the current time now, and setup a timeout in 1 second */
KeQueryTickCount(&TickCount);
Timeout.QuadPart = TickCount.QuadPart / (10000000 / KeQueryTimeIncrement());
/* Check if the timeout is small enough */
if (Timeout.QuadPart < 60 )
{
/* Show the prompt */
ConMgrSimpleEventMessage(Reboot ?
SAC_RESTART_PROMPT : SAC_SHUTDOWN_PROMPT,
TRUE);
/* Do the wait */
KeInitializeEvent(&Event, SynchronizationEvent, 0);
Timeout.QuadPart = -10000000 * (60 - Timeout.LowPart);
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &Timeout);
}
/* Do a shutdown or a reboot, based on the request */
Status = NtShutdownSystem(Reboot ? ShutdownReboot : ShutdownPowerOff);
/* Check if anyone in the command channel already allocated this */
if (!GlobalBuffer)
{
/* Allocate it */
GlobalBuffer = SacAllocatePool(PAGE_SIZE, GLOBAL_BLOCK_TAG);
if (!GlobalBuffer)
{
/* We need the global buffer, bail out without it*/
SacPutSimpleMessage(SAC_OUT_OF_MEMORY_PROMPT);
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC DoRebootCommand: Exiting (1).\n");
return;
}
/* Set the size of the buffer */
GlobalBufferSize = PAGE_SIZE;
}
/* We came back from a reboot, this doesn't make sense, tell the user */
SacPutSimpleMessage(Reboot ? SAC_RESTART_FAIL_PROMPT : SAC_SHUTDOWN_FAIL_PROMPT);
swprintf(GlobalBuffer, GetMessage(SAC_FAIL_PROMPT), Status);
SacPutString(GlobalBuffer);
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC DoRebootCommand: Exiting.\n");
}
VOID
NTAPI
DoFullInfoCommand(VOID)
{
}
VOID
DoPagingCommand(
VOID
)
NTAPI
DoPagingCommand(VOID)
{
}
VOID
DoSetTimeCommand(
IN PCHAR InputTime
)
NTAPI
DoSetTimeCommand(IN PCHAR InputTime)
{
}
VOID
DoKillCommand(
IN PCHAR KillString
)
NTAPI
DoKillCommand(IN PCHAR KillString)
{
}
VOID
DoLowerPriorityCommand(
IN PCHAR PrioString
)
NTAPI
DoLowerPriorityCommand(IN PCHAR PrioString)
{
}
VOID
DoRaisePriorityCommand(
IN PCHAR PrioString
)
NTAPI
DoRaisePriorityCommand(IN PCHAR PrioString)
{
}
VOID
DoLimitMemoryCommand(
IN PCHAR LimitString
)
NTAPI
DoLimitMemoryCommand(IN PCHAR LimitString)
{
}
VOID
DoCrashCommand(
VOID
)
NTAPI
DoCrashCommand(VOID)
{
}
VOID
DoMachineInformationCommand(
VOID
)
{
}
NTSTATUS
DoChannelListCommand(
VOID
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
DoChannelCloseByNameCommand(
IN PCHAR Count
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
DoChannelCloseByIndexCommand(
IN ULONG ChannelIndex
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
DoChannelSwitchByNameCommand(
IN PCHAR Count
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
DoChannelSwitchByIndexCommand(
IN ULONG ChannelIndex
)
{
return STATUS_NOT_IMPLEMENTED;
}
VOID
DoChannelCommand(
IN PCHAR ChannelString
)
NTAPI
DoMachineInformationCommand(VOID)
{
}
VOID
DoCmdCommand(
VOID
)
NTAPI
DoChannelCommand(IN PCHAR ChannelString)
{
}
VOID
DoLockCommand(
VOID
)
NTAPI
DoCmdCommand(IN PCHAR InputString)
{
}
VOID
DoHelpCommand(
VOID
)
NTAPI
DoLockCommand(VOID)
{
}
#define PRINT_HELP_MESSAGE(x) \
{ \
Count += NewCount; \
NewCount = GetMessageLineCount(x); \
if ( (NewCount + Count) > SAC_VTUTF8_COL_HEIGHT) \
{ \
PutMore(&ScreenFull); \
if (ScreenFull) return; \
Count = 0; \
} \
SacPutSimpleMessage(x); \
}
VOID
NTAPI
DoHelpCommand(VOID)
{
ULONG NewCount = 0, Count = 0;
BOOLEAN ScreenFull = FALSE;
PRINT_HELP_MESSAGE(112);
PRINT_HELP_MESSAGE(12);
PRINT_HELP_MESSAGE(13);
PRINT_HELP_MESSAGE(14);
PRINT_HELP_MESSAGE(15);
PRINT_HELP_MESSAGE(16);
PRINT_HELP_MESSAGE(31);
PRINT_HELP_MESSAGE(18);
PRINT_HELP_MESSAGE(19);
PRINT_HELP_MESSAGE(32);
PRINT_HELP_MESSAGE(20);
PRINT_HELP_MESSAGE(21);
PRINT_HELP_MESSAGE(22);
PRINT_HELP_MESSAGE(23);
PRINT_HELP_MESSAGE(24);
PRINT_HELP_MESSAGE(25);
PRINT_HELP_MESSAGE(27);
PRINT_HELP_MESSAGE(28);
PRINT_HELP_MESSAGE(29);
}
VOID
NTAPI
DoGetNetInfo(IN BOOLEAN DoPrint)
{
}
VOID
DoGetNetInfo(
IN BOOLEAN DoPrint
)
NTAPI
DoSetIpAddressCommand(IN PCHAR IpString)
{
}
VOID
DoSetIpAddressCommand(
IN PCHAR IpString
)
NTAPI
DoTlistCommand(VOID)
{
}
VOID
DoTlistCommand(
VOID
)
{
}
}

View file

@ -169,7 +169,7 @@ ConMgrInitialize(VOID)
/* Setup the attributes for the raw SAC channel */
RtlZeroMemory(&SacChannelAttributes, sizeof(SacChannelAttributes));
SacChannelAttributes.ChannelType = Raw;
SacChannelAttributes.ChannelType = Raw; /* FIXME: Should be VtUtf8 */
/* Get the right name for it */
pcwch = GetMessage(SAC_CHANNEL_NAME);
@ -438,6 +438,7 @@ ConMgrChannelOWrite(IN PSAC_CHANNEL Channel,
/* Do the write with the lock held */
SacAcquireMutexLock();
ASSERT(FALSE);
Status = STATUS_NOT_IMPLEMENTED;// ChannelOWrite(Channel, WriteBuffer + 24, *(WriteBuffer + 20));
SacReleaseMutexLock();
@ -446,22 +447,137 @@ ConMgrChannelOWrite(IN PSAC_CHANNEL Channel,
return Status;
}
#define Shutdown 1
#define Restart 3
#define Nothing 0
BOOLEAN GlobalPagingNeeded;
VOID
NTAPI
ConMgrProcessInputLine(VOID)
{
ASSERT(FALSE);
}
BOOLEAN EnablePaging;
NTSTATUS Status;
#define Nothing 0
SAC_DBG(4, "SAC Input Test: %s\n", InputBuffer);
if (!strncmp(InputBuffer, "t", 1))
{
DoTlistCommand();
}
else if (!strncmp(InputBuffer, "?", 1))
{
DoHelpCommand();
}
else if (!strncmp(InputBuffer, "help", 4))
{
DoHelpCommand();
}
else if (!strncmp(InputBuffer, "f", 1))
{
DoFullInfoCommand();
}
else if (!strncmp(InputBuffer, "p", 1))
{
DoPagingCommand();
}
else if (!strncmp(InputBuffer, "id", 2))
{
DoMachineInformationCommand();
}
else if (!strncmp(InputBuffer, "crashdump", 9))
{
DoCrashCommand();
}
else if (!strncmp(InputBuffer, "lock", 4))
{
DoLockCommand();
}
else if (!strncmp(InputBuffer, "shutdown", 8))
{
ExecutePostConsumerCommand = Shutdown;
}
else if (!strncmp(InputBuffer, "restart", 7))
{
ExecutePostConsumerCommand = Restart;
}
else if (!strncmp(InputBuffer, "d", 1))
{
EnablePaging = GlobalPagingNeeded;
Status = HeadlessDispatch(HeadlessCmdDisplayLog,
&EnablePaging,
sizeof(EnablePaging),
NULL,
0);
if (!NT_SUCCESS(Status)) SAC_DBG(4, "SAC Display Log failed.\n");
}
else if (!strncmp(InputBuffer, "cmd", 3))
{
if (CommandConsoleLaunchingEnabled)
{
DoCmdCommand(InputBuffer);
}
else
{
SacPutSimpleMessage(148);
}
}
else if (!(strncmp(InputBuffer, "ch", 2)) &&
(((strlen(InputBuffer) > 1) && (InputBuffer[2] == ' ')) ||
(strlen(InputBuffer) == 2)))
{
DoChannelCommand(InputBuffer);
}
else if (!(strncmp(InputBuffer, "k", 1)) &&
(((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) ||
(strlen(InputBuffer) == 1)))
{
DoKillCommand(InputBuffer);
}
else if (!(strncmp(InputBuffer, "l", 1)) &&
(((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) ||
(strlen(InputBuffer) == 1)))
{
DoLowerPriorityCommand(InputBuffer);
}
else if (!(strncmp(InputBuffer, "r", 1)) &&
(((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) ||
(strlen(InputBuffer) == 1)))
{
DoRaisePriorityCommand(InputBuffer);
}
else if (!(strncmp(InputBuffer, "m", 1)) &&
(((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) ||
(strlen(InputBuffer) == 1)))
{
DoLimitMemoryCommand(InputBuffer);
}
else if (!(strncmp(InputBuffer, "s", 1)) &&
(((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) ||
(strlen(InputBuffer) == 1)))
{
DoSetTimeCommand(InputBuffer);
}
else if (!(strncmp(InputBuffer, "i", 1)) &&
(((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) ||
(strlen(InputBuffer) == 1)))
{
DoSetIpAddressCommand(InputBuffer);
}
else if ((InputBuffer[0] != '\n') && (InputBuffer[0] != ANSI_NULL))
{
SacPutSimpleMessage(105);
}
}
VOID
NTAPI
ConMgrSerialPortConsumer(VOID)
{
NTSTATUS Status;
CHAR Char, LastChar;
CHAR WriteBuffer[2], ReadBuffer[2];
CHAR Char;
WCHAR LastChar;
CHAR ReadBuffer[2];
ULONG ReadBufferSize, i;
WCHAR StringBuffer[2];
SAC_DBG(SAC_DBG_MACHINE, "SAC TimerDpcRoutine: Entering.\n"); //bug
@ -546,8 +662,8 @@ ConMgrSerialPortConsumer(VOID)
if ((InputInEscape) && (CurrentChannel != SacChannel))
{
/* Store the ESC in the current channel buffer */
WriteBuffer[0] = '\x1B';
ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR));
ReadBuffer[0] = '\x1B';
ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR));
}
/* Check if we are no longer pressing ESC and exit the mode if so */
@ -582,26 +698,26 @@ DoLineParsing:
ChannelIReadLast(CurrentChannel);
/* NULL-terminate the channel's input buffer */
WriteBuffer[0] = ANSI_NULL;
ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR));
ReadBuffer[0] = ANSI_NULL;
ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR));
/* Loop over every last character */
do
{
/* Read every character in the channel, and strip whitespace */
LastChar = ChannelIReadLast(CurrentChannel);
WriteBuffer[0] = LastChar;
ReadBuffer[0] = (CHAR) LastChar;
} while ((!(LastChar) ||
(LastChar == ' ') ||
(LastChar == '\t')) &&
(LastChar == L' ') ||
(LastChar == L'\t')) &&
(ChannelIBufferLength(CurrentChannel)));
/* Write back into the channel the last character */
ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR));
ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR));
/* NULL-terminate the input buffer */
WriteBuffer[0] = ANSI_NULL;
ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(WCHAR));
ReadBuffer[0] = ANSI_NULL;
ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR));
/* Now loop over every first character */
do
@ -609,11 +725,10 @@ DoLineParsing:
/* Read every character in the channel, and strip whitespace */
ChannelIRead(CurrentChannel,
ReadBuffer,
sizeof(ReadBuffer),
sizeof(CHAR), /* FIXME: Should be sizeof(ReadBuffer) */
&ReadBufferSize);
WriteBuffer[0] = ReadBuffer[0];
} while ((ReadBufferSize) &&
((ReadBuffer[0] != ' ') || (ReadBuffer[0] != '\t')));
((ReadBuffer[0] == ' ') || (ReadBuffer[0] == '\t')));
/* We read one more than we should, so treat that as our first one */
InputBuffer[0] = ReadBuffer[0];
@ -625,7 +740,7 @@ DoLineParsing:
/* Read each character -- there should be max 80 */
ChannelIRead(CurrentChannel,
ReadBuffer,
sizeof(ReadBuffer),
sizeof(CHAR), /* FIXME: Should be sizeof(ReadBuffer) */
&ReadBufferSize);
ASSERT(i < SAC_VTUTF8_COL_WIDTH);
InputBuffer[i++] = ReadBuffer[0];
@ -637,7 +752,7 @@ DoLineParsing:
/* Again it should be less than 80 characters */
ASSERT(i < SAC_VTUTF8_COL_WIDTH);
/* And upcase each character */
/* And downbase each character */
Char = InputBuffer[i];
if ((Char >= 'A') && (Char <= 'Z')) InputBuffer[i] = Char + ' ';
}
@ -700,9 +815,9 @@ DoLineParsing:
ChannelIReadLast(CurrentChannel);
ChannelIReadLast(CurrentChannel);
/* NULL-terminate it */
WriteBuffer[0] = Char;
ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR));
/* Write the last character that was just typed in */
ReadBuffer[0] = Char;
ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR));
continue;
}

View file

@ -23,17 +23,19 @@ RawChannelCreate(IN PSAC_CHANNEL Channel)
{
CHECK_PARAMETER(Channel);
/* Allocate the output buffer */
Channel->OBuffer = SacAllocatePool(SAC_RAW_OBUFFER_SIZE, GLOBAL_BLOCK_TAG);
CHECK_ALLOCATION(Channel->OBuffer);
/* Allocate the input buffer */
Channel->IBuffer = SacAllocatePool(SAC_RAW_IBUFFER_SIZE, GLOBAL_BLOCK_TAG);
CHECK_ALLOCATION(Channel->IBuffer);
/* Reset all flags and return success */
Channel->OBufferIndex = 0;
Channel->OBufferFirstGoodIndex = 0;
Channel->ChannelHasNewIBufferData = FALSE;
Channel->ChannelHasNewOBufferData = FALSE;
return STATUS_SUCCESS;
}
@ -43,16 +45,9 @@ RawChannelDestroy(IN PSAC_CHANNEL Channel)
{
CHECK_PARAMETER(Channel);
if (Channel->OBuffer)
{
SacFreePool(Channel->OBuffer);
}
if (Channel->IBuffer)
{
SacFreePool(Channel->IBuffer);
}
/* Free the buffer and then destroy the channel */
if (Channel->OBuffer) SacFreePool(Channel->OBuffer);
if (Channel->IBuffer) SacFreePool(Channel->IBuffer);
return ChannelDestroy(Channel);
}
@ -63,13 +58,6 @@ ChannelHasNewOBufferData(IN PSAC_CHANNEL Channel)
return Channel->ChannelHasNewOBufferData;
}
FORCEINLINE
BOOLEAN
ChannelHasNewIBufferData(IN PSAC_CHANNEL Channel)
{
return Channel->ChannelHasNewIBufferData;
}
NTSTATUS
NTAPI
RawChannelORead(IN PSAC_CHANNEL Channel,
@ -207,38 +195,6 @@ RawChannelOFlush(IN PSAC_CHANNEL Channel)
return ConMgrFlushData(Channel);
}
ULONG
NTAPI
RawChannelGetIBufferIndex(IN PSAC_CHANNEL Channel)
{
ASSERT(Channel);
ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
return Channel->IBufferIndex;
}
VOID
NTAPI
RawChannelSetIBufferIndex(IN PSAC_CHANNEL Channel,
IN ULONG BufferIndex)
{
NTSTATUS Status;
ASSERT(Channel);
ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
Channel->IBufferIndex = BufferIndex;
Channel->ChannelHasNewIBufferData = BufferIndex != 0;
if (!Channel->IBufferIndex)
{
if (Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
{
ChannelClearEvent(Channel, HasNewDataEvent);
UNREFERENCED_PARAMETER(Status);
}
}
}
NTSTATUS
NTAPI
RawChannelOWrite(IN PSAC_CHANNEL Channel,
@ -256,6 +212,40 @@ RawChannelOWrite(IN PSAC_CHANNEL Channel,
return RawChannelOWrite2(Channel, String, Length);
}
ULONG
NTAPI
RawChannelGetIBufferIndex(IN PSAC_CHANNEL Channel)
{
ASSERT(Channel);
ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
/* Return the current buffer index */
return Channel->IBufferIndex;
}
VOID
NTAPI
RawChannelSetIBufferIndex(IN PSAC_CHANNEL Channel,
IN ULONG BufferIndex)
{
NTSTATUS Status;
ASSERT(Channel);
ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
/* Set the new index, and if it's not zero, it means we have data */
Channel->IBufferIndex = BufferIndex;
_InterlockedExchange(&Channel->ChannelHasNewIBufferData, BufferIndex != 0);
/* If we have new data, and an event has been registered... */
if (!(Channel->IBufferIndex) &&
(Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT))
{
/* Go ahead and signal it */
ChannelClearEvent(Channel, HasNewDataEvent);
UNREFERENCED_PARAMETER(Status);
}
}
NTSTATUS
NTAPI
RawChannelIRead(IN PSAC_CHANNEL Channel,
@ -264,38 +254,46 @@ RawChannelIRead(IN PSAC_CHANNEL Channel,
IN PULONG ReturnBufferSize)
{
ULONG CopyChars;
CHECK_PARAMETER1(Channel);
CHECK_PARAMETER2(Buffer);
CHECK_PARAMETER_WITH_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
/* Assume failure */
*ReturnBufferSize = 0;
/* Check how many bytes are in the buffer */
if (Channel->ChannelInputBufferLength(Channel) == 0)
{
/* Apparently nothing. Make sure the flag indicates so too */
ASSERT(ChannelHasNewIBufferData(Channel) == FALSE);
}
else
{
CopyChars = Channel->ChannelInputBufferLength(Channel);
if (CopyChars > BufferSize) CopyChars = BufferSize;
/* Use the smallest number of bytes either in the buffer or requested */
CopyChars = min(Channel->ChannelInputBufferLength(Channel), BufferSize);
ASSERT(CopyChars <= Channel->ChannelInputBufferLength(Channel));
/* Copy them into the caller's buffer */
RtlCopyMemory(Buffer, Channel->IBuffer, CopyChars);
/* Update the channel's index past the copied (read) bytes */
RawChannelSetIBufferIndex(Channel,
RawChannelGetIBufferIndex(Channel) - CopyChars);
/* Are there still bytes that haven't been read yet? */
if (Channel->ChannelInputBufferLength(Channel))
{
/* Shift them up in the buffer */
RtlMoveMemory(Channel->IBuffer,
&Channel->IBuffer[CopyChars],
Channel->ChannelInputBufferLength(Channel));
}
/* Return the number of bytes we actually copied */
*ReturnBufferSize = CopyChars;
}
/* Return success */
return STATUS_SUCCESS;
}
@ -307,6 +305,7 @@ RawChannelIBufferIsFull(IN PSAC_CHANNEL Channel,
CHECK_PARAMETER1(Channel);
CHECK_PARAMETER2(BufferStatus);
/* If the index is beyond the length, the buffer must be full */
*BufferStatus = RawChannelGetIBufferIndex(Channel) > SAC_RAW_IBUFFER_SIZE;
return STATUS_SUCCESS;
}
@ -316,25 +315,31 @@ NTAPI
RawChannelIBufferLength(IN PSAC_CHANNEL Channel)
{
ASSERT(Channel);
/* The index is the current length (since we're 0-based) */
return RawChannelGetIBufferIndex(Channel);
}
CHAR
WCHAR
NTAPI
RawChannelIReadLast(IN PSAC_CHANNEL Channel)
{
UCHAR LastChar = 0;
ASSERT(Channel);
/* Check if there's anything to read in the buffer */
if (Channel->ChannelInputBufferLength(Channel))
{
RawChannelSetIBufferIndex(Channel, RawChannelGetIBufferIndex(Channel) - 1);
/* Go back one character */
RawChannelSetIBufferIndex(Channel,
RawChannelGetIBufferIndex(Channel) - 1);
/* Read it, and clear its current value */
LastChar = Channel->IBuffer[RawChannelGetIBufferIndex(Channel)];
Channel->IBuffer[RawChannelGetIBufferIndex(Channel)] = 0;
Channel->IBuffer[RawChannelGetIBufferIndex(Channel)] = ANSI_NULL;
}
/* Return the last character */
return LastChar;
}
@ -347,27 +352,34 @@ RawChannelIWrite(IN PSAC_CHANNEL Channel,
NTSTATUS Status;
BOOLEAN IsFull;
ULONG Index;
CHECK_PARAMETER1(Channel);
CHECK_PARAMETER2(Buffer);
CHECK_PARAMETER_WITH_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
/* First, check if the input buffer still has space */
Status = RawChannelIBufferIsFull(Channel, &IsFull);
if (!NT_SUCCESS(Status)) return Status;
if (IsFull) return STATUS_UNSUCCESSFUL;
/* Get the current buffer index */
Index = RawChannelGetIBufferIndex(Channel);
if ((SAC_RAW_IBUFFER_SIZE - Index) >= BufferSize) return STATUS_INSUFFICIENT_RESOURCES;
if ((SAC_RAW_IBUFFER_SIZE - Index) < BufferSize)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Copy the new data */
RtlCopyMemory(&Channel->IBuffer[Index], Buffer, BufferSize);
/* Update the index */
RawChannelSetIBufferIndex(Channel, BufferSize + Index);
/* Signal the event, if one was set */
if (Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
{
ChannelSetEvent(Channel, HasNewDataEvent);
}
/* All done */
return STATUS_SUCCESS;
}

View file

@ -157,6 +157,7 @@
#define SAC_SERIAL_PORT_BUFFER_SIZE 1024 // 1KB
#define SAC_MAX_MESSAGES 200
#define SAC_VTUTF8_COL_WIDTH 80
#define SAC_VTUTF8_COL_HEIGHT 25
//
// Channel flags
@ -302,7 +303,7 @@ ULONG
);
typedef
CHAR
WCHAR
(NTAPI *PSAC_CHANNEL_IREAD_LAST)(
IN struct _SAC_CHANNEL* Channel
);
@ -775,7 +776,7 @@ ChannelIWrite(
IN ULONG BufferSize
);
UCHAR
WCHAR
NTAPI
ChannelIReadLast(
IN PSAC_CHANNEL Channel
@ -864,7 +865,7 @@ RawChannelIBufferLength(
IN PSAC_CHANNEL Channel
);
CHAR
WCHAR
NTAPI
RawChannelIReadLast(
IN PSAC_CHANNEL Channel
@ -878,9 +879,106 @@ RawChannelIWrite(
IN ULONG BufferSize
);
//
// VT-UTF8 Channel Table
//
NTSTATUS
NTAPI
VTUTF8ChannelCreate(
IN PSAC_CHANNEL Channel
);
NTSTATUS
NTAPI
VTUTF8ChannelDestroy(
IN PSAC_CHANNEL Channel
);
NTSTATUS
NTAPI
VTUTF8ChannelORead(
IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize,
OUT PULONG ByteCount
);
NTSTATUS
NTAPI
VTUTF8ChannelOEcho(
IN PSAC_CHANNEL Channel,
IN PCHAR String,
IN ULONG Length
);
NTSTATUS
NTAPI
VTUTF8ChannelOFlush(
IN PSAC_CHANNEL Channel
);
NTSTATUS
NTAPI
VTUTF8ChannelOWrite(
IN PSAC_CHANNEL Channel,
IN PCHAR String,
IN ULONG Length
);
NTSTATUS
NTAPI
VTUTF8ChannelIRead(
IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize,
IN PULONG ReturnBufferSize
);
NTSTATUS
NTAPI
VTUTF8ChannelIBufferIsFull(
IN PSAC_CHANNEL Channel,
OUT PBOOLEAN BufferStatus
);
ULONG
NTAPI
VTUTF8ChannelIBufferLength(
IN PSAC_CHANNEL Channel
);
WCHAR
NTAPI
VTUTF8ChannelIReadLast(
IN PSAC_CHANNEL Channel
);
NTSTATUS
NTAPI
VTUTF8ChannelIWrite(
IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize
);
//
// Helper Routines
//
BOOLEAN
NTAPI
SacTranslateUtf8ToUnicode(
IN CHAR Utf8Char,
IN PCHAR Utf8Buffer,
OUT PWCHAR Utf8Value
);
ULONG
NTAPI
GetMessageLineCount(
IN ULONG MessageIndex
);
NTSTATUS
NTAPI
SerialBufferGetChar(
@ -923,6 +1021,102 @@ DoRebootCommand(
IN BOOLEAN Reboot
);
VOID
NTAPI
DoFullInfoCommand(
VOID
);
VOID
NTAPI
DoPagingCommand(
VOID
);
VOID
NTAPI
DoSetTimeCommand(
IN PCHAR InputTime
);
VOID
NTAPI
DoKillCommand(
IN PCHAR KillString
);
VOID
NTAPI
DoLowerPriorityCommand(
IN PCHAR PrioString
);
VOID
NTAPI
DoRaisePriorityCommand(
IN PCHAR PrioString
);
VOID
NTAPI
DoLimitMemoryCommand(
IN PCHAR LimitString
);
VOID
NTAPI
DoCrashCommand(
VOID
);
VOID
NTAPI
DoMachineInformationCommand(
VOID
);
VOID
NTAPI
DoChannelCommand(
IN PCHAR ChannelString
);
VOID
NTAPI
DoCmdCommand(
IN PCHAR InputString
);
VOID
NTAPI
DoLockCommand(
VOID
);
VOID
NTAPI
DoHelpCommand(
VOID
);
VOID
NTAPI
DoGetNetInfo(
IN BOOLEAN DoPrint
);
VOID
NTAPI
DoSetIpAddressCommand(
IN PCHAR IpString
);
VOID
NTAPI
DoTlistCommand(
VOID
);
//
// External data
//
@ -933,7 +1127,9 @@ extern LONG CurrentChannelRefCount;
extern PCHAR SerialPortBuffer;
extern LONG SerialPortConsumerIndex, SerialPortProducerIndex;
extern PCHAR Utf8ConversionBuffer;
extern BOOLEAN GlobalPagingNeeded;
extern ULONG Utf8ConversionBufferSize;
extern BOOLEAN CommandConsoleLaunchingEnabled;
//
// Function to initailize a SAC Semaphore Lock
@ -1046,3 +1242,11 @@ ChannelGetIndex(IN PSAC_CHANNEL Channel)
/* Return the index of the channel */
return Channel->Index;
}
FORCEINLINE
BOOLEAN
ChannelHasNewIBufferData(IN PSAC_CHANNEL Channel)
{
/* Return if there's any new data in the input buffer */
return Channel->ChannelHasNewIBufferData;
}

View file

@ -34,6 +34,56 @@ PCHAR SerialPortBuffer;
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
SacTranslateUtf8ToUnicode(IN CHAR Utf8Char,
IN PCHAR Utf8Buffer,
OUT PWCHAR Utf8Value)
{
ULONG i;
/* Find out how many valid characters we have in the buffer */
i = 0;
while (Utf8Buffer[i++] && (i < 3));
/* If we have at least 3, shift everything by a byte */
if (i >= 3)
{
/* The last input character goes at the end */
Utf8Buffer[0] = Utf8Buffer[1];
Utf8Buffer[1] = Utf8Buffer[2];
Utf8Buffer[2] = Utf8Char;
}
else
{
/* We don't have more than 3 characters, place the input at the index */
Utf8Buffer[i] = Utf8Char;
}
/* Print to debugger */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SacTranslateUtf8ToUnicode - About to decode the UTF8 buffer.\n");
SAC_DBG(SAC_DBG_ENTRY_EXIT, " UTF8[0]: 0x%02lx UTF8[1]: 0x%02lx UTF8[2]: 0x%02lx\n",
Utf8Buffer[0],
Utf8Buffer[1],
Utf8Buffer[2]);
/* Is this a simple ANSI character? */
if (!(Utf8Char & 0x80))
{
/* Return it as Unicode, nothing left to do */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SACDRV: SacTranslateUTf8ToUnicode - Case1\n");
*Utf8Value = (WCHAR)Utf8Char;
Utf8Buffer[0] = Utf8Buffer[1];
Utf8Buffer[1] = Utf8Buffer[2];
Utf8Buffer[2] = UNICODE_NULL;
return TRUE;
}
/* Anything else is not yet supported */
ASSERT(FALSE);
return FALSE;
}
BOOLEAN
NTAPI
SacTranslateUnicodeToUtf8(IN PWCHAR SourceBuffer,
@ -151,8 +201,76 @@ SacFormatMessage(IN PWCHAR FormattedString,
IN PWCHAR MessageString,
IN ULONG MessageSize)
{
/* FIXME: For now don't format anything */
wcsncpy(FormattedString, MessageString, MessageSize / sizeof(WCHAR));
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Entering.\n");
/* Check if any of the parameters are NULL or zero */
if (!(MessageString) || !(FormattedString) || !(MessageSize))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Exiting with invalid parameters.\n");
return;
}
/* Keep going as long as there's still characters */
while ((MessageString[0]) && (MessageSize))
{
/* Is it a non-formatting character? */
if (MessageString[0] != L'%')
{
/* Just write it back into the buffer and keep going */
*FormattedString++ = MessageString[0];
MessageString++;
}
else
{
/* Go over the format characters we recognize */
switch (MessageString[1])
{
case L'0':
*FormattedString = UNICODE_NULL;
return;
case L'%':
*FormattedString++ = L'%';
break;
case L'\\':
*FormattedString++ = L'\r';
*FormattedString++ = L'\n';
break;
case L'r':
*FormattedString++ = L'\r';
break;
case L'b':
*FormattedString++ = L' ';
break;
case L'.':
*FormattedString++ = L'.';
break;
case L'!':
*FormattedString++ = L'!';
break;
default:
/* Only move forward one character */
MessageString--;
break;
}
/* Move forward two characters */
MessageString += 2;
}
/* Move to the next character*/
MessageSize--;
}
/* All done */
*FormattedString = UNICODE_NULL;
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Exiting.\n");
}
NTSTATUS
@ -1105,6 +1223,25 @@ SerialBufferGetChar(OUT PCHAR Char)
return STATUS_SUCCESS;
}
ULONG
NTAPI
GetMessageLineCount(IN ULONG MessageIndex)
{
ULONG LineCount = 0;
PWCHAR Buffer;
/* Get the message buffer */
Buffer = GetMessage(MessageIndex);
if (Buffer)
{
/* Scan it looking for new lines, and increment the conut each time */
while (*Buffer) if (*Buffer++ == L'\n') ++LineCount;
}
/* Return the line count */
return LineCount;
}
ULONG
ConvertAnsiToUnicode(
IN PWCHAR pwch,
@ -1131,16 +1268,6 @@ InvokeUserModeService(
return STATUS_NOT_IMPLEMENTED;
}
BOOLEAN
SacTranslateUtf8ToUnicode(
IN CHAR Utf8Char,
IN PCHAR UnicodeBuffer,
OUT PCHAR Utf8Value
)
{
return FALSE;
}
NTSTATUS
TranslateMachineInformationText(
IN PWCHAR Buffer)
@ -1159,14 +1286,6 @@ CopyAndInsertStringAtInterval(
return STATUS_NOT_IMPLEMENTED;
}
ULONG
GetMessageLineCount(
IN ULONG MessageIndex
)
{
return 0;
}
NTSTATUS
RegisterSacCmdEvent(
IN PVOID Object,

View file

@ -1,36 +1,109 @@
/*
* PROJECT: ReactOS Boot Loader
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/sac/driver/vtutf8chan.c
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
* PROGRAMMERS: ReactOS Portable Systems Group
* PROJECT: ReactOS Drivers
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/sac/driver/vtutf8chan.c
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
/* INCLUDES ******************************************************************/
#include "sacdrv.h"
/* GLOBALS ********************************************************************/
/* GLOBALS *******************************************************************/
/* FUNCTIONS ******************************************************************/
CHAR IncomingUtf8ConversionBuffer[4];
WCHAR IncomingUnicodeValue;
/* FUNCTIONS *****************************************************************/
typedef struct _SAC_CURSOR_DATA
{
UCHAR CursorX;
UCHAR CursorY;
UCHAR CursorVisible;
WCHAR CursorValue;
} SAC_CURSOR_DATA, *PSAC_CURSOR_DATA;
C_ASSERT(sizeof(SAC_CURSOR_DATA) == 6);
#define SAC_VTUTF8_OBUFFER_SIZE 0x2D00
#define SAC_VTUTF8_IBUFFER_SIZE 0x2000
NTSTATUS
VTUTF8ChannelCreate(
IN PSAC_CHANNEL Channel
)
NTAPI
VTUTF8ChannelOInit(IN PSAC_CHANNEL Channel)
{
return STATUS_NOT_IMPLEMENTED;
PSAC_CURSOR_DATA Cursor;
ULONG x, y;
CHECK_PARAMETER(Channel);
/* Set the current channel cursor parameters */
Channel->CursorVisible = 0;
Channel->CursorX = 40;
Channel->CursorY = 37;
/* Loop the output buffer height by width */
Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer;
y = SAC_VTUTF8_COL_HEIGHT - 1;
do
{
x = SAC_VTUTF8_COL_WIDTH;
do
{
/* For every character, set the defaults */
Cursor->CursorValue = ' ';
Cursor->CursorX = 40;
Cursor->CursorY = 38;
/* Move to the next character */
Cursor++;
} while (--x);
} while (--y);
/* All done */
return STATUS_SUCCESS;
}
NTSTATUS
VTUTF8ChannelDestroy(
IN PSAC_CHANNEL Channel
)
NTAPI
VTUTF8ChannelCreate(IN PSAC_CHANNEL Channel)
{
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
CHECK_PARAMETER(Channel);
/* Allocate the output buffer */
Channel->OBuffer = SacAllocatePool(SAC_VTUTF8_OBUFFER_SIZE, GLOBAL_BLOCK_TAG);
CHECK_ALLOCATION(Channel->OBuffer);
/* Allocate the input buffer */
Channel->IBuffer = SacAllocatePool(SAC_VTUTF8_IBUFFER_SIZE, GLOBAL_BLOCK_TAG);
CHECK_ALLOCATION(Channel->IBuffer);
/* Initialize the output stream */
Status = VTUTF8ChannelOInit(Channel);
if (NT_SUCCESS(Status)) return Status;
/* Reset all flags and return success */
_InterlockedExchange(&Channel->ChannelHasNewOBufferData, 0);
_InterlockedExchange(&Channel->ChannelHasNewIBufferData, 0);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
VTUTF8ChannelDestroy(IN PSAC_CHANNEL Channel)
{
CHECK_PARAMETER(Channel);
/* Free the buffer and then destroy the channel */
if (Channel->OBuffer) SacFreePool(Channel->OBuffer);
if (Channel->IBuffer) SacFreePool(Channel->IBuffer);
return ChannelDestroy(Channel);
}
NTSTATUS
NTAPI
VTUTF8ChannelORead(
IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
@ -41,17 +114,8 @@ VTUTF8ChannelORead(
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
VTUTF8ChannelOEcho(
IN PSAC_CHANNEL Channel,
IN PWCHAR String,
IN ULONG Size
)
{
return STATUS_NOT_IMPLEMENTED;
}
BOOLEAN
NTAPI
VTUTF8ChannelScanForNumber(
IN PWCHAR String,
OUT PULONG Number
@ -61,6 +125,7 @@ VTUTF8ChannelScanForNumber(
}
NTSTATUS
NTAPI
VTUTF8ChannelAnsiDispatch(
IN NTSTATUS Status,
IN ULONG AnsiCode,
@ -72,6 +137,7 @@ VTUTF8ChannelAnsiDispatch(
}
NTSTATUS
NTAPI
VTUTF8ChannelProcessAttributes(
IN PSAC_CHANNEL Channel,
IN UCHAR Attribute
@ -80,24 +146,8 @@ VTUTF8ChannelProcessAttributes(
return STATUS_NOT_IMPLEMENTED;
}
ULONG
VTUTF8ChannelGetIBufferIndex(
IN PSAC_CHANNEL Channel
)
{
return 0;
}
VOID
VTUTF8ChannelSetIBufferIndex(
IN PSAC_CHANNEL Channel,
IN ULONG BufferIndex
)
{
}
NTSTATUS
NTAPI
VTUTF8ChannelConsumeEscapeSequence(
IN PSAC_CHANNEL Channel,
IN PWCHAR String
@ -107,6 +157,7 @@ VTUTF8ChannelConsumeEscapeSequence(
}
NTSTATUS
NTAPI
VTUTF8ChannelOFlush(
IN PSAC_CHANNEL Channel
)
@ -115,67 +166,240 @@ VTUTF8ChannelOFlush(
}
NTSTATUS
VTUTF8ChannelIRead(
IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize,
IN PULONG ReturnBufferSize
)
NTAPI
VTUTF8ChannelOWrite2(IN PSAC_CHANNEL Channel,
IN PCHAR String,
IN ULONG Size)
{
return STATUS_NOT_IMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
VTUTF8ChannelIBufferIsFull(
IN PSAC_CHANNEL Channel,
OUT PBOOLEAN BufferStatus
)
NTAPI
VTUTF8ChannelOEcho(IN PSAC_CHANNEL Channel,
IN PCHAR String,
IN ULONG Size)
{
return STATUS_NOT_IMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
WCHAR
VTUTF8ChannelIReadLast(
IN PSAC_CHANNEL Channel
)
NTSTATUS
NTAPI
VTUTF8ChannelOWrite(IN PSAC_CHANNEL Channel,
IN PCHAR String,
IN ULONG Length)
{
return 0;
NTSTATUS Status;
CHECK_PARAMETER1(Channel);
CHECK_PARAMETER2(String);
/* Call the lower level function */
Status = VTUTF8ChannelOWrite2(Channel, String, Length / sizeof(WCHAR));
if (NT_SUCCESS(Status))
{
/* Is the channel enabled for output? */
if ((ConMgrIsWriteEnabled(Channel)) && (Channel->WriteEnabled))
{
/* Go ahead and output it */
Status = VTUTF8ChannelOEcho(Channel, String, Length);
}
else
{
/* Otherwise, just remember that we have new data */
_InterlockedExchange(&Channel->ChannelHasNewOBufferData, 1);
}
}
/* We're done */
return Status;
}
ULONG
VTUTF8ChannelIBufferLength(
IN PSAC_CHANNEL Channel
)
NTAPI
VTUTF8ChannelGetIBufferIndex(IN PSAC_CHANNEL Channel)
{
return 0;
ASSERT(Channel);
ASSERT((Channel->IBufferIndex % sizeof(WCHAR)) == 0);
ASSERT(Channel->IBufferIndex < SAC_VTUTF8_IBUFFER_SIZE);
/* Return the current buffer index */
return Channel->IBufferIndex;
}
VOID
NTAPI
VTUTF8ChannelSetIBufferIndex(IN PSAC_CHANNEL Channel,
IN ULONG BufferIndex)
{
NTSTATUS Status;
ASSERT(Channel);
ASSERT((Channel->IBufferIndex % sizeof(WCHAR)) == 0);
ASSERT(Channel->IBufferIndex < SAC_VTUTF8_IBUFFER_SIZE);
/* Set the new index, and if it's not zero, it means we have data */
Channel->IBufferIndex = BufferIndex;
_InterlockedExchange(&Channel->ChannelHasNewIBufferData, BufferIndex != 0);
/* If we have new data, and an event has been registered... */
if (!(Channel->IBufferIndex) &&
(Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT))
{
/* Go ahead and signal it */
ChannelClearEvent(Channel, HasNewDataEvent);
UNREFERENCED_PARAMETER(Status);
}
}
NTSTATUS
VTUTF8ChannelOWrite2(
IN PSAC_CHANNEL Channel,
IN PWCHAR String,
IN ULONG Size
)
NTAPI
VTUTF8ChannelIRead(IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize,
IN PULONG ReturnBufferSize)
{
return STATUS_NOT_IMPLEMENTED;
ULONG CopyChars;
CHECK_PARAMETER1(Channel);
CHECK_PARAMETER2(Buffer);
CHECK_PARAMETER_WITH_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
/* Assume failure */
*ReturnBufferSize = 0;
/* Check how many bytes are in the buffer */
if (Channel->ChannelInputBufferLength(Channel) == 0)
{
/* Apparently nothing. Make sure the flag indicates so too */
ASSERT(ChannelHasNewIBufferData(Channel) == FALSE);
}
else
{
/* Use the smallest number of bytes either in the buffer or requested */
CopyChars = min(Channel->ChannelInputBufferLength(Channel) * sizeof(WCHAR),
BufferSize);
ASSERT(CopyChars <= Channel->ChannelInputBufferLength(Channel));
/* Copy them into the caller's buffer */
RtlCopyMemory(Buffer, Channel->IBuffer, CopyChars);
/* Update the channel's index past the copied (read) bytes */
VTUTF8ChannelSetIBufferIndex(Channel,
VTUTF8ChannelGetIBufferIndex(Channel) - CopyChars);
/* Are there still bytes that haven't been read yet? */
if (Channel->ChannelInputBufferLength(Channel))
{
/* Shift them up in the buffer */
RtlMoveMemory(Channel->IBuffer,
&Channel->IBuffer[CopyChars],
Channel->ChannelInputBufferLength(Channel) *
sizeof(WCHAR));
}
/* Return the number of bytes we actually copied */
*ReturnBufferSize = CopyChars;
}
/* Return success */
return STATUS_SUCCESS;
}
NTSTATUS
VTUTF8ChannelIWrite(
IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize
)
NTAPI
VTUTF8ChannelIBufferIsFull(IN PSAC_CHANNEL Channel,
OUT PBOOLEAN BufferStatus)
{
return STATUS_NOT_IMPLEMENTED;
CHECK_PARAMETER1(Channel);
/* If the index is beyond the length, the buffer must be full */
*BufferStatus = VTUTF8ChannelGetIBufferIndex(Channel) > SAC_VTUTF8_IBUFFER_SIZE;
return STATUS_SUCCESS;
}
ULONG
NTAPI
VTUTF8ChannelIBufferLength(IN PSAC_CHANNEL Channel)
{
ASSERT(Channel);
/* The index is the length, so divide by two to get character count */
return VTUTF8ChannelGetIBufferIndex(Channel) / sizeof(WCHAR);
}
WCHAR
NTAPI
VTUTF8ChannelIReadLast(IN PSAC_CHANNEL Channel)
{
PWCHAR LastCharLocation;
WCHAR LastChar = 0;
ASSERT(Channel);
/* Check if there's anything to read in the buffer */
if (Channel->ChannelInputBufferLength(Channel))
{
/* Go back one character */
VTUTF8ChannelSetIBufferIndex(Channel,
VTUTF8ChannelGetIBufferIndex(Channel) -
sizeof(WCHAR));
/* Read it, and clear its current value */
LastCharLocation = (PWCHAR)&Channel->IBuffer[VTUTF8ChannelGetIBufferIndex(Channel)];
LastChar = *LastCharLocation;
*LastCharLocation = UNICODE_NULL;
}
/* Return the last character */
return LastChar;
}
NTSTATUS
VTUTF8ChannelOWrite(
IN PSAC_CHANNEL Channel,
IN PWCHAR String,
IN ULONG Length
)
NTAPI
VTUTF8ChannelIWrite(IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize)
{
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
BOOLEAN IsFull;
ULONG Index, i;
CHECK_PARAMETER1(Channel);
CHECK_PARAMETER2(Buffer);
CHECK_PARAMETER_WITH_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
/* First, check if the input buffer still has space */
Status = VTUTF8ChannelIBufferIsFull(Channel, &IsFull);
if (!NT_SUCCESS(Status)) return Status;
if (IsFull) return STATUS_UNSUCCESSFUL;
/* Get the current buffer index */
Index = VTUTF8ChannelGetIBufferIndex(Channel);
if ((SAC_VTUTF8_IBUFFER_SIZE - Index) < BufferSize)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Copy the new data */
for (i = 0; i < BufferSize; i++)
{
/* Convert the character */
if (SacTranslateUtf8ToUnicode(Buffer[i],
IncomingUtf8ConversionBuffer,
&IncomingUnicodeValue))
{
/* Write it into the buffer */
*(PWCHAR)&Channel->IBuffer[VTUTF8ChannelGetIBufferIndex(Channel)] =
IncomingUnicodeValue;
/* Update the index */
Index = VTUTF8ChannelGetIBufferIndex(Channel);
VTUTF8ChannelSetIBufferIndex(Channel, Index + sizeof(WCHAR));
}
}
/* Signal the event, if one was set */
if (Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
{
ChannelSetEvent(Channel, HasNewDataEvent);
}
/* All done */
return STATUS_SUCCESS;
}

View file

@ -1,7 +1,12 @@
MessageId=1
SymbolicName=SAC_INIT_STATUS
Language=English
Computer is booting, SAC started and initialized.\n\nUse the \"ch -?\" command for information about using channels.\nUse the \"?\" command for general help.
Computer is booting, SAC started and initialized.
Use the "ch -?" command for information about using channels.
Use the "?" command for general help.
.
MessageId=2
@ -25,7 +30,8 @@ The SAC is unavailable, it was directly unloaded.
MessageId=5
SymbolicName=SACDRV_5
Language=English
The SAC will become unavailable soon. The computer is shutting down.\n
The SAC will become unavailable soon. The computer is shutting down.
.
MessageId=6
@ -295,7 +301,9 @@ SAC failed to retrieve the task list.
MessageId=69
SymbolicName=SACDRV_69
Language=English
memory: %%4ld kb uptime:%%3ld %%2ld:%%02ld:%%02ld.%%03ld\n\n
memory: %%4ld kb uptime:%%3ld %%2ld:%%02ld:%%02ld.%%03ld
.
MessageId=70
@ -319,7 +327,8 @@ Language=English
MessageId=73
SymbolicName=SACDRV_73
Language=English
\n Memory:%%7ldK Avail:%%7ldK TotalWs:%%7ldK InRam Kernel:%%5ldK P:%%5ldK
Memory:%%7ldK Avail:%%7ldK TotalWs:%%7ldK InRam Kernel:%%5ldK P:%%5ldK
.
MessageId=74
@ -421,7 +430,8 @@ That process has been killed and is being cleaned up by the system.
MessageId=90
SymbolicName=SACDRV_90
Language=English
A duplicate process id is being cleaned up by the system. Try the \ncommand again in a few seconds.
A duplicate process id is being cleaned up by the system. Try the
command again in a few seconds.
.
MessageId=92
@ -523,31 +533,46 @@ Error: Could not find a channel with that name.
MessageId=108
SymbolicName=SACDRV_108
Language=English
Channel List\n \n(Use \"ch -?\" for information on using channels)\n\n# Status Channel Name
Channel List
(Use "ch -?" for information on using channels)
# Status Channel Name
.
MessageId=109
SymbolicName=SACDRV_109
Language=English
EVENT: A new channel has been created. Use \"ch -?\" for channel help.\nChannel: %%s
EVENT: A new channel has been created. Use "ch -?" for channel help.
Channel: %%s
.
MessageId=110
SymbolicName=SACDRV_110
Language=English
EVENT: A channel has been closed.\nChannel: %%s
EVENT: A channel has been closed.
Channel: %%s
.
MessageId=111
SymbolicName=SACDRV_111
Language=English
Name: %%s\nDescription: %%s\nType: %%s\nChannel GUID: %%08lx-%%04x-%%04x-%%02x%%02x-%%02x%%02x%%02x%%02x%%02x%%02x\nApplication Type GUID: %%08lx-%%04x-%%04x-%%02x%%02x-%%02x%%02x%%02x%%02x%%02x%%02x\n\nPress <esc><tab> for next channel.\nPress <esc><tab>0 to return to the SAC channel.\nUse any other key to view this channel.\n
Name: %%s
Description: %%s
Type: %%s
Channel GUID: %%08lx-%%04x-%%04x-%%02x%%02x-%%02x%%02x%%02x%%02x%%02x%%02x
Application Type GUID: %%08lx-%%04x-%%04x-%%02x%%02x-%%02x%%02x%%02x%%02x%%02x%%02x
Press <esc><tab> for next channel.
Press <esc><tab>0 to return to the SAC channel.
Use any other key to view this channel.
.
MessageId=112
SymbolicName=SACDRV_112
Language=English
ch Channel management commands. Use ch -? for more help.
ch Channel management commands. Use ch -? for more help.
.
MessageId=113
@ -571,7 +596,10 @@ SAC preparing to shutdown the system.
MessageId=116
SymbolicName=SACDRV_116
Language=English
Error! Failed to remove channel! \n\nPlease contact your system administrator.\n
Error! Failed to remove channel!
Please contact your system administrator.
.
MessageId=119
@ -583,7 +611,9 @@ cmd Create a Command Prompt channel.
MessageId=120
SymbolicName=SACDRV_120
Language=English
Timeout: Unable to launch a Command Prompt. The service responsible for \n launching Command Prompt channels has timed out. This may be \n because the service is malfunctioning or is unresponsive.
Timeout: Unable to launch a Command Prompt. The service responsible for
launching Command Prompt channels has timed out. This may be
because the service is malfunctioning or is unresponsive.
.
MessageId=121
@ -601,7 +631,10 @@ Error: The SAC Command Console session failed to be created.
MessageId=131
SymbolicName=SACDRV_131
Language=English
Error: Unable to launch a Command Prompt. The service responsible for launching\n Command Prompt channels has not yet registered. This may be because the\n service is not yet started, is disabled by the administrator, is\n malfunctioning or is unresponsive.
Error: Unable to launch a Command Prompt. The service responsible for launching
Command Prompt channels has not yet registered. This may be because the
service is not yet started, is disabled by the administrator, is
malfunctioning or is unresponsive.
.
MessageId=132
@ -619,19 +652,39 @@ EVENT: The CMD command is unavailable.
MessageId=134
SymbolicName=SACDRV_134
Language=English
EVENT: An attempt was made to close a channel but failed.\nChannel: %%s
EVENT: An attempt was made to close a channel but failed.
Channel: %%s
.
MessageId=135
SymbolicName=SACDRV_135
Language=English
EVENT: An attempt to close a channel failed because it is already closed.\nChannel: %%s
EVENT: An attempt to close a channel failed because it is already closed.
Channel: %%s
.
MessageId=136
SymbolicName=SACDRV_136
Language=English
Channel management commands:\n\nch List all channels.\n\nStatus Legend: (AB)\nA: Channel operational status\n 'A' = Channel is active.\n 'I' = Channel is inactive.\nB: Channel Type\n 'V' = VT-UTF8 emulation.\n 'R' = Raw - no emulation.\n\nch -si <#> Switch to a channel by its number.\nch -sn <name> Switch to a channel by its name.\nch -ci <#> Close a channel by its number.\nch -cn <name> Close a channel by its name.\n\nPress <esc><tab> to select a channel.\nPress <esc><tab>0 to return to the SAC channel.
Channel management commands:
ch List all channels.
Status Legend: (AB)
A: Channel operational status
'A' = Channel is active.
'I' = Channel is inactive.
B: Channel Type
'V' = VT-UTF8 emulation.
'R' = Raw - no emulation.
ch -si <#> Switch to a channel by its number.
ch -sn <name> Switch to a channel by its name.
ch -ci <#> Close a channel by its number.
ch -cn <name> Close a channel by its name.
Press <esc><tab> to select a channel.
Press <esc><tab>0 to return to the SAC channel.
.
MessageId=137
@ -703,5 +756,5 @@ not yet initialized%0
MessageId=154
SymbolicName=SACDRV_154
Language=English
The maximum number of channels has been reached.
The maximum number of channels has been reached.
.