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
| CREATE_NEW_CONSOLE
))
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
, DWORD process_flags
,
250 RTL_USER_PROCESS_PARAMETERS
*params
,
251 RTL_USER_PROCESS_INFORMATION
*info
, HANDLE parent
,
252 const struct proc_thread_attr
*handle_list
,
253 const struct proc_thread_attr
*job_list
)
255 OBJECT_ATTRIBUTES process_attr
, thread_attr
;
256 PS_CREATE_INFO create_info
;
257 ULONG_PTR buffer
[offsetof( PS_ATTRIBUTE_LIST
, Attributes
[8] ) / sizeof(ULONG_PTR
)];
258 PS_ATTRIBUTE_LIST
*attr
= (PS_ATTRIBUTE_LIST
*)buffer
;
259 UNICODE_STRING nameW
;
263 if (!params
->ImagePathName
.Buffer
[0]) return STATUS_OBJECT_PATH_NOT_FOUND
;
264 status
= RtlDosPathNameToNtPathName_U_WithStatus( params
->ImagePathName
.Buffer
, &nameW
, NULL
, NULL
);
267 RtlNormalizeProcessParams( params
);
269 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_NAME
;
270 attr
->Attributes
[pos
].Size
= nameW
.Length
;
271 attr
->Attributes
[pos
].ValuePtr
= nameW
.Buffer
;
272 attr
->Attributes
[pos
].ReturnLength
= NULL
;
274 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_CLIENT_ID
;
275 attr
->Attributes
[pos
].Size
= sizeof(info
->ClientId
);
276 attr
->Attributes
[pos
].ValuePtr
= &info
->ClientId
;
277 attr
->Attributes
[pos
].ReturnLength
= NULL
;
279 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_INFO
;
280 attr
->Attributes
[pos
].Size
= sizeof(info
->ImageInformation
);
281 attr
->Attributes
[pos
].ValuePtr
= &info
->ImageInformation
;
282 attr
->Attributes
[pos
].ReturnLength
= NULL
;
286 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_PARENT_PROCESS
;
287 attr
->Attributes
[pos
].Size
= sizeof(parent
);
288 attr
->Attributes
[pos
].ValuePtr
= parent
;
289 attr
->Attributes
[pos
].ReturnLength
= NULL
;
292 if ((process_flags
& PROCESS_CREATE_FLAGS_INHERIT_HANDLES
) && handle_list
)
294 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_HANDLE_LIST
;
295 attr
->Attributes
[pos
].Size
= handle_list
->size
;
296 attr
->Attributes
[pos
].ValuePtr
= handle_list
->value
;
297 attr
->Attributes
[pos
].ReturnLength
= NULL
;
302 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_TOKEN
;
303 attr
->Attributes
[pos
].Size
= sizeof(token
);
304 attr
->Attributes
[pos
].ValuePtr
= token
;
305 attr
->Attributes
[pos
].ReturnLength
= NULL
;
310 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_DEBUG_PORT
;
311 attr
->Attributes
[pos
].Size
= sizeof(debug
);
312 attr
->Attributes
[pos
].ValuePtr
= debug
;
313 attr
->Attributes
[pos
].ReturnLength
= NULL
;
318 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_JOB_LIST
;
319 attr
->Attributes
[pos
].Size
= job_list
->size
;
320 attr
->Attributes
[pos
].ValuePtr
= job_list
->value
;
321 attr
->Attributes
[pos
].ReturnLength
= NULL
;
324 attr
->TotalLength
= offsetof( PS_ATTRIBUTE_LIST
, Attributes
[pos
] );
326 InitializeObjectAttributes( &process_attr
, NULL
, 0, NULL
, psa
? psa
->lpSecurityDescriptor
: NULL
);
327 InitializeObjectAttributes( &thread_attr
, NULL
, 0, NULL
, tsa
? tsa
->lpSecurityDescriptor
: NULL
);
329 status
= NtCreateUserProcess( &info
->Process
, &info
->Thread
, PROCESS_ALL_ACCESS
, THREAD_ALL_ACCESS
,
330 &process_attr
, &thread_attr
, process_flags
,
331 THREAD_CREATE_FLAGS_CREATE_SUSPENDED
, params
,
332 &create_info
, attr
);
334 RtlFreeUnicodeString( &nameW
);
340 /***********************************************************************
343 static NTSTATUS
create_vdm_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
344 SECURITY_ATTRIBUTES
*tsa
, DWORD flags
,
345 RTL_USER_PROCESS_PARAMETERS
*params
,
346 RTL_USER_PROCESS_INFORMATION
*info
)
348 const WCHAR
*winevdm
= (is_win64
|| is_wow64
?
349 L
"C:\\windows\\syswow64\\winevdm.exe" :
350 L
"C:\\windows\\system32\\winevdm.exe");
355 len
= (lstrlenW(params
->ImagePathName
.Buffer
) + lstrlenW(params
->CommandLine
.Buffer
) +
356 lstrlenW(winevdm
) + 16);
358 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
359 return STATUS_NO_MEMORY
;
361 swprintf( newcmdline
, len
, L
"%s --app-name \"%s\" %s",
362 winevdm
, params
->ImagePathName
.Buffer
, params
->CommandLine
.Buffer
);
363 RtlInitUnicodeString( ¶ms
->ImagePathName
, winevdm
);
364 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
365 status
= create_nt_process( token
, debug
, psa
, tsa
, flags
, params
, info
, NULL
, NULL
, NULL
);
366 HeapFree( GetProcessHeap(), 0, newcmdline
);
371 /***********************************************************************
374 static NTSTATUS
create_cmd_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
375 SECURITY_ATTRIBUTES
*tsa
, DWORD flags
,
376 RTL_USER_PROCESS_PARAMETERS
*params
,
377 RTL_USER_PROCESS_INFORMATION
*info
)
379 WCHAR comspec
[MAX_PATH
];
384 if (!GetEnvironmentVariableW( L
"COMSPEC", comspec
, ARRAY_SIZE( comspec
)))
385 lstrcpyW( comspec
, L
"C:\\windows\\system32\\cmd.exe" );
387 len
= lstrlenW(comspec
) + 7 + lstrlenW(params
->CommandLine
.Buffer
) + 2;
388 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
389 return STATUS_NO_MEMORY
;
391 swprintf( newcmdline
, len
, L
"%s /s/c \"%s\"", comspec
, params
->CommandLine
.Buffer
);
392 RtlInitUnicodeString( ¶ms
->ImagePathName
, comspec
);
393 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
394 status
= create_nt_process( token
, debug
, psa
, tsa
, flags
, params
, info
, NULL
, NULL
, NULL
);
395 RtlFreeHeap( GetProcessHeap(), 0, newcmdline
);
400 /*********************************************************************
401 * CloseHandle (kernelbase.@)
403 BOOL WINAPI DECLSPEC_HOTPATCH
CloseHandle( HANDLE handle
)
405 if (handle
== (HANDLE
)STD_INPUT_HANDLE
)
406 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
, 0 );
407 else if (handle
== (HANDLE
)STD_OUTPUT_HANDLE
)
408 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
, 0 );
409 else if (handle
== (HANDLE
)STD_ERROR_HANDLE
)
410 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
, 0 );
412 return set_ntstatus( NtClose( handle
));
416 /**********************************************************************
417 * CreateProcessAsUserA (kernelbase.@)
419 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserA( HANDLE token
, const char *app_name
, char *cmd_line
,
420 SECURITY_ATTRIBUTES
*process_attr
,
421 SECURITY_ATTRIBUTES
*thread_attr
,
422 BOOL inherit
, DWORD flags
, void *env
,
423 const char *cur_dir
, STARTUPINFOA
*startup_info
,
424 PROCESS_INFORMATION
*info
)
426 return CreateProcessInternalA( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
427 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
431 /**********************************************************************
432 * CreateProcessAsUserW (kernelbase.@)
434 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
435 SECURITY_ATTRIBUTES
*process_attr
,
436 SECURITY_ATTRIBUTES
*thread_attr
,
437 BOOL inherit
, DWORD flags
, void *env
,
438 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
439 PROCESS_INFORMATION
*info
)
441 return CreateProcessInternalW( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
442 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
445 /**********************************************************************
446 * CreateProcessInternalA (kernelbase.@)
448 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalA( HANDLE token
, const char *app_name
, char *cmd_line
,
449 SECURITY_ATTRIBUTES
*process_attr
,
450 SECURITY_ATTRIBUTES
*thread_attr
,
451 BOOL inherit
, DWORD flags
, void *env
,
452 const char *cur_dir
, STARTUPINFOA
*startup_info
,
453 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
456 WCHAR
*app_nameW
= NULL
, *cmd_lineW
= NULL
, *cur_dirW
= NULL
;
457 UNICODE_STRING desktopW
, titleW
;
458 STARTUPINFOEXW infoW
;
460 desktopW
.Buffer
= NULL
;
461 titleW
.Buffer
= NULL
;
462 if (app_name
&& !(app_nameW
= file_name_AtoW( app_name
, TRUE
))) goto done
;
463 if (cmd_line
&& !(cmd_lineW
= file_name_AtoW( cmd_line
, TRUE
))) goto done
;
464 if (cur_dir
&& !(cur_dirW
= file_name_AtoW( cur_dir
, TRUE
))) goto done
;
466 if (startup_info
->lpDesktop
) RtlCreateUnicodeStringFromAsciiz( &desktopW
, startup_info
->lpDesktop
);
467 if (startup_info
->lpTitle
) RtlCreateUnicodeStringFromAsciiz( &titleW
, startup_info
->lpTitle
);
469 memcpy( &infoW
.StartupInfo
, startup_info
, sizeof(infoW
.StartupInfo
) );
470 infoW
.StartupInfo
.lpDesktop
= desktopW
.Buffer
;
471 infoW
.StartupInfo
.lpTitle
= titleW
.Buffer
;
473 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
474 infoW
.lpAttributeList
= ((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
476 ret
= CreateProcessInternalW( token
, app_nameW
, cmd_lineW
, process_attr
, thread_attr
,
477 inherit
, flags
, env
, cur_dirW
, (STARTUPINFOW
*)&infoW
, info
, new_token
);
479 RtlFreeHeap( GetProcessHeap(), 0, app_nameW
);
480 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW
);
481 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW
);
482 RtlFreeUnicodeString( &desktopW
);
483 RtlFreeUnicodeString( &titleW
);
487 /**********************************************************************
488 * CreateProcessInternalW (kernelbase.@)
490 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
491 SECURITY_ATTRIBUTES
*process_attr
,
492 SECURITY_ATTRIBUTES
*thread_attr
,
493 BOOL inherit
, DWORD flags
, void *env
,
494 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
495 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
497 const struct proc_thread_attr
*handle_list
= NULL
, *job_list
= NULL
;
498 WCHAR name
[MAX_PATH
];
499 WCHAR
*p
, *tidy_cmdline
= cmd_line
;
500 RTL_USER_PROCESS_PARAMETERS
*params
= NULL
;
501 RTL_USER_PROCESS_INFORMATION rtl_info
;
502 HANDLE parent
= 0, debug
= 0;
506 /* Process the AppName and/or CmdLine to get module name and path */
508 TRACE( "app %s cmdline %s\n", debugstr_w(app_name
), debugstr_w(cmd_line
) );
510 if (new_token
) FIXME( "No support for returning created process token\n" );
514 if (!cmd_line
|| !cmd_line
[0]) /* no command-line, create one */
516 if (!(tidy_cmdline
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name
)+3) * sizeof(WCHAR
) )))
518 swprintf( tidy_cmdline
, lstrlenW(app_name
) + 3, L
"\"%s\"", app_name
);
523 if (!(tidy_cmdline
= get_file_name( cmd_line
, name
, ARRAY_SIZE(name
) ))) return FALSE
;
527 /* Warn if unsupported features are used */
529 if (flags
& (IDLE_PRIORITY_CLASS
| HIGH_PRIORITY_CLASS
| REALTIME_PRIORITY_CLASS
|
530 CREATE_DEFAULT_ERROR_MODE
| CREATE_NO_WINDOW
|
531 PROFILE_USER
| PROFILE_KERNEL
| PROFILE_SERVER
))
532 WARN( "(%s,...): ignoring some flags in %x\n", debugstr_w(app_name
), flags
);
536 DWORD attr
= GetFileAttributesW( cur_dir
);
537 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
539 status
= STATUS_NOT_A_DIRECTORY
;
544 info
->hThread
= info
->hProcess
= 0;
545 info
->dwProcessId
= info
->dwThreadId
= 0;
547 if (!(params
= create_process_params( app_name
, tidy_cmdline
, cur_dir
, env
, flags
, startup_info
)))
549 status
= STATUS_NO_MEMORY
;
553 if (flags
& (DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
))
555 if ((status
= DbgUiConnectToDbg())) goto done
;
556 debug
= DbgUiGetThreadDebugObject();
559 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
561 struct _PROC_THREAD_ATTRIBUTE_LIST
*attrs
=
562 (struct _PROC_THREAD_ATTRIBUTE_LIST
*)((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
567 for (i
= 0; i
< attrs
->count
; ++i
)
569 switch(attrs
->attrs
[i
].attr
)
571 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
572 parent
= *(HANDLE
*)attrs
->attrs
[i
].value
;
573 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent
);
576 status
= STATUS_INVALID_HANDLE
;
580 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
581 handle_list
= &attrs
->attrs
[i
];
582 TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs
->attrs
[i
].size
/ sizeof(HANDLE
));
584 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
586 struct pseudo_console
*console
= attrs
->attrs
[i
].value
;
587 TRACE( "PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE %p reference %p\n",
588 console
, console
->reference
);
589 params
->ConsoleHandle
= console
->reference
;
592 case PROC_THREAD_ATTRIBUTE_JOB_LIST
:
593 job_list
= &attrs
->attrs
[i
];
594 TRACE( "PROC_THREAD_ATTRIBUTE_JOB_LIST handle count %Iu.\n",
595 attrs
->attrs
[i
].size
/ sizeof(HANDLE
) );
598 FIXME("Unsupported attribute %#Ix.\n", attrs
->attrs
[i
].attr
);
605 if (inherit
) nt_flags
|= PROCESS_CREATE_FLAGS_INHERIT_HANDLES
;
606 if (flags
& DEBUG_ONLY_THIS_PROCESS
) nt_flags
|= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT
;
607 if (flags
& CREATE_BREAKAWAY_FROM_JOB
) nt_flags
|= PROCESS_CREATE_FLAGS_BREAKAWAY
;
608 if (flags
& CREATE_SUSPENDED
) nt_flags
|= PROCESS_CREATE_FLAGS_SUSPENDED
;
610 status
= create_nt_process( token
, debug
, process_attr
, thread_attr
,
611 nt_flags
, params
, &rtl_info
, parent
, handle_list
, job_list
);
616 case STATUS_INVALID_IMAGE_WIN_16
:
617 case STATUS_INVALID_IMAGE_NE_FORMAT
:
618 case STATUS_INVALID_IMAGE_PROTECT
:
619 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name
) );
620 status
= create_vdm_process( token
, debug
, process_attr
, thread_attr
,
621 nt_flags
, params
, &rtl_info
);
623 case STATUS_INVALID_IMAGE_NOT_MZ
:
624 /* check for .com or .bat extension */
625 if (!(p
= wcsrchr( app_name
, '.' ))) break;
626 if (!wcsicmp( p
, L
".com" ) || !wcsicmp( p
, L
".pif" ))
628 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name
) );
629 status
= create_vdm_process( token
, debug
, process_attr
, thread_attr
,
630 nt_flags
, params
, &rtl_info
);
632 else if (!wcsicmp( p
, L
".bat" ) || !wcsicmp( p
, L
".cmd" ))
634 TRACE( "starting %s as batch binary\n", debugstr_w(app_name
) );
635 status
= create_cmd_process( token
, debug
, process_attr
, thread_attr
,
636 nt_flags
, params
, &rtl_info
);
643 info
->hProcess
= rtl_info
.Process
;
644 info
->hThread
= rtl_info
.Thread
;
645 info
->dwProcessId
= HandleToUlong( rtl_info
.ClientId
.UniqueProcess
);
646 info
->dwThreadId
= HandleToUlong( rtl_info
.ClientId
.UniqueThread
);
647 if (!(flags
& CREATE_SUSPENDED
)) NtResumeThread( rtl_info
.Thread
, NULL
);
648 TRACE( "started process pid %04x tid %04x\n", info
->dwProcessId
, info
->dwThreadId
);
652 RtlDestroyProcessParameters( params
);
653 if (tidy_cmdline
!= cmd_line
) HeapFree( GetProcessHeap(), 0, tidy_cmdline
);
654 return set_ntstatus( status
);
658 /**********************************************************************
659 * CreateProcessA (kernelbase.@)
661 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessA( const char *app_name
, char *cmd_line
,
662 SECURITY_ATTRIBUTES
*process_attr
,
663 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
,
664 DWORD flags
, void *env
, const char *cur_dir
,
665 STARTUPINFOA
*startup_info
, PROCESS_INFORMATION
*info
)
667 return CreateProcessInternalA( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
668 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
672 /**********************************************************************
673 * CreateProcessW (kernelbase.@)
675 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessW( const WCHAR
*app_name
, WCHAR
*cmd_line
,
676 SECURITY_ATTRIBUTES
*process_attr
,
677 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
, DWORD flags
,
678 void *env
, const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
679 PROCESS_INFORMATION
*info
)
681 return CreateProcessInternalW( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
682 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
686 /*********************************************************************
687 * DuplicateHandle (kernelbase.@)
689 BOOL WINAPI DECLSPEC_HOTPATCH
DuplicateHandle( HANDLE source_process
, HANDLE source
,
690 HANDLE dest_process
, HANDLE
*dest
,
691 DWORD access
, BOOL inherit
, DWORD options
)
693 return set_ntstatus( NtDuplicateObject( source_process
, source
, dest_process
, dest
,
694 access
, inherit
? OBJ_INHERIT
: 0, options
));
698 /****************************************************************************
699 * FlushInstructionCache (kernelbase.@)
701 BOOL WINAPI DECLSPEC_HOTPATCH
FlushInstructionCache( HANDLE process
, LPCVOID addr
, SIZE_T size
)
703 return set_ntstatus( NtFlushInstructionCache( process
, addr
, size
));
707 /***********************************************************************
708 * GetApplicationRestartSettings (kernelbase.@)
710 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ GetApplicationRestartSettings( HANDLE process
, WCHAR
*cmdline
,
711 DWORD
*size
, DWORD
*flags
)
713 FIXME( "%p, %p, %p, %p)\n", process
, cmdline
, size
, flags
);
718 /***********************************************************************
719 * GetCurrentProcess (kernelbase.@)
721 HANDLE WINAPI
kernelbase_GetCurrentProcess(void)
723 return (HANDLE
)~(ULONG_PTR
)0;
727 /***********************************************************************
728 * GetCurrentProcessId (kernelbase.@)
730 DWORD WINAPI
kernelbase_GetCurrentProcessId(void)
732 return HandleToULong( NtCurrentTeb()->ClientId
.UniqueProcess
);
736 /***********************************************************************
737 * GetErrorMode (kernelbase.@)
739 UINT WINAPI DECLSPEC_HOTPATCH
GetErrorMode(void)
743 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
744 &mode
, sizeof(mode
), NULL
);
749 /***********************************************************************
750 * GetExitCodeProcess (kernelbase.@)
752 BOOL WINAPI DECLSPEC_HOTPATCH
GetExitCodeProcess( HANDLE process
, LPDWORD exit_code
)
755 PROCESS_BASIC_INFORMATION pbi
;
757 status
= NtQueryInformationProcess( process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
758 if (!status
&& exit_code
) *exit_code
= pbi
.ExitStatus
;
759 return set_ntstatus( status
);
763 /*********************************************************************
764 * GetHandleInformation (kernelbase.@)
766 BOOL WINAPI DECLSPEC_HOTPATCH
GetHandleInformation( HANDLE handle
, DWORD
*flags
)
768 OBJECT_DATA_INFORMATION info
;
770 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
776 if (info
.InheritHandle
) *flags
|= HANDLE_FLAG_INHERIT
;
777 if (info
.ProtectFromClose
) *flags
|= HANDLE_FLAG_PROTECT_FROM_CLOSE
;
783 /***********************************************************************
784 * GetPriorityClass (kernelbase.@)
786 DWORD WINAPI DECLSPEC_HOTPATCH
GetPriorityClass( HANDLE process
)
788 PROCESS_BASIC_INFORMATION pbi
;
790 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
791 &pbi
, sizeof(pbi
), NULL
)))
794 switch (pbi
.BasePriority
)
796 case PROCESS_PRIOCLASS_IDLE
: return IDLE_PRIORITY_CLASS
;
797 case PROCESS_PRIOCLASS_BELOW_NORMAL
: return BELOW_NORMAL_PRIORITY_CLASS
;
798 case PROCESS_PRIOCLASS_NORMAL
: return NORMAL_PRIORITY_CLASS
;
799 case PROCESS_PRIOCLASS_ABOVE_NORMAL
: return ABOVE_NORMAL_PRIORITY_CLASS
;
800 case PROCESS_PRIOCLASS_HIGH
: return HIGH_PRIORITY_CLASS
;
801 case PROCESS_PRIOCLASS_REALTIME
: return REALTIME_PRIORITY_CLASS
;
807 /***********************************************************************
808 * GetProcessGroupAffinity (kernelbase.@)
810 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessGroupAffinity( HANDLE process
, USHORT
*count
, USHORT
*array
)
812 FIXME( "(%p,%p,%p): stub\n", process
, count
, array
);
813 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
818 /******************************************************************
819 * GetProcessHandleCount (kernelbase.@)
821 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessHandleCount( HANDLE process
, DWORD
*count
)
823 return set_ntstatus( NtQueryInformationProcess( process
, ProcessHandleCount
,
824 count
, sizeof(*count
), NULL
));
828 /***********************************************************************
829 * GetProcessHeap (kernelbase.@)
831 HANDLE WINAPI
kernelbase_GetProcessHeap(void)
833 return NtCurrentTeb()->Peb
->ProcessHeap
;
837 /*********************************************************************
838 * GetProcessId (kernelbase.@)
840 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessId( HANDLE process
)
842 PROCESS_BASIC_INFORMATION pbi
;
844 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
845 &pbi
, sizeof(pbi
), NULL
)))
847 return pbi
.UniqueProcessId
;
851 /**********************************************************************
852 * GetProcessMitigationPolicy (kernelbase.@)
854 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process
, PROCESS_MITIGATION_POLICY policy
,
855 void *buffer
, SIZE_T length
)
857 FIXME( "(%p, %u, %p, %lu): stub\n", process
, policy
, buffer
, length
);
862 /***********************************************************************
863 * GetProcessPriorityBoost (kernelbase.@)
865 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessPriorityBoost( HANDLE process
, PBOOL disable
)
867 FIXME( "(%p,%p): semi-stub\n", process
, disable
);
868 *disable
= FALSE
; /* report that no boost is present */
873 /***********************************************************************
874 * GetProcessShutdownParameters (kernelbase.@)
876 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessShutdownParameters( LPDWORD level
, LPDWORD flags
)
878 *level
= shutdown_priority
;
879 *flags
= shutdown_flags
;
884 /*********************************************************************
885 * GetProcessTimes (kernelbase.@)
887 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessTimes( HANDLE process
, FILETIME
*create
, FILETIME
*exit
,
888 FILETIME
*kernel
, FILETIME
*user
)
890 KERNEL_USER_TIMES time
;
892 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessTimes
, &time
, sizeof(time
), NULL
)))
895 create
->dwLowDateTime
= time
.CreateTime
.u
.LowPart
;
896 create
->dwHighDateTime
= time
.CreateTime
.u
.HighPart
;
897 exit
->dwLowDateTime
= time
.ExitTime
.u
.LowPart
;
898 exit
->dwHighDateTime
= time
.ExitTime
.u
.HighPart
;
899 kernel
->dwLowDateTime
= time
.KernelTime
.u
.LowPart
;
900 kernel
->dwHighDateTime
= time
.KernelTime
.u
.HighPart
;
901 user
->dwLowDateTime
= time
.UserTime
.u
.LowPart
;
902 user
->dwHighDateTime
= time
.UserTime
.u
.HighPart
;
907 /***********************************************************************
908 * GetProcessVersion (kernelbase.@)
910 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessVersion( DWORD pid
)
912 SECTION_IMAGE_INFORMATION info
;
916 if (pid
&& pid
!= GetCurrentProcessId())
918 if (!(process
= OpenProcess( PROCESS_QUERY_INFORMATION
, FALSE
, pid
))) return 0;
919 status
= NtQueryInformationProcess( process
, ProcessImageInformation
, &info
, sizeof(info
), NULL
);
920 CloseHandle( process
);
922 else status
= NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation
,
923 &info
, sizeof(info
), NULL
);
925 if (!set_ntstatus( status
)) return 0;
926 return MAKELONG( info
.MinorSubsystemVersion
, info
.MajorSubsystemVersion
);
930 /***********************************************************************
931 * GetProcessWorkingSetSizeEx (kernelbase.@)
933 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T
*minset
,
934 SIZE_T
*maxset
, DWORD
*flags
)
936 FIXME( "(%p,%p,%p,%p): stub\n", process
, minset
, maxset
, flags
);
937 /* 32 MB working set size */
938 if (minset
) *minset
= 32*1024*1024;
939 if (maxset
) *maxset
= 32*1024*1024;
940 if (flags
) *flags
= QUOTA_LIMITS_HARDWS_MIN_DISABLE
| QUOTA_LIMITS_HARDWS_MAX_DISABLE
;
945 /******************************************************************************
946 * IsProcessInJob (kernelbase.@)
948 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessInJob( HANDLE process
, HANDLE job
, BOOL
*result
)
950 NTSTATUS status
= NtIsProcessInJob( process
, job
);
954 case STATUS_PROCESS_IN_JOB
:
957 case STATUS_PROCESS_NOT_IN_JOB
:
961 return set_ntstatus( status
);
966 /***********************************************************************
967 * IsProcessorFeaturePresent (kernelbase.@)
969 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessorFeaturePresent ( DWORD feature
)
971 return RtlIsProcessorFeaturePresent( feature
);
975 /**********************************************************************
976 * IsWow64Process2 (kernelbase.@)
978 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process2( HANDLE process
, USHORT
*machine
, USHORT
*native_machine
)
980 return set_ntstatus( RtlWow64GetProcessMachines( process
, machine
, native_machine
));
984 /**********************************************************************
985 * IsWow64Process (kernelbase.@)
987 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process( HANDLE process
, PBOOL wow64
)
992 status
= NtQueryInformationProcess( process
, ProcessWow64Information
, &pbi
, sizeof(pbi
), NULL
);
993 if (!status
) *wow64
= !!pbi
;
994 return set_ntstatus( status
);
998 /*********************************************************************
999 * OpenProcess (kernelbase.@)
1001 HANDLE WINAPI DECLSPEC_HOTPATCH
OpenProcess( DWORD access
, BOOL inherit
, DWORD id
)
1004 OBJECT_ATTRIBUTES attr
;
1007 if (GetVersion() & 0x80000000) access
= PROCESS_ALL_ACCESS
;
1009 attr
.Length
= sizeof(OBJECT_ATTRIBUTES
);
1010 attr
.RootDirectory
= 0;
1011 attr
.Attributes
= inherit
? OBJ_INHERIT
: 0;
1012 attr
.ObjectName
= NULL
;
1013 attr
.SecurityDescriptor
= NULL
;
1014 attr
.SecurityQualityOfService
= NULL
;
1016 cid
.UniqueProcess
= ULongToHandle(id
);
1017 cid
.UniqueThread
= 0;
1019 if (!set_ntstatus( NtOpenProcess( &handle
, access
, &attr
, &cid
))) return NULL
;
1024 /***********************************************************************
1025 * ProcessIdToSessionId (kernelbase.@)
1027 BOOL WINAPI DECLSPEC_HOTPATCH
ProcessIdToSessionId( DWORD pid
, DWORD
*id
)
1032 if (pid
== GetCurrentProcessId())
1034 *id
= NtCurrentTeb()->Peb
->SessionId
;
1037 if (!(process
= OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION
, FALSE
, pid
))) return FALSE
;
1038 status
= NtQueryInformationProcess( process
, ProcessSessionInformation
, id
, sizeof(*id
), NULL
);
1039 CloseHandle( process
);
1040 return set_ntstatus( status
);
1044 /***********************************************************************
1045 * QueryProcessCycleTime (kernelbase.@)
1047 BOOL WINAPI DECLSPEC_HOTPATCH
QueryProcessCycleTime( HANDLE process
, ULONG64
*cycle
)
1050 if (!once
++) FIXME( "(%p,%p): stub!\n", process
, cycle
);
1051 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1056 /***********************************************************************
1057 * SetErrorMode (kernelbase.@)
1059 UINT WINAPI DECLSPEC_HOTPATCH
SetErrorMode( UINT mode
)
1061 UINT old
= GetErrorMode();
1063 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
1064 &mode
, sizeof(mode
) );
1069 /*************************************************************************
1070 * SetHandleCount (kernelbase.@)
1072 UINT WINAPI DECLSPEC_HOTPATCH
SetHandleCount( UINT count
)
1078 /*********************************************************************
1079 * SetHandleInformation (kernelbase.@)
1081 BOOL WINAPI DECLSPEC_HOTPATCH
SetHandleInformation( HANDLE handle
, DWORD mask
, DWORD flags
)
1083 OBJECT_DATA_INFORMATION info
;
1085 /* if not setting both fields, retrieve current value first */
1086 if ((mask
& (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
)) !=
1087 (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
))
1089 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
1092 if (mask
& HANDLE_FLAG_INHERIT
)
1093 info
.InheritHandle
= (flags
& HANDLE_FLAG_INHERIT
) != 0;
1094 if (mask
& HANDLE_FLAG_PROTECT_FROM_CLOSE
)
1095 info
.ProtectFromClose
= (flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
) != 0;
1097 return set_ntstatus( NtSetInformationObject( handle
, ObjectDataInformation
, &info
, sizeof(info
) ));
1101 /***********************************************************************
1102 * SetPriorityClass (kernelbase.@)
1104 BOOL WINAPI DECLSPEC_HOTPATCH
SetPriorityClass( HANDLE process
, DWORD
class )
1106 PROCESS_PRIORITY_CLASS ppc
;
1108 ppc
.Foreground
= FALSE
;
1111 case IDLE_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_IDLE
; break;
1112 case BELOW_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_BELOW_NORMAL
; break;
1113 case NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_NORMAL
; break;
1114 case ABOVE_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_ABOVE_NORMAL
; break;
1115 case HIGH_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_HIGH
; break;
1116 case REALTIME_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_REALTIME
; break;
1118 SetLastError( ERROR_INVALID_PARAMETER
);
1121 return set_ntstatus( NtSetInformationProcess( process
, ProcessPriorityClass
, &ppc
, sizeof(ppc
) ));
1125 /***********************************************************************
1126 * SetProcessAffinityUpdateMode (kernelbase.@)
1128 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessAffinityUpdateMode( HANDLE process
, DWORD flags
)
1130 FIXME( "(%p,0x%08x): stub\n", process
, flags
);
1131 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1136 /**********************************************************************
1137 * SetProcessMitigationPolicy (kernelbase.@)
1139 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy
,
1140 void *buffer
, SIZE_T length
)
1142 FIXME( "(%d, %p, %lu): stub\n", policy
, buffer
, length
);
1147 /***********************************************************************
1148 * SetProcessPriorityBoost (kernelbase.@)
1150 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process
, BOOL disable
)
1152 FIXME( "(%p,%d): stub\n", process
, disable
);
1157 /***********************************************************************
1158 * SetProcessShutdownParameters (kernelbase.@)
1160 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessShutdownParameters( DWORD level
, DWORD flags
)
1162 FIXME( "(%08x, %08x): partial stub.\n", level
, flags
);
1163 shutdown_flags
= flags
;
1164 shutdown_priority
= level
;
1169 /***********************************************************************
1170 * SetProcessWorkingSetSizeEx (kernelbase.@)
1172 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T minset
,
1173 SIZE_T maxset
, DWORD flags
)
1179 /******************************************************************************
1180 * TerminateProcess (kernelbase.@)
1182 BOOL WINAPI DECLSPEC_HOTPATCH
TerminateProcess( HANDLE handle
, DWORD exit_code
)
1186 SetLastError( ERROR_INVALID_HANDLE
);
1189 return set_ntstatus( NtTerminateProcess( handle
, exit_code
));
1193 /***********************************************************************
1194 * Process startup information
1195 ***********************************************************************/
1198 static STARTUPINFOW startup_infoW
;
1199 static char *command_lineA
;
1200 static WCHAR
*command_lineW
;
1202 /******************************************************************
1205 void init_startup_info( RTL_USER_PROCESS_PARAMETERS
*params
)
1209 startup_infoW
.cb
= sizeof(startup_infoW
);
1210 startup_infoW
.lpReserved
= NULL
;
1211 startup_infoW
.lpDesktop
= params
->Desktop
.Buffer
;
1212 startup_infoW
.lpTitle
= params
->WindowTitle
.Buffer
;
1213 startup_infoW
.dwX
= params
->dwX
;
1214 startup_infoW
.dwY
= params
->dwY
;
1215 startup_infoW
.dwXSize
= params
->dwXSize
;
1216 startup_infoW
.dwYSize
= params
->dwYSize
;
1217 startup_infoW
.dwXCountChars
= params
->dwXCountChars
;
1218 startup_infoW
.dwYCountChars
= params
->dwYCountChars
;
1219 startup_infoW
.dwFillAttribute
= params
->dwFillAttribute
;
1220 startup_infoW
.dwFlags
= params
->dwFlags
;
1221 startup_infoW
.wShowWindow
= params
->wShowWindow
;
1222 startup_infoW
.cbReserved2
= params
->RuntimeInfo
.MaximumLength
;
1223 startup_infoW
.lpReserved2
= params
->RuntimeInfo
.MaximumLength
? (void *)params
->RuntimeInfo
.Buffer
: NULL
;
1224 startup_infoW
.hStdInput
= params
->hStdInput
? params
->hStdInput
: INVALID_HANDLE_VALUE
;
1225 startup_infoW
.hStdOutput
= params
->hStdOutput
? params
->hStdOutput
: INVALID_HANDLE_VALUE
;
1226 startup_infoW
.hStdError
= params
->hStdError
? params
->hStdError
: INVALID_HANDLE_VALUE
;
1228 command_lineW
= params
->CommandLine
.Buffer
;
1229 if (!RtlUnicodeStringToAnsiString( &ansi
, ¶ms
->CommandLine
, TRUE
)) command_lineA
= ansi
.Buffer
;
1233 /**********************************************************************
1234 * BaseFlushAppcompatCache (kernelbase.@)
1236 BOOL WINAPI
BaseFlushAppcompatCache(void)
1239 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1244 /***********************************************************************
1245 * GetCommandLineA (kernelbase.@)
1247 LPSTR WINAPI
GetCommandLineA(void)
1249 return command_lineA
;
1253 /***********************************************************************
1254 * GetCommandLineW (kernelbase.@)
1256 LPWSTR WINAPI
GetCommandLineW(void)
1258 return command_lineW
;
1262 /***********************************************************************
1263 * GetStartupInfoW (kernelbase.@)
1265 void WINAPI DECLSPEC_HOTPATCH
GetStartupInfoW( STARTUPINFOW
*info
)
1267 *info
= startup_infoW
;
1271 /***********************************************************************
1272 * GetStdHandle (kernelbase.@)
1274 HANDLE WINAPI DECLSPEC_HOTPATCH
GetStdHandle( DWORD std_handle
)
1278 case STD_INPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
1279 case STD_OUTPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
1280 case STD_ERROR_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
1282 SetLastError( ERROR_INVALID_HANDLE
);
1283 return INVALID_HANDLE_VALUE
;
1287 /***********************************************************************
1288 * SetStdHandle (kernelbase.@)
1290 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandle( DWORD std_handle
, HANDLE handle
)
1294 case STD_INPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
= handle
; return TRUE
;
1295 case STD_OUTPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
= handle
; return TRUE
;
1296 case STD_ERROR_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
= handle
; return TRUE
;
1298 SetLastError( ERROR_INVALID_HANDLE
);
1303 /***********************************************************************
1304 * SetStdHandleEx (kernelbase.@)
1306 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandleEx( DWORD std_handle
, HANDLE handle
, HANDLE
*prev
)
1312 case STD_INPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
; break;
1313 case STD_OUTPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
; break;
1314 case STD_ERROR_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
; break;
1316 SetLastError( ERROR_INVALID_HANDLE
);
1319 if (prev
) *prev
= *ptr
;
1325 /***********************************************************************
1326 * Process environment
1327 ***********************************************************************/
1330 static inline SIZE_T
get_env_length( const WCHAR
*env
)
1332 const WCHAR
*end
= env
;
1333 while (*end
) end
+= lstrlenW(end
) + 1;
1334 return end
+ 1 - env
;
1337 /***********************************************************************
1338 * ExpandEnvironmentStringsA (kernelbase.@)
1340 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsA( LPCSTR src
, LPSTR dst
, DWORD count
)
1342 UNICODE_STRING us_src
;
1346 RtlCreateUnicodeStringFromAsciiz( &us_src
, src
);
1349 if (!(dstW
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
)))) return 0;
1350 ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, dstW
, count
);
1351 if (ret
) WideCharToMultiByte( CP_ACP
, 0, dstW
, ret
, dst
, count
, NULL
, NULL
);
1353 else ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, NULL
, 0 );
1355 RtlFreeUnicodeString( &us_src
);
1356 HeapFree( GetProcessHeap(), 0, dstW
);
1361 /***********************************************************************
1362 * ExpandEnvironmentStringsW (kernelbase.@)
1364 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsW( LPCWSTR src
, LPWSTR dst
, DWORD len
)
1366 UNICODE_STRING us_src
, us_dst
;
1370 TRACE( "(%s %p %u)\n", debugstr_w(src
), dst
, len
);
1372 RtlInitUnicodeString( &us_src
, src
);
1374 /* make sure we don't overflow the maximum UNICODE_STRING size */
1375 len
= min( len
, UNICODE_STRING_MAX_CHARS
);
1378 us_dst
.MaximumLength
= len
* sizeof(WCHAR
);
1379 us_dst
.Buffer
= dst
;
1382 status
= RtlExpandEnvironmentStrings_U( NULL
, &us_src
, &us_dst
, &res
);
1383 res
/= sizeof(WCHAR
);
1384 if (!set_ntstatus( status
))
1386 if (status
!= STATUS_BUFFER_TOO_SMALL
) return 0;
1387 if (len
&& dst
) dst
[len
- 1] = 0;
1393 /***********************************************************************
1394 * GetEnvironmentStrings (kernelbase.@)
1395 * GetEnvironmentStringsA (kernelbase.@)
1397 LPSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsA(void)
1403 RtlAcquirePebLock();
1404 env
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
1405 lenW
= get_env_length( env
);
1406 lenA
= WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, NULL
, 0, NULL
, NULL
);
1407 if ((ret
= HeapAlloc( GetProcessHeap(), 0, lenA
)))
1408 WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, ret
, lenA
, NULL
, NULL
);
1409 RtlReleasePebLock();
1414 /***********************************************************************
1415 * GetEnvironmentStringsW (kernelbase.@)
1417 LPWSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsW(void)
1422 RtlAcquirePebLock();
1423 len
= get_env_length( NtCurrentTeb()->Peb
->ProcessParameters
->Environment
) * sizeof(WCHAR
);
1424 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
1425 memcpy( ret
, NtCurrentTeb()->Peb
->ProcessParameters
->Environment
, len
);
1426 RtlReleasePebLock();
1431 /***********************************************************************
1432 * SetEnvironmentStringsA (kernelbase.@)
1434 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsA( char *env
)
1437 const char *p
= env
;
1441 for (p
= env
; *p
; p
+= strlen( p
) + 1);
1443 len
= MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, NULL
, 0 );
1444 if (!(envW
= HeapAlloc( GetProcessHeap(), 0, len
)))
1446 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1449 MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, envW
, len
);
1450 ret
= SetEnvironmentStringsW( envW
);
1451 HeapFree( GetProcessHeap(), 0, envW
);
1456 /***********************************************************************
1457 * SetEnvironmentStringsW (kernelbase.@)
1459 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsW( WCHAR
*env
)
1465 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1467 const WCHAR
*eq
= wcschr( p
, '=' );
1470 SetLastError( ERROR_INVALID_PARAMETER
);
1475 if ((status
= RtlCreateEnvironment( FALSE
, &new_env
)))
1476 return set_ntstatus( status
);
1478 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1480 const WCHAR
*eq
= wcschr( p
, '=' );
1481 UNICODE_STRING var
, value
;
1483 var
.Length
= (eq
- p
) * sizeof(WCHAR
);
1484 RtlInitUnicodeString( &value
, eq
+ 1 );
1485 if ((status
= RtlSetEnvironmentVariable( &new_env
, &var
, &value
)))
1487 RtlDestroyEnvironment( new_env
);
1488 return set_ntstatus( status
);
1492 RtlSetCurrentEnvironment( new_env
, NULL
);
1497 /***********************************************************************
1498 * GetEnvironmentVariableA (kernelbase.@)
1500 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableA( LPCSTR name
, LPSTR value
, DWORD size
)
1502 UNICODE_STRING us_name
, us_value
;
1507 /* limit the size to sane values */
1508 size
= min( size
, 32767 );
1509 if (!(valueW
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1511 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1512 us_value
.Length
= 0;
1513 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1514 us_value
.Buffer
= valueW
;
1516 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1517 len
= us_value
.Length
/ sizeof(WCHAR
);
1518 if (status
== STATUS_BUFFER_TOO_SMALL
) ret
= len
+ 1;
1519 else if (!set_ntstatus( status
)) ret
= 0;
1520 else if (!size
) ret
= len
+ 1;
1523 if (len
) WideCharToMultiByte( CP_ACP
, 0, valueW
, len
+ 1, value
, size
, NULL
, NULL
);
1528 RtlFreeUnicodeString( &us_name
);
1529 HeapFree( GetProcessHeap(), 0, valueW
);
1534 /***********************************************************************
1535 * GetEnvironmentVariableW (kernelbase.@)
1537 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableW( LPCWSTR name
, LPWSTR val
, DWORD size
)
1539 UNICODE_STRING us_name
, us_value
;
1543 TRACE( "(%s %p %u)\n", debugstr_w(name
), val
, size
);
1545 RtlInitUnicodeString( &us_name
, name
);
1546 us_value
.Length
= 0;
1547 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1548 us_value
.Buffer
= val
;
1550 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1551 len
= us_value
.Length
/ sizeof(WCHAR
);
1552 if (status
== STATUS_BUFFER_TOO_SMALL
) return len
+ 1;
1553 if (!set_ntstatus( status
)) return 0;
1554 if (!size
) return len
+ 1;
1560 /***********************************************************************
1561 * FreeEnvironmentStringsA (kernelbase.@)
1562 * FreeEnvironmentStringsW (kernelbase.@)
1564 BOOL WINAPI DECLSPEC_HOTPATCH
FreeEnvironmentStringsW( LPWSTR ptr
)
1566 return HeapFree( GetProcessHeap(), 0, ptr
);
1570 /***********************************************************************
1571 * SetEnvironmentVariableA (kernelbase.@)
1573 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableA( LPCSTR name
, LPCSTR value
)
1575 UNICODE_STRING us_name
, us_value
;
1580 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1584 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1587 RtlCreateUnicodeStringFromAsciiz( &us_value
, value
);
1588 ret
= SetEnvironmentVariableW( us_name
.Buffer
, us_value
.Buffer
);
1589 RtlFreeUnicodeString( &us_value
);
1591 else ret
= SetEnvironmentVariableW( us_name
.Buffer
, NULL
);
1592 RtlFreeUnicodeString( &us_name
);
1597 /***********************************************************************
1598 * SetEnvironmentVariableW (kernelbase.@)
1600 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableW( LPCWSTR name
, LPCWSTR value
)
1602 UNICODE_STRING us_name
, us_value
;
1605 TRACE( "(%s %s)\n", debugstr_w(name
), debugstr_w(value
) );
1609 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1613 RtlInitUnicodeString( &us_name
, name
);
1616 RtlInitUnicodeString( &us_value
, value
);
1617 status
= RtlSetEnvironmentVariable( NULL
, &us_name
, &us_value
);
1619 else status
= RtlSetEnvironmentVariable( NULL
, &us_name
, NULL
);
1621 return set_ntstatus( status
);
1625 /***********************************************************************
1626 * Process/thread attribute lists
1627 ***********************************************************************/
1629 /***********************************************************************
1630 * InitializeProcThreadAttributeList (kernelbase.@)
1632 BOOL WINAPI DECLSPEC_HOTPATCH
InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1633 DWORD count
, DWORD flags
, SIZE_T
*size
)
1638 TRACE( "(%p %d %x %p)\n", list
, count
, flags
, size
);
1640 needed
= FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST
, attrs
[count
] );
1641 if (list
&& *size
>= needed
)
1649 else SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1656 /***********************************************************************
1657 * UpdateProcThreadAttribute (kernelbase.@)
1659 BOOL WINAPI DECLSPEC_HOTPATCH
UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1660 DWORD flags
, DWORD_PTR attr
, void *value
,
1661 SIZE_T size
, void *prev_ret
, SIZE_T
*size_ret
)
1664 struct proc_thread_attr
*entry
;
1666 TRACE( "(%p %x %08lx %p %ld %p %p)\n", list
, flags
, attr
, value
, size
, prev_ret
, size_ret
);
1668 if (list
->count
>= list
->size
)
1670 SetLastError( ERROR_GEN_FAILURE
);
1676 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
1677 if (size
!= sizeof(HANDLE
))
1679 SetLastError( ERROR_BAD_LENGTH
);
1684 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
1685 if ((size
/ sizeof(HANDLE
)) * sizeof(HANDLE
) != size
)
1687 SetLastError( ERROR_BAD_LENGTH
);
1692 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR
:
1693 if (size
!= sizeof(PROCESSOR_NUMBER
))
1695 SetLastError( ERROR_BAD_LENGTH
);
1700 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY
:
1701 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
))
1703 SetLastError( ERROR_BAD_LENGTH
);
1708 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
:
1709 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
) && size
!= sizeof(DWORD64
) * 2)
1711 SetLastError( ERROR_BAD_LENGTH
);
1716 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
1717 if (size
!= sizeof(HPCON
))
1719 SetLastError( ERROR_BAD_LENGTH
);
1724 case PROC_THREAD_ATTRIBUTE_JOB_LIST
:
1725 if ((size
/ sizeof(HANDLE
)) * sizeof(HANDLE
) != size
)
1727 SetLastError( ERROR_BAD_LENGTH
);
1733 SetLastError( ERROR_NOT_SUPPORTED
);
1734 FIXME( "Unhandled attribute %lu\n", attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1738 mask
= 1 << (attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1739 if (list
->mask
& mask
)
1741 SetLastError( ERROR_OBJECT_NAME_EXISTS
);
1746 entry
= list
->attrs
+ list
->count
;
1749 entry
->value
= value
;
1755 /***********************************************************************
1756 * DeleteProcThreadAttributeList (kernelbase.@)
1758 void WINAPI DECLSPEC_HOTPATCH
DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
)