usp10/tests: A spelling fix in an ok() message.
[wine.git] / dlls / ntdll / tests / env.c
blob4e2ef8222de6f8c12a6235b131f4e436f9bbccb6
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
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);
33 static NTSTATUS (WINAPI *pRtlCreateProcessParameters)(RTL_USER_PROCESS_PARAMETERS**,
34 const UNICODE_STRING*, const UNICODE_STRING*,
35 const UNICODE_STRING*, const UNICODE_STRING*,
36 PWSTR, const UNICODE_STRING*, const UNICODE_STRING*,
37 const UNICODE_STRING*, const UNICODE_STRING*);
38 static void (WINAPI *pRtlDestroyProcessParameters)(RTL_USER_PROCESS_PARAMETERS *);
40 static void *initial_env;
42 static WCHAR small_env[] = {'f','o','o','=','t','o','t','o',0,
43 'f','o','=','t','i','t','i',0,
44 'f','o','o','o','=','t','u','t','u',0,
45 's','r','=','a','n','=','o','u','o',0,
46 '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',
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',
55 '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,
56 '=','o','O','H','=','I','I','I',0,
57 'n','u','l','=',0,
58 0};
60 static void testQuery(void)
62 struct test
64 const char *var;
65 int len;
66 NTSTATUS status;
67 const char *val;
68 NTSTATUS alt;
71 static const struct test tests[] =
73 {"foo", 256, STATUS_SUCCESS, "toto"},
74 {"FoO", 256, STATUS_SUCCESS, "toto"},
75 {"foo=", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
76 {"foo ", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
77 {"foo", 1, STATUS_BUFFER_TOO_SMALL, "toto"},
78 {"foo", 3, STATUS_BUFFER_TOO_SMALL, "toto"},
79 {"foo", 4, STATUS_SUCCESS, "toto", STATUS_BUFFER_TOO_SMALL},
80 {"foo", 5, STATUS_SUCCESS, "toto"},
81 {"fooo", 256, STATUS_SUCCESS, "tutu"},
82 {"f", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
83 {"g", 256, STATUS_SUCCESS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
84 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
85 {"sr=an", 256, STATUS_SUCCESS, "ouo", STATUS_VARIABLE_NOT_FOUND},
86 {"sr", 256, STATUS_SUCCESS, "an=ouo"},
87 {"=oOH", 256, STATUS_SUCCESS, "III"},
88 {"", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
89 {"nul", 256, STATUS_SUCCESS, ""},
90 {NULL, 0, 0, NULL}
93 WCHAR bn[257];
94 WCHAR bv[257];
95 UNICODE_STRING name;
96 UNICODE_STRING value;
97 NTSTATUS nts;
98 unsigned int i;
100 for (i = 0; tests[i].var; i++)
102 const struct test *test = &tests[i];
103 name.Length = strlen(test->var) * 2;
104 name.MaximumLength = name.Length + 2;
105 name.Buffer = bn;
106 value.Length = 0;
107 value.MaximumLength = test->len * 2;
108 value.Buffer = bv;
109 bv[test->len] = '@';
111 pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->var, strlen(test->var)+1 );
112 nts = pRtlQueryEnvironmentVariable_U(small_env, &name, &value);
113 ok( nts == test->status || (test->alt && nts == test->alt),
114 "[%d]: Wrong status for '%s', expecting %x got %x\n",
115 i, test->var, test->status, nts );
116 if (nts == test->status) switch (nts)
118 case STATUS_SUCCESS:
119 pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->val, strlen(test->val)+1 );
120 ok( value.Length == strlen(test->val) * sizeof(WCHAR), "Wrong length %d for %s\n",
121 value.Length, test->var );
122 ok((value.Length == strlen(test->val) * sizeof(WCHAR) && memcmp(bv, bn, value.Length) == 0) ||
123 lstrcmpW(bv, bn) == 0,
124 "Wrong result for %s/%d\n", test->var, test->len);
125 ok(bv[test->len] == '@', "Writing too far away in the buffer for %s/%d\n", test->var, test->len);
126 break;
127 case STATUS_BUFFER_TOO_SMALL:
128 ok( value.Length == strlen(test->val) * sizeof(WCHAR),
129 "Wrong returned length %d (too small buffer) for %s\n", value.Length, test->var );
130 break;
135 static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATUS ret, NTSTATUS alt)
137 WCHAR bvar[256], bval1[256], bval2[256];
138 UNICODE_STRING uvar;
139 UNICODE_STRING uval;
140 NTSTATUS nts;
142 uvar.Length = strlen(var) * sizeof(WCHAR);
143 uvar.MaximumLength = uvar.Length + sizeof(WCHAR);
144 uvar.Buffer = bvar;
145 pRtlMultiByteToUnicodeN( bvar, sizeof(bvar), NULL, var, strlen(var)+1 );
146 if (val)
148 uval.Length = strlen(val) * sizeof(WCHAR);
149 uval.MaximumLength = uval.Length + sizeof(WCHAR);
150 uval.Buffer = bval1;
151 pRtlMultiByteToUnicodeN( bval1, sizeof(bval1), NULL, val, strlen(val)+1 );
153 nts = pRtlSetEnvironmentVariable(env, &uvar, val ? &uval : NULL);
154 ok(nts == ret || (alt && nts == alt), "Setting var %s=%s (%x/%x)\n", var, val, nts, ret);
155 if (nts == STATUS_SUCCESS)
157 uval.Length = 0;
158 uval.MaximumLength = sizeof(bval2);
159 uval.Buffer = bval2;
160 nts = pRtlQueryEnvironmentVariable_U(*env, &uvar, &uval);
161 switch (nts)
163 case STATUS_SUCCESS:
164 ok(lstrcmpW(bval1, bval2) == 0, "Cannot get value written to environment\n");
165 break;
166 case STATUS_VARIABLE_NOT_FOUND:
167 ok(val == NULL ||
168 broken(strchr(var,'=') != NULL), /* variable containing '=' may be set but not found again on NT4 */
169 "Couldn't find variable, but didn't delete it. val = %s\n", val);
170 break;
171 default:
172 ok(0, "Wrong ret %u for %s\n", nts, var);
173 break;
178 static void testSet(void)
180 LPWSTR env;
181 char tmp[16];
182 int i;
184 ok(pRtlCreateEnvironment(FALSE, &env) == STATUS_SUCCESS, "Creating environment\n");
186 testSetHelper(&env, "cat", "dog", STATUS_SUCCESS, 0);
187 testSetHelper(&env, "cat", "horse", STATUS_SUCCESS, 0);
188 testSetHelper(&env, "cat", "zz", STATUS_SUCCESS, 0);
189 testSetHelper(&env, "cat", NULL, STATUS_SUCCESS, 0);
190 testSetHelper(&env, "cat", NULL, STATUS_SUCCESS, STATUS_VARIABLE_NOT_FOUND);
191 testSetHelper(&env, "foo", "meouw", STATUS_SUCCESS, 0);
192 testSetHelper(&env, "me=too", "also", STATUS_SUCCESS, STATUS_INVALID_PARAMETER);
193 testSetHelper(&env, "me", "too=also", STATUS_SUCCESS, 0);
194 testSetHelper(&env, "=too", "also", STATUS_SUCCESS, 0);
195 testSetHelper(&env, "=", "also", STATUS_SUCCESS, 0);
197 for (i = 0; i < 128; i++)
199 sprintf(tmp, "zork%03d", i);
200 testSetHelper(&env, tmp, "is alive", STATUS_SUCCESS, 0);
203 for (i = 0; i < 128; i++)
205 sprintf(tmp, "zork%03d", i);
206 testSetHelper(&env, tmp, NULL, STATUS_SUCCESS, 0);
208 testSetHelper(&env, "fOo", NULL, STATUS_SUCCESS, 0);
210 ok(pRtlDestroyEnvironment(env) == STATUS_SUCCESS, "Destroying environment\n");
213 static void testExpand(void)
215 static const struct test
217 const char *src;
218 const char *dst;
219 } tests[] =
221 {"hello%foo%world", "hellototoworld"},
222 {"hello%=oOH%world", "helloIIIworld"},
223 {"hello%foo", "hello%foo"},
224 {"hello%bar%world", "hello%bar%world"},
226 * {"hello%foo%world%=oOH%eeck", "hellototoworldIIIeeck"},
227 * Interestingly enough, with a 8 WCHAR buffers, we get on 2k:
228 * helloIII
229 * so it seems like strings overflowing the buffer are written
230 * (truncated) but the write cursor is not advanced :-/
232 {NULL, NULL}
235 const struct test* test;
236 NTSTATUS nts;
237 UNICODE_STRING us_src, us_dst;
238 WCHAR src[256], dst[256], rst[256];
239 ULONG ul;
241 for (test = tests; test->src; test++)
243 pRtlMultiByteToUnicodeN(src, sizeof(src), NULL, test->src, strlen(test->src)+1);
244 pRtlMultiByteToUnicodeN(rst, sizeof(rst), NULL, test->dst, strlen(test->dst)+1);
246 us_src.Length = strlen(test->src) * sizeof(WCHAR);
247 us_src.MaximumLength = us_src.Length + 2;
248 us_src.Buffer = src;
250 us_dst.Length = 0;
251 us_dst.MaximumLength = 0;
252 us_dst.Buffer = NULL;
254 nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
255 ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%u)\n", nts);
256 ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
257 "Wrong returned length for %s: %u\n", test->src, ul );
259 us_dst.Length = 0;
260 us_dst.MaximumLength = sizeof(dst);
261 us_dst.Buffer = dst;
263 nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
264 ok(nts == STATUS_SUCCESS, "Call failed (%u)\n", nts);
265 ok(ul == us_dst.Length + sizeof(WCHAR),
266 "Wrong returned length for %s: %u\n", test->src, ul);
267 ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
268 "Wrong returned length for %s: %u\n", test->src, ul);
269 ok(lstrcmpW(dst, rst) == 0, "Wrong result for %s: expecting %s\n",
270 test->src, test->dst);
272 us_dst.Length = 0;
273 us_dst.MaximumLength = 8 * sizeof(WCHAR);
274 us_dst.Buffer = dst;
275 dst[8] = '-';
276 nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
277 ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%u)\n", nts);
278 ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
279 "Wrong returned length for %s (with buffer too small): %u\n", test->src, ul);
280 ok(dst[8] == '-', "Writing too far in buffer (got %c/%d)\n", dst[8], dst[8]);
285 static WCHAR *get_params_string( RTL_USER_PROCESS_PARAMETERS *params, UNICODE_STRING *str )
287 if (params->Flags & PROCESS_PARAMS_FLAG_NORMALIZED) return str->Buffer;
288 return (WCHAR *)((char *)params + (UINT_PTR)str->Buffer);
291 static UINT_PTR check_string_( int line, RTL_USER_PROCESS_PARAMETERS *params, UNICODE_STRING *str,
292 const UNICODE_STRING *expect, UINT_PTR pos )
294 if (expect)
296 ok_(__FILE__,line)( str->Length == expect->Length, "wrong length %u/%u\n",
297 str->Length, expect->Length );
298 ok_(__FILE__,line)( str->MaximumLength == expect->MaximumLength ||
299 broken( str->MaximumLength == 1 && expect->MaximumLength == 2 ), /* winxp */
300 "wrong maxlength %u/%u\n", str->MaximumLength, expect->MaximumLength );
302 if (!str->MaximumLength)
304 ok_(__FILE__,line)( str->Buffer == NULL, "buffer not null %p\n", str->Buffer );
305 return pos;
307 ok_(__FILE__,line)( (UINT_PTR)str->Buffer == ((pos + sizeof(void*) - 1) & ~(sizeof(void *) - 1)) ||
308 (!expect && (UINT_PTR)str->Buffer == pos) || /* initial params are not aligned */
309 broken( (UINT_PTR)str->Buffer == ((pos + 3) & ~3) ), "wrong buffer %lx/%lx\n",
310 (UINT_PTR)str->Buffer, pos );
311 if (str->Length < str->MaximumLength)
313 WCHAR *ptr = get_params_string( params, str );
314 ok_(__FILE__,line)( !ptr[str->Length / sizeof(WCHAR)], "string not null-terminated %s\n",
315 wine_dbgstr_wn( ptr, str->MaximumLength / sizeof(WCHAR) ));
317 return (UINT_PTR)str->Buffer + str->MaximumLength;
319 #define check_string(params,str,expect,pos) check_string_(__LINE__,params,str,expect,pos)
321 static void test_process_params(void)
323 static WCHAR empty[] = {0};
324 static const UNICODE_STRING empty_str = { 0, sizeof(empty), empty };
325 static const UNICODE_STRING null_str = { 0, 0, NULL };
326 static WCHAR exeW[] = {'c',':','\\','f','o','o','.','e','x','e',0};
327 static WCHAR dummyW[] = {'d','u','m','m','y','1',0};
328 static WCHAR dummy_dirW[MAX_PATH] = {'d','u','m','m','y','2',0};
329 static WCHAR dummy_env[] = {'a','=','b',0,'c','=','d',0,0};
330 UNICODE_STRING image = { sizeof(exeW) - sizeof(WCHAR), sizeof(exeW), exeW };
331 UNICODE_STRING dummy = { sizeof(dummyW) - sizeof(WCHAR), sizeof(dummyW), dummyW };
332 UNICODE_STRING dummy_dir = { 6*sizeof(WCHAR), sizeof(dummy_dirW), dummy_dirW };
333 RTL_USER_PROCESS_PARAMETERS *params = NULL;
334 RTL_USER_PROCESS_PARAMETERS *cur_params = NtCurrentTeb()->Peb->ProcessParameters;
335 SIZE_T size;
336 WCHAR *str;
337 UINT_PTR pos;
338 MEMORY_BASIC_INFORMATION info;
339 NTSTATUS status = pRtlCreateProcessParameters( &params, &image, NULL, NULL, NULL, NULL,
340 NULL, NULL, NULL, NULL );
341 ok( !status, "failed %x\n", status );
342 if (VirtualQuery( params, &info, sizeof(info) ) && info.AllocationBase == params)
344 size = info.RegionSize;
345 ok( broken(TRUE), "not a heap block %p\n", params ); /* winxp */
346 ok( params->AllocationSize == info.RegionSize,
347 "wrong AllocationSize %x/%lx\n", params->AllocationSize, info.RegionSize );
349 else
351 size = HeapSize( GetProcessHeap(), 0, params );
352 ok( size != ~0UL, "not a heap block %p\n", params );
353 ok( params->AllocationSize == params->Size,
354 "wrong AllocationSize %x/%x\n", params->AllocationSize, params->Size );
356 ok( params->Size < size || broken(params->Size == size), /* <= win2k3 */
357 "wrong Size %x/%lx\n", params->Size, size );
358 ok( params->Flags == 0, "wrong Flags %u\n", params->Flags );
359 ok( params->DebugFlags == 0, "wrong Flags %u\n", params->DebugFlags );
360 ok( params->ConsoleHandle == 0, "wrong ConsoleHandle %p\n", params->ConsoleHandle );
361 ok( params->ConsoleFlags == 0, "wrong ConsoleFlags %u\n", params->ConsoleFlags );
362 ok( params->hStdInput == 0, "wrong hStdInput %p\n", params->hStdInput );
363 ok( params->hStdOutput == 0, "wrong hStdOutput %p\n", params->hStdOutput );
364 ok( params->hStdError == 0, "wrong hStdError %p\n", params->hStdError );
365 ok( params->dwX == 0, "wrong dwX %u\n", params->dwX );
366 ok( params->dwY == 0, "wrong dwY %u\n", params->dwY );
367 ok( params->dwXSize == 0, "wrong dwXSize %u\n", params->dwXSize );
368 ok( params->dwYSize == 0, "wrong dwYSize %u\n", params->dwYSize );
369 ok( params->dwXCountChars == 0, "wrong dwXCountChars %u\n", params->dwXCountChars );
370 ok( params->dwYCountChars == 0, "wrong dwYCountChars %u\n", params->dwYCountChars );
371 ok( params->dwFillAttribute == 0, "wrong dwFillAttribute %u\n", params->dwFillAttribute );
372 ok( params->dwFlags == 0, "wrong dwFlags %u\n", params->dwFlags );
373 ok( params->wShowWindow == 0, "wrong wShowWindow %u\n", params->wShowWindow );
374 pos = (UINT_PTR)params->CurrentDirectory.DosPath.Buffer;
376 ok( params->CurrentDirectory.DosPath.MaximumLength == MAX_PATH * sizeof(WCHAR),
377 "wrong length %x\n", params->CurrentDirectory.DosPath.MaximumLength );
378 pos = check_string( params, &params->CurrentDirectory.DosPath,
379 &cur_params->CurrentDirectory.DosPath, pos );
380 if (params->DllPath.MaximumLength)
381 pos = check_string( params, &params->DllPath, &cur_params->DllPath, pos );
382 else
383 pos = check_string( params, &params->DllPath, &null_str, pos );
384 pos = check_string( params, &params->ImagePathName, &image, pos );
385 pos = check_string( params, &params->CommandLine, &image, pos );
386 pos = check_string( params, &params->WindowTitle, &empty_str, pos );
387 pos = check_string( params, &params->Desktop, &empty_str, pos );
388 pos = check_string( params, &params->ShellInfo, &empty_str, pos );
389 pos = check_string( params, &params->RuntimeInfo, &null_str, pos );
390 pos = (pos + 3) & ~3;
391 ok( pos == params->Size || pos + 4 == params->Size,
392 "wrong pos %lx/%x\n", pos, params->Size );
393 pos = params->Size;
394 if ((char *)params->Environment > (char *)params &&
395 (char *)params->Environment < (char *)params + size)
397 ok( (char *)params->Environment - (char *)params == (UINT_PTR)pos,
398 "wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos);
399 str = params->Environment;
400 while (*str) str += lstrlenW(str) + 1;
401 str++;
402 pos += (str - params->Environment) * sizeof(WCHAR);
403 ok( ((pos + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) == size ||
404 broken( ((pos + 3) & ~3) == size ), "wrong size %lx/%lx\n", pos, size );
406 else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */
407 pRtlDestroyProcessParameters( params );
409 status = pRtlCreateProcessParameters( &params, &image, &dummy, &dummy, &dummy, dummy_env,
410 &dummy, &dummy, &dummy, &dummy );
411 ok( !status, "failed %x\n", status );
412 if (VirtualQuery( params, &info, sizeof(info) ) && info.AllocationBase == params)
414 size = info.RegionSize;
415 ok( broken(TRUE), "not a heap block %p\n", params ); /* winxp */
416 ok( params->AllocationSize == info.RegionSize,
417 "wrong AllocationSize %x/%lx\n", params->AllocationSize, info.RegionSize );
419 else
421 size = HeapSize( GetProcessHeap(), 0, params );
422 ok( size != ~0UL, "not a heap block %p\n", params );
423 ok( params->AllocationSize == params->Size,
424 "wrong AllocationSize %x/%x\n", params->AllocationSize, params->Size );
426 ok( params->Size < size || broken(params->Size == size), /* <= win2k3 */
427 "wrong Size %x/%lx\n", params->Size, size );
428 pos = (UINT_PTR)params->CurrentDirectory.DosPath.Buffer;
430 if (params->CurrentDirectory.DosPath.Length == dummy_dir.Length + sizeof(WCHAR))
432 /* win10 appends a backslash */
433 dummy_dirW[dummy_dir.Length / sizeof(WCHAR)] = '\\';
434 dummy_dir.Length += sizeof(WCHAR);
436 pos = check_string( params, &params->CurrentDirectory.DosPath, &dummy_dir, pos );
437 pos = check_string( params, &params->DllPath, &dummy, pos );
438 pos = check_string( params, &params->ImagePathName, &image, pos );
439 pos = check_string( params, &params->CommandLine, &dummy, pos );
440 pos = check_string( params, &params->WindowTitle, &dummy, pos );
441 pos = check_string( params, &params->Desktop, &dummy, pos );
442 pos = check_string( params, &params->ShellInfo, &dummy, pos );
443 pos = check_string( params, &params->RuntimeInfo, &dummy, pos );
444 pos = (pos + 3) & ~3;
445 ok( pos == params->Size || pos + 4 == params->Size,
446 "wrong pos %lx/%x\n", pos, params->Size );
447 pos = params->Size;
448 if ((char *)params->Environment > (char *)params &&
449 (char *)params->Environment < (char *)params + size)
451 ok( (char *)params->Environment - (char *)params == pos,
452 "wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos);
453 str = params->Environment;
454 while (*str) str += lstrlenW(str) + 1;
455 str++;
456 pos += (str - params->Environment) * sizeof(WCHAR);
457 ok( ((pos + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) == size ||
458 broken( ((pos + 3) & ~3) == size ), "wrong size %lx/%lx\n", pos, size );
460 else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */
461 pRtlDestroyProcessParameters( params );
463 /* also test the actual parameters of the current process */
465 ok( cur_params->Flags & PROCESS_PARAMS_FLAG_NORMALIZED, "current params not normalized\n" );
466 if (VirtualQuery( cur_params, &info, sizeof(info) ) && info.AllocationBase == cur_params)
468 ok( broken(TRUE), "not a heap block %p\n", cur_params ); /* winxp */
469 ok( cur_params->AllocationSize == info.RegionSize,
470 "wrong AllocationSize %x/%lx\n", cur_params->AllocationSize, info.RegionSize );
472 else
474 size = HeapSize( GetProcessHeap(), 0, cur_params );
475 ok( size != ~0UL, "not a heap block %p\n", cur_params );
476 ok( cur_params->AllocationSize == cur_params->Size,
477 "wrong AllocationSize %x/%x\n", cur_params->AllocationSize, cur_params->Size );
478 ok( cur_params->Size == size, "wrong Size %x/%lx\n", cur_params->Size, size );
481 /* CurrentDirectory points outside the params, and DllPath may be null */
482 pos = (UINT_PTR)cur_params->DllPath.Buffer;
483 if (!pos) pos = (UINT_PTR)cur_params->ImagePathName.Buffer;
484 pos = check_string( cur_params, &cur_params->DllPath, NULL, pos );
485 pos = check_string( cur_params, &cur_params->ImagePathName, NULL, pos );
486 pos = check_string( cur_params, &cur_params->CommandLine, NULL, pos );
487 pos = check_string( cur_params, &cur_params->WindowTitle, NULL, pos );
488 pos = check_string( cur_params, &cur_params->Desktop, NULL, pos );
489 pos = check_string( cur_params, &cur_params->ShellInfo, NULL, pos );
490 pos = check_string( cur_params, &cur_params->RuntimeInfo, NULL, pos );
491 /* environment may follow */
492 str = (WCHAR *)pos;
493 if (pos - (UINT_PTR)cur_params < cur_params->Size)
495 while (*str) str += lstrlenW(str) + 1;
496 str++;
498 ok( (char *)str == (char *)cur_params + cur_params->Size,
499 "wrong end ptr %p/%p\n", str, (char *)cur_params + cur_params->Size );
501 /* initial environment is a separate block */
503 ok( (char *)initial_env < (char *)cur_params || (char *)initial_env >= (char *)cur_params + size,
504 "initial environment inside block %p / %p\n", cur_params, initial_env );
506 if (VirtualQuery( initial_env, &info, sizeof(info) ) && info.AllocationBase == initial_env)
508 todo_wine
509 ok( broken(TRUE), "env not a heap block %p / %p\n", cur_params, initial_env ); /* winxp */
511 else
513 size = HeapSize( GetProcessHeap(), 0, initial_env );
514 ok( size != ~0UL, "env is not a heap block %p / %p\n", cur_params, initial_env );
518 START_TEST(env)
520 HMODULE mod = GetModuleHandleA("ntdll.dll");
522 initial_env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
524 pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN");
525 pRtlCreateEnvironment = (void*)GetProcAddress(mod, "RtlCreateEnvironment");
526 pRtlDestroyEnvironment = (void*)GetProcAddress(mod, "RtlDestroyEnvironment");
527 pRtlQueryEnvironmentVariable_U = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable_U");
528 pRtlSetCurrentEnvironment = (void*)GetProcAddress(mod, "RtlSetCurrentEnvironment");
529 pRtlSetEnvironmentVariable = (void*)GetProcAddress(mod, "RtlSetEnvironmentVariable");
530 pRtlExpandEnvironmentStrings_U = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings_U");
531 pRtlCreateProcessParameters = (void*)GetProcAddress(mod, "RtlCreateProcessParameters");
532 pRtlDestroyProcessParameters = (void*)GetProcAddress(mod, "RtlDestroyProcessParameters");
534 testQuery();
535 testSet();
536 testExpand();
537 test_process_params();