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 "wine/test.h"
30 #include "wine/unicode.h"
32 static NTSTATUS (WINAPI
*pRtlMultiByteToUnicodeN
)( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
33 LPCSTR src
, DWORD srclen
);
34 static NTSTATUS (WINAPI
*pRtlCreateEnvironment
)(BOOLEAN
, PWSTR
*);
35 static NTSTATUS (WINAPI
*pRtlDestroyEnvironment
)(PWSTR
);
36 static NTSTATUS (WINAPI
*pRtlQueryEnvironmentVariable_U
)(PWSTR
, PUNICODE_STRING
, PUNICODE_STRING
);
37 static void (WINAPI
*pRtlSetCurrentEnvironment
)(PWSTR
, PWSTR
*);
38 static NTSTATUS (WINAPI
*pRtlSetEnvironmentVariable
)(PWSTR
*, PUNICODE_STRING
, PUNICODE_STRING
);
39 static NTSTATUS (WINAPI
*pRtlExpandEnvironmentStrings_U
)(LPWSTR
, PUNICODE_STRING
, PUNICODE_STRING
, PULONG
);
41 static WCHAR small_env
[] = {'f','o','o','=','t','o','t','o',0,
42 'f','o','=','t','i','t','i',0,
43 'f','o','o','o','=','t','u','t','u',0,
44 's','r','=','a','n','=','o','u','o',0,
45 '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',
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',
49 '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',
50 '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',
51 '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',
52 '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',
53 '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',
54 '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,
55 '=','o','O','H','=','I','I','I',0,
59 static void testQuery(void)
69 static const struct test tests
[] =
71 {"foo", 256, STATUS_SUCCESS
, "toto"},
72 {"FoO", 256, STATUS_SUCCESS
, "toto"},
73 {"foo=", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
74 {"foo ", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
75 {"foo", 1, STATUS_BUFFER_TOO_SMALL
, "toto"},
76 {"foo", 3, STATUS_BUFFER_TOO_SMALL
, "toto"},
77 {"foo", 4, STATUS_SUCCESS
, "toto"},
78 {"fooo", 256, STATUS_SUCCESS
, "tutu"},
79 {"f", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
80 {"g", 256, STATUS_SUCCESS
, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
81 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
82 {"sr=an", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
83 {"sr", 256, STATUS_SUCCESS
, "an=ouo"},
84 {"=oOH", 256, STATUS_SUCCESS
, "III"},
85 {"", 256, STATUS_VARIABLE_NOT_FOUND
, NULL
},
86 {"nul", 256, STATUS_SUCCESS
, ""},
94 const struct test
* test
;
97 for (test
= tests
; test
->var
; test
++)
99 name
.Length
= strlen(test
->var
) * 2;
100 name
.MaximumLength
= name
.Length
+ 2;
103 value
.MaximumLength
= test
->len
* 2;
107 pRtlMultiByteToUnicodeN( bn
, sizeof(bn
), NULL
, test
->var
, strlen(test
->var
)+1 );
108 nts
= pRtlQueryEnvironmentVariable_U(small_env
, &name
, &value
);
109 ok( nts
== test
->status
, "[%d]: Wrong status for '%s', expecting %lx got %lx\n",
110 test
- tests
, test
->var
, test
->status
, nts
);
111 if (nts
== test
->status
) switch (nts
)
114 pRtlMultiByteToUnicodeN( bn
, sizeof(bn
), NULL
, test
->val
, strlen(test
->val
)+1 );
115 ok( value
.Length
== strlen(test
->val
) * sizeof(WCHAR
), "Wrong length %d/%d for %s\n",
116 value
.Length
, strlen(test
->val
) * sizeof(WCHAR
), test
->var
);
117 ok((value
.Length
== strlen(test
->val
) * sizeof(WCHAR
) && strncmpW(bv
, bn
, test
->len
) == 0) ||
118 strcmpW(bv
, bn
) == 0,
119 "Wrong result for %s/%d\n", test
->var
, test
->len
);
120 ok(bv
[test
->len
] == '@', "Writing too far away in the buffer for %s/%d\n", test
->var
, test
->len
);
122 case STATUS_BUFFER_TOO_SMALL
:
123 ok( value
.Length
== strlen(test
->val
) * sizeof(WCHAR
),
124 "Wrong returned length %d/%d (too small buffer) for %s\n",
125 value
.Length
, strlen(test
->val
) * sizeof(WCHAR
), test
->var
);
131 static void testSetHelper(LPWSTR
* env
, const char* var
, const char* val
, NTSTATUS ret
)
133 WCHAR bvar
[256], bval1
[256], bval2
[256];
138 uvar
.Length
= strlen(var
) * sizeof(WCHAR
);
139 uvar
.MaximumLength
= uvar
.Length
+ sizeof(WCHAR
);
141 pRtlMultiByteToUnicodeN( bvar
, sizeof(bvar
), NULL
, var
, strlen(var
)+1 );
144 uval
.Length
= strlen(val
) * sizeof(WCHAR
);
145 uval
.MaximumLength
= uval
.Length
+ sizeof(WCHAR
);
147 pRtlMultiByteToUnicodeN( bval1
, sizeof(bval1
), NULL
, val
, strlen(val
)+1 );
149 nts
= pRtlSetEnvironmentVariable(env
, &uvar
, val
? &uval
: NULL
);
150 ok(nts
== ret
, "Setting var %s=%s (%lx/%lx)\n", var
, val
, nts
, ret
);
151 if (nts
== STATUS_SUCCESS
)
154 uval
.MaximumLength
= sizeof(bval2
);
156 nts
= pRtlQueryEnvironmentVariable_U(*env
, &uvar
, &uval
);
160 ok(strcmpW(bval1
, bval2
) == 0, "Cannot get value written to environment\n");
162 case STATUS_VARIABLE_NOT_FOUND
:
163 ok(val
== NULL
, "Couldn't find variable, but didn't delete it\n");
166 ok(0, "Wrong ret %lu for %s\n", nts
, var
);
172 static void testSet(void)
178 ok(pRtlCreateEnvironment(FALSE
, &env
) == STATUS_SUCCESS
, "Creating environment\n");
179 memmove(env
, small_env
, sizeof(small_env
));
181 testSetHelper(&env
, "cat", "dog", STATUS_SUCCESS
);
182 testSetHelper(&env
, "cat", "horse", STATUS_SUCCESS
);
183 testSetHelper(&env
, "cat", "zz", STATUS_SUCCESS
);
184 testSetHelper(&env
, "cat", NULL
, STATUS_SUCCESS
);
185 testSetHelper(&env
, "cat", NULL
, STATUS_VARIABLE_NOT_FOUND
);
186 testSetHelper(&env
, "foo", "meouw", STATUS_SUCCESS
);
187 testSetHelper(&env
, "me=too", "also", STATUS_INVALID_PARAMETER
);
188 testSetHelper(&env
, "me", "too=also", STATUS_SUCCESS
);
189 testSetHelper(&env
, "=too", "also", STATUS_SUCCESS
);
190 testSetHelper(&env
, "=", "also", STATUS_SUCCESS
);
192 for (i
= 0; i
< 128; i
++)
194 sprintf(tmp
, "zork%03d", i
);
195 testSetHelper(&env
, tmp
, "is alive", STATUS_SUCCESS
);
198 for (i
= 0; i
< 128; i
++)
200 sprintf(tmp
, "zork%03d", i
);
201 testSetHelper(&env
, tmp
, NULL
, STATUS_SUCCESS
);
203 testSetHelper(&env
, "fOo", NULL
, STATUS_SUCCESS
);
205 ok(pRtlDestroyEnvironment(env
) == STATUS_SUCCESS
, "Destroying environment\n");
208 static void testExpand(void)
210 static const struct test
216 {"hello%foo%world", "hellototoworld"},
217 {"hello%=oOH%world", "helloIIIworld"},
218 {"hello%foo", "hello%foo"},
219 {"hello%bar%world", "hello%bar%world"},
221 * {"hello%foo%world%=oOH%eeck", "hellototoworldIIIeeck"},
222 * Interestingly enough, with a 8 WCHAR buffers, we get on 2k:
224 * so it seems like strings overflowing the buffer are written
225 * (troncated) but the write cursor is not advanced :-/
230 const struct test
* test
;
232 UNICODE_STRING us_src
, us_dst
;
233 WCHAR src
[256], dst
[256], rst
[256];
236 for (test
= tests
; test
->src
; test
++)
238 pRtlMultiByteToUnicodeN(src
, sizeof(src
), NULL
, test
->src
, strlen(test
->src
)+1);
239 pRtlMultiByteToUnicodeN(rst
, sizeof(rst
), NULL
, test
->dst
, strlen(test
->dst
)+1);
241 us_src
.Length
= strlen(test
->src
) * sizeof(WCHAR
);
242 us_src
.MaximumLength
= us_src
.Length
+ 2;
246 us_dst
.MaximumLength
= 0;
247 us_dst
.Buffer
= NULL
;
249 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
250 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
251 "Wrong returned length for %s: %lu <> %u\n",
252 test
->src
, ul
, strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
));
255 us_dst
.MaximumLength
= sizeof(dst
);
258 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
259 ok(nts
== STATUS_SUCCESS
, "Call failed (%lu)\n", nts
);
260 ok(ul
== us_dst
.Length
+ sizeof(WCHAR
),
261 "Wrong returned length for %s: %lu <> %u\n",
262 test
->src
, ul
, us_dst
.Length
+ sizeof(WCHAR
));
263 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
264 "Wrong returned length for %s: %lu <> %u\n",
265 test
->src
, ul
, strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
));
266 ok(strcmpW(dst
, rst
) == 0, "Wrong result for %s: expecting %s\n",
267 test
->src
, test
->dst
);
270 us_dst
.MaximumLength
= 8 * sizeof(WCHAR
);
273 nts
= pRtlExpandEnvironmentStrings_U(small_env
, &us_src
, &us_dst
, &ul
);
274 ok(nts
== STATUS_BUFFER_TOO_SMALL
, "Call failed (%lu)\n", nts
);
275 ok(ul
== strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
),
276 "Wrong returned length for %s (with buffer too small): %lu <> %u\n",
277 test
->src
, ul
, strlen(test
->dst
) * sizeof(WCHAR
) + sizeof(WCHAR
));
278 ok(strncmpW(dst
, rst
, 8) == 0,
279 "Wrong result for %s (with buffer too small): expecting %s\n",
280 test
->src
, test
->dst
);
281 ok(dst
[8] == '-', "Writing too far in buffer (got %c/%d)\n", dst
[8], dst
[8]);
288 HMODULE mod
= GetModuleHandleA("ntdll.dll");
290 pRtlMultiByteToUnicodeN
= (void *)GetProcAddress(mod
,"RtlMultiByteToUnicodeN");
291 pRtlCreateEnvironment
= (void*)GetProcAddress(mod
, "RtlCreateEnvironment");
292 pRtlDestroyEnvironment
= (void*)GetProcAddress(mod
, "RtlDestroyEnvironment");
293 pRtlQueryEnvironmentVariable_U
= (void*)GetProcAddress(mod
, "RtlQueryEnvironmentVariable_U");
294 pRtlSetCurrentEnvironment
= (void*)GetProcAddress(mod
, "RtlSetCurrentEnvironment");
295 pRtlSetEnvironmentVariable
= (void*)GetProcAddress(mod
, "RtlSetEnvironmentVariable");
296 pRtlExpandEnvironmentStrings_U
= (void*)GetProcAddress(mod
, "RtlExpandEnvironmentStrings_U");
298 if (pRtlQueryEnvironmentVariable_U
)
300 if (pRtlSetEnvironmentVariable
)
302 if (pRtlExpandEnvironmentStrings_U
)