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
);
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,
60 static void testQuery(void)
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
, ""},
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;
107 value
.MaximumLength
= test
->len
* 2;
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
)
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
);
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
);
135 static void testSetHelper(LPWSTR
* env
, const char* var
, const char* val
, NTSTATUS ret
, NTSTATUS alt
)
137 WCHAR bvar
[256], bval1
[256], bval2
[256];
142 uvar
.Length
= strlen(var
) * sizeof(WCHAR
);
143 uvar
.MaximumLength
= uvar
.Length
+ sizeof(WCHAR
);
145 pRtlMultiByteToUnicodeN( bvar
, sizeof(bvar
), NULL
, var
, strlen(var
)+1 );
148 uval
.Length
= strlen(val
) * sizeof(WCHAR
);
149 uval
.MaximumLength
= uval
.Length
+ sizeof(WCHAR
);
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
)
158 uval
.MaximumLength
= sizeof(bval2
);
160 nts
= pRtlQueryEnvironmentVariable_U(*env
, &uvar
, &uval
);
164 ok(lstrcmpW(bval1
, bval2
) == 0, "Cannot get value written to environment\n");
166 case STATUS_VARIABLE_NOT_FOUND
:
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
);
172 ok(0, "Wrong ret %u for %s\n", nts
, var
);
178 static void testSet(void)
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
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:
229 * so it seems like strings overflowing the buffer are written
230 * (truncated) but the write cursor is not advanced :-/
235 const struct test
* test
;
237 UNICODE_STRING us_src
, us_dst
;
238 WCHAR src
[256], dst
[256], rst
[256];
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;
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
);
260 us_dst
.MaximumLength
= sizeof(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
);
273 us_dst
.MaximumLength
= 8 * sizeof(WCHAR
);
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
)
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
);
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
;
338 MEMORY_BASIC_INFORMATION info
;
339 NTSTATUS status
= pRtlCreateProcessParameters( ¶ms
, &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
);
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
, ¶ms
->CurrentDirectory
.DosPath
,
379 &cur_params
->CurrentDirectory
.DosPath
, pos
);
380 if (params
->DllPath
.MaximumLength
)
381 pos
= check_string( params
, ¶ms
->DllPath
, &cur_params
->DllPath
, pos
);
383 pos
= check_string( params
, ¶ms
->DllPath
, &null_str
, pos
);
384 pos
= check_string( params
, ¶ms
->ImagePathName
, &image
, pos
);
385 pos
= check_string( params
, ¶ms
->CommandLine
, &image
, pos
);
386 pos
= check_string( params
, ¶ms
->WindowTitle
, &empty_str
, pos
);
387 pos
= check_string( params
, ¶ms
->Desktop
, &empty_str
, pos
);
388 pos
= check_string( params
, ¶ms
->ShellInfo
, &empty_str
, pos
);
389 pos
= check_string( params
, ¶ms
->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
);
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;
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( ¶ms
, &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
);
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
, ¶ms
->CurrentDirectory
.DosPath
, &dummy_dir
, pos
);
437 pos
= check_string( params
, ¶ms
->DllPath
, &dummy
, pos
);
438 pos
= check_string( params
, ¶ms
->ImagePathName
, &image
, pos
);
439 pos
= check_string( params
, ¶ms
->CommandLine
, &dummy
, pos
);
440 pos
= check_string( params
, ¶ms
->WindowTitle
, &dummy
, pos
);
441 pos
= check_string( params
, ¶ms
->Desktop
, &dummy
, pos
);
442 pos
= check_string( params
, ¶ms
->ShellInfo
, &dummy
, pos
);
443 pos
= check_string( params
, ¶ms
->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
);
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;
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
);
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 */
493 if (pos
- (UINT_PTR
)cur_params
< cur_params
->Size
)
495 while (*str
) str
+= lstrlenW(str
) + 1;
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
)
509 ok( broken(TRUE
), "env not a heap block %p / %p\n", cur_params
, initial_env
); /* winxp */
513 size
= HeapSize( GetProcessHeap(), 0, initial_env
);
514 ok( size
!= ~0UL, "env is not a heap block %p / %p\n", cur_params
, initial_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");
537 test_process_params();