X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=drivers%2Fsac%2Fdriver%2Fvtutf8chan.c;h=946a90ceafe81b41940c4e418f6f01eb07507b78;hp=26f80d8b4489b12f12bf0c928ac6d6a2ea66a0a0;hb=8e37700e5c527418228fa2269adc06c7ebcebcb9;hpb=23fbc3204c2fea26c52b8116bf0fe4842feba0dd diff --git a/drivers/sac/driver/vtutf8chan.c b/drivers/sac/driver/vtutf8chan.c index 26f80d8b448..946a90ceafe 100644 --- a/drivers/sac/driver/vtutf8chan.c +++ b/drivers/sac/driver/vtutf8chan.c @@ -1,57 +1,121 @@ /* - * 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 -VTUTF8ChannelORead( - IN PSAC_CHANNEL Channel, - IN PCHAR Buffer, - IN ULONG BufferSize, - OUT PULONG ByteCount - ) +NTAPI +VTUTF8ChannelDestroy(IN PSAC_CHANNEL Channel) { - return STATUS_NOT_IMPLEMENTED; + 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 -VTUTF8ChannelOEcho( +NTAPI +VTUTF8ChannelORead( IN PSAC_CHANNEL Channel, - IN PWCHAR String, - IN ULONG Size + IN PCHAR Buffer, + IN ULONG BufferSize, + OUT PULONG ByteCount ) { 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; }