Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873/* * Win32 processes * * Copyright 1996, 1998 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include <stdarg.h>#include <string.h>
#include "ntstatus.h"#define WIN32_NO_STATUS#include "windef.h"#include "winbase.h"#include "winnls.h"#include "wincontypes.h"#include "winternl.h"
#include "kernelbase.h"#include "wine/debug.h"#include "wine/condrv.h"
WINE_DEFAULT_DEBUG_CHANNEL(process);
static DWORD shutdown_flags = 0;static DWORD shutdown_priority = 0x280;
/*********************************************************************** * Processes ***********************************************************************/
/*********************************************************************** * find_exe_file */static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, DWORD buflen ){ WCHAR *load_path; BOOL ret;
if (!set_ntstatus( RtlGetExePath( name, &load_path ))) return FALSE;
TRACE( "looking for %s in %s\n", debugstr_w(name), debugstr_w(load_path) );
ret = (SearchPathW( load_path, name, L".exe", buflen, buffer, NULL ) || /* not found, try without extension in case it is a Unix app */ SearchPathW( load_path, name, NULL, buflen, buffer, NULL ));
if (ret) /* make sure it can be opened, SearchPathW also returns directories */ { HANDLE handle = CreateFileW( buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0 ); if ((ret = (handle != INVALID_HANDLE_VALUE))) CloseHandle( handle ); } RtlReleasePath( load_path ); return ret;}
/************************************************************************* * get_file_name * * Helper for CreateProcess: retrieve the file name to load from the * app name and command line. Store the file name in buffer, and * return a possibly modified command line. */static WCHAR *get_file_name( WCHAR *cmdline, WCHAR *buffer, DWORD buflen ){ WCHAR *name, *pos, *first_space, *ret = NULL; const WCHAR *p;
/* first check for a quoted file name */
if (cmdline[0] == '"' && (p = wcschr( cmdline + 1, '"' ))) { int len = p - cmdline - 1; /* extract the quoted portion as file name */ if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL; memcpy( name, cmdline + 1, len * sizeof(WCHAR) ); name[len] = 0;
if (!find_exe_file( name, buffer, buflen )) goto done; ret = cmdline; /* no change necessary */ goto done; }
/* now try the command-line word by word */
if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR) ))) return NULL; pos = name; p = cmdline; first_space = NULL;
for (;;) { while (*p && *p != ' ' && *p != '\t') *pos++ = *p++; *pos = 0; if (find_exe_file( name, buffer, buflen )) { ret = cmdline; break; } if (!first_space) first_space = pos; if (!(*pos++ = *p++)) break; }
if (!ret) { SetLastError( ERROR_FILE_NOT_FOUND ); } else if (first_space) /* build a new command-line with quotes */ { if (!(ret = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline) + 3) * sizeof(WCHAR) ))) goto done; swprintf( ret, lstrlenW(cmdline) + 3, L"\"%s\"%s", name, p ); }
done: RtlFreeHeap( GetProcessHeap(), 0, name ); return ret;}
/*********************************************************************** * create_process_params */static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename, const WCHAR *cmdline, const WCHAR *cur_dir, void *env, DWORD flags, const STARTUPINFOW *startup ){ RTL_USER_PROCESS_PARAMETERS *params; UNICODE_STRING imageW, curdirW, cmdlineW, titleW, desktopW, runtimeW, newdirW; WCHAR imagepath[MAX_PATH]; WCHAR *envW = env;
if (!GetLongPathNameW( filename, imagepath, MAX_PATH )) lstrcpynW( imagepath, filename, MAX_PATH ); if (!GetFullPathNameW( imagepath, MAX_PATH, imagepath, NULL )) lstrcpynW( imagepath, filename, MAX_PATH );
if (env && !(flags & CREATE_UNICODE_ENVIRONMENT)) /* convert environment to unicode */ { char *e = env; DWORD lenW;
while (*e) e += strlen(e) + 1; e++; /* final null */ lenW = MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, NULL, 0 ); if ((envW = RtlAllocateHeap( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, envW, lenW ); }
newdirW.Buffer = NULL; if (cur_dir) { if (RtlDosPathNameToNtPathName_U( cur_dir, &newdirW, NULL, NULL )) cur_dir = newdirW.Buffer + 4; /* skip \??\ prefix */ else cur_dir = NULL; } RtlInitUnicodeString( &imageW, imagepath ); RtlInitUnicodeString( &curdirW, cur_dir ); RtlInitUnicodeString( &cmdlineW, cmdline ); RtlInitUnicodeString( &titleW, startup->lpTitle ? startup->lpTitle : imagepath ); RtlInitUnicodeString( &desktopW, startup->lpDesktop ); runtimeW.Buffer = (WCHAR *)startup->lpReserved2; runtimeW.Length = runtimeW.MaximumLength = startup->cbReserved2; if (RtlCreateProcessParametersEx( ¶ms, &imageW, NULL, cur_dir ? &curdirW : NULL, &cmdlineW, envW, &titleW, &desktopW, NULL, &runtimeW, PROCESS_PARAMS_FLAG_NORMALIZED )) { RtlFreeUnicodeString( &newdirW ); if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW ); return NULL; } RtlFreeUnicodeString( &newdirW );
if (!(flags & CREATE_NEW_PROCESS_GROUP)) params->ProcessGroupId = NtCurrentTeb()->Peb->ProcessParameters->ProcessGroupId; else if (!(flags & CREATE_NEW_CONSOLE)) params->ConsoleFlags = 1;
if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; else if (!(flags & DETACHED_PROCESS)) { if (flags & CREATE_NO_WINDOW) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC_NO_WINDOW; else { params->ConsoleHandle = NtCurrentTeb()->Peb->ProcessParameters->ConsoleHandle; if (!params->ConsoleHandle) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; } }
if (startup->dwFlags & STARTF_USESTDHANDLES) { params->hStdInput = startup->hStdInput; params->hStdOutput = startup->hStdOutput; params->hStdError = startup->hStdError; } else if (!(flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE))) { params->hStdInput = NtCurrentTeb()->Peb->ProcessParameters->hStdInput; params->hStdOutput = NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; params->hStdError = NtCurrentTeb()->Peb->ProcessParameters->hStdError; }
if (params->hStdInput == INVALID_HANDLE_VALUE) params->hStdInput = NULL; if (params->hStdOutput == INVALID_HANDLE_VALUE) params->hStdOutput = NULL; if (params->hStdError == INVALID_HANDLE_VALUE) params->hStdError = NULL;
params->dwX = startup->dwX; params->dwY = startup->dwY; params->dwXSize = startup->dwXSize; params->dwYSize = startup->dwYSize; params->dwXCountChars = startup->dwXCountChars; params->dwYCountChars = startup->dwYCountChars; params->dwFillAttribute = startup->dwFillAttribute; params->dwFlags = startup->dwFlags; params->wShowWindow = startup->wShowWindow;
if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW ); return params;}
struct proc_thread_attr{ DWORD_PTR attr; SIZE_T size; void *value;};
struct _PROC_THREAD_ATTRIBUTE_LIST{ DWORD mask; /* bitmask of items in list */ DWORD size; /* max number of items in list */ DWORD count; /* number of items in list */ DWORD pad; DWORD_PTR unk; struct proc_thread_attr attrs[1];};
/*********************************************************************** * create_nt_process */static NTSTATUS create_nt_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, DWORD process_flags, RTL_USER_PROCESS_PARAMETERS *params, RTL_USER_PROCESS_INFORMATION *info, HANDLE parent, USHORT machine, const struct proc_thread_attr *handle_list, const struct proc_thread_attr *job_list){ OBJECT_ATTRIBUTES process_attr, thread_attr; PS_CREATE_INFO create_info; ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[9] ) / sizeof(ULONG_PTR)]; PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer; UNICODE_STRING nameW; NTSTATUS status; UINT pos = 0;
if (!params->ImagePathName.Buffer[0]) return STATUS_OBJECT_PATH_NOT_FOUND; status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nameW, NULL, NULL ); if (!status) { RtlNormalizeProcessParams( params );
attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_NAME; attr->Attributes[pos].Size = nameW.Length; attr->Attributes[pos].ValuePtr = nameW.Buffer; attr->Attributes[pos].ReturnLength = NULL; pos++; attr->Attributes[pos].Attribute = PS_ATTRIBUTE_CLIENT_ID; attr->Attributes[pos].Size = sizeof(info->ClientId); attr->Attributes[pos].ValuePtr = &info->ClientId; attr->Attributes[pos].ReturnLength = NULL; pos++; attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_INFO; attr->Attributes[pos].Size = sizeof(info->ImageInformation); attr->Attributes[pos].ValuePtr = &info->ImageInformation; attr->Attributes[pos].ReturnLength = NULL; pos++; if (parent) { attr->Attributes[pos].Attribute = PS_ATTRIBUTE_PARENT_PROCESS; attr->Attributes[pos].Size = sizeof(parent); attr->Attributes[pos].ValuePtr = parent; attr->Attributes[pos].ReturnLength = NULL; pos++; } if ((process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES) && handle_list) { attr->Attributes[pos].Attribute = PS_ATTRIBUTE_HANDLE_LIST; attr->Attributes[pos].Size = handle_list->size; attr->Attributes[pos].ValuePtr = handle_list->value; attr->Attributes[pos].ReturnLength = NULL; pos++; } if (token) { attr->Attributes[pos].Attribute = PS_ATTRIBUTE_TOKEN; attr->Attributes[pos].Size = sizeof(token); attr->Attributes[pos].ValuePtr = token; attr->Attributes[pos].ReturnLength = NULL; pos++; } if (debug) { attr->Attributes[pos].Attribute = PS_ATTRIBUTE_DEBUG_PORT; attr->Attributes[pos].Size = sizeof(debug); attr->Attributes[pos].ValuePtr = debug; attr->Attributes[pos].ReturnLength = NULL; pos++; } if (job_list) { attr->Attributes[pos].Attribute = PS_ATTRIBUTE_JOB_LIST; attr->Attributes[pos].Size = job_list->size; attr->Attributes[pos].ValuePtr = job_list->value; attr->Attributes[pos].ReturnLength = NULL; pos++; } if (machine) { attr->Attributes[pos].Attribute = PS_ATTRIBUTE_MACHINE_TYPE; attr->Attributes[pos].Size = sizeof(machine); attr->Attributes[pos].Value = machine; attr->Attributes[pos].ReturnLength = NULL; pos++; } attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] );
InitializeObjectAttributes( &process_attr, NULL, 0, NULL, psa ? psa->lpSecurityDescriptor : NULL ); InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, tsa ? tsa->lpSecurityDescriptor : NULL );
status = NtCreateUserProcess( &info->Process, &info->Thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, &process_attr, &thread_attr, process_flags, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params, &create_info, attr );
RtlFreeUnicodeString( &nameW ); } return status;}
/*********************************************************************** * create_vdm_process */static NTSTATUS create_vdm_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, RTL_USER_PROCESS_INFORMATION *info ){ const WCHAR *winevdm = (is_win64 || is_wow64 ? L"C:\\windows\\syswow64\\winevdm.exe" : L"C:\\windows\\system32\\winevdm.exe"); WCHAR *newcmdline; NTSTATUS status; UINT len;
len = (lstrlenW(params->ImagePathName.Buffer) + lstrlenW(params->CommandLine.Buffer) + lstrlenW(winevdm) + 16);
if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return STATUS_NO_MEMORY;
swprintf( newcmdline, len, L"%s --app-name \"%s\" %s", winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer ); RtlInitUnicodeString( ¶ms->ImagePathName, winevdm ); RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); status = create_nt_process( token, debug, psa, tsa, flags, params, info, 0, 0, NULL, NULL ); HeapFree( GetProcessHeap(), 0, newcmdline ); return status;}
/*********************************************************************** * create_cmd_process */static NTSTATUS create_cmd_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, RTL_USER_PROCESS_INFORMATION *info ){ WCHAR comspec[MAX_PATH]; WCHAR *newcmdline; NTSTATUS status; UINT len;
if (!GetEnvironmentVariableW( L"COMSPEC", comspec, ARRAY_SIZE( comspec ))) lstrcpyW( comspec, L"C:\\windows\\system32\\cmd.exe" );
len = lstrlenW(comspec) + 7 + lstrlenW(params->CommandLine.Buffer) + 2; if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return STATUS_NO_MEMORY;
swprintf( newcmdline, len, L"%s /s/c \"%s\"", comspec, params->CommandLine.Buffer ); RtlInitUnicodeString( ¶ms->ImagePathName, comspec ); RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); status = create_nt_process( token, debug, psa, tsa, flags, params, info, 0, 0, NULL, NULL ); RtlFreeHeap( GetProcessHeap(), 0, newcmdline ); return status;}
/********************************************************************* * CloseHandle (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CloseHandle( HANDLE handle ){ if (handle == (HANDLE)STD_INPUT_HANDLE) handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdInput, 0 ); else if (handle == (HANDLE)STD_OUTPUT_HANDLE) handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput, 0 ); else if (handle == (HANDLE)STD_ERROR_HANDLE) handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdError, 0 );
return set_ntstatus( NtClose( handle ));}
/********************************************************************** * CreateProcessAsUserA (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserA( HANDLE token, const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info ){ return CreateProcessInternalA( token, app_name, cmd_line, process_attr, thread_attr, inherit, flags, env, cur_dir, startup_info, info, NULL );}
/********************************************************************** * CreateProcessAsUserW (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const WCHAR *cur_dir, STARTUPINFOW *startup_info, PROCESS_INFORMATION *info ){ return CreateProcessInternalW( token, app_name, cmd_line, process_attr, thread_attr, inherit, flags, env, cur_dir, startup_info, info, NULL );}
/********************************************************************** * CreateProcessInternalA (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalA( HANDLE token, const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info, HANDLE *new_token ){ BOOL ret = FALSE; WCHAR *app_nameW = NULL, *cmd_lineW = NULL, *cur_dirW = NULL; UNICODE_STRING desktopW, titleW; STARTUPINFOEXW infoW;
desktopW.Buffer = NULL; titleW.Buffer = NULL; if (app_name && !(app_nameW = file_name_AtoW( app_name, TRUE ))) goto done; if (cmd_line && !(cmd_lineW = file_name_AtoW( cmd_line, TRUE ))) goto done; if (cur_dir && !(cur_dirW = file_name_AtoW( cur_dir, TRUE ))) goto done;
if (startup_info->lpDesktop) RtlCreateUnicodeStringFromAsciiz( &desktopW, startup_info->lpDesktop ); if (startup_info->lpTitle) RtlCreateUnicodeStringFromAsciiz( &titleW, startup_info->lpTitle );
memcpy( &infoW.StartupInfo, startup_info, sizeof(infoW.StartupInfo) ); infoW.StartupInfo.lpDesktop = desktopW.Buffer; infoW.StartupInfo.lpTitle = titleW.Buffer;
if (flags & EXTENDED_STARTUPINFO_PRESENT) infoW.lpAttributeList = ((STARTUPINFOEXW *)startup_info)->lpAttributeList;
ret = CreateProcessInternalW( token, app_nameW, cmd_lineW, process_attr, thread_attr, inherit, flags, env, cur_dirW, (STARTUPINFOW *)&infoW, info, new_token );done: RtlFreeHeap( GetProcessHeap(), 0, app_nameW ); RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW ); RtlFreeHeap( GetProcessHeap(), 0, cur_dirW ); RtlFreeUnicodeString( &desktopW ); RtlFreeUnicodeString( &titleW ); return ret;}
/********************************************************************** * CreateProcessInternalW (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const WCHAR *cur_dir, STARTUPINFOW *startup_info, PROCESS_INFORMATION *info, HANDLE *new_token ){ const struct proc_thread_attr *handle_list = NULL, *job_list = NULL; WCHAR name[MAX_PATH]; WCHAR *p, *tidy_cmdline = cmd_line; RTL_USER_PROCESS_PARAMETERS *params = NULL; RTL_USER_PROCESS_INFORMATION rtl_info; HANDLE parent = 0, debug = 0; ULONG nt_flags = 0; USHORT machine = 0; NTSTATUS status;
/* Process the AppName and/or CmdLine to get module name and path */
TRACE( "app %s cmdline %s\n", debugstr_w(app_name), debugstr_w(cmd_line) );
if (new_token) FIXME( "No support for returning created process token\n" );
if (app_name) { if (!cmd_line || !cmd_line[0]) /* no command-line, create one */ { if (!(tidy_cmdline = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name)+3) * sizeof(WCHAR) ))) return FALSE; swprintf( tidy_cmdline, lstrlenW(app_name) + 3, L"\"%s\"", app_name ); } } else { if (!(tidy_cmdline = get_file_name( cmd_line, name, ARRAY_SIZE(name) ))) return FALSE; app_name = name; }
/* Warn if unsupported features are used */
if (flags & (IDLE_PRIORITY_CLASS | HIGH_PRIORITY_CLASS | REALTIME_PRIORITY_CLASS | CREATE_DEFAULT_ERROR_MODE | PROFILE_USER | PROFILE_KERNEL | PROFILE_SERVER)) WARN( "(%s,...): ignoring some flags in %lx\n", debugstr_w(app_name), flags );
if (cur_dir) { DWORD attr = GetFileAttributesW( cur_dir ); if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY)) { status = STATUS_NOT_A_DIRECTORY; goto done; } }
info->hThread = info->hProcess = 0; info->dwProcessId = info->dwThreadId = 0;
if (!(params = create_process_params( app_name, tidy_cmdline, cur_dir, env, flags, startup_info ))) { status = STATUS_NO_MEMORY; goto done; }
if (flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) { if ((status = DbgUiConnectToDbg())) goto done; debug = DbgUiGetThreadDebugObject(); }
if (flags & EXTENDED_STARTUPINFO_PRESENT) { struct _PROC_THREAD_ATTRIBUTE_LIST *attrs = (struct _PROC_THREAD_ATTRIBUTE_LIST *)((STARTUPINFOEXW *)startup_info)->lpAttributeList; unsigned int i;
if (attrs) { for (i = 0; i < attrs->count; ++i) { switch(attrs->attrs[i].attr) { case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: parent = *(HANDLE *)attrs->attrs[i].value; TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent); if (!parent) { status = STATUS_INVALID_HANDLE; goto done; } break; case PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS: FIXME("PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS %lx.\n", *(ULONG *)attrs->attrs[i].value); break; case PROC_THREAD_ATTRIBUTE_HANDLE_LIST: handle_list = &attrs->attrs[i]; TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs->attrs[i].size / sizeof(HANDLE)); break; case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: { struct pseudo_console *console = attrs->attrs[i].value; TRACE( "PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE %p reference %p\n", console, console->reference ); params->ConsoleHandle = console->reference; break; } case PROC_THREAD_ATTRIBUTE_JOB_LIST: job_list = &attrs->attrs[i]; TRACE( "PROC_THREAD_ATTRIBUTE_JOB_LIST handle count %Iu.\n", attrs->attrs[i].size / sizeof(HANDLE) ); break; case PROC_THREAD_ATTRIBUTE_MACHINE_TYPE: machine = *(USHORT *)attrs->attrs[i].value; TRACE( "PROC_THREAD_ATTRIBUTE_MACHINE %x.\n", machine ); break; default: FIXME("Unsupported attribute %#Ix.\n", attrs->attrs[i].attr); break; } } } }
if (inherit) nt_flags |= PROCESS_CREATE_FLAGS_INHERIT_HANDLES; if (flags & DEBUG_ONLY_THIS_PROCESS) nt_flags |= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT; if (flags & CREATE_BREAKAWAY_FROM_JOB) nt_flags |= PROCESS_CREATE_FLAGS_BREAKAWAY; if (flags & CREATE_SUSPENDED) nt_flags |= PROCESS_CREATE_FLAGS_SUSPENDED;
status = create_nt_process( token, debug, process_attr, thread_attr, nt_flags, params, &rtl_info, parent, machine, handle_list, job_list ); switch (status) { case STATUS_SUCCESS: break; case STATUS_INVALID_IMAGE_WIN_16: case STATUS_INVALID_IMAGE_NE_FORMAT: case STATUS_INVALID_IMAGE_PROTECT: TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name) ); status = create_vdm_process( token, debug, process_attr, thread_attr, nt_flags, params, &rtl_info ); break; case STATUS_INVALID_IMAGE_NOT_MZ: /* check for .com or .bat extension */ if (!(p = wcsrchr( app_name, '.' ))) break; if (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" )) { TRACE( "starting %s as DOS binary\n", debugstr_w(app_name) ); status = create_vdm_process( token, debug, process_attr, thread_attr, nt_flags, params, &rtl_info ); } else if (!wcsicmp( p, L".bat" ) || !wcsicmp( p, L".cmd" )) { TRACE( "starting %s as batch binary\n", debugstr_w(app_name) ); status = create_cmd_process( token, debug, process_attr, thread_attr, nt_flags, params, &rtl_info ); } break; }
if (!status) { info->hProcess = rtl_info.Process; info->hThread = rtl_info.Thread; info->dwProcessId = HandleToUlong( rtl_info.ClientId.UniqueProcess ); info->dwThreadId = HandleToUlong( rtl_info.ClientId.UniqueThread ); if (!(flags & CREATE_SUSPENDED)) NtResumeThread( rtl_info.Thread, NULL ); TRACE( "started process pid %04lx tid %04lx\n", info->dwProcessId, info->dwThreadId ); }
done: RtlDestroyProcessParameters( params ); if (tidy_cmdline != cmd_line) HeapFree( GetProcessHeap(), 0, tidy_cmdline ); return set_ntstatus( status );}
/********************************************************************** * CreateProcessA (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA( const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info ){ return CreateProcessInternalA( NULL, app_name, cmd_line, process_attr, thread_attr, inherit, flags, env, cur_dir, startup_info, info, NULL );}
/********************************************************************** * CreateProcessW (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW( const WCHAR *app_name, WCHAR *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const WCHAR *cur_dir, STARTUPINFOW *startup_info, PROCESS_INFORMATION *info ){ return CreateProcessInternalW( NULL, app_name, cmd_line, process_attr, thread_attr, inherit, flags, env, cur_dir, startup_info, info, NULL );}
/********************************************************************** * SetProcessInformation (kernelbase.@) */BOOL WINAPI SetProcessInformation( HANDLE process, PROCESS_INFORMATION_CLASS info_class, void *info, DWORD size ){ switch (info_class) { case ProcessMemoryPriority: return set_ntstatus( NtSetInformationProcess( process, ProcessPagePriority, info, size )); case ProcessPowerThrottling: return set_ntstatus( NtSetInformationProcess( process, ProcessPowerThrottlingState, info, size )); case ProcessLeapSecondInfo: return set_ntstatus( NtSetInformationProcess( process, ProcessLeapSecondInformation, info, size )); default: FIXME("Unrecognized information class %d.\n", info_class); return FALSE; }}
/********************************************************************* * DuplicateHandle (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH DuplicateHandle( HANDLE source_process, HANDLE source, HANDLE dest_process, HANDLE *dest, DWORD access, BOOL inherit, DWORD options ){ return set_ntstatus( NtDuplicateObject( source_process, source, dest_process, dest, access, inherit ? OBJ_INHERIT : 0, options ));}
/*********************************************************************** * GetApplicationRestartSettings (kernelbase.@) */HRESULT WINAPI /* DECLSPEC_HOTPATCH */ GetApplicationRestartSettings( HANDLE process, WCHAR *cmdline, DWORD *size, DWORD *flags ){ FIXME( "%p, %p, %p, %p)\n", process, cmdline, size, flags ); return E_NOTIMPL;}
/*********************************************************************** * GetCurrentProcess (kernelbase.@) */HANDLE WINAPI kernelbase_GetCurrentProcess(void){ return (HANDLE)~(ULONG_PTR)0;}
/*********************************************************************** * GetCurrentProcessId (kernelbase.@) */DWORD WINAPI kernelbase_GetCurrentProcessId(void){ return HandleToULong( NtCurrentTeb()->ClientId.UniqueProcess );}
/*********************************************************************** * GetErrorMode (kernelbase.@) */UINT WINAPI DECLSPEC_HOTPATCH GetErrorMode(void){ UINT mode;
NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode, &mode, sizeof(mode), NULL ); return mode;}
/*********************************************************************** * GetExitCodeProcess (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetExitCodeProcess( HANDLE process, LPDWORD exit_code ){ NTSTATUS status; PROCESS_BASIC_INFORMATION pbi;
status = NtQueryInformationProcess( process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL ); if (!status && exit_code) *exit_code = pbi.ExitStatus; return set_ntstatus( status );}
/********************************************************************* * GetHandleInformation (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetHandleInformation( HANDLE handle, DWORD *flags ){ OBJECT_HANDLE_FLAG_INFORMATION info;
if (!set_ntstatus( NtQueryObject( handle, ObjectHandleFlagInformation, &info, sizeof(info), NULL ))) return FALSE;
if (flags) { *flags = 0; if (info.Inherit) *flags |= HANDLE_FLAG_INHERIT; if (info.ProtectFromClose) *flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE; } return TRUE;}
/*********************************************************************** * GetPriorityClass (kernelbase.@) */DWORD WINAPI DECLSPEC_HOTPATCH GetPriorityClass( HANDLE process ){ PROCESS_BASIC_INFORMATION pbi;
if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL ))) return 0;
switch (pbi.BasePriority) { case PROCESS_PRIOCLASS_IDLE: return IDLE_PRIORITY_CLASS; case PROCESS_PRIOCLASS_BELOW_NORMAL: return BELOW_NORMAL_PRIORITY_CLASS; case PROCESS_PRIOCLASS_NORMAL: return NORMAL_PRIORITY_CLASS; case PROCESS_PRIOCLASS_ABOVE_NORMAL: return ABOVE_NORMAL_PRIORITY_CLASS; case PROCESS_PRIOCLASS_HIGH: return HIGH_PRIORITY_CLASS; case PROCESS_PRIOCLASS_REALTIME: return REALTIME_PRIORITY_CLASS; default: return 0; }}
/*********************************************************************** * GetProcessGroupAffinity (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetProcessGroupAffinity( HANDLE process, USHORT *count, USHORT *array ){ FIXME( "(%p,%p,%p): stub\n", process, count, array ); SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); return FALSE;}
/****************************************************************** * GetProcessHandleCount (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetProcessHandleCount( HANDLE process, DWORD *count ){ return set_ntstatus( NtQueryInformationProcess( process, ProcessHandleCount, count, sizeof(*count), NULL ));}
/*********************************************************************** * GetProcessHeap (kernelbase.@) */HANDLE WINAPI kernelbase_GetProcessHeap(void){ return NtCurrentTeb()->Peb->ProcessHeap;}
/********************************************************************* * GetProcessId (kernelbase.@) */DWORD WINAPI DECLSPEC_HOTPATCH GetProcessId( HANDLE process ){ PROCESS_BASIC_INFORMATION pbi;
if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL ))) return 0; return pbi.UniqueProcessId;}
/********************************************************************** * GetProcessMitigationPolicy (kernelbase.@) */BOOL WINAPI /* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process, PROCESS_MITIGATION_POLICY policy, void *buffer, SIZE_T length ){ FIXME( "(%p, %u, %p, %Iu): stub\n", process, policy, buffer, length ); return TRUE;}
/*********************************************************************** * GetProcessPriorityBoost (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetProcessPriorityBoost( HANDLE process, PBOOL disable ){ FIXME( "(%p,%p): semi-stub\n", process, disable ); *disable = FALSE; /* report that no boost is present */ return TRUE;}
/*********************************************************************** * GetProcessShutdownParameters (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetProcessShutdownParameters( LPDWORD level, LPDWORD flags ){ *level = shutdown_priority; *flags = shutdown_flags; return TRUE;}
/********************************************************************* * GetProcessTimes (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetProcessTimes( HANDLE process, FILETIME *create, FILETIME *exit, FILETIME *kernel, FILETIME *user ){ KERNEL_USER_TIMES time;
if (!set_ntstatus( NtQueryInformationProcess( process, ProcessTimes, &time, sizeof(time), NULL ))) return FALSE;
create->dwLowDateTime = time.CreateTime.u.LowPart; create->dwHighDateTime = time.CreateTime.u.HighPart; exit->dwLowDateTime = time.ExitTime.u.LowPart; exit->dwHighDateTime = time.ExitTime.u.HighPart; kernel->dwLowDateTime = time.KernelTime.u.LowPart; kernel->dwHighDateTime = time.KernelTime.u.HighPart; user->dwLowDateTime = time.UserTime.u.LowPart; user->dwHighDateTime = time.UserTime.u.HighPart; return TRUE;}
/*********************************************************************** * GetProcessVersion (kernelbase.@) */DWORD WINAPI DECLSPEC_HOTPATCH GetProcessVersion( DWORD pid ){ SECTION_IMAGE_INFORMATION info; NTSTATUS status; HANDLE process;
if (pid && pid != GetCurrentProcessId()) { if (!(process = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid ))) return 0; status = NtQueryInformationProcess( process, ProcessImageInformation, &info, sizeof(info), NULL ); CloseHandle( process ); } else status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation, &info, sizeof(info), NULL );
if (!set_ntstatus( status )) return 0; return MAKELONG( info.MinorSubsystemVersion, info.MajorSubsystemVersion );}
/*********************************************************************** * GetProcessWorkingSetSizeEx (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH GetProcessWorkingSetSizeEx( HANDLE process, SIZE_T *minset, SIZE_T *maxset, DWORD *flags){ FIXME( "(%p,%p,%p,%p): stub\n", process, minset, maxset, flags ); /* 32 MB working set size */ if (minset) *minset = 32*1024*1024; if (maxset) *maxset = 32*1024*1024; if (flags) *flags = QUOTA_LIMITS_HARDWS_MIN_DISABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE; return TRUE;}
/****************************************************************************** * IsProcessInJob (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH IsProcessInJob( HANDLE process, HANDLE job, BOOL *result ){ NTSTATUS status = NtIsProcessInJob( process, job );
switch (status) { case STATUS_PROCESS_IN_JOB: *result = TRUE; return TRUE; case STATUS_PROCESS_NOT_IN_JOB: *result = FALSE; return TRUE; default: return set_ntstatus( status ); }}
/*********************************************************************** * IsProcessorFeaturePresent (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH IsProcessorFeaturePresent ( DWORD feature ){ return RtlIsProcessorFeaturePresent( feature );}
/********************************************************************** * IsWow64Process2 (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process2( HANDLE process, USHORT *machine, USHORT *native_machine ){ return set_ntstatus( RtlWow64GetProcessMachines( process, machine, native_machine ));}
/********************************************************************** * IsWow64Process (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process( HANDLE process, PBOOL wow64 ){ ULONG_PTR pbi; NTSTATUS status;
status = NtQueryInformationProcess( process, ProcessWow64Information, &pbi, sizeof(pbi), NULL ); if (!status) *wow64 = !!pbi; return set_ntstatus( status );}
/********************************************************************* * GetProcessInformation (kernelbase.@) */BOOL WINAPI GetProcessInformation( HANDLE process, PROCESS_INFORMATION_CLASS info_class, void *data, DWORD size ){ switch (info_class) { case ProcessMachineTypeInfo: { PROCESS_MACHINE_INFORMATION *mi = data; SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION machines[8]; NTSTATUS status; ULONG i;
if (size != sizeof(*mi)) { SetLastError(ERROR_BAD_LENGTH); return FALSE; }
status = NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process), machines, sizeof(machines), NULL ); if (status) return set_ntstatus( status );
for (i = 0; machines[i].Machine; i++) { if (machines[i].Process) { mi->ProcessMachine = machines[i].Machine; mi->Res0 = 0; mi->MachineAttributes = 0; if (machines[i].KernelMode) mi->MachineAttributes |= KernelEnabled; if (machines[i].UserMode) mi->MachineAttributes |= UserEnabled; if (machines[i].WoW64Container) mi->MachineAttributes |= Wow64Container;
return TRUE; } }
break; } default: FIXME("Unsupported information class %d.\n", info_class); }
return FALSE;}
/********************************************************************* * OpenProcess (kernelbase.@) */HANDLE WINAPI DECLSPEC_HOTPATCH OpenProcess( DWORD access, BOOL inherit, DWORD id ){ HANDLE handle; OBJECT_ATTRIBUTES attr; CLIENT_ID cid;
if (GetVersion() & 0x80000000) access = PROCESS_ALL_ACCESS;
attr.Length = sizeof(OBJECT_ATTRIBUTES); attr.RootDirectory = 0; attr.Attributes = inherit ? OBJ_INHERIT : 0; attr.ObjectName = NULL; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
cid.UniqueProcess = ULongToHandle(id); cid.UniqueThread = 0;
if (!set_ntstatus( NtOpenProcess( &handle, access, &attr, &cid ))) return NULL; return handle;}
/*********************************************************************** * ProcessIdToSessionId (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH ProcessIdToSessionId( DWORD pid, DWORD *id ){ HANDLE process; NTSTATUS status;
if (pid == GetCurrentProcessId()) { *id = NtCurrentTeb()->Peb->SessionId; return TRUE; } if (!(process = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid ))) return FALSE; status = NtQueryInformationProcess( process, ProcessSessionInformation, id, sizeof(*id), NULL ); CloseHandle( process ); return set_ntstatus( status );}
/*********************************************************************** * QueryProcessCycleTime (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH QueryProcessCycleTime( HANDLE process, ULONG64 *cycle ){ PROCESS_CYCLE_TIME_INFORMATION time;
if (!set_ntstatus( NtQueryInformationProcess( process, ProcessCycleTime, &time, sizeof(time), NULL ) )) return FALSE;
*cycle = time.AccumulatedCycles; return TRUE;}
/*********************************************************************** * SetErrorMode (kernelbase.@) */UINT WINAPI DECLSPEC_HOTPATCH SetErrorMode( UINT mode ){ UINT old = GetErrorMode();
NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode, &mode, sizeof(mode) ); return old;}
/************************************************************************* * SetHandleCount (kernelbase.@) */UINT WINAPI DECLSPEC_HOTPATCH SetHandleCount( UINT count ){ return count;}
/********************************************************************* * SetHandleInformation (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetHandleInformation( HANDLE handle, DWORD mask, DWORD flags ){ OBJECT_HANDLE_FLAG_INFORMATION info;
/* if not setting both fields, retrieve current value first */ if ((mask & (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE)) != (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE)) { if (!set_ntstatus( NtQueryObject( handle, ObjectHandleFlagInformation, &info, sizeof(info), NULL ))) return FALSE; } if (mask & HANDLE_FLAG_INHERIT) info.Inherit = (flags & HANDLE_FLAG_INHERIT) != 0; if (mask & HANDLE_FLAG_PROTECT_FROM_CLOSE) info.ProtectFromClose = (flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0;
return set_ntstatus( NtSetInformationObject( handle, ObjectHandleFlagInformation, &info, sizeof(info) ));}
/*********************************************************************** * SetPriorityClass (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetPriorityClass( HANDLE process, DWORD class ){ PROCESS_PRIORITY_CLASS ppc;
ppc.Foreground = FALSE; switch (class) { case IDLE_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_IDLE; break; case BELOW_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_BELOW_NORMAL; break; case NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_NORMAL; break; case ABOVE_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_ABOVE_NORMAL; break; case HIGH_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_HIGH; break; case REALTIME_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_REALTIME; break; default: SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } return set_ntstatus( NtSetInformationProcess( process, ProcessPriorityClass, &ppc, sizeof(ppc) ));}
/*********************************************************************** * SetProcessAffinityUpdateMode (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetProcessAffinityUpdateMode( HANDLE process, DWORD flags ){ FIXME( "(%p,0x%08lx): stub\n", process, flags ); SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); return FALSE;}
/*********************************************************************** * SetProcessGroupAffinity (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetProcessGroupAffinity( HANDLE process, const GROUP_AFFINITY *new, GROUP_AFFINITY *old ){ FIXME( "(%p,%p,%p): stub\n", process, new, old ); SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); return FALSE;}
/********************************************************************** * SetProcessMitigationPolicy (kernelbase.@) */BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy, void *buffer, SIZE_T length ){ FIXME( "(%d, %p, %Iu): stub\n", policy, buffer, length ); return TRUE;}
/*********************************************************************** * SetProcessPriorityBoost (kernelbase.@) */BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process, BOOL disable ){ FIXME( "(%p,%d): stub\n", process, disable ); return TRUE;}
/*********************************************************************** * SetProcessShutdownParameters (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetProcessShutdownParameters( DWORD level, DWORD flags ){ FIXME( "(%08lx, %08lx): partial stub.\n", level, flags ); shutdown_flags = flags; shutdown_priority = level; return TRUE;}
/*********************************************************************** * SetProcessWorkingSetSizeEx (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetProcessWorkingSetSizeEx( HANDLE process, SIZE_T minset, SIZE_T maxset, DWORD flags ){ return TRUE;}
/****************************************************************************** * TerminateProcess (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code ){ if (!handle) { SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } return set_ntstatus( NtTerminateProcess( handle, exit_code ));}
/*********************************************************************** * Process startup information ***********************************************************************/
static char *command_lineA;static WCHAR *command_lineW;
/****************************************************************** * init_startup_info */void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params ){ ANSI_STRING ansi;
command_lineW = params->CommandLine.Buffer; if (!RtlUnicodeStringToAnsiString( &ansi, ¶ms->CommandLine, TRUE )) command_lineA = ansi.Buffer;}
/********************************************************************** * BaseFlushAppcompatCache (kernelbase.@) */BOOL WINAPI BaseFlushAppcompatCache(void){ FIXME( "stub\n" ); SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); return FALSE;}
/*********************************************************************** * GetCommandLineA (kernelbase.@) */LPSTR WINAPI GetCommandLineA(void){ return command_lineA;}
/*********************************************************************** * GetCommandLineW (kernelbase.@) */LPWSTR WINAPI GetCommandLineW(void){ return command_lineW;}
/*********************************************************************** * GetStartupInfoW (kernelbase.@) */void WINAPI DECLSPEC_HOTPATCH GetStartupInfoW( STARTUPINFOW *info ){ RTL_USER_PROCESS_PARAMETERS *params;
RtlAcquirePebLock();
params = RtlGetCurrentPeb()->ProcessParameters;
info->cb = sizeof(*info); info->lpReserved = NULL; info->lpDesktop = params->Desktop.Buffer; info->lpTitle = params->WindowTitle.Buffer; info->dwX = params->dwX; info->dwY = params->dwY; info->dwXSize = params->dwXSize; info->dwYSize = params->dwYSize; info->dwXCountChars = params->dwXCountChars; info->dwYCountChars = params->dwYCountChars; info->dwFillAttribute = params->dwFillAttribute; info->dwFlags = params->dwFlags; info->wShowWindow = params->wShowWindow; info->cbReserved2 = params->RuntimeInfo.MaximumLength; info->lpReserved2 = params->RuntimeInfo.MaximumLength ? (void *)params->RuntimeInfo.Buffer : NULL; if (params->dwFlags & STARTF_USESTDHANDLES) { info->hStdInput = params->hStdInput; info->hStdOutput = params->hStdOutput; info->hStdError = params->hStdError; } RtlReleasePebLock();}
/*********************************************************************** * GetStdHandle (kernelbase.@) */HANDLE WINAPI DECLSPEC_HOTPATCH GetStdHandle( DWORD std_handle ){ switch (std_handle) { case STD_INPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdInput; case STD_OUTPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; case STD_ERROR_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdError; } SetLastError( ERROR_INVALID_HANDLE ); return INVALID_HANDLE_VALUE;}
/*********************************************************************** * SetStdHandle (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle( DWORD std_handle, HANDLE handle ){ switch (std_handle) { case STD_INPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdInput = handle; return TRUE; case STD_OUTPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdOutput = handle; return TRUE; case STD_ERROR_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdError = handle; return TRUE; } SetLastError( ERROR_INVALID_HANDLE ); return FALSE;}
/*********************************************************************** * SetStdHandleEx (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandleEx( DWORD std_handle, HANDLE handle, HANDLE *prev ){ HANDLE *ptr;
switch (std_handle) { case STD_INPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdInput; break; case STD_OUTPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; break; case STD_ERROR_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdError; break; default: SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (prev) *prev = *ptr; *ptr = handle; return TRUE;}
/*********************************************************************** * Process environment ***********************************************************************/
static inline SIZE_T get_env_length( const WCHAR *env ){ const WCHAR *end = env; while (*end) end += lstrlenW(end) + 1; return end + 1 - env;}
/*********************************************************************** * ExpandEnvironmentStringsA (kernelbase.@) */DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, DWORD count ){ UNICODE_STRING us_src; PWSTR dstW = NULL; DWORD count_neededW; DWORD count_neededA = 0;
RtlCreateUnicodeStringFromAsciiz( &us_src, src );
/* We always need to call ExpandEnvironmentStringsW, since we need the result to calculate the needed buffer size */ count_neededW = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0 ); if (!(dstW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, count_neededW * sizeof(WCHAR) ))) goto cleanup; count_neededW = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count_neededW );
/* Calculate needed buffer */ count_neededA = WideCharToMultiByte( CP_ACP, 0, dstW, count_neededW, NULL, 0, NULL, NULL );
/* If provided buffer is enough, do actual conversion */ if (count > count_neededA) count_neededA = WideCharToMultiByte( CP_ACP, 0, dstW, count_neededW, dst, count, NULL, NULL ); else if(dst) *dst = 0;
cleanup: RtlFreeUnicodeString( &us_src ); HeapFree( GetProcessHeap(), 0, dstW );
if (count_neededA >= count) /* When the buffer is too small, native over-reports by one byte */ return count_neededA + 1; return count_neededA;}
/*********************************************************************** * ExpandEnvironmentStringsW (kernelbase.@) */DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len ){ UNICODE_STRING us_src, us_dst; NTSTATUS status; DWORD res;
TRACE( "(%s %p %lu)\n", debugstr_w(src), dst, len );
RtlInitUnicodeString( &us_src, src );
/* make sure we don't overflow the maximum UNICODE_STRING size */ len = min( len, UNICODE_STRING_MAX_CHARS );
us_dst.Length = 0; us_dst.MaximumLength = len * sizeof(WCHAR); us_dst.Buffer = dst;
res = 0; status = RtlExpandEnvironmentStrings_U( NULL, &us_src, &us_dst, &res ); res /= sizeof(WCHAR); if (status != STATUS_BUFFER_TOO_SMALL) { if(!set_ntstatus( status )) return 0; } return res;}
/*********************************************************************** * GetEnvironmentStrings (kernelbase.@) * GetEnvironmentStringsA (kernelbase.@) */LPSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsA(void){ LPWSTR env; LPSTR ret; SIZE_T lenA, lenW;
RtlAcquirePebLock(); env = NtCurrentTeb()->Peb->ProcessParameters->Environment; lenW = get_env_length( env ); lenA = WideCharToMultiByte( CP_ACP, 0, env, lenW, NULL, 0, NULL, NULL ); if ((ret = HeapAlloc( GetProcessHeap(), 0, lenA ))) WideCharToMultiByte( CP_ACP, 0, env, lenW, ret, lenA, NULL, NULL ); RtlReleasePebLock(); return ret;}
/*********************************************************************** * GetEnvironmentStringsW (kernelbase.@) */LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void){ LPWSTR ret; SIZE_T len;
RtlAcquirePebLock(); len = get_env_length( NtCurrentTeb()->Peb->ProcessParameters->Environment ) * sizeof(WCHAR); if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, NtCurrentTeb()->Peb->ProcessParameters->Environment, len ); RtlReleasePebLock(); return ret;}
/*********************************************************************** * SetEnvironmentStringsA (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsA( char *env ){ WCHAR *envW; const char *p = env; DWORD len; BOOL ret;
for (p = env; *p; p += strlen( p ) + 1);
len = MultiByteToWideChar( CP_ACP, 0, env, p - env, NULL, 0 ); if (!(envW = HeapAlloc( GetProcessHeap(), 0, len ))) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return FALSE; } MultiByteToWideChar( CP_ACP, 0, env, p - env, envW, len ); ret = SetEnvironmentStringsW( envW ); HeapFree( GetProcessHeap(), 0, envW ); return ret;}
/*********************************************************************** * SetEnvironmentStringsW (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsW( WCHAR *env ){ WCHAR *p; WCHAR *new_env; NTSTATUS status;
for (p = env; *p; p += wcslen( p ) + 1) { const WCHAR *eq = wcschr( p, '=' ); if (!eq || eq == p) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } }
if ((status = RtlCreateEnvironment( FALSE, &new_env ))) return set_ntstatus( status );
for (p = env; *p; p += wcslen( p ) + 1) { const WCHAR *eq = wcschr( p, '=' ); UNICODE_STRING var, value; var.Buffer = p; var.Length = (eq - p) * sizeof(WCHAR); RtlInitUnicodeString( &value, eq + 1 ); if ((status = RtlSetEnvironmentVariable( &new_env, &var, &value ))) { RtlDestroyEnvironment( new_env ); return set_ntstatus( status ); } }
RtlSetCurrentEnvironment( new_env, NULL ); return TRUE;}
/*********************************************************************** * GetEnvironmentVariableA (kernelbase.@) */DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size ){ UNICODE_STRING us_name, us_value; PWSTR valueW; NTSTATUS status; DWORD len, ret;
/* limit the size to sane values */ size = min( size, 32767 ); if (!(valueW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0;
RtlCreateUnicodeStringFromAsciiz( &us_name, name ); us_value.Length = 0; us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR); us_value.Buffer = valueW;
status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value ); len = us_value.Length / sizeof(WCHAR); if (status == STATUS_BUFFER_TOO_SMALL) ret = len + 1; else if (!set_ntstatus( status )) ret = 0; else if (!size) ret = len + 1; else { if (len) WideCharToMultiByte( CP_ACP, 0, valueW, len + 1, value, size, NULL, NULL ); value[len] = 0; ret = len; }
RtlFreeUnicodeString( &us_name ); HeapFree( GetProcessHeap(), 0, valueW ); return ret;}
/*********************************************************************** * GetEnvironmentVariableW (kernelbase.@) */DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size ){ UNICODE_STRING us_name, us_value; NTSTATUS status; DWORD len;
TRACE( "(%s %p %lu)\n", debugstr_w(name), val, size );
RtlInitUnicodeString( &us_name, name ); us_value.Length = 0; us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR); us_value.Buffer = val;
status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value ); len = us_value.Length / sizeof(WCHAR); if (status == STATUS_BUFFER_TOO_SMALL) return len + 1; if (!set_ntstatus( status )) return 0; if (!size) return len + 1; val[len] = 0; return len;}
/*********************************************************************** * FreeEnvironmentStringsA (kernelbase.@) * FreeEnvironmentStringsW (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH FreeEnvironmentStringsW( LPWSTR ptr ){ return HeapFree( GetProcessHeap(), 0, ptr );}
/*********************************************************************** * SetEnvironmentVariableA (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA( LPCSTR name, LPCSTR value ){ UNICODE_STRING us_name, us_value; BOOL ret;
if (!name) { SetLastError( ERROR_ENVVAR_NOT_FOUND ); return FALSE; }
RtlCreateUnicodeStringFromAsciiz( &us_name, name ); if (value) { RtlCreateUnicodeStringFromAsciiz( &us_value, value ); ret = SetEnvironmentVariableW( us_name.Buffer, us_value.Buffer ); RtlFreeUnicodeString( &us_value ); } else ret = SetEnvironmentVariableW( us_name.Buffer, NULL ); RtlFreeUnicodeString( &us_name ); return ret;}
/*********************************************************************** * SetEnvironmentVariableW (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value ){ UNICODE_STRING us_name, us_value; NTSTATUS status;
TRACE( "(%s %s)\n", debugstr_w(name), debugstr_w(value) );
if (!name) { SetLastError( ERROR_ENVVAR_NOT_FOUND ); return FALSE; }
RtlInitUnicodeString( &us_name, name ); if (value) { RtlInitUnicodeString( &us_value, value ); status = RtlSetEnvironmentVariable( NULL, &us_name, &us_value ); } else status = RtlSetEnvironmentVariable( NULL, &us_name, NULL );
return set_ntstatus( status );}
/*********************************************************************** * Process/thread attribute lists ***********************************************************************/
/*********************************************************************** * InitializeProcThreadAttributeList (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list, DWORD count, DWORD flags, SIZE_T *size ){ SIZE_T needed; BOOL ret = FALSE;
TRACE( "(%p %ld %lx %p)\n", list, count, flags, size );
needed = FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST, attrs[count] ); if (list && *size >= needed) { list->mask = 0; list->size = count; list->count = 0; list->unk = 0; ret = TRUE; } else SetLastError( ERROR_INSUFFICIENT_BUFFER );
*size = needed; return ret;}
static inline DWORD validate_proc_thread_attribute( DWORD_PTR attr, SIZE_T size ){ switch (attr) { case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: if (size != sizeof(HANDLE)) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS: if (size != sizeof(ULONG)) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_HANDLE_LIST: if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR: if (size != sizeof(PROCESSOR_NUMBER)) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY: if (size != sizeof(DWORD) && size != sizeof(DWORD64)) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY: if (size != sizeof(DWORD) && size != sizeof(DWORD64) && size != sizeof(DWORD64) * 2) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: if (size != sizeof(HPCON)) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_JOB_LIST: if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size) return ERROR_BAD_LENGTH; break; case PROC_THREAD_ATTRIBUTE_MACHINE_TYPE: if (size != sizeof(USHORT)) return ERROR_BAD_LENGTH; break; default: FIXME( "Unhandled attribute %Iu\n", attr & PROC_THREAD_ATTRIBUTE_NUMBER ); return ERROR_NOT_SUPPORTED; } return 0;}
/*********************************************************************** * UpdateProcThreadAttribute (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST *list, DWORD flags, DWORD_PTR attr, void *value, SIZE_T size, void *prev_ret, SIZE_T *size_ret ){ DWORD mask, err; struct proc_thread_attr *entry;
TRACE( "(%p %lx %08Ix %p %Id %p %p)\n", list, flags, attr, value, size, prev_ret, size_ret );
if (list->count >= list->size) { SetLastError( ERROR_GEN_FAILURE ); return FALSE; } if ((err = validate_proc_thread_attribute( attr, size ))) { SetLastError( err ); return FALSE; }
mask = 1 << (attr & PROC_THREAD_ATTRIBUTE_NUMBER); if (list->mask & mask) { SetLastError( ERROR_OBJECT_NAME_EXISTS ); return FALSE; } list->mask |= mask;
entry = list->attrs + list->count; entry->attr = attr; entry->size = size; entry->value = value; list->count++; return TRUE;}
/*********************************************************************** * DeleteProcThreadAttributeList (kernelbase.@) */void WINAPI DECLSPEC_HOTPATCH DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list ){ return;}
/*********************************************************************** * CompareObjectHandles (kernelbase.@) */BOOL WINAPI DECLSPEC_HOTPATCH CompareObjectHandles( HANDLE first, HANDLE second ){ return set_ntstatus( NtCompareObjects( first, second ));}