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"
36 #include "wine/condrv.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(process
);
40 static DWORD shutdown_flags
= 0;
41 static DWORD shutdown_priority
= 0x280;
43 /***********************************************************************
45 ***********************************************************************/
48 /***********************************************************************
51 static BOOL
find_exe_file( const WCHAR
*name
, WCHAR
*buffer
, DWORD buflen
)
56 if (!set_ntstatus( RtlGetExePath( name
, &load_path
))) return FALSE
;
58 TRACE( "looking for %s in %s\n", debugstr_w(name
), debugstr_w(load_path
) );
60 ret
= (SearchPathW( load_path
, name
, L
".exe", buflen
, buffer
, NULL
) ||
61 /* not found, try without extension in case it is a Unix app */
62 SearchPathW( load_path
, name
, NULL
, buflen
, buffer
, NULL
));
64 if (ret
) /* make sure it can be opened, SearchPathW also returns directories */
66 HANDLE handle
= CreateFileW( buffer
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_DELETE
,
67 NULL
, OPEN_EXISTING
, 0, 0 );
68 if ((ret
= (handle
!= INVALID_HANDLE_VALUE
))) CloseHandle( handle
);
70 RtlReleasePath( load_path
);
75 /*************************************************************************
78 * Helper for CreateProcess: retrieve the file name to load from the
79 * app name and command line. Store the file name in buffer, and
80 * return a possibly modified command line.
82 static WCHAR
*get_file_name( WCHAR
*cmdline
, WCHAR
*buffer
, DWORD buflen
)
84 WCHAR
*name
, *pos
, *first_space
, *ret
= NULL
;
87 /* first check for a quoted file name */
89 if (cmdline
[0] == '"' && (p
= wcschr( cmdline
+ 1, '"' )))
91 int len
= p
- cmdline
- 1;
92 /* extract the quoted portion as file name */
93 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
94 memcpy( name
, cmdline
+ 1, len
* sizeof(WCHAR
) );
97 if (!find_exe_file( name
, buffer
, buflen
)) goto done
;
98 ret
= cmdline
; /* no change necessary */
102 /* now try the command-line word by word */
104 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline
) + 1) * sizeof(WCHAR
) )))
112 while (*p
&& *p
!= ' ' && *p
!= '\t') *pos
++ = *p
++;
114 if (find_exe_file( name
, buffer
, buflen
))
119 if (!first_space
) first_space
= pos
;
120 if (!(*pos
++ = *p
++)) break;
125 SetLastError( ERROR_FILE_NOT_FOUND
);
127 else if (first_space
) /* build a new command-line with quotes */
129 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline
) + 3) * sizeof(WCHAR
) )))
131 swprintf( ret
, lstrlenW(cmdline
) + 3, L
"\"%s\"%s", name
, p
);
135 RtlFreeHeap( GetProcessHeap(), 0, name
);
140 /***********************************************************************
141 * create_process_params
143 static RTL_USER_PROCESS_PARAMETERS
*create_process_params( const WCHAR
*filename
, const WCHAR
*cmdline
,
144 const WCHAR
*cur_dir
, void *env
, DWORD flags
,
145 const STARTUPINFOW
*startup
)
147 RTL_USER_PROCESS_PARAMETERS
*params
;
148 UNICODE_STRING imageW
, curdirW
, cmdlineW
, titleW
, desktopW
, runtimeW
, newdirW
;
149 WCHAR imagepath
[MAX_PATH
];
152 if (!GetLongPathNameW( filename
, imagepath
, MAX_PATH
)) lstrcpynW( imagepath
, filename
, MAX_PATH
);
153 if (!GetFullPathNameW( imagepath
, MAX_PATH
, imagepath
, NULL
)) lstrcpynW( imagepath
, filename
, MAX_PATH
);
155 if (env
&& !(flags
& CREATE_UNICODE_ENVIRONMENT
)) /* convert environment to unicode */
160 while (*e
) e
+= strlen(e
) + 1;
161 e
++; /* final null */
162 lenW
= MultiByteToWideChar( CP_ACP
, 0, env
, e
- (char *)env
, NULL
, 0 );
163 if ((envW
= RtlAllocateHeap( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
164 MultiByteToWideChar( CP_ACP
, 0, env
, e
- (char *)env
, envW
, lenW
);
167 newdirW
.Buffer
= NULL
;
170 if (RtlDosPathNameToNtPathName_U( cur_dir
, &newdirW
, NULL
, NULL
))
171 cur_dir
= newdirW
.Buffer
+ 4; /* skip \??\ prefix */
175 RtlInitUnicodeString( &imageW
, imagepath
);
176 RtlInitUnicodeString( &curdirW
, cur_dir
);
177 RtlInitUnicodeString( &cmdlineW
, cmdline
);
178 RtlInitUnicodeString( &titleW
, startup
->lpTitle
? startup
->lpTitle
: imagepath
);
179 RtlInitUnicodeString( &desktopW
, startup
->lpDesktop
);
180 runtimeW
.Buffer
= (WCHAR
*)startup
->lpReserved2
;
181 runtimeW
.Length
= runtimeW
.MaximumLength
= startup
->cbReserved2
;
182 if (RtlCreateProcessParametersEx( ¶ms
, &imageW
, NULL
, cur_dir
? &curdirW
: NULL
,
183 &cmdlineW
, envW
, &titleW
, &desktopW
,
184 NULL
, &runtimeW
, PROCESS_PARAMS_FLAG_NORMALIZED
))
186 RtlFreeUnicodeString( &newdirW
);
187 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
190 RtlFreeUnicodeString( &newdirW
);
192 if (flags
& CREATE_NEW_PROCESS_GROUP
) params
->ConsoleFlags
= 1;
193 if (flags
& CREATE_NEW_CONSOLE
) params
->ConsoleHandle
= CONSOLE_HANDLE_ALLOC
;
194 else if (!(flags
& DETACHED_PROCESS
))
196 if (flags
& CREATE_NO_WINDOW
) params
->ConsoleHandle
= CONSOLE_HANDLE_ALLOC_NO_WINDOW
;
199 params
->ConsoleHandle
= NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleHandle
;
200 if (!params
->ConsoleHandle
) params
->ConsoleHandle
= CONSOLE_HANDLE_ALLOC
;
204 if (startup
->dwFlags
& STARTF_USESTDHANDLES
)
206 params
->hStdInput
= startup
->hStdInput
;
207 params
->hStdOutput
= startup
->hStdOutput
;
208 params
->hStdError
= startup
->hStdError
;
210 else if (flags
& (DETACHED_PROCESS
| CREATE_NEW_CONSOLE
))
212 params
->hStdInput
= INVALID_HANDLE_VALUE
;
213 params
->hStdOutput
= INVALID_HANDLE_VALUE
;
214 params
->hStdError
= INVALID_HANDLE_VALUE
;
218 params
->hStdInput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
219 params
->hStdOutput
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
220 params
->hStdError
= NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
223 params
->dwX
= startup
->dwX
;
224 params
->dwY
= startup
->dwY
;
225 params
->dwXSize
= startup
->dwXSize
;
226 params
->dwYSize
= startup
->dwYSize
;
227 params
->dwXCountChars
= startup
->dwXCountChars
;
228 params
->dwYCountChars
= startup
->dwYCountChars
;
229 params
->dwFillAttribute
= startup
->dwFillAttribute
;
230 params
->dwFlags
= startup
->dwFlags
;
231 params
->wShowWindow
= startup
->wShowWindow
;
233 if (envW
!= env
) RtlFreeHeap( GetProcessHeap(), 0, envW
);
237 struct proc_thread_attr
244 struct _PROC_THREAD_ATTRIBUTE_LIST
246 DWORD mask
; /* bitmask of items in list */
247 DWORD size
; /* max number of items in list */
248 DWORD count
; /* number of items in list */
251 struct proc_thread_attr attrs
[1];
254 /***********************************************************************
257 static NTSTATUS
create_nt_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
258 SECURITY_ATTRIBUTES
*tsa
, DWORD process_flags
,
259 RTL_USER_PROCESS_PARAMETERS
*params
,
260 RTL_USER_PROCESS_INFORMATION
*info
, HANDLE parent
,
261 const struct proc_thread_attr
*handle_list
,
262 const struct proc_thread_attr
*job_list
)
264 OBJECT_ATTRIBUTES process_attr
, thread_attr
;
265 PS_CREATE_INFO create_info
;
266 ULONG_PTR buffer
[offsetof( PS_ATTRIBUTE_LIST
, Attributes
[8] ) / sizeof(ULONG_PTR
)];
267 PS_ATTRIBUTE_LIST
*attr
= (PS_ATTRIBUTE_LIST
*)buffer
;
268 UNICODE_STRING nameW
;
272 if (!params
->ImagePathName
.Buffer
[0]) return STATUS_OBJECT_PATH_NOT_FOUND
;
273 status
= RtlDosPathNameToNtPathName_U_WithStatus( params
->ImagePathName
.Buffer
, &nameW
, NULL
, NULL
);
276 RtlNormalizeProcessParams( params
);
278 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_NAME
;
279 attr
->Attributes
[pos
].Size
= nameW
.Length
;
280 attr
->Attributes
[pos
].ValuePtr
= nameW
.Buffer
;
281 attr
->Attributes
[pos
].ReturnLength
= NULL
;
283 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_CLIENT_ID
;
284 attr
->Attributes
[pos
].Size
= sizeof(info
->ClientId
);
285 attr
->Attributes
[pos
].ValuePtr
= &info
->ClientId
;
286 attr
->Attributes
[pos
].ReturnLength
= NULL
;
288 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_INFO
;
289 attr
->Attributes
[pos
].Size
= sizeof(info
->ImageInformation
);
290 attr
->Attributes
[pos
].ValuePtr
= &info
->ImageInformation
;
291 attr
->Attributes
[pos
].ReturnLength
= NULL
;
295 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_PARENT_PROCESS
;
296 attr
->Attributes
[pos
].Size
= sizeof(parent
);
297 attr
->Attributes
[pos
].ValuePtr
= parent
;
298 attr
->Attributes
[pos
].ReturnLength
= NULL
;
301 if ((process_flags
& PROCESS_CREATE_FLAGS_INHERIT_HANDLES
) && handle_list
)
303 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_HANDLE_LIST
;
304 attr
->Attributes
[pos
].Size
= handle_list
->size
;
305 attr
->Attributes
[pos
].ValuePtr
= handle_list
->value
;
306 attr
->Attributes
[pos
].ReturnLength
= NULL
;
311 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_TOKEN
;
312 attr
->Attributes
[pos
].Size
= sizeof(token
);
313 attr
->Attributes
[pos
].ValuePtr
= token
;
314 attr
->Attributes
[pos
].ReturnLength
= NULL
;
319 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_DEBUG_PORT
;
320 attr
->Attributes
[pos
].Size
= sizeof(debug
);
321 attr
->Attributes
[pos
].ValuePtr
= debug
;
322 attr
->Attributes
[pos
].ReturnLength
= NULL
;
327 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_JOB_LIST
;
328 attr
->Attributes
[pos
].Size
= job_list
->size
;
329 attr
->Attributes
[pos
].ValuePtr
= job_list
->value
;
330 attr
->Attributes
[pos
].ReturnLength
= NULL
;
333 attr
->TotalLength
= offsetof( PS_ATTRIBUTE_LIST
, Attributes
[pos
] );
335 InitializeObjectAttributes( &process_attr
, NULL
, 0, NULL
, psa
? psa
->lpSecurityDescriptor
: NULL
);
336 InitializeObjectAttributes( &thread_attr
, NULL
, 0, NULL
, tsa
? tsa
->lpSecurityDescriptor
: NULL
);
338 status
= NtCreateUserProcess( &info
->Process
, &info
->Thread
, PROCESS_ALL_ACCESS
, THREAD_ALL_ACCESS
,
339 &process_attr
, &thread_attr
, process_flags
,
340 THREAD_CREATE_FLAGS_CREATE_SUSPENDED
, params
,
341 &create_info
, attr
);
343 RtlFreeUnicodeString( &nameW
);
349 /***********************************************************************
352 static NTSTATUS
create_vdm_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
353 SECURITY_ATTRIBUTES
*tsa
, DWORD flags
,
354 RTL_USER_PROCESS_PARAMETERS
*params
,
355 RTL_USER_PROCESS_INFORMATION
*info
)
357 const WCHAR
*winevdm
= (is_win64
|| is_wow64
?
358 L
"C:\\windows\\syswow64\\winevdm.exe" :
359 L
"C:\\windows\\system32\\winevdm.exe");
364 len
= (lstrlenW(params
->ImagePathName
.Buffer
) + lstrlenW(params
->CommandLine
.Buffer
) +
365 lstrlenW(winevdm
) + 16);
367 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
368 return STATUS_NO_MEMORY
;
370 swprintf( newcmdline
, len
, L
"%s --app-name \"%s\" %s",
371 winevdm
, params
->ImagePathName
.Buffer
, params
->CommandLine
.Buffer
);
372 RtlInitUnicodeString( ¶ms
->ImagePathName
, winevdm
);
373 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
374 status
= create_nt_process( token
, debug
, psa
, tsa
, flags
, params
, info
, NULL
, NULL
, NULL
);
375 HeapFree( GetProcessHeap(), 0, newcmdline
);
380 /***********************************************************************
383 static NTSTATUS
create_cmd_process( HANDLE token
, HANDLE debug
, SECURITY_ATTRIBUTES
*psa
,
384 SECURITY_ATTRIBUTES
*tsa
, DWORD flags
,
385 RTL_USER_PROCESS_PARAMETERS
*params
,
386 RTL_USER_PROCESS_INFORMATION
*info
)
388 WCHAR comspec
[MAX_PATH
];
393 if (!GetEnvironmentVariableW( L
"COMSPEC", comspec
, ARRAY_SIZE( comspec
)))
394 lstrcpyW( comspec
, L
"C:\\windows\\system32\\cmd.exe" );
396 len
= lstrlenW(comspec
) + 7 + lstrlenW(params
->CommandLine
.Buffer
) + 2;
397 if (!(newcmdline
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
398 return STATUS_NO_MEMORY
;
400 swprintf( newcmdline
, len
, L
"%s /s/c \"%s\"", comspec
, params
->CommandLine
.Buffer
);
401 RtlInitUnicodeString( ¶ms
->ImagePathName
, comspec
);
402 RtlInitUnicodeString( ¶ms
->CommandLine
, newcmdline
);
403 status
= create_nt_process( token
, debug
, psa
, tsa
, flags
, params
, info
, NULL
, NULL
, NULL
);
404 RtlFreeHeap( GetProcessHeap(), 0, newcmdline
);
409 /*********************************************************************
410 * CloseHandle (kernelbase.@)
412 BOOL WINAPI DECLSPEC_HOTPATCH
CloseHandle( HANDLE handle
)
414 if (handle
== (HANDLE
)STD_INPUT_HANDLE
)
415 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
, 0 );
416 else if (handle
== (HANDLE
)STD_OUTPUT_HANDLE
)
417 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
, 0 );
418 else if (handle
== (HANDLE
)STD_ERROR_HANDLE
)
419 handle
= InterlockedExchangePointer( &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
, 0 );
421 return set_ntstatus( NtClose( handle
));
425 /**********************************************************************
426 * CreateProcessAsUserA (kernelbase.@)
428 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserA( HANDLE token
, const char *app_name
, char *cmd_line
,
429 SECURITY_ATTRIBUTES
*process_attr
,
430 SECURITY_ATTRIBUTES
*thread_attr
,
431 BOOL inherit
, DWORD flags
, void *env
,
432 const char *cur_dir
, STARTUPINFOA
*startup_info
,
433 PROCESS_INFORMATION
*info
)
435 return CreateProcessInternalA( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
436 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
440 /**********************************************************************
441 * CreateProcessAsUserW (kernelbase.@)
443 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessAsUserW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
444 SECURITY_ATTRIBUTES
*process_attr
,
445 SECURITY_ATTRIBUTES
*thread_attr
,
446 BOOL inherit
, DWORD flags
, void *env
,
447 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
448 PROCESS_INFORMATION
*info
)
450 return CreateProcessInternalW( token
, app_name
, cmd_line
, process_attr
, thread_attr
,
451 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
454 /**********************************************************************
455 * CreateProcessInternalA (kernelbase.@)
457 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalA( HANDLE token
, const char *app_name
, char *cmd_line
,
458 SECURITY_ATTRIBUTES
*process_attr
,
459 SECURITY_ATTRIBUTES
*thread_attr
,
460 BOOL inherit
, DWORD flags
, void *env
,
461 const char *cur_dir
, STARTUPINFOA
*startup_info
,
462 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
465 WCHAR
*app_nameW
= NULL
, *cmd_lineW
= NULL
, *cur_dirW
= NULL
;
466 UNICODE_STRING desktopW
, titleW
;
467 STARTUPINFOEXW infoW
;
469 desktopW
.Buffer
= NULL
;
470 titleW
.Buffer
= NULL
;
471 if (app_name
&& !(app_nameW
= file_name_AtoW( app_name
, TRUE
))) goto done
;
472 if (cmd_line
&& !(cmd_lineW
= file_name_AtoW( cmd_line
, TRUE
))) goto done
;
473 if (cur_dir
&& !(cur_dirW
= file_name_AtoW( cur_dir
, TRUE
))) goto done
;
475 if (startup_info
->lpDesktop
) RtlCreateUnicodeStringFromAsciiz( &desktopW
, startup_info
->lpDesktop
);
476 if (startup_info
->lpTitle
) RtlCreateUnicodeStringFromAsciiz( &titleW
, startup_info
->lpTitle
);
478 memcpy( &infoW
.StartupInfo
, startup_info
, sizeof(infoW
.StartupInfo
) );
479 infoW
.StartupInfo
.lpDesktop
= desktopW
.Buffer
;
480 infoW
.StartupInfo
.lpTitle
= titleW
.Buffer
;
482 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
483 infoW
.lpAttributeList
= ((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
485 ret
= CreateProcessInternalW( token
, app_nameW
, cmd_lineW
, process_attr
, thread_attr
,
486 inherit
, flags
, env
, cur_dirW
, (STARTUPINFOW
*)&infoW
, info
, new_token
);
488 RtlFreeHeap( GetProcessHeap(), 0, app_nameW
);
489 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW
);
490 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW
);
491 RtlFreeUnicodeString( &desktopW
);
492 RtlFreeUnicodeString( &titleW
);
496 /**********************************************************************
497 * CreateProcessInternalW (kernelbase.@)
499 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessInternalW( HANDLE token
, const WCHAR
*app_name
, WCHAR
*cmd_line
,
500 SECURITY_ATTRIBUTES
*process_attr
,
501 SECURITY_ATTRIBUTES
*thread_attr
,
502 BOOL inherit
, DWORD flags
, void *env
,
503 const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
504 PROCESS_INFORMATION
*info
, HANDLE
*new_token
)
506 const struct proc_thread_attr
*handle_list
= NULL
, *job_list
= NULL
;
507 WCHAR name
[MAX_PATH
];
508 WCHAR
*p
, *tidy_cmdline
= cmd_line
;
509 RTL_USER_PROCESS_PARAMETERS
*params
= NULL
;
510 RTL_USER_PROCESS_INFORMATION rtl_info
;
511 HANDLE parent
= 0, debug
= 0;
515 /* Process the AppName and/or CmdLine to get module name and path */
517 TRACE( "app %s cmdline %s\n", debugstr_w(app_name
), debugstr_w(cmd_line
) );
519 if (new_token
) FIXME( "No support for returning created process token\n" );
523 if (!cmd_line
|| !cmd_line
[0]) /* no command-line, create one */
525 if (!(tidy_cmdline
= RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name
)+3) * sizeof(WCHAR
) )))
527 swprintf( tidy_cmdline
, lstrlenW(app_name
) + 3, L
"\"%s\"", app_name
);
532 if (!(tidy_cmdline
= get_file_name( cmd_line
, name
, ARRAY_SIZE(name
) ))) return FALSE
;
536 /* Warn if unsupported features are used */
538 if (flags
& (IDLE_PRIORITY_CLASS
| HIGH_PRIORITY_CLASS
| REALTIME_PRIORITY_CLASS
|
539 CREATE_DEFAULT_ERROR_MODE
| PROFILE_USER
| PROFILE_KERNEL
| PROFILE_SERVER
))
540 WARN( "(%s,...): ignoring some flags in %lx\n", debugstr_w(app_name
), flags
);
544 DWORD attr
= GetFileAttributesW( cur_dir
);
545 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
547 status
= STATUS_NOT_A_DIRECTORY
;
552 info
->hThread
= info
->hProcess
= 0;
553 info
->dwProcessId
= info
->dwThreadId
= 0;
555 if (!(params
= create_process_params( app_name
, tidy_cmdline
, cur_dir
, env
, flags
, startup_info
)))
557 status
= STATUS_NO_MEMORY
;
561 if (flags
& (DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
))
563 if ((status
= DbgUiConnectToDbg())) goto done
;
564 debug
= DbgUiGetThreadDebugObject();
567 if (flags
& EXTENDED_STARTUPINFO_PRESENT
)
569 struct _PROC_THREAD_ATTRIBUTE_LIST
*attrs
=
570 (struct _PROC_THREAD_ATTRIBUTE_LIST
*)((STARTUPINFOEXW
*)startup_info
)->lpAttributeList
;
575 for (i
= 0; i
< attrs
->count
; ++i
)
577 switch(attrs
->attrs
[i
].attr
)
579 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
580 parent
= *(HANDLE
*)attrs
->attrs
[i
].value
;
581 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent
);
584 status
= STATUS_INVALID_HANDLE
;
588 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
589 handle_list
= &attrs
->attrs
[i
];
590 TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs
->attrs
[i
].size
/ sizeof(HANDLE
));
592 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
594 struct pseudo_console
*console
= attrs
->attrs
[i
].value
;
595 TRACE( "PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE %p reference %p\n",
596 console
, console
->reference
);
597 params
->ConsoleHandle
= console
->reference
;
600 case PROC_THREAD_ATTRIBUTE_JOB_LIST
:
601 job_list
= &attrs
->attrs
[i
];
602 TRACE( "PROC_THREAD_ATTRIBUTE_JOB_LIST handle count %Iu.\n",
603 attrs
->attrs
[i
].size
/ sizeof(HANDLE
) );
606 FIXME("Unsupported attribute %#Ix.\n", attrs
->attrs
[i
].attr
);
613 if (inherit
) nt_flags
|= PROCESS_CREATE_FLAGS_INHERIT_HANDLES
;
614 if (flags
& DEBUG_ONLY_THIS_PROCESS
) nt_flags
|= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT
;
615 if (flags
& CREATE_BREAKAWAY_FROM_JOB
) nt_flags
|= PROCESS_CREATE_FLAGS_BREAKAWAY
;
616 if (flags
& CREATE_SUSPENDED
) nt_flags
|= PROCESS_CREATE_FLAGS_SUSPENDED
;
618 status
= create_nt_process( token
, debug
, process_attr
, thread_attr
,
619 nt_flags
, params
, &rtl_info
, parent
, handle_list
, job_list
);
624 case STATUS_INVALID_IMAGE_WIN_16
:
625 case STATUS_INVALID_IMAGE_NE_FORMAT
:
626 case STATUS_INVALID_IMAGE_PROTECT
:
627 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name
) );
628 status
= create_vdm_process( token
, debug
, process_attr
, thread_attr
,
629 nt_flags
, params
, &rtl_info
);
631 case STATUS_INVALID_IMAGE_NOT_MZ
:
632 /* check for .com or .bat extension */
633 if (!(p
= wcsrchr( app_name
, '.' ))) break;
634 if (!wcsicmp( p
, L
".com" ) || !wcsicmp( p
, L
".pif" ))
636 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name
) );
637 status
= create_vdm_process( token
, debug
, process_attr
, thread_attr
,
638 nt_flags
, params
, &rtl_info
);
640 else if (!wcsicmp( p
, L
".bat" ) || !wcsicmp( p
, L
".cmd" ))
642 TRACE( "starting %s as batch binary\n", debugstr_w(app_name
) );
643 status
= create_cmd_process( token
, debug
, process_attr
, thread_attr
,
644 nt_flags
, params
, &rtl_info
);
651 info
->hProcess
= rtl_info
.Process
;
652 info
->hThread
= rtl_info
.Thread
;
653 info
->dwProcessId
= HandleToUlong( rtl_info
.ClientId
.UniqueProcess
);
654 info
->dwThreadId
= HandleToUlong( rtl_info
.ClientId
.UniqueThread
);
655 if (!(flags
& CREATE_SUSPENDED
)) NtResumeThread( rtl_info
.Thread
, NULL
);
656 TRACE( "started process pid %04lx tid %04lx\n", info
->dwProcessId
, info
->dwThreadId
);
660 RtlDestroyProcessParameters( params
);
661 if (tidy_cmdline
!= cmd_line
) HeapFree( GetProcessHeap(), 0, tidy_cmdline
);
662 return set_ntstatus( status
);
666 /**********************************************************************
667 * CreateProcessA (kernelbase.@)
669 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessA( const char *app_name
, char *cmd_line
,
670 SECURITY_ATTRIBUTES
*process_attr
,
671 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
,
672 DWORD flags
, void *env
, const char *cur_dir
,
673 STARTUPINFOA
*startup_info
, PROCESS_INFORMATION
*info
)
675 return CreateProcessInternalA( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
676 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
680 /**********************************************************************
681 * CreateProcessW (kernelbase.@)
683 BOOL WINAPI DECLSPEC_HOTPATCH
CreateProcessW( const WCHAR
*app_name
, WCHAR
*cmd_line
,
684 SECURITY_ATTRIBUTES
*process_attr
,
685 SECURITY_ATTRIBUTES
*thread_attr
, BOOL inherit
, DWORD flags
,
686 void *env
, const WCHAR
*cur_dir
, STARTUPINFOW
*startup_info
,
687 PROCESS_INFORMATION
*info
)
689 return CreateProcessInternalW( NULL
, app_name
, cmd_line
, process_attr
, thread_attr
,
690 inherit
, flags
, env
, cur_dir
, startup_info
, info
, NULL
);
694 /*********************************************************************
695 * DuplicateHandle (kernelbase.@)
697 BOOL WINAPI DECLSPEC_HOTPATCH
DuplicateHandle( HANDLE source_process
, HANDLE source
,
698 HANDLE dest_process
, HANDLE
*dest
,
699 DWORD access
, BOOL inherit
, DWORD options
)
701 return set_ntstatus( NtDuplicateObject( source_process
, source
, dest_process
, dest
,
702 access
, inherit
? OBJ_INHERIT
: 0, options
));
706 /****************************************************************************
707 * FlushInstructionCache (kernelbase.@)
709 BOOL WINAPI DECLSPEC_HOTPATCH
FlushInstructionCache( HANDLE process
, LPCVOID addr
, SIZE_T size
)
711 return set_ntstatus( NtFlushInstructionCache( process
, addr
, size
));
715 /***********************************************************************
716 * GetApplicationRestartSettings (kernelbase.@)
718 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ GetApplicationRestartSettings( HANDLE process
, WCHAR
*cmdline
,
719 DWORD
*size
, DWORD
*flags
)
721 FIXME( "%p, %p, %p, %p)\n", process
, cmdline
, size
, flags
);
726 /***********************************************************************
727 * GetCurrentProcess (kernelbase.@)
729 HANDLE WINAPI
kernelbase_GetCurrentProcess(void)
731 return (HANDLE
)~(ULONG_PTR
)0;
735 /***********************************************************************
736 * GetCurrentProcessId (kernelbase.@)
738 DWORD WINAPI
kernelbase_GetCurrentProcessId(void)
740 return HandleToULong( NtCurrentTeb()->ClientId
.UniqueProcess
);
744 /***********************************************************************
745 * GetErrorMode (kernelbase.@)
747 UINT WINAPI DECLSPEC_HOTPATCH
GetErrorMode(void)
751 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
752 &mode
, sizeof(mode
), NULL
);
757 /***********************************************************************
758 * GetExitCodeProcess (kernelbase.@)
760 BOOL WINAPI DECLSPEC_HOTPATCH
GetExitCodeProcess( HANDLE process
, LPDWORD exit_code
)
763 PROCESS_BASIC_INFORMATION pbi
;
765 status
= NtQueryInformationProcess( process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
766 if (!status
&& exit_code
) *exit_code
= pbi
.ExitStatus
;
767 return set_ntstatus( status
);
771 /*********************************************************************
772 * GetHandleInformation (kernelbase.@)
774 BOOL WINAPI DECLSPEC_HOTPATCH
GetHandleInformation( HANDLE handle
, DWORD
*flags
)
776 OBJECT_DATA_INFORMATION info
;
778 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
784 if (info
.InheritHandle
) *flags
|= HANDLE_FLAG_INHERIT
;
785 if (info
.ProtectFromClose
) *flags
|= HANDLE_FLAG_PROTECT_FROM_CLOSE
;
791 /***********************************************************************
792 * GetPriorityClass (kernelbase.@)
794 DWORD WINAPI DECLSPEC_HOTPATCH
GetPriorityClass( HANDLE process
)
796 PROCESS_BASIC_INFORMATION pbi
;
798 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
799 &pbi
, sizeof(pbi
), NULL
)))
802 switch (pbi
.BasePriority
)
804 case PROCESS_PRIOCLASS_IDLE
: return IDLE_PRIORITY_CLASS
;
805 case PROCESS_PRIOCLASS_BELOW_NORMAL
: return BELOW_NORMAL_PRIORITY_CLASS
;
806 case PROCESS_PRIOCLASS_NORMAL
: return NORMAL_PRIORITY_CLASS
;
807 case PROCESS_PRIOCLASS_ABOVE_NORMAL
: return ABOVE_NORMAL_PRIORITY_CLASS
;
808 case PROCESS_PRIOCLASS_HIGH
: return HIGH_PRIORITY_CLASS
;
809 case PROCESS_PRIOCLASS_REALTIME
: return REALTIME_PRIORITY_CLASS
;
815 /***********************************************************************
816 * GetProcessGroupAffinity (kernelbase.@)
818 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessGroupAffinity( HANDLE process
, USHORT
*count
, USHORT
*array
)
820 FIXME( "(%p,%p,%p): stub\n", process
, count
, array
);
821 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
826 /******************************************************************
827 * GetProcessHandleCount (kernelbase.@)
829 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessHandleCount( HANDLE process
, DWORD
*count
)
831 return set_ntstatus( NtQueryInformationProcess( process
, ProcessHandleCount
,
832 count
, sizeof(*count
), NULL
));
836 /***********************************************************************
837 * GetProcessHeap (kernelbase.@)
839 HANDLE WINAPI
kernelbase_GetProcessHeap(void)
841 return NtCurrentTeb()->Peb
->ProcessHeap
;
845 /*********************************************************************
846 * GetProcessId (kernelbase.@)
848 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessId( HANDLE process
)
850 PROCESS_BASIC_INFORMATION pbi
;
852 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
853 &pbi
, sizeof(pbi
), NULL
)))
855 return pbi
.UniqueProcessId
;
859 /**********************************************************************
860 * GetProcessMitigationPolicy (kernelbase.@)
862 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process
, PROCESS_MITIGATION_POLICY policy
,
863 void *buffer
, SIZE_T length
)
865 FIXME( "(%p, %u, %p, %Iu): stub\n", process
, policy
, buffer
, length
);
870 /***********************************************************************
871 * GetProcessPriorityBoost (kernelbase.@)
873 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessPriorityBoost( HANDLE process
, PBOOL disable
)
875 FIXME( "(%p,%p): semi-stub\n", process
, disable
);
876 *disable
= FALSE
; /* report that no boost is present */
881 /***********************************************************************
882 * GetProcessShutdownParameters (kernelbase.@)
884 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessShutdownParameters( LPDWORD level
, LPDWORD flags
)
886 *level
= shutdown_priority
;
887 *flags
= shutdown_flags
;
892 /*********************************************************************
893 * GetProcessTimes (kernelbase.@)
895 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessTimes( HANDLE process
, FILETIME
*create
, FILETIME
*exit
,
896 FILETIME
*kernel
, FILETIME
*user
)
898 KERNEL_USER_TIMES time
;
900 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessTimes
, &time
, sizeof(time
), NULL
)))
903 create
->dwLowDateTime
= time
.CreateTime
.u
.LowPart
;
904 create
->dwHighDateTime
= time
.CreateTime
.u
.HighPart
;
905 exit
->dwLowDateTime
= time
.ExitTime
.u
.LowPart
;
906 exit
->dwHighDateTime
= time
.ExitTime
.u
.HighPart
;
907 kernel
->dwLowDateTime
= time
.KernelTime
.u
.LowPart
;
908 kernel
->dwHighDateTime
= time
.KernelTime
.u
.HighPart
;
909 user
->dwLowDateTime
= time
.UserTime
.u
.LowPart
;
910 user
->dwHighDateTime
= time
.UserTime
.u
.HighPart
;
915 /***********************************************************************
916 * GetProcessVersion (kernelbase.@)
918 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessVersion( DWORD pid
)
920 SECTION_IMAGE_INFORMATION info
;
924 if (pid
&& pid
!= GetCurrentProcessId())
926 if (!(process
= OpenProcess( PROCESS_QUERY_INFORMATION
, FALSE
, pid
))) return 0;
927 status
= NtQueryInformationProcess( process
, ProcessImageInformation
, &info
, sizeof(info
), NULL
);
928 CloseHandle( process
);
930 else status
= NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation
,
931 &info
, sizeof(info
), NULL
);
933 if (!set_ntstatus( status
)) return 0;
934 return MAKELONG( info
.MinorSubsystemVersion
, info
.MajorSubsystemVersion
);
938 /***********************************************************************
939 * GetProcessWorkingSetSizeEx (kernelbase.@)
941 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T
*minset
,
942 SIZE_T
*maxset
, DWORD
*flags
)
944 FIXME( "(%p,%p,%p,%p): stub\n", process
, minset
, maxset
, flags
);
945 /* 32 MB working set size */
946 if (minset
) *minset
= 32*1024*1024;
947 if (maxset
) *maxset
= 32*1024*1024;
948 if (flags
) *flags
= QUOTA_LIMITS_HARDWS_MIN_DISABLE
| QUOTA_LIMITS_HARDWS_MAX_DISABLE
;
953 /******************************************************************************
954 * IsProcessInJob (kernelbase.@)
956 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessInJob( HANDLE process
, HANDLE job
, BOOL
*result
)
958 NTSTATUS status
= NtIsProcessInJob( process
, job
);
962 case STATUS_PROCESS_IN_JOB
:
965 case STATUS_PROCESS_NOT_IN_JOB
:
969 return set_ntstatus( status
);
974 /***********************************************************************
975 * IsProcessorFeaturePresent (kernelbase.@)
977 BOOL WINAPI DECLSPEC_HOTPATCH
IsProcessorFeaturePresent ( DWORD feature
)
979 return RtlIsProcessorFeaturePresent( feature
);
983 /**********************************************************************
984 * IsWow64Process2 (kernelbase.@)
986 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process2( HANDLE process
, USHORT
*machine
, USHORT
*native_machine
)
988 return set_ntstatus( RtlWow64GetProcessMachines( process
, machine
, native_machine
));
992 /**********************************************************************
993 * IsWow64Process (kernelbase.@)
995 BOOL WINAPI DECLSPEC_HOTPATCH
IsWow64Process( HANDLE process
, PBOOL wow64
)
1000 status
= NtQueryInformationProcess( process
, ProcessWow64Information
, &pbi
, sizeof(pbi
), NULL
);
1001 if (!status
) *wow64
= !!pbi
;
1002 return set_ntstatus( status
);
1006 /*********************************************************************
1007 * OpenProcess (kernelbase.@)
1009 HANDLE WINAPI DECLSPEC_HOTPATCH
OpenProcess( DWORD access
, BOOL inherit
, DWORD id
)
1012 OBJECT_ATTRIBUTES attr
;
1015 if (GetVersion() & 0x80000000) access
= PROCESS_ALL_ACCESS
;
1017 attr
.Length
= sizeof(OBJECT_ATTRIBUTES
);
1018 attr
.RootDirectory
= 0;
1019 attr
.Attributes
= inherit
? OBJ_INHERIT
: 0;
1020 attr
.ObjectName
= NULL
;
1021 attr
.SecurityDescriptor
= NULL
;
1022 attr
.SecurityQualityOfService
= NULL
;
1024 cid
.UniqueProcess
= ULongToHandle(id
);
1025 cid
.UniqueThread
= 0;
1027 if (!set_ntstatus( NtOpenProcess( &handle
, access
, &attr
, &cid
))) return NULL
;
1032 /***********************************************************************
1033 * ProcessIdToSessionId (kernelbase.@)
1035 BOOL WINAPI DECLSPEC_HOTPATCH
ProcessIdToSessionId( DWORD pid
, DWORD
*id
)
1040 if (pid
== GetCurrentProcessId())
1042 *id
= NtCurrentTeb()->Peb
->SessionId
;
1045 if (!(process
= OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION
, FALSE
, pid
))) return FALSE
;
1046 status
= NtQueryInformationProcess( process
, ProcessSessionInformation
, id
, sizeof(*id
), NULL
);
1047 CloseHandle( process
);
1048 return set_ntstatus( status
);
1052 /***********************************************************************
1053 * QueryProcessCycleTime (kernelbase.@)
1055 BOOL WINAPI DECLSPEC_HOTPATCH
QueryProcessCycleTime( HANDLE process
, ULONG64
*cycle
)
1058 if (!once
++) FIXME( "(%p,%p): stub!\n", process
, cycle
);
1059 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1064 /***********************************************************************
1065 * SetErrorMode (kernelbase.@)
1067 UINT WINAPI DECLSPEC_HOTPATCH
SetErrorMode( UINT mode
)
1069 UINT old
= GetErrorMode();
1071 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode
,
1072 &mode
, sizeof(mode
) );
1077 /*************************************************************************
1078 * SetHandleCount (kernelbase.@)
1080 UINT WINAPI DECLSPEC_HOTPATCH
SetHandleCount( UINT count
)
1086 /*********************************************************************
1087 * SetHandleInformation (kernelbase.@)
1089 BOOL WINAPI DECLSPEC_HOTPATCH
SetHandleInformation( HANDLE handle
, DWORD mask
, DWORD flags
)
1091 OBJECT_DATA_INFORMATION info
;
1093 /* if not setting both fields, retrieve current value first */
1094 if ((mask
& (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
)) !=
1095 (HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
))
1097 if (!set_ntstatus( NtQueryObject( handle
, ObjectDataInformation
, &info
, sizeof(info
), NULL
)))
1100 if (mask
& HANDLE_FLAG_INHERIT
)
1101 info
.InheritHandle
= (flags
& HANDLE_FLAG_INHERIT
) != 0;
1102 if (mask
& HANDLE_FLAG_PROTECT_FROM_CLOSE
)
1103 info
.ProtectFromClose
= (flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
) != 0;
1105 return set_ntstatus( NtSetInformationObject( handle
, ObjectDataInformation
, &info
, sizeof(info
) ));
1109 /***********************************************************************
1110 * SetPriorityClass (kernelbase.@)
1112 BOOL WINAPI DECLSPEC_HOTPATCH
SetPriorityClass( HANDLE process
, DWORD
class )
1114 PROCESS_PRIORITY_CLASS ppc
;
1116 ppc
.Foreground
= FALSE
;
1119 case IDLE_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_IDLE
; break;
1120 case BELOW_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_BELOW_NORMAL
; break;
1121 case NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_NORMAL
; break;
1122 case ABOVE_NORMAL_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_ABOVE_NORMAL
; break;
1123 case HIGH_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_HIGH
; break;
1124 case REALTIME_PRIORITY_CLASS
: ppc
.PriorityClass
= PROCESS_PRIOCLASS_REALTIME
; break;
1126 SetLastError( ERROR_INVALID_PARAMETER
);
1129 return set_ntstatus( NtSetInformationProcess( process
, ProcessPriorityClass
, &ppc
, sizeof(ppc
) ));
1133 /***********************************************************************
1134 * SetProcessAffinityUpdateMode (kernelbase.@)
1136 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessAffinityUpdateMode( HANDLE process
, DWORD flags
)
1138 FIXME( "(%p,0x%08lx): stub\n", process
, flags
);
1139 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1144 /***********************************************************************
1145 * SetProcessGroupAffinity (kernelbase.@)
1147 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessGroupAffinity( HANDLE process
, const GROUP_AFFINITY
*new,
1148 GROUP_AFFINITY
*old
)
1150 FIXME( "(%p,%p,%p): stub\n", process
, new, old
);
1151 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1156 /**********************************************************************
1157 * SetProcessMitigationPolicy (kernelbase.@)
1159 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy
,
1160 void *buffer
, SIZE_T length
)
1162 FIXME( "(%d, %p, %Iu): stub\n", policy
, buffer
, length
);
1167 /***********************************************************************
1168 * SetProcessPriorityBoost (kernelbase.@)
1170 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process
, BOOL disable
)
1172 FIXME( "(%p,%d): stub\n", process
, disable
);
1177 /***********************************************************************
1178 * SetProcessShutdownParameters (kernelbase.@)
1180 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessShutdownParameters( DWORD level
, DWORD flags
)
1182 FIXME( "(%08lx, %08lx): partial stub.\n", level
, flags
);
1183 shutdown_flags
= flags
;
1184 shutdown_priority
= level
;
1189 /***********************************************************************
1190 * SetProcessWorkingSetSizeEx (kernelbase.@)
1192 BOOL WINAPI DECLSPEC_HOTPATCH
SetProcessWorkingSetSizeEx( HANDLE process
, SIZE_T minset
,
1193 SIZE_T maxset
, DWORD flags
)
1199 /******************************************************************************
1200 * TerminateProcess (kernelbase.@)
1202 BOOL WINAPI DECLSPEC_HOTPATCH
TerminateProcess( HANDLE handle
, DWORD exit_code
)
1206 SetLastError( ERROR_INVALID_HANDLE
);
1209 return set_ntstatus( NtTerminateProcess( handle
, exit_code
));
1213 /***********************************************************************
1214 * Process startup information
1215 ***********************************************************************/
1218 static STARTUPINFOW startup_infoW
;
1219 static char *command_lineA
;
1220 static WCHAR
*command_lineW
;
1222 /******************************************************************
1225 void init_startup_info( RTL_USER_PROCESS_PARAMETERS
*params
)
1229 startup_infoW
.cb
= sizeof(startup_infoW
);
1230 startup_infoW
.lpReserved
= NULL
;
1231 startup_infoW
.lpDesktop
= params
->Desktop
.Buffer
;
1232 startup_infoW
.lpTitle
= params
->WindowTitle
.Buffer
;
1233 startup_infoW
.dwX
= params
->dwX
;
1234 startup_infoW
.dwY
= params
->dwY
;
1235 startup_infoW
.dwXSize
= params
->dwXSize
;
1236 startup_infoW
.dwYSize
= params
->dwYSize
;
1237 startup_infoW
.dwXCountChars
= params
->dwXCountChars
;
1238 startup_infoW
.dwYCountChars
= params
->dwYCountChars
;
1239 startup_infoW
.dwFillAttribute
= params
->dwFillAttribute
;
1240 startup_infoW
.dwFlags
= params
->dwFlags
;
1241 startup_infoW
.wShowWindow
= params
->wShowWindow
;
1242 startup_infoW
.cbReserved2
= params
->RuntimeInfo
.MaximumLength
;
1243 startup_infoW
.lpReserved2
= params
->RuntimeInfo
.MaximumLength
? (void *)params
->RuntimeInfo
.Buffer
: NULL
;
1244 startup_infoW
.hStdInput
= params
->hStdInput
? params
->hStdInput
: INVALID_HANDLE_VALUE
;
1245 startup_infoW
.hStdOutput
= params
->hStdOutput
? params
->hStdOutput
: INVALID_HANDLE_VALUE
;
1246 startup_infoW
.hStdError
= params
->hStdError
? params
->hStdError
: INVALID_HANDLE_VALUE
;
1248 command_lineW
= params
->CommandLine
.Buffer
;
1249 if (!RtlUnicodeStringToAnsiString( &ansi
, ¶ms
->CommandLine
, TRUE
)) command_lineA
= ansi
.Buffer
;
1253 /**********************************************************************
1254 * BaseFlushAppcompatCache (kernelbase.@)
1256 BOOL WINAPI
BaseFlushAppcompatCache(void)
1259 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1264 /***********************************************************************
1265 * GetCommandLineA (kernelbase.@)
1267 LPSTR WINAPI
GetCommandLineA(void)
1269 return command_lineA
;
1273 /***********************************************************************
1274 * GetCommandLineW (kernelbase.@)
1276 LPWSTR WINAPI
GetCommandLineW(void)
1278 return command_lineW
;
1282 /***********************************************************************
1283 * GetStartupInfoW (kernelbase.@)
1285 void WINAPI DECLSPEC_HOTPATCH
GetStartupInfoW( STARTUPINFOW
*info
)
1287 *info
= startup_infoW
;
1291 /***********************************************************************
1292 * GetStdHandle (kernelbase.@)
1294 HANDLE WINAPI DECLSPEC_HOTPATCH
GetStdHandle( DWORD std_handle
)
1298 case STD_INPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
;
1299 case STD_OUTPUT_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
;
1300 case STD_ERROR_HANDLE
: return NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
;
1302 SetLastError( ERROR_INVALID_HANDLE
);
1303 return INVALID_HANDLE_VALUE
;
1307 /***********************************************************************
1308 * SetStdHandle (kernelbase.@)
1310 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandle( DWORD std_handle
, HANDLE handle
)
1314 case STD_INPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
= handle
; return TRUE
;
1315 case STD_OUTPUT_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
= handle
; return TRUE
;
1316 case STD_ERROR_HANDLE
: NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
= handle
; return TRUE
;
1318 SetLastError( ERROR_INVALID_HANDLE
);
1323 /***********************************************************************
1324 * SetStdHandleEx (kernelbase.@)
1326 BOOL WINAPI DECLSPEC_HOTPATCH
SetStdHandleEx( DWORD std_handle
, HANDLE handle
, HANDLE
*prev
)
1332 case STD_INPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdInput
; break;
1333 case STD_OUTPUT_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdOutput
; break;
1334 case STD_ERROR_HANDLE
: ptr
= &NtCurrentTeb()->Peb
->ProcessParameters
->hStdError
; break;
1336 SetLastError( ERROR_INVALID_HANDLE
);
1339 if (prev
) *prev
= *ptr
;
1345 /***********************************************************************
1346 * Process environment
1347 ***********************************************************************/
1350 static inline SIZE_T
get_env_length( const WCHAR
*env
)
1352 const WCHAR
*end
= env
;
1353 while (*end
) end
+= lstrlenW(end
) + 1;
1354 return end
+ 1 - env
;
1357 /***********************************************************************
1358 * ExpandEnvironmentStringsA (kernelbase.@)
1360 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsA( LPCSTR src
, LPSTR dst
, DWORD count
)
1362 UNICODE_STRING us_src
;
1366 RtlCreateUnicodeStringFromAsciiz( &us_src
, src
);
1369 if (!(dstW
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
)))) return 0;
1370 ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, dstW
, count
);
1371 if (ret
) WideCharToMultiByte( CP_ACP
, 0, dstW
, ret
, dst
, count
, NULL
, NULL
);
1373 else ret
= ExpandEnvironmentStringsW( us_src
.Buffer
, NULL
, 0 );
1375 RtlFreeUnicodeString( &us_src
);
1376 HeapFree( GetProcessHeap(), 0, dstW
);
1381 /***********************************************************************
1382 * ExpandEnvironmentStringsW (kernelbase.@)
1384 DWORD WINAPI DECLSPEC_HOTPATCH
ExpandEnvironmentStringsW( LPCWSTR src
, LPWSTR dst
, DWORD len
)
1386 UNICODE_STRING us_src
, us_dst
;
1390 TRACE( "(%s %p %lu)\n", debugstr_w(src
), dst
, len
);
1392 RtlInitUnicodeString( &us_src
, src
);
1394 /* make sure we don't overflow the maximum UNICODE_STRING size */
1395 len
= min( len
, UNICODE_STRING_MAX_CHARS
);
1398 us_dst
.MaximumLength
= len
* sizeof(WCHAR
);
1399 us_dst
.Buffer
= dst
;
1402 status
= RtlExpandEnvironmentStrings_U( NULL
, &us_src
, &us_dst
, &res
);
1403 res
/= sizeof(WCHAR
);
1404 if (!set_ntstatus( status
))
1406 if (status
!= STATUS_BUFFER_TOO_SMALL
) return 0;
1407 if (len
&& dst
) dst
[len
- 1] = 0;
1413 /***********************************************************************
1414 * GetEnvironmentStrings (kernelbase.@)
1415 * GetEnvironmentStringsA (kernelbase.@)
1417 LPSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsA(void)
1423 RtlAcquirePebLock();
1424 env
= NtCurrentTeb()->Peb
->ProcessParameters
->Environment
;
1425 lenW
= get_env_length( env
);
1426 lenA
= WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, NULL
, 0, NULL
, NULL
);
1427 if ((ret
= HeapAlloc( GetProcessHeap(), 0, lenA
)))
1428 WideCharToMultiByte( CP_ACP
, 0, env
, lenW
, ret
, lenA
, NULL
, NULL
);
1429 RtlReleasePebLock();
1434 /***********************************************************************
1435 * GetEnvironmentStringsW (kernelbase.@)
1437 LPWSTR WINAPI DECLSPEC_HOTPATCH
GetEnvironmentStringsW(void)
1442 RtlAcquirePebLock();
1443 len
= get_env_length( NtCurrentTeb()->Peb
->ProcessParameters
->Environment
) * sizeof(WCHAR
);
1444 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
1445 memcpy( ret
, NtCurrentTeb()->Peb
->ProcessParameters
->Environment
, len
);
1446 RtlReleasePebLock();
1451 /***********************************************************************
1452 * SetEnvironmentStringsA (kernelbase.@)
1454 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsA( char *env
)
1457 const char *p
= env
;
1461 for (p
= env
; *p
; p
+= strlen( p
) + 1);
1463 len
= MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, NULL
, 0 );
1464 if (!(envW
= HeapAlloc( GetProcessHeap(), 0, len
)))
1466 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1469 MultiByteToWideChar( CP_ACP
, 0, env
, p
- env
, envW
, len
);
1470 ret
= SetEnvironmentStringsW( envW
);
1471 HeapFree( GetProcessHeap(), 0, envW
);
1476 /***********************************************************************
1477 * SetEnvironmentStringsW (kernelbase.@)
1479 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentStringsW( WCHAR
*env
)
1485 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1487 const WCHAR
*eq
= wcschr( p
, '=' );
1490 SetLastError( ERROR_INVALID_PARAMETER
);
1495 if ((status
= RtlCreateEnvironment( FALSE
, &new_env
)))
1496 return set_ntstatus( status
);
1498 for (p
= env
; *p
; p
+= wcslen( p
) + 1)
1500 const WCHAR
*eq
= wcschr( p
, '=' );
1501 UNICODE_STRING var
, value
;
1503 var
.Length
= (eq
- p
) * sizeof(WCHAR
);
1504 RtlInitUnicodeString( &value
, eq
+ 1 );
1505 if ((status
= RtlSetEnvironmentVariable( &new_env
, &var
, &value
)))
1507 RtlDestroyEnvironment( new_env
);
1508 return set_ntstatus( status
);
1512 RtlSetCurrentEnvironment( new_env
, NULL
);
1517 /***********************************************************************
1518 * GetEnvironmentVariableA (kernelbase.@)
1520 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableA( LPCSTR name
, LPSTR value
, DWORD size
)
1522 UNICODE_STRING us_name
, us_value
;
1527 /* limit the size to sane values */
1528 size
= min( size
, 32767 );
1529 if (!(valueW
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1531 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1532 us_value
.Length
= 0;
1533 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1534 us_value
.Buffer
= valueW
;
1536 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1537 len
= us_value
.Length
/ sizeof(WCHAR
);
1538 if (status
== STATUS_BUFFER_TOO_SMALL
) ret
= len
+ 1;
1539 else if (!set_ntstatus( status
)) ret
= 0;
1540 else if (!size
) ret
= len
+ 1;
1543 if (len
) WideCharToMultiByte( CP_ACP
, 0, valueW
, len
+ 1, value
, size
, NULL
, NULL
);
1548 RtlFreeUnicodeString( &us_name
);
1549 HeapFree( GetProcessHeap(), 0, valueW
);
1554 /***********************************************************************
1555 * GetEnvironmentVariableW (kernelbase.@)
1557 DWORD WINAPI DECLSPEC_HOTPATCH
GetEnvironmentVariableW( LPCWSTR name
, LPWSTR val
, DWORD size
)
1559 UNICODE_STRING us_name
, us_value
;
1563 TRACE( "(%s %p %lu)\n", debugstr_w(name
), val
, size
);
1565 RtlInitUnicodeString( &us_name
, name
);
1566 us_value
.Length
= 0;
1567 us_value
.MaximumLength
= (size
? size
- 1 : 0) * sizeof(WCHAR
);
1568 us_value
.Buffer
= val
;
1570 status
= RtlQueryEnvironmentVariable_U( NULL
, &us_name
, &us_value
);
1571 len
= us_value
.Length
/ sizeof(WCHAR
);
1572 if (status
== STATUS_BUFFER_TOO_SMALL
) return len
+ 1;
1573 if (!set_ntstatus( status
)) return 0;
1574 if (!size
) return len
+ 1;
1580 /***********************************************************************
1581 * FreeEnvironmentStringsA (kernelbase.@)
1582 * FreeEnvironmentStringsW (kernelbase.@)
1584 BOOL WINAPI DECLSPEC_HOTPATCH
FreeEnvironmentStringsW( LPWSTR ptr
)
1586 return HeapFree( GetProcessHeap(), 0, ptr
);
1590 /***********************************************************************
1591 * SetEnvironmentVariableA (kernelbase.@)
1593 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableA( LPCSTR name
, LPCSTR value
)
1595 UNICODE_STRING us_name
, us_value
;
1600 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1604 RtlCreateUnicodeStringFromAsciiz( &us_name
, name
);
1607 RtlCreateUnicodeStringFromAsciiz( &us_value
, value
);
1608 ret
= SetEnvironmentVariableW( us_name
.Buffer
, us_value
.Buffer
);
1609 RtlFreeUnicodeString( &us_value
);
1611 else ret
= SetEnvironmentVariableW( us_name
.Buffer
, NULL
);
1612 RtlFreeUnicodeString( &us_name
);
1617 /***********************************************************************
1618 * SetEnvironmentVariableW (kernelbase.@)
1620 BOOL WINAPI DECLSPEC_HOTPATCH
SetEnvironmentVariableW( LPCWSTR name
, LPCWSTR value
)
1622 UNICODE_STRING us_name
, us_value
;
1625 TRACE( "(%s %s)\n", debugstr_w(name
), debugstr_w(value
) );
1629 SetLastError( ERROR_ENVVAR_NOT_FOUND
);
1633 RtlInitUnicodeString( &us_name
, name
);
1636 RtlInitUnicodeString( &us_value
, value
);
1637 status
= RtlSetEnvironmentVariable( NULL
, &us_name
, &us_value
);
1639 else status
= RtlSetEnvironmentVariable( NULL
, &us_name
, NULL
);
1641 return set_ntstatus( status
);
1645 /***********************************************************************
1646 * Process/thread attribute lists
1647 ***********************************************************************/
1649 /***********************************************************************
1650 * InitializeProcThreadAttributeList (kernelbase.@)
1652 BOOL WINAPI DECLSPEC_HOTPATCH
InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1653 DWORD count
, DWORD flags
, SIZE_T
*size
)
1658 TRACE( "(%p %ld %lx %p)\n", list
, count
, flags
, size
);
1660 needed
= FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST
, attrs
[count
] );
1661 if (list
&& *size
>= needed
)
1669 else SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1676 /***********************************************************************
1677 * UpdateProcThreadAttribute (kernelbase.@)
1679 BOOL WINAPI DECLSPEC_HOTPATCH
UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
,
1680 DWORD flags
, DWORD_PTR attr
, void *value
,
1681 SIZE_T size
, void *prev_ret
, SIZE_T
*size_ret
)
1684 struct proc_thread_attr
*entry
;
1686 TRACE( "(%p %lx %08Ix %p %Id %p %p)\n", list
, flags
, attr
, value
, size
, prev_ret
, size_ret
);
1688 if (list
->count
>= list
->size
)
1690 SetLastError( ERROR_GEN_FAILURE
);
1696 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
:
1697 if (size
!= sizeof(HANDLE
))
1699 SetLastError( ERROR_BAD_LENGTH
);
1704 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST
:
1705 if ((size
/ sizeof(HANDLE
)) * sizeof(HANDLE
) != size
)
1707 SetLastError( ERROR_BAD_LENGTH
);
1712 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR
:
1713 if (size
!= sizeof(PROCESSOR_NUMBER
))
1715 SetLastError( ERROR_BAD_LENGTH
);
1720 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY
:
1721 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
))
1723 SetLastError( ERROR_BAD_LENGTH
);
1728 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
:
1729 if (size
!= sizeof(DWORD
) && size
!= sizeof(DWORD64
) && size
!= sizeof(DWORD64
) * 2)
1731 SetLastError( ERROR_BAD_LENGTH
);
1736 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
:
1737 if (size
!= sizeof(HPCON
))
1739 SetLastError( ERROR_BAD_LENGTH
);
1744 case PROC_THREAD_ATTRIBUTE_JOB_LIST
:
1745 if ((size
/ sizeof(HANDLE
)) * sizeof(HANDLE
) != size
)
1747 SetLastError( ERROR_BAD_LENGTH
);
1753 SetLastError( ERROR_NOT_SUPPORTED
);
1754 FIXME( "Unhandled attribute %Iu\n", attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1758 mask
= 1 << (attr
& PROC_THREAD_ATTRIBUTE_NUMBER
);
1759 if (list
->mask
& mask
)
1761 SetLastError( ERROR_OBJECT_NAME_EXISTS
);
1766 entry
= list
->attrs
+ list
->count
;
1769 entry
->value
= value
;
1775 /***********************************************************************
1776 * DeleteProcThreadAttributeList (kernelbase.@)
1778 void WINAPI DECLSPEC_HOTPATCH
DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST
*list
)
1784 /***********************************************************************
1785 * CompareObjectHandles (kernelbase.@)
1787 BOOL WINAPI DECLSPEC_HOTPATCH
CompareObjectHandles( HANDLE first
, HANDLE second
)
1789 return set_ntstatus( NtCompareObjects( first
, second
));