4 * Copyright 1996, 1998 Alexandre Julliard
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
25 #define WIN32_NO_STATUS
26 #define NONAMELESSUNION
32 #include "kernelbase.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(process
);
37 static DWORD shutdown_flags
= 0;
38 static DWORD shutdown_priority
= 0x280;
40 /***********************************************************************
42 ***********************************************************************/
45 /***********************************************************************
48 static BOOL
find_exe_file( const WCHAR
*name
, WCHAR
*buffer
, DWORD buflen
)
53 if (!set_ntstatus( RtlGetExePath( name
, &load_path
))) return FALSE
;
55 TRACE( "looking for %s in %s\n", debugstr_w(name
), debugstr_w(load_path
) );
57 ret
= (SearchPathW( load_path
, name
, L
".exe", buflen
, buffer
, NULL
) ||
58 /* not found, try without extension in case it is a Unix app */
59 SearchPathW( load_path
, name
, NULL
, buflen
, buffer
, NULL
));
61 if (ret
) /* make sure it can be opened, SearchPathW also returns directories */
63 HANDLE handle
= CreateFileW( buffer
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_DELETE
,
64 NULL
, OPEN_EXISTING
, 0, 0 );
65 if ((ret
= (handle
!= INVALID_HANDLE_VALUE
))) CloseHandle( handle
);
67 RtlReleasePath( load_path
);
72 /*************************************************************************
75 * Helper for CreateProcess: retrieve the file name to load from the
76 * app name and command line. Store the file name in buffer, and
77 * return a possibly modified command line.
79 static WCHAR
*get_file_name( WCHAR
*cmdline
, WCHAR
*buffer
, DWORD buflen
)
81 WCHAR
*name
, *pos
, *first_space
, *ret
= NULL
;
84 /* first check for a quoted file name */
86 if (cmdline
[0] == '"' && (p
= wcschr( cmdline
+ 1, '"' )))
88 int len
= p
- cmdline
- 1;
89 /* extract the quoted portion as file name */
90 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
91 memcpy( name
, cmdline
+ 1, len
* sizeof(WCHAR
) );
94 if (!find_exe_file( name
, buffer
, buflen
)) goto done
;
95 ret
= cmdline
; /* no change necessary */
99 /* now try the command-line word by word */
101 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline
) + 1) * sizeof(WCHAR
) )))
109 while (*p
&& *p
!= ' ' && *p
!= '\t') *pos
++ = *p
++;
111 if (find_exe_file( name
, buffer
, buflen
))
116 if (!first_space
) first_space
= pos
;
117 if (!(*pos
++ = *p
++)) break;
122 SetLastError( ERROR_FILE_NOT_FOUND
);
124 else if (first_space
) /* build a new command-line with quotes */
126 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline
) + 3) * sizeof(WCHAR
) )))
128 swprintf( ret
, lstrlenW(cmdline
) + 3, L
"\"%s\"%s", name
, p
);
132 RtlFreeHeap( GetProcessHeap(), 0, name
);
137 /***********************************************************************
138 * create_process_params
140 static RTL_USER_PROCESS_PARAMETERS
*create_process_params( const WCHAR
*filename
, const WCHAR
*cmdline
,
141 const WCHAR
*cur_dir
, void *env
, DWORD flags
,
142 const STARTUPINFOW
*startup
)
144 RTL_USER_PROCESS_PARAMETERS
*params
;
145 UNICODE_STRING imageW
, dllpathW
, curdirW
, cmdlineW
, titleW
, desktopW
, runtimeW
, newdirW
;
146 WCHAR imagepath
[MAX_PATH
];
147 WCHAR
*load_path
, *dummy
, *envW
= env
;
149 if (!GetLongPathNameW( filename
, imagepath
, MAX_PATH
)) lstrcpynW( imagepath
, filename
, MAX_PATH
);
150 if (!GetFullPathNameW( imagepath
, MAX_PATH
, imagepath
, NULL
)) lstrcpynW( imagepath
, filename
, MAX_PATH
);
152 if (env
&& !(flags
& CREATE_UNICODE_ENVIRONMENT
)) /* convert environment to unicode */
157 while (*e
) e
+= strlen(e
) + 1;
158 e
++; /* final null */
159 lenW
= MultiByteToWideChar( CP_ACP
, 0, env
, e
- (char *)env
, NULL
, 0 );
160 if ((envW
= RtlAllocateHeap( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
161 MultiByteToWideChar( CP_ACP
, 0, env
, e
- (char *)env
, envW
, lenW
);
164 newdirW
.Buffer
= NULL
;
167 if (RtlDosPathNameToNtPathName_U( cur_dir
, &newdirW
, NULL
, NULL
))
168 cur_dir
= newdirW
.Buffer
+ 4; /* skip \??\ prefix */
172 LdrGetDllPath( imagepath
, LOAD_WITH_ALTERED_SEARCH_PATH
, &load_path
, &dummy
);
173 RtlInitUnicodeString( &imageW
, imagepath
);
174 RtlInitUnicodeString( &dllpathW
, load_path
);
175 RtlInitUnicodeString( &curdirW
, cur_dir
);
176 RtlInitUnicodeString( &cmdlineW
, cmdline
);
177 RtlInitUnicodeString( &titleW
, startup
->lpTitle
? startup
->lpTitle
: imagepath
);
178 RtlInitUnicodeString( &desktopW
, startup
->lpDesktop
);
179 runtimeW
.Buffer
= (WCHAR
*)startup
->lpReserved2
;
180 runtimeW
.Length
= runtimeW
.MaximumLength
= startup
->cbReserved2
;
181 if (RtlCreateProcessParametersEx( ¶ms
, &imageW
, &dllpathW
, cur_dir
? &curdirW
: NULL
,
182 &cmdlineW
, envW
, &titleW
, &desktopW
,
183 NULL
, &runtimeW
, PROCESS_PARAMS_FLAG_NORMALIZED
))
185 RtlReleasePath( load_path
);
186 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
189 RtlReleasePath( load_path
);
191 if (flags
& CREATE_NEW_PROCESS_GROUP
) params
->ConsoleFlags
= 1;
192 if (flags
& CREATE_NEW_CONSOLE
) params
->ConsoleHandle
= (HANDLE
)1; /* KERNEL32_CONSOLE_ALLOC */
194 if (startup
->dwFlags
& STARTF_USESTDHANDLES
)
196 params
->hStdInput
= startup
->hStdInput
;
197 params
->hStdOutput
= startup
->hStdOutput
;
198 params
->hStdError
= startup
->hStdError
;
200 else if (flags
& DETACHED_PROCESS
)
202 params
->hStdInput
= INVALID_HANDLE_VALUE
;
203 params
->hStdOutput
= INVALID_HANDLE_VALUE
;
204 params
->hStdError
= INVALID_HANDLE_VALUE
;
208 params
->hStdInput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
209 params
->hStdOutput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
210 params
->hStdError
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
213 if (flags
& CREATE_NEW_CONSOLE
)
215 /* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
216 if (is_console_handle(params
->hStdInput
)) params
->hStdInput
= INVALID_HANDLE_VALUE
;
217 if (is_console_handle(params
->hStdOutput
)) params
->hStdOutput
= INVALID_HANDLE_VALUE
;
218 if (is_console_handle(params
->hStdError
)) params
->hStdError
= INVALID_HANDLE_VALUE
;
222 if (is_console_handle(params
->hStdInput
)) params
->hStdInput
= (HANDLE
)((UINT_PTR
)params
->hStdInput
& ~3);
223 if (is_console_handle(params
->hStdOutput
)) params
->hStdOutput
= (HANDLE
)((UINT_PTR
)params
->hStdOutput
& ~3);
224 if (is_console_handle(params
->hStdError
)) params
->hStdError
= (HANDLE
)((UINT_PTR
)params
->hStdError
& ~3);
227 params
->dwX
= startup
->dwX
;
228 params
->dwY
= startup
->dwY
;
229 params
->dwXSize
= startup
->dwXSize
;
230 params
->dwYSize
= startup
->dwYSize
;
231 params
->dwXCountChars
= startup
->dwXCountChars
;
232 params
->dwYCountChars
= startup
->dwYCountChars
;
233 params
->dwFillAttribute
= startup
->dwFillAttribute
;
234 params
->dwFlags
= startup
->dwFlags
;
235 params
->wShowWindow
= startup
->wShowWindow
;
237 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
242 /***********************************************************************
245 static NTSTATUS
create_nt_process( SECURITY_ATTRIBUTES
*psa
, SECURITY_ATTRIBUTES
*tsa
,
246 BOOL inherit
, DWORD flags
, RTL_USER_PROCESS_PARAMETERS
*params
,
247 RTL_USER_PROCESS_INFORMATION
*info
, HANDLE parent
)
250 UNICODE_STRING nameW
;
252 if (!params
->ImagePathName
.Buffer
[0]) return STATUS_OBJECT_PATH_NOT_FOUND
;
253 status
= RtlDosPathNameToNtPathName_U_WithStatus( params
->ImagePathName
.Buffer
, &nameW
, NULL
, NULL
);
256 params
->DebugFlags
= flags
; /* hack, cf. RtlCreateUserProcess implementation */
257 status
= RtlCreateUserProcess( &nameW
, OBJ_CASE_INSENSITIVE
, params
,
258 psa
? psa
->lpSecurityDescriptor
: NULL
,
259 tsa
? tsa
->lpSecurityDescriptor
: NULL
,
260 parent
, inherit
, 0, 0, info
);
261 RtlFreeUnicodeString( &nameW
);
267 /***********************************************************************
270 static NTSTATUS
create_vdm_process( SECURITY_ATTRIBUTES
*psa
, SECURITY_ATTRIBUTES
*tsa
,
271 BOOL inherit
, DWORD flags
, RTL_USER_PROCESS_PARAMETERS
*params
,
272 RTL_USER_PROCESS_INFORMATION
*info
)
274 const WCHAR
*winevdm
= (is_win64
|| is_wow64
?
275 L
"C:\\windows\\syswow64\\winevdm.exe" :
276 L
"C:\\windows\\system32\\winevdm.exe");
281 len
= (lstrlenW(params
->ImagePathName
.Buffer
) + lstrlenW(params
->CommandLine
.Buffer
) +
282 lstrlenW(winevdm
) + 16);
284 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
285 return STATUS_NO_MEMORY
;
287 swprintf( newcmdline
, len
, L
"%s --app-name \"%s\" %s",
288 winevdm
, params
->ImagePathName
.Buffer
, params
->CommandLine
.Buffer
);
289 RtlInitUnicodeString( ¶ms
->ImagePathName
, winevdm
);
290 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
291 status
= create_nt_process( psa
, tsa
, inherit
, flags
, params
, info
, NULL
);
292 HeapFree( GetProcessHeap(), 0, newcmdline
);
297 /***********************************************************************
300 static NTSTATUS
create_cmd_process( SECURITY_ATTRIBUTES
*psa
, SECURITY_ATTRIBUTES
*tsa
,
301 BOOL inherit
, DWORD flags
, RTL_USER_PROCESS_PARAMETERS
*params
,
302 RTL_USER_PROCESS_INFORMATION
*info
)
304 WCHAR comspec
[MAX_PATH
];
309 if (!GetEnvironmentVariableW( L
"COMSPEC", comspec
, ARRAY_SIZE( comspec
)))
310 lstrcpyW( comspec
, L
"C:\\windows\\system32\\cmd.exe" );
312 len
= lstrlenW(comspec
) + 7 + lstrlenW(params
->CommandLine
.Buffer
) + 2;
313 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
314 return STATUS_NO_MEMORY
;
316 swprintf( newcmdline
, len
, L
"%s /s/c \"%s\"", comspec
, params
->CommandLine
.Buffer
);
317 RtlInitUnicodeString( ¶ms
->ImagePathName
, comspec
);
318 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
319 status
= create_nt_process( psa
, tsa
, inherit
, flags
, params
, info
, NULL
);
320 RtlFreeHeap( GetProcessHeap(), 0, newcmdline
);
325 /*********************************************************************
326 * CloseHandle (kernelbase.@)
328 BOOL WINAPI DECLSPEC_HOTPATCH
CloseHandle( HANDLE handle
)
330 if (handle
== (HANDLE
)STD_INPUT_HANDLE
)
331 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
, 0 );
332 else if (handle
== (HANDLE
)STD_OUTPUT_HANDLE
)
333 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
, 0 );
334 else if (handle
== (HANDLE
)STD_ERROR_HANDLE
)
335 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
, 0 );
337 if (is_console_handle( handle
)) handle
= console_handle_map( handle
);
338 return set_ntstatus( NtClose( handle
));
342 /**********************************************************************
343 * CreateProcessAsUserA (kernelbase.@)
345 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserA( HANDLE token
, const char *app_name
, char *cmd_line
,
346 SECURITY_ATTRIBUTES
*process_attr
,
347 SECURITY_ATTRIBUTES
*thread_attr
,
348 BOOL inherit
, DWORD flags
, void *env
,
349 const char *cur_dir
, STARTUPINFOA
*startup_info
,
350 PROCESS_INFORMATION
*info
)
352 return CreateProcessInternalA( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
353 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
357 /**********************************************************************
358 * CreateProcessAsUserW (kernelbase.@)
360 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
361 SECURITY_ATTRIBUTES
*process_attr
,
362 SECURITY_ATTRIBUTES
*thread_attr
,
363 BOOL inherit
, DWORD flags
, void *env
,
364 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
365 PROCESS_INFORMATION
*info
)
367 return CreateProcessInternalW( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
368 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
371 /**********************************************************************
372 * CreateProcessInternalA (kernelbase.@)
374 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalA( HANDLE token
, const char *app_name
, char *cmd_line
,
375 SECURITY_ATTRIBUTES
*process_attr
,
376 SECURITY_ATTRIBUTES
*thread_attr
,
377 BOOL inherit
, DWORD flags
, void *env
,
378 const char *cur_dir
, STARTUPINFOA
*startup_info
,
379 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
382 WCHAR
*app_nameW
= NULL
, *cmd_lineW
= NULL
, *cur_dirW
= NULL
;
383 UNICODE_STRING desktopW
, titleW
;
384 STARTUPINFOEXW infoW
;
386 desktopW
.Buffer
= NULL
;
387 titleW
.Buffer
= NULL
;
388 if (app_name
&& !(app_nameW
= file_name_AtoW( app_name
, TRUE
))) goto done
;
389 if (cmd_line
&& !(cmd_lineW
= file_name_AtoW( cmd_line
, TRUE
))) goto done
;
390 if (cur_dir
&& !(cur_dirW
= file_name_AtoW( cur_dir
, TRUE
))) goto done
;
392 if (startup_info
->lpDesktop
) RtlCreateUnicodeStringFromAsciiz( &desktopW
, startup_info
->lpDesktop
);
393 if (startup_info
->lpTitle
) RtlCreateUnicodeStringFromAsciiz( &titleW
, startup_info
->lpTitle
);
395 memcpy( &infoW
.StartupInfo
, startup_info
, sizeof(infoW
.StartupInfo
) );
396 infoW
.StartupInfo
.lpDesktop
= desktopW
.Buffer
;
397 infoW
.StartupInfo
.lpTitle
= titleW
.Buffer
;
399 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
400 infoW
.lpAttributeList
= ((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
402 ret
= CreateProcessInternalW( token
, app_nameW
, cmd_lineW
, process_attr
, thread_attr
,
403 inherit
, flags
, env
, cur_dirW
, (STARTUPINFOW
*)&infoW
, info
, new_token
);
405 RtlFreeHeap( GetProcessHeap(), 0, app_nameW
);
406 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW
);
407 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW
);
408 RtlFreeUnicodeString( &desktopW
);
409 RtlFreeUnicodeString( &titleW
);
413 struct proc_thread_attr
420 struct _PROC_THREAD_ATTRIBUTE_LIST
422 DWORD mask
; /* bitmask of items in list */
423 DWORD size
; /* max number of items in list */
424 DWORD count
; /* number of items in list */
427 struct proc_thread_attr attrs
[1];
430 /**********************************************************************
431 * CreateProcessInternalW (kernelbase.@)
433 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
434 SECURITY_ATTRIBUTES
*process_attr
,
435 SECURITY_ATTRIBUTES
*thread_attr
,
436 BOOL inherit
, DWORD flags
, void *env
,
437 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
438 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
440 WCHAR name
[MAX_PATH
];
441 WCHAR
*p
, *tidy_cmdline
= cmd_line
;
442 RTL_USER_PROCESS_PARAMETERS
*params
= NULL
;
443 RTL_USER_PROCESS_INFORMATION rtl_info
;
444 HANDLE parent
= NULL
;
447 /* Process the AppName and/or CmdLine to get module name and path */
449 TRACE( "app %s cmdline %s\n", debugstr_w(app_name
), debugstr_w(cmd_line
) );
451 if (token
) FIXME( "Creating a process with a token is not yet implemented\n" );
452 if (new_token
) FIXME( "No support for returning created process token\n" );
456 if (!cmd_line
|| !cmd_line
[0]) /* no command-line, create one */
458 if (!(tidy_cmdline
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name
)+3) * sizeof(WCHAR
) )))
460 swprintf( tidy_cmdline
, lstrlenW(app_name
) + 3, L
"\"%s\"", app_name
);
465 if (!(tidy_cmdline
= get_file_name( cmd_line
, name
, ARRAY_SIZE(name
) ))) return FALSE
;
469 /* Warn if unsupported features are used */
471 if (flags
& (IDLE_PRIORITY_CLASS
| HIGH_PRIORITY_CLASS
| REALTIME_PRIORITY_CLASS
|
472 CREATE_DEFAULT_ERROR_MODE
| CREATE_NO_WINDOW
|
473 PROFILE_USER
| PROFILE_KERNEL
| PROFILE_SERVER
))
474 WARN( "(%s,...): ignoring some flags in %x\n", debugstr_w(app_name
), flags
);
478 DWORD attr
= GetFileAttributesW( cur_dir
);
479 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
481 status
= STATUS_NOT_A_DIRECTORY
;
486 info
->hThread
= info
->hProcess
= 0;
487 info
->dwProcessId
= info
->dwThreadId
= 0;
489 if (!(params
= create_process_params( app_name
, tidy_cmdline
, cur_dir
, env
, flags
, startup_info
)))
491 status
= STATUS_NO_MEMORY
;
495 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
497 struct _PROC_THREAD_ATTRIBUTE_LIST
*attrs
=
498 (struct _PROC_THREAD_ATTRIBUTE_LIST
*)((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
503 for (i
= 0; i
< attrs
->count
; ++i
)
505 switch(attrs
->attrs
[i
].attr
)
507 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
508 parent
= *(HANDLE
*)attrs
->attrs
[i
].value
;
509 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent
);
512 status
= STATUS_INVALID_HANDLE
;
517 FIXME("Unsupported attribute %#Ix.\n", attrs
->attrs
[i
].attr
);
524 status
= create_nt_process( process_attr
, thread_attr
, inherit
, flags
, params
, &rtl_info
, parent
);
529 case STATUS_INVALID_IMAGE_WIN_16
:
530 case STATUS_INVALID_IMAGE_NE_FORMAT
:
531 case STATUS_INVALID_IMAGE_PROTECT
:
532 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name
) );
533 status
= create_vdm_process( process_attr
, thread_attr
, inherit
, flags
, params
, &rtl_info
);
535 case STATUS_INVALID_IMAGE_NOT_MZ
:
536 /* check for .com or .bat extension */
537 if (!(p
= wcsrchr( app_name
, '.' ))) break;
538 if (!wcsicmp( p
, L
".com" ) || !wcsicmp( p
, L
".pif" ))
540 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name
) );
541 status
= create_vdm_process( process_attr
, thread_attr
, inherit
, flags
, params
, &rtl_info
);
543 else if (!wcsicmp( p
, L
".bat" ) || !wcsicmp( p
, L
".cmd" ))
545 TRACE( "starting %s as batch binary\n", debugstr_w(app_name
) );
546 status
= create_cmd_process( process_attr
, thread_attr
, inherit
, flags
, params
, &rtl_info
);
553 info
->hProcess
= rtl_info
.Process
;
554 info
->hThread
= rtl_info
.Thread
;
555 info
->dwProcessId
= HandleToUlong( rtl_info
.ClientId
.UniqueProcess
);
556 info
->dwThreadId
= HandleToUlong( rtl_info
.ClientId
.UniqueThread
);
557 if (!(flags
& CREATE_SUSPENDED
)) NtResumeThread( rtl_info
.Thread
, NULL
);
558 TRACE( "started process pid %04x tid %04x\n", info
->dwProcessId
, info
->dwThreadId
);
562 RtlDestroyProcessParameters( params
);
563 if (tidy_cmdline
!= cmd_line
) HeapFree( GetProcessHeap(), 0, tidy_cmdline
);
564 return set_ntstatus( status
);
568 /**********************************************************************
569 * CreateProcessA (kernelbase.@)
571 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessA( const char *app_name
, char *cmd_line
,
572 SECURITY_ATTRIBUTES
*process_attr
,
573 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
,
574 DWORD flags
, void *env
, const char *cur_dir
,
575 STARTUPINFOA
*startup_info
, PROCESS_INFORMATION
*info
)
577 return CreateProcessInternalA( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
578 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
582 /**********************************************************************
583 * CreateProcessW (kernelbase.@)
585 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessW( const WCHAR
*app_name
, WCHAR
*cmd_line
,
586 SECURITY_ATTRIBUTES
*process_attr
,
587 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
, DWORD flags
,
588 void *env
, const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
589 PROCESS_INFORMATION
*info
)
591 return CreateProcessInternalW( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
592 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
596 /*********************************************************************
597 * DuplicateHandle (kernelbase.@)
599 BOOL WINAPI DECLSPEC_HOTPATCH
DuplicateHandle( HANDLE source_process
, HANDLE source
,
600 HANDLE dest_process
, HANDLE
*dest
,
601 DWORD access
, BOOL inherit
, DWORD options
)
603 if (is_console_handle( source
))
605 source
= console_handle_map( source
);
606 if (!set_ntstatus( NtDuplicateObject( source_process
, source
, dest_process
, dest
,
607 access
, inherit
? OBJ_INHERIT
: 0, options
)))
609 *dest
= console_handle_map( *dest
);
612 return set_ntstatus( NtDuplicateObject( source_process
, source
, dest_process
, dest
,
613 access
, inherit
? OBJ_INHERIT
: 0, options
));
617 /****************************************************************************
618 * FlushInstructionCache (kernelbase.@)
620 BOOL WINAPI DECLSPEC_HOTPATCH
FlushInstructionCache( HANDLE process
, LPCVOID addr
, SIZE_T size
)
622 return set_ntstatus( NtFlushInstructionCache( process
, addr
, size
));
626 /***********************************************************************
627 * GetCurrentProcess (kernelbase.@)
629 HANDLE WINAPI
kernelbase_GetCurrentProcess(void)
631 return (HANDLE
)~(ULONG_PTR
)0;
635 /***********************************************************************
636 * GetCurrentProcessId (kernelbase.@)
638 DWORD WINAPI
kernelbase_GetCurrentProcessId(void)
640 return HandleToULong( NtCurrentTeb()->ClientId
.UniqueProcess
);
644 /***********************************************************************
645 * GetErrorMode (kernelbase.@)
647 UINT WINAPI DECLSPEC_HOTPATCH
GetErrorMode(void)
651 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
652 &mode
, sizeof(mode
), NULL
);
657 /***********************************************************************
658 * GetExitCodeProcess (kernelbase.@)
660 BOOL WINAPI DECLSPEC_HOTPATCH
GetExitCodeProcess( HANDLE process
, LPDWORD exit_code
)
663 PROCESS_BASIC_INFORMATION pbi
;
665 status
= NtQueryInformationProcess( process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
666 if (status
&& exit_code
) *exit_code
= pbi
.ExitStatus
;
667 return set_ntstatus( status
);
671 /*********************************************************************
672 * GetHandleInformation (kernelbase.@)
674 BOOL WINAPI DECLSPEC_HOTPATCH
GetHandleInformation( HANDLE handle
, DWORD
*flags
)
676 OBJECT_DATA_INFORMATION info
;
678 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
684 if (info
.InheritHandle
) *flags
|= HANDLE_FLAG_INHERIT
;
685 if (info
.ProtectFromClose
) *flags
|= HANDLE_FLAG_PROTECT_FROM_CLOSE
;
691 /***********************************************************************
692 * GetPriorityClass (kernelbase.@)
694 DWORD WINAPI DECLSPEC_HOTPATCH
GetPriorityClass( HANDLE process
)
696 PROCESS_BASIC_INFORMATION pbi
;
698 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
699 &pbi
, sizeof(pbi
), NULL
)))
702 switch (pbi
.BasePriority
)
704 case PROCESS_PRIOCLASS_IDLE
: return IDLE_PRIORITY_CLASS
;
705 case PROCESS_PRIOCLASS_BELOW_NORMAL
: return BELOW_NORMAL_PRIORITY_CLASS
;
706 case PROCESS_PRIOCLASS_NORMAL
: return NORMAL_PRIORITY_CLASS
;
707 case PROCESS_PRIOCLASS_ABOVE_NORMAL
: return ABOVE_NORMAL_PRIORITY_CLASS
;
708 case PROCESS_PRIOCLASS_HIGH
: return HIGH_PRIORITY_CLASS
;
709 case PROCESS_PRIOCLASS_REALTIME
: return REALTIME_PRIORITY_CLASS
;
715 /******************************************************************
716 * GetProcessHandleCount (kernelbase.@)
718 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessHandleCount( HANDLE process
, DWORD
*count
)
720 return set_ntstatus( NtQueryInformationProcess( process
, ProcessHandleCount
,
721 count
, sizeof(*count
), NULL
));
725 /***********************************************************************
726 * GetProcessHeap (kernelbase.@)
728 HANDLE WINAPI
kernelbase_GetProcessHeap(void)
730 return NtCurrentTeb()->Peb
->ProcessHeap
;
734 /*********************************************************************
735 * GetProcessId (kernelbase.@)
737 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessId( HANDLE process
)
739 PROCESS_BASIC_INFORMATION pbi
;
741 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
742 &pbi
, sizeof(pbi
), NULL
)))
744 return pbi
.UniqueProcessId
;
748 /**********************************************************************
749 * GetProcessMitigationPolicy (kernelbase.@)
751 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process
, PROCESS_MITIGATION_POLICY policy
,
752 void *buffer
, SIZE_T length
)
754 FIXME( "(%p, %u, %p, %lu): stub\n", process
, policy
, buffer
, length
);
759 /***********************************************************************
760 * GetProcessPriorityBoost (kernelbase.@)
762 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessPriorityBoost( HANDLE process
, PBOOL disable
)
764 FIXME( "(%p,%p): semi-stub\n", process
, disable
);
765 *disable
= FALSE
; /* report that no boost is present */
770 /***********************************************************************
771 * GetProcessShutdownParameters (kernelbase.@)
773 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessShutdownParameters( LPDWORD level
, LPDWORD flags
)
775 *level
= shutdown_priority
;
776 *flags
= shutdown_flags
;
781 /***********************************************************************
782 * GetProcessWorkingSetSizeEx (kernelbase.@)
784 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T
*minset
,
785 SIZE_T
*maxset
, DWORD
*flags
)
787 FIXME( "(%p,%p,%p,%p): stub\n", process
, minset
, maxset
, flags
);
788 /* 32 MB working set size */
789 if (minset
) *minset
= 32*1024*1024;
790 if (maxset
) *maxset
= 32*1024*1024;
791 if (flags
) *flags
= QUOTA_LIMITS_HARDWS_MIN_DISABLE
| QUOTA_LIMITS_HARDWS_MAX_DISABLE
;
796 /******************************************************************************
797 * IsProcessInJob (kernelbase.@)
799 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessInJob( HANDLE process
, HANDLE job
, BOOL
*result
)
801 NTSTATUS status
= NtIsProcessInJob( process
, job
);
805 case STATUS_PROCESS_IN_JOB
:
808 case STATUS_PROCESS_NOT_IN_JOB
:
812 return set_ntstatus( status
);
817 /***********************************************************************
818 * IsProcessorFeaturePresent (kernelbase.@)
820 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessorFeaturePresent ( DWORD feature
)
822 return RtlIsProcessorFeaturePresent( feature
);
826 /**********************************************************************
827 * IsWow64Process (kernelbase.@)
829 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process( HANDLE process
, PBOOL wow64
)
834 status
= NtQueryInformationProcess( process
, ProcessWow64Information
, &pbi
, sizeof(pbi
), NULL
);
835 if (!status
) *wow64
= !!pbi
;
836 return set_ntstatus( status
);
840 /*********************************************************************
841 * OpenProcess (kernelbase.@)
843 HANDLE WINAPI DECLSPEC_HOTPATCH
OpenProcess( DWORD access
, BOOL inherit
, DWORD id
)
846 OBJECT_ATTRIBUTES attr
;
849 if (GetVersion() & 0x80000000) access
= PROCESS_ALL_ACCESS
;
851 attr
.Length
= sizeof(OBJECT_ATTRIBUTES
);
852 attr
.RootDirectory
= 0;
853 attr
.Attributes
= inherit
? OBJ_INHERIT
: 0;
854 attr
.ObjectName
= NULL
;
855 attr
.SecurityDescriptor
= NULL
;
856 attr
.SecurityQualityOfService
= NULL
;
858 cid
.UniqueProcess
= ULongToHandle(id
);
859 cid
.UniqueThread
= 0;
861 if (!set_ntstatus( NtOpenProcess( &handle
, access
, &attr
, &cid
))) return NULL
;
866 /***********************************************************************
867 * SetErrorMode (kernelbase.@)
869 UINT WINAPI DECLSPEC_HOTPATCH
SetErrorMode( UINT mode
)
871 UINT old
= GetErrorMode();
873 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
874 &mode
, sizeof(mode
) );
879 /*************************************************************************
880 * SetHandleCount (kernelbase.@)
882 UINT WINAPI DECLSPEC_HOTPATCH
SetHandleCount( UINT count
)
888 /*********************************************************************
889 * SetHandleInformation (kernelbase.@)
891 BOOL WINAPI DECLSPEC_HOTPATCH
SetHandleInformation( HANDLE handle
, DWORD mask
, DWORD flags
)
893 OBJECT_DATA_INFORMATION info
;
895 /* if not setting both fields, retrieve current value first */
896 if ((mask
& (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
)) !=
897 (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
))
899 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
902 if (mask
& HANDLE_FLAG_INHERIT
)
903 info
.InheritHandle
= (flags
& HANDLE_FLAG_INHERIT
) != 0;
904 if (mask
& HANDLE_FLAG_PROTECT_FROM_CLOSE
)
905 info
.ProtectFromClose
= (flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
) != 0;
907 return set_ntstatus( NtSetInformationObject( handle
, ObjectDataInformation
, &info
, sizeof(info
) ));
911 /***********************************************************************
912 * SetPriorityClass (kernelbase.@)
914 BOOL WINAPI DECLSPEC_HOTPATCH
SetPriorityClass( HANDLE process
, DWORD
class )
916 PROCESS_PRIORITY_CLASS ppc
;
918 ppc
.Foreground
= FALSE
;
921 case IDLE_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_IDLE
; break;
922 case BELOW_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_BELOW_NORMAL
; break;
923 case NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_NORMAL
; break;
924 case ABOVE_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_ABOVE_NORMAL
; break;
925 case HIGH_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_HIGH
; break;
926 case REALTIME_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_REALTIME
; break;
928 SetLastError( ERROR_INVALID_PARAMETER
);
931 return set_ntstatus( NtSetInformationProcess( process
, ProcessPriorityClass
, &ppc
, sizeof(ppc
) ));
935 /***********************************************************************
936 * SetProcessAffinityUpdateMode (kernelbase.@)
938 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessAffinityUpdateMode( HANDLE process
, DWORD flags
)
940 FIXME( "(%p,0x%08x): stub\n", process
, flags
);
941 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
946 /**********************************************************************
947 * SetProcessMitigationPolicy (kernelbase.@)
949 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy
,
950 void *buffer
, SIZE_T length
)
952 FIXME( "(%d, %p, %lu): stub\n", policy
, buffer
, length
);
957 /***********************************************************************
958 * SetProcessPriorityBoost (kernelbase.@)
960 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process
, BOOL disable
)
962 FIXME( "(%p,%d): stub\n", process
, disable
);
967 /***********************************************************************
968 * SetProcessShutdownParameters (kernelbase.@)
970 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessShutdownParameters( DWORD level
, DWORD flags
)
972 FIXME( "(%08x, %08x): partial stub.\n", level
, flags
);
973 shutdown_flags
= flags
;
974 shutdown_priority
= level
;
979 /***********************************************************************
980 * SetProcessWorkingSetSizeEx (kernelbase.@)
982 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T minset
,
983 SIZE_T maxset
, DWORD flags
)
989 /******************************************************************************
990 * TerminateProcess (kernelbase.@)
992 BOOL WINAPI DECLSPEC_HOTPATCH
TerminateProcess( HANDLE handle
, DWORD exit_code
)
996 SetLastError( ERROR_INVALID_HANDLE
);
999 return set_ntstatus( NtTerminateProcess( handle
, exit_code
));
1003 /***********************************************************************
1004 * Process startup information
1005 ***********************************************************************/
1008 static STARTUPINFOW startup_infoW
;
1009 static char *command_lineA
;
1010 static WCHAR
*command_lineW
;
1012 /******************************************************************
1015 void init_startup_info( RTL_USER_PROCESS_PARAMETERS
*params
)
1019 startup_infoW
.cb
= sizeof(startup_infoW
);
1020 startup_infoW
.lpReserved
= NULL
;
1021 startup_infoW
.lpDesktop
= params
->Desktop
.Buffer
;
1022 startup_infoW
.lpTitle
= params
->WindowTitle
.Buffer
;
1023 startup_infoW
.dwX
= params
->dwX
;
1024 startup_infoW
.dwY
= params
->dwY
;
1025 startup_infoW
.dwXSize
= params
->dwXSize
;
1026 startup_infoW
.dwYSize
= params
->dwYSize
;
1027 startup_infoW
.dwXCountChars
= params
->dwXCountChars
;
1028 startup_infoW
.dwYCountChars
= params
->dwYCountChars
;
1029 startup_infoW
.dwFillAttribute
= params
->dwFillAttribute
;
1030 startup_infoW
.dwFlags
= params
->dwFlags
;
1031 startup_infoW
.wShowWindow
= params
->wShowWindow
;
1032 startup_infoW
.cbReserved2
= params
->RuntimeInfo
.MaximumLength
;
1033 startup_infoW
.lpReserved2
= params
->RuntimeInfo
.MaximumLength
? (void *)params
->RuntimeInfo
.Buffer
: NULL
;
1034 startup_infoW
.hStdInput
= params
->hStdInput
? params
->hStdInput
: INVALID_HANDLE_VALUE
;
1035 startup_infoW
.hStdOutput
= params
->hStdOutput
? params
->hStdOutput
: INVALID_HANDLE_VALUE
;
1036 startup_infoW
.hStdError
= params
->hStdError
? params
->hStdError
: INVALID_HANDLE_VALUE
;
1038 command_lineW
= params
->CommandLine
.Buffer
;
1039 if (!RtlUnicodeStringToAnsiString( &ansi
, ¶ms
->CommandLine
, TRUE
)) command_lineA
= ansi
.Buffer
;
1043 /***********************************************************************
1044 * GetCommandLineA (kernelbase.@)
1046 LPSTR WINAPI DECLSPEC_HOTPATCH
GetCommandLineA(void)
1048 return command_lineA
;
1052 /***********************************************************************
1053 * GetCommandLineW (kernelbase.@)
1055 LPWSTR WINAPI DECLSPEC_HOTPATCH
GetCommandLineW(void)
1057 return NtCurrentTeb()->Peb
->ProcessParameters
->CommandLine
.Buffer
;
1061 /***********************************************************************
1062 * GetStartupInfoW (kernelbase.@)
1064 void WINAPI DECLSPEC_HOTPATCH
GetStartupInfoW( STARTUPINFOW
*info
)
1066 *info
= startup_infoW
;
1070 /***********************************************************************
1071 * GetStdHandle (kernelbase.@)
1073 HANDLE WINAPI DECLSPEC_HOTPATCH
GetStdHandle( DWORD std_handle
)
1077 case STD_INPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
1078 case STD_OUTPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
1079 case STD_ERROR_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
1081 SetLastError( ERROR_INVALID_HANDLE
);
1082 return INVALID_HANDLE_VALUE
;
1086 /***********************************************************************
1087 * SetStdHandle (kernelbase.@)
1089 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandle( DWORD std_handle
, HANDLE handle
)
1093 case STD_INPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
= handle
; return TRUE
;
1094 case STD_OUTPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
= handle
; return TRUE
;
1095 case STD_ERROR_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
= handle
; return TRUE
;
1097 SetLastError( ERROR_INVALID_HANDLE
);
1102 /***********************************************************************
1103 * SetStdHandleEx (kernelbase.@)
1105 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandleEx( DWORD std_handle
, HANDLE handle
, HANDLE
*prev
)
1111 case STD_INPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
; break;
1112 case STD_OUTPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
; break;
1113 case STD_ERROR_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
; break;
1115 SetLastError( ERROR_INVALID_HANDLE
);
1118 if (prev
) *prev
= *ptr
;
1124 /***********************************************************************
1125 * Process environment
1126 ***********************************************************************/
1129 static inline SIZE_T
get_env_length( const WCHAR
*env
)
1131 const WCHAR
*end
= env
;
1132 while (*end
) end
+= lstrlenW(end
) + 1;
1133 return end
+ 1 - env
;
1136 /***********************************************************************
1137 * ExpandEnvironmentStringsA (kernelbase.@)
1139 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsA( LPCSTR src
, LPSTR dst
, DWORD count
)
1141 UNICODE_STRING us_src
;
1145 RtlCreateUnicodeStringFromAsciiz( &us_src
, src
);
1148 if (!(dstW
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
)))) return 0;
1149 ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, dstW
, count
);
1150 if (ret
) WideCharToMultiByte( CP_ACP
, 0, dstW
, ret
, dst
, count
, NULL
, NULL
);
1152 else ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, NULL
, 0 );
1154 RtlFreeUnicodeString( &us_src
);
1155 HeapFree( GetProcessHeap(), 0, dstW
);
1160 /***********************************************************************
1161 * ExpandEnvironmentStringsW (kernelbase.@)
1163 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsW( LPCWSTR src
, LPWSTR dst
, DWORD len
)
1165 UNICODE_STRING us_src
, us_dst
;
1169 TRACE( "(%s %p %u)\n", debugstr_w(src
), dst
, len
);
1171 RtlInitUnicodeString( &us_src
, src
);
1173 /* make sure we don't overflow the maximum UNICODE_STRING size */
1174 len
= min( len
, UNICODE_STRING_MAX_CHARS
);
1177 us_dst
.MaximumLength
= len
* sizeof(WCHAR
);
1178 us_dst
.Buffer
= dst
;
1181 status
= RtlExpandEnvironmentStrings_U( NULL
, &us_src
, &us_dst
, &res
);
1182 res
/= sizeof(WCHAR
);
1183 if (!set_ntstatus( status
))
1185 if (status
!= STATUS_BUFFER_TOO_SMALL
) return 0;
1186 if (len
&& dst
) dst
[len
- 1] = 0;
1192 /***********************************************************************
1193 * GetEnvironmentStrings (kernelbase.@)
1194 * GetEnvironmentStringsA (kernelbase.@)
1196 LPSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsA(void)
1202 RtlAcquirePebLock();
1203 env
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
1204 lenW
= get_env_length( env
);
1205 lenA
= WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, NULL
, 0, NULL
, NULL
);
1206 if ((ret
= HeapAlloc( GetProcessHeap(), 0, lenA
)))
1207 WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, ret
, lenA
, NULL
, NULL
);
1208 RtlReleasePebLock();
1213 /***********************************************************************
1214 * GetEnvironmentStringsW (kernelbase.@)
1216 LPWSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsW(void)
1221 RtlAcquirePebLock();
1222 len
= get_env_length( NtCurrentTeb()->Peb
->ProcessParameters
->Environment
) * sizeof(WCHAR
);
1223 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
1224 memcpy( ret
, NtCurrentTeb()->Peb
->ProcessParameters
->Environment
, len
);
1225 RtlReleasePebLock();
1230 /***********************************************************************
1231 * GetEnvironmentVariableA (kernelbase.@)
1233 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableA( LPCSTR name
, LPSTR value
, DWORD size
)
1235 UNICODE_STRING us_name
;
1239 /* limit the size to sane values */
1240 size
= min( size
, 32767 );
1241 if (!(valueW
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1243 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1245 ret
= GetEnvironmentVariableW( us_name
.Buffer
, valueW
, size
);
1246 if (ret
&& ret
< size
) WideCharToMultiByte( CP_ACP
, 0, valueW
, ret
+ 1, value
, size
, NULL
, NULL
);
1248 /* this is needed to tell, with 0 as a return value, the difference between:
1249 * - an error (GetLastError() != 0)
1250 * - returning an empty string (in this case, we need to update the buffer)
1252 if (ret
== 0 && size
&& GetLastError() == 0) value
[0] = 0;
1253 RtlFreeUnicodeString( &us_name
);
1254 HeapFree( GetProcessHeap(), 0, valueW
);
1259 /***********************************************************************
1260 * GetEnvironmentVariableW (kernelbase.@)
1262 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableW( LPCWSTR name
, LPWSTR val
, DWORD size
)
1264 UNICODE_STRING us_name
, us_value
;
1268 TRACE( "(%s %p %u)\n", debugstr_w(name
), val
, size
);
1270 RtlInitUnicodeString( &us_name
, name
);
1271 us_value
.Length
= 0;
1272 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1273 us_value
.Buffer
= val
;
1275 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1276 len
= us_value
.Length
/ sizeof(WCHAR
);
1277 if (!set_ntstatus( status
)) return (status
== STATUS_BUFFER_TOO_SMALL
) ? len
+ 1 : 0;
1278 if (size
) val
[len
] = 0;
1283 /***********************************************************************
1284 * FreeEnvironmentStringsA (kernelbase.@)
1285 * FreeEnvironmentStringsW (kernelbase.@)
1287 BOOL WINAPI DECLSPEC_HOTPATCH
FreeEnvironmentStringsW( LPWSTR ptr
)
1289 return HeapFree( GetProcessHeap(), 0, ptr
);
1293 /***********************************************************************
1294 * SetEnvironmentVariableA (kernelbase.@)
1296 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableA( LPCSTR name
, LPCSTR value
)
1298 UNICODE_STRING us_name
, us_value
;
1303 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1307 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1310 RtlCreateUnicodeStringFromAsciiz( &us_value
, value
);
1311 ret
= SetEnvironmentVariableW( us_name
.Buffer
, us_value
.Buffer
);
1312 RtlFreeUnicodeString( &us_value
);
1314 else ret
= SetEnvironmentVariableW( us_name
.Buffer
, NULL
);
1315 RtlFreeUnicodeString( &us_name
);
1320 /***********************************************************************
1321 * SetEnvironmentVariableW (kernelbase.@)
1323 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableW( LPCWSTR name
, LPCWSTR value
)
1325 UNICODE_STRING us_name
, us_value
;
1328 TRACE( "(%s %s)\n", debugstr_w(name
), debugstr_w(value
) );
1332 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1336 RtlInitUnicodeString( &us_name
, name
);
1339 RtlInitUnicodeString( &us_value
, value
);
1340 status
= RtlSetEnvironmentVariable( NULL
, &us_name
, &us_value
);
1342 else status
= RtlSetEnvironmentVariable( NULL
, &us_name
, NULL
);
1344 return set_ntstatus( status
);
1348 /***********************************************************************
1349 * Process/thread attribute lists
1350 ***********************************************************************/
1352 /***********************************************************************
1353 * InitializeProcThreadAttributeList (kernelbase.@)
1355 BOOL WINAPI DECLSPEC_HOTPATCH
InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1356 DWORD count
, DWORD flags
, SIZE_T
*size
)
1361 TRACE( "(%p %d %x %p)\n", list
, count
, flags
, size
);
1363 needed
= FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST
, attrs
[count
] );
1364 if (list
&& *size
>= needed
)
1372 else SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1379 /***********************************************************************
1380 * UpdateProcThreadAttribute (kernelbase.@)
1382 BOOL WINAPI DECLSPEC_HOTPATCH
UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1383 DWORD flags
, DWORD_PTR attr
, void *value
,
1384 SIZE_T size
, void *prev_ret
, SIZE_T
*size_ret
)
1387 struct proc_thread_attr
*entry
;
1389 TRACE( "(%p %x %08lx %p %ld %p %p)\n", list
, flags
, attr
, value
, size
, prev_ret
, size_ret
);
1391 if (list
->count
>= list
->size
)
1393 SetLastError( ERROR_GEN_FAILURE
);
1399 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
1400 if (size
!= sizeof(HANDLE
))
1402 SetLastError( ERROR_BAD_LENGTH
);
1407 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
1408 if ((size
/ sizeof(HANDLE
)) * sizeof(HANDLE
) != size
)
1410 SetLastError( ERROR_BAD_LENGTH
);
1415 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR
:
1416 if (size
!= sizeof(PROCESSOR_NUMBER
))
1418 SetLastError( ERROR_BAD_LENGTH
);
1423 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY
:
1424 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
))
1426 SetLastError( ERROR_BAD_LENGTH
);
1431 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
:
1432 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
) && size
!= sizeof(DWORD64
) * 2)
1434 SetLastError( ERROR_BAD_LENGTH
);
1440 SetLastError( ERROR_NOT_SUPPORTED
);
1441 FIXME( "Unhandled attribute %lu\n", attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1445 mask
= 1 << (attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1446 if (list
->mask
& mask
)
1448 SetLastError( ERROR_OBJECT_NAME_EXISTS
);
1453 entry
= list
->attrs
+ list
->count
;
1456 entry
->value
= value
;
1462 /***********************************************************************
1463 * DeleteProcThreadAttributeList (kernelbase.@)
1465 void WINAPI DECLSPEC_HOTPATCH
DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
)