libwine: Remove __wine_main_arg* from the public header.
[wine/zf.git] / dlls / kernelbase / process.c
blobb125f100f6e2c15bbcbc62530c2be095818c8d1a
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 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "winternl.h"
32 #include "kernelbase.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(process);
37 static DWORD shutdown_flags = 0;
38 static DWORD shutdown_priority = 0x280;
40 /***********************************************************************
41 * Processes
42 ***********************************************************************/
45 /***********************************************************************
46 * find_exe_file
48 static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, DWORD buflen )
50 WCHAR *load_path;
51 BOOL ret;
53 if (!set_ntstatus( RtlGetExePath( name, &load_path ))) return FALSE;
55 TRACE( "looking for %s in %s\n", debugstr_w(name), debugstr_w(load_path) );
57 ret = (SearchPathW( load_path, name, L".exe", buflen, buffer, NULL ) ||
58 /* not found, try without extension in case it is a Unix app */
59 SearchPathW( load_path, name, NULL, buflen, buffer, NULL ));
61 if (ret) /* make sure it can be opened, SearchPathW also returns directories */
63 HANDLE handle = CreateFileW( buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE,
64 NULL, OPEN_EXISTING, 0, 0 );
65 if ((ret = (handle != INVALID_HANDLE_VALUE))) CloseHandle( handle );
67 RtlReleasePath( load_path );
68 return ret;
72 /*************************************************************************
73 * get_file_name
75 * Helper for CreateProcess: retrieve the file name to load from the
76 * app name and command line. Store the file name in buffer, and
77 * return a possibly modified command line.
79 static WCHAR *get_file_name( WCHAR *cmdline, WCHAR *buffer, DWORD buflen )
81 WCHAR *name, *pos, *first_space, *ret = NULL;
82 const WCHAR *p;
84 /* first check for a quoted file name */
86 if (cmdline[0] == '"' && (p = wcschr( cmdline + 1, '"' )))
88 int len = p - cmdline - 1;
89 /* extract the quoted portion as file name */
90 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
91 memcpy( name, cmdline + 1, len * sizeof(WCHAR) );
92 name[len] = 0;
94 if (!find_exe_file( name, buffer, buflen )) goto done;
95 ret = cmdline; /* no change necessary */
96 goto done;
99 /* now try the command-line word by word */
101 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR) )))
102 return NULL;
103 pos = name;
104 p = cmdline;
105 first_space = NULL;
107 for (;;)
109 while (*p && *p != ' ' && *p != '\t') *pos++ = *p++;
110 *pos = 0;
111 if (find_exe_file( name, buffer, buflen ))
113 ret = cmdline;
114 break;
116 if (!first_space) first_space = pos;
117 if (!(*pos++ = *p++)) break;
120 if (!ret)
122 SetLastError( ERROR_FILE_NOT_FOUND );
124 else if (first_space) /* build a new command-line with quotes */
126 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline) + 3) * sizeof(WCHAR) )))
127 goto done;
128 swprintf( ret, lstrlenW(cmdline) + 3, L"\"%s\"%s", name, p );
131 done:
132 RtlFreeHeap( GetProcessHeap(), 0, name );
133 return ret;
137 /***********************************************************************
138 * create_process_params
140 static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename, const WCHAR *cmdline,
141 const WCHAR *cur_dir, void *env, DWORD flags,
142 const STARTUPINFOW *startup )
144 RTL_USER_PROCESS_PARAMETERS *params;
145 UNICODE_STRING imageW, dllpathW, curdirW, cmdlineW, titleW, desktopW, runtimeW, newdirW;
146 WCHAR imagepath[MAX_PATH];
147 WCHAR *load_path, *dummy, *envW = env;
149 if (!GetLongPathNameW( filename, imagepath, MAX_PATH )) lstrcpynW( imagepath, filename, MAX_PATH );
150 if (!GetFullPathNameW( imagepath, MAX_PATH, imagepath, NULL )) lstrcpynW( imagepath, filename, MAX_PATH );
152 if (env && !(flags & CREATE_UNICODE_ENVIRONMENT)) /* convert environment to unicode */
154 char *e = env;
155 DWORD lenW;
157 while (*e) e += strlen(e) + 1;
158 e++; /* final null */
159 lenW = MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, NULL, 0 );
160 if ((envW = RtlAllocateHeap( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
161 MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, envW, lenW );
164 newdirW.Buffer = NULL;
165 if (cur_dir)
167 if (RtlDosPathNameToNtPathName_U( cur_dir, &newdirW, NULL, NULL ))
168 cur_dir = newdirW.Buffer + 4; /* skip \??\ prefix */
169 else
170 cur_dir = NULL;
172 LdrGetDllPath( imagepath, LOAD_WITH_ALTERED_SEARCH_PATH, &load_path, &dummy );
173 RtlInitUnicodeString( &imageW, imagepath );
174 RtlInitUnicodeString( &dllpathW, load_path );
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, &dllpathW, cur_dir ? &curdirW : NULL,
182 &cmdlineW, envW, &titleW, &desktopW,
183 NULL, &runtimeW, PROCESS_PARAMS_FLAG_NORMALIZED ))
185 RtlReleasePath( load_path );
186 if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW );
187 return NULL;
189 RtlReleasePath( load_path );
191 if (flags & CREATE_NEW_PROCESS_GROUP) params->ConsoleFlags = 1;
192 if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = (HANDLE)1; /* KERNEL32_CONSOLE_ALLOC */
194 if (startup->dwFlags & STARTF_USESTDHANDLES)
196 params->hStdInput = startup->hStdInput;
197 params->hStdOutput = startup->hStdOutput;
198 params->hStdError = startup->hStdError;
200 else if (flags & DETACHED_PROCESS)
202 params->hStdInput = INVALID_HANDLE_VALUE;
203 params->hStdOutput = INVALID_HANDLE_VALUE;
204 params->hStdError = INVALID_HANDLE_VALUE;
206 else
208 params->hStdInput = NtCurrentTeb()->Peb->ProcessParameters->hStdInput;
209 params->hStdOutput = NtCurrentTeb()->Peb->ProcessParameters->hStdOutput;
210 params->hStdError = NtCurrentTeb()->Peb->ProcessParameters->hStdError;
213 if (flags & CREATE_NEW_CONSOLE)
215 /* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
216 if (is_console_handle(params->hStdInput)) params->hStdInput = INVALID_HANDLE_VALUE;
217 if (is_console_handle(params->hStdOutput)) params->hStdOutput = INVALID_HANDLE_VALUE;
218 if (is_console_handle(params->hStdError)) params->hStdError = INVALID_HANDLE_VALUE;
220 else
222 if (is_console_handle(params->hStdInput)) params->hStdInput = (HANDLE)((UINT_PTR)params->hStdInput & ~3);
223 if (is_console_handle(params->hStdOutput)) params->hStdOutput = (HANDLE)((UINT_PTR)params->hStdOutput & ~3);
224 if (is_console_handle(params->hStdError)) params->hStdError = (HANDLE)((UINT_PTR)params->hStdError & ~3);
227 params->dwX = startup->dwX;
228 params->dwY = startup->dwY;
229 params->dwXSize = startup->dwXSize;
230 params->dwYSize = startup->dwYSize;
231 params->dwXCountChars = startup->dwXCountChars;
232 params->dwYCountChars = startup->dwYCountChars;
233 params->dwFillAttribute = startup->dwFillAttribute;
234 params->dwFlags = startup->dwFlags;
235 params->wShowWindow = startup->wShowWindow;
237 if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW );
238 return params;
242 /***********************************************************************
243 * create_nt_process
245 static NTSTATUS create_nt_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa,
246 BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params,
247 RTL_USER_PROCESS_INFORMATION *info, HANDLE parent )
249 NTSTATUS status;
250 UNICODE_STRING nameW;
252 if (!params->ImagePathName.Buffer[0]) return STATUS_OBJECT_PATH_NOT_FOUND;
253 status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nameW, NULL, NULL );
254 if (!status)
256 params->DebugFlags = flags; /* hack, cf. RtlCreateUserProcess implementation */
257 status = RtlCreateUserProcess( &nameW, OBJ_CASE_INSENSITIVE, params,
258 psa ? psa->lpSecurityDescriptor : NULL,
259 tsa ? tsa->lpSecurityDescriptor : NULL,
260 parent, inherit, 0, 0, info );
261 RtlFreeUnicodeString( &nameW );
263 return status;
267 /***********************************************************************
268 * create_vdm_process
270 static NTSTATUS create_vdm_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa,
271 BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params,
272 RTL_USER_PROCESS_INFORMATION *info )
274 const WCHAR *winevdm = (is_win64 || is_wow64 ?
275 L"C:\\windows\\syswow64\\winevdm.exe" :
276 L"C:\\windows\\system32\\winevdm.exe");
277 WCHAR *newcmdline;
278 NTSTATUS status;
279 UINT len;
281 len = (lstrlenW(params->ImagePathName.Buffer) + lstrlenW(params->CommandLine.Buffer) +
282 lstrlenW(winevdm) + 16);
284 if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
285 return STATUS_NO_MEMORY;
287 swprintf( newcmdline, len, L"%s --app-name \"%s\" %s",
288 winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer );
289 RtlInitUnicodeString( &params->ImagePathName, winevdm );
290 RtlInitUnicodeString( &params->CommandLine, newcmdline );
291 status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL );
292 HeapFree( GetProcessHeap(), 0, newcmdline );
293 return status;
297 /***********************************************************************
298 * create_cmd_process
300 static NTSTATUS create_cmd_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa,
301 BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params,
302 RTL_USER_PROCESS_INFORMATION *info )
304 WCHAR comspec[MAX_PATH];
305 WCHAR *newcmdline;
306 NTSTATUS status;
307 UINT len;
309 if (!GetEnvironmentVariableW( L"COMSPEC", comspec, ARRAY_SIZE( comspec )))
310 lstrcpyW( comspec, L"C:\\windows\\system32\\cmd.exe" );
312 len = lstrlenW(comspec) + 7 + lstrlenW(params->CommandLine.Buffer) + 2;
313 if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
314 return STATUS_NO_MEMORY;
316 swprintf( newcmdline, len, L"%s /s/c \"%s\"", comspec, params->CommandLine.Buffer );
317 RtlInitUnicodeString( &params->ImagePathName, comspec );
318 RtlInitUnicodeString( &params->CommandLine, newcmdline );
319 status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL );
320 RtlFreeHeap( GetProcessHeap(), 0, newcmdline );
321 return status;
325 /*********************************************************************
326 * CloseHandle (kernelbase.@)
328 BOOL WINAPI DECLSPEC_HOTPATCH CloseHandle( HANDLE handle )
330 if (handle == (HANDLE)STD_INPUT_HANDLE)
331 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdInput, 0 );
332 else if (handle == (HANDLE)STD_OUTPUT_HANDLE)
333 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput, 0 );
334 else if (handle == (HANDLE)STD_ERROR_HANDLE)
335 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdError, 0 );
337 if (is_console_handle( handle )) handle = console_handle_map( handle );
338 return set_ntstatus( NtClose( handle ));
342 /**********************************************************************
343 * CreateProcessAsUserA (kernelbase.@)
345 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserA( HANDLE token, const char *app_name, char *cmd_line,
346 SECURITY_ATTRIBUTES *process_attr,
347 SECURITY_ATTRIBUTES *thread_attr,
348 BOOL inherit, DWORD flags, void *env,
349 const char *cur_dir, STARTUPINFOA *startup_info,
350 PROCESS_INFORMATION *info )
352 return CreateProcessInternalA( token, app_name, cmd_line, process_attr, thread_attr,
353 inherit, flags, env, cur_dir, startup_info, info, NULL );
357 /**********************************************************************
358 * CreateProcessAsUserW (kernelbase.@)
360 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line,
361 SECURITY_ATTRIBUTES *process_attr,
362 SECURITY_ATTRIBUTES *thread_attr,
363 BOOL inherit, DWORD flags, void *env,
364 const WCHAR *cur_dir, STARTUPINFOW *startup_info,
365 PROCESS_INFORMATION *info )
367 return CreateProcessInternalW( token, app_name, cmd_line, process_attr, thread_attr,
368 inherit, flags, env, cur_dir, startup_info, info, NULL );
371 /**********************************************************************
372 * CreateProcessInternalA (kernelbase.@)
374 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalA( HANDLE token, const char *app_name, char *cmd_line,
375 SECURITY_ATTRIBUTES *process_attr,
376 SECURITY_ATTRIBUTES *thread_attr,
377 BOOL inherit, DWORD flags, void *env,
378 const char *cur_dir, STARTUPINFOA *startup_info,
379 PROCESS_INFORMATION *info, HANDLE *new_token )
381 BOOL ret = FALSE;
382 WCHAR *app_nameW = NULL, *cmd_lineW = NULL, *cur_dirW = NULL;
383 UNICODE_STRING desktopW, titleW;
384 STARTUPINFOEXW infoW;
386 desktopW.Buffer = NULL;
387 titleW.Buffer = NULL;
388 if (app_name && !(app_nameW = file_name_AtoW( app_name, TRUE ))) goto done;
389 if (cmd_line && !(cmd_lineW = file_name_AtoW( cmd_line, TRUE ))) goto done;
390 if (cur_dir && !(cur_dirW = file_name_AtoW( cur_dir, TRUE ))) goto done;
392 if (startup_info->lpDesktop) RtlCreateUnicodeStringFromAsciiz( &desktopW, startup_info->lpDesktop );
393 if (startup_info->lpTitle) RtlCreateUnicodeStringFromAsciiz( &titleW, startup_info->lpTitle );
395 memcpy( &infoW.StartupInfo, startup_info, sizeof(infoW.StartupInfo) );
396 infoW.StartupInfo.lpDesktop = desktopW.Buffer;
397 infoW.StartupInfo.lpTitle = titleW.Buffer;
399 if (flags & EXTENDED_STARTUPINFO_PRESENT)
400 infoW.lpAttributeList = ((STARTUPINFOEXW *)startup_info)->lpAttributeList;
402 ret = CreateProcessInternalW( token, app_nameW, cmd_lineW, process_attr, thread_attr,
403 inherit, flags, env, cur_dirW, (STARTUPINFOW *)&infoW, info, new_token );
404 done:
405 RtlFreeHeap( GetProcessHeap(), 0, app_nameW );
406 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW );
407 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW );
408 RtlFreeUnicodeString( &desktopW );
409 RtlFreeUnicodeString( &titleW );
410 return ret;
413 struct proc_thread_attr
415 DWORD_PTR attr;
416 SIZE_T size;
417 void *value;
420 struct _PROC_THREAD_ATTRIBUTE_LIST
422 DWORD mask; /* bitmask of items in list */
423 DWORD size; /* max number of items in list */
424 DWORD count; /* number of items in list */
425 DWORD pad;
426 DWORD_PTR unk;
427 struct proc_thread_attr attrs[1];
430 /**********************************************************************
431 * CreateProcessInternalW (kernelbase.@)
433 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line,
434 SECURITY_ATTRIBUTES *process_attr,
435 SECURITY_ATTRIBUTES *thread_attr,
436 BOOL inherit, DWORD flags, void *env,
437 const WCHAR *cur_dir, STARTUPINFOW *startup_info,
438 PROCESS_INFORMATION *info, HANDLE *new_token )
440 WCHAR name[MAX_PATH];
441 WCHAR *p, *tidy_cmdline = cmd_line;
442 RTL_USER_PROCESS_PARAMETERS *params = NULL;
443 RTL_USER_PROCESS_INFORMATION rtl_info;
444 HANDLE parent = NULL;
445 NTSTATUS status;
447 /* Process the AppName and/or CmdLine to get module name and path */
449 TRACE( "app %s cmdline %s\n", debugstr_w(app_name), debugstr_w(cmd_line) );
451 if (token) FIXME( "Creating a process with a token is not yet implemented\n" );
452 if (new_token) FIXME( "No support for returning created process token\n" );
454 if (app_name)
456 if (!cmd_line || !cmd_line[0]) /* no command-line, create one */
458 if (!(tidy_cmdline = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name)+3) * sizeof(WCHAR) )))
459 return FALSE;
460 swprintf( tidy_cmdline, lstrlenW(app_name) + 3, L"\"%s\"", app_name );
463 else
465 if (!(tidy_cmdline = get_file_name( cmd_line, name, ARRAY_SIZE(name) ))) return FALSE;
466 app_name = name;
469 /* Warn if unsupported features are used */
471 if (flags & (IDLE_PRIORITY_CLASS | HIGH_PRIORITY_CLASS | REALTIME_PRIORITY_CLASS |
472 CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW |
473 PROFILE_USER | PROFILE_KERNEL | PROFILE_SERVER))
474 WARN( "(%s,...): ignoring some flags in %x\n", debugstr_w(app_name), flags );
476 if (cur_dir)
478 DWORD attr = GetFileAttributesW( cur_dir );
479 if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY))
481 status = STATUS_NOT_A_DIRECTORY;
482 goto done;
486 info->hThread = info->hProcess = 0;
487 info->dwProcessId = info->dwThreadId = 0;
489 if (!(params = create_process_params( app_name, tidy_cmdline, cur_dir, env, flags, startup_info )))
491 status = STATUS_NO_MEMORY;
492 goto done;
495 if (flags & EXTENDED_STARTUPINFO_PRESENT)
497 struct _PROC_THREAD_ATTRIBUTE_LIST *attrs =
498 (struct _PROC_THREAD_ATTRIBUTE_LIST *)((STARTUPINFOEXW *)startup_info)->lpAttributeList;
499 unsigned int i;
501 if (attrs)
503 for (i = 0; i < attrs->count; ++i)
505 switch(attrs->attrs[i].attr)
507 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:
508 parent = *(HANDLE *)attrs->attrs[i].value;
509 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent);
510 if (!parent)
512 status = STATUS_INVALID_HANDLE;
513 goto done;
515 break;
516 default:
517 FIXME("Unsupported attribute %#Ix.\n", attrs->attrs[i].attr);
518 break;
524 status = create_nt_process( process_attr, thread_attr, inherit, flags, params, &rtl_info, parent );
525 switch (status)
527 case STATUS_SUCCESS:
528 break;
529 case STATUS_INVALID_IMAGE_WIN_16:
530 case STATUS_INVALID_IMAGE_NE_FORMAT:
531 case STATUS_INVALID_IMAGE_PROTECT:
532 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name) );
533 status = create_vdm_process( process_attr, thread_attr, inherit, flags, params, &rtl_info );
534 break;
535 case STATUS_INVALID_IMAGE_NOT_MZ:
536 /* check for .com or .bat extension */
537 if (!(p = wcsrchr( app_name, '.' ))) break;
538 if (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" ))
540 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name) );
541 status = create_vdm_process( process_attr, thread_attr, inherit, flags, params, &rtl_info );
543 else if (!wcsicmp( p, L".bat" ) || !wcsicmp( p, L".cmd" ))
545 TRACE( "starting %s as batch binary\n", debugstr_w(app_name) );
546 status = create_cmd_process( process_attr, thread_attr, inherit, flags, params, &rtl_info );
548 break;
551 if (!status)
553 info->hProcess = rtl_info.Process;
554 info->hThread = rtl_info.Thread;
555 info->dwProcessId = HandleToUlong( rtl_info.ClientId.UniqueProcess );
556 info->dwThreadId = HandleToUlong( rtl_info.ClientId.UniqueThread );
557 if (!(flags & CREATE_SUSPENDED)) NtResumeThread( rtl_info.Thread, NULL );
558 TRACE( "started process pid %04x tid %04x\n", info->dwProcessId, info->dwThreadId );
561 done:
562 RtlDestroyProcessParameters( params );
563 if (tidy_cmdline != cmd_line) HeapFree( GetProcessHeap(), 0, tidy_cmdline );
564 return set_ntstatus( status );
568 /**********************************************************************
569 * CreateProcessA (kernelbase.@)
571 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA( const char *app_name, char *cmd_line,
572 SECURITY_ATTRIBUTES *process_attr,
573 SECURITY_ATTRIBUTES *thread_attr, BOOL inherit,
574 DWORD flags, void *env, const char *cur_dir,
575 STARTUPINFOA *startup_info, PROCESS_INFORMATION *info )
577 return CreateProcessInternalA( NULL, app_name, cmd_line, process_attr, thread_attr,
578 inherit, flags, env, cur_dir, startup_info, info, NULL );
582 /**********************************************************************
583 * CreateProcessW (kernelbase.@)
585 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW( const WCHAR *app_name, WCHAR *cmd_line,
586 SECURITY_ATTRIBUTES *process_attr,
587 SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags,
588 void *env, const WCHAR *cur_dir, STARTUPINFOW *startup_info,
589 PROCESS_INFORMATION *info )
591 return CreateProcessInternalW( NULL, app_name, cmd_line, process_attr, thread_attr,
592 inherit, flags, env, cur_dir, startup_info, info, NULL );
596 /*********************************************************************
597 * DuplicateHandle (kernelbase.@)
599 BOOL WINAPI DECLSPEC_HOTPATCH DuplicateHandle( HANDLE source_process, HANDLE source,
600 HANDLE dest_process, HANDLE *dest,
601 DWORD access, BOOL inherit, DWORD options )
603 if (is_console_handle( source ))
605 source = console_handle_map( source );
606 if (!set_ntstatus( NtDuplicateObject( source_process, source, dest_process, dest,
607 access, inherit ? OBJ_INHERIT : 0, options )))
608 return FALSE;
609 *dest = console_handle_map( *dest );
610 return TRUE;
612 return set_ntstatus( NtDuplicateObject( source_process, source, dest_process, dest,
613 access, inherit ? OBJ_INHERIT : 0, options ));
617 /****************************************************************************
618 * FlushInstructionCache (kernelbase.@)
620 BOOL WINAPI DECLSPEC_HOTPATCH FlushInstructionCache( HANDLE process, LPCVOID addr, SIZE_T size )
622 return set_ntstatus( NtFlushInstructionCache( process, addr, size ));
626 /***********************************************************************
627 * GetCurrentProcess (kernelbase.@)
629 HANDLE WINAPI kernelbase_GetCurrentProcess(void)
631 return (HANDLE)~(ULONG_PTR)0;
635 /***********************************************************************
636 * GetCurrentProcessId (kernelbase.@)
638 DWORD WINAPI kernelbase_GetCurrentProcessId(void)
640 return HandleToULong( NtCurrentTeb()->ClientId.UniqueProcess );
644 /***********************************************************************
645 * GetErrorMode (kernelbase.@)
647 UINT WINAPI DECLSPEC_HOTPATCH GetErrorMode(void)
649 UINT mode;
651 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode,
652 &mode, sizeof(mode), NULL );
653 return mode;
657 /***********************************************************************
658 * GetExitCodeProcess (kernelbase.@)
660 BOOL WINAPI DECLSPEC_HOTPATCH GetExitCodeProcess( HANDLE process, LPDWORD exit_code )
662 NTSTATUS status;
663 PROCESS_BASIC_INFORMATION pbi;
665 status = NtQueryInformationProcess( process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
666 if (status && exit_code) *exit_code = pbi.ExitStatus;
667 return set_ntstatus( status );
671 /*********************************************************************
672 * GetHandleInformation (kernelbase.@)
674 BOOL WINAPI DECLSPEC_HOTPATCH GetHandleInformation( HANDLE handle, DWORD *flags )
676 OBJECT_DATA_INFORMATION info;
678 if (!set_ntstatus( NtQueryObject( handle, ObjectDataInformation, &info, sizeof(info), NULL )))
679 return FALSE;
681 if (flags)
683 *flags = 0;
684 if (info.InheritHandle) *flags |= HANDLE_FLAG_INHERIT;
685 if (info.ProtectFromClose) *flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
687 return TRUE;
691 /***********************************************************************
692 * GetPriorityClass (kernelbase.@)
694 DWORD WINAPI DECLSPEC_HOTPATCH GetPriorityClass( HANDLE process )
696 PROCESS_BASIC_INFORMATION pbi;
698 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation,
699 &pbi, sizeof(pbi), NULL )))
700 return 0;
702 switch (pbi.BasePriority)
704 case PROCESS_PRIOCLASS_IDLE: return IDLE_PRIORITY_CLASS;
705 case PROCESS_PRIOCLASS_BELOW_NORMAL: return BELOW_NORMAL_PRIORITY_CLASS;
706 case PROCESS_PRIOCLASS_NORMAL: return NORMAL_PRIORITY_CLASS;
707 case PROCESS_PRIOCLASS_ABOVE_NORMAL: return ABOVE_NORMAL_PRIORITY_CLASS;
708 case PROCESS_PRIOCLASS_HIGH: return HIGH_PRIORITY_CLASS;
709 case PROCESS_PRIOCLASS_REALTIME: return REALTIME_PRIORITY_CLASS;
710 default: return 0;
715 /******************************************************************
716 * GetProcessHandleCount (kernelbase.@)
718 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessHandleCount( HANDLE process, DWORD *count )
720 return set_ntstatus( NtQueryInformationProcess( process, ProcessHandleCount,
721 count, sizeof(*count), NULL ));
725 /***********************************************************************
726 * GetProcessHeap (kernelbase.@)
728 HANDLE WINAPI kernelbase_GetProcessHeap(void)
730 return NtCurrentTeb()->Peb->ProcessHeap;
734 /*********************************************************************
735 * GetProcessId (kernelbase.@)
737 DWORD WINAPI DECLSPEC_HOTPATCH GetProcessId( HANDLE process )
739 PROCESS_BASIC_INFORMATION pbi;
741 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation,
742 &pbi, sizeof(pbi), NULL )))
743 return 0;
744 return pbi.UniqueProcessId;
748 /**********************************************************************
749 * GetProcessMitigationPolicy (kernelbase.@)
751 BOOL WINAPI /* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process, PROCESS_MITIGATION_POLICY policy,
752 void *buffer, SIZE_T length )
754 FIXME( "(%p, %u, %p, %lu): stub\n", process, policy, buffer, length );
755 return TRUE;
759 /***********************************************************************
760 * GetProcessPriorityBoost (kernelbase.@)
762 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessPriorityBoost( HANDLE process, PBOOL disable )
764 FIXME( "(%p,%p): semi-stub\n", process, disable );
765 *disable = FALSE; /* report that no boost is present */
766 return TRUE;
770 /***********************************************************************
771 * GetProcessShutdownParameters (kernelbase.@)
773 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessShutdownParameters( LPDWORD level, LPDWORD flags )
775 *level = shutdown_priority;
776 *flags = shutdown_flags;
777 return TRUE;
781 /***********************************************************************
782 * GetProcessWorkingSetSizeEx (kernelbase.@)
784 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessWorkingSetSizeEx( HANDLE process, SIZE_T *minset,
785 SIZE_T *maxset, DWORD *flags)
787 FIXME( "(%p,%p,%p,%p): stub\n", process, minset, maxset, flags );
788 /* 32 MB working set size */
789 if (minset) *minset = 32*1024*1024;
790 if (maxset) *maxset = 32*1024*1024;
791 if (flags) *flags = QUOTA_LIMITS_HARDWS_MIN_DISABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE;
792 return TRUE;
796 /******************************************************************************
797 * IsProcessInJob (kernelbase.@)
799 BOOL WINAPI DECLSPEC_HOTPATCH IsProcessInJob( HANDLE process, HANDLE job, BOOL *result )
801 NTSTATUS status = NtIsProcessInJob( process, job );
803 switch (status)
805 case STATUS_PROCESS_IN_JOB:
806 *result = TRUE;
807 return TRUE;
808 case STATUS_PROCESS_NOT_IN_JOB:
809 *result = FALSE;
810 return TRUE;
811 default:
812 return set_ntstatus( status );
817 /***********************************************************************
818 * IsProcessorFeaturePresent (kernelbase.@)
820 BOOL WINAPI DECLSPEC_HOTPATCH IsProcessorFeaturePresent ( DWORD feature )
822 return RtlIsProcessorFeaturePresent( feature );
826 /**********************************************************************
827 * IsWow64Process (kernelbase.@)
829 BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process( HANDLE process, PBOOL wow64 )
831 ULONG_PTR pbi;
832 NTSTATUS status;
834 status = NtQueryInformationProcess( process, ProcessWow64Information, &pbi, sizeof(pbi), NULL );
835 if (!status) *wow64 = !!pbi;
836 return set_ntstatus( status );
840 /*********************************************************************
841 * OpenProcess (kernelbase.@)
843 HANDLE WINAPI DECLSPEC_HOTPATCH OpenProcess( DWORD access, BOOL inherit, DWORD id )
845 HANDLE handle;
846 OBJECT_ATTRIBUTES attr;
847 CLIENT_ID cid;
849 if (GetVersion() & 0x80000000) access = PROCESS_ALL_ACCESS;
851 attr.Length = sizeof(OBJECT_ATTRIBUTES);
852 attr.RootDirectory = 0;
853 attr.Attributes = inherit ? OBJ_INHERIT : 0;
854 attr.ObjectName = NULL;
855 attr.SecurityDescriptor = NULL;
856 attr.SecurityQualityOfService = NULL;
858 cid.UniqueProcess = ULongToHandle(id);
859 cid.UniqueThread = 0;
861 if (!set_ntstatus( NtOpenProcess( &handle, access, &attr, &cid ))) return NULL;
862 return handle;
866 /***********************************************************************
867 * SetErrorMode (kernelbase.@)
869 UINT WINAPI DECLSPEC_HOTPATCH SetErrorMode( UINT mode )
871 UINT old = GetErrorMode();
873 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode,
874 &mode, sizeof(mode) );
875 return old;
879 /*************************************************************************
880 * SetHandleCount (kernelbase.@)
882 UINT WINAPI DECLSPEC_HOTPATCH SetHandleCount( UINT count )
884 return count;
888 /*********************************************************************
889 * SetHandleInformation (kernelbase.@)
891 BOOL WINAPI DECLSPEC_HOTPATCH SetHandleInformation( HANDLE handle, DWORD mask, DWORD flags )
893 OBJECT_DATA_INFORMATION info;
895 /* if not setting both fields, retrieve current value first */
896 if ((mask & (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE)) !=
897 (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE))
899 if (!set_ntstatus( NtQueryObject( handle, ObjectDataInformation, &info, sizeof(info), NULL )))
900 return FALSE;
902 if (mask & HANDLE_FLAG_INHERIT)
903 info.InheritHandle = (flags & HANDLE_FLAG_INHERIT) != 0;
904 if (mask & HANDLE_FLAG_PROTECT_FROM_CLOSE)
905 info.ProtectFromClose = (flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0;
907 return set_ntstatus( NtSetInformationObject( handle, ObjectDataInformation, &info, sizeof(info) ));
911 /***********************************************************************
912 * SetPriorityClass (kernelbase.@)
914 BOOL WINAPI DECLSPEC_HOTPATCH SetPriorityClass( HANDLE process, DWORD class )
916 PROCESS_PRIORITY_CLASS ppc;
918 ppc.Foreground = FALSE;
919 switch (class)
921 case IDLE_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_IDLE; break;
922 case BELOW_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_BELOW_NORMAL; break;
923 case NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_NORMAL; break;
924 case ABOVE_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_ABOVE_NORMAL; break;
925 case HIGH_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_HIGH; break;
926 case REALTIME_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_REALTIME; break;
927 default:
928 SetLastError( ERROR_INVALID_PARAMETER );
929 return FALSE;
931 return set_ntstatus( NtSetInformationProcess( process, ProcessPriorityClass, &ppc, sizeof(ppc) ));
935 /***********************************************************************
936 * SetProcessAffinityUpdateMode (kernelbase.@)
938 BOOL WINAPI DECLSPEC_HOTPATCH SetProcessAffinityUpdateMode( HANDLE process, DWORD flags )
940 FIXME( "(%p,0x%08x): stub\n", process, flags );
941 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
942 return FALSE;
946 /**********************************************************************
947 * SetProcessMitigationPolicy (kernelbase.@)
949 BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy,
950 void *buffer, SIZE_T length )
952 FIXME( "(%d, %p, %lu): stub\n", policy, buffer, length );
953 return TRUE;
957 /***********************************************************************
958 * SetProcessPriorityBoost (kernelbase.@)
960 BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process, BOOL disable )
962 FIXME( "(%p,%d): stub\n", process, disable );
963 return TRUE;
967 /***********************************************************************
968 * SetProcessShutdownParameters (kernelbase.@)
970 BOOL WINAPI DECLSPEC_HOTPATCH SetProcessShutdownParameters( DWORD level, DWORD flags )
972 FIXME( "(%08x, %08x): partial stub.\n", level, flags );
973 shutdown_flags = flags;
974 shutdown_priority = level;
975 return TRUE;
979 /***********************************************************************
980 * SetProcessWorkingSetSizeEx (kernelbase.@)
982 BOOL WINAPI DECLSPEC_HOTPATCH SetProcessWorkingSetSizeEx( HANDLE process, SIZE_T minset,
983 SIZE_T maxset, DWORD flags )
985 return TRUE;
989 /******************************************************************************
990 * TerminateProcess (kernelbase.@)
992 BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code )
994 if (!handle)
996 SetLastError( ERROR_INVALID_HANDLE );
997 return FALSE;
999 return set_ntstatus( NtTerminateProcess( handle, exit_code ));
1003 /***********************************************************************
1004 * Process startup information
1005 ***********************************************************************/
1008 static STARTUPINFOW startup_infoW;
1009 static char *command_lineA;
1010 static WCHAR *command_lineW;
1012 /******************************************************************
1013 * init_startup_info
1015 void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params )
1017 ANSI_STRING ansi;
1019 startup_infoW.cb = sizeof(startup_infoW);
1020 startup_infoW.lpReserved = NULL;
1021 startup_infoW.lpDesktop = params->Desktop.Buffer;
1022 startup_infoW.lpTitle = params->WindowTitle.Buffer;
1023 startup_infoW.dwX = params->dwX;
1024 startup_infoW.dwY = params->dwY;
1025 startup_infoW.dwXSize = params->dwXSize;
1026 startup_infoW.dwYSize = params->dwYSize;
1027 startup_infoW.dwXCountChars = params->dwXCountChars;
1028 startup_infoW.dwYCountChars = params->dwYCountChars;
1029 startup_infoW.dwFillAttribute = params->dwFillAttribute;
1030 startup_infoW.dwFlags = params->dwFlags;
1031 startup_infoW.wShowWindow = params->wShowWindow;
1032 startup_infoW.cbReserved2 = params->RuntimeInfo.MaximumLength;
1033 startup_infoW.lpReserved2 = params->RuntimeInfo.MaximumLength ? (void *)params->RuntimeInfo.Buffer : NULL;
1034 startup_infoW.hStdInput = params->hStdInput ? params->hStdInput : INVALID_HANDLE_VALUE;
1035 startup_infoW.hStdOutput = params->hStdOutput ? params->hStdOutput : INVALID_HANDLE_VALUE;
1036 startup_infoW.hStdError = params->hStdError ? params->hStdError : INVALID_HANDLE_VALUE;
1038 command_lineW = params->CommandLine.Buffer;
1039 if (!RtlUnicodeStringToAnsiString( &ansi, &params->CommandLine, TRUE )) command_lineA = ansi.Buffer;
1043 /***********************************************************************
1044 * GetCommandLineA (kernelbase.@)
1046 LPSTR WINAPI DECLSPEC_HOTPATCH GetCommandLineA(void)
1048 return command_lineA;
1052 /***********************************************************************
1053 * GetCommandLineW (kernelbase.@)
1055 LPWSTR WINAPI DECLSPEC_HOTPATCH GetCommandLineW(void)
1057 return NtCurrentTeb()->Peb->ProcessParameters->CommandLine.Buffer;
1061 /***********************************************************************
1062 * GetStartupInfoW (kernelbase.@)
1064 void WINAPI DECLSPEC_HOTPATCH GetStartupInfoW( STARTUPINFOW *info )
1066 *info = startup_infoW;
1070 /***********************************************************************
1071 * GetStdHandle (kernelbase.@)
1073 HANDLE WINAPI DECLSPEC_HOTPATCH GetStdHandle( DWORD std_handle )
1075 switch (std_handle)
1077 case STD_INPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdInput;
1078 case STD_OUTPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdOutput;
1079 case STD_ERROR_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdError;
1081 SetLastError( ERROR_INVALID_HANDLE );
1082 return INVALID_HANDLE_VALUE;
1086 /***********************************************************************
1087 * SetStdHandle (kernelbase.@)
1089 BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle( DWORD std_handle, HANDLE handle )
1091 switch (std_handle)
1093 case STD_INPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdInput = handle; return TRUE;
1094 case STD_OUTPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdOutput = handle; return TRUE;
1095 case STD_ERROR_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdError = handle; return TRUE;
1097 SetLastError( ERROR_INVALID_HANDLE );
1098 return FALSE;
1102 /***********************************************************************
1103 * SetStdHandleEx (kernelbase.@)
1105 BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandleEx( DWORD std_handle, HANDLE handle, HANDLE *prev )
1107 HANDLE *ptr;
1109 switch (std_handle)
1111 case STD_INPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdInput; break;
1112 case STD_OUTPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; break;
1113 case STD_ERROR_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdError; break;
1114 default:
1115 SetLastError( ERROR_INVALID_HANDLE );
1116 return FALSE;
1118 if (prev) *prev = *ptr;
1119 *ptr = handle;
1120 return TRUE;
1124 /***********************************************************************
1125 * Process environment
1126 ***********************************************************************/
1129 static inline SIZE_T get_env_length( const WCHAR *env )
1131 const WCHAR *end = env;
1132 while (*end) end += lstrlenW(end) + 1;
1133 return end + 1 - env;
1136 /***********************************************************************
1137 * ExpandEnvironmentStringsA (kernelbase.@)
1139 DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, DWORD count )
1141 UNICODE_STRING us_src;
1142 PWSTR dstW = NULL;
1143 DWORD ret;
1145 RtlCreateUnicodeStringFromAsciiz( &us_src, src );
1146 if (count)
1148 if (!(dstW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR)))) return 0;
1149 ret = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count);
1150 if (ret) WideCharToMultiByte( CP_ACP, 0, dstW, ret, dst, count, NULL, NULL );
1152 else ret = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0 );
1154 RtlFreeUnicodeString( &us_src );
1155 HeapFree( GetProcessHeap(), 0, dstW );
1156 return ret;
1160 /***********************************************************************
1161 * ExpandEnvironmentStringsW (kernelbase.@)
1163 DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len )
1165 UNICODE_STRING us_src, us_dst;
1166 NTSTATUS status;
1167 DWORD res;
1169 TRACE( "(%s %p %u)\n", debugstr_w(src), dst, len );
1171 RtlInitUnicodeString( &us_src, src );
1173 /* make sure we don't overflow the maximum UNICODE_STRING size */
1174 len = min( len, UNICODE_STRING_MAX_CHARS );
1176 us_dst.Length = 0;
1177 us_dst.MaximumLength = len * sizeof(WCHAR);
1178 us_dst.Buffer = dst;
1180 res = 0;
1181 status = RtlExpandEnvironmentStrings_U( NULL, &us_src, &us_dst, &res );
1182 res /= sizeof(WCHAR);
1183 if (!set_ntstatus( status ))
1185 if (status != STATUS_BUFFER_TOO_SMALL) return 0;
1186 if (len && dst) dst[len - 1] = 0;
1188 return res;
1192 /***********************************************************************
1193 * GetEnvironmentStrings (kernelbase.@)
1194 * GetEnvironmentStringsA (kernelbase.@)
1196 LPSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsA(void)
1198 LPWSTR env;
1199 LPSTR ret;
1200 SIZE_T lenA, lenW;
1202 RtlAcquirePebLock();
1203 env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
1204 lenW = get_env_length( env );
1205 lenA = WideCharToMultiByte( CP_ACP, 0, env, lenW, NULL, 0, NULL, NULL );
1206 if ((ret = HeapAlloc( GetProcessHeap(), 0, lenA )))
1207 WideCharToMultiByte( CP_ACP, 0, env, lenW, ret, lenA, NULL, NULL );
1208 RtlReleasePebLock();
1209 return ret;
1213 /***********************************************************************
1214 * GetEnvironmentStringsW (kernelbase.@)
1216 LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void)
1218 LPWSTR ret;
1219 SIZE_T len;
1221 RtlAcquirePebLock();
1222 len = get_env_length( NtCurrentTeb()->Peb->ProcessParameters->Environment ) * sizeof(WCHAR);
1223 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
1224 memcpy( ret, NtCurrentTeb()->Peb->ProcessParameters->Environment, len );
1225 RtlReleasePebLock();
1226 return ret;
1230 /***********************************************************************
1231 * GetEnvironmentVariableA (kernelbase.@)
1233 DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size )
1235 UNICODE_STRING us_name;
1236 PWSTR valueW;
1237 DWORD ret;
1239 /* limit the size to sane values */
1240 size = min( size, 32767 );
1241 if (!(valueW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0;
1243 RtlCreateUnicodeStringFromAsciiz( &us_name, name );
1244 SetLastError( 0 );
1245 ret = GetEnvironmentVariableW( us_name.Buffer, valueW, size);
1246 if (ret && ret < size) WideCharToMultiByte( CP_ACP, 0, valueW, ret + 1, value, size, NULL, NULL );
1248 /* this is needed to tell, with 0 as a return value, the difference between:
1249 * - an error (GetLastError() != 0)
1250 * - returning an empty string (in this case, we need to update the buffer)
1252 if (ret == 0 && size && GetLastError() == 0) value[0] = 0;
1253 RtlFreeUnicodeString( &us_name );
1254 HeapFree( GetProcessHeap(), 0, valueW );
1255 return ret;
1259 /***********************************************************************
1260 * GetEnvironmentVariableW (kernelbase.@)
1262 DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size )
1264 UNICODE_STRING us_name, us_value;
1265 NTSTATUS status;
1266 DWORD len;
1268 TRACE( "(%s %p %u)\n", debugstr_w(name), val, size );
1270 RtlInitUnicodeString( &us_name, name );
1271 us_value.Length = 0;
1272 us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR);
1273 us_value.Buffer = val;
1275 status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value );
1276 len = us_value.Length / sizeof(WCHAR);
1277 if (!set_ntstatus( status )) return (status == STATUS_BUFFER_TOO_SMALL) ? len + 1 : 0;
1278 if (size) val[len] = 0;
1279 return len;
1283 /***********************************************************************
1284 * FreeEnvironmentStringsA (kernelbase.@)
1285 * FreeEnvironmentStringsW (kernelbase.@)
1287 BOOL WINAPI DECLSPEC_HOTPATCH FreeEnvironmentStringsW( LPWSTR ptr )
1289 return HeapFree( GetProcessHeap(), 0, ptr );
1293 /***********************************************************************
1294 * SetEnvironmentVariableA (kernelbase.@)
1296 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
1298 UNICODE_STRING us_name, us_value;
1299 BOOL ret;
1301 if (!name)
1303 SetLastError( ERROR_ENVVAR_NOT_FOUND );
1304 return FALSE;
1307 RtlCreateUnicodeStringFromAsciiz( &us_name, name );
1308 if (value)
1310 RtlCreateUnicodeStringFromAsciiz( &us_value, value );
1311 ret = SetEnvironmentVariableW( us_name.Buffer, us_value.Buffer );
1312 RtlFreeUnicodeString( &us_value );
1314 else ret = SetEnvironmentVariableW( us_name.Buffer, NULL );
1315 RtlFreeUnicodeString( &us_name );
1316 return ret;
1320 /***********************************************************************
1321 * SetEnvironmentVariableW (kernelbase.@)
1323 BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value )
1325 UNICODE_STRING us_name, us_value;
1326 NTSTATUS status;
1328 TRACE( "(%s %s)\n", debugstr_w(name), debugstr_w(value) );
1330 if (!name)
1332 SetLastError( ERROR_ENVVAR_NOT_FOUND );
1333 return FALSE;
1336 RtlInitUnicodeString( &us_name, name );
1337 if (value)
1339 RtlInitUnicodeString( &us_value, value );
1340 status = RtlSetEnvironmentVariable( NULL, &us_name, &us_value );
1342 else status = RtlSetEnvironmentVariable( NULL, &us_name, NULL );
1344 return set_ntstatus( status );
1348 /***********************************************************************
1349 * Process/thread attribute lists
1350 ***********************************************************************/
1352 /***********************************************************************
1353 * InitializeProcThreadAttributeList (kernelbase.@)
1355 BOOL WINAPI DECLSPEC_HOTPATCH InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list,
1356 DWORD count, DWORD flags, SIZE_T *size )
1358 SIZE_T needed;
1359 BOOL ret = FALSE;
1361 TRACE( "(%p %d %x %p)\n", list, count, flags, size );
1363 needed = FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST, attrs[count] );
1364 if (list && *size >= needed)
1366 list->mask = 0;
1367 list->size = count;
1368 list->count = 0;
1369 list->unk = 0;
1370 ret = TRUE;
1372 else SetLastError( ERROR_INSUFFICIENT_BUFFER );
1374 *size = needed;
1375 return ret;
1379 /***********************************************************************
1380 * UpdateProcThreadAttribute (kernelbase.@)
1382 BOOL WINAPI DECLSPEC_HOTPATCH UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST *list,
1383 DWORD flags, DWORD_PTR attr, void *value,
1384 SIZE_T size, void *prev_ret, SIZE_T *size_ret )
1386 DWORD mask;
1387 struct proc_thread_attr *entry;
1389 TRACE( "(%p %x %08lx %p %ld %p %p)\n", list, flags, attr, value, size, prev_ret, size_ret );
1391 if (list->count >= list->size)
1393 SetLastError( ERROR_GEN_FAILURE );
1394 return FALSE;
1397 switch (attr)
1399 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:
1400 if (size != sizeof(HANDLE))
1402 SetLastError( ERROR_BAD_LENGTH );
1403 return FALSE;
1405 break;
1407 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST:
1408 if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size)
1410 SetLastError( ERROR_BAD_LENGTH );
1411 return FALSE;
1413 break;
1415 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR:
1416 if (size != sizeof(PROCESSOR_NUMBER))
1418 SetLastError( ERROR_BAD_LENGTH );
1419 return FALSE;
1421 break;
1423 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY:
1424 if (size != sizeof(DWORD) && size != sizeof(DWORD64))
1426 SetLastError( ERROR_BAD_LENGTH );
1427 return FALSE;
1429 break;
1431 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY:
1432 if (size != sizeof(DWORD) && size != sizeof(DWORD64) && size != sizeof(DWORD64) * 2)
1434 SetLastError( ERROR_BAD_LENGTH );
1435 return FALSE;
1437 break;
1439 default:
1440 SetLastError( ERROR_NOT_SUPPORTED );
1441 FIXME( "Unhandled attribute %lu\n", attr & PROC_THREAD_ATTRIBUTE_NUMBER );
1442 return FALSE;
1445 mask = 1 << (attr & PROC_THREAD_ATTRIBUTE_NUMBER);
1446 if (list->mask & mask)
1448 SetLastError( ERROR_OBJECT_NAME_EXISTS );
1449 return FALSE;
1451 list->mask |= mask;
1453 entry = list->attrs + list->count;
1454 entry->attr = attr;
1455 entry->size = size;
1456 entry->value = value;
1457 list->count++;
1458 return TRUE;
1462 /***********************************************************************
1463 * DeleteProcThreadAttributeList (kernelbase.@)
1465 void WINAPI DECLSPEC_HOTPATCH DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list )
1467 return;