diff --git a/dlls/ntdll/tests/.cvsignore b/dlls/ntdll/tests/.cvsignore index 007df7377b5..aea4bfbd6d4 100644 --- a/dlls/ntdll/tests/.cvsignore +++ b/dlls/ntdll/tests/.cvsignore @@ -3,6 +3,7 @@ error.ok generated.ok large_int.ok ntdll_test.exe.spec.c +rtl.ok rtlbitmap.ok rtlstr.ok string.ok diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in index 872018abab1..32ee55ac7c7 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -9,6 +9,7 @@ CTESTS = \ error.c \ generated.c \ large_int.c \ + rtl.c \ rtlbitmap.c \ rtlstr.c \ string.c diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c new file mode 100644 index 00000000000..147e9c4e1a6 --- /dev/null +++ b/dlls/ntdll/tests/rtl.c @@ -0,0 +1,335 @@ +/* Unit test suite for Rtl* API functions + * + * Copyright 2003 Thomas Mertes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES + * We use function pointers here as there is no import library for NTDLL on + * windows. + */ + +#include + +#include "winbase.h" +#include "wine/test.h" +#include "winnt.h" +#include "winnls.h" +#include "winternl.h" + +/* Function ptrs for ntdll calls */ +static HMODULE hntdll = 0; +static SIZE_T (WINAPI *pRtlCompareMemoryUlong)(PULONG, SIZE_T, ULONG); +static ULONG (WINAPI *pRtlUniform)(PULONG); + + +static void InitFunctionPtrs(void) +{ + hntdll = LoadLibraryA("ntdll.dll"); + ok(hntdll != 0, "LoadLibrary failed"); + if (hntdll) { + pRtlCompareMemoryUlong = (void *)GetProcAddress(hntdll, "RtlCompareMemoryUlong"); + pRtlUniform = (void *)GetProcAddress(hntdll, "RtlUniform"); + } /* if */ +} + + +static void test_RtlCompareMemoryUlong(void) +{ + ULONG a[10]; + ULONG result; + + a[0]= 0x0123; + a[1]= 0x4567; + a[2]= 0x89ab; + a[3]= 0xcdef; + result = pRtlCompareMemoryUlong(a, 0, 0x0123); + ok(result == 0, "RtlCompareMemoryUlong(%p, 0, 0x0123) returns %lu, expected 0\n", a, result); + result = pRtlCompareMemoryUlong(a, 3, 0x0123); + ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %lu, expected 0\n", a, result); + result = pRtlCompareMemoryUlong(a, 4, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 5, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 7, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 8, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 9, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 4, 0x0127); + ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x0127) returns %lu, expected 0\n", a, result); + result = pRtlCompareMemoryUlong(a, 4, 0x7123); + ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x7123) returns %lu, expected 0\n", a, result); + result = pRtlCompareMemoryUlong(a, 16, 0x4567); + ok(result == 0, "RtlCompareMemoryUlong(%p, 16, 0x4567) returns %lu, expected 0\n", a, result); + + a[1]= 0x0123; + result = pRtlCompareMemoryUlong(a, 3, 0x0123); + ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %lu, expected 0\n", a, result); + result = pRtlCompareMemoryUlong(a, 4, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 5, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 7, 0x0123); + ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %lu, expected 4\n", a, result); + result = pRtlCompareMemoryUlong(a, 8, 0x0123); + ok(result == 8, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %lu, expected 8\n", a, result); + result = pRtlCompareMemoryUlong(a, 9, 0x0123); + ok(result == 8, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %lu, expected 8\n", a, result); +} + + +static void test_RtlUniform(void) +{ + ULONGLONG num; + ULONG seed; + ULONG seed_bak; + ULONG expected; + ULONG result; + +/* + * According to the documentation RtlUniform is using D.H. Lehmer's 1948 + * algorithm. This algorithm is: + * + * seed = (seed * const_1 + const_2) % const_3; + * + * According to the documentation the random number is distributed over + * [0..MAXLONG]. Therefore const_3 is MAXLONG + 1: + * + * seed = (seed * const_1 + const_2) % (MAXLONG + 1); + * + * Because MAXLONG is 0xfffffff (which is 0x10000000 - 1) the algorithm + * can be expressed as: + * + * seed = (seed * const_1 + const_2) & MAXLONG; + * + * To find out const_2 we just call RtlUniform with seed set to 0: + */ + seed = 0; + expected = 0x7fffffc3; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 0)) returns %lx, expected %lx", + result, expected); +/* + * The algorithm is now: + * + * seed = (seed * const_1 + 0x7fffffc3) & MAXLONG; + * + * To find out const_1 we can use: + * + * const_1 = RtlUniform(1) - 0x7fffffc3; + * + * If that does not work a search loop can try all possible values of + * const_1 and compare to the result to RtlUniform(1). + * This way we find out that const_1 is 0xffffffed. + * + * For seed = 1 the const_2 is 0x7fffffc4: + */ + seed = 1; + expected = seed * 0xffffffed + 0x7fffffc3 + 1; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 1)) returns %lx, expected %lx", + result, expected); +/* + * For seed = 2 the const_2 is 0x7fffffc3: + */ + seed = 2; + expected = seed * 0xffffffed + 0x7fffffc3; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 2)) returns %lx, expected %lx", + result, expected); +/* + * More tests show that if seed is odd the result must be incremented by 1: + */ + seed = 3; + expected = seed * 0xffffffed + 0x7fffffc3 + (seed & 1); + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 2)) returns %lx, expected %lx", + result, expected); + + seed = 0x6bca1aa; + expected = seed * 0xffffffed + 0x7fffffc3; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 0x6bca1aa)) returns %lx, expected %lx", + result, expected); + + seed = 0x6bca1ab; + expected = seed * 0xffffffed + 0x7fffffc3 + 1; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 0x6bca1ab)) returns %lx, expected %lx", + result, expected); +/* + * When seed is 0x6bca1ac there is an exception: + */ + seed = 0x6bca1ac; + expected = seed * 0xffffffed + 0x7fffffc3 + 2; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 0x6bca1ac)) returns %lx, expected %lx", + result, expected); +/* + * Note that up to here const_3 is not used + * (the highest bit of the result is not set). + * + * Starting with 0x6bca1ad: If seed is even the result must be incremented by 1: + */ + seed = 0x6bca1ad; + expected = (seed * 0xffffffed + 0x7fffffc3) & MAXLONG; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 0x6bca1ad)) returns %lx, expected %lx", + result, expected); + + seed = 0x6bca1ae; + expected = (seed * 0xffffffed + 0x7fffffc3 + 1) & MAXLONG; + result = pRtlUniform(&seed); + ok(result == expected, + "RtlUniform(&seed (seed == 0x6bca1ae)) returns %lx, expected %lx", + result, expected); +/* + * There are several ranges where for odd or even seed the result must be + * incremented by 1. You can see this ranges in the following test. + * + * For a full test use one of the following loop heads: + * + * for (num = 0; num <= 0xffffffff; num++) { + * seed = num; + * ... + * + * seed = 0; + * for (num = 0; num <= 0xffffffff; num++) { + * ... + */ + seed = 0; + for (num = 0; num <= 100000; num++) { + + expected = seed * 0xffffffed + 0x7fffffc3; + if (seed < 0x6bca1ac) { + expected = expected + (seed & 1); + } else if (seed == 0x6bca1ac) { + expected = (expected + 2) & MAXLONG; + } else if (seed < 0xd79435c) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x1435e50b) { + expected = expected + (seed & 1); + } else if (seed < 0x1af286ba) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x21af2869) { + expected = expected + (seed & 1); + } else if (seed < 0x286bca18) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x2f286bc7) { + expected = expected + (seed & 1); + } else if (seed < 0x35e50d77) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x3ca1af26) { + expected = expected + (seed & 1); + } else if (seed < 0x435e50d5) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x4a1af284) { + expected = expected + (seed & 1); + } else if (seed < 0x50d79433) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x579435e2) { + expected = expected + (seed & 1); + } else if (seed < 0x5e50d792) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x650d7941) { + expected = expected + (seed & 1); + } else if (seed < 0x6bca1af0) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x7286bc9f) { + expected = expected + (seed & 1); + } else if (seed < 0x79435e4e) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x7ffffffd) { + expected = expected + (seed & 1); + } else if (seed < 0x86bca1ac) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed == 0x86bca1ac) { + expected = (expected + 1) & MAXLONG; + } else if (seed < 0x8d79435c) { + expected = expected + (seed & 1); + } else if (seed < 0x9435e50b) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0x9af286ba) { + expected = expected + (seed & 1); + } else if (seed < 0xa1af2869) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0xa86bca18) { + expected = expected + (seed & 1); + } else if (seed < 0xaf286bc7) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed == 0xaf286bc7) { + expected = (expected + 2) & MAXLONG; + } else if (seed < 0xb5e50d77) { + expected = expected + (seed & 1); + } else if (seed < 0xbca1af26) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0xc35e50d5) { + expected = expected + (seed & 1); + } else if (seed < 0xca1af284) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0xd0d79433) { + expected = expected + (seed & 1); + } else if (seed < 0xd79435e2) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0xde50d792) { + expected = expected + (seed & 1); + } else if (seed < 0xe50d7941) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0xebca1af0) { + expected = expected + (seed & 1); + } else if (seed < 0xf286bc9f) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else if (seed < 0xf9435e4e) { + expected = expected + (seed & 1); + } else if (seed < 0xfffffffd) { + expected = (expected + (~seed & 1)) & MAXLONG; + } else { + expected = expected + (seed & 1); + } /* if */ + seed_bak = seed; + result = pRtlUniform(&seed); + ok(result == expected, + "test: %llu RtlUniform(&seed (seed == %lx)) returns %lx, expected %lx", + num, seed_bak, result, expected); + ok(seed == expected, + "test: %llu RtlUniform(&seed (seed == %lx)) sets seed to %lx, expected %lx", + num, seed_bak, seed, expected); + } /* for */ +/* + * Further investigation shows: In the different regions the highest bit + * is set or cleared when even or odd seeds need an increment by 1. + * This leads to the simplified RtlUniform of wine (see dlls/ntdll/rtl.c). + */ +} + + +START_TEST(rtl) +{ + InitFunctionPtrs(); + + test_RtlCompareMemoryUlong(); + test_RtlUniform(); +} + diff --git a/dlls/ntdll/tests/rtlstr.c b/dlls/ntdll/tests/rtlstr.c index 50e828b5820..703809e3153 100644 --- a/dlls/ntdll/tests/rtlstr.c +++ b/dlls/ntdll/tests/rtlstr.c @@ -35,9 +35,11 @@ static STRING str; /* Function ptrs for ntdll calls */ static HMODULE hntdll = 0; +static NTSTATUS (WINAPI *pRtlAppendUnicodeStringToString)(UNICODE_STRING *, const UNICODE_STRING *); static NTSTATUS (WINAPI *pRtlCharToInteger)(char *, ULONG, int *); static VOID (WINAPI *pRtlCopyString)(STRING *, const STRING *); static BOOLEAN (WINAPI *pRtlCreateUnicodeString)(PUNICODE_STRING, LPCWSTR); +static NTSTATUS (WINAPI *pRtlDowncaseUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN); static BOOLEAN (WINAPI *pRtlEqualUnicodeString)(const UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN); static VOID (WINAPI *pRtlFreeAnsiString)(PSTRING); static VOID (WINAPI *pRtlInitAnsiString)(PSTRING, LPCSTR); @@ -91,9 +93,11 @@ static void InitFunctionPtrs(void) hntdll = LoadLibraryA("ntdll.dll"); ok(hntdll != 0, "LoadLibrary failed"); if (hntdll) { + pRtlAppendUnicodeStringToString = (void *)GetProcAddress(hntdll, "RtlAppendUnicodeStringToString"); pRtlCharToInteger = (void *)GetProcAddress(hntdll, "RtlCharToInteger"); pRtlCopyString = (void *)GetProcAddress(hntdll, "RtlCopyString"); pRtlCreateUnicodeString = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeString"); + pRtlDowncaseUnicodeString = (void *)GetProcAddress(hntdll, "RtlDowncaseUnicodeString"); pRtlEqualUnicodeString = (void *)GetProcAddress(hntdll, "RtlEqualUnicodeString"); pRtlFreeAnsiString = (void *)GetProcAddress(hntdll, "RtlFreeAnsiString"); pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString"); @@ -305,6 +309,190 @@ static void test_RtlUpcaseUnicodeString(void) } +static void test_RtlDowncaseUnicodeString(void) +{ + int i; + WCHAR ch; + WCHAR lower_ch; + WCHAR source_buf[1025]; + WCHAR result_buf[1025]; + WCHAR lower_buf[1025]; + UNICODE_STRING source_str; + UNICODE_STRING result_str; + UNICODE_STRING lower_str; + + for (i = 0; i <= 1024; i++) { + ch = (WCHAR) i; + if (ch >= 'A' && ch <= 'Z') { + lower_ch = ch - 'A' + 'a'; + } else if (ch >= 0xc0 && ch <= 0xde && ch != 0xd7) { + lower_ch = ch + 0x20; + } else if (ch >= 0x391 && ch <= 0x3ab && ch != 0x3a2) { + lower_ch = ch + 0x20; + } else { + switch (ch) { + case 0x178: lower_ch = 0xff; break; + case 0x181: lower_ch = 0x253; break; + case 0x186: lower_ch = 0x254; break; + case 0x189: lower_ch = 0x256; break; + case 0x18a: lower_ch = 0x257; break; + case 0x18e: lower_ch = 0x1dd; break; + case 0x18f: lower_ch = 0x259; break; + case 0x190: lower_ch = 0x25b; break; + case 0x193: lower_ch = 0x260; break; + case 0x194: lower_ch = 0x263; break; + case 0x196: lower_ch = 0x269; break; + case 0x197: lower_ch = 0x268; break; + case 0x19c: lower_ch = 0x26f; break; + case 0x19d: lower_ch = 0x272; break; + case 0x19f: lower_ch = 0x275; break; + case 0x1a9: lower_ch = 0x283; break; + case 0x1ae: lower_ch = 0x288; break; + case 0x1b1: lower_ch = 0x28a; break; + case 0x1b2: lower_ch = 0x28b; break; + case 0x1b7: lower_ch = 0x292; break; + case 0x1c4: lower_ch = 0x1c6; break; + case 0x1c7: lower_ch = 0x1c9; break; + case 0x1ca: lower_ch = 0x1cc; break; + case 0x1f1: lower_ch = 0x1f3; break; + case 0x386: lower_ch = 0x3ac; break; + case 0x388: lower_ch = 0x3ad; break; + case 0x389: lower_ch = 0x3ae; break; + case 0x38a: lower_ch = 0x3af; break; + case 0x38c: lower_ch = 0x3cc; break; + case 0x38e: lower_ch = 0x3cd; break; + case 0x38f: lower_ch = 0x3ce; break; + case 0x400: lower_ch = 0x0; break; + default: lower_ch = ch; break; + } /* switch */ + } /* if */ + source_buf[i] = ch; + result_buf[i] = '\0'; + lower_buf[i] = lower_ch; + } /* for */ + source_buf[i] = '\0'; + result_buf[i] = '\0'; + lower_buf[i] = '\0'; + source_str.Length = 2048; + source_str.MaximumLength = 2048; + source_str.Buffer = source_buf; + result_str.Length = 2048; + result_str.MaximumLength = 2048; + result_str.Buffer = result_buf; + lower_str.Length = 2048; + lower_str.MaximumLength = 2048; + lower_str.Buffer = lower_buf; + + pRtlDowncaseUnicodeString(&result_str, &source_str, 0); + for (i = 0; i <= 1024; i++) { + ok(result_str.Buffer[i] == lower_str.Buffer[i] || result_str.Buffer[i] == source_str.Buffer[i] + 1, + "RtlDowncaseUnicodeString works wrong: '%c'[=0x%x] is converted to '%c'[=0x%x], expected: '%c'[=0x%x]", + source_str.Buffer[i], source_str.Buffer[i], + result_str.Buffer[i], result_str.Buffer[i], + lower_str.Buffer[i], lower_str.Buffer[i]); + } /* for */ +} + + +static void test_RtlAppendUnicodeStringToString(void) +{ + CHAR dest_buf[257]; + CHAR src_buf[257]; + UNICODE_STRING dest_str; + UNICODE_STRING src_str; + NTSTATUS result; + + strcpy(dest_buf, "ThisisafakeU0123456789abcdefghij"); + strcpy(src_buf, "nicodeStringZYXWVUTS"); + dest_str.Length = 12; + dest_str.MaximumLength = 26; + dest_str.Buffer = (WCHAR *) dest_buf; + src_str.Length = 12; + src_str.MaximumLength = 12; + src_str.Buffer = (WCHAR *) src_buf; + result = pRtlAppendUnicodeStringToString(&dest_str, &src_str); + ok(result == STATUS_SUCCESS, + "call failed: RtlAppendUnicodeStringToString(dest, src) has result %lx", + result); + ok(memcmp(dest_buf, "ThisisafakeUnicodeString\0\0efghij", 32) == 0, + "call failed: RtlAppendUnicodeStringToString(dest, src) has dest \"%s\"", + dest_buf); + + strcpy(dest_buf, "ThisisafakeU0123456789abcdefghij"); + dest_str.Length = 12; + dest_str.MaximumLength = 25; + result = pRtlAppendUnicodeStringToString(&dest_str, &src_str); + ok(result == STATUS_SUCCESS, + "call failed: RtlAppendUnicodeStringToString(dest, src) has result %lx", + result); + ok(memcmp(dest_buf, "ThisisafakeUnicodeString\0\0efghij", 32) == 0, + "call failed: RtlAppendUnicodeStringToString(dest, src) has dest \"%s\"", + dest_buf); + + strcpy(dest_buf, "ThisisafakeU0123456789abcdefghij"); + dest_str.Length = 12; + dest_str.MaximumLength = 24; + result = pRtlAppendUnicodeStringToString(&dest_str, &src_str); + ok(result == STATUS_SUCCESS, + "call failed: RtlAppendUnicodeStringToString(dest, src) has result %lx", + result); + ok(memcmp(dest_buf, "ThisisafakeUnicodeStringcdefghij", 32) == 0, + "call failed: RtlAppendUnicodeStringToString(dest, src) has dest \"%s\"", + dest_buf); + + strcpy(dest_buf, "ThisisafakeU0123456789abcdefghij"); + dest_str.Length = 12; + dest_str.MaximumLength = 23; + result = pRtlAppendUnicodeStringToString(&dest_str, &src_str); + ok(result == STATUS_BUFFER_TOO_SMALL, + "call failed: RtlAppendUnicodeStringToString(dest, src) has result %lx", + result); + ok(memcmp(dest_buf, "ThisisafakeU0123456789abcdefghij", 32) == 0, + "call failed: RtlAppendUnicodeStringToString(dest, src) has dest \"%s\"", + dest_buf); + + strcpy(dest_buf, "ThisisafakeU0123456789abcdefghij"); + dest_str.Length = 12; + dest_str.MaximumLength = 0; + src_str.Length = 0; + src_str.MaximumLength = 0; + result = pRtlAppendUnicodeStringToString(&dest_str, &src_str); + ok(result == STATUS_SUCCESS, + "call failed: RtlAppendUnicodeStringToString(dest, src) has result %lx", + result); + ok(memcmp(dest_buf, "ThisisafakeU0123456789abcdefghij", 32) == 0, + "call failed: RtlAppendUnicodeStringToString(dest, src) has dest \"%s\"", + dest_buf); + + strcpy(dest_buf, "ThisisafakeU0123456789abcdefghij"); + dest_str.Length = 12; + dest_str.MaximumLength = 22; + src_str.Length = 0; + src_str.MaximumLength = 0; + result = pRtlAppendUnicodeStringToString(&dest_str, &src_str); + ok(result == STATUS_SUCCESS, + "call failed: RtlAppendUnicodeStringToString(dest, src) has result %lx", + result); + ok(memcmp(dest_buf, "ThisisafakeU0123456789abcdefghij", 32) == 0, + "call failed: RtlAppendUnicodeStringToString(dest, src) has dest \"%s\"", + dest_buf); + + strcpy(dest_buf, "ThisisafakeU0123456789abcdefghij"); + dest_str.Length = 12; + dest_str.MaximumLength = 22; + src_str.Length = 0; + src_str.MaximumLength = 0; + src_str.Buffer = NULL; + result = pRtlAppendUnicodeStringToString(&dest_str, &src_str); + ok(result == STATUS_SUCCESS, + "call failed: RtlAppendUnicodeStringToString(dest, src) has result %lx", + result); + ok(memcmp(dest_buf, "ThisisafakeU0123456789abcdefghij", 32) == 0, + "call failed: RtlAppendUnicodeStringToString(dest, src) has dest \"%s\"", + dest_buf); +} + + typedef struct { int base; char *str; @@ -321,6 +509,14 @@ static const str2int_t str2int[] = { { 0, "-+214", 0, STATUS_SUCCESS}, { 0, "++214", 0, STATUS_SUCCESS}, { 0, "+-214", 0, STATUS_SUCCESS}, + { 0, "\001\002\003\00411", 11, STATUS_SUCCESS}, /* whitespace char 1 to 4 */ + { 0, "\005\006\007\01012", 12, STATUS_SUCCESS}, /* whitespace char 5 to 8 */ + { 0, "\011\012\013\01413", 13, STATUS_SUCCESS}, /* whitespace char 9 to 12 */ + { 0, "\015\016\017\02014", 14, STATUS_SUCCESS}, /* whitespace char 13 to 16 */ + { 0, "\021\022\023\02415", 15, STATUS_SUCCESS}, /* whitespace char 17 to 20 */ + { 0, "\025\026\027\03016", 16, STATUS_SUCCESS}, /* whitespace char 21 to 24 */ + { 0, "\031\032\033\03417", 17, STATUS_SUCCESS}, /* whitespace char 25 to 28 */ + { 0, "\035\036\037\04018", 18, STATUS_SUCCESS}, /* whitespace char 29 to 32 */ { 0, " \n \r \t214", 214, STATUS_SUCCESS}, { 0, " \n \r \t+214", 214, STATUS_SUCCESS}, /* Signs can be used after whitespace */ { 0, " \n \r \t-214", -214, STATUS_SUCCESS}, @@ -772,9 +968,11 @@ START_TEST(rtlstr) test_RtlIntegerToChar(); test_RtlUpperChar(); test_RtlUpperString(); + test_RtlAppendUnicodeStringToString(); } /* if */ /* * test_RtlUpcaseUnicodeChar(); * test_RtlUpcaseUnicodeString(); + * test_RtlDowncaseUnicodeString(); */ }