winegstreamer: Register stub ColorConvertDMO transform.
[wine.git] / dlls / kernelbase / process.c
blob32f622bdf3e7cb57c5d3a65551d306a792b58ed5
1 /*
2 * Win32 processes
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
21 #include <stdarg.h>
22 #include <string.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31 #include "wincontypes.h"
32 #include "winternl.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 /***********************************************************************
44 * Processes
45 ***********************************************************************/
48 /***********************************************************************
49 * find_exe_file
51 static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, DWORD buflen )
53 WCHAR *load_path;
54 BOOL ret;
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 );
71 return ret;
75 /*************************************************************************
76 * get_file_name
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;
85 const WCHAR *p;
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) );
95 name[len] = 0;
97 if (!find_exe_file( name, buffer, buflen )) goto done;
98 ret = cmdline; /* no change necessary */
99 goto done;
102 /* now try the command-line word by word */
104 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR) )))
105 return NULL;
106 pos = name;
107 p = cmdline;
108 first_space = NULL;
110 for (;;)
112 while (*p && *p != ' ' && *p != '\t') *pos++ = *p++;
113 *pos = 0;
114 if (find_exe_file( name, buffer, buflen ))
116 ret = cmdline;
117 break;
119 if (!first_space) first_space = pos;
120 if (!(*pos++ = *p++)) break;
123 if (!ret)
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) )))
130 goto done;
131 swprintf( ret, lstrlenW(cmdline) + 3, L"\"%s\"%s", name, p );
134 done:
135 RtlFreeHeap( GetProcessHeap(), 0, name );
136 return ret;
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];
150 WCHAR *envW = env;
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 */
157 char *e = env;
158 DWORD lenW;
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;
168 if (cur_dir)
170 if (RtlDosPathNameToNtPathName_U( cur_dir, &newdirW, NULL, NULL ))
171 cur_dir = newdirW.Buffer + 4; /* skip \??\ prefix */
172 else
173 cur_dir = NULL;
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( &params, &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 );
188 return NULL;
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;
197 else
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;
216 else
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 );
234 return params;
237 struct proc_thread_attr
239 DWORD_PTR attr;
240 SIZE_T size;
241 void *value;
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 */
249 DWORD pad;
250 DWORD_PTR unk;
251 struct proc_thread_attr attrs[1];
254 /***********************************************************************
255 * create_nt_process
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;
269 NTSTATUS status;
270 UINT pos = 0;
272 if (!params->ImagePathName.Buffer[0]) return STATUS_OBJECT_PATH_NOT_FOUND;
273 status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nameW, NULL, NULL );
274 if (!status)
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;
282 pos++;
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;
287 pos++;
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;
292 pos++;
293 if (parent)
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;
299 pos++;
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;
307 pos++;
309 if (token)
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;
315 pos++;
317 if (debug)
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;
323 pos++;
325 if (job_list)
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;
331 pos++;
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 );
345 return status;
349 /***********************************************************************
350 * create_vdm_process
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");
360 WCHAR *newcmdline;
361 NTSTATUS status;
362 UINT len;
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( &params->ImagePathName, winevdm );
373 RtlInitUnicodeString( &params->CommandLine, newcmdline );
374 status = create_nt_process( token, debug, psa, tsa, flags, params, info, NULL, NULL, NULL );
375 HeapFree( GetProcessHeap(), 0, newcmdline );
376 return status;
380 /***********************************************************************
381 * create_cmd_process
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];
389 WCHAR *newcmdline;
390 NTSTATUS status;
391 UINT len;
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( &params->ImagePathName, comspec );
402 RtlInitUnicodeString( &params->CommandLine, newcmdline );
403 status = create_nt_process( token, debug, psa, tsa, flags, params, info, NULL, NULL, NULL );
404 RtlFreeHeap( GetProcessHeap(), 0, newcmdline );
405 return status;
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 )
464 BOOL ret = FALSE;
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 );
487 done:
488 RtlFreeHeap( GetProcessHeap(), 0, app_nameW );
489 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW );
490 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW );
491 RtlFreeUnicodeString( &desktopW );
492 RtlFreeUnicodeString( &titleW );
493 return ret;
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;
512 ULONG nt_flags = 0;
513 NTSTATUS status;
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" );
521 if (app_name)
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) )))
526 return FALSE;
527 swprintf( tidy_cmdline, lstrlenW(app_name) + 3, L"\"%s\"", app_name );
530 else
532 if (!(tidy_cmdline = get_file_name( cmd_line, name, ARRAY_SIZE(name) ))) return FALSE;
533 app_name = name;
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 );
542 if (cur_dir)
544 DWORD attr = GetFileAttributesW( cur_dir );
545 if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY))
547 status = STATUS_NOT_A_DIRECTORY;
548 goto done;
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;
558 goto done;
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;
571 unsigned int i;
573 if (attrs)
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);
582 if (!parent)
584 status = STATUS_INVALID_HANDLE;
585 goto done;
587 break;
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));
591 break;
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;
598 break;
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) );
604 break;
605 default:
606 FIXME("Unsupported attribute %#Ix.\n", attrs->attrs[i].attr);
607 break;
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 );
620 switch (status)
622 case STATUS_SUCCESS:
623 break;
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 );
630 break;
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 );
646 break;
649 if (!status)
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 );
659 done:
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 );
722 return E_NOTIMPL;
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)
749 UINT mode;
751 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode,
752 &mode, sizeof(mode), NULL );
753 return mode;
757 /***********************************************************************
758 * GetExitCodeProcess (kernelbase.@)
760 BOOL WINAPI DECLSPEC_HOTPATCH GetExitCodeProcess( HANDLE process, LPDWORD exit_code )
762 NTSTATUS status;
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 )))
779 return FALSE;
781 if (flags)
783 *flags = 0;
784 if (info.InheritHandle) *flags |= HANDLE_FLAG_INHERIT;
785 if (info.ProtectFromClose) *flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
787 return TRUE;
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 )))
800 return 0;
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;
810 default: return 0;
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 );
822 return FALSE;
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 )))
854 return 0;
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 );
866 return TRUE;
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 */
877 return TRUE;
881 /***********************************************************************
882 * GetProcessShutdownParameters (kernelbase.@)
884 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessShutdownParameters( LPDWORD level, LPDWORD flags )
886 *level = shutdown_priority;
887 *flags = shutdown_flags;
888 return TRUE;
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 )))
901 return FALSE;
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;
911 return TRUE;
915 /***********************************************************************
916 * GetProcessVersion (kernelbase.@)
918 DWORD WINAPI DECLSPEC_HOTPATCH GetProcessVersion( DWORD pid )
920 SECTION_IMAGE_INFORMATION info;
921 NTSTATUS status;
922 HANDLE process;
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;
949 return TRUE;
953 /******************************************************************************
954 * IsProcessInJob (kernelbase.@)
956 BOOL WINAPI DECLSPEC_HOTPATCH IsProcessInJob( HANDLE process, HANDLE job, BOOL *result )
958 NTSTATUS status = NtIsProcessInJob( process, job );
960 switch (status)
962 case STATUS_PROCESS_IN_JOB:
963 *result = TRUE;
964 return TRUE;
965 case STATUS_PROCESS_NOT_IN_JOB:
966 *result = FALSE;
967 return TRUE;
968 default:
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 )
997 ULONG_PTR pbi;
998 NTSTATUS status;
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 )
1011 HANDLE handle;
1012 OBJECT_ATTRIBUTES attr;
1013 CLIENT_ID cid;
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;
1028 return handle;
1032 /***********************************************************************
1033 * ProcessIdToSessionId (kernelbase.@)
1035 BOOL WINAPI DECLSPEC_HOTPATCH ProcessIdToSessionId( DWORD pid, DWORD *id )
1037 HANDLE process;
1038 NTSTATUS status;
1040 if (pid == GetCurrentProcessId())
1042 *id = NtCurrentTeb()->Peb->SessionId;
1043 return TRUE;
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 )
1057 static int once;
1058 if (!once++) FIXME( "(%p,%p): stub!\n", process, cycle );
1059 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1060 return FALSE;
1064 /***********************************************************************
1065 * SetErrorMode (kernelbase.@)
1067 UINT WINAPI DECLSPEC_HOTPATCH SetErrorMode( UINT mode )
1069 UINT old = GetErrorMode();
1071 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode,
1072 &mode, sizeof(mode) );
1073 return old;
1077 /*************************************************************************
1078 * SetHandleCount (kernelbase.@)
1080 UINT WINAPI DECLSPEC_HOTPATCH SetHandleCount( UINT count )
1082 return 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 )))
1098 return FALSE;
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;
1117 switch (class)
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;
1125 default:
1126 SetLastError( ERROR_INVALID_PARAMETER );
1127 return FALSE;
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 );
1140 return FALSE;
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 );
1152 return FALSE;
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 );
1163 return TRUE;
1167 /***********************************************************************
1168 * SetProcessPriorityBoost (kernelbase.@)
1170 BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process, BOOL disable )
1172 FIXME( "(%p,%d): stub\n", process, disable );
1173 return TRUE;
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;
1185 return TRUE;
1189 /***********************************************************************
1190 * SetProcessWorkingSetSizeEx (kernelbase.@)
1192 BOOL WINAPI DECLSPEC_HOTPATCH SetProcessWorkingSetSizeEx( HANDLE process, SIZE_T minset,
1193 SIZE_T maxset, DWORD flags )
1195 return TRUE;
1199 /******************************************************************************
1200 * TerminateProcess (kernelbase.@)
1202 BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code )
1204 if (!handle)
1206 SetLastError( ERROR_INVALID_HANDLE );
1207 return FALSE;
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 /******************************************************************
1223 * init_startup_info
1225 void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params )
1227 ANSI_STRING ansi;
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, &params->CommandLine, TRUE )) command_lineA = ansi.Buffer;
1253 /**********************************************************************
1254 * BaseFlushAppcompatCache (kernelbase.@)
1256 BOOL WINAPI BaseFlushAppcompatCache(void)
1258 FIXME( "stub\n" );
1259 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1260 return FALSE;
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 )
1296 switch (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 )
1312 switch (std_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 );
1319 return FALSE;
1323 /***********************************************************************
1324 * SetStdHandleEx (kernelbase.@)
1326 BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandleEx( DWORD std_handle, HANDLE handle, HANDLE *prev )
1328 HANDLE *ptr;
1330 switch (std_handle)
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;
1335 default:
1336 SetLastError( ERROR_INVALID_HANDLE );
1337 return FALSE;
1339 if (prev) *prev = *ptr;
1340 *ptr = handle;
1341 return TRUE;
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;
1363 PWSTR dstW = NULL;
1364 DWORD ret;
1366 RtlCreateUnicodeStringFromAsciiz( &us_src, src );
1367 if (count)
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 );
1377 return ret;
1381 /***********************************************************************
1382 * ExpandEnvironmentStringsW (kernelbase.@)
1384 DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len )
1386 UNICODE_STRING us_src, us_dst;
1387 NTSTATUS status;
1388 DWORD res;
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 );
1397 us_dst.Length = 0;
1398 us_dst.MaximumLength = len * sizeof(WCHAR);
1399 us_dst.Buffer = dst;
1401 res = 0;
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;
1409 return res;
1413 /***********************************************************************
1414 * GetEnvironmentStrings (kernelbase.@)
1415 * GetEnvironmentStringsA (kernelbase.@)
1417 LPSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsA(void)
1419 LPWSTR env;
1420 LPSTR ret;
1421 SIZE_T lenA, lenW;
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();
1430 return ret;
1434 /***********************************************************************
1435 * GetEnvironmentStringsW (kernelbase.@)
1437 LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void)
1439 LPWSTR ret;
1440 SIZE_T len;
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();
1447 return ret;
1451 /***********************************************************************
1452 * SetEnvironmentStringsA (kernelbase.@)
1454 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsA( char *env )
1456 WCHAR *envW;
1457 const char *p = env;
1458 DWORD len;
1459 BOOL ret;
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 );
1467 return FALSE;
1469 MultiByteToWideChar( CP_ACP, 0, env, p - env, envW, len );
1470 ret = SetEnvironmentStringsW( envW );
1471 HeapFree( GetProcessHeap(), 0, envW );
1472 return ret;
1476 /***********************************************************************
1477 * SetEnvironmentStringsW (kernelbase.@)
1479 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsW( WCHAR *env )
1481 WCHAR *p;
1482 WCHAR *new_env;
1483 NTSTATUS status;
1485 for (p = env; *p; p += wcslen( p ) + 1)
1487 const WCHAR *eq = wcschr( p, '=' );
1488 if (!eq || eq == p)
1490 SetLastError( ERROR_INVALID_PARAMETER );
1491 return FALSE;
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;
1502 var.Buffer = p;
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 );
1513 return TRUE;
1517 /***********************************************************************
1518 * GetEnvironmentVariableA (kernelbase.@)
1520 DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size )
1522 UNICODE_STRING us_name, us_value;
1523 PWSTR valueW;
1524 NTSTATUS status;
1525 DWORD len, ret;
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;
1541 else
1543 if (len) WideCharToMultiByte( CP_ACP, 0, valueW, len + 1, value, size, NULL, NULL );
1544 value[len] = 0;
1545 ret = len;
1548 RtlFreeUnicodeString( &us_name );
1549 HeapFree( GetProcessHeap(), 0, valueW );
1550 return ret;
1554 /***********************************************************************
1555 * GetEnvironmentVariableW (kernelbase.@)
1557 DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size )
1559 UNICODE_STRING us_name, us_value;
1560 NTSTATUS status;
1561 DWORD len;
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;
1575 val[len] = 0;
1576 return len;
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;
1596 BOOL ret;
1598 if (!name)
1600 SetLastError( ERROR_ENVVAR_NOT_FOUND );
1601 return FALSE;
1604 RtlCreateUnicodeStringFromAsciiz( &us_name, name );
1605 if (value)
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 );
1613 return ret;
1617 /***********************************************************************
1618 * SetEnvironmentVariableW (kernelbase.@)
1620 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value )
1622 UNICODE_STRING us_name, us_value;
1623 NTSTATUS status;
1625 TRACE( "(%s %s)\n", debugstr_w(name), debugstr_w(value) );
1627 if (!name)
1629 SetLastError( ERROR_ENVVAR_NOT_FOUND );
1630 return FALSE;
1633 RtlInitUnicodeString( &us_name, name );
1634 if (value)
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 )
1655 SIZE_T needed;
1656 BOOL ret = FALSE;
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)
1663 list->mask = 0;
1664 list->size = count;
1665 list->count = 0;
1666 list->unk = 0;
1667 ret = TRUE;
1669 else SetLastError( ERROR_INSUFFICIENT_BUFFER );
1671 *size = needed;
1672 return ret;
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 )
1683 DWORD mask;
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 );
1691 return FALSE;
1694 switch (attr)
1696 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:
1697 if (size != sizeof(HANDLE))
1699 SetLastError( ERROR_BAD_LENGTH );
1700 return FALSE;
1702 break;
1704 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST:
1705 if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size)
1707 SetLastError( ERROR_BAD_LENGTH );
1708 return FALSE;
1710 break;
1712 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR:
1713 if (size != sizeof(PROCESSOR_NUMBER))
1715 SetLastError( ERROR_BAD_LENGTH );
1716 return FALSE;
1718 break;
1720 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY:
1721 if (size != sizeof(DWORD) && size != sizeof(DWORD64))
1723 SetLastError( ERROR_BAD_LENGTH );
1724 return FALSE;
1726 break;
1728 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY:
1729 if (size != sizeof(DWORD) && size != sizeof(DWORD64) && size != sizeof(DWORD64) * 2)
1731 SetLastError( ERROR_BAD_LENGTH );
1732 return FALSE;
1734 break;
1736 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE:
1737 if (size != sizeof(HPCON))
1739 SetLastError( ERROR_BAD_LENGTH );
1740 return FALSE;
1742 break;
1744 case PROC_THREAD_ATTRIBUTE_JOB_LIST:
1745 if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size)
1747 SetLastError( ERROR_BAD_LENGTH );
1748 return FALSE;
1750 break;
1752 default:
1753 SetLastError( ERROR_NOT_SUPPORTED );
1754 FIXME( "Unhandled attribute %Iu\n", attr & PROC_THREAD_ATTRIBUTE_NUMBER );
1755 return FALSE;
1758 mask = 1 << (attr & PROC_THREAD_ATTRIBUTE_NUMBER);
1759 if (list->mask & mask)
1761 SetLastError( ERROR_OBJECT_NAME_EXISTS );
1762 return FALSE;
1764 list->mask |= mask;
1766 entry = list->attrs + list->count;
1767 entry->attr = attr;
1768 entry->size = size;
1769 entry->value = value;
1770 list->count++;
1771 return TRUE;
1775 /***********************************************************************
1776 * DeleteProcThreadAttributeList (kernelbase.@)
1778 void WINAPI DECLSPEC_HOTPATCH DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list )
1780 return;
1784 /***********************************************************************
1785 * CompareObjectHandles (kernelbase.@)
1787 BOOL WINAPI DECLSPEC_HOTPATCH CompareObjectHandles( HANDLE first, HANDLE second )
1789 return set_ntstatus( NtCompareObjects( first, second ));