2 * Unit test suite for ntdll path functions
4 * Copyright 2003 Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "ntdll_test.h"
25 static NTSTATUS (WINAPI
*pRtlMultiByteToUnicodeN
)( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
26 LPCSTR src
, DWORD srclen
);
27 static NTSTATUS (WINAPI
*pRtlCreateEnvironment
)(BOOLEAN
, PWSTR
*);
28 static NTSTATUS (WINAPI
*pRtlDestroyEnvironment
)(PWSTR
);
29 static NTSTATUS (WINAPI
*pRtlQueryEnvironmentVariable_U
)(PWSTR
, PUNICODE_STRING
, PUNICODE_STRING
);
30 static void (WINAPI
*pRtlSetCurrentEnvironment
)(PWSTR
, PWSTR
*);
31 static NTSTATUS (WINAPI
*pRtlSetEnvironmentVariable
)(PWSTR
*, PUNICODE_STRING
, PUNICODE_STRING
);
32 static NTSTATUS (WINAPI
*pRtlExpandEnvironmentStrings_U
)(LPWSTR
, PUNICODE_STRING
, PUNICODE_STRING
, PULONG
);
34 static WCHAR small_env
[] = {'f','o','o','=','t','o','t','o',0,
35 'f','o','=','t','i','t','i',0,
36 'f','o','o','o','=','t','u','t','u',0,
37 's','r','=','a','n','=','o','u','o',0,
38 'g','=','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
39 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
40 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
41 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
42 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
43 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
44 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
45 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
46 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
47 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0,
48 '=','o','O','H','=','I','I','I',0,
52 static void testQuery(void)
63 static const struct test tests
[] =
65 {"foo", 256, STATUS_SUCCESS
, "toto"},
66 {"FoO", 256, STATUS_SUCCESS
, "toto"},
67 {"foo=", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
68 {"foo ", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
69 {"foo", 1, STATUS_BUFFER_TOO_SMALL
, "toto"},
70 {"foo", 3, STATUS_BUFFER_TOO_SMALL
, "toto"},
71 {"foo", 4, STATUS_SUCCESS
, "toto", STATUS_BUFFER_TOO_SMALL
},
72 {"foo", 5, STATUS_SUCCESS
, "toto"},
73 {"fooo", 256, STATUS_SUCCESS
, "tutu"},
74 {"f", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
75 {"g", 256, STATUS_SUCCESS
, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
76 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
77 {"sr=an", 256, STATUS_SUCCESS
, "ouo", STATUS_VARIABLE_NOT_FOUND
},
78 {"sr", 256, STATUS_SUCCESS
, "an=ouo"},
79 {"=oOH", 256, STATUS_SUCCESS
, "III"},
80 {"", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
81 {"nul", 256, STATUS_SUCCESS
, ""},
89 const struct test
* test
;
92 for (test
= tests
; test
->var
; test
++)
94 name
.Length
= strlen(test
->var
) * 2;
95 name
.MaximumLength
= name
.Length
+ 2;
98 value
.MaximumLength
= test
->len
* 2;
102 pRtlMultiByteToUnicodeN( bn
, sizeof(bn
), NULL
, test
->var
, strlen(test
->var
)+1 );
103 nts
= pRtlQueryEnvironmentVariable_U(small_env
, &name
, &value
);
104 ok( nts
== test
->status
|| (test
->alt
&& nts
== test
->alt
),
105 "[%d]: Wrong status for '%s', expecting %x got %x\n",
106 test
- tests
, test
->var
, test
->status
, nts
);
107 if (nts
== test
->status
) switch (nts
)
110 pRtlMultiByteToUnicodeN( bn
, sizeof(bn
), NULL
, test
->val
, strlen(test
->val
)+1 );
111 ok( value
.Length
== strlen(test
->val
) * sizeof(WCHAR
), "Wrong length %d for %s\n",
112 value
.Length
, test
->var
);
113 ok((value
.Length
== strlen(test
->val
) * sizeof(WCHAR
) && memcmp(bv
, bn
, test
->len
*sizeof(WCHAR
)) == 0) ||
114 lstrcmpW(bv
, bn
) == 0,
115 "Wrong result for %s/%d\n", test
->var
, test
->len
);
116 ok(bv
[test
->len
] == '@', "Writing too far away in the buffer for %s/%d\n", test
->var
, test
->len
);
118 case STATUS_BUFFER_TOO_SMALL
:
119 ok( value
.Length
== strlen(test
->val
) * sizeof(WCHAR
),
120 "Wrong returned length %d (too small buffer) for %s\n", value
.Length
, test
->var
);
126 static void testSetHelper(LPWSTR
* env
, const char* var
, const char* val
, NTSTATUS ret
, NTSTATUS alt
)
128 WCHAR bvar
[256], bval1
[256], bval2
[256];
133 uvar
.Length
= strlen(var
) * sizeof(WCHAR
);
134 uvar
.MaximumLength
= uvar
.Length
+ sizeof(WCHAR
);
136 pRtlMultiByteToUnicodeN( bvar
, sizeof(bvar
), NULL
, var
, strlen(var
)+1 );
139 uval
.Length
= strlen(val
) * sizeof(WCHAR
);
140 uval
.MaximumLength
= uval
.Length
+ sizeof(WCHAR
);
142 pRtlMultiByteToUnicodeN( bval1
, sizeof(bval1
), NULL
, val
, strlen(val
)+1 );
144 nts
= pRtlSetEnvironmentVariable(env
, &uvar
, val
? &uval
: NULL
);
145 ok(nts
== ret
|| (alt
&& nts
== alt
), "Setting var %s=%s (%x/%x)\n", var
, val
, nts
, ret
);
146 if (nts
== STATUS_SUCCESS
)
149 uval
.MaximumLength
= sizeof(bval2
);
151 nts
= pRtlQueryEnvironmentVariable_U(*env
, &uvar
, &uval
);
155 ok(lstrcmpW(bval1
, bval2
) == 0, "Cannot get value written to environment\n");
157 case STATUS_VARIABLE_NOT_FOUND
:
158 ok(val
== NULL
, "Couldn't find variable, but didn't delete it. val = %s\n", val
);
161 ok(0, "Wrong ret %u for %s\n", nts
, var
);
167 static void testSet(void)
173 ok(pRtlCreateEnvironment(FALSE
, &env
) == STATUS_SUCCESS
, "Creating environment\n");
175 testSetHelper(&env
, "cat", "dog", STATUS_SUCCESS
, 0);
176 testSetHelper(&env
, "cat", "horse", STATUS_SUCCESS
, 0);
177 testSetHelper(&env
, "cat", "zz", STATUS_SUCCESS
, 0);
178 testSetHelper(&env
, "cat", NULL
, STATUS_SUCCESS
, 0);
179 testSetHelper(&env
, "cat", NULL
, STATUS_SUCCESS
, STATUS_VARIABLE_NOT_FOUND
);
180 testSetHelper(&env
, "foo", "meouw", STATUS_SUCCESS
, 0);
181 testSetHelper(&env
, "me=too", "also", STATUS_INVALID_PARAMETER
, 0);
182 testSetHelper(&env
, "me", "too=also", STATUS_SUCCESS
, 0);
183 testSetHelper(&env
, "=too", "also", STATUS_SUCCESS
, 0);
184 testSetHelper(&env
, "=", "also", STATUS_SUCCESS
, 0);
186 for (i
= 0; i
< 128; i
++)
188 sprintf(tmp
, "zork%03d", i
);
189 testSetHelper(&env
, tmp
, "is alive", STATUS_SUCCESS
, 0);
192 for (i
= 0; i
< 128; i
++)
194 sprintf(tmp
, "zork%03d", i
);
195 testSetHelper(&env
, tmp
, NULL
, STATUS_SUCCESS
, 0);
197 testSetHelper(&env
, "fOo", NULL
, STATUS_SUCCESS
, 0);
199 ok(pRtlDestroyEnvironment(env
) == STATUS_SUCCESS
, "Destroying environment\n");
202 static void testExpand(void)
204 static const struct test
210 {"hello%foo%world", "hellototoworld"},
211 {"hello%=oOH%world", "helloIIIworld"},
212 {"hello%foo", "hello%foo"},
213 {"hello%bar%world", "hello%bar%world"},
215 * {"hello%foo%world%=oOH%eeck", "hellototoworldIIIeeck"},
216 * Interestingly enough, with a 8 WCHAR buffers, we get on 2k:
218 * so it seems like strings overflowing the buffer are written
219 * (truncated) but the write cursor is not advanced :-/
224 const struct test
* test
;
226 UNICODE_STRING us_src
, us_dst
;
227 WCHAR src
[256], dst
[256], rst
[256];
230 for (test
= tests
; test
->src
; test
++)
232 pRtlMultiByteToUnicodeN(src
, sizeof(src
), NULL
, test
->src
, strlen(test
->src
)+1);
233 pRtlMultiByteToUnicodeN(rst
, sizeof(rst
), NULL
, test
->dst
, strlen(test
->dst
)+1);
235 us_src
.Length
= strlen(test
->src
) * sizeof(WCHAR
);
236 us_src
.MaximumLength
= us_src
.Length
+ 2;
240 us_dst
.MaximumLength
= 0;
241 us_dst
.Buffer
= NULL
;
243 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
244 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
245 "Wrong returned length for %s: %u\n", test
->src
, ul
);
248 us_dst
.MaximumLength
= sizeof(dst
);
251 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
252 ok(nts
== STATUS_SUCCESS
, "Call failed (%u)\n", nts
);
253 ok(ul
== us_dst
.Length
+ sizeof(WCHAR
),
254 "Wrong returned length for %s: %u\n", test
->src
, ul
);
255 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
256 "Wrong returned length for %s: %u\n", test
->src
, ul
);
257 ok(lstrcmpW(dst
, rst
) == 0, "Wrong result for %s: expecting %s\n",
258 test
->src
, test
->dst
);
261 us_dst
.MaximumLength
= 8 * sizeof(WCHAR
);
264 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
265 ok(nts
== STATUS_BUFFER_TOO_SMALL
, "Call failed (%u)\n", nts
);
266 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
267 "Wrong returned length for %s (with buffer too small): %u\n", test
->src
, ul
);
268 ok(dst
[8] == '-', "Writing too far in buffer (got %c/%d)\n", dst
[8], dst
[8]);
275 HMODULE mod
= GetModuleHandleA("ntdll.dll");
277 pRtlMultiByteToUnicodeN
= (void *)GetProcAddress(mod
,"RtlMultiByteToUnicodeN");
278 pRtlCreateEnvironment
= (void*)GetProcAddress(mod
, "RtlCreateEnvironment");
279 pRtlDestroyEnvironment
= (void*)GetProcAddress(mod
, "RtlDestroyEnvironment");
280 pRtlQueryEnvironmentVariable_U
= (void*)GetProcAddress(mod
, "RtlQueryEnvironmentVariable_U");
281 pRtlSetCurrentEnvironment
= (void*)GetProcAddress(mod
, "RtlSetCurrentEnvironment");
282 pRtlSetEnvironmentVariable
= (void*)GetProcAddress(mod
, "RtlSetEnvironmentVariable");
283 pRtlExpandEnvironmentStrings_U
= (void*)GetProcAddress(mod
, "RtlExpandEnvironmentStrings_U");
285 if (pRtlQueryEnvironmentVariable_U
)
287 if (pRtlSetEnvironmentVariable
)
289 if (pRtlExpandEnvironmentStrings_U
)