2 * Ntdll environment functions
4 * Copyright 1996, 1998 Alexandre Julliard
5 * Copyright 2003 Eric Pouech
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <sys/types.h>
27 #define WIN32_NO_STATUS
30 #include "wine/debug.h"
31 #include "ntdll_misc.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(environ
);
36 static WCHAR empty
[] = L
"";
37 static const UNICODE_STRING empty_str
= { 0, sizeof(empty
), empty
};
38 static const UNICODE_STRING null_str
= { 0, 0, NULL
};
40 static const BOOL is_win64
= (sizeof(void *) > sizeof(int));
42 static inline SIZE_T
get_env_length( const WCHAR
*env
)
44 const WCHAR
*end
= env
;
45 while (*end
) end
+= wcslen(end
) + 1;
50 /***********************************************************************
51 * set_wow64_environment
53 * Set the environment variables that change across 32/64/Wow64.
55 static void set_wow64_environment( WCHAR
**env
)
58 UNICODE_STRING arch_strW
= RTL_CONSTANT_STRING( L
"PROCESSOR_ARCHITECTURE" );
59 UNICODE_STRING arch6432_strW
= RTL_CONSTANT_STRING( L
"PROCESSOR_ARCHITEW6432" );
60 UNICODE_STRING valW
= { 0, sizeof(buf
), buf
};
63 /* set the PROCESSOR_ARCHITECTURE variable */
65 if (!RtlQueryEnvironmentVariable_U( *env
, &arch6432_strW
, &valW
))
69 RtlSetEnvironmentVariable( env
, &arch_strW
, &valW
);
70 RtlSetEnvironmentVariable( env
, &arch6432_strW
, NULL
);
73 else if (NtCurrentTeb64() && !RtlQueryEnvironmentVariable_U( *env
, &arch_strW
, &valW
))
75 RtlSetEnvironmentVariable( env
, &arch6432_strW
, &valW
);
76 RtlInitUnicodeString( &nameW
, L
"x86" );
77 RtlSetEnvironmentVariable( env
, &arch_strW
, &nameW
);
80 /* set the ProgramFiles variables */
82 RtlInitUnicodeString( &nameW
, is_win64
? L
"ProgramW6432" : L
"ProgramFiles(x86)" );
83 if (!RtlQueryEnvironmentVariable_U( *env
, &nameW
, &valW
))
85 RtlInitUnicodeString( &nameW
, L
"ProgramFiles" );
86 RtlSetEnvironmentVariable( env
, &nameW
, &valW
);
89 /* set the CommonProgramFiles variables */
91 RtlInitUnicodeString( &nameW
, is_win64
? L
"CommonProgramW6432" : L
"CommonProgramFiles(x86)" );
92 if (!RtlQueryEnvironmentVariable_U( *env
, &nameW
, &valW
))
94 RtlInitUnicodeString( &nameW
, L
"CommonProgramFiles" );
95 RtlSetEnvironmentVariable( env
, &nameW
, &valW
);
98 RtlReAllocateHeap( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY
, *env
,
99 get_env_length(*env
) * sizeof(WCHAR
) );
103 /******************************************************************************
104 * RtlCreateEnvironment [NTDLL.@]
106 NTSTATUS WINAPI
RtlCreateEnvironment(BOOLEAN inherit
, PWSTR
* env
)
110 TRACE("(%u,%p)!\n", inherit
, env
);
115 size
= get_env_length( NtCurrentTeb()->Peb
->ProcessParameters
->Environment
) * sizeof(WCHAR
);
116 if ((*env
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
117 memcpy( *env
, NtCurrentTeb()->Peb
->ProcessParameters
->Environment
, size
);
120 else *env
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WCHAR
) );
122 return *env
? STATUS_SUCCESS
: STATUS_NO_MEMORY
;
125 /******************************************************************************
126 * RtlDestroyEnvironment [NTDLL.@]
128 NTSTATUS WINAPI
RtlDestroyEnvironment(PWSTR env
)
130 RtlFreeHeap( GetProcessHeap(), 0, env
);
131 return STATUS_SUCCESS
;
134 static LPCWSTR
ENV_FindVariable(PCWSTR var
, PCWSTR name
, unsigned namelen
)
138 /* match var names, but avoid setting a var with a name including a '='
139 * (a starting '=' is valid though)
141 unsigned int len
= wcslen( var
);
143 var
[namelen
] == '=' &&
144 !RtlCompareUnicodeStrings( var
, namelen
, name
, namelen
, TRUE
) &&
145 wcschr(var
+ 1, '=') == var
+ namelen
)
147 return var
+ namelen
+ 1;
154 /******************************************************************
155 * RtlQueryEnvironmentVariable_U [NTDLL.@]
157 * NOTES: when the buffer is too small, the string is not written, but if the
158 * terminating null char is the only char that cannot be written, then
159 * all chars (except the null) are written and success is returned
160 * (behavior of Win2k at least)
162 NTSTATUS WINAPI
RtlQueryEnvironmentVariable_U(PWSTR env
,
163 PUNICODE_STRING name
,
164 PUNICODE_STRING value
)
166 NTSTATUS nts
= STATUS_VARIABLE_NOT_FOUND
;
170 TRACE("%p %s %p\n", env
, debugstr_us(name
), value
);
173 namelen
= name
->Length
/ sizeof(WCHAR
);
174 if (!namelen
) return nts
;
179 var
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
183 var
= ENV_FindVariable(var
, name
->Buffer
, namelen
);
186 value
->Length
= wcslen(var
) * sizeof(WCHAR
);
188 if (value
->Length
<= value
->MaximumLength
)
190 memmove(value
->Buffer
, var
, min(value
->Length
+ sizeof(WCHAR
), value
->MaximumLength
));
191 nts
= STATUS_SUCCESS
;
193 else nts
= STATUS_BUFFER_TOO_SMALL
;
196 if (!env
) RtlReleasePebLock();
202 /******************************************************************
203 * RtlQueryEnvironmentVariable [NTDLL.@]
205 NTSTATUS WINAPI
RtlQueryEnvironmentVariable( WCHAR
*env
, const WCHAR
*name
, SIZE_T namelen
,
206 WCHAR
*value
, SIZE_T value_length
, SIZE_T
*return_length
)
208 NTSTATUS nts
= STATUS_VARIABLE_NOT_FOUND
;
212 if (!namelen
) return nts
;
217 var
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
221 var
= ENV_FindVariable(var
, name
, namelen
);
225 if (len
<= value_length
)
227 memcpy(value
, var
, min(len
+ 1, value_length
) * sizeof(WCHAR
));
228 nts
= STATUS_SUCCESS
;
233 nts
= STATUS_BUFFER_TOO_SMALL
;
236 *return_length
= len
;
238 if (!env
) RtlReleasePebLock();
243 /******************************************************************
244 * RtlSetCurrentEnvironment [NTDLL.@]
247 void WINAPI
RtlSetCurrentEnvironment(PWSTR new_env
, PWSTR
* old_env
)
251 TRACE("(%p %p)\n", new_env
, old_env
);
255 prev
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
256 NtCurrentTeb()->Peb
->ProcessParameters
->Environment
= new_env
;
257 NtCurrentTeb()->Peb
->ProcessParameters
->EnvironmentSize
= RtlSizeHeap( GetProcessHeap(), 0, new_env
);
264 RtlDestroyEnvironment( prev
);
268 /******************************************************************************
269 * RtlSetEnvironmentVariable [NTDLL.@]
271 NTSTATUS WINAPI
RtlSetEnvironmentVariable(PWSTR
* penv
, PUNICODE_STRING name
,
272 PUNICODE_STRING value
)
274 INT varlen
, len
, old_size
;
276 NTSTATUS nts
= STATUS_SUCCESS
;
278 TRACE("(%p, %s, %s)\n", penv
, debugstr_us(name
), debugstr_us(value
));
280 if (!name
|| !name
->Buffer
|| !name
->Length
)
281 return STATUS_INVALID_PARAMETER_1
;
283 len
= name
->Length
/ sizeof(WCHAR
);
285 /* variable names can't contain a '=' except as a first character */
286 for (p
= name
->Buffer
+ 1; p
< name
->Buffer
+ len
; p
++)
287 if (*p
== '=') return STATUS_INVALID_PARAMETER
;
292 env
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
295 old_size
= get_env_length( env
);
297 /* Find a place to insert the string */
298 for (p
= env
; *p
; p
+= varlen
+ 1)
301 if (varlen
> len
&& p
[len
] == '=' &&
302 !RtlCompareUnicodeStrings( name
->Buffer
, len
, p
, len
, TRUE
)) break;
304 if (!value
&& !*p
) goto done
; /* Value to remove doesn't exist */
306 /* Realloc the buffer */
307 len
= value
? len
+ value
->Length
/ sizeof(WCHAR
) + 2 : 0;
308 if (*p
) len
-= wcslen(p
) + 1; /* The name already exists */
312 LPWSTR next
= p
+ wcslen(p
) + 1; /* We know there is a next one */
313 memmove(next
+ len
, next
, (old_size
- (next
- env
)) * sizeof(WCHAR
));
316 if ((old_size
+ len
) * sizeof(WCHAR
) > RtlSizeHeap( GetProcessHeap(), 0, env
))
318 SIZE_T new_size
= (old_size
+ len
) * sizeof(WCHAR
);
319 LPWSTR new_env
= RtlAllocateHeap( GetProcessHeap(), 0, new_size
);
323 nts
= STATUS_NO_MEMORY
;
326 memcpy(new_env
, env
, (p
- env
) * sizeof(WCHAR
));
327 memcpy(new_env
+ (p
- env
) + len
, p
, (old_size
- (p
- env
)) * sizeof(WCHAR
));
328 p
= new_env
+ (p
- env
);
330 RtlDestroyEnvironment(env
);
333 NtCurrentTeb()->Peb
->ProcessParameters
->Environment
= new_env
;
334 NtCurrentTeb()->Peb
->ProcessParameters
->EnvironmentSize
= new_size
;
336 else *penv
= new_env
;
340 if (len
> 0) memmove(p
+ len
, p
, (old_size
- (p
- env
)) * sizeof(WCHAR
));
343 /* Set the new string */
346 memcpy( p
, name
->Buffer
, name
->Length
);
347 p
+= name
->Length
/ sizeof(WCHAR
);
349 memcpy( p
, value
->Buffer
, value
->Length
);
350 p
[value
->Length
/ sizeof(WCHAR
)] = 0;
354 if (!penv
) RtlReleasePebLock();
359 /******************************************************************************
360 * RtlExpandEnvironmentStrings (NTDLL.@)
362 NTSTATUS WINAPI
RtlExpandEnvironmentStrings( const WCHAR
*renv
, WCHAR
*src
, SIZE_T src_len
,
363 WCHAR
*dst
, SIZE_T count
, SIZE_T
*plen
)
365 SIZE_T len
, total_size
= 1; /* 1 for terminating '\0' */
371 env
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
379 for (len
= 0; len
< src_len
; len
++) if (src
[len
] == '%') break;
384 else /* we are at the start of a variable */
386 for (len
= 1; len
< src_len
; len
++) if (src
[len
] == '%') break;
389 if ((var
= ENV_FindVariable( env
, src
+ 1, len
- 1 )))
391 src
+= len
+ 1; /* Skip the variable name */
397 var
= src
; /* Copy original name instead */
403 else /* unfinished variable name, ignore it */
413 if (count
< len
) len
= count
;
414 memcpy(dst
, var
, len
* sizeof(WCHAR
));
420 if (!renv
) RtlReleasePebLock();
422 if (dst
&& count
) *dst
= '\0';
423 if (plen
) *plen
= total_size
;
425 return (count
) ? STATUS_SUCCESS
: STATUS_BUFFER_TOO_SMALL
;
428 /******************************************************************
429 * RtlExpandEnvironmentStrings_U (NTDLL.@)
431 NTSTATUS WINAPI
RtlExpandEnvironmentStrings_U( const WCHAR
*env
, const UNICODE_STRING
*src
,
432 UNICODE_STRING
*dst
, ULONG
*plen
)
437 ret
= RtlExpandEnvironmentStrings( env
, src
->Buffer
, src
->Length
/ sizeof(WCHAR
),
438 dst
->Buffer
, dst
->MaximumLength
/ sizeof(WCHAR
), &len
);
439 if (plen
) *plen
= len
* sizeof(WCHAR
); /* FIXME: check for overflow? */
440 if (len
> UNICODE_STRING_MAX_CHARS
) ret
= STATUS_BUFFER_TOO_SMALL
;
441 if (!ret
) dst
->Length
= (len
- 1) * sizeof(WCHAR
);
445 static inline void normalize( void *base
, WCHAR
**ptr
)
447 if (*ptr
) *ptr
= (WCHAR
*)((char *)base
+ (UINT_PTR
)*ptr
);
450 /******************************************************************************
451 * RtlNormalizeProcessParams [NTDLL.@]
453 PRTL_USER_PROCESS_PARAMETERS WINAPI
RtlNormalizeProcessParams( RTL_USER_PROCESS_PARAMETERS
*params
)
455 if (params
&& !(params
->Flags
& PROCESS_PARAMS_FLAG_NORMALIZED
))
457 normalize( params
, ¶ms
->CurrentDirectory
.DosPath
.Buffer
);
458 normalize( params
, ¶ms
->DllPath
.Buffer
);
459 normalize( params
, ¶ms
->ImagePathName
.Buffer
);
460 normalize( params
, ¶ms
->CommandLine
.Buffer
);
461 normalize( params
, ¶ms
->WindowTitle
.Buffer
);
462 normalize( params
, ¶ms
->Desktop
.Buffer
);
463 normalize( params
, ¶ms
->ShellInfo
.Buffer
);
464 normalize( params
, ¶ms
->RuntimeInfo
.Buffer
);
465 params
->Flags
|= PROCESS_PARAMS_FLAG_NORMALIZED
;
471 static inline void denormalize( const void *base
, WCHAR
**ptr
)
473 if (*ptr
) *ptr
= (WCHAR
*)(UINT_PTR
)((char *)*ptr
- (const char *)base
);
476 /******************************************************************************
477 * RtlDeNormalizeProcessParams [NTDLL.@]
479 PRTL_USER_PROCESS_PARAMETERS WINAPI
RtlDeNormalizeProcessParams( RTL_USER_PROCESS_PARAMETERS
*params
)
481 if (params
&& (params
->Flags
& PROCESS_PARAMS_FLAG_NORMALIZED
))
483 denormalize( params
, ¶ms
->CurrentDirectory
.DosPath
.Buffer
);
484 denormalize( params
, ¶ms
->DllPath
.Buffer
);
485 denormalize( params
, ¶ms
->ImagePathName
.Buffer
);
486 denormalize( params
, ¶ms
->CommandLine
.Buffer
);
487 denormalize( params
, ¶ms
->WindowTitle
.Buffer
);
488 denormalize( params
, ¶ms
->Desktop
.Buffer
);
489 denormalize( params
, ¶ms
->ShellInfo
.Buffer
);
490 denormalize( params
, ¶ms
->RuntimeInfo
.Buffer
);
491 params
->Flags
&= ~PROCESS_PARAMS_FLAG_NORMALIZED
;
497 #define ROUND_SIZE(size,align) (((size) + (align) - 1) & ~((align) - 1))
499 /* append a unicode string to the process params data; helper for RtlCreateProcessParameters */
500 static void append_unicode_string( void **data
, const UNICODE_STRING
*src
,
501 UNICODE_STRING
*dst
, size_t align
)
503 dst
->Length
= src
->Length
;
504 dst
->MaximumLength
= src
->MaximumLength
;
505 if (dst
->MaximumLength
)
508 memcpy( dst
->Buffer
, src
->Buffer
, dst
->Length
);
509 *data
= (char *)dst
->Buffer
+ ROUND_SIZE( dst
->MaximumLength
, align
);
511 else dst
->Buffer
= NULL
;
514 static RTL_USER_PROCESS_PARAMETERS
*alloc_process_params( size_t align
,
515 const UNICODE_STRING
*image
,
516 const UNICODE_STRING
*dllpath
,
517 const UNICODE_STRING
*curdir
,
518 const UNICODE_STRING
*cmdline
,
520 const UNICODE_STRING
*title
,
521 const UNICODE_STRING
*desktop
,
522 const UNICODE_STRING
*shell
,
523 const UNICODE_STRING
*runtime
)
525 RTL_USER_PROCESS_PARAMETERS
*params
;
526 SIZE_T size
, env_size
= 0;
529 if (env
) env_size
= get_env_length( env
) * sizeof(WCHAR
);
531 size
= (sizeof(RTL_USER_PROCESS_PARAMETERS
)
532 + ROUND_SIZE( image
->MaximumLength
, align
)
533 + ROUND_SIZE( dllpath
->MaximumLength
, align
)
534 + ROUND_SIZE( curdir
->MaximumLength
, align
)
535 + ROUND_SIZE( cmdline
->MaximumLength
, align
)
536 + ROUND_SIZE( title
->MaximumLength
, align
)
537 + ROUND_SIZE( desktop
->MaximumLength
, align
)
538 + ROUND_SIZE( shell
->MaximumLength
, align
)
539 + ROUND_SIZE( runtime
->MaximumLength
, align
));
541 if (!(ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
+ ROUND_SIZE( env_size
, align
))))
545 params
->AllocationSize
= size
;
547 params
->Flags
= PROCESS_PARAMS_FLAG_NORMALIZED
;
548 params
->EnvironmentSize
= ROUND_SIZE( env_size
, align
);
549 /* all other fields are zero */
552 append_unicode_string( &ptr
, curdir
, ¶ms
->CurrentDirectory
.DosPath
, align
);
553 append_unicode_string( &ptr
, dllpath
, ¶ms
->DllPath
, align
);
554 append_unicode_string( &ptr
, image
, ¶ms
->ImagePathName
, align
);
555 append_unicode_string( &ptr
, cmdline
, ¶ms
->CommandLine
, align
);
556 append_unicode_string( &ptr
, title
, ¶ms
->WindowTitle
, align
);
557 append_unicode_string( &ptr
, desktop
, ¶ms
->Desktop
, align
);
558 append_unicode_string( &ptr
, shell
, ¶ms
->ShellInfo
, align
);
559 append_unicode_string( &ptr
, runtime
, ¶ms
->RuntimeInfo
, align
);
560 if (env
) params
->Environment
= memcpy( ptr
, env
, env_size
);
565 /******************************************************************************
566 * RtlCreateProcessParametersEx [NTDLL.@]
568 NTSTATUS WINAPI
RtlCreateProcessParametersEx( RTL_USER_PROCESS_PARAMETERS
**result
,
569 const UNICODE_STRING
*ImagePathName
,
570 const UNICODE_STRING
*DllPath
,
571 const UNICODE_STRING
*CurrentDirectoryName
,
572 const UNICODE_STRING
*CommandLine
,
574 const UNICODE_STRING
*WindowTitle
,
575 const UNICODE_STRING
*Desktop
,
576 const UNICODE_STRING
*ShellInfo
,
577 const UNICODE_STRING
*RuntimeInfo
,
580 UNICODE_STRING curdir
;
581 const RTL_USER_PROCESS_PARAMETERS
*cur_params
;
582 NTSTATUS status
= STATUS_SUCCESS
;
585 cur_params
= NtCurrentTeb()->Peb
->ProcessParameters
;
586 if (!DllPath
) DllPath
= &null_str
;
587 if (!CurrentDirectoryName
)
589 if (NtCurrentTeb()->Tib
.SubSystemTib
) /* FIXME: hack */
590 curdir
= ((WIN16_SUBSYSTEM_TIB
*)NtCurrentTeb()->Tib
.SubSystemTib
)->curdir
.DosPath
;
592 curdir
= cur_params
->CurrentDirectory
.DosPath
;
594 else curdir
= *CurrentDirectoryName
;
595 curdir
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
597 if (!CommandLine
) CommandLine
= ImagePathName
;
598 if (!Environment
&& cur_params
) Environment
= cur_params
->Environment
;
599 if (!WindowTitle
) WindowTitle
= &empty_str
;
600 if (!Desktop
) Desktop
= &empty_str
;
601 if (!ShellInfo
) ShellInfo
= &empty_str
;
602 if (!RuntimeInfo
) RuntimeInfo
= &null_str
;
604 if ((*result
= alloc_process_params( sizeof(void *), ImagePathName
, DllPath
, &curdir
, CommandLine
,
605 Environment
, WindowTitle
, Desktop
, ShellInfo
, RuntimeInfo
)))
607 if (cur_params
) (*result
)->ConsoleFlags
= cur_params
->ConsoleFlags
;
608 if (!(flags
& PROCESS_PARAMS_FLAG_NORMALIZED
)) RtlDeNormalizeProcessParams( *result
);
610 else status
= STATUS_NO_MEMORY
;
617 /******************************************************************************
618 * RtlCreateProcessParameters [NTDLL.@]
620 NTSTATUS WINAPI
RtlCreateProcessParameters( RTL_USER_PROCESS_PARAMETERS
**result
,
621 const UNICODE_STRING
*image
,
622 const UNICODE_STRING
*dllpath
,
623 const UNICODE_STRING
*curdir
,
624 const UNICODE_STRING
*cmdline
,
626 const UNICODE_STRING
*title
,
627 const UNICODE_STRING
*desktop
,
628 const UNICODE_STRING
*shellinfo
,
629 const UNICODE_STRING
*runtime
)
631 return RtlCreateProcessParametersEx( result
, image
, dllpath
, curdir
, cmdline
,
632 env
, title
, desktop
, shellinfo
, runtime
, 0 );
636 /******************************************************************************
637 * RtlDestroyProcessParameters [NTDLL.@]
639 void WINAPI
RtlDestroyProcessParameters( RTL_USER_PROCESS_PARAMETERS
*params
)
641 RtlFreeHeap( GetProcessHeap(), 0, params
);
645 /***********************************************************************
646 * init_user_process_params
648 * Fill the initial RTL_USER_PROCESS_PARAMETERS structure from the server.
650 void init_user_process_params(void)
653 SIZE_T size
= 0, env_size
;
654 RTL_USER_PROCESS_PARAMETERS
*new_params
, *params
= NtCurrentTeb()->Peb
->ProcessParameters
;
655 UNICODE_STRING curdir
;
657 /* environment needs to be a separate memory block */
658 env_size
= params
->EnvironmentSize
;
659 if ((env
= RtlAllocateHeap( GetProcessHeap(), 0, max( env_size
, sizeof(WCHAR
) ))))
661 if (env_size
) memcpy( env
, params
->Environment
, env_size
);
665 if (!(new_params
= alloc_process_params( 1, ¶ms
->ImagePathName
, ¶ms
->DllPath
,
666 ¶ms
->CurrentDirectory
.DosPath
, ¶ms
->CommandLine
,
667 NULL
, ¶ms
->WindowTitle
, ¶ms
->Desktop
,
668 ¶ms
->ShellInfo
, ¶ms
->RuntimeInfo
)))
671 new_params
->Environment
= env
;
672 new_params
->DebugFlags
= params
->DebugFlags
;
673 new_params
->ConsoleHandle
= params
->ConsoleHandle
;
674 new_params
->ConsoleFlags
= params
->ConsoleFlags
;
675 new_params
->hStdInput
= params
->hStdInput
;
676 new_params
->hStdOutput
= params
->hStdOutput
;
677 new_params
->hStdError
= params
->hStdError
;
678 new_params
->dwX
= params
->dwX
;
679 new_params
->dwY
= params
->dwY
;
680 new_params
->dwXSize
= params
->dwXSize
;
681 new_params
->dwYSize
= params
->dwYSize
;
682 new_params
->dwXCountChars
= params
->dwXCountChars
;
683 new_params
->dwYCountChars
= params
->dwYCountChars
;
684 new_params
->dwFillAttribute
= params
->dwFillAttribute
;
685 new_params
->dwFlags
= params
->dwFlags
;
686 new_params
->wShowWindow
= params
->wShowWindow
;
688 NtCurrentTeb()->Peb
->ProcessParameters
= new_params
;
689 NtFreeVirtualMemory( GetCurrentProcess(), (void **)¶ms
, &size
, MEM_RELEASE
);
691 if (RtlSetCurrentDirectory_U( &new_params
->CurrentDirectory
.DosPath
))
693 MESSAGE("wine: could not open working directory %s, starting in the Windows directory.\n",
694 debugstr_w( new_params
->CurrentDirectory
.DosPath
.Buffer
));
695 RtlInitUnicodeString( &curdir
, windows_dir
);
696 RtlSetCurrentDirectory_U( &curdir
);
698 set_wow64_environment( &new_params
->Environment
);
699 new_params
->EnvironmentSize
= RtlSizeHeap( GetProcessHeap(), 0, new_params
->Environment
);