Add trailing '\n's to ok() calls.
[wine.git] / dlls / ntdll / tests / env.c
blobfd51938b11d6b2398c8c603a89df4a2ff88a6664
1 /*
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
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include "wine/test.h"
24 #include "ntstatus.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnt.h"
28 #include "winreg.h"
29 #include "winternl.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,
56 'n','u','l','=',0,
57 0};
59 static void testQuery(void)
61 struct test
63 const char *var;
64 int len;
65 NTSTATUS status;
66 const char *val;
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, ""},
87 {NULL, 0, 0, NULL}
90 WCHAR bn[257];
91 WCHAR bv[257];
92 UNICODE_STRING name;
93 UNICODE_STRING value;
94 const struct test* test;
95 NTSTATUS nts;
97 for (test = tests; test->var; test++)
99 name.Length = strlen(test->var) * 2;
100 name.MaximumLength = name.Length + 2;
101 name.Buffer = bn;
102 value.Length = 0;
103 value.MaximumLength = test->len * 2;
104 value.Buffer = bv;
105 bv[test->len] = '@';
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)
113 case STATUS_SUCCESS:
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);
121 break;
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 );
126 break;
131 static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATUS ret)
133 WCHAR bvar[256], bval1[256], bval2[256];
134 UNICODE_STRING uvar;
135 UNICODE_STRING uval;
136 NTSTATUS nts;
138 uvar.Length = strlen(var) * sizeof(WCHAR);
139 uvar.MaximumLength = uvar.Length + sizeof(WCHAR);
140 uvar.Buffer = bvar;
141 pRtlMultiByteToUnicodeN( bvar, sizeof(bvar), NULL, var, strlen(var)+1 );
142 if (val)
144 uval.Length = strlen(val) * sizeof(WCHAR);
145 uval.MaximumLength = uval.Length + sizeof(WCHAR);
146 uval.Buffer = bval1;
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)
153 uval.Length = 0;
154 uval.MaximumLength = sizeof(bval2);
155 uval.Buffer = bval2;
156 nts = pRtlQueryEnvironmentVariable_U(*env, &uvar, &uval);
157 switch (nts)
159 case STATUS_SUCCESS:
160 ok(strcmpW(bval1, bval2) == 0, "Cannot get value written to environment\n");
161 break;
162 case STATUS_VARIABLE_NOT_FOUND:
163 ok(val == NULL, "Couldn't find variable, but didn't delete it\n");
164 break;
165 default:
166 ok(0, "Wrong ret %lu for %s\n", nts, var);
167 break;
172 static void testSet(void)
174 LPWSTR env;
175 char tmp[16];
176 int i;
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
212 const char *src;
213 const char *dst;
214 } tests[] =
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:
223 * helloIII
224 * so it seems like strings overflowing the buffer are written
225 * (troncated) but the write cursor is not advanced :-/
227 {NULL, NULL}
230 const struct test* test;
231 NTSTATUS nts;
232 UNICODE_STRING us_src, us_dst;
233 WCHAR src[256], dst[256], rst[256];
234 ULONG ul;
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;
243 us_src.Buffer = src;
245 us_dst.Length = 0;
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));
254 us_dst.Length = 0;
255 us_dst.MaximumLength = sizeof(dst);
256 us_dst.Buffer = 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);
269 us_dst.Length = 0;
270 us_dst.MaximumLength = 8 * sizeof(WCHAR);
271 us_dst.Buffer = dst;
272 dst[8] = '-';
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]);
286 START_TEST(env)
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)
299 testQuery();
300 if (pRtlSetEnvironmentVariable)
301 testSet();
302 if (pRtlExpandEnvironmentStrings_U)
303 testExpand();