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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "ntdll_test.h"
24 #include "wine/unicode.h"
26 static NTSTATUS (WINAPI
*pRtlMultiByteToUnicodeN
)( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
27 LPCSTR src
, DWORD srclen
);
28 static NTSTATUS (WINAPI
*pRtlCreateEnvironment
)(BOOLEAN
, PWSTR
*);
29 static NTSTATUS (WINAPI
*pRtlDestroyEnvironment
)(PWSTR
);
30 static NTSTATUS (WINAPI
*pRtlQueryEnvironmentVariable_U
)(PWSTR
, PUNICODE_STRING
, PUNICODE_STRING
);
31 static void (WINAPI
*pRtlSetCurrentEnvironment
)(PWSTR
, PWSTR
*);
32 static NTSTATUS (WINAPI
*pRtlSetEnvironmentVariable
)(PWSTR
*, PUNICODE_STRING
, PUNICODE_STRING
);
33 static NTSTATUS (WINAPI
*pRtlExpandEnvironmentStrings_U
)(LPWSTR
, PUNICODE_STRING
, PUNICODE_STRING
, PULONG
);
35 static WCHAR small_env
[] = {'f','o','o','=','t','o','t','o',0,
36 'f','o','=','t','i','t','i',0,
37 'f','o','o','o','=','t','u','t','u',0,
38 's','r','=','a','n','=','o','u','o',0,
39 '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',
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',
48 '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,
49 '=','o','O','H','=','I','I','I',0,
53 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"},
72 {"fooo", 256, STATUS_SUCCESS
, "tutu"},
73 {"f", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
74 {"g", 256, STATUS_SUCCESS
, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
75 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
76 {"sr=an", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
77 {"sr", 256, STATUS_SUCCESS
, "an=ouo"},
78 {"=oOH", 256, STATUS_SUCCESS
, "III"},
79 {"", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
80 {"nul", 256, STATUS_SUCCESS
, ""},
88 const struct test
* test
;
91 for (test
= tests
; test
->var
; test
++)
93 name
.Length
= strlen(test
->var
) * 2;
94 name
.MaximumLength
= name
.Length
+ 2;
97 value
.MaximumLength
= test
->len
* 2;
101 pRtlMultiByteToUnicodeN( bn
, sizeof(bn
), NULL
, test
->var
, strlen(test
->var
)+1 );
102 nts
= pRtlQueryEnvironmentVariable_U(small_env
, &name
, &value
);
103 ok( nts
== test
->status
, "[%d]: Wrong status for '%s', expecting %lx got %lx\n",
104 test
- tests
, test
->var
, test
->status
, nts
);
105 if (nts
== test
->status
) switch (nts
)
108 pRtlMultiByteToUnicodeN( bn
, sizeof(bn
), NULL
, test
->val
, strlen(test
->val
)+1 );
109 ok( value
.Length
== strlen(test
->val
) * sizeof(WCHAR
), "Wrong length %d/%d for %s\n",
110 value
.Length
, strlen(test
->val
) * sizeof(WCHAR
), test
->var
);
111 ok((value
.Length
== strlen(test
->val
) * sizeof(WCHAR
) && strncmpW(bv
, bn
, test
->len
) == 0) ||
112 strcmpW(bv
, bn
) == 0,
113 "Wrong result for %s/%d\n", test
->var
, test
->len
);
114 ok(bv
[test
->len
] == '@', "Writing too far away in the buffer for %s/%d\n", test
->var
, test
->len
);
116 case STATUS_BUFFER_TOO_SMALL
:
117 ok( value
.Length
== strlen(test
->val
) * sizeof(WCHAR
),
118 "Wrong returned length %d/%d (too small buffer) for %s\n",
119 value
.Length
, strlen(test
->val
) * sizeof(WCHAR
), test
->var
);
125 static void testSetHelper(LPWSTR
* env
, const char* var
, const char* val
, NTSTATUS ret
)
127 WCHAR bvar
[256], bval1
[256], bval2
[256];
132 uvar
.Length
= strlen(var
) * sizeof(WCHAR
);
133 uvar
.MaximumLength
= uvar
.Length
+ sizeof(WCHAR
);
135 pRtlMultiByteToUnicodeN( bvar
, sizeof(bvar
), NULL
, var
, strlen(var
)+1 );
138 uval
.Length
= strlen(val
) * sizeof(WCHAR
);
139 uval
.MaximumLength
= uval
.Length
+ sizeof(WCHAR
);
141 pRtlMultiByteToUnicodeN( bval1
, sizeof(bval1
), NULL
, val
, strlen(val
)+1 );
143 nts
= pRtlSetEnvironmentVariable(env
, &uvar
, val
? &uval
: NULL
);
144 ok(nts
== ret
, "Setting var %s=%s (%lx/%lx)\n", var
, val
, nts
, ret
);
145 if (nts
== STATUS_SUCCESS
)
148 uval
.MaximumLength
= sizeof(bval2
);
150 nts
= pRtlQueryEnvironmentVariable_U(*env
, &uvar
, &uval
);
154 ok(strcmpW(bval1
, bval2
) == 0, "Cannot get value written to environment\n");
156 case STATUS_VARIABLE_NOT_FOUND
:
157 ok(val
== NULL
, "Couldn't find variable, but didn't delete it. val = %s\n", val
);
160 ok(0, "Wrong ret %lu for %s\n", nts
, var
);
166 static void testSet(void)
172 ok(pRtlCreateEnvironment(FALSE
, &env
) == STATUS_SUCCESS
, "Creating environment\n");
173 memmove(env
, small_env
, sizeof(small_env
));
175 testSetHelper(&env
, "cat", "dog", STATUS_SUCCESS
);
176 testSetHelper(&env
, "cat", "horse", STATUS_SUCCESS
);
177 testSetHelper(&env
, "cat", "zz", STATUS_SUCCESS
);
178 testSetHelper(&env
, "cat", NULL
, STATUS_SUCCESS
);
179 testSetHelper(&env
, "cat", NULL
, STATUS_VARIABLE_NOT_FOUND
);
180 testSetHelper(&env
, "foo", "meouw", STATUS_SUCCESS
);
181 testSetHelper(&env
, "me=too", "also", STATUS_INVALID_PARAMETER
);
182 testSetHelper(&env
, "me", "too=also", STATUS_SUCCESS
);
183 testSetHelper(&env
, "=too", "also", STATUS_SUCCESS
);
184 testSetHelper(&env
, "=", "also", STATUS_SUCCESS
);
186 for (i
= 0; i
< 128; i
++)
188 sprintf(tmp
, "zork%03d", i
);
189 testSetHelper(&env
, tmp
, "is alive", STATUS_SUCCESS
);
192 for (i
= 0; i
< 128; i
++)
194 sprintf(tmp
, "zork%03d", i
);
195 testSetHelper(&env
, tmp
, NULL
, STATUS_SUCCESS
);
197 testSetHelper(&env
, "fOo", NULL
, STATUS_SUCCESS
);
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 * (troncated) 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: %lu <> %u\n",
246 test
->src
, ul
, strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
));
249 us_dst
.MaximumLength
= sizeof(dst
);
252 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
253 ok(nts
== STATUS_SUCCESS
, "Call failed (%lu)\n", nts
);
254 ok(ul
== us_dst
.Length
+ sizeof(WCHAR
),
255 "Wrong returned length for %s: %lu <> %u\n",
256 test
->src
, ul
, us_dst
.Length
+ sizeof(WCHAR
));
257 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
258 "Wrong returned length for %s: %lu <> %u\n",
259 test
->src
, ul
, strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
));
260 ok(strcmpW(dst
, rst
) == 0, "Wrong result for %s: expecting %s\n",
261 test
->src
, test
->dst
);
264 us_dst
.MaximumLength
= 8 * sizeof(WCHAR
);
267 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
268 ok(nts
== STATUS_BUFFER_TOO_SMALL
, "Call failed (%lu)\n", nts
);
269 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
270 "Wrong returned length for %s (with buffer too small): %lu <> %u\n",
271 test
->src
, ul
, strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
));
272 ok(strncmpW(dst
, rst
, 8) == 0,
273 "Wrong result for %s (with buffer too small): expecting %s\n",
274 test
->src
, test
->dst
);
275 ok(dst
[8] == '-', "Writing too far in buffer (got %c/%d)\n", dst
[8], dst
[8]);
282 HMODULE mod
= GetModuleHandleA("ntdll.dll");
284 pRtlMultiByteToUnicodeN
= (void *)GetProcAddress(mod
,"RtlMultiByteToUnicodeN");
285 pRtlCreateEnvironment
= (void*)GetProcAddress(mod
, "RtlCreateEnvironment");
286 pRtlDestroyEnvironment
= (void*)GetProcAddress(mod
, "RtlDestroyEnvironment");
287 pRtlQueryEnvironmentVariable_U
= (void*)GetProcAddress(mod
, "RtlQueryEnvironmentVariable_U");
288 pRtlSetCurrentEnvironment
= (void*)GetProcAddress(mod
, "RtlSetCurrentEnvironment");
289 pRtlSetEnvironmentVariable
= (void*)GetProcAddress(mod
, "RtlSetEnvironmentVariable");
290 pRtlExpandEnvironmentStrings_U
= (void*)GetProcAddress(mod
, "RtlExpandEnvironmentStrings_U");
292 if (pRtlQueryEnvironmentVariable_U
)
294 if (pRtlSetEnvironmentVariable
)
296 if (pRtlExpandEnvironmentStrings_U
)