You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
788 lines
19 KiB
788 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
nlsboot.c
|
|
|
|
Abstract:
|
|
|
|
This module contains NLS routines for use by the OS Loader. Before
|
|
the NLS tables are loaded, they convert between ANSI and Unicode by
|
|
zero-extending.
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 11-Nov-1992
|
|
|
|
Revision History:
|
|
|
|
John Vert (jvert) 11-Nov-1992
|
|
created - mostly copied from old RTL routines
|
|
|
|
--*/
|
|
#include "bldr.h"
|
|
|
|
//
|
|
// Hack-o-rama string routines to use before tables are loaded
|
|
//
|
|
|
|
#define upcase(C) (WCHAR )(((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C)))
|
|
|
|
|
|
NTSTATUS
|
|
RtlAnsiStringToUnicodeString(
|
|
OUT PUNICODE_STRING DestinationString,
|
|
IN PCANSI_STRING SourceString,
|
|
IN BOOLEAN AllocateDestinationString
|
|
)
|
|
|
|
{
|
|
ULONG UnicodeLength;
|
|
ULONG Index;
|
|
|
|
UnicodeLength = (SourceString->Length << 1) + sizeof(UNICODE_NULL);
|
|
|
|
if ( UnicodeLength > MAXUSHORT ) {
|
|
return STATUS_INVALID_PARAMETER_2;
|
|
}
|
|
|
|
DestinationString->Length = (USHORT)(UnicodeLength - sizeof(UNICODE_NULL));
|
|
if ( AllocateDestinationString ) {
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
else {
|
|
if ( DestinationString->Length >= DestinationString->MaximumLength ) {
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
|
|
Index = 0;
|
|
while(Index < SourceString->Length ) {
|
|
DestinationString->Buffer[Index] = (WCHAR)SourceString->Buffer[Index];
|
|
Index++;
|
|
}
|
|
DestinationString->Buffer[Index] = UNICODE_NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
RtlUnicodeStringToAnsiString(
|
|
OUT PANSI_STRING DestinationString,
|
|
IN PCUNICODE_STRING SourceString,
|
|
IN BOOLEAN AllocateDestinationString
|
|
)
|
|
|
|
{
|
|
ULONG AnsiLength;
|
|
ULONG Index;
|
|
|
|
AnsiLength = SourceString->Length + 1;
|
|
|
|
if ( AnsiLength > MAXUSHORT ) {
|
|
return STATUS_INVALID_PARAMETER_2;
|
|
}
|
|
|
|
DestinationString->Length = SourceString->Length >> 1;
|
|
if ( AllocateDestinationString ) {
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
else {
|
|
if ( DestinationString->Length >= DestinationString->MaximumLength ) {
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
|
|
Index = 0;
|
|
while(Index < SourceString->Length ) {
|
|
DestinationString->Buffer[Index] = (CHAR)SourceString->Buffer[Index];
|
|
Index++;
|
|
}
|
|
DestinationString->Buffer[Index] = '\0';
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
LONG
|
|
RtlCompareUnicodeString(
|
|
IN PCUNICODE_STRING String1,
|
|
IN PCUNICODE_STRING String2,
|
|
IN BOOLEAN CaseInSensitive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The RtlCompareUnicodeString function compares two counted strings. The
|
|
return value indicates if the strings are equal or String1 is less than
|
|
String2 or String1 is greater than String2.
|
|
|
|
The CaseInSensitive parameter specifies if case is to be ignored when
|
|
doing the comparison.
|
|
|
|
Arguments:
|
|
|
|
String1 - Pointer to the first string.
|
|
|
|
String2 - Pointer to the second string.
|
|
|
|
CaseInsensitive - TRUE if case should be ignored when doing the
|
|
comparison.
|
|
|
|
Return Value:
|
|
|
|
Signed value that gives the results of the comparison:
|
|
|
|
Zero - String1 equals String2
|
|
|
|
< Zero - String1 less than String2
|
|
|
|
> Zero - String1 greater than String2
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UNALIGNED WCHAR *s1, *s2;
|
|
USHORT n1, n2;
|
|
WCHAR c1, c2;
|
|
LONG cDiff;
|
|
|
|
s1 = String1->Buffer;
|
|
s2 = String2->Buffer;
|
|
n1 = (USHORT )(String1->Length / sizeof(WCHAR));
|
|
n2 = (USHORT )(String2->Length / sizeof(WCHAR));
|
|
while (n1 && n2) {
|
|
c1 = *s1++;
|
|
c2 = *s2++;
|
|
|
|
if (CaseInSensitive) {
|
|
//
|
|
// Note that this needs to reference the translation table !
|
|
//
|
|
c1 = upcase(c1);
|
|
c2 = upcase(c2);
|
|
}
|
|
|
|
if ((cDiff = ((LONG)c1 - (LONG)c2)) != 0) {
|
|
return( cDiff );
|
|
}
|
|
|
|
n1--;
|
|
n2--;
|
|
}
|
|
|
|
return( n1 - n2 );
|
|
}
|
|
|
|
BOOLEAN
|
|
RtlEqualUnicodeString(
|
|
IN const UNICODE_STRING *String1,
|
|
IN const UNICODE_STRING *String2,
|
|
IN BOOLEAN CaseInSensitive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The RtlEqualUnicodeString function compares two counted unicode strings for
|
|
equality.
|
|
|
|
The CaseInSensitive parameter specifies if case is to be ignored when
|
|
doing the comparison.
|
|
|
|
Arguments:
|
|
|
|
String1 - Pointer to the first string.
|
|
|
|
String2 - Pointer to the second string.
|
|
|
|
CaseInsensitive - TRUE if case should be ignored when doing the
|
|
comparison.
|
|
|
|
Return Value:
|
|
|
|
Boolean value that is TRUE if String1 equals String2 and FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNALIGNED WCHAR *s1, *s2;
|
|
USHORT n1, n2;
|
|
WCHAR c1, c2;
|
|
|
|
s1 = String1->Buffer;
|
|
s2 = String2->Buffer;
|
|
n1 = (USHORT )(String1->Length / sizeof(WCHAR));
|
|
n2 = (USHORT )(String2->Length / sizeof(WCHAR));
|
|
|
|
if ( n1 != n2 ) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (CaseInSensitive) {
|
|
|
|
while ( n1 ) {
|
|
|
|
if ( *s1++ != *s2++ ) {
|
|
c1 = upcase(*(s1-1));
|
|
c2 = upcase(*(s2-1));
|
|
if (c1 != c2) {
|
|
return( FALSE );
|
|
}
|
|
}
|
|
n1--;
|
|
}
|
|
}
|
|
else {
|
|
|
|
while ( n1 ) {
|
|
|
|
if (*s1++ != *s2++) {
|
|
return( FALSE );
|
|
}
|
|
|
|
n1--;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
RtlInitString(
|
|
OUT PSTRING DestinationString,
|
|
IN PCSZ SourceString OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The RtlInitString function initializes an NT counted string.
|
|
The DestinationString is initialized to point to the SourceString
|
|
and the Length and MaximumLength fields of DestinationString are
|
|
initialized to the length of the SourceString, which is zero if
|
|
SourceString is not specified.
|
|
|
|
Arguments:
|
|
|
|
DestinationString - Pointer to the counted string to initialize
|
|
|
|
SourceString - Optional pointer to a null terminated string that
|
|
the counted string is to point to.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DestinationString->Length = 0;
|
|
DestinationString->Buffer = (PCHAR)SourceString;
|
|
if (ARGUMENT_PRESENT( SourceString )) {
|
|
while (*SourceString++) {
|
|
DestinationString->Length++;
|
|
}
|
|
|
|
DestinationString->MaximumLength = (SHORT)(DestinationString->Length+1);
|
|
}
|
|
else {
|
|
DestinationString->MaximumLength = 0;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
RtlInitUnicodeString(
|
|
OUT PUNICODE_STRING DestinationString,
|
|
IN PCWSTR SourceString OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The RtlInitUnicodeString function initializes an NT counted
|
|
unicode string. The DestinationString is initialized to point to
|
|
the SourceString and the Length and MaximumLength fields of
|
|
DestinationString are initialized to the length of the SourceString,
|
|
which is zero if SourceString is not specified.
|
|
|
|
Arguments:
|
|
|
|
DestinationString - Pointer to the counted string to initialize
|
|
|
|
SourceString - Optional pointer to a null terminated unicode string that
|
|
the counted string is to point to.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
USHORT Length = 0;
|
|
DestinationString->Length = 0;
|
|
DestinationString->Buffer = (PWSTR)SourceString;
|
|
if (ARGUMENT_PRESENT( SourceString )) {
|
|
while (*SourceString++) {
|
|
Length += sizeof(*SourceString);
|
|
}
|
|
|
|
DestinationString->Length = Length;
|
|
|
|
DestinationString->MaximumLength = Length+(USHORT)sizeof(UNICODE_NULL);
|
|
}
|
|
else {
|
|
DestinationString->MaximumLength = 0;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
RtlInitAnsiString(
|
|
OUT PANSI_STRING DestinationString,
|
|
IN PCSTR SourceString OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The RtlInitAnsiString function initializes an NT counted
|
|
ANSI string. The DestinationString is initialized to point to
|
|
the SourceString and the Length and MaximumLength fields of
|
|
DestinationString are initialized to the length of the SourceString,
|
|
which is zero if SourceString is not specified.
|
|
|
|
Arguments:
|
|
|
|
DestinationString - Pointer to the counted string to initialize
|
|
|
|
SourceString - Optional pointer to a null terminated ANSI string that
|
|
the counted string is to point to.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
USHORT Length = 0;
|
|
DestinationString->Length = 0;
|
|
DestinationString->Buffer = (PSTR)SourceString;
|
|
if (ARGUMENT_PRESENT( SourceString )) {
|
|
while (*SourceString++) {
|
|
Length += sizeof(*SourceString);
|
|
}
|
|
|
|
DestinationString->Length = Length;
|
|
|
|
DestinationString->MaximumLength = Length+1;
|
|
}
|
|
else {
|
|
DestinationString->MaximumLength = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
RtlAppendUnicodeStringToString (
|
|
IN OUT PUNICODE_STRING Destination,
|
|
IN PCUNICODE_STRING Source
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will concatinate two PSTRINGs together. It will copy
|
|
bytes from the source up to the MaximumLength of the destination.
|
|
|
|
Arguments:
|
|
|
|
IN PSTRING Destination, - Supplies the destination string
|
|
IN PSTRING Source - Supplies the source for the string copy
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The source string was successfully appended to the
|
|
destination counted string.
|
|
|
|
STATUS_BUFFER_TOO_SMALL - The destination string length was not big
|
|
enough to allow the source string to be appended. The Destination
|
|
string length is not updated.
|
|
|
|
--*/
|
|
|
|
{
|
|
USHORT n = Source->Length;
|
|
UNALIGNED WCHAR *dst;
|
|
|
|
if (n) {
|
|
if ((n + Destination->Length) > Destination->MaximumLength) {
|
|
return( STATUS_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
dst = &Destination->Buffer[ (Destination->Length / sizeof( WCHAR )) ];
|
|
RtlMoveMemory( dst, Source->Buffer, n );
|
|
|
|
Destination->Length = Destination->Length + n;
|
|
|
|
if (Destination->Length < Destination->MaximumLength) {
|
|
dst[ n / sizeof( WCHAR ) ] = UNICODE_NULL;
|
|
}
|
|
}
|
|
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
RtlAppendUnicodeToString (
|
|
IN PUNICODE_STRING Destination,
|
|
IN PCWSTR Source OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine appends the supplied UNICODE string to an existing
|
|
PUNICODE_STRING.
|
|
|
|
It will copy bytes from the Source PSZ to the destination PSTRING up to
|
|
the destinations PUNICODE_STRING->MaximumLength field.
|
|
|
|
Arguments:
|
|
|
|
IN PUNICODE_STRING Destination, - Supplies a pointer to the destination
|
|
string
|
|
IN PWSTR Source - Supplies the string to append to the destination
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The source string was successfully appended to the
|
|
destination counted string.
|
|
|
|
STATUS_BUFFER_TOO_SMALL - The destination string length was not big
|
|
enough to allow the source string to be appended. The Destination
|
|
string length is not updated.
|
|
|
|
--*/
|
|
|
|
{
|
|
USHORT n;
|
|
UNALIGNED WCHAR *dst;
|
|
|
|
if (ARGUMENT_PRESENT( Source )) {
|
|
UNICODE_STRING UniSource;
|
|
|
|
RtlInitUnicodeString(&UniSource, Source);
|
|
|
|
n = UniSource.Length;
|
|
|
|
if ((n + Destination->Length) > Destination->MaximumLength) {
|
|
return( STATUS_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
dst = &Destination->Buffer[ (Destination->Length / sizeof( WCHAR )) ];
|
|
RtlMoveMemory( dst, Source, n );
|
|
|
|
Destination->Length = Destination->Length + n;
|
|
|
|
if (Destination->Length < Destination->MaximumLength) {
|
|
dst[ n / sizeof( WCHAR ) ] = UNICODE_NULL;
|
|
}
|
|
}
|
|
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
|
|
WCHAR
|
|
RtlUpcaseUnicodeChar(
|
|
IN WCHAR SourceCharacter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates the specified unicode character to its
|
|
equivalent upcased unicode chararacter. The purpose for this routine
|
|
is to allow for character by character upcase translation. The
|
|
translation is done with respect to the current system locale
|
|
information.
|
|
|
|
|
|
Arguments:
|
|
|
|
SourceCharacter - Supplies the unicode character to be upcased.
|
|
|
|
Return Value:
|
|
|
|
Returns the upcased unicode equivalent of the specified input character.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return (upcase(SourceCharacter));
|
|
}
|
|
|
|
WCHAR
|
|
RtlAnsiCharToUnicodeChar(
|
|
IN OUT PUCHAR *SourceCharacter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates the specified ansi character to unicode and
|
|
returns the unicode value. The purpose for this routine is to allow
|
|
for character by character ansi to unicode translation. The
|
|
translation is done with respect to the current system locale
|
|
information.
|
|
|
|
|
|
Arguments:
|
|
|
|
SourceCharacter - Supplies a pointer to an ansi character pointer.
|
|
Through two levels of indirection, this supplies an ansi
|
|
character that is to be translated to unicode. After
|
|
translation, the ansi character pointer is modified to point to
|
|
the next character to be converted. This is done to allow for
|
|
dbcs ansi characters.
|
|
|
|
Return Value:
|
|
|
|
Returns the unicode equivalent of the specified ansi character.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR UnicodeCharacter;
|
|
|
|
|
|
UnicodeCharacter = (WCHAR)**SourceCharacter;
|
|
(*SourceCharacter)++;
|
|
return(UnicodeCharacter);
|
|
}
|
|
|
|
NTSTATUS
|
|
RtlUpcaseUnicodeToMultiByteN(
|
|
OUT PCH MultiByteString,
|
|
IN ULONG MaxBytesInMultiByteString,
|
|
OUT PULONG BytesInMultiByteString OPTIONAL,
|
|
IN PWCH UnicodeString,
|
|
IN ULONG BytesInUnicodeString)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions upper cases the specified unicode source string and
|
|
converts it into an ansi string. The translation is done with respect
|
|
to the ANSI Code Page (ACP) loaded at boot time.
|
|
|
|
Arguments:
|
|
|
|
MultiByteString - Returns an ansi string that is equivalent to the
|
|
upper case of the unicode source string. If the translation can
|
|
not be done, an error is returned.
|
|
|
|
MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
|
|
written to MultiByteString. If this causes MultiByteString to be a
|
|
truncated equivalent of UnicodeString, no error condition results.
|
|
|
|
BytesInMultiByteString - Returns the number of bytes in the returned
|
|
ansi string pointed to by MultiByteString.
|
|
|
|
UnicodeString - Supplies the unicode source string that is to be
|
|
converted to ansi.
|
|
|
|
BytesInUnicodeString - The number of bytes in the the string pointed to by
|
|
UnicodeString.
|
|
|
|
Return Value:
|
|
|
|
SUCCESS - The conversion was successful
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG LoopCount;
|
|
ULONG CharsInUnicodeString;
|
|
ULONG i;
|
|
|
|
//
|
|
// Convert Unicode byte count to character count. Byte count of
|
|
// multibyte string is equivalent to character count.
|
|
//
|
|
CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
|
|
|
|
LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
|
|
CharsInUnicodeString : MaxBytesInMultiByteString;
|
|
|
|
if (ARGUMENT_PRESENT(BytesInMultiByteString))
|
|
*BytesInMultiByteString = LoopCount;
|
|
|
|
|
|
for (i=0;i<LoopCount;i++) {
|
|
|
|
MultiByteString[i] = (UCHAR)RtlUpcaseUnicodeChar((UCHAR)(UnicodeString[i]));
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
RtlMultiByteToUnicodeN(
|
|
OUT PWCH UnicodeString,
|
|
IN ULONG MaxBytesInUnicodeString,
|
|
OUT PULONG BytesInUnicodeString OPTIONAL,
|
|
IN PCSTR MultiByteString,
|
|
IN ULONG BytesInMultiByteString)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions converts the specified ansi source string into a
|
|
Unicode string. The translation is done with respect to the
|
|
ANSI Code Page (ACP) installed at boot time. Single byte characters
|
|
in the range 0x00 - 0x7f are simply zero extended as a performance
|
|
enhancement. In some far eastern code pages 0x5c is defined as the
|
|
Yen sign. For system translation we always want to consider 0x5c
|
|
to be the backslash character. We get this for free by zero extending.
|
|
|
|
NOTE: This routine only supports precomposed Unicode characters.
|
|
|
|
Arguments:
|
|
|
|
UnicodeString - Returns a unicode string that is equivalent to
|
|
the ansi source string.
|
|
|
|
MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
|
|
written to UnicodeString. If this causes UnicodeString to be a
|
|
truncated equivalent of MultiByteString, no error condition results.
|
|
|
|
BytesInUnicodeString - Returns the number of bytes in the returned
|
|
unicode string pointed to by UnicodeString.
|
|
|
|
MultiByteString - Supplies the ansi source string that is to be
|
|
converted to unicode.
|
|
|
|
BytesInMultiByteString - The number of bytes in the string pointed to
|
|
by MultiByteString.
|
|
|
|
Return Value:
|
|
|
|
SUCCESS - The conversion was successful.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG LoopCount;
|
|
ULONG MaxCharsInUnicodeString;
|
|
ULONG i;
|
|
|
|
MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
|
|
|
|
LoopCount = (MaxCharsInUnicodeString < BytesInMultiByteString) ?
|
|
MaxCharsInUnicodeString : BytesInMultiByteString;
|
|
|
|
if (ARGUMENT_PRESENT(BytesInUnicodeString))
|
|
*BytesInUnicodeString = LoopCount * sizeof(WCHAR);
|
|
|
|
for (i=0;i<LoopCount;i++) {
|
|
UnicodeString[i] = (WCHAR)((UCHAR)(MultiByteString[i]));
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
RtlUnicodeToMultiByteN(
|
|
OUT PCH MultiByteString,
|
|
IN ULONG MaxBytesInMultiByteString,
|
|
OUT PULONG BytesInMultiByteString OPTIONAL,
|
|
IN PWCH UnicodeString,
|
|
IN ULONG BytesInUnicodeString)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions converts the specified unicode source string into an
|
|
ansi string. The translation is done with respect to the
|
|
ANSI Code Page (ACP) loaded at boot time.
|
|
|
|
Arguments:
|
|
|
|
MultiByteString - Returns an ansi string that is equivalent to the
|
|
unicode source string. If the translation can not be done,
|
|
an error is returned.
|
|
|
|
MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
|
|
written to MultiByteString. If this causes MultiByteString to be a
|
|
truncated equivalent of UnicodeString, no error condition results.
|
|
|
|
BytesInMultiByteString - Returns the number of bytes in the returned
|
|
ansi string pointed to by MultiByteString.
|
|
|
|
UnicodeString - Supplies the unicode source string that is to be
|
|
converted to ansi.
|
|
|
|
BytesInUnicodeString - The number of bytes in the the string pointed to by
|
|
UnicodeString.
|
|
|
|
Return Value:
|
|
|
|
SUCCESS - The conversion was successful
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG LoopCount;
|
|
ULONG CharsInUnicodeString;
|
|
ULONG i;
|
|
|
|
//
|
|
// Convert Unicode byte count to character count. Byte count of
|
|
// multibyte string is equivalent to character count.
|
|
//
|
|
CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
|
|
|
|
LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
|
|
CharsInUnicodeString : MaxBytesInMultiByteString;
|
|
|
|
if (ARGUMENT_PRESENT(BytesInMultiByteString))
|
|
*BytesInMultiByteString = LoopCount;
|
|
|
|
|
|
for (i=0;i<LoopCount;i++) {
|
|
MultiByteString[i] = (CHAR)(UnicodeString[i]);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|