#define NDEBUG
#include <debug.h>
+#include <wine/unicode.h>
+
/* GLOBALS *******************************************************************/
extern BOOLEAN NlsMbCodePageTag;
extern BOOLEAN NlsMbOemCodePageTag;
extern PUSHORT NlsLeadByteInfo;
+extern USHORT NlsOemDefaultChar;
+extern USHORT NlsUnicodeDefaultChar;
+
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
WCHAR
-STDCALL
+NTAPI
RtlAnsiCharToUnicodeChar(IN PUCHAR *AnsiChar)
{
ULONG Size;
NTSTATUS Status;
- WCHAR UnicodeChar = 0x20;
+ WCHAR UnicodeChar = L' ';
Size = (NlsLeadByteInfo[**AnsiChar] == 0) ? 1 : 2;
Status = RtlMultiByteToUnicodeN(&UnicodeChar,
sizeof(WCHAR),
NULL,
- *AnsiChar,
+ (PCHAR)*AnsiChar,
Size);
if (!NT_SUCCESS(Status))
{
- UnicodeChar = 0x20;
+ UnicodeChar = L' ';
}
*AnsiChar += Size;
* If the dest buffer is too small a partial copy is NOT performed!
*/
NTSTATUS
-STDCALL
+NTAPI
RtlAnsiStringToUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PANSI_STRING AnsiSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
Length = RtlAnsiStringToUnicodeSize(AnsiSource);
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
UniDest->Length = (USHORT)Length - sizeof(WCHAR);
- if (AllocateDestinationString == TRUE)
+ if (AllocateDestinationString)
{
UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
UniDest->MaximumLength = Length;
if (!UniDest->Buffer) return STATUS_NO_MEMORY;
}
- else if (Length >= UniDest->MaximumLength)
+ else if (UniDest->Length >= UniDest->MaximumLength)
{
- return STATUS_BUFFER_TOO_SMALL;
+ return STATUS_BUFFER_OVERFLOW;
}
Status = RtlMultiByteToUnicodeN(UniDest->Buffer,
AnsiSource->Buffer,
AnsiSource->Length);
- if (!NT_SUCCESS(Status) && AllocateDestinationString)
+ if (!NT_SUCCESS(Status))
{
- RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
+ if (AllocateDestinationString)
+ {
+ RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
+ UniDest->Buffer = NULL;
+ }
return Status;
}
* The calculated size in bytes including nullterm.
*/
ULONG
-STDCALL
+NTAPI
RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString)
{
ULONG Size;
* Dest is never nullterminated.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlAppendStringToString(IN PSTRING Destination,
IN PSTRING Source)
{
* When dest fits exactly in MaximumLength characters the nullterm is ommitted.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlAppendUnicodeStringToString(
IN OUT PUNICODE_STRING Destination,
IN PCUNICODE_STRING Source)
* This function does not read garbage behind '\0' as the native version does.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlCharToInteger(
PCSZ str, /* [I] '\0' terminated single-byte string containing a number */
ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
char bMinus = 0;
while (*str != '\0' && *str <= ' ') {
- str++;
+ str++;
} /* while */
if (*str == '+') {
- str++;
+ str++;
} else if (*str == '-') {
- bMinus = 1;
- str++;
+ bMinus = 1;
+ str++;
} /* if */
if (base == 0) {
- base = 10;
- if (str[0] == '0') {
- if (str[1] == 'b') {
- str += 2;
- base = 2;
- } else if (str[1] == 'o') {
- str += 2;
- base = 8;
- } else if (str[1] == 'x') {
- str += 2;
- base = 16;
- } /* if */
- } /* if */
+ base = 10;
+ if (str[0] == '0') {
+ if (str[1] == 'b') {
+ str += 2;
+ base = 2;
+ } else if (str[1] == 'o') {
+ str += 2;
+ base = 8;
+ } else if (str[1] == 'x') {
+ str += 2;
+ base = 16;
+ } /* if */
+ } /* if */
} else if (base != 2 && base != 8 && base != 10 && base != 16) {
- return STATUS_INVALID_PARAMETER;
+ return STATUS_INVALID_PARAMETER;
} /* if */
if (value == NULL) {
- return STATUS_ACCESS_VIOLATION;
+ return STATUS_ACCESS_VIOLATION;
} /* if */
while (*str != '\0') {
- chCurrent = *str;
- if (chCurrent >= '0' && chCurrent <= '9') {
- digit = chCurrent - '0';
- } else if (chCurrent >= 'A' && chCurrent <= 'Z') {
- digit = chCurrent - 'A' + 10;
- } else if (chCurrent >= 'a' && chCurrent <= 'z') {
- digit = chCurrent - 'a' + 10;
- } else {
- digit = -1;
- } /* if */
- if (digit < 0 || digit >= (int)base) {
- *value = bMinus ? -RunningTotal : RunningTotal;
- return STATUS_SUCCESS;
- } /* if */
-
- RunningTotal = RunningTotal * base + digit;
- str++;
+ chCurrent = *str;
+ if (chCurrent >= '0' && chCurrent <= '9') {
+ digit = chCurrent - '0';
+ } else if (chCurrent >= 'A' && chCurrent <= 'Z') {
+ digit = chCurrent - 'A' + 10;
+ } else if (chCurrent >= 'a' && chCurrent <= 'z') {
+ digit = chCurrent - 'a' + 10;
+ } else {
+ digit = -1;
+ } /* if */
+ if (digit < 0 || digit >= (int)base) {
+ *value = bMinus ? -RunningTotal : RunningTotal;
+ return STATUS_SUCCESS;
+ } /* if */
+
+ RunningTotal = RunningTotal * base + digit;
+ str++;
} /* while */
*value = bMinus ? -RunningTotal : RunningTotal;
* @implemented
*/
LONG
-STDCALL
+NTAPI
RtlCompareString(
IN PSTRING s1,
IN PSTRING s2,
* TRUE if strings are equal.
*/
BOOLEAN
-STDCALL
+NTAPI
RtlEqualString(
IN PSTRING s1,
IN PSTRING s2,
* TRUE if strings are equal.
*/
BOOLEAN
-STDCALL
+NTAPI
RtlEqualUnicodeString(
IN CONST UNICODE_STRING *s1,
IN CONST UNICODE_STRING *s2,
* @implemented
*/
VOID
-STDCALL
+NTAPI
RtlFreeAnsiString(IN PANSI_STRING AnsiString)
{
+ PAGED_CODE_RTL();
+
if (AnsiString->Buffer)
{
RtlpFreeStringMemory(AnsiString->Buffer, TAG_ASTR);
* @implemented
*/
VOID
-STDCALL
+NTAPI
RtlFreeOemString(IN POEM_STRING OemString)
{
+ PAGED_CODE_RTL();
+
if (OemString->Buffer) RtlpFreeStringMemory(OemString->Buffer, TAG_OSTR);
}
* @implemented
*/
VOID
-STDCALL
+NTAPI
RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
{
+ PAGED_CODE_RTL();
+
if (UnicodeString->Buffer)
{
- RtlpFreeStringMemory(UnicodeString->Buffer, TAG_ASTR);
+ RtlpFreeStringMemory(UnicodeString->Buffer, TAG_USTR);
RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
}
}
+
+/*
+ * @implemented
+ *
+ * NOTES
+ * Check the oem-string to match the uincoded-string.
+ *
+ * Functions who convert unicode strings to oem strings will set a DefaultChar from
+ * the OemCodepage when the character are unknown. So check it against the unicode string
+ * and return false when the unicode string not contain an TransDefaultChar.
+ */
+BOOLEAN
+NTAPI
+RtlpDidUnicodeToOemWork(IN PCUNICODE_STRING UnicodeString,
+ IN POEM_STRING OemString)
+{
+ ULONG i = 0;
+
+ /* Go through all characters of a string */
+ while (i < OemString->Length)
+ {
+ /* Check if it got translated into '?', but source char
+ wasn't '?' equivalent */
+ if ((OemString->Buffer[i] != 0) &&
+ (OemString->Buffer[i] == NlsOemDefaultChar) &&
+ (UnicodeString->Buffer[i] != NlsUnicodeDefaultChar))
+ {
+ /* Yes, it means unmappable characters were found */
+ return FALSE;
+ }
+
+ /* Move to the next char */
+ i++;
+ }
+
+ /* All chars were translated successfuly */
+ return TRUE;
+}
+
/*
* @unimplemented
*/
BOOLEAN
-STDCALL
+NTAPI
RtlIsValidOemCharacter(IN PWCHAR Char)
{
UNIMPLEMENTED;
* If source is NULL the length of source is assumed to be 0.
*/
VOID
-STDCALL
+NTAPI
RtlInitAnsiString(IN OUT PANSI_STRING DestinationString,
IN PCSZ SourceString)
{
DestinationString->Buffer = (PCHAR)SourceString;
}
+NTSTATUS
+NTAPI
+RtlInitAnsiStringEx(IN OUT PANSI_STRING DestinationString,
+ IN PCSZ SourceString)
+{
+ ULONG DestSize;
+
+ if(SourceString)
+ {
+ DestSize = strlen(SourceString);
+ if (DestSize >= 0xFFFF) return STATUS_NAME_TOO_LONG;
+ DestinationString->Length = (USHORT)DestSize;
+ DestinationString->MaximumLength = (USHORT)DestSize + sizeof(CHAR);
+ }
+ else
+ {
+ DestinationString->Length = 0;
+ DestinationString->MaximumLength = 0;
+ }
+
+ DestinationString->Buffer = (PCHAR)SourceString;
+ return STATUS_SUCCESS;
+
+}
/*
* @implemented
*
* If source is NULL the length of source is assumed to be 0.
*/
VOID
-STDCALL
+NTAPI
RtlInitString(
IN OUT PSTRING DestinationString,
IN PCSZ SourceString)
* If source is NULL the length of source is assumed to be 0.
*/
VOID
-STDCALL
+NTAPI
RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString)
{
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString)
{
if(SourceString)
{
DestSize = wcslen(SourceString) * sizeof(WCHAR);
- if (DestSize > 0xFFFC) return STATUS_NAME_TOO_LONG;
+ if (DestSize >= 0xFFFC) return STATUS_NAME_TOO_LONG;
DestinationString->Length = (USHORT)DestSize;
DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
}
* Str is nullterminated when length allowes it.
* When str fits exactly in length characters the nullterm is ommitted.
*/
-NTSTATUS
-STDCALL
-RtlIntegerToChar(
- IN ULONG Value,
- IN ULONG Base,
- IN ULONG Length,
- IN OUT PCHAR String)
+NTSTATUS NTAPI RtlIntegerToChar(
+ ULONG value, /* [I] Value to be converted */
+ ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
+ ULONG length, /* [I] Length of the str buffer in bytes */
+ PCHAR str) /* [O] Destination for the converted value */
{
- ULONG Radix;
- CHAR temp[33];
- ULONG v = Value;
- ULONG i;
- PCHAR tp;
- PCHAR sp;
-
- Radix = Base;
- if (Radix == 0)
- Radix = 10;
-
- if ((Radix != 2) && (Radix != 8) &&
- (Radix != 10) && (Radix != 16))
- {
- return STATUS_INVALID_PARAMETER;
- }
+ CHAR buffer[33];
+ PCHAR pos;
+ CHAR digit;
+ ULONG len;
- tp = temp;
- while (v || tp == temp)
- {
- i = v % Radix;
- v = v / Radix;
- if (i < 10)
- *tp = i + '0';
- else
- *tp = i + 'a' - 10;
- tp++;
- }
-
- if ((ULONG)((ULONG_PTR)tp - (ULONG_PTR)temp) >= Length)
- {
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- sp = String;
- while (tp > temp)
- *sp++ = *--tp;
- *sp = 0;
+ if (base == 0) {
+ base = 10;
+ } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+ return STATUS_INVALID_PARAMETER;
+ } /* if */
- return STATUS_SUCCESS;
+ pos = &buffer[32];
+ *pos = '\0';
+
+ do {
+ pos--;
+ digit = value % base;
+ value = value / base;
+ if (digit < 10) {
+ *pos = '0' + digit;
+ } else {
+ *pos = 'A' + digit - 10;
+ } /* if */
+ } while (value != 0L);
+
+ len = &buffer[32] - pos;
+ if (len > length) {
+ return STATUS_BUFFER_OVERFLOW;
+ } else if (str == NULL) {
+ return STATUS_ACCESS_VIOLATION;
+ } else if (len == length) {
+ memcpy(str, pos, len);
+ } else {
+ memcpy(str, pos, len + 1);
+ } /* if */
+ return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
RtlIntegerToUnicode(
IN ULONG Value,
IN ULONG Base OPTIONAL,
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
RtlIntegerToUnicodeString(
IN ULONG Value,
IN ULONG Base OPTIONAL,
IN OUT PUNICODE_STRING String)
{
ANSI_STRING AnsiString;
- CHAR Buffer[16];
+ CHAR Buffer[33];
NTSTATUS Status;
Status = RtlIntegerToChar(Value, Base, sizeof(Buffer), Buffer);
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
RtlInt64ToUnicodeString (
IN ULONGLONG Value,
IN ULONG Base OPTIONAL,
{
LARGE_INTEGER LargeInt;
ANSI_STRING AnsiString;
- CHAR Buffer[32];
+ CHAR Buffer[65];
NTSTATUS Status;
LargeInt.QuadPart = Value;
* TRUE if String2 contains String1 as a prefix.
*/
BOOLEAN
-STDCALL
+NTAPI
RtlPrefixString(
PANSI_STRING String1,
PANSI_STRING String2,
* TRUE if String2 contains String1 as a prefix.
*/
BOOLEAN
-STDCALL
+NTAPI
RtlPrefixUnicodeString(
PCUNICODE_STRING String1,
PCUNICODE_STRING String2,
}
return FALSE;
}
-
-/**************************************************************************
- * RtlUnicodeStringToInteger (NTDLL.@)
+/*
* @implemented
- * Converts an unicode string into its integer equivalent.
- *
- * RETURNS
- * Success: STATUS_SUCCESS. value contains the converted number
- * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
- * STATUS_ACCESS_VIOLATION, if value is NULL.
- *
- * NOTES
- * For base 0 it uses 10 as base and the string should be in the format
- * "{whitespace} [+|-] [0[x|o|b]] {digits}".
- * For other bases the string should be in the format
- * "{whitespace} [+|-] {digits}".
- * No check is made for value overflow, only the lower 32 bits are assigned.
- * If str is NULL it crashes, as the native function does.
- *
- * Note that regardless of success or failure status, we should leave the
- * partial value in Value. An error is never returned based on the chars
- * in the string.
- *
- * DIFFERENCES
- * This function does not read garbage on string length 0 as the native
- * version does.
*/
NTSTATUS
-STDCALL
-RtlUnicodeStringToInteger(
- PCUNICODE_STRING str, /* [I] Unicode string to be converted */
+NTAPI
+RtlUnicodeStringToInteger(const UNICODE_STRING *str, /* [I] Unicode string to be converted */
ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
- PULONG value) /* [O] Destination for the converted value */
+ ULONG *value) /* [O] Destination for the converted value */
{
LPWSTR lpwstr = str->Buffer;
USHORT CharsRemaining = str->Length / sizeof(WCHAR);
WCHAR wchCurrent;
int digit;
- ULONG newbase = 0;
ULONG RunningTotal = 0;
char bMinus = 0;
- while (CharsRemaining >= 1 && *lpwstr <= L' ') {
- lpwstr++;
- CharsRemaining--;
+ while (CharsRemaining >= 1 && *lpwstr <= ' ') {
+ lpwstr++;
+ CharsRemaining--;
} /* while */
if (CharsRemaining >= 1) {
- if (*lpwstr == L'+') {
- lpwstr++;
- CharsRemaining--;
- } else if (*lpwstr == L'-') {
- bMinus = 1;
- lpwstr++;
- CharsRemaining--;
- } /* if */
+ if (*lpwstr == '+') {
+ lpwstr++;
+ CharsRemaining--;
+ } else if (*lpwstr == '-') {
+ bMinus = 1;
+ lpwstr++;
+ CharsRemaining--;
+ } /* if */
} /* if */
- if (CharsRemaining >= 2 && lpwstr[0] == L'0') {
- if (lpwstr[1] == L'b' || lpwstr[1] == L'B') {
- lpwstr += 2;
- CharsRemaining -= 2;
- newbase = 2;
- } else if (lpwstr[1] == L'o' || lpwstr[1] == L'O') {
- lpwstr += 2;
- CharsRemaining -= 2;
- newbase = 8;
- } else if (lpwstr[1] == L'x' || lpwstr[1] == L'X') {
- lpwstr += 2;
- CharsRemaining -= 2;
- newbase = 16;
- } /* if */
- }
- if (base == 0 && newbase == 0) {
- base = 10;
- } else if (base == 0 && newbase != 0) {
- base = newbase;
- } else if ((newbase != 0 && base != newbase) ||
- (base != 2 && base != 8 && base != 10 && base != 16)) {
- return STATUS_INVALID_PARAMETER;
-
+ if (base == 0) {
+ base = 10;
+ if (CharsRemaining >= 2 && lpwstr[0] == '0') {
+ if (lpwstr[1] == 'b') {
+ lpwstr += 2;
+ CharsRemaining -= 2;
+ base = 2;
+ } else if (lpwstr[1] == 'o') {
+ lpwstr += 2;
+ CharsRemaining -= 2;
+ base = 8;
+ } else if (lpwstr[1] == 'x') {
+ lpwstr += 2;
+ CharsRemaining -= 2;
+ base = 16;
+ } /* if */
+ } /* if */
+ } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+ return STATUS_INVALID_PARAMETER;
} /* if */
if (value == NULL) {
- return STATUS_ACCESS_VIOLATION;
+ return STATUS_ACCESS_VIOLATION;
} /* if */
while (CharsRemaining >= 1) {
- wchCurrent = *lpwstr;
- if (wchCurrent >= L'0' && wchCurrent <= L'9') {
- digit = wchCurrent - L'0';
- } else if (wchCurrent >= L'A' && wchCurrent <= L'Z') {
- digit = wchCurrent - L'A' + 10;
- } else if (wchCurrent >= L'a' && wchCurrent <= L'z') {
- digit = wchCurrent - L'a' + 10;
- } else {
- digit = -1;
- } /* if */
- if (digit < 0 || digit >= (int)base) {
- *value = bMinus ? -RunningTotal : RunningTotal;
- return STATUS_SUCCESS;
- } /* if */
-
- RunningTotal = RunningTotal * base + digit;
- lpwstr++;
- CharsRemaining--;
+ wchCurrent = *lpwstr;
+ if (wchCurrent >= '0' && wchCurrent <= '9') {
+ digit = wchCurrent - '0';
+ } else if (wchCurrent >= 'A' && wchCurrent <= 'Z') {
+ digit = wchCurrent - 'A' + 10;
+ } else if (wchCurrent >= 'a' && wchCurrent <= 'z') {
+ digit = wchCurrent - 'a' + 10;
+ } else {
+ digit = -1;
+ } /* if */
+ if (digit < 0 || digit >= base) {
+ *value = bMinus ? -RunningTotal : RunningTotal;
+ return STATUS_SUCCESS;
+ } /* if */
+
+ RunningTotal = RunningTotal * base + digit;
+ lpwstr++;
+ CharsRemaining--;
} /* while */
*value = bMinus ? -RunningTotal : RunningTotal;
* Bytes necessary for the conversion including nullterm.
*/
ULONG
-STDCALL
+NTAPI
RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString)
{
ULONG Size;
* It performs a partial copy if ansi is too small.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlUnicodeStringToAnsiString(
IN OUT PANSI_STRING AnsiDest,
IN PCUNICODE_STRING UniSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
Length = RtlUnicodeStringToAnsiSize(UniSource);
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
* Does NOT perform a partial copy if unicode is too small!
*/
NTSTATUS
-STDCALL
+NTAPI
RtlOemStringToUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PCOEM_STRING OemSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
Length = RtlOemStringToUnicodeSize(OemSource);
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
* This function always '\0' terminates the string returned.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlUnicodeStringToOemString(
IN OUT POEM_STRING OemDest,
IN PCUNICODE_STRING UniSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
Length = RtlUnicodeStringToOemSize(UniSource);
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
* RETURNS
* The length of the string if all tests were passed, 0 otherwise.
*/
-ULONG STDCALL
-RtlIsTextUnicode (PVOID Buffer,
- ULONG Length,
- ULONG *Flags)
+BOOLEAN
+NTAPI
+RtlIsTextUnicode( PVOID buf, INT len, INT *pf )
{
- PWSTR s = Buffer;
- ULONG in_flags = (ULONG)-1;
- ULONG out_flags = 0;
-
- if (Length == 0)
- goto done;
+ static const WCHAR std_control_chars[] = {'\r','\n','\t',' ',0x3000,0};
+ static const WCHAR byterev_control_chars[] = {0x0d00,0x0a00,0x0900,0x2000,0};
+ const WCHAR *s = buf;
+ int i;
+ unsigned int flags = MAXULONG, out_flags = 0;
- if (Flags != 0)
- in_flags = *Flags;
-
- /*
- * Apply various tests to the text string. According to the
- * docs, each test "passed" sets the corresponding flag in
- * the output flags. But some of the tests are mutually
- * exclusive, so I don't see how you could pass all tests ...
- */
-
- /* Check for an odd length ... pass if even. */
- if (!(Length & 1))
- out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
-
- /* Check for the BOM (byte order mark). */
- if (*s == 0xFEFF)
- out_flags |= IS_TEXT_UNICODE_SIGNATURE;
-
-#if 0
- /* Check for the reverse BOM (byte order mark). */
- if (*s == 0xFFFE)
- out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
-#endif
+ if (len < sizeof(WCHAR))
+ {
+ /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
+ if (pf) *pf = 0;
+ return FALSE;
+ }
+ if (pf)
+ flags = *pf;
+ /*
+ * Apply various tests to the text string. According to the
+ * docs, each test "passed" sets the corresponding flag in
+ * the output flags. But some of the tests are mutually
+ * exclusive, so I don't see how you could pass all tests ...
+ */
+
+ /* Check for an odd length ... pass if even. */
+ if (len & 1) out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
+
+ if (((char *)buf)[len - 1] == 0)
+ len--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
+
+ len /= sizeof(WCHAR);
+ /* Windows only checks the first 256 characters */
+ if (len > 256) len = 256;
+
+ /* Check for the special byte order unicode marks. */
+ if (*s == 0xFEFF) out_flags |= IS_TEXT_UNICODE_SIGNATURE;
+ if (*s == 0xFFFE) out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
+
+ /* apply some statistical analysis */
+ if (flags & IS_TEXT_UNICODE_STATISTICS)
+ {
+ int stats = 0;
+ /* FIXME: checks only for ASCII characters in the unicode stream */
+ for (i = 0; i < len; i++)
+ {
+ if (s[i] <= 255) stats++;
+ }
+ if (stats > len / 2)
+ out_flags |= IS_TEXT_UNICODE_STATISTICS;
+ }
- /* FIXME: Add more tests */
+ /* Check for unicode NULL chars */
+ if (flags & IS_TEXT_UNICODE_NULL_BYTES)
+ {
+ for (i = 0; i < len; i++)
+ {
+ if (!(s[i] & 0xff) || !(s[i] >> 8))
+ {
+ out_flags |= IS_TEXT_UNICODE_NULL_BYTES;
+ break;
+ }
+ }
+ }
- /*
- * Check whether the string passed all of the tests.
- */
- in_flags &= ITU_IMPLEMENTED_TESTS;
- if ((out_flags & in_flags) != in_flags)
- Length = 0;
+ if (flags & IS_TEXT_UNICODE_CONTROLS)
+ {
+ for (i = 0; i < len; i++)
+ {
+ if (strchrW(std_control_chars, s[i]))
+ {
+ out_flags |= IS_TEXT_UNICODE_CONTROLS;
+ break;
+ }
+ }
+ }
-done:
- if (Flags != 0)
- *Flags = out_flags;
+ if (flags & IS_TEXT_UNICODE_REVERSE_CONTROLS)
+ {
+ for (i = 0; i < len; i++)
+ {
+ if (strchrW(byterev_control_chars, s[i]))
+ {
+ out_flags |= IS_TEXT_UNICODE_REVERSE_CONTROLS;
+ break;
+ }
+ }
+ }
- return Length;
+ if (pf)
+ {
+ out_flags &= *pf;
+ *pf = out_flags;
+ }
+ /* check for flags that indicate it's definitely not valid Unicode */
+ if (out_flags & (IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK)) return FALSE;
+ /* now check for invalid ASCII, and assume Unicode if so */
+ if (out_flags & IS_TEXT_UNICODE_NOT_ASCII_MASK) return TRUE;
+ /* now check for Unicode flags */
+ if (out_flags & IS_TEXT_UNICODE_UNICODE_MASK) return TRUE;
+ /* no flags set */
+ return FALSE;
}
+
/*
* @implemented
*
* A partial copy is NOT performed if the dest buffer is too small!
*/
NTSTATUS
-STDCALL
+NTAPI
RtlOemStringToCountedUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PCOEM_STRING OemSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
+ /* Calculate size of the string */
Length = RtlOemStringToCountedUnicodeSize(OemSource);
+ /* If it's 0 then zero out dest string and return */
if (!Length)
{
RtlZeroMemory(UniDest, sizeof(UNICODE_STRING));
return STATUS_SUCCESS;
}
+ /* Check if length is a sane value */
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
+ /* Store it in dest string */
UniDest->Length = (USHORT)Length;
+ /* If we're asked to alloc the string - do so */
if (AllocateDestinationString)
{
UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
UniDest->MaximumLength = Length;
if (!UniDest->Buffer) return STATUS_NO_MEMORY;
}
- else if (UniDest->Length >= UniDest->MaximumLength)
+ else if (UniDest->Length > UniDest->MaximumLength)
{
return STATUS_BUFFER_OVERFLOW;
}
+ /* Do the conversion */
Status = RtlOemToUnicodeN(UniDest->Buffer,
UniDest->Length,
&Index,
if (!NT_SUCCESS(Status) && AllocateDestinationString)
{
+ /* Conversion failed, free dest string and return status code */
RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
UniDest->Buffer = NULL;
return Status;
* The comparison is case insensitive.
*/
BOOLEAN
-STDCALL
+NTAPI
RtlEqualComputerName(
IN PUNICODE_STRING ComputerName1,
IN PUNICODE_STRING ComputerName2)
* The comparison is case insensitive.
*/
BOOLEAN
-STDCALL
+NTAPI
RtlEqualDomainName (
IN PUNICODE_STRING DomainName1,
IN PUNICODE_STRING DomainName2
* See RtlStringFromGUID.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlGUIDFromString(
IN UNICODE_STRING *str,
OUT GUID* guid
/* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
* to memory: DWORD... WORD WORD BYTES............
*/
- while (i < 37)
+ while (i <= 37)
{
switch (i)
{
* @implemented
*/
VOID
-STDCALL
+NTAPI
RtlEraseUnicodeString(
IN PUNICODE_STRING String)
{
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
RtlHashUnicodeString(
IN CONST UNICODE_STRING *String,
IN BOOLEAN CaseInSensitive,
* Does a partial copy if the dest buffer is too small
*/
NTSTATUS
-STDCALL
+NTAPI
RtlUnicodeStringToCountedOemString(
IN OUT POEM_STRING OemDest,
IN PUNICODE_STRING UniSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
+ /* Calculate size of the string */
Length = RtlUnicodeStringToCountedOemSize(UniSource);
+ /* If it's 0 then zero out dest string and return */
if (!Length)
{
- RtlZeroMemory(OemDest, sizeof(UNICODE_STRING));
+ RtlZeroMemory(OemDest, sizeof(OEM_STRING));
+ return STATUS_SUCCESS;
}
+ /* Check if length is a sane value */
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
+ /* Store it in dest string */
OemDest->Length = (USHORT)Length;
+ /* If we're asked to alloc the string - do so */
if (AllocateDestinationString)
{
OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR);
OemDest->MaximumLength = Length;
if (!OemDest->Buffer) return STATUS_NO_MEMORY;
}
- else if (OemDest->Length >= OemDest->MaximumLength)
+ else if (OemDest->Length > OemDest->MaximumLength)
{
return STATUS_BUFFER_OVERFLOW;
}
+ /* Do the conversion */
Status = RtlUnicodeToOemN(OemDest->Buffer,
OemDest->Length,
&Index,
UniSource->Buffer,
UniSource->Length);
- /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+ /* Check for unmapped character */
+ if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+ Status = STATUS_UNMAPPABLE_CHARACTER;
if (!NT_SUCCESS(Status) && AllocateDestinationString)
{
+ /* Conversion failed, free dest string and return status code */
RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR);
OemDest->Buffer = NULL;
return Status;
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
RtlLargeIntegerToChar(
IN PLARGE_INTEGER Value,
IN ULONG Base,
IN ULONG Length,
IN OUT PCHAR String)
{
- ULONG Radix;
- CHAR temp[65];
- ULONGLONG v = Value->QuadPart;
- ULONG i;
- PCHAR tp;
- PCHAR sp;
+ ULONGLONG Val = Value->QuadPart;
+ NTSTATUS Status = STATUS_SUCCESS;
+ CHAR Buffer[65];
+ CHAR Digit;
+ ULONG Len;
+ PCHAR Pos;
- Radix = Base;
- if (Radix == 0)
- Radix = 10;
+ if (Base == 0) Base = 10;
- if ((Radix != 2) && (Radix != 8) &&
- (Radix != 10) && (Radix != 16))
- return STATUS_INVALID_PARAMETER;
+ if ((Base != 2) && (Base != 8) &&
+ (Base != 10) && (Base != 16))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
- tp = temp;
- while (v || tp == temp)
- {
- i = v % Radix;
- v = v / Radix;
- if (i < 10)
- *tp = i + '0';
- else
- *tp = i + 'a' - 10;
- tp++;
- }
+ Pos = &Buffer[64];
+ *Pos = '\0';
- if ((ULONG)((ULONG_PTR)tp - (ULONG_PTR)temp) >= Length)
- return STATUS_BUFFER_TOO_SMALL;
+ do
+ {
+ Pos--;
+ Digit = Val % Base;
+ Val = Val / Base;
+ if (Digit < 10)
+ *Pos = '0' + Digit;
+ else
+ *Pos = 'A' + Digit - 10;
+ }
+ while (Val != 0L);
- sp = String;
- while (tp > temp)
- *sp++ = *--tp;
- *sp = 0;
+ Len = &Buffer[64] - Pos;
- return STATUS_SUCCESS;
+ if (Len > Length)
+ return STATUS_BUFFER_OVERFLOW;
+
+#if 1 /* It needs to be removed, when will probably use SEH in rtl */
+ if (String == NULL)
+ {
+ return STATUS_ACCESS_VIOLATION;
+ }
+#endif
+
+#if 0
+ _SEH2_TRY
+ {
+#endif
+ if (Len == Length)
+ RtlCopyMemory(String, Pos, Len);
+ else
+ RtlCopyMemory(String, Pos, Len + 1);
+#if 0
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the error code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+#endif
+
+ return Status;
}
/*
* might not be '\0' terminated. dest->Length is only set upon success.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlUpcaseUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PCUNICODE_STRING UniSource,
{
ULONG i, j;
+ PAGED_CODE_RTL();
+
if (AllocateDestinationString == TRUE)
{
UniDest->MaximumLength = UniSource->Length;
* It performs a partial copy if ansi is too small.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlUpcaseUnicodeStringToAnsiString(
IN OUT PANSI_STRING AnsiDest,
IN PUNICODE_STRING UniSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
Length = RtlUnicodeStringToAnsiSize(UniSource);
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
* It performs a partial copy if ansi is too small.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlUpcaseUnicodeStringToCountedOemString(
IN OUT POEM_STRING OemDest,
IN PCUNICODE_STRING UniSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
Length = RtlUnicodeStringToCountedOemSize(UniSource);
if (!Length)
{
- RtlZeroMemory(OemDest, sizeof(UNICODE_STRING));
+ RtlZeroMemory(OemDest, sizeof(OEM_STRING));
}
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
OemDest->MaximumLength = Length;
if (!OemDest->Buffer) return STATUS_NO_MEMORY;
}
- else if (OemDest->Length >= OemDest->MaximumLength)
+ else if (OemDest->Length > OemDest->MaximumLength)
{
return STATUS_BUFFER_OVERFLOW;
}
UniSource->Buffer,
UniSource->Length);
- /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+ /* Check for unmapped characters */
+ if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+ Status = STATUS_UNMAPPABLE_CHARACTER;
if (!NT_SUCCESS(Status) && AllocateDestinationString)
{
* It performs a partial copy if oem is too small.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlUpcaseUnicodeStringToOemString (
IN OUT POEM_STRING OemDest,
IN PCUNICODE_STRING UniSource,
ULONG Length;
ULONG Index;
+ PAGED_CODE_RTL();
+
Length = RtlUnicodeStringToOemSize(UniSource);
if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
UniSource->Buffer,
UniSource->Length);
- /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+ /* Check for unmapped characters */
+ if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+ Status = STATUS_UNMAPPABLE_CHARACTER;
if (!NT_SUCCESS(Status) && AllocateDestinationString)
{
* Bytes calculated including nullterm
*/
ULONG
-STDCALL
+NTAPI
RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString)
{
ULONG Size;
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
RtlStringFromGUID (IN REFGUID Guid,
OUT PUNICODE_STRING GuidString)
{
- STATIC CONST PWCHAR Hex = L"0123456789ABCDEF";
- WCHAR Buffer[40];
- PWCHAR BufferPtr;
- ULONG i;
-
- if (Guid == NULL)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- swprintf (Buffer,
- L"{%08lX-%04X-%04X-%02X%02X-",
+ /* Setup the string */
+ GuidString->Length = 38 * sizeof(WCHAR);
+ GuidString->MaximumLength = GuidString->Length + sizeof(UNICODE_NULL);
+ GuidString->Buffer = RtlpAllocateStringMemory(GuidString->MaximumLength,
+ TAG_USTR);
+ if (!GuidString->Buffer) return STATUS_NO_MEMORY;
+
+ /* Now format the GUID */
+ swprintf(GuidString->Buffer,
+ L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
Guid->Data1,
Guid->Data2,
Guid->Data3,
Guid->Data4[0],
- Guid->Data4[1]);
- BufferPtr = Buffer + 25;
-
- /* 6 hex bytes */
- for (i = 2; i < 8; i++)
- {
- *BufferPtr++ = Hex[Guid->Data4[i] >> 4];
- *BufferPtr++ = Hex[Guid->Data4[i] & 0xf];
- }
-
- *BufferPtr++ = L'}';
- *BufferPtr++ = L'\0';
-
- return RtlCreateUnicodeString (GuidString, Buffer);
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]);
+ return STATUS_SUCCESS;
}
/*
* Bytes calculated including nullterm
*/
ULONG
-STDCALL
+NTAPI
RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString)
{
ULONG Size;
* @implemented
*/
LONG
-STDCALL
+NTAPI
RtlCompareUnicodeString(
IN PCUNICODE_STRING s1,
IN PCUNICODE_STRING s2,
* @implemented
*/
VOID
-STDCALL
+NTAPI
RtlCopyString(
IN OUT PSTRING DestinationString,
IN PSTRING SourceString OPTIONAL)
* @implemented
*/
VOID
-STDCALL
+NTAPI
RtlCopyUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PCUNICODE_STRING SourceString)
* Creates a nullterminated UNICODE_STRING
*/
BOOLEAN
-STDCALL
+NTAPI
RtlCreateUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PCWSTR Source)
{
ULONG Length;
+ PAGED_CODE_RTL();
+
Length = (wcslen(Source) + 1) * sizeof(WCHAR);
+ if (Length > 0xFFFE) return FALSE;
+
UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
if (UniDest->Buffer == NULL) return FALSE;
- RtlMoveMemory(UniDest->Buffer, Source, Length);
+ RtlCopyMemory(UniDest->Buffer, Source, Length);
UniDest->MaximumLength = (USHORT)Length;
UniDest->Length = Length - sizeof (WCHAR);
* @implemented
*/
BOOLEAN
-STDCALL
+NTAPI
RtlCreateUnicodeStringFromAsciiz(
OUT PUNICODE_STRING Destination,
IN PCSZ Source)
* Dest->Length is only set upon success.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlDowncaseUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PCUNICODE_STRING UniSource,
ULONG i;
ULONG StopGap;
+ PAGED_CODE_RTL();
+
if (AllocateDestinationString)
{
UniDest->MaximumLength = UniSource->Length;
* When dest fits exactly in MaximumLength characters the '\0' is ommitted.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination,
IN PCWSTR Source)
{
* dest is never '\0' terminated.
*/
NTSTATUS
-STDCALL
+NTAPI
RtlAppendAsciizToString(
IN OUT PSTRING Destination,
IN PCSZ Source)
* @implemented
*/
VOID
-STDCALL
+NTAPI
RtlUpperString(PSTRING DestinationString,
PSTRING SourceString)
{
PCHAR Src, Dest;
Length = min(SourceString->Length,
- DestinationString->MaximumLength - 1);
+ DestinationString->MaximumLength);
Src = SourceString->Buffer;
Dest = DestinationString->Buffer;
* See RtlpDuplicateUnicodeString
*/
NTSTATUS
-STDCALL
+NTAPI
RtlDuplicateUnicodeString(
IN ULONG Flags,
IN PCUNICODE_STRING SourceString,
OUT PUNICODE_STRING DestinationString)
{
- if (SourceString == NULL || DestinationString == NULL)
- return STATUS_INVALID_PARAMETER;
+ PAGED_CODE_RTL();
+
+ if (SourceString == NULL || DestinationString == NULL ||
+ SourceString->Length > SourceString->MaximumLength ||
+ (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) ||
+ Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4) {
+ return STATUS_INVALID_PARAMETER;
+ }
- if ((SourceString->Length == 0) &&
- (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
+ if ((SourceString->Length == 0) &&
+ (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
{
DestinationString->Length = 0;
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS NTAPI
RtlValidateUnicodeString(IN ULONG Flags,
- IN PUNICODE_STRING UnicodeString)
+ IN PCUNICODE_STRING UnicodeString)
{
/* currently no flags are supported! */
ASSERT(Flags == 0);
}
}
-/* EOF */
+NTSTATUS
+NTAPI
+RtlFindCharInUnicodeString(IN ULONG Flags,
+ IN PUNICODE_STRING SearchString,
+ IN PCUNICODE_STRING MatchString,
+ OUT PUSHORT Position)
+{
+ int main_idx;
+ unsigned int search_idx;
+
+ switch (Flags)
+ {
+ case 0:
+ {
+ for (main_idx = 0; main_idx < SearchString->Length / sizeof(WCHAR); main_idx++)
+ {
+ for (search_idx = 0; search_idx < MatchString->Length / sizeof(WCHAR); search_idx++)
+ {
+ if (SearchString->Buffer[main_idx] == MatchString->Buffer[search_idx])
+ {
+ *Position = (main_idx + 1) * sizeof(WCHAR);
+ return STATUS_SUCCESS;
+ }
+ }
+ }
+ *Position = 0;
+ return STATUS_NOT_FOUND;
+ }
+
+ case 1:
+ {
+ for (main_idx = SearchString->Length / sizeof(WCHAR) - 1; main_idx >= 0; main_idx--)
+ {
+ for (search_idx = 0; search_idx < MatchString->Length / sizeof(WCHAR); search_idx++)
+ {
+ if (SearchString->Buffer[main_idx] == MatchString->Buffer[search_idx])
+ {
+ *Position = main_idx * sizeof(WCHAR);
+ return STATUS_SUCCESS;
+ }
+ }
+ }
+ *Position = 0;
+ return STATUS_NOT_FOUND;
+ }
+
+ case 2:
+ {
+ for (main_idx = 0; main_idx < SearchString->Length / sizeof(WCHAR); main_idx++)
+ {
+ search_idx = 0;
+ while (search_idx < MatchString->Length / sizeof(WCHAR) &&
+ SearchString->Buffer[main_idx] != MatchString->Buffer[search_idx])
+ {
+ search_idx++;
+ }
+ if (search_idx >= MatchString->Length / sizeof(WCHAR))
+ {
+ *Position = (main_idx + 1) * sizeof(WCHAR);
+ return STATUS_SUCCESS;
+ }
+ }
+ *Position = 0;
+ return STATUS_NOT_FOUND;
+ }
+
+ case 3:
+ {
+ for (main_idx = SearchString->Length / sizeof(WCHAR) - 1; main_idx >= 0; main_idx--)
+ {
+ search_idx = 0;
+ while (search_idx < MatchString->Length / sizeof(WCHAR) &&
+ SearchString->Buffer[main_idx] != MatchString->Buffer[search_idx])
+ {
+ search_idx++;
+ }
+ if (search_idx >= MatchString->Length / sizeof(WCHAR))
+ {
+ *Position = main_idx * sizeof(WCHAR);
+ return STATUS_SUCCESS;
+ }
+ }
+ *Position = 0;
+ return STATUS_NOT_FOUND;
+ }
+ } /* switch */
+
+ return STATUS_NOT_FOUND;
+}