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
27 #define NONAMELESSSTRUCT
31 #include "wincontypes.h"
34 #include "kernelbase.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(process
);
39 static DWORD shutdown_flags
= 0;
40 static DWORD shutdown_priority
= 0x280;
42 /***********************************************************************
44 ***********************************************************************/
47 /***********************************************************************
50 static BOOL
find_exe_file( const WCHAR
*name
, WCHAR
*buffer
, DWORD buflen
)
55 if (!set_ntstatus( RtlGetExePath( name
, &load_path
))) return FALSE
;
57 TRACE( "looking for %s in %s\n", debugstr_w(name
), debugstr_w(load_path
) );
59 ret
= (SearchPathW( load_path
, name
, L
".exe", buflen
, buffer
, NULL
) ||
60 /* not found, try without extension in case it is a Unix app */
61 SearchPathW( load_path
, name
, NULL
, buflen
, buffer
, NULL
));
63 if (ret
) /* make sure it can be opened, SearchPathW also returns directories */
65 HANDLE handle
= CreateFileW( buffer
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_DELETE
,
66 NULL
, OPEN_EXISTING
, 0, 0 );
67 if ((ret
= (handle
!= INVALID_HANDLE_VALUE
))) CloseHandle( handle
);
69 RtlReleasePath( load_path
);
74 /*************************************************************************
77 * Helper for CreateProcess: retrieve the file name to load from the
78 * app name and command line. Store the file name in buffer, and
79 * return a possibly modified command line.
81 static WCHAR
*get_file_name( WCHAR
*cmdline
, WCHAR
*buffer
, DWORD buflen
)
83 WCHAR
*name
, *pos
, *first_space
, *ret
= NULL
;
86 /* first check for a quoted file name */
88 if (cmdline
[0] == '"' && (p
= wcschr( cmdline
+ 1, '"' )))
90 int len
= p
- cmdline
- 1;
91 /* extract the quoted portion as file name */
92 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
93 memcpy( name
, cmdline
+ 1, len
* sizeof(WCHAR
) );
96 if (!find_exe_file( name
, buffer
, buflen
)) goto done
;
97 ret
= cmdline
; /* no change necessary */
101 /* now try the command-line word by word */
103 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline
) + 1) * sizeof(WCHAR
) )))
111 while (*p
&& *p
!= ' ' && *p
!= '\t') *pos
++ = *p
++;
113 if (find_exe_file( name
, buffer
, buflen
))
118 if (!first_space
) first_space
= pos
;
119 if (!(*pos
++ = *p
++)) break;
124 SetLastError( ERROR_FILE_NOT_FOUND
);
126 else if (first_space
) /* build a new command-line with quotes */
128 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline
) + 3) * sizeof(WCHAR
) )))
130 swprintf( ret
, lstrlenW(cmdline
) + 3, L
"\"%s\"%s", name
, p
);
134 RtlFreeHeap( GetProcessHeap(), 0, name
);
139 /***********************************************************************
140 * create_process_params
142 static RTL_USER_PROCESS_PARAMETERS
*create_process_params( const WCHAR
*filename
, const WCHAR
*cmdline
,
143 const WCHAR
*cur_dir
, void *env
, DWORD flags
,
144 const STARTUPINFOW
*startup
)
146 RTL_USER_PROCESS_PARAMETERS
*params
;
147 UNICODE_STRING imageW
, curdirW
, cmdlineW
, titleW
, desktopW
, runtimeW
, newdirW
;
148 WCHAR imagepath
[MAX_PATH
];
151 if (!GetLongPathNameW( filename
, imagepath
, MAX_PATH
)) lstrcpynW( imagepath
, filename
, MAX_PATH
);
152 if (!GetFullPathNameW( imagepath
, MAX_PATH
, imagepath
, NULL
)) lstrcpynW( imagepath
, filename
, MAX_PATH
);
154 if (env
&& !(flags
& CREATE_UNICODE_ENVIRONMENT
)) /* convert environment to unicode */
159 while (*e
) e
+= strlen(e
) + 1;
160 e
++; /* final null */
161 lenW
= MultiByteToWideChar( CP_ACP
, 0, env
, e
- (char *)env
, NULL
, 0 );
162 if ((envW
= RtlAllocateHeap( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
163 MultiByteToWideChar( CP_ACP
, 0, env
, e
- (char *)env
, envW
, lenW
);
166 newdirW
.Buffer
= NULL
;
169 if (RtlDosPathNameToNtPathName_U( cur_dir
, &newdirW
, NULL
, NULL
))
170 cur_dir
= newdirW
.Buffer
+ 4; /* skip \??\ prefix */
174 RtlInitUnicodeString( &imageW
, imagepath
);
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
, NULL
, cur_dir
? &curdirW
: NULL
,
182 &cmdlineW
, envW
, &titleW
, &desktopW
,
183 NULL
, &runtimeW
, PROCESS_PARAMS_FLAG_NORMALIZED
))
185 RtlFreeUnicodeString( &newdirW
);
186 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
189 RtlFreeUnicodeString( &newdirW
);
191 if (flags
& CREATE_NEW_PROCESS_GROUP
) params
->ConsoleFlags
= 1;
192 if (flags
& CREATE_NEW_CONSOLE
) params
->ConsoleHandle
= (HANDLE
)1; /* KERNEL32_CONSOLE_ALLOC */
193 else if (!(flags
& DETACHED_PROCESS
)) params
->ConsoleHandle
= NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleHandle
;
195 if (startup
->dwFlags
& STARTF_USESTDHANDLES
)
197 params
->hStdInput
= startup
->hStdInput
;
198 params
->hStdOutput
= startup
->hStdOutput
;
199 params
->hStdError
= startup
->hStdError
;
201 else if (flags
& DETACHED_PROCESS
)
203 params
->hStdInput
= INVALID_HANDLE_VALUE
;
204 params
->hStdOutput
= INVALID_HANDLE_VALUE
;
205 params
->hStdError
= INVALID_HANDLE_VALUE
;
209 params
->hStdInput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
210 params
->hStdOutput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
211 params
->hStdError
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
214 params
->dwX
= startup
->dwX
;
215 params
->dwY
= startup
->dwY
;
216 params
->dwXSize
= startup
->dwXSize
;
217 params
->dwYSize
= startup
->dwYSize
;
218 params
->dwXCountChars
= startup
->dwXCountChars
;
219 params
->dwYCountChars
= startup
->dwYCountChars
;
220 params
->dwFillAttribute
= startup
->dwFillAttribute
;
221 params
->dwFlags
= startup
->dwFlags
;
222 params
->wShowWindow
= startup
->wShowWindow
;
224 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
228 struct proc_thread_attr
235 struct _PROC_THREAD_ATTRIBUTE_LIST
237 DWORD mask
; /* bitmask of items in list */
238 DWORD size
; /* max number of items in list */
239 DWORD count
; /* number of items in list */
242 struct proc_thread_attr attrs
[1];
245 /***********************************************************************
248 static NTSTATUS
create_nt_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
249 SECURITY_ATTRIBUTES
*tsa
, BOOL inherit
, DWORD flags
,
250 RTL_USER_PROCESS_PARAMETERS
*params
,
251 RTL_USER_PROCESS_INFORMATION
*info
, HANDLE parent
,
252 const struct proc_thread_attr
*handle_list
)
254 OBJECT_ATTRIBUTES process_attr
, thread_attr
;
255 PS_CREATE_INFO create_info
;
256 ULONG_PTR buffer
[offsetof( PS_ATTRIBUTE_LIST
, Attributes
[7] ) / sizeof(ULONG_PTR
)];
257 PS_ATTRIBUTE_LIST
*attr
= (PS_ATTRIBUTE_LIST
*)buffer
;
258 UNICODE_STRING nameW
;
262 if (!params
->ImagePathName
.Buffer
[0]) return STATUS_OBJECT_PATH_NOT_FOUND
;
263 status
= RtlDosPathNameToNtPathName_U_WithStatus( params
->ImagePathName
.Buffer
, &nameW
, NULL
, NULL
);
266 params
->DebugFlags
= flags
; /* hack, cf. RtlCreateUserProcess implementation */
268 RtlNormalizeProcessParams( params
);
270 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_NAME
;
271 attr
->Attributes
[pos
].Size
= nameW
.Length
;
272 attr
->Attributes
[pos
].ValuePtr
= nameW
.Buffer
;
273 attr
->Attributes
[pos
].ReturnLength
= NULL
;
275 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_CLIENT_ID
;
276 attr
->Attributes
[pos
].Size
= sizeof(info
->ClientId
);
277 attr
->Attributes
[pos
].ValuePtr
= &info
->ClientId
;
278 attr
->Attributes
[pos
].ReturnLength
= NULL
;
280 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_INFO
;
281 attr
->Attributes
[pos
].Size
= sizeof(info
->ImageInformation
);
282 attr
->Attributes
[pos
].ValuePtr
= &info
->ImageInformation
;
283 attr
->Attributes
[pos
].ReturnLength
= NULL
;
287 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_PARENT_PROCESS
;
288 attr
->Attributes
[pos
].Size
= sizeof(parent
);
289 attr
->Attributes
[pos
].ValuePtr
= parent
;
290 attr
->Attributes
[pos
].ReturnLength
= NULL
;
293 if (inherit
&& handle_list
)
295 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_HANDLE_LIST
;
296 attr
->Attributes
[pos
].Size
= handle_list
->size
;
297 attr
->Attributes
[pos
].ValuePtr
= handle_list
->value
;
298 attr
->Attributes
[pos
].ReturnLength
= NULL
;
303 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_TOKEN
;
304 attr
->Attributes
[pos
].Size
= sizeof(token
);
305 attr
->Attributes
[pos
].ValuePtr
= token
;
306 attr
->Attributes
[pos
].ReturnLength
= NULL
;
311 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_DEBUG_PORT
;
312 attr
->Attributes
[pos
].Size
= sizeof(debug
);
313 attr
->Attributes
[pos
].ValuePtr
= debug
;
314 attr
->Attributes
[pos
].ReturnLength
= NULL
;
317 attr
->TotalLength
= offsetof( PS_ATTRIBUTE_LIST
, Attributes
[pos
] );
319 InitializeObjectAttributes( &process_attr
, NULL
, 0, NULL
, psa
? psa
->lpSecurityDescriptor
: NULL
);
320 InitializeObjectAttributes( &thread_attr
, NULL
, 0, NULL
, tsa
? tsa
->lpSecurityDescriptor
: NULL
);
322 status
= NtCreateUserProcess( &info
->Process
, &info
->Thread
, PROCESS_ALL_ACCESS
, THREAD_ALL_ACCESS
,
323 &process_attr
, &thread_attr
,
324 inherit
? PROCESS_CREATE_FLAGS_INHERIT_HANDLES
: 0,
325 THREAD_CREATE_FLAGS_CREATE_SUSPENDED
, params
,
326 &create_info
, attr
);
328 RtlFreeUnicodeString( &nameW
);
334 /***********************************************************************
337 static NTSTATUS
create_vdm_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
338 SECURITY_ATTRIBUTES
*tsa
, BOOL inherit
, DWORD flags
,
339 RTL_USER_PROCESS_PARAMETERS
*params
,
340 RTL_USER_PROCESS_INFORMATION
*info
)
342 const WCHAR
*winevdm
= (is_win64
|| is_wow64
?
343 L
"C:\\windows\\syswow64\\winevdm.exe" :
344 L
"C:\\windows\\system32\\winevdm.exe");
349 len
= (lstrlenW(params
->ImagePathName
.Buffer
) + lstrlenW(params
->CommandLine
.Buffer
) +
350 lstrlenW(winevdm
) + 16);
352 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
353 return STATUS_NO_MEMORY
;
355 swprintf( newcmdline
, len
, L
"%s --app-name \"%s\" %s",
356 winevdm
, params
->ImagePathName
.Buffer
, params
->CommandLine
.Buffer
);
357 RtlInitUnicodeString( ¶ms
->ImagePathName
, winevdm
);
358 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
359 status
= create_nt_process( token
, debug
, psa
, tsa
, inherit
, flags
, params
, info
, NULL
, NULL
);
360 HeapFree( GetProcessHeap(), 0, newcmdline
);
365 /***********************************************************************
368 static NTSTATUS
create_cmd_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
369 SECURITY_ATTRIBUTES
*tsa
, BOOL inherit
, DWORD flags
,
370 RTL_USER_PROCESS_PARAMETERS
*params
,
371 RTL_USER_PROCESS_INFORMATION
*info
)
373 WCHAR comspec
[MAX_PATH
];
378 if (!GetEnvironmentVariableW( L
"COMSPEC", comspec
, ARRAY_SIZE( comspec
)))
379 lstrcpyW( comspec
, L
"C:\\windows\\system32\\cmd.exe" );
381 len
= lstrlenW(comspec
) + 7 + lstrlenW(params
->CommandLine
.Buffer
) + 2;
382 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
383 return STATUS_NO_MEMORY
;
385 swprintf( newcmdline
, len
, L
"%s /s/c \"%s\"", comspec
, params
->CommandLine
.Buffer
);
386 RtlInitUnicodeString( ¶ms
->ImagePathName
, comspec
);
387 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
388 status
= create_nt_process( token
, debug
, psa
, tsa
, inherit
, flags
, params
, info
, NULL
, NULL
);
389 RtlFreeHeap( GetProcessHeap(), 0, newcmdline
);
394 /*********************************************************************
395 * CloseHandle (kernelbase.@)
397 BOOL WINAPI DECLSPEC_HOTPATCH
CloseHandle( HANDLE handle
)
399 if (handle
== (HANDLE
)STD_INPUT_HANDLE
)
400 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
, 0 );
401 else if (handle
== (HANDLE
)STD_OUTPUT_HANDLE
)
402 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
, 0 );
403 else if (handle
== (HANDLE
)STD_ERROR_HANDLE
)
404 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
, 0 );
406 return set_ntstatus( NtClose( handle
));
410 /**********************************************************************
411 * CreateProcessAsUserA (kernelbase.@)
413 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserA( HANDLE token
, const char *app_name
, char *cmd_line
,
414 SECURITY_ATTRIBUTES
*process_attr
,
415 SECURITY_ATTRIBUTES
*thread_attr
,
416 BOOL inherit
, DWORD flags
, void *env
,
417 const char *cur_dir
, STARTUPINFOA
*startup_info
,
418 PROCESS_INFORMATION
*info
)
420 return CreateProcessInternalA( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
421 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
425 /**********************************************************************
426 * CreateProcessAsUserW (kernelbase.@)
428 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
429 SECURITY_ATTRIBUTES
*process_attr
,
430 SECURITY_ATTRIBUTES
*thread_attr
,
431 BOOL inherit
, DWORD flags
, void *env
,
432 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
433 PROCESS_INFORMATION
*info
)
435 return CreateProcessInternalW( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
436 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
439 /**********************************************************************
440 * CreateProcessInternalA (kernelbase.@)
442 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalA( HANDLE token
, const char *app_name
, char *cmd_line
,
443 SECURITY_ATTRIBUTES
*process_attr
,
444 SECURITY_ATTRIBUTES
*thread_attr
,
445 BOOL inherit
, DWORD flags
, void *env
,
446 const char *cur_dir
, STARTUPINFOA
*startup_info
,
447 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
450 WCHAR
*app_nameW
= NULL
, *cmd_lineW
= NULL
, *cur_dirW
= NULL
;
451 UNICODE_STRING desktopW
, titleW
;
452 STARTUPINFOEXW infoW
;
454 desktopW
.Buffer
= NULL
;
455 titleW
.Buffer
= NULL
;
456 if (app_name
&& !(app_nameW
= file_name_AtoW( app_name
, TRUE
))) goto done
;
457 if (cmd_line
&& !(cmd_lineW
= file_name_AtoW( cmd_line
, TRUE
))) goto done
;
458 if (cur_dir
&& !(cur_dirW
= file_name_AtoW( cur_dir
, TRUE
))) goto done
;
460 if (startup_info
->lpDesktop
) RtlCreateUnicodeStringFromAsciiz( &desktopW
, startup_info
->lpDesktop
);
461 if (startup_info
->lpTitle
) RtlCreateUnicodeStringFromAsciiz( &titleW
, startup_info
->lpTitle
);
463 memcpy( &infoW
.StartupInfo
, startup_info
, sizeof(infoW
.StartupInfo
) );
464 infoW
.StartupInfo
.lpDesktop
= desktopW
.Buffer
;
465 infoW
.StartupInfo
.lpTitle
= titleW
.Buffer
;
467 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
468 infoW
.lpAttributeList
= ((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
470 ret
= CreateProcessInternalW( token
, app_nameW
, cmd_lineW
, process_attr
, thread_attr
,
471 inherit
, flags
, env
, cur_dirW
, (STARTUPINFOW
*)&infoW
, info
, new_token
);
473 RtlFreeHeap( GetProcessHeap(), 0, app_nameW
);
474 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW
);
475 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW
);
476 RtlFreeUnicodeString( &desktopW
);
477 RtlFreeUnicodeString( &titleW
);
481 /**********************************************************************
482 * CreateProcessInternalW (kernelbase.@)
484 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
485 SECURITY_ATTRIBUTES
*process_attr
,
486 SECURITY_ATTRIBUTES
*thread_attr
,
487 BOOL inherit
, DWORD flags
, void *env
,
488 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
489 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
491 const struct proc_thread_attr
*handle_list
= NULL
;
492 WCHAR name
[MAX_PATH
];
493 WCHAR
*p
, *tidy_cmdline
= cmd_line
;
494 RTL_USER_PROCESS_PARAMETERS
*params
= NULL
;
495 RTL_USER_PROCESS_INFORMATION rtl_info
;
496 HANDLE parent
= 0, debug
= 0;
499 /* Process the AppName and/or CmdLine to get module name and path */
501 TRACE( "app %s cmdline %s\n", debugstr_w(app_name
), debugstr_w(cmd_line
) );
503 if (new_token
) FIXME( "No support for returning created process token\n" );
507 if (!cmd_line
|| !cmd_line
[0]) /* no command-line, create one */
509 if (!(tidy_cmdline
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name
)+3) * sizeof(WCHAR
) )))
511 swprintf( tidy_cmdline
, lstrlenW(app_name
) + 3, L
"\"%s\"", app_name
);
516 if (!(tidy_cmdline
= get_file_name( cmd_line
, name
, ARRAY_SIZE(name
) ))) return FALSE
;
520 /* Warn if unsupported features are used */
522 if (flags
& (IDLE_PRIORITY_CLASS
| HIGH_PRIORITY_CLASS
| REALTIME_PRIORITY_CLASS
|
523 CREATE_DEFAULT_ERROR_MODE
| CREATE_NO_WINDOW
|
524 PROFILE_USER
| PROFILE_KERNEL
| PROFILE_SERVER
))
525 WARN( "(%s,...): ignoring some flags in %x\n", debugstr_w(app_name
), flags
);
529 DWORD attr
= GetFileAttributesW( cur_dir
);
530 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
532 status
= STATUS_NOT_A_DIRECTORY
;
537 info
->hThread
= info
->hProcess
= 0;
538 info
->dwProcessId
= info
->dwThreadId
= 0;
540 if (!(params
= create_process_params( app_name
, tidy_cmdline
, cur_dir
, env
, flags
, startup_info
)))
542 status
= STATUS_NO_MEMORY
;
546 if (flags
& (DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
))
548 if ((status
= DbgUiConnectToDbg())) goto done
;
549 debug
= DbgUiGetThreadDebugObject();
552 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
554 struct _PROC_THREAD_ATTRIBUTE_LIST
*attrs
=
555 (struct _PROC_THREAD_ATTRIBUTE_LIST
*)((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
560 for (i
= 0; i
< attrs
->count
; ++i
)
562 switch(attrs
->attrs
[i
].attr
)
564 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
565 parent
= *(HANDLE
*)attrs
->attrs
[i
].value
;
566 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent
);
569 status
= STATUS_INVALID_HANDLE
;
573 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
574 handle_list
= &attrs
->attrs
[i
];
575 TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs
->attrs
[i
].size
/ sizeof(HANDLE
));
577 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
579 struct pseudo_console
*console
= attrs
->attrs
[i
].value
;
580 TRACE( "PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE %p reference %p\n",
581 console
, console
->reference
);
582 params
->ConsoleHandle
= console
->reference
;
586 FIXME("Unsupported attribute %#Ix.\n", attrs
->attrs
[i
].attr
);
593 status
= create_nt_process( token
, debug
, process_attr
, thread_attr
, inherit
,
594 flags
, params
, &rtl_info
, parent
, handle_list
);
599 case STATUS_INVALID_IMAGE_WIN_16
:
600 case STATUS_INVALID_IMAGE_NE_FORMAT
:
601 case STATUS_INVALID_IMAGE_PROTECT
:
602 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name
) );
603 status
= create_vdm_process( token
, debug
, process_attr
, thread_attr
,
604 inherit
, flags
, params
, &rtl_info
);
606 case STATUS_INVALID_IMAGE_NOT_MZ
:
607 /* check for .com or .bat extension */
608 if (!(p
= wcsrchr( app_name
, '.' ))) break;
609 if (!wcsicmp( p
, L
".com" ) || !wcsicmp( p
, L
".pif" ))
611 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name
) );
612 status
= create_vdm_process( token
, debug
, process_attr
, thread_attr
,
613 inherit
, flags
, params
, &rtl_info
);
615 else if (!wcsicmp( p
, L
".bat" ) || !wcsicmp( p
, L
".cmd" ))
617 TRACE( "starting %s as batch binary\n", debugstr_w(app_name
) );
618 status
= create_cmd_process( token
, debug
, process_attr
, thread_attr
,
619 inherit
, flags
, params
, &rtl_info
);
626 info
->hProcess
= rtl_info
.Process
;
627 info
->hThread
= rtl_info
.Thread
;
628 info
->dwProcessId
= HandleToUlong( rtl_info
.ClientId
.UniqueProcess
);
629 info
->dwThreadId
= HandleToUlong( rtl_info
.ClientId
.UniqueThread
);
630 if (!(flags
& CREATE_SUSPENDED
)) NtResumeThread( rtl_info
.Thread
, NULL
);
631 TRACE( "started process pid %04x tid %04x\n", info
->dwProcessId
, info
->dwThreadId
);
635 RtlDestroyProcessParameters( params
);
636 if (tidy_cmdline
!= cmd_line
) HeapFree( GetProcessHeap(), 0, tidy_cmdline
);
637 return set_ntstatus( status
);
641 /**********************************************************************
642 * CreateProcessA (kernelbase.@)
644 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessA( const char *app_name
, char *cmd_line
,
645 SECURITY_ATTRIBUTES
*process_attr
,
646 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
,
647 DWORD flags
, void *env
, const char *cur_dir
,
648 STARTUPINFOA
*startup_info
, PROCESS_INFORMATION
*info
)
650 return CreateProcessInternalA( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
651 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
655 /**********************************************************************
656 * CreateProcessW (kernelbase.@)
658 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessW( const WCHAR
*app_name
, WCHAR
*cmd_line
,
659 SECURITY_ATTRIBUTES
*process_attr
,
660 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
, DWORD flags
,
661 void *env
, const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
662 PROCESS_INFORMATION
*info
)
664 return CreateProcessInternalW( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
665 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
669 /*********************************************************************
670 * DuplicateHandle (kernelbase.@)
672 BOOL WINAPI DECLSPEC_HOTPATCH
DuplicateHandle( HANDLE source_process
, HANDLE source
,
673 HANDLE dest_process
, HANDLE
*dest
,
674 DWORD access
, BOOL inherit
, DWORD options
)
676 return set_ntstatus( NtDuplicateObject( source_process
, source
, dest_process
, dest
,
677 access
, inherit
? OBJ_INHERIT
: 0, options
));
681 /****************************************************************************
682 * FlushInstructionCache (kernelbase.@)
684 BOOL WINAPI DECLSPEC_HOTPATCH
FlushInstructionCache( HANDLE process
, LPCVOID addr
, SIZE_T size
)
686 return set_ntstatus( NtFlushInstructionCache( process
, addr
, size
));
690 /***********************************************************************
691 * GetApplicationRestartSettings (kernelbase.@)
693 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ GetApplicationRestartSettings( HANDLE process
, WCHAR
*cmdline
,
694 DWORD
*size
, DWORD
*flags
)
696 FIXME( "%p, %p, %p, %p)\n", process
, cmdline
, size
, flags
);
701 /***********************************************************************
702 * GetCurrentProcess (kernelbase.@)
704 HANDLE WINAPI
kernelbase_GetCurrentProcess(void)
706 return (HANDLE
)~(ULONG_PTR
)0;
710 /***********************************************************************
711 * GetCurrentProcessId (kernelbase.@)
713 DWORD WINAPI
kernelbase_GetCurrentProcessId(void)
715 return HandleToULong( NtCurrentTeb()->ClientId
.UniqueProcess
);
719 /***********************************************************************
720 * GetErrorMode (kernelbase.@)
722 UINT WINAPI DECLSPEC_HOTPATCH
GetErrorMode(void)
726 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
727 &mode
, sizeof(mode
), NULL
);
732 /***********************************************************************
733 * GetExitCodeProcess (kernelbase.@)
735 BOOL WINAPI DECLSPEC_HOTPATCH
GetExitCodeProcess( HANDLE process
, LPDWORD exit_code
)
738 PROCESS_BASIC_INFORMATION pbi
;
740 status
= NtQueryInformationProcess( process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
741 if (!status
&& exit_code
) *exit_code
= pbi
.ExitStatus
;
742 return set_ntstatus( status
);
746 /*********************************************************************
747 * GetHandleInformation (kernelbase.@)
749 BOOL WINAPI DECLSPEC_HOTPATCH
GetHandleInformation( HANDLE handle
, DWORD
*flags
)
751 OBJECT_DATA_INFORMATION info
;
753 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
759 if (info
.InheritHandle
) *flags
|= HANDLE_FLAG_INHERIT
;
760 if (info
.ProtectFromClose
) *flags
|= HANDLE_FLAG_PROTECT_FROM_CLOSE
;
766 /***********************************************************************
767 * GetPriorityClass (kernelbase.@)
769 DWORD WINAPI DECLSPEC_HOTPATCH
GetPriorityClass( HANDLE process
)
771 PROCESS_BASIC_INFORMATION pbi
;
773 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
774 &pbi
, sizeof(pbi
), NULL
)))
777 switch (pbi
.BasePriority
)
779 case PROCESS_PRIOCLASS_IDLE
: return IDLE_PRIORITY_CLASS
;
780 case PROCESS_PRIOCLASS_BELOW_NORMAL
: return BELOW_NORMAL_PRIORITY_CLASS
;
781 case PROCESS_PRIOCLASS_NORMAL
: return NORMAL_PRIORITY_CLASS
;
782 case PROCESS_PRIOCLASS_ABOVE_NORMAL
: return ABOVE_NORMAL_PRIORITY_CLASS
;
783 case PROCESS_PRIOCLASS_HIGH
: return HIGH_PRIORITY_CLASS
;
784 case PROCESS_PRIOCLASS_REALTIME
: return REALTIME_PRIORITY_CLASS
;
790 /******************************************************************
791 * GetProcessHandleCount (kernelbase.@)
793 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessHandleCount( HANDLE process
, DWORD
*count
)
795 return set_ntstatus( NtQueryInformationProcess( process
, ProcessHandleCount
,
796 count
, sizeof(*count
), NULL
));
800 /***********************************************************************
801 * GetProcessHeap (kernelbase.@)
803 HANDLE WINAPI
kernelbase_GetProcessHeap(void)
805 return NtCurrentTeb()->Peb
->ProcessHeap
;
809 /*********************************************************************
810 * GetProcessId (kernelbase.@)
812 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessId( HANDLE process
)
814 PROCESS_BASIC_INFORMATION pbi
;
816 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
817 &pbi
, sizeof(pbi
), NULL
)))
819 return pbi
.UniqueProcessId
;
823 /**********************************************************************
824 * GetProcessMitigationPolicy (kernelbase.@)
826 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process
, PROCESS_MITIGATION_POLICY policy
,
827 void *buffer
, SIZE_T length
)
829 FIXME( "(%p, %u, %p, %lu): stub\n", process
, policy
, buffer
, length
);
834 /***********************************************************************
835 * GetProcessPriorityBoost (kernelbase.@)
837 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessPriorityBoost( HANDLE process
, PBOOL disable
)
839 FIXME( "(%p,%p): semi-stub\n", process
, disable
);
840 *disable
= FALSE
; /* report that no boost is present */
845 /***********************************************************************
846 * GetProcessShutdownParameters (kernelbase.@)
848 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessShutdownParameters( LPDWORD level
, LPDWORD flags
)
850 *level
= shutdown_priority
;
851 *flags
= shutdown_flags
;
856 /*********************************************************************
857 * GetProcessTimes (kernelbase.@)
859 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessTimes( HANDLE process
, FILETIME
*create
, FILETIME
*exit
,
860 FILETIME
*kernel
, FILETIME
*user
)
862 KERNEL_USER_TIMES time
;
864 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessTimes
, &time
, sizeof(time
), NULL
)))
867 create
->dwLowDateTime
= time
.CreateTime
.u
.LowPart
;
868 create
->dwHighDateTime
= time
.CreateTime
.u
.HighPart
;
869 exit
->dwLowDateTime
= time
.ExitTime
.u
.LowPart
;
870 exit
->dwHighDateTime
= time
.ExitTime
.u
.HighPart
;
871 kernel
->dwLowDateTime
= time
.KernelTime
.u
.LowPart
;
872 kernel
->dwHighDateTime
= time
.KernelTime
.u
.HighPart
;
873 user
->dwLowDateTime
= time
.UserTime
.u
.LowPart
;
874 user
->dwHighDateTime
= time
.UserTime
.u
.HighPart
;
879 /***********************************************************************
880 * GetProcessVersion (kernelbase.@)
882 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessVersion( DWORD pid
)
884 SECTION_IMAGE_INFORMATION info
;
888 if (pid
&& pid
!= GetCurrentProcessId())
890 if (!(process
= OpenProcess( PROCESS_QUERY_INFORMATION
, FALSE
, pid
))) return 0;
891 status
= NtQueryInformationProcess( process
, ProcessImageInformation
, &info
, sizeof(info
), NULL
);
892 CloseHandle( process
);
894 else status
= NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation
,
895 &info
, sizeof(info
), NULL
);
897 if (!set_ntstatus( status
)) return 0;
898 return MAKELONG( info
.MinorSubsystemVersion
, info
.MajorSubsystemVersion
);
902 /***********************************************************************
903 * GetProcessWorkingSetSizeEx (kernelbase.@)
905 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T
*minset
,
906 SIZE_T
*maxset
, DWORD
*flags
)
908 FIXME( "(%p,%p,%p,%p): stub\n", process
, minset
, maxset
, flags
);
909 /* 32 MB working set size */
910 if (minset
) *minset
= 32*1024*1024;
911 if (maxset
) *maxset
= 32*1024*1024;
912 if (flags
) *flags
= QUOTA_LIMITS_HARDWS_MIN_DISABLE
| QUOTA_LIMITS_HARDWS_MAX_DISABLE
;
917 /******************************************************************************
918 * IsProcessInJob (kernelbase.@)
920 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessInJob( HANDLE process
, HANDLE job
, BOOL
*result
)
922 NTSTATUS status
= NtIsProcessInJob( process
, job
);
926 case STATUS_PROCESS_IN_JOB
:
929 case STATUS_PROCESS_NOT_IN_JOB
:
933 return set_ntstatus( status
);
938 /***********************************************************************
939 * IsProcessorFeaturePresent (kernelbase.@)
941 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessorFeaturePresent ( DWORD feature
)
943 return RtlIsProcessorFeaturePresent( feature
);
947 /**********************************************************************
948 * IsWow64Process2 (kernelbase.@)
950 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process2( HANDLE process
, USHORT
*machine
, USHORT
*native_machine
)
955 TRACE( "(%p,%p,%p)\n", process
, machine
, native_machine
);
957 if (!IsWow64Process( process
, &wow64
))
962 if (process
!= GetCurrentProcess())
964 #if defined(__i386__) || defined(__x86_64__)
965 *machine
= IMAGE_FILE_MACHINE_I386
;
967 FIXME("not implemented for other process\n");
968 *machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
973 IMAGE_NT_HEADERS
*nt
;
974 nt
= RtlImageNtHeader( NtCurrentTeb()->Peb
->ImageBaseAddress
);
975 *machine
= nt
->FileHeader
.Machine
;
978 if (!native_machine
) return TRUE
;
980 GetNativeSystemInfo( &si
);
984 *machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
986 if (!native_machine
) return TRUE
;
989 GetSystemInfo( &si
);
991 GetNativeSystemInfo( &si
);
995 switch (si
.u
.s
.wProcessorArchitecture
)
997 case PROCESSOR_ARCHITECTURE_INTEL
:
998 *native_machine
= IMAGE_FILE_MACHINE_I386
;
1000 case PROCESSOR_ARCHITECTURE_ARM
:
1001 *native_machine
= IMAGE_FILE_MACHINE_ARMNT
;
1003 case PROCESSOR_ARCHITECTURE_AMD64
:
1004 *native_machine
= IMAGE_FILE_MACHINE_AMD64
;
1006 case PROCESSOR_ARCHITECTURE_ARM64
:
1007 *native_machine
= IMAGE_FILE_MACHINE_ARM64
;
1010 FIXME("unknown architecture %u\n", si
.u
.s
.wProcessorArchitecture
);
1011 *native_machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
1019 /**********************************************************************
1020 * IsWow64Process (kernelbase.@)
1022 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process( HANDLE process
, PBOOL wow64
)
1027 status
= NtQueryInformationProcess( process
, ProcessWow64Information
, &pbi
, sizeof(pbi
), NULL
);
1028 if (!status
) *wow64
= !!pbi
;
1029 return set_ntstatus( status
);
1033 /*********************************************************************
1034 * OpenProcess (kernelbase.@)
1036 HANDLE WINAPI DECLSPEC_HOTPATCH
OpenProcess( DWORD access
, BOOL inherit
, DWORD id
)
1039 OBJECT_ATTRIBUTES attr
;
1042 if (GetVersion() & 0x80000000) access
= PROCESS_ALL_ACCESS
;
1044 attr
.Length
= sizeof(OBJECT_ATTRIBUTES
);
1045 attr
.RootDirectory
= 0;
1046 attr
.Attributes
= inherit
? OBJ_INHERIT
: 0;
1047 attr
.ObjectName
= NULL
;
1048 attr
.SecurityDescriptor
= NULL
;
1049 attr
.SecurityQualityOfService
= NULL
;
1051 cid
.UniqueProcess
= ULongToHandle(id
);
1052 cid
.UniqueThread
= 0;
1054 if (!set_ntstatus( NtOpenProcess( &handle
, access
, &attr
, &cid
))) return NULL
;
1059 /***********************************************************************
1060 * ProcessIdToSessionId (kernelbase.@)
1062 BOOL WINAPI DECLSPEC_HOTPATCH
ProcessIdToSessionId( DWORD procid
, DWORD
*sessionid
)
1064 if (procid
!= GetCurrentProcessId()) FIXME( "Unsupported for other process %x\n", procid
);
1065 *sessionid
= NtCurrentTeb()->Peb
->SessionId
;
1070 /***********************************************************************
1071 * QueryProcessCycleTime (kernelbase.@)
1073 BOOL WINAPI DECLSPEC_HOTPATCH
QueryProcessCycleTime( HANDLE process
, ULONG64
*cycle
)
1076 if (!once
++) FIXME( "(%p,%p): stub!\n", process
, cycle
);
1077 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1082 /***********************************************************************
1083 * SetErrorMode (kernelbase.@)
1085 UINT WINAPI DECLSPEC_HOTPATCH
SetErrorMode( UINT mode
)
1087 UINT old
= GetErrorMode();
1089 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
1090 &mode
, sizeof(mode
) );
1095 /*************************************************************************
1096 * SetHandleCount (kernelbase.@)
1098 UINT WINAPI DECLSPEC_HOTPATCH
SetHandleCount( UINT count
)
1104 /*********************************************************************
1105 * SetHandleInformation (kernelbase.@)
1107 BOOL WINAPI DECLSPEC_HOTPATCH
SetHandleInformation( HANDLE handle
, DWORD mask
, DWORD flags
)
1109 OBJECT_DATA_INFORMATION info
;
1111 /* if not setting both fields, retrieve current value first */
1112 if ((mask
& (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
)) !=
1113 (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
))
1115 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
1118 if (mask
& HANDLE_FLAG_INHERIT
)
1119 info
.InheritHandle
= (flags
& HANDLE_FLAG_INHERIT
) != 0;
1120 if (mask
& HANDLE_FLAG_PROTECT_FROM_CLOSE
)
1121 info
.ProtectFromClose
= (flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
) != 0;
1123 return set_ntstatus( NtSetInformationObject( handle
, ObjectDataInformation
, &info
, sizeof(info
) ));
1127 /***********************************************************************
1128 * SetPriorityClass (kernelbase.@)
1130 BOOL WINAPI DECLSPEC_HOTPATCH
SetPriorityClass( HANDLE process
, DWORD
class )
1132 PROCESS_PRIORITY_CLASS ppc
;
1134 ppc
.Foreground
= FALSE
;
1137 case IDLE_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_IDLE
; break;
1138 case BELOW_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_BELOW_NORMAL
; break;
1139 case NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_NORMAL
; break;
1140 case ABOVE_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_ABOVE_NORMAL
; break;
1141 case HIGH_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_HIGH
; break;
1142 case REALTIME_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_REALTIME
; break;
1144 SetLastError( ERROR_INVALID_PARAMETER
);
1147 return set_ntstatus( NtSetInformationProcess( process
, ProcessPriorityClass
, &ppc
, sizeof(ppc
) ));
1151 /***********************************************************************
1152 * SetProcessAffinityUpdateMode (kernelbase.@)
1154 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessAffinityUpdateMode( HANDLE process
, DWORD flags
)
1156 FIXME( "(%p,0x%08x): stub\n", process
, flags
);
1157 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1162 /**********************************************************************
1163 * SetProcessMitigationPolicy (kernelbase.@)
1165 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy
,
1166 void *buffer
, SIZE_T length
)
1168 FIXME( "(%d, %p, %lu): stub\n", policy
, buffer
, length
);
1173 /***********************************************************************
1174 * SetProcessPriorityBoost (kernelbase.@)
1176 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process
, BOOL disable
)
1178 FIXME( "(%p,%d): stub\n", process
, disable
);
1183 /***********************************************************************
1184 * SetProcessShutdownParameters (kernelbase.@)
1186 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessShutdownParameters( DWORD level
, DWORD flags
)
1188 FIXME( "(%08x, %08x): partial stub.\n", level
, flags
);
1189 shutdown_flags
= flags
;
1190 shutdown_priority
= level
;
1195 /***********************************************************************
1196 * SetProcessWorkingSetSizeEx (kernelbase.@)
1198 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T minset
,
1199 SIZE_T maxset
, DWORD flags
)
1205 /******************************************************************************
1206 * TerminateProcess (kernelbase.@)
1208 BOOL WINAPI DECLSPEC_HOTPATCH
TerminateProcess( HANDLE handle
, DWORD exit_code
)
1212 SetLastError( ERROR_INVALID_HANDLE
);
1215 return set_ntstatus( NtTerminateProcess( handle
, exit_code
));
1219 /***********************************************************************
1220 * Process startup information
1221 ***********************************************************************/
1224 static STARTUPINFOW startup_infoW
;
1225 static char *command_lineA
;
1226 static WCHAR
*command_lineW
;
1228 /******************************************************************
1231 void init_startup_info( RTL_USER_PROCESS_PARAMETERS
*params
)
1235 startup_infoW
.cb
= sizeof(startup_infoW
);
1236 startup_infoW
.lpReserved
= NULL
;
1237 startup_infoW
.lpDesktop
= params
->Desktop
.Buffer
;
1238 startup_infoW
.lpTitle
= params
->WindowTitle
.Buffer
;
1239 startup_infoW
.dwX
= params
->dwX
;
1240 startup_infoW
.dwY
= params
->dwY
;
1241 startup_infoW
.dwXSize
= params
->dwXSize
;
1242 startup_infoW
.dwYSize
= params
->dwYSize
;
1243 startup_infoW
.dwXCountChars
= params
->dwXCountChars
;
1244 startup_infoW
.dwYCountChars
= params
->dwYCountChars
;
1245 startup_infoW
.dwFillAttribute
= params
->dwFillAttribute
;
1246 startup_infoW
.dwFlags
= params
->dwFlags
;
1247 startup_infoW
.wShowWindow
= params
->wShowWindow
;
1248 startup_infoW
.cbReserved2
= params
->RuntimeInfo
.MaximumLength
;
1249 startup_infoW
.lpReserved2
= params
->RuntimeInfo
.MaximumLength
? (void *)params
->RuntimeInfo
.Buffer
: NULL
;
1250 startup_infoW
.hStdInput
= params
->hStdInput
? params
->hStdInput
: INVALID_HANDLE_VALUE
;
1251 startup_infoW
.hStdOutput
= params
->hStdOutput
? params
->hStdOutput
: INVALID_HANDLE_VALUE
;
1252 startup_infoW
.hStdError
= params
->hStdError
? params
->hStdError
: INVALID_HANDLE_VALUE
;
1254 command_lineW
= params
->CommandLine
.Buffer
;
1255 if (!RtlUnicodeStringToAnsiString( &ansi
, ¶ms
->CommandLine
, TRUE
)) command_lineA
= ansi
.Buffer
;
1259 /**********************************************************************
1260 * BaseFlushAppcompatCache (kernelbase.@)
1262 BOOL WINAPI
BaseFlushAppcompatCache(void)
1265 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1270 /***********************************************************************
1271 * GetCommandLineA (kernelbase.@)
1273 LPSTR WINAPI
GetCommandLineA(void)
1275 return command_lineA
;
1279 /***********************************************************************
1280 * GetCommandLineW (kernelbase.@)
1282 LPWSTR WINAPI
GetCommandLineW(void)
1284 return command_lineW
;
1288 /***********************************************************************
1289 * GetStartupInfoW (kernelbase.@)
1291 void WINAPI DECLSPEC_HOTPATCH
GetStartupInfoW( STARTUPINFOW
*info
)
1293 *info
= startup_infoW
;
1297 /***********************************************************************
1298 * GetStdHandle (kernelbase.@)
1300 HANDLE WINAPI DECLSPEC_HOTPATCH
GetStdHandle( DWORD std_handle
)
1304 case STD_INPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
1305 case STD_OUTPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
1306 case STD_ERROR_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
1308 SetLastError( ERROR_INVALID_HANDLE
);
1309 return INVALID_HANDLE_VALUE
;
1313 /***********************************************************************
1314 * SetStdHandle (kernelbase.@)
1316 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandle( DWORD std_handle
, HANDLE handle
)
1320 case STD_INPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
= handle
; return TRUE
;
1321 case STD_OUTPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
= handle
; return TRUE
;
1322 case STD_ERROR_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
= handle
; return TRUE
;
1324 SetLastError( ERROR_INVALID_HANDLE
);
1329 /***********************************************************************
1330 * SetStdHandleEx (kernelbase.@)
1332 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandleEx( DWORD std_handle
, HANDLE handle
, HANDLE
*prev
)
1338 case STD_INPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
; break;
1339 case STD_OUTPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
; break;
1340 case STD_ERROR_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
; break;
1342 SetLastError( ERROR_INVALID_HANDLE
);
1345 if (prev
) *prev
= *ptr
;
1351 /***********************************************************************
1352 * Process environment
1353 ***********************************************************************/
1356 static inline SIZE_T
get_env_length( const WCHAR
*env
)
1358 const WCHAR
*end
= env
;
1359 while (*end
) end
+= lstrlenW(end
) + 1;
1360 return end
+ 1 - env
;
1363 /***********************************************************************
1364 * ExpandEnvironmentStringsA (kernelbase.@)
1366 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsA( LPCSTR src
, LPSTR dst
, DWORD count
)
1368 UNICODE_STRING us_src
;
1372 RtlCreateUnicodeStringFromAsciiz( &us_src
, src
);
1375 if (!(dstW
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
)))) return 0;
1376 ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, dstW
, count
);
1377 if (ret
) WideCharToMultiByte( CP_ACP
, 0, dstW
, ret
, dst
, count
, NULL
, NULL
);
1379 else ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, NULL
, 0 );
1381 RtlFreeUnicodeString( &us_src
);
1382 HeapFree( GetProcessHeap(), 0, dstW
);
1387 /***********************************************************************
1388 * ExpandEnvironmentStringsW (kernelbase.@)
1390 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsW( LPCWSTR src
, LPWSTR dst
, DWORD len
)
1392 UNICODE_STRING us_src
, us_dst
;
1396 TRACE( "(%s %p %u)\n", debugstr_w(src
), dst
, len
);
1398 RtlInitUnicodeString( &us_src
, src
);
1400 /* make sure we don't overflow the maximum UNICODE_STRING size */
1401 len
= min( len
, UNICODE_STRING_MAX_CHARS
);
1404 us_dst
.MaximumLength
= len
* sizeof(WCHAR
);
1405 us_dst
.Buffer
= dst
;
1408 status
= RtlExpandEnvironmentStrings_U( NULL
, &us_src
, &us_dst
, &res
);
1409 res
/= sizeof(WCHAR
);
1410 if (!set_ntstatus( status
))
1412 if (status
!= STATUS_BUFFER_TOO_SMALL
) return 0;
1413 if (len
&& dst
) dst
[len
- 1] = 0;
1419 /***********************************************************************
1420 * GetEnvironmentStrings (kernelbase.@)
1421 * GetEnvironmentStringsA (kernelbase.@)
1423 LPSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsA(void)
1429 RtlAcquirePebLock();
1430 env
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
1431 lenW
= get_env_length( env
);
1432 lenA
= WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, NULL
, 0, NULL
, NULL
);
1433 if ((ret
= HeapAlloc( GetProcessHeap(), 0, lenA
)))
1434 WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, ret
, lenA
, NULL
, NULL
);
1435 RtlReleasePebLock();
1440 /***********************************************************************
1441 * GetEnvironmentStringsW (kernelbase.@)
1443 LPWSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsW(void)
1448 RtlAcquirePebLock();
1449 len
= get_env_length( NtCurrentTeb()->Peb
->ProcessParameters
->Environment
) * sizeof(WCHAR
);
1450 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
1451 memcpy( ret
, NtCurrentTeb()->Peb
->ProcessParameters
->Environment
, len
);
1452 RtlReleasePebLock();
1457 /***********************************************************************
1458 * SetEnvironmentStringsA (kernelbase.@)
1460 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsA( char *env
)
1463 const char *p
= env
;
1467 for (p
= env
; *p
; p
+= strlen( p
) + 1);
1469 len
= MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, NULL
, 0 );
1470 if (!(envW
= HeapAlloc( GetProcessHeap(), 0, len
)))
1472 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1475 MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, envW
, len
);
1476 ret
= SetEnvironmentStringsW( envW
);
1477 HeapFree( GetProcessHeap(), 0, envW
);
1482 /***********************************************************************
1483 * SetEnvironmentStringsW (kernelbase.@)
1485 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsW( WCHAR
*env
)
1491 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1493 const WCHAR
*eq
= wcschr( p
, '=' );
1496 SetLastError( ERROR_INVALID_PARAMETER
);
1501 if ((status
= RtlCreateEnvironment( FALSE
, &new_env
)))
1502 return set_ntstatus( status
);
1504 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1506 const WCHAR
*eq
= wcschr( p
, '=' );
1507 UNICODE_STRING var
, value
;
1509 var
.Length
= (eq
- p
) * sizeof(WCHAR
);
1510 RtlInitUnicodeString( &value
, eq
+ 1 );
1511 if ((status
= RtlSetEnvironmentVariable( &new_env
, &var
, &value
)))
1513 RtlDestroyEnvironment( new_env
);
1514 return set_ntstatus( status
);
1518 RtlSetCurrentEnvironment( new_env
, NULL
);
1523 /***********************************************************************
1524 * GetEnvironmentVariableA (kernelbase.@)
1526 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableA( LPCSTR name
, LPSTR value
, DWORD size
)
1528 UNICODE_STRING us_name
, us_value
;
1533 /* limit the size to sane values */
1534 size
= min( size
, 32767 );
1535 if (!(valueW
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1537 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1538 us_value
.Length
= 0;
1539 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1540 us_value
.Buffer
= valueW
;
1542 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1543 len
= us_value
.Length
/ sizeof(WCHAR
);
1544 if (status
== STATUS_BUFFER_TOO_SMALL
) ret
= len
+ 1;
1545 else if (!set_ntstatus( status
)) ret
= 0;
1546 else if (!size
) ret
= len
+ 1;
1549 if (len
) WideCharToMultiByte( CP_ACP
, 0, valueW
, len
+ 1, value
, size
, NULL
, NULL
);
1554 RtlFreeUnicodeString( &us_name
);
1555 HeapFree( GetProcessHeap(), 0, valueW
);
1560 /***********************************************************************
1561 * GetEnvironmentVariableW (kernelbase.@)
1563 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableW( LPCWSTR name
, LPWSTR val
, DWORD size
)
1565 UNICODE_STRING us_name
, us_value
;
1569 TRACE( "(%s %p %u)\n", debugstr_w(name
), val
, size
);
1571 RtlInitUnicodeString( &us_name
, name
);
1572 us_value
.Length
= 0;
1573 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1574 us_value
.Buffer
= val
;
1576 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1577 len
= us_value
.Length
/ sizeof(WCHAR
);
1578 if (status
== STATUS_BUFFER_TOO_SMALL
) return len
+ 1;
1579 if (!set_ntstatus( status
)) return 0;
1580 if (!size
) return len
+ 1;
1586 /***********************************************************************
1587 * FreeEnvironmentStringsA (kernelbase.@)
1588 * FreeEnvironmentStringsW (kernelbase.@)
1590 BOOL WINAPI DECLSPEC_HOTPATCH
FreeEnvironmentStringsW( LPWSTR ptr
)
1592 return HeapFree( GetProcessHeap(), 0, ptr
);
1596 /***********************************************************************
1597 * SetEnvironmentVariableA (kernelbase.@)
1599 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableA( LPCSTR name
, LPCSTR value
)
1601 UNICODE_STRING us_name
, us_value
;
1606 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1610 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1613 RtlCreateUnicodeStringFromAsciiz( &us_value
, value
);
1614 ret
= SetEnvironmentVariableW( us_name
.Buffer
, us_value
.Buffer
);
1615 RtlFreeUnicodeString( &us_value
);
1617 else ret
= SetEnvironmentVariableW( us_name
.Buffer
, NULL
);
1618 RtlFreeUnicodeString( &us_name
);
1623 /***********************************************************************
1624 * SetEnvironmentVariableW (kernelbase.@)
1626 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableW( LPCWSTR name
, LPCWSTR value
)
1628 UNICODE_STRING us_name
, us_value
;
1631 TRACE( "(%s %s)\n", debugstr_w(name
), debugstr_w(value
) );
1635 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1639 RtlInitUnicodeString( &us_name
, name
);
1642 RtlInitUnicodeString( &us_value
, value
);
1643 status
= RtlSetEnvironmentVariable( NULL
, &us_name
, &us_value
);
1645 else status
= RtlSetEnvironmentVariable( NULL
, &us_name
, NULL
);
1647 return set_ntstatus( status
);
1651 /***********************************************************************
1652 * Process/thread attribute lists
1653 ***********************************************************************/
1655 /***********************************************************************
1656 * InitializeProcThreadAttributeList (kernelbase.@)
1658 BOOL WINAPI DECLSPEC_HOTPATCH
InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1659 DWORD count
, DWORD flags
, SIZE_T
*size
)
1664 TRACE( "(%p %d %x %p)\n", list
, count
, flags
, size
);
1666 needed
= FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST
, attrs
[count
] );
1667 if (list
&& *size
>= needed
)
1675 else SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1682 /***********************************************************************
1683 * UpdateProcThreadAttribute (kernelbase.@)
1685 BOOL WINAPI DECLSPEC_HOTPATCH
UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1686 DWORD flags
, DWORD_PTR attr
, void *value
,
1687 SIZE_T size
, void *prev_ret
, SIZE_T
*size_ret
)
1690 struct proc_thread_attr
*entry
;
1692 TRACE( "(%p %x %08lx %p %ld %p %p)\n", list
, flags
, attr
, value
, size
, prev_ret
, size_ret
);
1694 if (list
->count
>= list
->size
)
1696 SetLastError( ERROR_GEN_FAILURE
);
1702 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
1703 if (size
!= sizeof(HANDLE
))
1705 SetLastError( ERROR_BAD_LENGTH
);
1710 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
1711 if ((size
/ sizeof(HANDLE
)) * sizeof(HANDLE
) != size
)
1713 SetLastError( ERROR_BAD_LENGTH
);
1718 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR
:
1719 if (size
!= sizeof(PROCESSOR_NUMBER
))
1721 SetLastError( ERROR_BAD_LENGTH
);
1726 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY
:
1727 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
))
1729 SetLastError( ERROR_BAD_LENGTH
);
1734 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
:
1735 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
) && size
!= sizeof(DWORD64
) * 2)
1737 SetLastError( ERROR_BAD_LENGTH
);
1742 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
1743 if (size
!= sizeof(HPCON
))
1745 SetLastError( ERROR_BAD_LENGTH
);
1751 SetLastError( ERROR_NOT_SUPPORTED
);
1752 FIXME( "Unhandled attribute %lu\n", attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1756 mask
= 1 << (attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1757 if (list
->mask
& mask
)
1759 SetLastError( ERROR_OBJECT_NAME_EXISTS
);
1764 entry
= list
->attrs
+ list
->count
;
1767 entry
->value
= value
;
1773 /***********************************************************************
1774 * DeleteProcThreadAttributeList (kernelbase.@)
1776 void WINAPI DECLSPEC_HOTPATCH
DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
)