mfmediaengine: Handle B8G8R8X8 format for d3d11 texture output.
[wine.git] / dlls / kernelbase / process.c
blob101d3fa321312f66b10b21efaebc3ef7f6d00bf7
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"
37 WINE_DEFAULT_DEBUG_CHANNEL(process);
39 static DWORD shutdown_flags = 0;
40 static DWORD shutdown_priority = 0x280;
42 /***********************************************************************
43 * Processes
44 ***********************************************************************/
47 /***********************************************************************
48 * find_exe_file
50 static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, DWORD buflen )
52 WCHAR *load_path;
53 BOOL ret;
55 if (!set_ntstatus( RtlGetExePath( name, &load_path ))) return FALSE;
57 TRACE( "looking for %s in %s\n", debugstr_w(name), debugstr_w(load_path) );
59 ret = (SearchPathW( load_path, name, L".exe", buflen, buffer, NULL ) ||
60 /* not found, try without extension in case it is a Unix app */
61 SearchPathW( load_path, name, NULL, buflen, buffer, NULL ));
63 if (ret) /* make sure it can be opened, SearchPathW also returns directories */
65 HANDLE handle = CreateFileW( buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE,
66 NULL, OPEN_EXISTING, 0, 0 );
67 if ((ret = (handle != INVALID_HANDLE_VALUE))) CloseHandle( handle );
69 RtlReleasePath( load_path );
70 return ret;
74 /*************************************************************************
75 * get_file_name
77 * Helper for CreateProcess: retrieve the file name to load from the
78 * app name and command line. Store the file name in buffer, and
79 * return a possibly modified command line.
81 static WCHAR *get_file_name( WCHAR *cmdline, WCHAR *buffer, DWORD buflen )
83 WCHAR *name, *pos, *first_space, *ret = NULL;
84 const WCHAR *p;
86 /* first check for a quoted file name */
88 if (cmdline[0] == '"' && (p = wcschr( cmdline + 1, '"' )))
90 int len = p - cmdline - 1;
91 /* extract the quoted portion as file name */
92 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
93 memcpy( name, cmdline + 1, len * sizeof(WCHAR) );
94 name[len] = 0;
96 if (!find_exe_file( name, buffer, buflen )) goto done;
97 ret = cmdline; /* no change necessary */
98 goto done;
101 /* now try the command-line word by word */
103 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR) )))
104 return NULL;
105 pos = name;
106 p = cmdline;
107 first_space = NULL;
109 for (;;)
111 while (*p && *p != ' ' && *p != '\t') *pos++ = *p++;
112 *pos = 0;
113 if (find_exe_file( name, buffer, buflen ))
115 ret = cmdline;
116 break;
118 if (!first_space) first_space = pos;
119 if (!(*pos++ = *p++)) break;
122 if (!ret)
124 SetLastError( ERROR_FILE_NOT_FOUND );
126 else if (first_space) /* build a new command-line with quotes */
128 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline) + 3) * sizeof(WCHAR) )))
129 goto done;
130 swprintf( ret, lstrlenW(cmdline) + 3, L"\"%s\"%s", name, p );
133 done:
134 RtlFreeHeap( GetProcessHeap(), 0, name );
135 return ret;
139 /***********************************************************************
140 * create_process_params
142 static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename, const WCHAR *cmdline,
143 const WCHAR *cur_dir, void *env, DWORD flags,
144 const STARTUPINFOW *startup )
146 RTL_USER_PROCESS_PARAMETERS *params;
147 UNICODE_STRING imageW, curdirW, cmdlineW, titleW, desktopW, runtimeW, newdirW;
148 WCHAR imagepath[MAX_PATH];
149 WCHAR *envW = env;
151 if (!GetLongPathNameW( filename, imagepath, MAX_PATH )) lstrcpynW( imagepath, filename, MAX_PATH );
152 if (!GetFullPathNameW( imagepath, MAX_PATH, imagepath, NULL )) lstrcpynW( imagepath, filename, MAX_PATH );
154 if (env && !(flags & CREATE_UNICODE_ENVIRONMENT)) /* convert environment to unicode */
156 char *e = env;
157 DWORD lenW;
159 while (*e) e += strlen(e) + 1;
160 e++; /* final null */
161 lenW = MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, NULL, 0 );
162 if ((envW = RtlAllocateHeap( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
163 MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, envW, lenW );
166 newdirW.Buffer = NULL;
167 if (cur_dir)
169 if (RtlDosPathNameToNtPathName_U( cur_dir, &newdirW, NULL, NULL ))
170 cur_dir = newdirW.Buffer + 4; /* skip \??\ prefix */
171 else
172 cur_dir = NULL;
174 RtlInitUnicodeString( &imageW, imagepath );
175 RtlInitUnicodeString( &curdirW, cur_dir );
176 RtlInitUnicodeString( &cmdlineW, cmdline );
177 RtlInitUnicodeString( &titleW, startup->lpTitle ? startup->lpTitle : imagepath );
178 RtlInitUnicodeString( &desktopW, startup->lpDesktop );
179 runtimeW.Buffer = (WCHAR *)startup->lpReserved2;
180 runtimeW.Length = runtimeW.MaximumLength = startup->cbReserved2;
181 if (RtlCreateProcessParametersEx( &params, &imageW, NULL, cur_dir ? &curdirW : NULL,
182 &cmdlineW, envW, &titleW, &desktopW,
183 NULL, &runtimeW, PROCESS_PARAMS_FLAG_NORMALIZED ))
185 RtlFreeUnicodeString( &newdirW );
186 if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW );
187 return NULL;
189 RtlFreeUnicodeString( &newdirW );
191 if (flags & CREATE_NEW_PROCESS_GROUP) params->ConsoleFlags = 1;
192 if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = (HANDLE)1; /* KERNEL32_CONSOLE_ALLOC */
193 else if (!(flags & DETACHED_PROCESS)) params->ConsoleHandle = NtCurrentTeb()->Peb->ProcessParameters->ConsoleHandle;
195 if (startup->dwFlags & STARTF_USESTDHANDLES)
197 params->hStdInput = startup->hStdInput;
198 params->hStdOutput = startup->hStdOutput;
199 params->hStdError = startup->hStdError;
201 else if (flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE))
203 params->hStdInput = INVALID_HANDLE_VALUE;
204 params->hStdOutput = INVALID_HANDLE_VALUE;
205 params->hStdError = INVALID_HANDLE_VALUE;
207 else
209 params->hStdInput = NtCurrentTeb()->Peb->ProcessParameters->hStdInput;
210 params->hStdOutput = NtCurrentTeb()->Peb->ProcessParameters->hStdOutput;
211 params->hStdError = NtCurrentTeb()->Peb->ProcessParameters->hStdError;
214 params->dwX = startup->dwX;
215 params->dwY = startup->dwY;
216 params->dwXSize = startup->dwXSize;
217 params->dwYSize = startup->dwYSize;
218 params->dwXCountChars = startup->dwXCountChars;
219 params->dwYCountChars = startup->dwYCountChars;
220 params->dwFillAttribute = startup->dwFillAttribute;
221 params->dwFlags = startup->dwFlags;
222 params->wShowWindow = startup->wShowWindow;
224 if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW );
225 return params;
228 struct proc_thread_attr
230 DWORD_PTR attr;
231 SIZE_T size;
232 void *value;
235 struct _PROC_THREAD_ATTRIBUTE_LIST
237 DWORD mask; /* bitmask of items in list */
238 DWORD size; /* max number of items in list */
239 DWORD count; /* number of items in list */
240 DWORD pad;
241 DWORD_PTR unk;
242 struct proc_thread_attr attrs[1];
245 /***********************************************************************
246 * create_nt_process
248 static NTSTATUS create_nt_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa,
249 SECURITY_ATTRIBUTES *tsa, DWORD process_flags,
250 RTL_USER_PROCESS_PARAMETERS *params,
251 RTL_USER_PROCESS_INFORMATION *info, HANDLE parent,
252 const struct proc_thread_attr *handle_list,
253 const struct proc_thread_attr *job_list)
255 OBJECT_ATTRIBUTES process_attr, thread_attr;
256 PS_CREATE_INFO create_info;
257 ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[8] ) / sizeof(ULONG_PTR)];
258 PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer;
259 UNICODE_STRING nameW;
260 NTSTATUS status;
261 UINT pos = 0;
263 if (!params->ImagePathName.Buffer[0]) return STATUS_OBJECT_PATH_NOT_FOUND;
264 status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nameW, NULL, NULL );
265 if (!status)
267 RtlNormalizeProcessParams( params );
269 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
270 attr->Attributes[pos].Size = nameW.Length;
271 attr->Attributes[pos].ValuePtr = nameW.Buffer;
272 attr->Attributes[pos].ReturnLength = NULL;
273 pos++;
274 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_CLIENT_ID;
275 attr->Attributes[pos].Size = sizeof(info->ClientId);
276 attr->Attributes[pos].ValuePtr = &info->ClientId;
277 attr->Attributes[pos].ReturnLength = NULL;
278 pos++;
279 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_INFO;
280 attr->Attributes[pos].Size = sizeof(info->ImageInformation);
281 attr->Attributes[pos].ValuePtr = &info->ImageInformation;
282 attr->Attributes[pos].ReturnLength = NULL;
283 pos++;
284 if (parent)
286 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_PARENT_PROCESS;
287 attr->Attributes[pos].Size = sizeof(parent);
288 attr->Attributes[pos].ValuePtr = parent;
289 attr->Attributes[pos].ReturnLength = NULL;
290 pos++;
292 if ((process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES) && handle_list)
294 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_HANDLE_LIST;
295 attr->Attributes[pos].Size = handle_list->size;
296 attr->Attributes[pos].ValuePtr = handle_list->value;
297 attr->Attributes[pos].ReturnLength = NULL;
298 pos++;
300 if (token)
302 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_TOKEN;
303 attr->Attributes[pos].Size = sizeof(token);
304 attr->Attributes[pos].ValuePtr = token;
305 attr->Attributes[pos].ReturnLength = NULL;
306 pos++;
308 if (debug)
310 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_DEBUG_PORT;
311 attr->Attributes[pos].Size = sizeof(debug);
312 attr->Attributes[pos].ValuePtr = debug;
313 attr->Attributes[pos].ReturnLength = NULL;
314 pos++;
316 if (job_list)
318 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_JOB_LIST;
319 attr->Attributes[pos].Size = job_list->size;
320 attr->Attributes[pos].ValuePtr = job_list->value;
321 attr->Attributes[pos].ReturnLength = NULL;
322 pos++;
324 attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] );
326 InitializeObjectAttributes( &process_attr, NULL, 0, NULL, psa ? psa->lpSecurityDescriptor : NULL );
327 InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, tsa ? tsa->lpSecurityDescriptor : NULL );
329 status = NtCreateUserProcess( &info->Process, &info->Thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
330 &process_attr, &thread_attr, process_flags,
331 THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params,
332 &create_info, attr );
334 RtlFreeUnicodeString( &nameW );
336 return status;
340 /***********************************************************************
341 * create_vdm_process
343 static NTSTATUS create_vdm_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa,
344 SECURITY_ATTRIBUTES *tsa, DWORD flags,
345 RTL_USER_PROCESS_PARAMETERS *params,
346 RTL_USER_PROCESS_INFORMATION *info )
348 const WCHAR *winevdm = (is_win64 || is_wow64 ?
349 L"C:\\windows\\syswow64\\winevdm.exe" :
350 L"C:\\windows\\system32\\winevdm.exe");
351 WCHAR *newcmdline;
352 NTSTATUS status;
353 UINT len;
355 len = (lstrlenW(params->ImagePathName.Buffer) + lstrlenW(params->CommandLine.Buffer) +
356 lstrlenW(winevdm) + 16);
358 if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
359 return STATUS_NO_MEMORY;
361 swprintf( newcmdline, len, L"%s --app-name \"%s\" %s",
362 winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer );
363 RtlInitUnicodeString( &params->ImagePathName, winevdm );
364 RtlInitUnicodeString( &params->CommandLine, newcmdline );
365 status = create_nt_process( token, debug, psa, tsa, flags, params, info, NULL, NULL, NULL );
366 HeapFree( GetProcessHeap(), 0, newcmdline );
367 return status;
371 /***********************************************************************
372 * create_cmd_process
374 static NTSTATUS create_cmd_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa,
375 SECURITY_ATTRIBUTES *tsa, DWORD flags,
376 RTL_USER_PROCESS_PARAMETERS *params,
377 RTL_USER_PROCESS_INFORMATION *info )
379 WCHAR comspec[MAX_PATH];
380 WCHAR *newcmdline;
381 NTSTATUS status;
382 UINT len;
384 if (!GetEnvironmentVariableW( L"COMSPEC", comspec, ARRAY_SIZE( comspec )))
385 lstrcpyW( comspec, L"C:\\windows\\system32\\cmd.exe" );
387 len = lstrlenW(comspec) + 7 + lstrlenW(params->CommandLine.Buffer) + 2;
388 if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
389 return STATUS_NO_MEMORY;
391 swprintf( newcmdline, len, L"%s /s/c \"%s\"", comspec, params->CommandLine.Buffer );
392 RtlInitUnicodeString( &params->ImagePathName, comspec );
393 RtlInitUnicodeString( &params->CommandLine, newcmdline );
394 status = create_nt_process( token, debug, psa, tsa, flags, params, info, NULL, NULL, NULL );
395 RtlFreeHeap( GetProcessHeap(), 0, newcmdline );
396 return status;
400 /*********************************************************************
401 * CloseHandle (kernelbase.@)
403 BOOL WINAPI DECLSPEC_HOTPATCH CloseHandle( HANDLE handle )
405 if (handle == (HANDLE)STD_INPUT_HANDLE)
406 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdInput, 0 );
407 else if (handle == (HANDLE)STD_OUTPUT_HANDLE)
408 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput, 0 );
409 else if (handle == (HANDLE)STD_ERROR_HANDLE)
410 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdError, 0 );
412 return set_ntstatus( NtClose( handle ));
416 /**********************************************************************
417 * CreateProcessAsUserA (kernelbase.@)
419 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserA( HANDLE token, const char *app_name, char *cmd_line,
420 SECURITY_ATTRIBUTES *process_attr,
421 SECURITY_ATTRIBUTES *thread_attr,
422 BOOL inherit, DWORD flags, void *env,
423 const char *cur_dir, STARTUPINFOA *startup_info,
424 PROCESS_INFORMATION *info )
426 return CreateProcessInternalA( token, app_name, cmd_line, process_attr, thread_attr,
427 inherit, flags, env, cur_dir, startup_info, info, NULL );
431 /**********************************************************************
432 * CreateProcessAsUserW (kernelbase.@)
434 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line,
435 SECURITY_ATTRIBUTES *process_attr,
436 SECURITY_ATTRIBUTES *thread_attr,
437 BOOL inherit, DWORD flags, void *env,
438 const WCHAR *cur_dir, STARTUPINFOW *startup_info,
439 PROCESS_INFORMATION *info )
441 return CreateProcessInternalW( token, app_name, cmd_line, process_attr, thread_attr,
442 inherit, flags, env, cur_dir, startup_info, info, NULL );
445 /**********************************************************************
446 * CreateProcessInternalA (kernelbase.@)
448 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalA( HANDLE token, const char *app_name, char *cmd_line,
449 SECURITY_ATTRIBUTES *process_attr,
450 SECURITY_ATTRIBUTES *thread_attr,
451 BOOL inherit, DWORD flags, void *env,
452 const char *cur_dir, STARTUPINFOA *startup_info,
453 PROCESS_INFORMATION *info, HANDLE *new_token )
455 BOOL ret = FALSE;
456 WCHAR *app_nameW = NULL, *cmd_lineW = NULL, *cur_dirW = NULL;
457 UNICODE_STRING desktopW, titleW;
458 STARTUPINFOEXW infoW;
460 desktopW.Buffer = NULL;
461 titleW.Buffer = NULL;
462 if (app_name && !(app_nameW = file_name_AtoW( app_name, TRUE ))) goto done;
463 if (cmd_line && !(cmd_lineW = file_name_AtoW( cmd_line, TRUE ))) goto done;
464 if (cur_dir && !(cur_dirW = file_name_AtoW( cur_dir, TRUE ))) goto done;
466 if (startup_info->lpDesktop) RtlCreateUnicodeStringFromAsciiz( &desktopW, startup_info->lpDesktop );
467 if (startup_info->lpTitle) RtlCreateUnicodeStringFromAsciiz( &titleW, startup_info->lpTitle );
469 memcpy( &infoW.StartupInfo, startup_info, sizeof(infoW.StartupInfo) );
470 infoW.StartupInfo.lpDesktop = desktopW.Buffer;
471 infoW.StartupInfo.lpTitle = titleW.Buffer;
473 if (flags & EXTENDED_STARTUPINFO_PRESENT)
474 infoW.lpAttributeList = ((STARTUPINFOEXW *)startup_info)->lpAttributeList;
476 ret = CreateProcessInternalW( token, app_nameW, cmd_lineW, process_attr, thread_attr,
477 inherit, flags, env, cur_dirW, (STARTUPINFOW *)&infoW, info, new_token );
478 done:
479 RtlFreeHeap( GetProcessHeap(), 0, app_nameW );
480 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW );
481 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW );
482 RtlFreeUnicodeString( &desktopW );
483 RtlFreeUnicodeString( &titleW );
484 return ret;
487 /**********************************************************************
488 * CreateProcessInternalW (kernelbase.@)
490 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line,
491 SECURITY_ATTRIBUTES *process_attr,
492 SECURITY_ATTRIBUTES *thread_attr,
493 BOOL inherit, DWORD flags, void *env,
494 const WCHAR *cur_dir, STARTUPINFOW *startup_info,
495 PROCESS_INFORMATION *info, HANDLE *new_token )
497 const struct proc_thread_attr *handle_list = NULL, *job_list = NULL;
498 WCHAR name[MAX_PATH];
499 WCHAR *p, *tidy_cmdline = cmd_line;
500 RTL_USER_PROCESS_PARAMETERS *params = NULL;
501 RTL_USER_PROCESS_INFORMATION rtl_info;
502 HANDLE parent = 0, debug = 0;
503 ULONG nt_flags = 0;
504 NTSTATUS status;
506 /* Process the AppName and/or CmdLine to get module name and path */
508 TRACE( "app %s cmdline %s\n", debugstr_w(app_name), debugstr_w(cmd_line) );
510 if (new_token) FIXME( "No support for returning created process token\n" );
512 if (app_name)
514 if (!cmd_line || !cmd_line[0]) /* no command-line, create one */
516 if (!(tidy_cmdline = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name)+3) * sizeof(WCHAR) )))
517 return FALSE;
518 swprintf( tidy_cmdline, lstrlenW(app_name) + 3, L"\"%s\"", app_name );
521 else
523 if (!(tidy_cmdline = get_file_name( cmd_line, name, ARRAY_SIZE(name) ))) return FALSE;
524 app_name = name;
527 /* Warn if unsupported features are used */
529 if (flags & (IDLE_PRIORITY_CLASS | HIGH_PRIORITY_CLASS | REALTIME_PRIORITY_CLASS |
530 CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW |
531 PROFILE_USER | PROFILE_KERNEL | PROFILE_SERVER))
532 WARN( "(%s,...): ignoring some flags in %x\n", debugstr_w(app_name), flags );
534 if (cur_dir)
536 DWORD attr = GetFileAttributesW( cur_dir );
537 if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY))
539 status = STATUS_NOT_A_DIRECTORY;
540 goto done;
544 info->hThread = info->hProcess = 0;
545 info->dwProcessId = info->dwThreadId = 0;
547 if (!(params = create_process_params( app_name, tidy_cmdline, cur_dir, env, flags, startup_info )))
549 status = STATUS_NO_MEMORY;
550 goto done;
553 if (flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
555 if ((status = DbgUiConnectToDbg())) goto done;
556 debug = DbgUiGetThreadDebugObject();
559 if (flags & EXTENDED_STARTUPINFO_PRESENT)
561 struct _PROC_THREAD_ATTRIBUTE_LIST *attrs =
562 (struct _PROC_THREAD_ATTRIBUTE_LIST *)((STARTUPINFOEXW *)startup_info)->lpAttributeList;
563 unsigned int i;
565 if (attrs)
567 for (i = 0; i < attrs->count; ++i)
569 switch(attrs->attrs[i].attr)
571 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:
572 parent = *(HANDLE *)attrs->attrs[i].value;
573 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent);
574 if (!parent)
576 status = STATUS_INVALID_HANDLE;
577 goto done;
579 break;
580 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST:
581 handle_list = &attrs->attrs[i];
582 TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs->attrs[i].size / sizeof(HANDLE));
583 break;
584 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE:
586 struct pseudo_console *console = attrs->attrs[i].value;
587 TRACE( "PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE %p reference %p\n",
588 console, console->reference );
589 params->ConsoleHandle = console->reference;
590 break;
592 case PROC_THREAD_ATTRIBUTE_JOB_LIST:
593 job_list = &attrs->attrs[i];
594 TRACE( "PROC_THREAD_ATTRIBUTE_JOB_LIST handle count %Iu.\n",
595 attrs->attrs[i].size / sizeof(HANDLE) );
596 break;
597 default:
598 FIXME("Unsupported attribute %#Ix.\n", attrs->attrs[i].attr);
599 break;
605 if (inherit) nt_flags |= PROCESS_CREATE_FLAGS_INHERIT_HANDLES;
606 if (flags & DEBUG_ONLY_THIS_PROCESS) nt_flags |= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT;
607 if (flags & CREATE_BREAKAWAY_FROM_JOB) nt_flags |= PROCESS_CREATE_FLAGS_BREAKAWAY;
608 if (flags & CREATE_SUSPENDED) nt_flags |= PROCESS_CREATE_FLAGS_SUSPENDED;
610 status = create_nt_process( token, debug, process_attr, thread_attr,
611 nt_flags, params, &rtl_info, parent, handle_list, job_list );
612 switch (status)
614 case STATUS_SUCCESS:
615 break;
616 case STATUS_INVALID_IMAGE_WIN_16:
617 case STATUS_INVALID_IMAGE_NE_FORMAT:
618 case STATUS_INVALID_IMAGE_PROTECT:
619 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name) );
620 status = create_vdm_process( token, debug, process_attr, thread_attr,
621 nt_flags, params, &rtl_info );
622 break;
623 case STATUS_INVALID_IMAGE_NOT_MZ:
624 /* check for .com or .bat extension */
625 if (!(p = wcsrchr( app_name, '.' ))) break;
626 if (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" ))
628 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name) );
629 status = create_vdm_process( token, debug, process_attr, thread_attr,
630 nt_flags, params, &rtl_info );
632 else if (!wcsicmp( p, L".bat" ) || !wcsicmp( p, L".cmd" ))
634 TRACE( "starting %s as batch binary\n", debugstr_w(app_name) );
635 status = create_cmd_process( token, debug, process_attr, thread_attr,
636 nt_flags, params, &rtl_info );
638 break;
641 if (!status)
643 info->hProcess = rtl_info.Process;
644 info->hThread = rtl_info.Thread;
645 info->dwProcessId = HandleToUlong( rtl_info.ClientId.UniqueProcess );
646 info->dwThreadId = HandleToUlong( rtl_info.ClientId.UniqueThread );
647 if (!(flags & CREATE_SUSPENDED)) NtResumeThread( rtl_info.Thread, NULL );
648 TRACE( "started process pid %04x tid %04x\n", info->dwProcessId, info->dwThreadId );
651 done:
652 RtlDestroyProcessParameters( params );
653 if (tidy_cmdline != cmd_line) HeapFree( GetProcessHeap(), 0, tidy_cmdline );
654 return set_ntstatus( status );
658 /**********************************************************************
659 * CreateProcessA (kernelbase.@)
661 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA( const char *app_name, char *cmd_line,
662 SECURITY_ATTRIBUTES *process_attr,
663 SECURITY_ATTRIBUTES *thread_attr, BOOL inherit,
664 DWORD flags, void *env, const char *cur_dir,
665 STARTUPINFOA *startup_info, PROCESS_INFORMATION *info )
667 return CreateProcessInternalA( NULL, app_name, cmd_line, process_attr, thread_attr,
668 inherit, flags, env, cur_dir, startup_info, info, NULL );
672 /**********************************************************************
673 * CreateProcessW (kernelbase.@)
675 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW( const WCHAR *app_name, WCHAR *cmd_line,
676 SECURITY_ATTRIBUTES *process_attr,
677 SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags,
678 void *env, const WCHAR *cur_dir, STARTUPINFOW *startup_info,
679 PROCESS_INFORMATION *info )
681 return CreateProcessInternalW( NULL, app_name, cmd_line, process_attr, thread_attr,
682 inherit, flags, env, cur_dir, startup_info, info, NULL );
686 /*********************************************************************
687 * DuplicateHandle (kernelbase.@)
689 BOOL WINAPI DECLSPEC_HOTPATCH DuplicateHandle( HANDLE source_process, HANDLE source,
690 HANDLE dest_process, HANDLE *dest,
691 DWORD access, BOOL inherit, DWORD options )
693 return set_ntstatus( NtDuplicateObject( source_process, source, dest_process, dest,
694 access, inherit ? OBJ_INHERIT : 0, options ));
698 /****************************************************************************
699 * FlushInstructionCache (kernelbase.@)
701 BOOL WINAPI DECLSPEC_HOTPATCH FlushInstructionCache( HANDLE process, LPCVOID addr, SIZE_T size )
703 return set_ntstatus( NtFlushInstructionCache( process, addr, size ));
707 /***********************************************************************
708 * GetApplicationRestartSettings (kernelbase.@)
710 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ GetApplicationRestartSettings( HANDLE process, WCHAR *cmdline,
711 DWORD *size, DWORD *flags )
713 FIXME( "%p, %p, %p, %p)\n", process, cmdline, size, flags );
714 return E_NOTIMPL;
718 /***********************************************************************
719 * GetCurrentProcess (kernelbase.@)
721 HANDLE WINAPI kernelbase_GetCurrentProcess(void)
723 return (HANDLE)~(ULONG_PTR)0;
727 /***********************************************************************
728 * GetCurrentProcessId (kernelbase.@)
730 DWORD WINAPI kernelbase_GetCurrentProcessId(void)
732 return HandleToULong( NtCurrentTeb()->ClientId.UniqueProcess );
736 /***********************************************************************
737 * GetErrorMode (kernelbase.@)
739 UINT WINAPI DECLSPEC_HOTPATCH GetErrorMode(void)
741 UINT mode;
743 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode,
744 &mode, sizeof(mode), NULL );
745 return mode;
749 /***********************************************************************
750 * GetExitCodeProcess (kernelbase.@)
752 BOOL WINAPI DECLSPEC_HOTPATCH GetExitCodeProcess( HANDLE process, LPDWORD exit_code )
754 NTSTATUS status;
755 PROCESS_BASIC_INFORMATION pbi;
757 status = NtQueryInformationProcess( process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
758 if (!status && exit_code) *exit_code = pbi.ExitStatus;
759 return set_ntstatus( status );
763 /*********************************************************************
764 * GetHandleInformation (kernelbase.@)
766 BOOL WINAPI DECLSPEC_HOTPATCH GetHandleInformation( HANDLE handle, DWORD *flags )
768 OBJECT_DATA_INFORMATION info;
770 if (!set_ntstatus( NtQueryObject( handle, ObjectDataInformation, &info, sizeof(info), NULL )))
771 return FALSE;
773 if (flags)
775 *flags = 0;
776 if (info.InheritHandle) *flags |= HANDLE_FLAG_INHERIT;
777 if (info.ProtectFromClose) *flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
779 return TRUE;
783 /***********************************************************************
784 * GetPriorityClass (kernelbase.@)
786 DWORD WINAPI DECLSPEC_HOTPATCH GetPriorityClass( HANDLE process )
788 PROCESS_BASIC_INFORMATION pbi;
790 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation,
791 &pbi, sizeof(pbi), NULL )))
792 return 0;
794 switch (pbi.BasePriority)
796 case PROCESS_PRIOCLASS_IDLE: return IDLE_PRIORITY_CLASS;
797 case PROCESS_PRIOCLASS_BELOW_NORMAL: return BELOW_NORMAL_PRIORITY_CLASS;
798 case PROCESS_PRIOCLASS_NORMAL: return NORMAL_PRIORITY_CLASS;
799 case PROCESS_PRIOCLASS_ABOVE_NORMAL: return ABOVE_NORMAL_PRIORITY_CLASS;
800 case PROCESS_PRIOCLASS_HIGH: return HIGH_PRIORITY_CLASS;
801 case PROCESS_PRIOCLASS_REALTIME: return REALTIME_PRIORITY_CLASS;
802 default: return 0;
807 /***********************************************************************
808 * GetProcessGroupAffinity (kernelbase.@)
810 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessGroupAffinity( HANDLE process, USHORT *count, USHORT *array )
812 FIXME( "(%p,%p,%p): stub\n", process, count, array );
813 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
814 return FALSE;
818 /******************************************************************
819 * GetProcessHandleCount (kernelbase.@)
821 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessHandleCount( HANDLE process, DWORD *count )
823 return set_ntstatus( NtQueryInformationProcess( process, ProcessHandleCount,
824 count, sizeof(*count), NULL ));
828 /***********************************************************************
829 * GetProcessHeap (kernelbase.@)
831 HANDLE WINAPI kernelbase_GetProcessHeap(void)
833 return NtCurrentTeb()->Peb->ProcessHeap;
837 /*********************************************************************
838 * GetProcessId (kernelbase.@)
840 DWORD WINAPI DECLSPEC_HOTPATCH GetProcessId( HANDLE process )
842 PROCESS_BASIC_INFORMATION pbi;
844 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation,
845 &pbi, sizeof(pbi), NULL )))
846 return 0;
847 return pbi.UniqueProcessId;
851 /**********************************************************************
852 * GetProcessMitigationPolicy (kernelbase.@)
854 BOOL WINAPI /* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process, PROCESS_MITIGATION_POLICY policy,
855 void *buffer, SIZE_T length )
857 FIXME( "(%p, %u, %p, %lu): stub\n", process, policy, buffer, length );
858 return TRUE;
862 /***********************************************************************
863 * GetProcessPriorityBoost (kernelbase.@)
865 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessPriorityBoost( HANDLE process, PBOOL disable )
867 FIXME( "(%p,%p): semi-stub\n", process, disable );
868 *disable = FALSE; /* report that no boost is present */
869 return TRUE;
873 /***********************************************************************
874 * GetProcessShutdownParameters (kernelbase.@)
876 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessShutdownParameters( LPDWORD level, LPDWORD flags )
878 *level = shutdown_priority;
879 *flags = shutdown_flags;
880 return TRUE;
884 /*********************************************************************
885 * GetProcessTimes (kernelbase.@)
887 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessTimes( HANDLE process, FILETIME *create, FILETIME *exit,
888 FILETIME *kernel, FILETIME *user )
890 KERNEL_USER_TIMES time;
892 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessTimes, &time, sizeof(time), NULL )))
893 return FALSE;
895 create->dwLowDateTime = time.CreateTime.u.LowPart;
896 create->dwHighDateTime = time.CreateTime.u.HighPart;
897 exit->dwLowDateTime = time.ExitTime.u.LowPart;
898 exit->dwHighDateTime = time.ExitTime.u.HighPart;
899 kernel->dwLowDateTime = time.KernelTime.u.LowPart;
900 kernel->dwHighDateTime = time.KernelTime.u.HighPart;
901 user->dwLowDateTime = time.UserTime.u.LowPart;
902 user->dwHighDateTime = time.UserTime.u.HighPart;
903 return TRUE;
907 /***********************************************************************
908 * GetProcessVersion (kernelbase.@)
910 DWORD WINAPI DECLSPEC_HOTPATCH GetProcessVersion( DWORD pid )
912 SECTION_IMAGE_INFORMATION info;
913 NTSTATUS status;
914 HANDLE process;
916 if (pid && pid != GetCurrentProcessId())
918 if (!(process = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid ))) return 0;
919 status = NtQueryInformationProcess( process, ProcessImageInformation, &info, sizeof(info), NULL );
920 CloseHandle( process );
922 else status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation,
923 &info, sizeof(info), NULL );
925 if (!set_ntstatus( status )) return 0;
926 return MAKELONG( info.MinorSubsystemVersion, info.MajorSubsystemVersion );
930 /***********************************************************************
931 * GetProcessWorkingSetSizeEx (kernelbase.@)
933 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessWorkingSetSizeEx( HANDLE process, SIZE_T *minset,
934 SIZE_T *maxset, DWORD *flags)
936 FIXME( "(%p,%p,%p,%p): stub\n", process, minset, maxset, flags );
937 /* 32 MB working set size */
938 if (minset) *minset = 32*1024*1024;
939 if (maxset) *maxset = 32*1024*1024;
940 if (flags) *flags = QUOTA_LIMITS_HARDWS_MIN_DISABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE;
941 return TRUE;
945 /******************************************************************************
946 * IsProcessInJob (kernelbase.@)
948 BOOL WINAPI DECLSPEC_HOTPATCH IsProcessInJob( HANDLE process, HANDLE job, BOOL *result )
950 NTSTATUS status = NtIsProcessInJob( process, job );
952 switch (status)
954 case STATUS_PROCESS_IN_JOB:
955 *result = TRUE;
956 return TRUE;
957 case STATUS_PROCESS_NOT_IN_JOB:
958 *result = FALSE;
959 return TRUE;
960 default:
961 return set_ntstatus( status );
966 /***********************************************************************
967 * IsProcessorFeaturePresent (kernelbase.@)
969 BOOL WINAPI DECLSPEC_HOTPATCH IsProcessorFeaturePresent ( DWORD feature )
971 return RtlIsProcessorFeaturePresent( feature );
975 /**********************************************************************
976 * IsWow64Process2 (kernelbase.@)
978 BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process2( HANDLE process, USHORT *machine, USHORT *native_machine )
980 return set_ntstatus( RtlWow64GetProcessMachines( process, machine, native_machine ));
984 /**********************************************************************
985 * IsWow64Process (kernelbase.@)
987 BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process( HANDLE process, PBOOL wow64 )
989 ULONG_PTR pbi;
990 NTSTATUS status;
992 status = NtQueryInformationProcess( process, ProcessWow64Information, &pbi, sizeof(pbi), NULL );
993 if (!status) *wow64 = !!pbi;
994 return set_ntstatus( status );
998 /*********************************************************************
999 * OpenProcess (kernelbase.@)
1001 HANDLE WINAPI DECLSPEC_HOTPATCH OpenProcess( DWORD access, BOOL inherit, DWORD id )
1003 HANDLE handle;
1004 OBJECT_ATTRIBUTES attr;
1005 CLIENT_ID cid;
1007 if (GetVersion() & 0x80000000) access = PROCESS_ALL_ACCESS;
1009 attr.Length = sizeof(OBJECT_ATTRIBUTES);
1010 attr.RootDirectory = 0;
1011 attr.Attributes = inherit ? OBJ_INHERIT : 0;
1012 attr.ObjectName = NULL;
1013 attr.SecurityDescriptor = NULL;
1014 attr.SecurityQualityOfService = NULL;
1016 cid.UniqueProcess = ULongToHandle(id);
1017 cid.UniqueThread = 0;
1019 if (!set_ntstatus( NtOpenProcess( &handle, access, &attr, &cid ))) return NULL;
1020 return handle;
1024 /***********************************************************************
1025 * ProcessIdToSessionId (kernelbase.@)
1027 BOOL WINAPI DECLSPEC_HOTPATCH ProcessIdToSessionId( DWORD pid, DWORD *id )
1029 HANDLE process;
1030 NTSTATUS status;
1032 if (pid == GetCurrentProcessId())
1034 *id = NtCurrentTeb()->Peb->SessionId;
1035 return TRUE;
1037 if (!(process = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid ))) return FALSE;
1038 status = NtQueryInformationProcess( process, ProcessSessionInformation, id, sizeof(*id), NULL );
1039 CloseHandle( process );
1040 return set_ntstatus( status );
1044 /***********************************************************************
1045 * QueryProcessCycleTime (kernelbase.@)
1047 BOOL WINAPI DECLSPEC_HOTPATCH QueryProcessCycleTime( HANDLE process, ULONG64 *cycle )
1049 static int once;
1050 if (!once++) FIXME( "(%p,%p): stub!\n", process, cycle );
1051 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1052 return FALSE;
1056 /***********************************************************************
1057 * SetErrorMode (kernelbase.@)
1059 UINT WINAPI DECLSPEC_HOTPATCH SetErrorMode( UINT mode )
1061 UINT old = GetErrorMode();
1063 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode,
1064 &mode, sizeof(mode) );
1065 return old;
1069 /*************************************************************************
1070 * SetHandleCount (kernelbase.@)
1072 UINT WINAPI DECLSPEC_HOTPATCH SetHandleCount( UINT count )
1074 return count;
1078 /*********************************************************************
1079 * SetHandleInformation (kernelbase.@)
1081 BOOL WINAPI DECLSPEC_HOTPATCH SetHandleInformation( HANDLE handle, DWORD mask, DWORD flags )
1083 OBJECT_DATA_INFORMATION info;
1085 /* if not setting both fields, retrieve current value first */
1086 if ((mask & (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE)) !=
1087 (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE))
1089 if (!set_ntstatus( NtQueryObject( handle, ObjectDataInformation, &info, sizeof(info), NULL )))
1090 return FALSE;
1092 if (mask & HANDLE_FLAG_INHERIT)
1093 info.InheritHandle = (flags & HANDLE_FLAG_INHERIT) != 0;
1094 if (mask & HANDLE_FLAG_PROTECT_FROM_CLOSE)
1095 info.ProtectFromClose = (flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0;
1097 return set_ntstatus( NtSetInformationObject( handle, ObjectDataInformation, &info, sizeof(info) ));
1101 /***********************************************************************
1102 * SetPriorityClass (kernelbase.@)
1104 BOOL WINAPI DECLSPEC_HOTPATCH SetPriorityClass( HANDLE process, DWORD class )
1106 PROCESS_PRIORITY_CLASS ppc;
1108 ppc.Foreground = FALSE;
1109 switch (class)
1111 case IDLE_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_IDLE; break;
1112 case BELOW_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_BELOW_NORMAL; break;
1113 case NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_NORMAL; break;
1114 case ABOVE_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_ABOVE_NORMAL; break;
1115 case HIGH_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_HIGH; break;
1116 case REALTIME_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_REALTIME; break;
1117 default:
1118 SetLastError( ERROR_INVALID_PARAMETER );
1119 return FALSE;
1121 return set_ntstatus( NtSetInformationProcess( process, ProcessPriorityClass, &ppc, sizeof(ppc) ));
1125 /***********************************************************************
1126 * SetProcessAffinityUpdateMode (kernelbase.@)
1128 BOOL WINAPI DECLSPEC_HOTPATCH SetProcessAffinityUpdateMode( HANDLE process, DWORD flags )
1130 FIXME( "(%p,0x%08x): stub\n", process, flags );
1131 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1132 return FALSE;
1136 /**********************************************************************
1137 * SetProcessMitigationPolicy (kernelbase.@)
1139 BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy,
1140 void *buffer, SIZE_T length )
1142 FIXME( "(%d, %p, %lu): stub\n", policy, buffer, length );
1143 return TRUE;
1147 /***********************************************************************
1148 * SetProcessPriorityBoost (kernelbase.@)
1150 BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process, BOOL disable )
1152 FIXME( "(%p,%d): stub\n", process, disable );
1153 return TRUE;
1157 /***********************************************************************
1158 * SetProcessShutdownParameters (kernelbase.@)
1160 BOOL WINAPI DECLSPEC_HOTPATCH SetProcessShutdownParameters( DWORD level, DWORD flags )
1162 FIXME( "(%08x, %08x): partial stub.\n", level, flags );
1163 shutdown_flags = flags;
1164 shutdown_priority = level;
1165 return TRUE;
1169 /***********************************************************************
1170 * SetProcessWorkingSetSizeEx (kernelbase.@)
1172 BOOL WINAPI DECLSPEC_HOTPATCH SetProcessWorkingSetSizeEx( HANDLE process, SIZE_T minset,
1173 SIZE_T maxset, DWORD flags )
1175 return TRUE;
1179 /******************************************************************************
1180 * TerminateProcess (kernelbase.@)
1182 BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code )
1184 if (!handle)
1186 SetLastError( ERROR_INVALID_HANDLE );
1187 return FALSE;
1189 return set_ntstatus( NtTerminateProcess( handle, exit_code ));
1193 /***********************************************************************
1194 * Process startup information
1195 ***********************************************************************/
1198 static STARTUPINFOW startup_infoW;
1199 static char *command_lineA;
1200 static WCHAR *command_lineW;
1202 /******************************************************************
1203 * init_startup_info
1205 void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params )
1207 ANSI_STRING ansi;
1209 startup_infoW.cb = sizeof(startup_infoW);
1210 startup_infoW.lpReserved = NULL;
1211 startup_infoW.lpDesktop = params->Desktop.Buffer;
1212 startup_infoW.lpTitle = params->WindowTitle.Buffer;
1213 startup_infoW.dwX = params->dwX;
1214 startup_infoW.dwY = params->dwY;
1215 startup_infoW.dwXSize = params->dwXSize;
1216 startup_infoW.dwYSize = params->dwYSize;
1217 startup_infoW.dwXCountChars = params->dwXCountChars;
1218 startup_infoW.dwYCountChars = params->dwYCountChars;
1219 startup_infoW.dwFillAttribute = params->dwFillAttribute;
1220 startup_infoW.dwFlags = params->dwFlags;
1221 startup_infoW.wShowWindow = params->wShowWindow;
1222 startup_infoW.cbReserved2 = params->RuntimeInfo.MaximumLength;
1223 startup_infoW.lpReserved2 = params->RuntimeInfo.MaximumLength ? (void *)params->RuntimeInfo.Buffer : NULL;
1224 startup_infoW.hStdInput = params->hStdInput ? params->hStdInput : INVALID_HANDLE_VALUE;
1225 startup_infoW.hStdOutput = params->hStdOutput ? params->hStdOutput : INVALID_HANDLE_VALUE;
1226 startup_infoW.hStdError = params->hStdError ? params->hStdError : INVALID_HANDLE_VALUE;
1228 command_lineW = params->CommandLine.Buffer;
1229 if (!RtlUnicodeStringToAnsiString( &ansi, &params->CommandLine, TRUE )) command_lineA = ansi.Buffer;
1233 /**********************************************************************
1234 * BaseFlushAppcompatCache (kernelbase.@)
1236 BOOL WINAPI BaseFlushAppcompatCache(void)
1238 FIXME( "stub\n" );
1239 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1240 return FALSE;
1244 /***********************************************************************
1245 * GetCommandLineA (kernelbase.@)
1247 LPSTR WINAPI GetCommandLineA(void)
1249 return command_lineA;
1253 /***********************************************************************
1254 * GetCommandLineW (kernelbase.@)
1256 LPWSTR WINAPI GetCommandLineW(void)
1258 return command_lineW;
1262 /***********************************************************************
1263 * GetStartupInfoW (kernelbase.@)
1265 void WINAPI DECLSPEC_HOTPATCH GetStartupInfoW( STARTUPINFOW *info )
1267 *info = startup_infoW;
1271 /***********************************************************************
1272 * GetStdHandle (kernelbase.@)
1274 HANDLE WINAPI DECLSPEC_HOTPATCH GetStdHandle( DWORD std_handle )
1276 switch (std_handle)
1278 case STD_INPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdInput;
1279 case STD_OUTPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdOutput;
1280 case STD_ERROR_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdError;
1282 SetLastError( ERROR_INVALID_HANDLE );
1283 return INVALID_HANDLE_VALUE;
1287 /***********************************************************************
1288 * SetStdHandle (kernelbase.@)
1290 BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle( DWORD std_handle, HANDLE handle )
1292 switch (std_handle)
1294 case STD_INPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdInput = handle; return TRUE;
1295 case STD_OUTPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdOutput = handle; return TRUE;
1296 case STD_ERROR_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdError = handle; return TRUE;
1298 SetLastError( ERROR_INVALID_HANDLE );
1299 return FALSE;
1303 /***********************************************************************
1304 * SetStdHandleEx (kernelbase.@)
1306 BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandleEx( DWORD std_handle, HANDLE handle, HANDLE *prev )
1308 HANDLE *ptr;
1310 switch (std_handle)
1312 case STD_INPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdInput; break;
1313 case STD_OUTPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; break;
1314 case STD_ERROR_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdError; break;
1315 default:
1316 SetLastError( ERROR_INVALID_HANDLE );
1317 return FALSE;
1319 if (prev) *prev = *ptr;
1320 *ptr = handle;
1321 return TRUE;
1325 /***********************************************************************
1326 * Process environment
1327 ***********************************************************************/
1330 static inline SIZE_T get_env_length( const WCHAR *env )
1332 const WCHAR *end = env;
1333 while (*end) end += lstrlenW(end) + 1;
1334 return end + 1 - env;
1337 /***********************************************************************
1338 * ExpandEnvironmentStringsA (kernelbase.@)
1340 DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, DWORD count )
1342 UNICODE_STRING us_src;
1343 PWSTR dstW = NULL;
1344 DWORD ret;
1346 RtlCreateUnicodeStringFromAsciiz( &us_src, src );
1347 if (count)
1349 if (!(dstW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR)))) return 0;
1350 ret = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count);
1351 if (ret) WideCharToMultiByte( CP_ACP, 0, dstW, ret, dst, count, NULL, NULL );
1353 else ret = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0 );
1355 RtlFreeUnicodeString( &us_src );
1356 HeapFree( GetProcessHeap(), 0, dstW );
1357 return ret;
1361 /***********************************************************************
1362 * ExpandEnvironmentStringsW (kernelbase.@)
1364 DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len )
1366 UNICODE_STRING us_src, us_dst;
1367 NTSTATUS status;
1368 DWORD res;
1370 TRACE( "(%s %p %u)\n", debugstr_w(src), dst, len );
1372 RtlInitUnicodeString( &us_src, src );
1374 /* make sure we don't overflow the maximum UNICODE_STRING size */
1375 len = min( len, UNICODE_STRING_MAX_CHARS );
1377 us_dst.Length = 0;
1378 us_dst.MaximumLength = len * sizeof(WCHAR);
1379 us_dst.Buffer = dst;
1381 res = 0;
1382 status = RtlExpandEnvironmentStrings_U( NULL, &us_src, &us_dst, &res );
1383 res /= sizeof(WCHAR);
1384 if (!set_ntstatus( status ))
1386 if (status != STATUS_BUFFER_TOO_SMALL) return 0;
1387 if (len && dst) dst[len - 1] = 0;
1389 return res;
1393 /***********************************************************************
1394 * GetEnvironmentStrings (kernelbase.@)
1395 * GetEnvironmentStringsA (kernelbase.@)
1397 LPSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsA(void)
1399 LPWSTR env;
1400 LPSTR ret;
1401 SIZE_T lenA, lenW;
1403 RtlAcquirePebLock();
1404 env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
1405 lenW = get_env_length( env );
1406 lenA = WideCharToMultiByte( CP_ACP, 0, env, lenW, NULL, 0, NULL, NULL );
1407 if ((ret = HeapAlloc( GetProcessHeap(), 0, lenA )))
1408 WideCharToMultiByte( CP_ACP, 0, env, lenW, ret, lenA, NULL, NULL );
1409 RtlReleasePebLock();
1410 return ret;
1414 /***********************************************************************
1415 * GetEnvironmentStringsW (kernelbase.@)
1417 LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void)
1419 LPWSTR ret;
1420 SIZE_T len;
1422 RtlAcquirePebLock();
1423 len = get_env_length( NtCurrentTeb()->Peb->ProcessParameters->Environment ) * sizeof(WCHAR);
1424 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
1425 memcpy( ret, NtCurrentTeb()->Peb->ProcessParameters->Environment, len );
1426 RtlReleasePebLock();
1427 return ret;
1431 /***********************************************************************
1432 * SetEnvironmentStringsA (kernelbase.@)
1434 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsA( char *env )
1436 WCHAR *envW;
1437 const char *p = env;
1438 DWORD len;
1439 BOOL ret;
1441 for (p = env; *p; p += strlen( p ) + 1);
1443 len = MultiByteToWideChar( CP_ACP, 0, env, p - env, NULL, 0 );
1444 if (!(envW = HeapAlloc( GetProcessHeap(), 0, len )))
1446 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1447 return FALSE;
1449 MultiByteToWideChar( CP_ACP, 0, env, p - env, envW, len );
1450 ret = SetEnvironmentStringsW( envW );
1451 HeapFree( GetProcessHeap(), 0, envW );
1452 return ret;
1456 /***********************************************************************
1457 * SetEnvironmentStringsW (kernelbase.@)
1459 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsW( WCHAR *env )
1461 WCHAR *p;
1462 WCHAR *new_env;
1463 NTSTATUS status;
1465 for (p = env; *p; p += wcslen( p ) + 1)
1467 const WCHAR *eq = wcschr( p, '=' );
1468 if (!eq || eq == p)
1470 SetLastError( ERROR_INVALID_PARAMETER );
1471 return FALSE;
1475 if ((status = RtlCreateEnvironment( FALSE, &new_env )))
1476 return set_ntstatus( status );
1478 for (p = env; *p; p += wcslen( p ) + 1)
1480 const WCHAR *eq = wcschr( p, '=' );
1481 UNICODE_STRING var, value;
1482 var.Buffer = p;
1483 var.Length = (eq - p) * sizeof(WCHAR);
1484 RtlInitUnicodeString( &value, eq + 1 );
1485 if ((status = RtlSetEnvironmentVariable( &new_env, &var, &value )))
1487 RtlDestroyEnvironment( new_env );
1488 return set_ntstatus( status );
1492 RtlSetCurrentEnvironment( new_env, NULL );
1493 return TRUE;
1497 /***********************************************************************
1498 * GetEnvironmentVariableA (kernelbase.@)
1500 DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size )
1502 UNICODE_STRING us_name, us_value;
1503 PWSTR valueW;
1504 NTSTATUS status;
1505 DWORD len, ret;
1507 /* limit the size to sane values */
1508 size = min( size, 32767 );
1509 if (!(valueW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0;
1511 RtlCreateUnicodeStringFromAsciiz( &us_name, name );
1512 us_value.Length = 0;
1513 us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR);
1514 us_value.Buffer = valueW;
1516 status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value );
1517 len = us_value.Length / sizeof(WCHAR);
1518 if (status == STATUS_BUFFER_TOO_SMALL) ret = len + 1;
1519 else if (!set_ntstatus( status )) ret = 0;
1520 else if (!size) ret = len + 1;
1521 else
1523 if (len) WideCharToMultiByte( CP_ACP, 0, valueW, len + 1, value, size, NULL, NULL );
1524 value[len] = 0;
1525 ret = len;
1528 RtlFreeUnicodeString( &us_name );
1529 HeapFree( GetProcessHeap(), 0, valueW );
1530 return ret;
1534 /***********************************************************************
1535 * GetEnvironmentVariableW (kernelbase.@)
1537 DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size )
1539 UNICODE_STRING us_name, us_value;
1540 NTSTATUS status;
1541 DWORD len;
1543 TRACE( "(%s %p %u)\n", debugstr_w(name), val, size );
1545 RtlInitUnicodeString( &us_name, name );
1546 us_value.Length = 0;
1547 us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR);
1548 us_value.Buffer = val;
1550 status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value );
1551 len = us_value.Length / sizeof(WCHAR);
1552 if (status == STATUS_BUFFER_TOO_SMALL) return len + 1;
1553 if (!set_ntstatus( status )) return 0;
1554 if (!size) return len + 1;
1555 val[len] = 0;
1556 return len;
1560 /***********************************************************************
1561 * FreeEnvironmentStringsA (kernelbase.@)
1562 * FreeEnvironmentStringsW (kernelbase.@)
1564 BOOL WINAPI DECLSPEC_HOTPATCH FreeEnvironmentStringsW( LPWSTR ptr )
1566 return HeapFree( GetProcessHeap(), 0, ptr );
1570 /***********************************************************************
1571 * SetEnvironmentVariableA (kernelbase.@)
1573 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
1575 UNICODE_STRING us_name, us_value;
1576 BOOL ret;
1578 if (!name)
1580 SetLastError( ERROR_ENVVAR_NOT_FOUND );
1581 return FALSE;
1584 RtlCreateUnicodeStringFromAsciiz( &us_name, name );
1585 if (value)
1587 RtlCreateUnicodeStringFromAsciiz( &us_value, value );
1588 ret = SetEnvironmentVariableW( us_name.Buffer, us_value.Buffer );
1589 RtlFreeUnicodeString( &us_value );
1591 else ret = SetEnvironmentVariableW( us_name.Buffer, NULL );
1592 RtlFreeUnicodeString( &us_name );
1593 return ret;
1597 /***********************************************************************
1598 * SetEnvironmentVariableW (kernelbase.@)
1600 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value )
1602 UNICODE_STRING us_name, us_value;
1603 NTSTATUS status;
1605 TRACE( "(%s %s)\n", debugstr_w(name), debugstr_w(value) );
1607 if (!name)
1609 SetLastError( ERROR_ENVVAR_NOT_FOUND );
1610 return FALSE;
1613 RtlInitUnicodeString( &us_name, name );
1614 if (value)
1616 RtlInitUnicodeString( &us_value, value );
1617 status = RtlSetEnvironmentVariable( NULL, &us_name, &us_value );
1619 else status = RtlSetEnvironmentVariable( NULL, &us_name, NULL );
1621 return set_ntstatus( status );
1625 /***********************************************************************
1626 * Process/thread attribute lists
1627 ***********************************************************************/
1629 /***********************************************************************
1630 * InitializeProcThreadAttributeList (kernelbase.@)
1632 BOOL WINAPI DECLSPEC_HOTPATCH InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list,
1633 DWORD count, DWORD flags, SIZE_T *size )
1635 SIZE_T needed;
1636 BOOL ret = FALSE;
1638 TRACE( "(%p %d %x %p)\n", list, count, flags, size );
1640 needed = FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST, attrs[count] );
1641 if (list && *size >= needed)
1643 list->mask = 0;
1644 list->size = count;
1645 list->count = 0;
1646 list->unk = 0;
1647 ret = TRUE;
1649 else SetLastError( ERROR_INSUFFICIENT_BUFFER );
1651 *size = needed;
1652 return ret;
1656 /***********************************************************************
1657 * UpdateProcThreadAttribute (kernelbase.@)
1659 BOOL WINAPI DECLSPEC_HOTPATCH UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST *list,
1660 DWORD flags, DWORD_PTR attr, void *value,
1661 SIZE_T size, void *prev_ret, SIZE_T *size_ret )
1663 DWORD mask;
1664 struct proc_thread_attr *entry;
1666 TRACE( "(%p %x %08lx %p %ld %p %p)\n", list, flags, attr, value, size, prev_ret, size_ret );
1668 if (list->count >= list->size)
1670 SetLastError( ERROR_GEN_FAILURE );
1671 return FALSE;
1674 switch (attr)
1676 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:
1677 if (size != sizeof(HANDLE))
1679 SetLastError( ERROR_BAD_LENGTH );
1680 return FALSE;
1682 break;
1684 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST:
1685 if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size)
1687 SetLastError( ERROR_BAD_LENGTH );
1688 return FALSE;
1690 break;
1692 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR:
1693 if (size != sizeof(PROCESSOR_NUMBER))
1695 SetLastError( ERROR_BAD_LENGTH );
1696 return FALSE;
1698 break;
1700 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY:
1701 if (size != sizeof(DWORD) && size != sizeof(DWORD64))
1703 SetLastError( ERROR_BAD_LENGTH );
1704 return FALSE;
1706 break;
1708 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY:
1709 if (size != sizeof(DWORD) && size != sizeof(DWORD64) && size != sizeof(DWORD64) * 2)
1711 SetLastError( ERROR_BAD_LENGTH );
1712 return FALSE;
1714 break;
1716 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE:
1717 if (size != sizeof(HPCON))
1719 SetLastError( ERROR_BAD_LENGTH );
1720 return FALSE;
1722 break;
1724 case PROC_THREAD_ATTRIBUTE_JOB_LIST:
1725 if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size)
1727 SetLastError( ERROR_BAD_LENGTH );
1728 return FALSE;
1730 break;
1732 default:
1733 SetLastError( ERROR_NOT_SUPPORTED );
1734 FIXME( "Unhandled attribute %lu\n", attr & PROC_THREAD_ATTRIBUTE_NUMBER );
1735 return FALSE;
1738 mask = 1 << (attr & PROC_THREAD_ATTRIBUTE_NUMBER);
1739 if (list->mask & mask)
1741 SetLastError( ERROR_OBJECT_NAME_EXISTS );
1742 return FALSE;
1744 list->mask |= mask;
1746 entry = list->attrs + list->count;
1747 entry->attr = attr;
1748 entry->size = size;
1749 entry->value = value;
1750 list->count++;
1751 return TRUE;
1755 /***********************************************************************
1756 * DeleteProcThreadAttributeList (kernelbase.@)
1758 void WINAPI DECLSPEC_HOTPATCH DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list )
1760 return;