Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895/* * PROJECT: ReactOS Drivers * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: drivers/sac/driver/conmgr.c * PURPOSE: Driver for the Server Administration Console (SAC) for EMS * PROGRAMMERS: ReactOS Portable Systems Group */
/* INCLUDES *******************************************************************/
#include "sacdrv.h"
#include <initguid.h>
/* GLOBALS ********************************************************************/
DEFINE_GUID(PRIMARY_SAC_CHANNEL_APPLICATION_GUID, 0x63D02270, 0x8AA4, 0x11D5, 0xBC, 0xCF, 0x80, 0x6D, 0x61, 0x72, 0x69, 0x6F);
LONG CurrentChannelRefCount;KMUTEX CurrentChannelLock;
PSAC_CHANNEL CurrentChannel;PSAC_CHANNEL SacChannel;
ULONG ExecutePostConsumerCommand;PSAC_CHANNEL ExecutePostConsumerCommandData;
BOOLEAN InputInEscape, InputInEscTab, ConMgrLastCharWasCR;CHAR InputBuffer[80];
BOOLEAN GlobalPagingNeeded, GlobalDoThreads;
/* FUNCTIONS ******************************************************************/
VOIDNTAPISacPutString(IN PWCHAR String){ NTSTATUS Status;
/* Write the string on the main SAC channel */ Status = ChannelOWrite(SacChannel, (PCHAR)String, wcslen(String) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { SAC_DBG(SAC_DBG_INIT, "SAC XmlMgrSacPutString: OWrite failed\n"); }}
BOOLEANNTAPISacPutSimpleMessage(IN ULONG MessageIndex){ PWCHAR MessageBuffer; BOOLEAN Result;
/* Get the message */ MessageBuffer = GetMessage(MessageIndex); if (MessageBuffer) { /* Output it */ SacPutString(MessageBuffer); Result = TRUE; } else { Result = FALSE; }
/* All done */ return Result;}
NTSTATUSNTAPIConMgrDisplayCurrentChannel(VOID){ NTSTATUS Status; BOOLEAN HasRedraw;
/* Make sure the lock is held */ SacAssertMutexLockHeld();
/* Check if we can redraw */ Status = ChannelHasRedrawEvent(CurrentChannel, &HasRedraw); if (NT_SUCCESS(Status)) { /* Enable writes */ _InterlockedExchange(&CurrentChannel->WriteEnabled, 1); if (HasRedraw) { /* If we can redraw, set the event */ ChannelSetRedrawEvent(CurrentChannel); }
/* Flush the output */ Status = ChannelOFlush(CurrentChannel); }
/* All done, return the status */ return Status;}
NTSTATUSNTAPIConMgrWriteData(IN PSAC_CHANNEL Channel, IN PVOID Buffer, IN ULONG BufferLength){ ULONG i; NTSTATUS Status; LARGE_INTEGER Interval;
/* Loop up to 32 times */ for (i = 0; i < 32; i++) { /* Attempt sending the data */ Status = HeadlessDispatch(HeadlessCmdPutData, Buffer, BufferLength, NULL, NULL); if (Status != STATUS_UNSUCCESSFUL) break;
/* Sending the data on the port failed, wait a second... */ Interval.HighPart = -1; Interval.LowPart = -100000; KeDelayExecutionThread(KernelMode, FALSE, &Interval); }
/* After 32 attempts it should really have worked... */ ASSERT(NT_SUCCESS(Status)); return Status;}
NTSTATUSNTAPIConMgrFlushData(IN PSAC_CHANNEL Channel){ /* Nothing to do */ return STATUS_SUCCESS;}
BOOLEANNTAPIConMgrIsSacChannel(IN PSAC_CHANNEL Channel){ /* Check which channel is active */ return Channel == SacChannel;}
BOOLEANNTAPIConMgrIsWriteEnabled(IN PSAC_CHANNEL Channel){ /* If the current channel is active, allow writes */ return ChannelIsEqual(Channel, &CurrentChannel->ChannelId);}
NTSTATUSNTAPIConMgrInitialize(VOID){ PWCHAR pcwch; PSAC_CHANNEL FoundChannel; SAC_CHANNEL_ATTRIBUTES SacChannelAttributes; NTSTATUS Status;
/* Initialize the connection manager lock */ SacInitializeMutexLock(); SacAcquireMutexLock();
/* Setup the attributes for the raw SAC channel */ RtlZeroMemory(&SacChannelAttributes, sizeof(SacChannelAttributes)); SacChannelAttributes.ChannelType = VtUtf8;
/* Get the right name for it */ pcwch = GetMessage(SAC_CHANNEL_NAME); ASSERT(pcwch); wcsncpy(SacChannelAttributes.NameBuffer, pcwch, SAC_CHANNEL_NAME_SIZE); SacChannelAttributes.NameBuffer[SAC_CHANNEL_NAME_SIZE] = ANSI_NULL;
/* Get the right description for it */ pcwch = GetMessage(SAC_CHANNEL_DESCRIPTION); ASSERT(pcwch); wcsncpy(SacChannelAttributes.DescriptionBuffer, pcwch, SAC_CHANNEL_DESCRIPTION_SIZE); SacChannelAttributes.DescriptionBuffer[SAC_CHANNEL_DESCRIPTION_SIZE] = ANSI_NULL;
/* Set all the right flags */ SacChannelAttributes.Flag = SAC_CHANNEL_FLAG_APPLICATION | SAC_CHANNEL_FLAG_INTERNAL; SacChannelAttributes.CloseEvent = NULL; SacChannelAttributes.HasNewDataEvent = NULL; SacChannelAttributes.LockEvent = NULL; SacChannelAttributes.RedrawEvent = NULL; SacChannelAttributes.ChannelId = PRIMARY_SAC_CHANNEL_APPLICATION_GUID;
/* Now create it */ Status = ChanMgrCreateChannel(&SacChannel, &SacChannelAttributes); if (NT_SUCCESS(Status)) { /* Try to get it back */ Status = ChanMgrGetByHandle(SacChannel->ChannelId, &FoundChannel); if (NT_SUCCESS(Status)) { /* Set it as the current and SAC channel */ SacChannel = CurrentChannel = FoundChannel;
/* Disable writes for now and clear the display */ _InterlockedExchange(&FoundChannel->WriteEnabled, FALSE); Status = HeadlessDispatch(HeadlessCmdClearDisplay, NULL, 0, NULL, NULL); if (!NT_SUCCESS(Status)) { SAC_DBG(SAC_DBG_INIT, "SAC ConMgrInitialize: Failed dispatch\n"); }
/* Display the initial prompt */ SacPutSimpleMessage(SAC_NEWLINE); SacPutSimpleMessage(SAC_INIT_STATUS); SacPutSimpleMessage(SAC_NEWLINE); SacPutSimpleMessage(SAC_PROMPT);
/* Display the current channel */ ConMgrDisplayCurrentChannel(); } }
/* Release the channel lock */ SacReleaseMutexLock(); return STATUS_SUCCESS;}
VOIDNTAPIConMgrEventMessage(IN PWCHAR EventMessage, IN BOOLEAN LockHeld){ /* Acquire the current channel lock if needed */ if (!LockHeld) SacAcquireMutexLock();
/* Send out the event message */ SacPutSimpleMessage(2); SacPutString(EventMessage); SacPutSimpleMessage(3);
/* Release the current channel lock if needed */ if (!LockHeld) SacReleaseMutexLock();}
BOOLEANNTAPIConMgrSimpleEventMessage(IN ULONG MessageIndex, IN BOOLEAN LockHeld){ PWCHAR MessageBuffer; BOOLEAN Result;
/* Get the message to send out */ MessageBuffer = GetMessage(MessageIndex); if (MessageBuffer) { /* Send it */ ConMgrEventMessage(MessageBuffer, LockHeld); Result = TRUE; } else { /* It doesn't exist, fail */ Result = FALSE; }
/* Return if the message was sent or not */ return Result;}
NTSTATUSNTAPIConMgrDisplayFastChannelSwitchingInterface(IN PSAC_CHANNEL Channel){ /* FIXME: TODO */ ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
NTSTATUSNTAPIConMgrSetCurrentChannel(IN PSAC_CHANNEL Channel){ NTSTATUS Status; BOOLEAN HasRedrawEvent;
/* Make sure the lock is held */ SacAssertMutexLockHeld();
/* Check if we have a redraw event */ Status = ChannelHasRedrawEvent(CurrentChannel, &HasRedrawEvent); if (!NT_SUCCESS(Status)) return Status;
/* Clear it */ if (HasRedrawEvent) ChannelClearRedrawEvent(CurrentChannel);
/* Disable writes on the current channel */ _InterlockedExchange(&CurrentChannel->WriteEnabled, 0);
/* Release the current channel */ Status = ChanMgrReleaseChannel(CurrentChannel); if (!NT_SUCCESS(Status)) return Status;
/* Set the new channel and also disable writes on it */ CurrentChannel = Channel; _InterlockedExchange(&Channel->WriteEnabled, 0); return STATUS_SUCCESS;}
NTSTATUSNTAPIConMgrResetCurrentChannel(IN BOOLEAN KeepChannel){ NTSTATUS Status; PSAC_CHANNEL Channel;
/* Make sure the lock is held */ SacAssertMutexLockHeld();
/* Get the current SAC channel */ Status = ChanMgrGetByHandle(SacChannel->ChannelId, &Channel); if (NT_SUCCESS(Status)) { /* Set this as the current SAC channel*/ SacChannel = Channel; Status = ConMgrSetCurrentChannel(Channel); if (NT_SUCCESS(Status)) { /* Check if the caller wants to switch or not */ if (KeepChannel) { /* Nope, keep the same channel */ Status = ConMgrDisplayCurrentChannel(); } else { /* Yep, show the switching interface */ Status = ConMgrDisplayFastChannelSwitchingInterface(CurrentChannel); } } }
/* All done */ return Status;}
NTSTATUSNTAPIConMgrChannelClose(IN PSAC_CHANNEL Channel){ NTSTATUS Status = STATUS_SUCCESS;
/* Check if we're in the right channel */ if (ConMgrIsWriteEnabled(Channel)) { /* Yep, reset it */ Status = ConMgrResetCurrentChannel(FALSE); ASSERT(NT_SUCCESS(Status)); }
/* All done */ return Status;}
NTSTATUSNTAPIConMgrShutdown(VOID){ NTSTATUS Status;
/* Check if we have a SAC channel */ if (SacChannel) { /* Close it */ Status = ChannelClose(SacChannel); if (!NT_SUCCESS(Status)) { SAC_DBG(SAC_DBG_INIT, "SAC ConMgrShutdown: failed closing SAC channel.\n"); }
/* No longer have one */ SacChannel = NULL; }
/* Check if we have a current channel */ if (CurrentChannel) { /* Release it */ Status = ChanMgrReleaseChannel(CurrentChannel); if (!NT_SUCCESS(Status)) { SAC_DBG(SAC_DBG_INIT, "SAC ConMgrShutdown: failed releasing current channel\n"); }
/* No longer have one */ CurrentChannel = NULL; }
/* All done */ return STATUS_SUCCESS;}
NTSTATUSNTAPIConMgrAdvanceCurrentChannel(VOID){ NTSTATUS Status; ULONG Index; PSAC_CHANNEL Channel;
/* Should always be called with the lock held */ SacAssertMutexLockHeld();
/* Get the next active channel */ Status = ChanMgrGetNextActiveChannel(CurrentChannel, &Index, &Channel); if (NT_SUCCESS(Status)) { /* Set it as the new channel */ Status = ConMgrSetCurrentChannel(Channel); if (NT_SUCCESS(Status)) { /* Let the user switch to it */ Status = ConMgrDisplayFastChannelSwitchingInterface(Channel); } }
/* All done */ return Status;}
NTSTATUSNTAPIConMgrChannelOWrite(IN PSAC_CHANNEL Channel, IN PVOID WriteBuffer){ NTSTATUS Status;
/* Do the write with the lock held */ SacAcquireMutexLock(); ASSERT(FALSE); Status = STATUS_NOT_IMPLEMENTED;// ChannelOWrite(Channel, WriteBuffer + 24, *(WriteBuffer + 20)); SacReleaseMutexLock();
/* Return back to the caller */ ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND); return Status;}
VOIDNTAPIConMgrProcessInputLine(VOID){ BOOLEAN EnablePaging; NTSTATUS Status;
SAC_DBG(SAC_DBG_INIT, "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, NULL); if (!NT_SUCCESS(Status)) SAC_DBG(SAC_DBG_INIT, "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(SAC_UNKNOWN_COMMAND); }}
VOIDNTAPIConMgrSerialPortConsumer(VOID){ NTSTATUS Status; CHAR Char; WCHAR LastChar; CHAR ReadBuffer[2]; ULONG ReadBufferSize, i; WCHAR StringBuffer[2]; SAC_DBG(SAC_DBG_MACHINE, "SAC TimerDpcRoutine: Entering.\n"); //bug
/* Acquire the manager lock and make sure a channel is selected */ SacAcquireMutexLock(); ASSERT(CurrentChannel);
/* Read whatever came off the serial port */ for (Status = SerialBufferGetChar(&Char); NT_SUCCESS(Status); Status = SerialBufferGetChar(&Char)) { /* If nothing came through, bail out */ if (Status == STATUS_NO_DATA_DETECTED) break;
/* Check if ESC was pressed */ if (Char == '\x1B') { /* Was it already pressed? */ if (!InputInEscape) { /* First time ESC is pressed! Remember and reset TAB state */ InputInEscTab = FALSE; InputInEscape = TRUE; continue; } } else if (Char == '\t') { /* TAB was pressed, is it following ESC (VT-100 sequence)? */ if (InputInEscape) { /* Yes! This must be the only ESC-TAB we see in once moment */ ASSERT(InputInEscTab == FALSE);
/* No longer treat us as being in ESC */ InputInEscape = FALSE;
/* ESC-TAB is the sequence for changing channels */ Status = ConMgrAdvanceCurrentChannel(); if (!NT_SUCCESS(Status)) break;
/* Remember ESC-TAB was pressed */ InputInEscTab = TRUE; continue; } } else if ((Char == '0') && (InputInEscTab)) { /* It this ESC-TAB-0? */ ASSERT(InputInEscape == FALSE); InputInEscTab = FALSE;
/* If writes are already enabled, don't do this */ if (!CurrentChannel->WriteEnabled) { /* Reset the channel, this is our special sequence */ Status = ConMgrResetCurrentChannel(FALSE); if (!NT_SUCCESS(Status)) break; }
continue; } else { /* This is ESC-TAB-something else */ InputInEscTab = FALSE;
/* If writes are already enabled, don't do this */ if (!CurrentChannel->WriteEnabled) { /* Display the current channel */ InputInEscape = FALSE; Status = ConMgrDisplayCurrentChannel(); if (!NT_SUCCESS(Status)) break; continue; } }
/* Check if an ESC-sequence was being typed into a command channel */ if ((InputInEscape) && (CurrentChannel != SacChannel)) { /* Store the ESC in the current channel buffer */ ReadBuffer[0] = '\x1B'; ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR)); }
/* Check if we are no longer pressing ESC and exit the mode if so */ if (Char != '\x1B') InputInEscape = FALSE;
/* Whatever was typed in, save it int eh current channel */ ChannelIWrite(CurrentChannel, &Char, sizeof(Char));
/* If this is a command channel, we're done, nothing to process */ if (CurrentChannel != SacChannel) continue;
/* Check for line feed right after a carriage return */ if ((ConMgrLastCharWasCR) && (Char == '\n')) { /* Ignore the line feed, but clear the carriage return */ ChannelIReadLast(CurrentChannel); ConMgrLastCharWasCR = 0; continue; }
/* Check if the user did a carriage return */ ConMgrLastCharWasCR = (Char == '\n');
/* If the user did an "ENTER", we need to run the command */ if ((Char == '\n') || (Char == '\r')) { /* Echo back to the terminal */ SacPutString(L"\r\n");
DoLineParsing: /* Inhibit the character (either CR or LF) */ ChannelIReadLast(CurrentChannel);
/* NULL-terminate the channel's input buffer */ 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); ReadBuffer[0] = (CHAR) LastChar; } while ((!(LastChar) || (LastChar == L' ') || (LastChar == L'\t')) && (ChannelIBufferLength(CurrentChannel)));
/* Write back into the channel the last character */ ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR));
/* NULL-terminate the input buffer */ ReadBuffer[0] = ANSI_NULL; ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR));
/* Now loop over every first character */ do { /* Read every character in the channel, and strip whitespace */ ChannelIRead(CurrentChannel, ReadBuffer, sizeof(ReadBuffer), &ReadBufferSize); } while ((ReadBufferSize) && ((ReadBuffer[0] == ' ') || (ReadBuffer[0] == '\t')));
/* We read one more than we should, so treat that as our first one */ InputBuffer[0] = ReadBuffer[0]; i = 1;
/* And now loop reading all the others */ do { /* Read each character -- there should be max 80 */ ChannelIRead(CurrentChannel, ReadBuffer, sizeof(ReadBuffer), &ReadBufferSize); ASSERT(i < SAC_VTUTF8_COL_WIDTH); InputBuffer[i++] = ReadBuffer[0]; } while (ReadBufferSize);
/* Now go over the entire input stream */ for (i = 0; InputBuffer[i]; i++) { /* Again it should be less than 80 characters */ ASSERT(i < SAC_VTUTF8_COL_WIDTH);
/* And downbase each character */ Char = InputBuffer[i]; if ((Char >= 'A') && (Char <= 'Z')) InputBuffer[i] = Char + ' '; }
/* Ok, at this point, no pending command should exist */ ASSERT(ExecutePostConsumerCommand == Nothing);
/* Go and process the input, then show the prompt again */ ConMgrProcessInputLine(); SacPutSimpleMessage(SAC_PROMPT);
/* If the user typed a valid command, get out of here */ if (ExecutePostConsumerCommand != Nothing) break;
/* Keep going */ continue; }
/* Check if the user typed backspace or delete */ if ((Char == '\b') || (Char == '\x7F')) { /* Omit the last character, which should be the DEL/BS itself */ if (ChannelIBufferLength(CurrentChannel)) { ChannelIReadLast(CurrentChannel); }
/* Omit the before-last character, which is the one to delete */ if (ChannelIBufferLength(CurrentChannel)) { /* Also send two backspaces back to the console */ SacPutString(L"\b \b"); ChannelIReadLast(CurrentChannel); }
/* Keep going */ continue; }
/* If the user pressed CTRL-C at this point, treat it like ENTER */ if (Char == '\x03') goto DoLineParsing;
/* Check if the user pressed TAB */ if (Char == '\t') { /* Omit it, send a BELL, and keep going. We ignore TABs */ ChannelIReadLast(CurrentChannel); SacPutString(L"\a"); continue; }
/* Check if the user is getting close to the end of the screen */ if (ChannelIBufferLength(CurrentChannel) == (SAC_VTUTF8_COL_WIDTH - 2)) { /* Delete the last character, replacing it with this one instead */ swprintf(StringBuffer, L"\b%c", Char); SacPutString(StringBuffer);
/* Omit the last two characters from the buffer */ ChannelIReadLast(CurrentChannel); ChannelIReadLast(CurrentChannel);
/* Write the last character that was just typed in */ ReadBuffer[0] = Char; ChannelIWrite(CurrentChannel, ReadBuffer, sizeof(CHAR)); continue; }
/* Nothing of interest happened, just write the character back */ swprintf(StringBuffer, L"%c", Char); SacPutString(StringBuffer); }
/* We're done, release the lock */ SacReleaseMutexLock(); SAC_DBG(SAC_DBG_MACHINE, "SAC TimerDpcRoutine: Exiting.\n"); //bug}
VOIDNTAPIConMgrWorkerProcessEvents(IN PSAC_DEVICE_EXTENSION DeviceExtension){ SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC WorkerProcessEvents: Entering.\n");
/* Enter the main loop */ while (TRUE) { /* Wait for something to do */ KeWaitForSingleObject(&DeviceExtension->Event, Executive, KernelMode, FALSE, NULL);
/* Consume data off the serial port */ ConMgrSerialPortConsumer(); switch (ExecutePostConsumerCommand) { case Restart: /* A reboot was sent, do it */ DoRebootCommand(FALSE); break;
case Close: /* A close was sent, do it */ ChanMgrCloseChannel(ExecutePostConsumerCommandData); ChanMgrReleaseChannel(ExecutePostConsumerCommandData); break;
case Shutdown: /* A shutdown was sent, do it */ DoRebootCommand(TRUE); break; }
/* Clear the serial port consumer state */ ExecutePostConsumerCommand = Nothing; ExecutePostConsumerCommandData = NULL; }}
NTSTATUSNTAPIConMgrGetChannelCloseMessage(IN PSAC_CHANNEL Channel, IN NTSTATUS CloseStatus, OUT PWCHAR OutputBuffer){ ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
NTSTATUSNTAPIConMgrHandleEvent(IN ULONG EventCode, IN PSAC_CHANNEL Channel, OUT PVOID Data){ ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}