mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[SACDRV]: Implement VTUTF8ChannelScanForNumber.
[SACDRV]: Implement VTUTF8ChannelOEcho. [SACDRV]: WIP-lement VTUTF8ChannelConsumeEscapeSequence. Have to do some reading up on ANSI to get this right. svn path=/trunk/; revision=59824
This commit is contained in:
parent
abedd40dd8
commit
e84d7ea634
2 changed files with 489 additions and 50 deletions
|
@ -158,6 +158,8 @@
|
||||||
#define SAC_MAX_MESSAGES 200
|
#define SAC_MAX_MESSAGES 200
|
||||||
#define SAC_VTUTF8_COL_WIDTH 80
|
#define SAC_VTUTF8_COL_WIDTH 80
|
||||||
#define SAC_VTUTF8_COL_HEIGHT 25
|
#define SAC_VTUTF8_COL_HEIGHT 25
|
||||||
|
#define SAC_VTUTF8_ROW_HEIGHT 24
|
||||||
|
#define MAX_UTF8_ENCODE_BLOCK_LENGTH (Utf8ConversionBufferSize / 3 - 1)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Channel flags
|
// Channel flags
|
||||||
|
@ -1012,6 +1014,17 @@ VerifyEventWaitable(
|
||||||
OUT PVOID *ActualWaitObject
|
OUT PVOID *ActualWaitObject
|
||||||
);
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
SacTranslateUnicodeToUtf8(
|
||||||
|
IN PWCHAR SourceBuffer,
|
||||||
|
IN ULONG SourceBufferLength,
|
||||||
|
OUT PCHAR DestinationBuffer,
|
||||||
|
IN ULONG DestinationBufferSize,
|
||||||
|
OUT PULONG UTF8Count,
|
||||||
|
OUT PULONG ProcessedCount
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// SAC Command Functions
|
// SAC Command Functions
|
||||||
//
|
//
|
||||||
|
|
|
@ -27,9 +27,398 @@ typedef struct _SAC_CURSOR_DATA
|
||||||
|
|
||||||
C_ASSERT(sizeof(SAC_CURSOR_DATA) == 6);
|
C_ASSERT(sizeof(SAC_CURSOR_DATA) == 6);
|
||||||
|
|
||||||
|
typedef struct _SAC_STATIC_ESCAPE_STRING
|
||||||
|
{
|
||||||
|
WCHAR Sequence[10];
|
||||||
|
ULONG Size;
|
||||||
|
ULONG Action;
|
||||||
|
} SAC_STATIC_ESCAPE_STRING, *PSAC_STATIC_ESCAPE_STRING;
|
||||||
|
|
||||||
|
SAC_STATIC_ESCAPE_STRING SacStaticEscapeStrings [] =
|
||||||
|
{
|
||||||
|
{ L"[A", 2, 0 },
|
||||||
|
{ L"[B", 2, 1 },
|
||||||
|
{ L"[C", 2, 2 },
|
||||||
|
{ L"[D", 2, 3 },
|
||||||
|
{ L"[0Z", 3, 11 },
|
||||||
|
{ L"[K", 2, 12 },
|
||||||
|
{ L"[1K", 3, 13 },
|
||||||
|
{ L"[2K", 3, 14 },
|
||||||
|
{ L"[J", 2, 15 },
|
||||||
|
{ L"[1J", 3, 16 },
|
||||||
|
{ L"[2J", 3, 17 },
|
||||||
|
};
|
||||||
|
|
||||||
#define SAC_VTUTF8_OBUFFER_SIZE 0x2D00
|
#define SAC_VTUTF8_OBUFFER_SIZE 0x2D00
|
||||||
#define SAC_VTUTF8_IBUFFER_SIZE 0x2000
|
#define SAC_VTUTF8_IBUFFER_SIZE 0x2000
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
VTUTF8ChannelScanForNumber(IN PWCHAR String,
|
||||||
|
OUT PULONG Number)
|
||||||
|
{
|
||||||
|
/* If the first character is invalid, fail early */
|
||||||
|
if ((*String < L'0') || (*String > L'9')) return FALSE;
|
||||||
|
|
||||||
|
/* Otherwise, initialize the output and loop the string */
|
||||||
|
*Number = 0;
|
||||||
|
while ((*String >= L'0') && (*String <= L'9'))
|
||||||
|
{
|
||||||
|
/* Save the first decimal */
|
||||||
|
*Number = 10 * *Number;
|
||||||
|
|
||||||
|
/* Compute and add the second one */
|
||||||
|
*Number += *++String - L'0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All done */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
VTUTF8ChannelAnsiDispatch(
|
||||||
|
IN NTSTATUS Status,
|
||||||
|
IN ULONG AnsiCode,
|
||||||
|
IN PWCHAR Data,
|
||||||
|
IN ULONG Length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
VTUTF8ChannelProcessAttributes(
|
||||||
|
IN PSAC_CHANNEL Channel,
|
||||||
|
IN UCHAR Attribute
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
VTUTF8ChannelAssertCursor(IN PSAC_CHANNEL Channel)
|
||||||
|
{
|
||||||
|
ASSERT(Channel->CursorRow < SAC_VTUTF8_ROW_HEIGHT);
|
||||||
|
ASSERT(Channel->CursorCol < SAC_VTUTF8_COL_WIDTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel,
|
||||||
|
IN PWCHAR String)
|
||||||
|
{
|
||||||
|
ULONG Number, Number2, Number3, i, Action, Result;
|
||||||
|
PWCHAR Sequence;
|
||||||
|
PSAC_CURSOR_DATA Cursor;
|
||||||
|
ASSERT(String[0] == L'\x1B');
|
||||||
|
|
||||||
|
for (i = 0; i < RTL_NUMBER_OF(SacStaticEscapeStrings); i++)
|
||||||
|
{
|
||||||
|
if (!wcsncmp(String + 1,
|
||||||
|
SacStaticEscapeStrings[i].Sequence,
|
||||||
|
SacStaticEscapeStrings[i].Size))
|
||||||
|
{
|
||||||
|
Action = SacStaticEscapeStrings[i].Action;
|
||||||
|
Result = SacStaticEscapeStrings[i].Size + 1;
|
||||||
|
Number = Number2 = Number3 = 1;
|
||||||
|
goto ProcessString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String[1] != L'[') return 0;
|
||||||
|
|
||||||
|
Sequence = String + 2;
|
||||||
|
switch (*Sequence)
|
||||||
|
{
|
||||||
|
case L'A':
|
||||||
|
Action = 0;
|
||||||
|
break;
|
||||||
|
case L'B':
|
||||||
|
Action = 1;
|
||||||
|
break;
|
||||||
|
case L'C':
|
||||||
|
Action = 3; //bug
|
||||||
|
break;
|
||||||
|
case L'D':
|
||||||
|
Action = 2; //bug
|
||||||
|
break;
|
||||||
|
case L'K':
|
||||||
|
Action = 12;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!VTUTF8ChannelScanForNumber(Sequence, &Number)) return 0;
|
||||||
|
|
||||||
|
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
||||||
|
|
||||||
|
if (*Sequence == 'm')
|
||||||
|
{
|
||||||
|
switch (Number)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Action = 4;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Action = 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
Action = 5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
Action = 9;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 22:
|
||||||
|
Action = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 25:
|
||||||
|
Action = 6;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 27:
|
||||||
|
Action = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if ((Number < 40) || (Number > 47))
|
||||||
|
{
|
||||||
|
if ((Number < 30) || (Number > 39))
|
||||||
|
{
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Action = 22;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Action = 21;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*Sequence != L';') return 0;
|
||||||
|
Sequence++;
|
||||||
|
|
||||||
|
if (!VTUTF8ChannelScanForNumber(Sequence, &Number2)) return 0;
|
||||||
|
|
||||||
|
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
||||||
|
|
||||||
|
if (*Sequence == L'm')
|
||||||
|
{
|
||||||
|
Action = 20;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*Sequence == L'H')
|
||||||
|
{
|
||||||
|
Action = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*Sequence != L';') return 0;
|
||||||
|
|
||||||
|
Sequence++;
|
||||||
|
|
||||||
|
if ((*Sequence == L'H') || (*Sequence == L'f'))
|
||||||
|
{
|
||||||
|
Action = 18;
|
||||||
|
}
|
||||||
|
else if (*Sequence == L'r')
|
||||||
|
{
|
||||||
|
Action = 19;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!VTUTF8ChannelScanForNumber(Sequence, &Number3)) return 0;
|
||||||
|
|
||||||
|
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
||||||
|
|
||||||
|
if (*Sequence == L'm')
|
||||||
|
{
|
||||||
|
Action = 23;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = Sequence - String + 1;
|
||||||
|
|
||||||
|
ProcessString:
|
||||||
|
Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer;
|
||||||
|
VTUTF8ChannelAssertCursor(Channel);
|
||||||
|
switch (Action)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (Channel->CursorRow < Number)
|
||||||
|
{
|
||||||
|
Channel->CursorRow = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Channel->CursorRow -= Number;
|
||||||
|
}
|
||||||
|
VTUTF8ChannelAssertCursor(Channel);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (Channel->CursorRow >= SAC_VTUTF8_ROW_HEIGHT)
|
||||||
|
{
|
||||||
|
Channel->CursorRow = SAC_VTUTF8_ROW_HEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Channel->CursorRow += Number;
|
||||||
|
}
|
||||||
|
VTUTF8ChannelAssertCursor(Channel);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (Channel->CursorCol < Number)
|
||||||
|
{
|
||||||
|
Channel->CursorCol = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Channel->CursorCol -= Number;
|
||||||
|
}
|
||||||
|
VTUTF8ChannelAssertCursor(Channel);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (Channel->CursorCol >= SAC_VTUTF8_COL_WIDTH)
|
||||||
|
{
|
||||||
|
Channel->CursorCol = SAC_VTUTF8_COL_WIDTH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Channel->CursorCol += Number;
|
||||||
|
}
|
||||||
|
VTUTF8ChannelAssertCursor(Channel);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
Channel->CursorVisible = 0;
|
||||||
|
Channel->CursorX = 40;
|
||||||
|
Channel->CursorY = 37;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
Channel->CursorVisible |= 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
Channel->CursorVisible &= ~1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
Channel->CursorVisible |= 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
Channel->CursorVisible &= ~2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
Channel->CursorVisible |= 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
Channel->CursorVisible &= ~4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
for (i = Channel->CursorCol; i < SAC_VTUTF8_COL_WIDTH; i++)
|
||||||
|
{
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorVisible = Channel->CursorVisible;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorX = Channel->CursorY;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorY = Channel->CursorX;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorValue = ' ';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
for (i = 0; i < (Channel->CursorCol + 1); i++)
|
||||||
|
{
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorVisible = Channel->CursorVisible;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorX = Channel->CursorY;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorY = Channel->CursorX;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorValue = ' ';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
for (i = 0; i < SAC_VTUTF8_COL_WIDTH; i++)
|
||||||
|
{
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorVisible = Channel->CursorVisible;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorX = Channel->CursorY;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorY = Channel->CursorX;
|
||||||
|
Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) +
|
||||||
|
(i * SAC_VTUTF8_ROW_HEIGHT)].CursorValue = ' ';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 15:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 17:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 18:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 19:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 20:
|
||||||
|
Channel->CursorY = Number;
|
||||||
|
Channel->CursorX = Number2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 21:
|
||||||
|
Channel->CursorX = Number;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 22:
|
||||||
|
Channel->CursorY = Number;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 23:
|
||||||
|
Channel->CursorVisible = Number;
|
||||||
|
Channel->CursorY = Number2;
|
||||||
|
Channel->CursorX = Number3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
VTUTF8ChannelOInit(IN PSAC_CHANNEL Channel)
|
VTUTF8ChannelOInit(IN PSAC_CHANNEL Channel)
|
||||||
|
@ -104,54 +493,10 @@ VTUTF8ChannelDestroy(IN PSAC_CHANNEL Channel)
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
VTUTF8ChannelORead(
|
VTUTF8ChannelORead(IN PSAC_CHANNEL Channel,
|
||||||
IN PSAC_CHANNEL Channel,
|
|
||||||
IN PCHAR Buffer,
|
IN PCHAR Buffer,
|
||||||
IN ULONG BufferSize,
|
IN ULONG BufferSize,
|
||||||
OUT PULONG ByteCount
|
OUT PULONG ByteCount)
|
||||||
)
|
|
||||||
{
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
VTUTF8ChannelScanForNumber(
|
|
||||||
IN PWCHAR String,
|
|
||||||
OUT PULONG Number
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
VTUTF8ChannelAnsiDispatch(
|
|
||||||
IN NTSTATUS Status,
|
|
||||||
IN ULONG AnsiCode,
|
|
||||||
IN PWCHAR Data,
|
|
||||||
IN ULONG Length
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
VTUTF8ChannelProcessAttributes(
|
|
||||||
IN PSAC_CHANNEL Channel,
|
|
||||||
IN UCHAR Attribute
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
VTUTF8ChannelConsumeEscapeSequence(
|
|
||||||
IN PSAC_CHANNEL Channel,
|
|
||||||
IN PWCHAR String
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +525,88 @@ VTUTF8ChannelOEcho(IN PSAC_CHANNEL Channel,
|
||||||
IN PCHAR String,
|
IN PCHAR String,
|
||||||
IN ULONG Size)
|
IN ULONG Size)
|
||||||
{
|
{
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PWSTR pwch;
|
||||||
|
ULONG i, k, TranslatedCount, UTF8TranslationSize;
|
||||||
|
BOOLEAN Result;
|
||||||
|
CHECK_PARAMETER1(Channel);
|
||||||
|
CHECK_PARAMETER2(String);
|
||||||
|
|
||||||
|
/* Return success if there's nothing to echo */
|
||||||
|
if (!(Size / sizeof(WCHAR))) return Status;
|
||||||
|
|
||||||
|
/* Start with the input string*/
|
||||||
|
pwch = (PWCHAR)String;
|
||||||
|
|
||||||
|
/* First, figure out how much is outside of the block length alignment */
|
||||||
|
k = (Size / sizeof(WCHAR)) % MAX_UTF8_ENCODE_BLOCK_LENGTH;
|
||||||
|
if (k)
|
||||||
|
{
|
||||||
|
/* Translate the misaligned portion */
|
||||||
|
Result = SacTranslateUnicodeToUtf8(pwch,
|
||||||
|
k,
|
||||||
|
Utf8ConversionBuffer,
|
||||||
|
Utf8ConversionBufferSize,
|
||||||
|
&UTF8TranslationSize,
|
||||||
|
&TranslatedCount);
|
||||||
|
ASSERT(k == TranslatedCount);
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
/* If we couldn't translate, write failure to break out below */
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Write the misaligned portion into the buffer */
|
||||||
|
Status = ConMgrWriteData(Channel,
|
||||||
|
Utf8ConversionBuffer,
|
||||||
|
UTF8TranslationSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If translation or write failed, bail out */
|
||||||
|
if (!NT_SUCCESS(Status)) goto Return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Push the string to its new location (this could be a noop if aligned) */
|
||||||
|
pwch += k;
|
||||||
|
|
||||||
|
/* Now figure out how many aligned blocks we have, and loop each one */
|
||||||
|
k = (Size / sizeof(WCHAR)) / MAX_UTF8_ENCODE_BLOCK_LENGTH;
|
||||||
|
for (i = 0; i < k; i++)
|
||||||
|
{
|
||||||
|
/* Translate the aligned block */
|
||||||
|
Result = SacTranslateUnicodeToUtf8(pwch,
|
||||||
|
MAX_UTF8_ENCODE_BLOCK_LENGTH,
|
||||||
|
Utf8ConversionBuffer,
|
||||||
|
Utf8ConversionBufferSize,
|
||||||
|
&UTF8TranslationSize,
|
||||||
|
&TranslatedCount);
|
||||||
|
ASSERT(MAX_UTF8_ENCODE_BLOCK_LENGTH == TranslatedCount);
|
||||||
|
ASSERT(UTF8TranslationSize > 0);
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
/* Set failure here, we'll break out below */
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Move the string location to the next aligned block */
|
||||||
|
pwch += MAX_UTF8_ENCODE_BLOCK_LENGTH;
|
||||||
|
|
||||||
|
/* Write the aligned block into the buffer */
|
||||||
|
Status = ConMgrWriteData(Channel,
|
||||||
|
Utf8ConversionBuffer,
|
||||||
|
UTF8TranslationSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If translation or write failed, bail out */
|
||||||
|
if (!NT_SUCCESS(Status)) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Return:
|
||||||
|
ASSERT(pwch == (PWSTR)(String + Size));
|
||||||
|
if (NT_SUCCESS(Status)) Status = ConMgrFlushData(Channel);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
Loading…
Reference in a new issue