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
, dllpathW
, curdirW
, cmdlineW
, titleW
, desktopW
, runtimeW
, newdirW
;
148 WCHAR imagepath
[MAX_PATH
];
149 WCHAR
*load_path
, *dummy
, *envW
= env
;
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 LdrGetDllPath( imagepath
, LOAD_WITH_ALTERED_SEARCH_PATH
, &load_path
, &dummy
);
175 RtlInitUnicodeString( &imageW
, imagepath
);
176 RtlInitUnicodeString( &dllpathW
, load_path
);
177 RtlInitUnicodeString( &curdirW
, cur_dir
);
178 RtlInitUnicodeString( &cmdlineW
, cmdline
);
179 RtlInitUnicodeString( &titleW
, startup
->lpTitle
? startup
->lpTitle
: imagepath
);
180 RtlInitUnicodeString( &desktopW
, startup
->lpDesktop
);
181 runtimeW
.Buffer
= (WCHAR
*)startup
->lpReserved2
;
182 runtimeW
.Length
= runtimeW
.MaximumLength
= startup
->cbReserved2
;
183 if (RtlCreateProcessParametersEx( ¶ms
, &imageW
, &dllpathW
, cur_dir
? &curdirW
: NULL
,
184 &cmdlineW
, envW
, &titleW
, &desktopW
,
185 NULL
, &runtimeW
, PROCESS_PARAMS_FLAG_NORMALIZED
))
187 RtlFreeUnicodeString( &newdirW
);
188 RtlReleasePath( load_path
);
189 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
192 RtlFreeUnicodeString( &newdirW
);
193 RtlReleasePath( load_path
);
195 if (flags
& CREATE_NEW_PROCESS_GROUP
) params
->ConsoleFlags
= 1;
196 if (flags
& CREATE_NEW_CONSOLE
) params
->ConsoleHandle
= (HANDLE
)1; /* KERNEL32_CONSOLE_ALLOC */
197 else if (!(flags
& DETACHED_PROCESS
)) params
->ConsoleHandle
= NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleHandle
;
199 if (startup
->dwFlags
& STARTF_USESTDHANDLES
)
201 params
->hStdInput
= startup
->hStdInput
;
202 params
->hStdOutput
= startup
->hStdOutput
;
203 params
->hStdError
= startup
->hStdError
;
205 else if (flags
& DETACHED_PROCESS
)
207 params
->hStdInput
= INVALID_HANDLE_VALUE
;
208 params
->hStdOutput
= INVALID_HANDLE_VALUE
;
209 params
->hStdError
= INVALID_HANDLE_VALUE
;
213 params
->hStdInput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
214 params
->hStdOutput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
215 params
->hStdError
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
218 if (flags
& CREATE_NEW_CONSOLE
)
220 /* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
221 if (is_console_handle(params
->hStdInput
)) params
->hStdInput
= INVALID_HANDLE_VALUE
;
222 if (is_console_handle(params
->hStdOutput
)) params
->hStdOutput
= INVALID_HANDLE_VALUE
;
223 if (is_console_handle(params
->hStdError
)) params
->hStdError
= INVALID_HANDLE_VALUE
;
227 if (is_console_handle(params
->hStdInput
)) params
->hStdInput
= (HANDLE
)((UINT_PTR
)params
->hStdInput
& ~3);
228 if (is_console_handle(params
->hStdOutput
)) params
->hStdOutput
= (HANDLE
)((UINT_PTR
)params
->hStdOutput
& ~3);
229 if (is_console_handle(params
->hStdError
)) params
->hStdError
= (HANDLE
)((UINT_PTR
)params
->hStdError
& ~3);
232 params
->dwX
= startup
->dwX
;
233 params
->dwY
= startup
->dwY
;
234 params
->dwXSize
= startup
->dwXSize
;
235 params
->dwYSize
= startup
->dwYSize
;
236 params
->dwXCountChars
= startup
->dwXCountChars
;
237 params
->dwYCountChars
= startup
->dwYCountChars
;
238 params
->dwFillAttribute
= startup
->dwFillAttribute
;
239 params
->dwFlags
= startup
->dwFlags
;
240 params
->wShowWindow
= startup
->wShowWindow
;
242 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
246 struct proc_thread_attr
253 struct _PROC_THREAD_ATTRIBUTE_LIST
255 DWORD mask
; /* bitmask of items in list */
256 DWORD size
; /* max number of items in list */
257 DWORD count
; /* number of items in list */
260 struct proc_thread_attr attrs
[1];
263 /***********************************************************************
266 static NTSTATUS
create_nt_process( HANDLE token
, SECURITY_ATTRIBUTES
*psa
, SECURITY_ATTRIBUTES
*tsa
,
267 BOOL inherit
, DWORD flags
, RTL_USER_PROCESS_PARAMETERS
*params
,
268 RTL_USER_PROCESS_INFORMATION
*info
, HANDLE parent
,
269 const struct proc_thread_attr
*handle_list
)
271 OBJECT_ATTRIBUTES process_attr
, thread_attr
;
272 PS_CREATE_INFO create_info
;
273 ULONG_PTR buffer
[offsetof( PS_ATTRIBUTE_LIST
, Attributes
[6] ) / sizeof(ULONG_PTR
)];
274 PS_ATTRIBUTE_LIST
*attr
= (PS_ATTRIBUTE_LIST
*)buffer
;
275 UNICODE_STRING nameW
;
279 if (!params
->ImagePathName
.Buffer
[0]) return STATUS_OBJECT_PATH_NOT_FOUND
;
280 status
= RtlDosPathNameToNtPathName_U_WithStatus( params
->ImagePathName
.Buffer
, &nameW
, NULL
, NULL
);
283 params
->DebugFlags
= flags
; /* hack, cf. RtlCreateUserProcess implementation */
285 RtlNormalizeProcessParams( params
);
287 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_NAME
;
288 attr
->Attributes
[pos
].Size
= nameW
.Length
;
289 attr
->Attributes
[pos
].ValuePtr
= nameW
.Buffer
;
290 attr
->Attributes
[pos
].ReturnLength
= NULL
;
292 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_CLIENT_ID
;
293 attr
->Attributes
[pos
].Size
= sizeof(info
->ClientId
);
294 attr
->Attributes
[pos
].ValuePtr
= &info
->ClientId
;
295 attr
->Attributes
[pos
].ReturnLength
= NULL
;
297 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_INFO
;
298 attr
->Attributes
[pos
].Size
= sizeof(info
->ImageInformation
);
299 attr
->Attributes
[pos
].ValuePtr
= &info
->ImageInformation
;
300 attr
->Attributes
[pos
].ReturnLength
= NULL
;
304 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_PARENT_PROCESS
;
305 attr
->Attributes
[pos
].Size
= sizeof(parent
);
306 attr
->Attributes
[pos
].ValuePtr
= parent
;
307 attr
->Attributes
[pos
].ReturnLength
= NULL
;
310 if (inherit
&& handle_list
)
312 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_HANDLE_LIST
;
313 attr
->Attributes
[pos
].Size
= handle_list
->size
;
314 attr
->Attributes
[pos
].ValuePtr
= handle_list
->value
;
315 attr
->Attributes
[pos
].ReturnLength
= NULL
;
320 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_TOKEN
;
321 attr
->Attributes
[pos
].Size
= sizeof(token
);
322 attr
->Attributes
[pos
].ValuePtr
= token
;
323 attr
->Attributes
[pos
].ReturnLength
= NULL
;
326 attr
->TotalLength
= offsetof( PS_ATTRIBUTE_LIST
, Attributes
[pos
] );
328 InitializeObjectAttributes( &process_attr
, NULL
, 0, NULL
, psa
? psa
->lpSecurityDescriptor
: NULL
);
329 InitializeObjectAttributes( &thread_attr
, NULL
, 0, NULL
, tsa
? tsa
->lpSecurityDescriptor
: NULL
);
331 status
= NtCreateUserProcess( &info
->Process
, &info
->Thread
, PROCESS_ALL_ACCESS
, THREAD_ALL_ACCESS
,
332 &process_attr
, &thread_attr
,
333 inherit
? PROCESS_CREATE_FLAGS_INHERIT_HANDLES
: 0,
334 THREAD_CREATE_FLAGS_CREATE_SUSPENDED
, params
,
335 &create_info
, attr
);
337 RtlFreeUnicodeString( &nameW
);
343 /***********************************************************************
346 static NTSTATUS
create_vdm_process( HANDLE token
, SECURITY_ATTRIBUTES
*psa
, SECURITY_ATTRIBUTES
*tsa
,
347 BOOL inherit
, DWORD flags
, RTL_USER_PROCESS_PARAMETERS
*params
,
348 RTL_USER_PROCESS_INFORMATION
*info
)
350 const WCHAR
*winevdm
= (is_win64
|| is_wow64
?
351 L
"C:\\windows\\syswow64\\winevdm.exe" :
352 L
"C:\\windows\\system32\\winevdm.exe");
357 len
= (lstrlenW(params
->ImagePathName
.Buffer
) + lstrlenW(params
->CommandLine
.Buffer
) +
358 lstrlenW(winevdm
) + 16);
360 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
361 return STATUS_NO_MEMORY
;
363 swprintf( newcmdline
, len
, L
"%s --app-name \"%s\" %s",
364 winevdm
, params
->ImagePathName
.Buffer
, params
->CommandLine
.Buffer
);
365 RtlInitUnicodeString( ¶ms
->ImagePathName
, winevdm
);
366 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
367 status
= create_nt_process( token
, psa
, tsa
, inherit
, flags
, params
, info
, NULL
, NULL
);
368 HeapFree( GetProcessHeap(), 0, newcmdline
);
373 /***********************************************************************
376 static NTSTATUS
create_cmd_process( HANDLE token
, SECURITY_ATTRIBUTES
*psa
, SECURITY_ATTRIBUTES
*tsa
,
377 BOOL inherit
, DWORD flags
, RTL_USER_PROCESS_PARAMETERS
*params
,
378 RTL_USER_PROCESS_INFORMATION
*info
)
380 WCHAR comspec
[MAX_PATH
];
385 if (!GetEnvironmentVariableW( L
"COMSPEC", comspec
, ARRAY_SIZE( comspec
)))
386 lstrcpyW( comspec
, L
"C:\\windows\\system32\\cmd.exe" );
388 len
= lstrlenW(comspec
) + 7 + lstrlenW(params
->CommandLine
.Buffer
) + 2;
389 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
390 return STATUS_NO_MEMORY
;
392 swprintf( newcmdline
, len
, L
"%s /s/c \"%s\"", comspec
, params
->CommandLine
.Buffer
);
393 RtlInitUnicodeString( ¶ms
->ImagePathName
, comspec
);
394 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
395 status
= create_nt_process( token
, psa
, tsa
, inherit
, flags
, params
, info
, NULL
, NULL
);
396 RtlFreeHeap( GetProcessHeap(), 0, newcmdline
);
401 /*********************************************************************
402 * CloseHandle (kernelbase.@)
404 BOOL WINAPI DECLSPEC_HOTPATCH
CloseHandle( HANDLE handle
)
406 if (handle
== (HANDLE
)STD_INPUT_HANDLE
)
407 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
, 0 );
408 else if (handle
== (HANDLE
)STD_OUTPUT_HANDLE
)
409 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
, 0 );
410 else if (handle
== (HANDLE
)STD_ERROR_HANDLE
)
411 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
, 0 );
413 if (is_console_handle( handle
)) handle
= console_handle_map( handle
);
414 return set_ntstatus( NtClose( handle
));
418 /**********************************************************************
419 * CreateProcessAsUserA (kernelbase.@)
421 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserA( HANDLE token
, const char *app_name
, char *cmd_line
,
422 SECURITY_ATTRIBUTES
*process_attr
,
423 SECURITY_ATTRIBUTES
*thread_attr
,
424 BOOL inherit
, DWORD flags
, void *env
,
425 const char *cur_dir
, STARTUPINFOA
*startup_info
,
426 PROCESS_INFORMATION
*info
)
428 return CreateProcessInternalA( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
429 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
433 /**********************************************************************
434 * CreateProcessAsUserW (kernelbase.@)
436 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
437 SECURITY_ATTRIBUTES
*process_attr
,
438 SECURITY_ATTRIBUTES
*thread_attr
,
439 BOOL inherit
, DWORD flags
, void *env
,
440 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
441 PROCESS_INFORMATION
*info
)
443 return CreateProcessInternalW( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
444 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
447 /**********************************************************************
448 * CreateProcessInternalA (kernelbase.@)
450 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalA( HANDLE token
, const char *app_name
, char *cmd_line
,
451 SECURITY_ATTRIBUTES
*process_attr
,
452 SECURITY_ATTRIBUTES
*thread_attr
,
453 BOOL inherit
, DWORD flags
, void *env
,
454 const char *cur_dir
, STARTUPINFOA
*startup_info
,
455 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
458 WCHAR
*app_nameW
= NULL
, *cmd_lineW
= NULL
, *cur_dirW
= NULL
;
459 UNICODE_STRING desktopW
, titleW
;
460 STARTUPINFOEXW infoW
;
462 desktopW
.Buffer
= NULL
;
463 titleW
.Buffer
= NULL
;
464 if (app_name
&& !(app_nameW
= file_name_AtoW( app_name
, TRUE
))) goto done
;
465 if (cmd_line
&& !(cmd_lineW
= file_name_AtoW( cmd_line
, TRUE
))) goto done
;
466 if (cur_dir
&& !(cur_dirW
= file_name_AtoW( cur_dir
, TRUE
))) goto done
;
468 if (startup_info
->lpDesktop
) RtlCreateUnicodeStringFromAsciiz( &desktopW
, startup_info
->lpDesktop
);
469 if (startup_info
->lpTitle
) RtlCreateUnicodeStringFromAsciiz( &titleW
, startup_info
->lpTitle
);
471 memcpy( &infoW
.StartupInfo
, startup_info
, sizeof(infoW
.StartupInfo
) );
472 infoW
.StartupInfo
.lpDesktop
= desktopW
.Buffer
;
473 infoW
.StartupInfo
.lpTitle
= titleW
.Buffer
;
475 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
476 infoW
.lpAttributeList
= ((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
478 ret
= CreateProcessInternalW( token
, app_nameW
, cmd_lineW
, process_attr
, thread_attr
,
479 inherit
, flags
, env
, cur_dirW
, (STARTUPINFOW
*)&infoW
, info
, new_token
);
481 RtlFreeHeap( GetProcessHeap(), 0, app_nameW
);
482 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW
);
483 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW
);
484 RtlFreeUnicodeString( &desktopW
);
485 RtlFreeUnicodeString( &titleW
);
489 /**********************************************************************
490 * CreateProcessInternalW (kernelbase.@)
492 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
493 SECURITY_ATTRIBUTES
*process_attr
,
494 SECURITY_ATTRIBUTES
*thread_attr
,
495 BOOL inherit
, DWORD flags
, void *env
,
496 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
497 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
499 const struct proc_thread_attr
*handle_list
= NULL
;
500 WCHAR name
[MAX_PATH
];
501 WCHAR
*p
, *tidy_cmdline
= cmd_line
;
502 RTL_USER_PROCESS_PARAMETERS
*params
= NULL
;
503 RTL_USER_PROCESS_INFORMATION rtl_info
;
504 HANDLE parent
= NULL
;
507 /* Process the AppName and/or CmdLine to get module name and path */
509 TRACE( "app %s cmdline %s\n", debugstr_w(app_name
), debugstr_w(cmd_line
) );
511 if (new_token
) FIXME( "No support for returning created process token\n" );
515 if (!cmd_line
|| !cmd_line
[0]) /* no command-line, create one */
517 if (!(tidy_cmdline
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name
)+3) * sizeof(WCHAR
) )))
519 swprintf( tidy_cmdline
, lstrlenW(app_name
) + 3, L
"\"%s\"", app_name
);
524 if (!(tidy_cmdline
= get_file_name( cmd_line
, name
, ARRAY_SIZE(name
) ))) return FALSE
;
528 /* Warn if unsupported features are used */
530 if (flags
& (IDLE_PRIORITY_CLASS
| HIGH_PRIORITY_CLASS
| REALTIME_PRIORITY_CLASS
|
531 CREATE_DEFAULT_ERROR_MODE
| CREATE_NO_WINDOW
|
532 PROFILE_USER
| PROFILE_KERNEL
| PROFILE_SERVER
))
533 WARN( "(%s,...): ignoring some flags in %x\n", debugstr_w(app_name
), flags
);
537 DWORD attr
= GetFileAttributesW( cur_dir
);
538 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
540 status
= STATUS_NOT_A_DIRECTORY
;
545 info
->hThread
= info
->hProcess
= 0;
546 info
->dwProcessId
= info
->dwThreadId
= 0;
548 if (!(params
= create_process_params( app_name
, tidy_cmdline
, cur_dir
, env
, flags
, startup_info
)))
550 status
= STATUS_NO_MEMORY
;
554 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
556 struct _PROC_THREAD_ATTRIBUTE_LIST
*attrs
=
557 (struct _PROC_THREAD_ATTRIBUTE_LIST
*)((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
562 for (i
= 0; i
< attrs
->count
; ++i
)
564 switch(attrs
->attrs
[i
].attr
)
566 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
567 parent
= *(HANDLE
*)attrs
->attrs
[i
].value
;
568 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent
);
571 status
= STATUS_INVALID_HANDLE
;
575 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
576 handle_list
= &attrs
->attrs
[i
];
577 TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs
->attrs
[i
].size
/ sizeof(HANDLE
));
579 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
581 struct pseudo_console
*console
= attrs
->attrs
[i
].value
;
582 TRACE( "PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE %p reference %p\n",
583 console
, console
->reference
);
584 params
->ConsoleHandle
= console
->reference
;
588 FIXME("Unsupported attribute %#Ix.\n", attrs
->attrs
[i
].attr
);
595 status
= create_nt_process( token
, process_attr
, thread_attr
, inherit
,
596 flags
, params
, &rtl_info
, parent
, handle_list
);
601 case STATUS_INVALID_IMAGE_WIN_16
:
602 case STATUS_INVALID_IMAGE_NE_FORMAT
:
603 case STATUS_INVALID_IMAGE_PROTECT
:
604 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name
) );
605 status
= create_vdm_process( token
, process_attr
, thread_attr
, inherit
, flags
, params
, &rtl_info
);
607 case STATUS_INVALID_IMAGE_NOT_MZ
:
608 /* check for .com or .bat extension */
609 if (!(p
= wcsrchr( app_name
, '.' ))) break;
610 if (!wcsicmp( p
, L
".com" ) || !wcsicmp( p
, L
".pif" ))
612 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name
) );
613 status
= create_vdm_process( token
, process_attr
, thread_attr
, 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
, process_attr
, thread_attr
, inherit
, flags
, params
, &rtl_info
);
625 info
->hProcess
= rtl_info
.Process
;
626 info
->hThread
= rtl_info
.Thread
;
627 info
->dwProcessId
= HandleToUlong( rtl_info
.ClientId
.UniqueProcess
);
628 info
->dwThreadId
= HandleToUlong( rtl_info
.ClientId
.UniqueThread
);
629 if (!(flags
& CREATE_SUSPENDED
)) NtResumeThread( rtl_info
.Thread
, NULL
);
630 TRACE( "started process pid %04x tid %04x\n", info
->dwProcessId
, info
->dwThreadId
);
634 RtlDestroyProcessParameters( params
);
635 if (tidy_cmdline
!= cmd_line
) HeapFree( GetProcessHeap(), 0, tidy_cmdline
);
636 return set_ntstatus( status
);
640 /**********************************************************************
641 * CreateProcessA (kernelbase.@)
643 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessA( const char *app_name
, char *cmd_line
,
644 SECURITY_ATTRIBUTES
*process_attr
,
645 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
,
646 DWORD flags
, void *env
, const char *cur_dir
,
647 STARTUPINFOA
*startup_info
, PROCESS_INFORMATION
*info
)
649 return CreateProcessInternalA( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
650 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
654 /**********************************************************************
655 * CreateProcessW (kernelbase.@)
657 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessW( const WCHAR
*app_name
, WCHAR
*cmd_line
,
658 SECURITY_ATTRIBUTES
*process_attr
,
659 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
, DWORD flags
,
660 void *env
, const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
661 PROCESS_INFORMATION
*info
)
663 return CreateProcessInternalW( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
664 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
668 /*********************************************************************
669 * DuplicateHandle (kernelbase.@)
671 BOOL WINAPI DECLSPEC_HOTPATCH
DuplicateHandle( HANDLE source_process
, HANDLE source
,
672 HANDLE dest_process
, HANDLE
*dest
,
673 DWORD access
, BOOL inherit
, DWORD options
)
675 if (is_console_handle( source
))
677 source
= console_handle_map( source
);
678 if (!set_ntstatus( NtDuplicateObject( source_process
, source
, dest_process
, dest
,
679 access
, inherit
? OBJ_INHERIT
: 0, options
)))
681 *dest
= console_handle_map( *dest
);
684 return set_ntstatus( NtDuplicateObject( source_process
, source
, dest_process
, dest
,
685 access
, inherit
? OBJ_INHERIT
: 0, options
));
689 /****************************************************************************
690 * FlushInstructionCache (kernelbase.@)
692 BOOL WINAPI DECLSPEC_HOTPATCH
FlushInstructionCache( HANDLE process
, LPCVOID addr
, SIZE_T size
)
694 return set_ntstatus( NtFlushInstructionCache( process
, addr
, size
));
698 /***********************************************************************
699 * GetApplicationRestartSettings (kernelbase.@)
701 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ GetApplicationRestartSettings( HANDLE process
, WCHAR
*cmdline
,
702 DWORD
*size
, DWORD
*flags
)
704 FIXME( "%p, %p, %p, %p)\n", process
, cmdline
, size
, flags
);
709 /***********************************************************************
710 * GetCurrentProcess (kernelbase.@)
712 HANDLE WINAPI
kernelbase_GetCurrentProcess(void)
714 return (HANDLE
)~(ULONG_PTR
)0;
718 /***********************************************************************
719 * GetCurrentProcessId (kernelbase.@)
721 DWORD WINAPI
kernelbase_GetCurrentProcessId(void)
723 return HandleToULong( NtCurrentTeb()->ClientId
.UniqueProcess
);
727 /***********************************************************************
728 * GetErrorMode (kernelbase.@)
730 UINT WINAPI DECLSPEC_HOTPATCH
GetErrorMode(void)
734 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
735 &mode
, sizeof(mode
), NULL
);
740 /***********************************************************************
741 * GetExitCodeProcess (kernelbase.@)
743 BOOL WINAPI DECLSPEC_HOTPATCH
GetExitCodeProcess( HANDLE process
, LPDWORD exit_code
)
746 PROCESS_BASIC_INFORMATION pbi
;
748 status
= NtQueryInformationProcess( process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
749 if (!status
&& exit_code
) *exit_code
= pbi
.ExitStatus
;
750 return set_ntstatus( status
);
754 /*********************************************************************
755 * GetHandleInformation (kernelbase.@)
757 BOOL WINAPI DECLSPEC_HOTPATCH
GetHandleInformation( HANDLE handle
, DWORD
*flags
)
759 OBJECT_DATA_INFORMATION info
;
761 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
767 if (info
.InheritHandle
) *flags
|= HANDLE_FLAG_INHERIT
;
768 if (info
.ProtectFromClose
) *flags
|= HANDLE_FLAG_PROTECT_FROM_CLOSE
;
774 /***********************************************************************
775 * GetPriorityClass (kernelbase.@)
777 DWORD WINAPI DECLSPEC_HOTPATCH
GetPriorityClass( HANDLE process
)
779 PROCESS_BASIC_INFORMATION pbi
;
781 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
782 &pbi
, sizeof(pbi
), NULL
)))
785 switch (pbi
.BasePriority
)
787 case PROCESS_PRIOCLASS_IDLE
: return IDLE_PRIORITY_CLASS
;
788 case PROCESS_PRIOCLASS_BELOW_NORMAL
: return BELOW_NORMAL_PRIORITY_CLASS
;
789 case PROCESS_PRIOCLASS_NORMAL
: return NORMAL_PRIORITY_CLASS
;
790 case PROCESS_PRIOCLASS_ABOVE_NORMAL
: return ABOVE_NORMAL_PRIORITY_CLASS
;
791 case PROCESS_PRIOCLASS_HIGH
: return HIGH_PRIORITY_CLASS
;
792 case PROCESS_PRIOCLASS_REALTIME
: return REALTIME_PRIORITY_CLASS
;
798 /******************************************************************
799 * GetProcessHandleCount (kernelbase.@)
801 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessHandleCount( HANDLE process
, DWORD
*count
)
803 return set_ntstatus( NtQueryInformationProcess( process
, ProcessHandleCount
,
804 count
, sizeof(*count
), NULL
));
808 /***********************************************************************
809 * GetProcessHeap (kernelbase.@)
811 HANDLE WINAPI
kernelbase_GetProcessHeap(void)
813 return NtCurrentTeb()->Peb
->ProcessHeap
;
817 /*********************************************************************
818 * GetProcessId (kernelbase.@)
820 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessId( HANDLE process
)
822 PROCESS_BASIC_INFORMATION pbi
;
824 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
825 &pbi
, sizeof(pbi
), NULL
)))
827 return pbi
.UniqueProcessId
;
831 /**********************************************************************
832 * GetProcessMitigationPolicy (kernelbase.@)
834 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process
, PROCESS_MITIGATION_POLICY policy
,
835 void *buffer
, SIZE_T length
)
837 FIXME( "(%p, %u, %p, %lu): stub\n", process
, policy
, buffer
, length
);
842 /***********************************************************************
843 * GetProcessPriorityBoost (kernelbase.@)
845 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessPriorityBoost( HANDLE process
, PBOOL disable
)
847 FIXME( "(%p,%p): semi-stub\n", process
, disable
);
848 *disable
= FALSE
; /* report that no boost is present */
853 /***********************************************************************
854 * GetProcessShutdownParameters (kernelbase.@)
856 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessShutdownParameters( LPDWORD level
, LPDWORD flags
)
858 *level
= shutdown_priority
;
859 *flags
= shutdown_flags
;
864 /*********************************************************************
865 * GetProcessTimes (kernelbase.@)
867 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessTimes( HANDLE process
, FILETIME
*create
, FILETIME
*exit
,
868 FILETIME
*kernel
, FILETIME
*user
)
870 KERNEL_USER_TIMES time
;
872 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessTimes
, &time
, sizeof(time
), NULL
)))
875 create
->dwLowDateTime
= time
.CreateTime
.u
.LowPart
;
876 create
->dwHighDateTime
= time
.CreateTime
.u
.HighPart
;
877 exit
->dwLowDateTime
= time
.ExitTime
.u
.LowPart
;
878 exit
->dwHighDateTime
= time
.ExitTime
.u
.HighPart
;
879 kernel
->dwLowDateTime
= time
.KernelTime
.u
.LowPart
;
880 kernel
->dwHighDateTime
= time
.KernelTime
.u
.HighPart
;
881 user
->dwLowDateTime
= time
.UserTime
.u
.LowPart
;
882 user
->dwHighDateTime
= time
.UserTime
.u
.HighPart
;
887 /***********************************************************************
888 * GetProcessVersion (kernelbase.@)
890 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessVersion( DWORD pid
)
892 SECTION_IMAGE_INFORMATION info
;
896 if (pid
&& pid
!= GetCurrentProcessId())
898 if (!(process
= OpenProcess( PROCESS_QUERY_INFORMATION
, FALSE
, pid
))) return 0;
899 status
= NtQueryInformationProcess( process
, ProcessImageInformation
, &info
, sizeof(info
), NULL
);
900 CloseHandle( process
);
902 else status
= NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation
,
903 &info
, sizeof(info
), NULL
);
905 if (!set_ntstatus( status
)) return 0;
906 return MAKELONG( info
.SubsystemVersionLow
, info
.SubsystemVersionHigh
);
910 /***********************************************************************
911 * GetProcessWorkingSetSizeEx (kernelbase.@)
913 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T
*minset
,
914 SIZE_T
*maxset
, DWORD
*flags
)
916 FIXME( "(%p,%p,%p,%p): stub\n", process
, minset
, maxset
, flags
);
917 /* 32 MB working set size */
918 if (minset
) *minset
= 32*1024*1024;
919 if (maxset
) *maxset
= 32*1024*1024;
920 if (flags
) *flags
= QUOTA_LIMITS_HARDWS_MIN_DISABLE
| QUOTA_LIMITS_HARDWS_MAX_DISABLE
;
925 /******************************************************************************
926 * IsProcessInJob (kernelbase.@)
928 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessInJob( HANDLE process
, HANDLE job
, BOOL
*result
)
930 NTSTATUS status
= NtIsProcessInJob( process
, job
);
934 case STATUS_PROCESS_IN_JOB
:
937 case STATUS_PROCESS_NOT_IN_JOB
:
941 return set_ntstatus( status
);
946 /***********************************************************************
947 * IsProcessorFeaturePresent (kernelbase.@)
949 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessorFeaturePresent ( DWORD feature
)
951 return RtlIsProcessorFeaturePresent( feature
);
955 /**********************************************************************
956 * IsWow64Process2 (kernelbase.@)
958 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process2( HANDLE process
, USHORT
*machine
, USHORT
*native_machine
)
963 TRACE( "(%p,%p,%p)\n", process
, machine
, native_machine
);
965 if (!IsWow64Process( process
, &wow64
))
970 if (process
!= GetCurrentProcess())
972 #if defined(__i386__) || defined(__x86_64__)
973 *machine
= IMAGE_FILE_MACHINE_I386
;
975 FIXME("not implemented for other process\n");
976 *machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
981 IMAGE_NT_HEADERS
*nt
;
982 nt
= RtlImageNtHeader( NtCurrentTeb()->Peb
->ImageBaseAddress
);
983 *machine
= nt
->FileHeader
.Machine
;
986 if (!native_machine
) return TRUE
;
988 GetNativeSystemInfo( &si
);
992 *machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
994 if (!native_machine
) return TRUE
;
997 GetSystemInfo( &si
);
999 GetNativeSystemInfo( &si
);
1003 switch (si
.u
.s
.wProcessorArchitecture
)
1005 case PROCESSOR_ARCHITECTURE_INTEL
:
1006 *native_machine
= IMAGE_FILE_MACHINE_I386
;
1008 case PROCESSOR_ARCHITECTURE_ARM
:
1009 *native_machine
= IMAGE_FILE_MACHINE_ARM
;
1011 case PROCESSOR_ARCHITECTURE_AMD64
:
1012 *native_machine
= IMAGE_FILE_MACHINE_AMD64
;
1014 case PROCESSOR_ARCHITECTURE_ARM64
:
1015 *native_machine
= IMAGE_FILE_MACHINE_ARM64
;
1018 FIXME("unknown architecture %u\n", si
.u
.s
.wProcessorArchitecture
);
1019 *native_machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
1027 /**********************************************************************
1028 * IsWow64Process (kernelbase.@)
1030 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process( HANDLE process
, PBOOL wow64
)
1035 status
= NtQueryInformationProcess( process
, ProcessWow64Information
, &pbi
, sizeof(pbi
), NULL
);
1036 if (!status
) *wow64
= !!pbi
;
1037 return set_ntstatus( status
);
1041 /*********************************************************************
1042 * OpenProcess (kernelbase.@)
1044 HANDLE WINAPI DECLSPEC_HOTPATCH
OpenProcess( DWORD access
, BOOL inherit
, DWORD id
)
1047 OBJECT_ATTRIBUTES attr
;
1050 if (GetVersion() & 0x80000000) access
= PROCESS_ALL_ACCESS
;
1052 attr
.Length
= sizeof(OBJECT_ATTRIBUTES
);
1053 attr
.RootDirectory
= 0;
1054 attr
.Attributes
= inherit
? OBJ_INHERIT
: 0;
1055 attr
.ObjectName
= NULL
;
1056 attr
.SecurityDescriptor
= NULL
;
1057 attr
.SecurityQualityOfService
= NULL
;
1059 cid
.UniqueProcess
= ULongToHandle(id
);
1060 cid
.UniqueThread
= 0;
1062 if (!set_ntstatus( NtOpenProcess( &handle
, access
, &attr
, &cid
))) return NULL
;
1067 /***********************************************************************
1068 * ProcessIdToSessionId (kernelbase.@)
1070 BOOL WINAPI DECLSPEC_HOTPATCH
ProcessIdToSessionId( DWORD procid
, DWORD
*sessionid
)
1072 if (procid
!= GetCurrentProcessId()) FIXME( "Unsupported for other process %x\n", procid
);
1073 *sessionid
= NtCurrentTeb()->Peb
->SessionId
;
1078 /***********************************************************************
1079 * QueryProcessCycleTime (kernelbase.@)
1081 BOOL WINAPI DECLSPEC_HOTPATCH
QueryProcessCycleTime( HANDLE process
, ULONG64
*cycle
)
1084 if (!once
++) FIXME( "(%p,%p): stub!\n", process
, cycle
);
1085 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1090 /***********************************************************************
1091 * SetErrorMode (kernelbase.@)
1093 UINT WINAPI DECLSPEC_HOTPATCH
SetErrorMode( UINT mode
)
1095 UINT old
= GetErrorMode();
1097 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
1098 &mode
, sizeof(mode
) );
1103 /*************************************************************************
1104 * SetHandleCount (kernelbase.@)
1106 UINT WINAPI DECLSPEC_HOTPATCH
SetHandleCount( UINT count
)
1112 /*********************************************************************
1113 * SetHandleInformation (kernelbase.@)
1115 BOOL WINAPI DECLSPEC_HOTPATCH
SetHandleInformation( HANDLE handle
, DWORD mask
, DWORD flags
)
1117 OBJECT_DATA_INFORMATION info
;
1119 /* if not setting both fields, retrieve current value first */
1120 if ((mask
& (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
)) !=
1121 (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
))
1123 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
1126 if (mask
& HANDLE_FLAG_INHERIT
)
1127 info
.InheritHandle
= (flags
& HANDLE_FLAG_INHERIT
) != 0;
1128 if (mask
& HANDLE_FLAG_PROTECT_FROM_CLOSE
)
1129 info
.ProtectFromClose
= (flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
) != 0;
1131 return set_ntstatus( NtSetInformationObject( handle
, ObjectDataInformation
, &info
, sizeof(info
) ));
1135 /***********************************************************************
1136 * SetPriorityClass (kernelbase.@)
1138 BOOL WINAPI DECLSPEC_HOTPATCH
SetPriorityClass( HANDLE process
, DWORD
class )
1140 PROCESS_PRIORITY_CLASS ppc
;
1142 ppc
.Foreground
= FALSE
;
1145 case IDLE_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_IDLE
; break;
1146 case BELOW_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_BELOW_NORMAL
; break;
1147 case NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_NORMAL
; break;
1148 case ABOVE_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_ABOVE_NORMAL
; break;
1149 case HIGH_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_HIGH
; break;
1150 case REALTIME_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_REALTIME
; break;
1152 SetLastError( ERROR_INVALID_PARAMETER
);
1155 return set_ntstatus( NtSetInformationProcess( process
, ProcessPriorityClass
, &ppc
, sizeof(ppc
) ));
1159 /***********************************************************************
1160 * SetProcessAffinityUpdateMode (kernelbase.@)
1162 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessAffinityUpdateMode( HANDLE process
, DWORD flags
)
1164 FIXME( "(%p,0x%08x): stub\n", process
, flags
);
1165 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1170 /**********************************************************************
1171 * SetProcessMitigationPolicy (kernelbase.@)
1173 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy
,
1174 void *buffer
, SIZE_T length
)
1176 FIXME( "(%d, %p, %lu): stub\n", policy
, buffer
, length
);
1181 /***********************************************************************
1182 * SetProcessPriorityBoost (kernelbase.@)
1184 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process
, BOOL disable
)
1186 FIXME( "(%p,%d): stub\n", process
, disable
);
1191 /***********************************************************************
1192 * SetProcessShutdownParameters (kernelbase.@)
1194 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessShutdownParameters( DWORD level
, DWORD flags
)
1196 FIXME( "(%08x, %08x): partial stub.\n", level
, flags
);
1197 shutdown_flags
= flags
;
1198 shutdown_priority
= level
;
1203 /***********************************************************************
1204 * SetProcessWorkingSetSizeEx (kernelbase.@)
1206 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T minset
,
1207 SIZE_T maxset
, DWORD flags
)
1213 /******************************************************************************
1214 * TerminateProcess (kernelbase.@)
1216 BOOL WINAPI DECLSPEC_HOTPATCH
TerminateProcess( HANDLE handle
, DWORD exit_code
)
1220 SetLastError( ERROR_INVALID_HANDLE
);
1223 return set_ntstatus( NtTerminateProcess( handle
, exit_code
));
1227 /***********************************************************************
1228 * Process startup information
1229 ***********************************************************************/
1232 static STARTUPINFOW startup_infoW
;
1233 static char *command_lineA
;
1234 static WCHAR
*command_lineW
;
1236 /******************************************************************
1239 void init_startup_info( RTL_USER_PROCESS_PARAMETERS
*params
)
1243 startup_infoW
.cb
= sizeof(startup_infoW
);
1244 startup_infoW
.lpReserved
= NULL
;
1245 startup_infoW
.lpDesktop
= params
->Desktop
.Buffer
;
1246 startup_infoW
.lpTitle
= params
->WindowTitle
.Buffer
;
1247 startup_infoW
.dwX
= params
->dwX
;
1248 startup_infoW
.dwY
= params
->dwY
;
1249 startup_infoW
.dwXSize
= params
->dwXSize
;
1250 startup_infoW
.dwYSize
= params
->dwYSize
;
1251 startup_infoW
.dwXCountChars
= params
->dwXCountChars
;
1252 startup_infoW
.dwYCountChars
= params
->dwYCountChars
;
1253 startup_infoW
.dwFillAttribute
= params
->dwFillAttribute
;
1254 startup_infoW
.dwFlags
= params
->dwFlags
;
1255 startup_infoW
.wShowWindow
= params
->wShowWindow
;
1256 startup_infoW
.cbReserved2
= params
->RuntimeInfo
.MaximumLength
;
1257 startup_infoW
.lpReserved2
= params
->RuntimeInfo
.MaximumLength
? (void *)params
->RuntimeInfo
.Buffer
: NULL
;
1258 startup_infoW
.hStdInput
= params
->hStdInput
? params
->hStdInput
: INVALID_HANDLE_VALUE
;
1259 startup_infoW
.hStdOutput
= params
->hStdOutput
? params
->hStdOutput
: INVALID_HANDLE_VALUE
;
1260 startup_infoW
.hStdError
= params
->hStdError
? params
->hStdError
: INVALID_HANDLE_VALUE
;
1262 command_lineW
= params
->CommandLine
.Buffer
;
1263 if (!RtlUnicodeStringToAnsiString( &ansi
, ¶ms
->CommandLine
, TRUE
)) command_lineA
= ansi
.Buffer
;
1267 /**********************************************************************
1268 * BaseFlushAppcompatCache (kernelbase.@)
1270 BOOL WINAPI
BaseFlushAppcompatCache(void)
1273 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1278 /***********************************************************************
1279 * GetCommandLineA (kernelbase.@)
1281 LPSTR WINAPI
GetCommandLineA(void)
1283 return command_lineA
;
1287 /***********************************************************************
1288 * GetCommandLineW (kernelbase.@)
1290 LPWSTR WINAPI
GetCommandLineW(void)
1292 return command_lineW
;
1296 /***********************************************************************
1297 * GetStartupInfoW (kernelbase.@)
1299 void WINAPI DECLSPEC_HOTPATCH
GetStartupInfoW( STARTUPINFOW
*info
)
1301 *info
= startup_infoW
;
1305 /***********************************************************************
1306 * GetStdHandle (kernelbase.@)
1308 HANDLE WINAPI DECLSPEC_HOTPATCH
GetStdHandle( DWORD std_handle
)
1312 case STD_INPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
1313 case STD_OUTPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
1314 case STD_ERROR_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
1316 SetLastError( ERROR_INVALID_HANDLE
);
1317 return INVALID_HANDLE_VALUE
;
1321 /***********************************************************************
1322 * SetStdHandle (kernelbase.@)
1324 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandle( DWORD std_handle
, HANDLE handle
)
1328 case STD_INPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
= handle
; return TRUE
;
1329 case STD_OUTPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
= handle
; return TRUE
;
1330 case STD_ERROR_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
= handle
; return TRUE
;
1332 SetLastError( ERROR_INVALID_HANDLE
);
1337 /***********************************************************************
1338 * SetStdHandleEx (kernelbase.@)
1340 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandleEx( DWORD std_handle
, HANDLE handle
, HANDLE
*prev
)
1346 case STD_INPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
; break;
1347 case STD_OUTPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
; break;
1348 case STD_ERROR_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
; break;
1350 SetLastError( ERROR_INVALID_HANDLE
);
1353 if (prev
) *prev
= *ptr
;
1359 /***********************************************************************
1360 * Process environment
1361 ***********************************************************************/
1364 static inline SIZE_T
get_env_length( const WCHAR
*env
)
1366 const WCHAR
*end
= env
;
1367 while (*end
) end
+= lstrlenW(end
) + 1;
1368 return end
+ 1 - env
;
1371 /***********************************************************************
1372 * ExpandEnvironmentStringsA (kernelbase.@)
1374 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsA( LPCSTR src
, LPSTR dst
, DWORD count
)
1376 UNICODE_STRING us_src
;
1380 RtlCreateUnicodeStringFromAsciiz( &us_src
, src
);
1383 if (!(dstW
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
)))) return 0;
1384 ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, dstW
, count
);
1385 if (ret
) WideCharToMultiByte( CP_ACP
, 0, dstW
, ret
, dst
, count
, NULL
, NULL
);
1387 else ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, NULL
, 0 );
1389 RtlFreeUnicodeString( &us_src
);
1390 HeapFree( GetProcessHeap(), 0, dstW
);
1395 /***********************************************************************
1396 * ExpandEnvironmentStringsW (kernelbase.@)
1398 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsW( LPCWSTR src
, LPWSTR dst
, DWORD len
)
1400 UNICODE_STRING us_src
, us_dst
;
1404 TRACE( "(%s %p %u)\n", debugstr_w(src
), dst
, len
);
1406 RtlInitUnicodeString( &us_src
, src
);
1408 /* make sure we don't overflow the maximum UNICODE_STRING size */
1409 len
= min( len
, UNICODE_STRING_MAX_CHARS
);
1412 us_dst
.MaximumLength
= len
* sizeof(WCHAR
);
1413 us_dst
.Buffer
= dst
;
1416 status
= RtlExpandEnvironmentStrings_U( NULL
, &us_src
, &us_dst
, &res
);
1417 res
/= sizeof(WCHAR
);
1418 if (!set_ntstatus( status
))
1420 if (status
!= STATUS_BUFFER_TOO_SMALL
) return 0;
1421 if (len
&& dst
) dst
[len
- 1] = 0;
1427 /***********************************************************************
1428 * GetEnvironmentStrings (kernelbase.@)
1429 * GetEnvironmentStringsA (kernelbase.@)
1431 LPSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsA(void)
1437 RtlAcquirePebLock();
1438 env
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
1439 lenW
= get_env_length( env
);
1440 lenA
= WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, NULL
, 0, NULL
, NULL
);
1441 if ((ret
= HeapAlloc( GetProcessHeap(), 0, lenA
)))
1442 WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, ret
, lenA
, NULL
, NULL
);
1443 RtlReleasePebLock();
1448 /***********************************************************************
1449 * GetEnvironmentStringsW (kernelbase.@)
1451 LPWSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsW(void)
1456 RtlAcquirePebLock();
1457 len
= get_env_length( NtCurrentTeb()->Peb
->ProcessParameters
->Environment
) * sizeof(WCHAR
);
1458 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
1459 memcpy( ret
, NtCurrentTeb()->Peb
->ProcessParameters
->Environment
, len
);
1460 RtlReleasePebLock();
1465 /***********************************************************************
1466 * SetEnvironmentStringsA (kernelbase.@)
1468 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsA( char *env
)
1471 const char *p
= env
;
1475 for (p
= env
; *p
; p
+= strlen( p
) + 1);
1477 len
= MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, NULL
, 0 );
1478 if (!(envW
= HeapAlloc( GetProcessHeap(), 0, len
)))
1480 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1483 MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, envW
, len
);
1484 ret
= SetEnvironmentStringsW( envW
);
1485 HeapFree( GetProcessHeap(), 0, envW
);
1490 /***********************************************************************
1491 * SetEnvironmentStringsW (kernelbase.@)
1493 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsW( WCHAR
*env
)
1499 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1501 const WCHAR
*eq
= wcschr( p
, '=' );
1504 SetLastError( ERROR_INVALID_PARAMETER
);
1509 if ((status
= RtlCreateEnvironment( FALSE
, &new_env
)))
1510 return set_ntstatus( status
);
1512 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1514 const WCHAR
*eq
= wcschr( p
, '=' );
1515 UNICODE_STRING var
, value
;
1517 var
.Length
= (eq
- p
) * sizeof(WCHAR
);
1518 RtlInitUnicodeString( &value
, eq
+ 1 );
1519 if ((status
= RtlSetEnvironmentVariable( &new_env
, &var
, &value
)))
1521 RtlDestroyEnvironment( new_env
);
1522 return set_ntstatus( status
);
1526 RtlSetCurrentEnvironment( new_env
, NULL
);
1531 /***********************************************************************
1532 * GetEnvironmentVariableA (kernelbase.@)
1534 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableA( LPCSTR name
, LPSTR value
, DWORD size
)
1536 UNICODE_STRING us_name
, us_value
;
1541 /* limit the size to sane values */
1542 size
= min( size
, 32767 );
1543 if (!(valueW
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1545 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1546 us_value
.Length
= 0;
1547 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1548 us_value
.Buffer
= valueW
;
1550 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1551 len
= us_value
.Length
/ sizeof(WCHAR
);
1552 if (status
== STATUS_BUFFER_TOO_SMALL
) ret
= len
+ 1;
1553 else if (!set_ntstatus( status
)) ret
= 0;
1554 else if (!size
) ret
= len
+ 1;
1557 if (len
) WideCharToMultiByte( CP_ACP
, 0, valueW
, len
+ 1, value
, size
, NULL
, NULL
);
1562 RtlFreeUnicodeString( &us_name
);
1563 HeapFree( GetProcessHeap(), 0, valueW
);
1568 /***********************************************************************
1569 * GetEnvironmentVariableW (kernelbase.@)
1571 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableW( LPCWSTR name
, LPWSTR val
, DWORD size
)
1573 UNICODE_STRING us_name
, us_value
;
1577 TRACE( "(%s %p %u)\n", debugstr_w(name
), val
, size
);
1579 RtlInitUnicodeString( &us_name
, name
);
1580 us_value
.Length
= 0;
1581 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1582 us_value
.Buffer
= val
;
1584 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1585 len
= us_value
.Length
/ sizeof(WCHAR
);
1586 if (status
== STATUS_BUFFER_TOO_SMALL
) return len
+ 1;
1587 if (!set_ntstatus( status
)) return 0;
1588 if (!size
) return len
+ 1;
1594 /***********************************************************************
1595 * FreeEnvironmentStringsA (kernelbase.@)
1596 * FreeEnvironmentStringsW (kernelbase.@)
1598 BOOL WINAPI DECLSPEC_HOTPATCH
FreeEnvironmentStringsW( LPWSTR ptr
)
1600 return HeapFree( GetProcessHeap(), 0, ptr
);
1604 /***********************************************************************
1605 * SetEnvironmentVariableA (kernelbase.@)
1607 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableA( LPCSTR name
, LPCSTR value
)
1609 UNICODE_STRING us_name
, us_value
;
1614 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1618 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1621 RtlCreateUnicodeStringFromAsciiz( &us_value
, value
);
1622 ret
= SetEnvironmentVariableW( us_name
.Buffer
, us_value
.Buffer
);
1623 RtlFreeUnicodeString( &us_value
);
1625 else ret
= SetEnvironmentVariableW( us_name
.Buffer
, NULL
);
1626 RtlFreeUnicodeString( &us_name
);
1631 /***********************************************************************
1632 * SetEnvironmentVariableW (kernelbase.@)
1634 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableW( LPCWSTR name
, LPCWSTR value
)
1636 UNICODE_STRING us_name
, us_value
;
1639 TRACE( "(%s %s)\n", debugstr_w(name
), debugstr_w(value
) );
1643 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1647 RtlInitUnicodeString( &us_name
, name
);
1650 RtlInitUnicodeString( &us_value
, value
);
1651 status
= RtlSetEnvironmentVariable( NULL
, &us_name
, &us_value
);
1653 else status
= RtlSetEnvironmentVariable( NULL
, &us_name
, NULL
);
1655 return set_ntstatus( status
);
1659 /***********************************************************************
1660 * Process/thread attribute lists
1661 ***********************************************************************/
1663 /***********************************************************************
1664 * InitializeProcThreadAttributeList (kernelbase.@)
1666 BOOL WINAPI DECLSPEC_HOTPATCH
InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1667 DWORD count
, DWORD flags
, SIZE_T
*size
)
1672 TRACE( "(%p %d %x %p)\n", list
, count
, flags
, size
);
1674 needed
= FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST
, attrs
[count
] );
1675 if (list
&& *size
>= needed
)
1683 else SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1690 /***********************************************************************
1691 * UpdateProcThreadAttribute (kernelbase.@)
1693 BOOL WINAPI DECLSPEC_HOTPATCH
UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1694 DWORD flags
, DWORD_PTR attr
, void *value
,
1695 SIZE_T size
, void *prev_ret
, SIZE_T
*size_ret
)
1698 struct proc_thread_attr
*entry
;
1700 TRACE( "(%p %x %08lx %p %ld %p %p)\n", list
, flags
, attr
, value
, size
, prev_ret
, size_ret
);
1702 if (list
->count
>= list
->size
)
1704 SetLastError( ERROR_GEN_FAILURE
);
1710 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
1711 if (size
!= sizeof(HANDLE
))
1713 SetLastError( ERROR_BAD_LENGTH
);
1718 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
1719 if ((size
/ sizeof(HANDLE
)) * sizeof(HANDLE
) != size
)
1721 SetLastError( ERROR_BAD_LENGTH
);
1726 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR
:
1727 if (size
!= sizeof(PROCESSOR_NUMBER
))
1729 SetLastError( ERROR_BAD_LENGTH
);
1734 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY
:
1735 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
))
1737 SetLastError( ERROR_BAD_LENGTH
);
1742 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
:
1743 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
) && size
!= sizeof(DWORD64
) * 2)
1745 SetLastError( ERROR_BAD_LENGTH
);
1750 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
1751 if (size
!= sizeof(HPCON
))
1753 SetLastError( ERROR_BAD_LENGTH
);
1759 SetLastError( ERROR_NOT_SUPPORTED
);
1760 FIXME( "Unhandled attribute %lu\n", attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1764 mask
= 1 << (attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1765 if (list
->mask
& mask
)
1767 SetLastError( ERROR_OBJECT_NAME_EXISTS
);
1772 entry
= list
->attrs
+ list
->count
;
1775 entry
->value
= value
;
1781 /***********************************************************************
1782 * DeleteProcThreadAttributeList (kernelbase.@)
1784 void WINAPI DECLSPEC_HOTPATCH
DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
)