Reactos
at master 1872 lines 67 kB view raw
1/* 2 * Win32 processes 3 * 4 * Copyright 1996, 1998 Alexandre Julliard 5 * 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. 10 * 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. 15 * 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 19 */ 20 21#include <stdarg.h> 22#include <string.h> 23 24#include "ntstatus.h" 25#define WIN32_NO_STATUS 26#include "windef.h" 27#include "winbase.h" 28#include "winnls.h" 29#include "wincontypes.h" 30#include "winternl.h" 31 32#include "kernelbase.h" 33#include "wine/debug.h" 34#include "wine/condrv.h" 35 36WINE_DEFAULT_DEBUG_CHANNEL(process); 37 38static DWORD shutdown_flags = 0; 39static DWORD shutdown_priority = 0x280; 40 41/*********************************************************************** 42 * Processes 43 ***********************************************************************/ 44 45 46/*********************************************************************** 47 * find_exe_file 48 */ 49static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, DWORD buflen ) 50{ 51 WCHAR *load_path; 52 BOOL ret; 53 54 if (!set_ntstatus( RtlGetExePath( name, &load_path ))) return FALSE; 55 56 TRACE( "looking for %s in %s\n", debugstr_w(name), debugstr_w(load_path) ); 57 58 ret = (SearchPathW( load_path, name, L".exe", buflen, buffer, NULL ) || 59 /* not found, try without extension in case it is a Unix app */ 60 SearchPathW( load_path, name, NULL, buflen, buffer, NULL )); 61 62 if (ret) /* make sure it can be opened, SearchPathW also returns directories */ 63 { 64 HANDLE handle = CreateFileW( buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, 65 NULL, OPEN_EXISTING, 0, 0 ); 66 if ((ret = (handle != INVALID_HANDLE_VALUE))) CloseHandle( handle ); 67 } 68 RtlReleasePath( load_path ); 69 return ret; 70} 71 72 73/************************************************************************* 74 * get_file_name 75 * 76 * Helper for CreateProcess: retrieve the file name to load from the 77 * app name and command line. Store the file name in buffer, and 78 * return a possibly modified command line. 79 */ 80static WCHAR *get_file_name( WCHAR *cmdline, WCHAR *buffer, DWORD buflen ) 81{ 82 WCHAR *name, *pos, *first_space, *ret = NULL; 83 const WCHAR *p; 84 85 /* first check for a quoted file name */ 86 87 if (cmdline[0] == '"' && (p = wcschr( cmdline + 1, '"' ))) 88 { 89 int len = p - cmdline - 1; 90 /* extract the quoted portion as file name */ 91 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL; 92 memcpy( name, cmdline + 1, len * sizeof(WCHAR) ); 93 name[len] = 0; 94 95 if (!find_exe_file( name, buffer, buflen )) goto done; 96 ret = cmdline; /* no change necessary */ 97 goto done; 98 } 99 100 /* now try the command-line word by word */ 101 102 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR) ))) 103 return NULL; 104 pos = name; 105 p = cmdline; 106 first_space = NULL; 107 108 for (;;) 109 { 110 while (*p && *p != ' ' && *p != '\t') *pos++ = *p++; 111 *pos = 0; 112 if (find_exe_file( name, buffer, buflen )) 113 { 114 ret = cmdline; 115 break; 116 } 117 if (!first_space) first_space = pos; 118 if (!(*pos++ = *p++)) break; 119 } 120 121 if (!ret) 122 { 123 SetLastError( ERROR_FILE_NOT_FOUND ); 124 } 125 else if (first_space) /* build a new command-line with quotes */ 126 { 127 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline) + 3) * sizeof(WCHAR) ))) 128 goto done; 129 swprintf( ret, lstrlenW(cmdline) + 3, L"\"%s\"%s", name, p ); 130 } 131 132 done: 133 RtlFreeHeap( GetProcessHeap(), 0, name ); 134 return ret; 135} 136 137 138/*********************************************************************** 139 * create_process_params 140 */ 141static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename, const WCHAR *cmdline, 142 const WCHAR *cur_dir, void *env, DWORD flags, 143 const STARTUPINFOW *startup ) 144{ 145 RTL_USER_PROCESS_PARAMETERS *params; 146 UNICODE_STRING imageW, curdirW, cmdlineW, titleW, desktopW, runtimeW, newdirW; 147 WCHAR imagepath[MAX_PATH]; 148 WCHAR *envW = env; 149 150 if (!GetLongPathNameW( filename, imagepath, MAX_PATH )) lstrcpynW( imagepath, filename, MAX_PATH ); 151 if (!GetFullPathNameW( imagepath, MAX_PATH, imagepath, NULL )) lstrcpynW( imagepath, filename, MAX_PATH ); 152 153 if (env && !(flags & CREATE_UNICODE_ENVIRONMENT)) /* convert environment to unicode */ 154 { 155 char *e = env; 156 DWORD lenW; 157 158 while (*e) e += strlen(e) + 1; 159 e++; /* final null */ 160 lenW = MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, NULL, 0 ); 161 if ((envW = RtlAllocateHeap( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) 162 MultiByteToWideChar( CP_ACP, 0, env, e - (char *)env, envW, lenW ); 163 } 164 165 newdirW.Buffer = NULL; 166 if (cur_dir) 167 { 168 if (RtlDosPathNameToNtPathName_U( cur_dir, &newdirW, NULL, NULL )) 169 cur_dir = newdirW.Buffer + 4; /* skip \??\ prefix */ 170 else 171 cur_dir = NULL; 172 } 173 RtlInitUnicodeString( &imageW, imagepath ); 174 RtlInitUnicodeString( &curdirW, cur_dir ); 175 RtlInitUnicodeString( &cmdlineW, cmdline ); 176 RtlInitUnicodeString( &titleW, startup->lpTitle ? startup->lpTitle : imagepath ); 177 RtlInitUnicodeString( &desktopW, startup->lpDesktop ); 178 runtimeW.Buffer = (WCHAR *)startup->lpReserved2; 179 runtimeW.Length = runtimeW.MaximumLength = startup->cbReserved2; 180 if (RtlCreateProcessParametersEx( &params, &imageW, NULL, cur_dir ? &curdirW : NULL, 181 &cmdlineW, envW, &titleW, &desktopW, 182 NULL, &runtimeW, PROCESS_PARAMS_FLAG_NORMALIZED )) 183 { 184 RtlFreeUnicodeString( &newdirW ); 185 if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW ); 186 return NULL; 187 } 188 RtlFreeUnicodeString( &newdirW ); 189 190 if (!(flags & CREATE_NEW_PROCESS_GROUP)) 191 params->ProcessGroupId = NtCurrentTeb()->Peb->ProcessParameters->ProcessGroupId; 192 else if (!(flags & CREATE_NEW_CONSOLE)) 193 params->ConsoleFlags = 1; 194 195 if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; 196 else if (!(flags & DETACHED_PROCESS)) 197 { 198 if (flags & CREATE_NO_WINDOW) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC_NO_WINDOW; 199 else 200 { 201 params->ConsoleHandle = NtCurrentTeb()->Peb->ProcessParameters->ConsoleHandle; 202 if (!params->ConsoleHandle) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; 203 } 204 } 205 206 if (startup->dwFlags & STARTF_USESTDHANDLES) 207 { 208 params->hStdInput = startup->hStdInput; 209 params->hStdOutput = startup->hStdOutput; 210 params->hStdError = startup->hStdError; 211 } 212 else if (!(flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE))) 213 { 214 params->hStdInput = NtCurrentTeb()->Peb->ProcessParameters->hStdInput; 215 params->hStdOutput = NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; 216 params->hStdError = NtCurrentTeb()->Peb->ProcessParameters->hStdError; 217 } 218 219 if (params->hStdInput == INVALID_HANDLE_VALUE) params->hStdInput = NULL; 220 if (params->hStdOutput == INVALID_HANDLE_VALUE) params->hStdOutput = NULL; 221 if (params->hStdError == INVALID_HANDLE_VALUE) params->hStdError = NULL; 222 223 params->dwX = startup->dwX; 224 params->dwY = startup->dwY; 225 params->dwXSize = startup->dwXSize; 226 params->dwYSize = startup->dwYSize; 227 params->dwXCountChars = startup->dwXCountChars; 228 params->dwYCountChars = startup->dwYCountChars; 229 params->dwFillAttribute = startup->dwFillAttribute; 230 params->dwFlags = startup->dwFlags; 231 params->wShowWindow = startup->wShowWindow; 232 233 if (envW != env) RtlFreeHeap( GetProcessHeap(), 0, envW ); 234 return params; 235} 236 237struct proc_thread_attr 238{ 239 DWORD_PTR attr; 240 SIZE_T size; 241 void *value; 242}; 243 244struct _PROC_THREAD_ATTRIBUTE_LIST 245{ 246 DWORD mask; /* bitmask of items in list */ 247 DWORD size; /* max number of items in list */ 248 DWORD count; /* number of items in list */ 249 DWORD pad; 250 DWORD_PTR unk; 251 struct proc_thread_attr attrs[1]; 252}; 253 254/*********************************************************************** 255 * create_nt_process 256 */ 257static NTSTATUS create_nt_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, 258 SECURITY_ATTRIBUTES *tsa, DWORD process_flags, 259 RTL_USER_PROCESS_PARAMETERS *params, 260 RTL_USER_PROCESS_INFORMATION *info, 261 HANDLE parent, USHORT machine, 262 const struct proc_thread_attr *handle_list, 263 const struct proc_thread_attr *job_list) 264{ 265 OBJECT_ATTRIBUTES process_attr, thread_attr; 266 PS_CREATE_INFO create_info; 267 ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[9] ) / sizeof(ULONG_PTR)]; 268 PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer; 269 UNICODE_STRING nameW; 270 NTSTATUS status; 271 UINT pos = 0; 272 273 if (!params->ImagePathName.Buffer[0]) return STATUS_OBJECT_PATH_NOT_FOUND; 274 status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nameW, NULL, NULL ); 275 if (!status) 276 { 277 RtlNormalizeProcessParams( params ); 278 279 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_NAME; 280 attr->Attributes[pos].Size = nameW.Length; 281 attr->Attributes[pos].ValuePtr = nameW.Buffer; 282 attr->Attributes[pos].ReturnLength = NULL; 283 pos++; 284 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_CLIENT_ID; 285 attr->Attributes[pos].Size = sizeof(info->ClientId); 286 attr->Attributes[pos].ValuePtr = &info->ClientId; 287 attr->Attributes[pos].ReturnLength = NULL; 288 pos++; 289 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_INFO; 290 attr->Attributes[pos].Size = sizeof(info->ImageInformation); 291 attr->Attributes[pos].ValuePtr = &info->ImageInformation; 292 attr->Attributes[pos].ReturnLength = NULL; 293 pos++; 294 if (parent) 295 { 296 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_PARENT_PROCESS; 297 attr->Attributes[pos].Size = sizeof(parent); 298 attr->Attributes[pos].ValuePtr = parent; 299 attr->Attributes[pos].ReturnLength = NULL; 300 pos++; 301 } 302 if ((process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES) && handle_list) 303 { 304 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_HANDLE_LIST; 305 attr->Attributes[pos].Size = handle_list->size; 306 attr->Attributes[pos].ValuePtr = handle_list->value; 307 attr->Attributes[pos].ReturnLength = NULL; 308 pos++; 309 } 310 if (token) 311 { 312 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_TOKEN; 313 attr->Attributes[pos].Size = sizeof(token); 314 attr->Attributes[pos].ValuePtr = token; 315 attr->Attributes[pos].ReturnLength = NULL; 316 pos++; 317 } 318 if (debug) 319 { 320 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_DEBUG_PORT; 321 attr->Attributes[pos].Size = sizeof(debug); 322 attr->Attributes[pos].ValuePtr = debug; 323 attr->Attributes[pos].ReturnLength = NULL; 324 pos++; 325 } 326 if (job_list) 327 { 328 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_JOB_LIST; 329 attr->Attributes[pos].Size = job_list->size; 330 attr->Attributes[pos].ValuePtr = job_list->value; 331 attr->Attributes[pos].ReturnLength = NULL; 332 pos++; 333 } 334 if (machine) 335 { 336 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_MACHINE_TYPE; 337 attr->Attributes[pos].Size = sizeof(machine); 338 attr->Attributes[pos].Value = machine; 339 attr->Attributes[pos].ReturnLength = NULL; 340 pos++; 341 } 342 attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] ); 343 344 InitializeObjectAttributes( &process_attr, NULL, 0, NULL, psa ? psa->lpSecurityDescriptor : NULL ); 345 InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, tsa ? tsa->lpSecurityDescriptor : NULL ); 346 347 status = NtCreateUserProcess( &info->Process, &info->Thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, 348 &process_attr, &thread_attr, process_flags, 349 THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params, 350 &create_info, attr ); 351 352 RtlFreeUnicodeString( &nameW ); 353 } 354 return status; 355} 356 357 358/*********************************************************************** 359 * create_vdm_process 360 */ 361static NTSTATUS create_vdm_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, 362 SECURITY_ATTRIBUTES *tsa, DWORD flags, 363 RTL_USER_PROCESS_PARAMETERS *params, 364 RTL_USER_PROCESS_INFORMATION *info ) 365{ 366 const WCHAR *winevdm = (is_win64 || is_wow64 ? 367 L"C:\\windows\\syswow64\\winevdm.exe" : 368 L"C:\\windows\\system32\\winevdm.exe"); 369 WCHAR *newcmdline; 370 NTSTATUS status; 371 UINT len; 372 373 len = (lstrlenW(params->ImagePathName.Buffer) + lstrlenW(params->CommandLine.Buffer) + 374 lstrlenW(winevdm) + 16); 375 376 if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 377 return STATUS_NO_MEMORY; 378 379 swprintf( newcmdline, len, L"%s --app-name \"%s\" %s", 380 winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer ); 381 RtlInitUnicodeString( &params->ImagePathName, winevdm ); 382 RtlInitUnicodeString( &params->CommandLine, newcmdline ); 383 status = create_nt_process( token, debug, psa, tsa, flags, params, info, 0, 0, NULL, NULL ); 384 HeapFree( GetProcessHeap(), 0, newcmdline ); 385 return status; 386} 387 388 389/*********************************************************************** 390 * create_cmd_process 391 */ 392static NTSTATUS create_cmd_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, 393 SECURITY_ATTRIBUTES *tsa, DWORD flags, 394 RTL_USER_PROCESS_PARAMETERS *params, 395 RTL_USER_PROCESS_INFORMATION *info ) 396{ 397 WCHAR comspec[MAX_PATH]; 398 WCHAR *newcmdline; 399 NTSTATUS status; 400 UINT len; 401 402 if (!GetEnvironmentVariableW( L"COMSPEC", comspec, ARRAY_SIZE( comspec ))) 403 lstrcpyW( comspec, L"C:\\windows\\system32\\cmd.exe" ); 404 405 len = lstrlenW(comspec) + 7 + lstrlenW(params->CommandLine.Buffer) + 2; 406 if (!(newcmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 407 return STATUS_NO_MEMORY; 408 409 swprintf( newcmdline, len, L"%s /s/c \"%s\"", comspec, params->CommandLine.Buffer ); 410 RtlInitUnicodeString( &params->ImagePathName, comspec ); 411 RtlInitUnicodeString( &params->CommandLine, newcmdline ); 412 status = create_nt_process( token, debug, psa, tsa, flags, params, info, 0, 0, NULL, NULL ); 413 RtlFreeHeap( GetProcessHeap(), 0, newcmdline ); 414 return status; 415} 416 417 418/********************************************************************* 419 * CloseHandle (kernelbase.@) 420 */ 421BOOL WINAPI DECLSPEC_HOTPATCH CloseHandle( HANDLE handle ) 422{ 423 if (handle == (HANDLE)STD_INPUT_HANDLE) 424 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdInput, 0 ); 425 else if (handle == (HANDLE)STD_OUTPUT_HANDLE) 426 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput, 0 ); 427 else if (handle == (HANDLE)STD_ERROR_HANDLE) 428 handle = InterlockedExchangePointer( &NtCurrentTeb()->Peb->ProcessParameters->hStdError, 0 ); 429 430 return set_ntstatus( NtClose( handle )); 431} 432 433 434/********************************************************************** 435 * CreateProcessAsUserA (kernelbase.@) 436 */ 437BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserA( HANDLE token, const char *app_name, char *cmd_line, 438 SECURITY_ATTRIBUTES *process_attr, 439 SECURITY_ATTRIBUTES *thread_attr, 440 BOOL inherit, DWORD flags, void *env, 441 const char *cur_dir, STARTUPINFOA *startup_info, 442 PROCESS_INFORMATION *info ) 443{ 444 return CreateProcessInternalA( token, app_name, cmd_line, process_attr, thread_attr, 445 inherit, flags, env, cur_dir, startup_info, info, NULL ); 446} 447 448 449/********************************************************************** 450 * CreateProcessAsUserW (kernelbase.@) 451 */ 452BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line, 453 SECURITY_ATTRIBUTES *process_attr, 454 SECURITY_ATTRIBUTES *thread_attr, 455 BOOL inherit, DWORD flags, void *env, 456 const WCHAR *cur_dir, STARTUPINFOW *startup_info, 457 PROCESS_INFORMATION *info ) 458{ 459 return CreateProcessInternalW( token, app_name, cmd_line, process_attr, thread_attr, 460 inherit, flags, env, cur_dir, startup_info, info, NULL ); 461} 462 463/********************************************************************** 464 * CreateProcessInternalA (kernelbase.@) 465 */ 466BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalA( HANDLE token, const char *app_name, char *cmd_line, 467 SECURITY_ATTRIBUTES *process_attr, 468 SECURITY_ATTRIBUTES *thread_attr, 469 BOOL inherit, DWORD flags, void *env, 470 const char *cur_dir, STARTUPINFOA *startup_info, 471 PROCESS_INFORMATION *info, HANDLE *new_token ) 472{ 473 BOOL ret = FALSE; 474 WCHAR *app_nameW = NULL, *cmd_lineW = NULL, *cur_dirW = NULL; 475 UNICODE_STRING desktopW, titleW; 476 STARTUPINFOEXW infoW; 477 478 desktopW.Buffer = NULL; 479 titleW.Buffer = NULL; 480 if (app_name && !(app_nameW = file_name_AtoW( app_name, TRUE ))) goto done; 481 if (cmd_line && !(cmd_lineW = file_name_AtoW( cmd_line, TRUE ))) goto done; 482 if (cur_dir && !(cur_dirW = file_name_AtoW( cur_dir, TRUE ))) goto done; 483 484 if (startup_info->lpDesktop) RtlCreateUnicodeStringFromAsciiz( &desktopW, startup_info->lpDesktop ); 485 if (startup_info->lpTitle) RtlCreateUnicodeStringFromAsciiz( &titleW, startup_info->lpTitle ); 486 487 memcpy( &infoW.StartupInfo, startup_info, sizeof(infoW.StartupInfo) ); 488 infoW.StartupInfo.lpDesktop = desktopW.Buffer; 489 infoW.StartupInfo.lpTitle = titleW.Buffer; 490 491 if (flags & EXTENDED_STARTUPINFO_PRESENT) 492 infoW.lpAttributeList = ((STARTUPINFOEXW *)startup_info)->lpAttributeList; 493 494 ret = CreateProcessInternalW( token, app_nameW, cmd_lineW, process_attr, thread_attr, 495 inherit, flags, env, cur_dirW, (STARTUPINFOW *)&infoW, info, new_token ); 496done: 497 RtlFreeHeap( GetProcessHeap(), 0, app_nameW ); 498 RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW ); 499 RtlFreeHeap( GetProcessHeap(), 0, cur_dirW ); 500 RtlFreeUnicodeString( &desktopW ); 501 RtlFreeUnicodeString( &titleW ); 502 return ret; 503} 504 505/********************************************************************** 506 * CreateProcessInternalW (kernelbase.@) 507 */ 508BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR *app_name, WCHAR *cmd_line, 509 SECURITY_ATTRIBUTES *process_attr, 510 SECURITY_ATTRIBUTES *thread_attr, 511 BOOL inherit, DWORD flags, void *env, 512 const WCHAR *cur_dir, STARTUPINFOW *startup_info, 513 PROCESS_INFORMATION *info, HANDLE *new_token ) 514{ 515 const struct proc_thread_attr *handle_list = NULL, *job_list = NULL; 516 WCHAR name[MAX_PATH]; 517 WCHAR *p, *tidy_cmdline = cmd_line; 518 RTL_USER_PROCESS_PARAMETERS *params = NULL; 519 RTL_USER_PROCESS_INFORMATION rtl_info; 520 HANDLE parent = 0, debug = 0; 521 ULONG nt_flags = 0; 522 USHORT machine = 0; 523 NTSTATUS status; 524 525 /* Process the AppName and/or CmdLine to get module name and path */ 526 527 TRACE( "app %s cmdline %s\n", debugstr_w(app_name), debugstr_w(cmd_line) ); 528 529 if (new_token) FIXME( "No support for returning created process token\n" ); 530 531 if (app_name) 532 { 533 if (!cmd_line || !cmd_line[0]) /* no command-line, create one */ 534 { 535 if (!(tidy_cmdline = RtlAllocateHeap( GetProcessHeap(), 0, (lstrlenW(app_name)+3) * sizeof(WCHAR) ))) 536 return FALSE; 537 swprintf( tidy_cmdline, lstrlenW(app_name) + 3, L"\"%s\"", app_name ); 538 } 539 } 540 else 541 { 542 if (!(tidy_cmdline = get_file_name( cmd_line, name, ARRAY_SIZE(name) ))) return FALSE; 543 app_name = name; 544 } 545 546 /* Warn if unsupported features are used */ 547 548 if (flags & (IDLE_PRIORITY_CLASS | HIGH_PRIORITY_CLASS | REALTIME_PRIORITY_CLASS | 549 CREATE_DEFAULT_ERROR_MODE | PROFILE_USER | PROFILE_KERNEL | PROFILE_SERVER)) 550 WARN( "(%s,...): ignoring some flags in %lx\n", debugstr_w(app_name), flags ); 551 552 if (cur_dir) 553 { 554 DWORD attr = GetFileAttributesW( cur_dir ); 555 if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY)) 556 { 557 status = STATUS_NOT_A_DIRECTORY; 558 goto done; 559 } 560 } 561 562 info->hThread = info->hProcess = 0; 563 info->dwProcessId = info->dwThreadId = 0; 564 565 if (!(params = create_process_params( app_name, tidy_cmdline, cur_dir, env, flags, startup_info ))) 566 { 567 status = STATUS_NO_MEMORY; 568 goto done; 569 } 570 571 if (flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) 572 { 573 if ((status = DbgUiConnectToDbg())) goto done; 574 debug = DbgUiGetThreadDebugObject(); 575 } 576 577 if (flags & EXTENDED_STARTUPINFO_PRESENT) 578 { 579 struct _PROC_THREAD_ATTRIBUTE_LIST *attrs = 580 (struct _PROC_THREAD_ATTRIBUTE_LIST *)((STARTUPINFOEXW *)startup_info)->lpAttributeList; 581 unsigned int i; 582 583 if (attrs) 584 { 585 for (i = 0; i < attrs->count; ++i) 586 { 587 switch(attrs->attrs[i].attr) 588 { 589 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: 590 parent = *(HANDLE *)attrs->attrs[i].value; 591 TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent); 592 if (!parent) 593 { 594 status = STATUS_INVALID_HANDLE; 595 goto done; 596 } 597 break; 598 case PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS: 599 FIXME("PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS %lx.\n", *(ULONG *)attrs->attrs[i].value); 600 break; 601 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST: 602 handle_list = &attrs->attrs[i]; 603 TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs->attrs[i].size / sizeof(HANDLE)); 604 break; 605 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: 606 { 607 struct pseudo_console *console = attrs->attrs[i].value; 608 TRACE( "PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE %p reference %p\n", 609 console, console->reference ); 610 params->ConsoleHandle = console->reference; 611 break; 612 } 613 case PROC_THREAD_ATTRIBUTE_JOB_LIST: 614 job_list = &attrs->attrs[i]; 615 TRACE( "PROC_THREAD_ATTRIBUTE_JOB_LIST handle count %Iu.\n", 616 attrs->attrs[i].size / sizeof(HANDLE) ); 617 break; 618 case PROC_THREAD_ATTRIBUTE_MACHINE_TYPE: 619 machine = *(USHORT *)attrs->attrs[i].value; 620 TRACE( "PROC_THREAD_ATTRIBUTE_MACHINE %x.\n", machine ); 621 break; 622 default: 623 FIXME("Unsupported attribute %#Ix.\n", attrs->attrs[i].attr); 624 break; 625 } 626 } 627 } 628 } 629 630 if (inherit) nt_flags |= PROCESS_CREATE_FLAGS_INHERIT_HANDLES; 631 if (flags & DEBUG_ONLY_THIS_PROCESS) nt_flags |= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT; 632 if (flags & CREATE_BREAKAWAY_FROM_JOB) nt_flags |= PROCESS_CREATE_FLAGS_BREAKAWAY; 633 if (flags & CREATE_SUSPENDED) nt_flags |= PROCESS_CREATE_FLAGS_SUSPENDED; 634 635 status = create_nt_process( token, debug, process_attr, thread_attr, 636 nt_flags, params, &rtl_info, parent, machine, handle_list, job_list ); 637 switch (status) 638 { 639 case STATUS_SUCCESS: 640 break; 641 case STATUS_INVALID_IMAGE_WIN_16: 642 case STATUS_INVALID_IMAGE_NE_FORMAT: 643 case STATUS_INVALID_IMAGE_PROTECT: 644 TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name) ); 645 status = create_vdm_process( token, debug, process_attr, thread_attr, 646 nt_flags, params, &rtl_info ); 647 break; 648 case STATUS_INVALID_IMAGE_NOT_MZ: 649 /* check for .com or .bat extension */ 650 if (!(p = wcsrchr( app_name, '.' ))) break; 651 if (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" )) 652 { 653 TRACE( "starting %s as DOS binary\n", debugstr_w(app_name) ); 654 status = create_vdm_process( token, debug, process_attr, thread_attr, 655 nt_flags, params, &rtl_info ); 656 } 657 else if (!wcsicmp( p, L".bat" ) || !wcsicmp( p, L".cmd" )) 658 { 659 TRACE( "starting %s as batch binary\n", debugstr_w(app_name) ); 660 status = create_cmd_process( token, debug, process_attr, thread_attr, 661 nt_flags, params, &rtl_info ); 662 } 663 break; 664 } 665 666 if (!status) 667 { 668 info->hProcess = rtl_info.Process; 669 info->hThread = rtl_info.Thread; 670 info->dwProcessId = HandleToUlong( rtl_info.ClientId.UniqueProcess ); 671 info->dwThreadId = HandleToUlong( rtl_info.ClientId.UniqueThread ); 672 if (!(flags & CREATE_SUSPENDED)) NtResumeThread( rtl_info.Thread, NULL ); 673 TRACE( "started process pid %04lx tid %04lx\n", info->dwProcessId, info->dwThreadId ); 674 } 675 676 done: 677 RtlDestroyProcessParameters( params ); 678 if (tidy_cmdline != cmd_line) HeapFree( GetProcessHeap(), 0, tidy_cmdline ); 679 return set_ntstatus( status ); 680} 681 682 683/********************************************************************** 684 * CreateProcessA (kernelbase.@) 685 */ 686BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA( const char *app_name, char *cmd_line, 687 SECURITY_ATTRIBUTES *process_attr, 688 SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, 689 DWORD flags, void *env, const char *cur_dir, 690 STARTUPINFOA *startup_info, PROCESS_INFORMATION *info ) 691{ 692 return CreateProcessInternalA( NULL, app_name, cmd_line, process_attr, thread_attr, 693 inherit, flags, env, cur_dir, startup_info, info, NULL ); 694} 695 696 697/********************************************************************** 698 * CreateProcessW (kernelbase.@) 699 */ 700BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW( const WCHAR *app_name, WCHAR *cmd_line, 701 SECURITY_ATTRIBUTES *process_attr, 702 SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, 703 void *env, const WCHAR *cur_dir, STARTUPINFOW *startup_info, 704 PROCESS_INFORMATION *info ) 705{ 706 return CreateProcessInternalW( NULL, app_name, cmd_line, process_attr, thread_attr, 707 inherit, flags, env, cur_dir, startup_info, info, NULL ); 708} 709 710 711/********************************************************************** 712 * SetProcessInformation (kernelbase.@) 713 */ 714BOOL WINAPI SetProcessInformation( HANDLE process, PROCESS_INFORMATION_CLASS info_class, void *info, DWORD size ) 715{ 716 switch (info_class) 717 { 718 case ProcessMemoryPriority: 719 return set_ntstatus( NtSetInformationProcess( process, ProcessPagePriority, info, size )); 720 case ProcessPowerThrottling: 721 return set_ntstatus( NtSetInformationProcess( process, ProcessPowerThrottlingState, info, size )); 722 case ProcessLeapSecondInfo: 723 return set_ntstatus( NtSetInformationProcess( process, ProcessLeapSecondInformation, info, size )); 724 default: 725 FIXME("Unrecognized information class %d.\n", info_class); 726 return FALSE; 727 } 728} 729 730 731/********************************************************************* 732 * DuplicateHandle (kernelbase.@) 733 */ 734BOOL WINAPI DECLSPEC_HOTPATCH DuplicateHandle( HANDLE source_process, HANDLE source, 735 HANDLE dest_process, HANDLE *dest, 736 DWORD access, BOOL inherit, DWORD options ) 737{ 738 return set_ntstatus( NtDuplicateObject( source_process, source, dest_process, dest, 739 access, inherit ? OBJ_INHERIT : 0, options )); 740} 741 742 743/*********************************************************************** 744 * GetApplicationRestartSettings (kernelbase.@) 745 */ 746HRESULT WINAPI /* DECLSPEC_HOTPATCH */ GetApplicationRestartSettings( HANDLE process, WCHAR *cmdline, 747 DWORD *size, DWORD *flags ) 748{ 749 FIXME( "%p, %p, %p, %p)\n", process, cmdline, size, flags ); 750 return E_NOTIMPL; 751} 752 753 754/*********************************************************************** 755 * GetCurrentProcess (kernelbase.@) 756 */ 757HANDLE WINAPI kernelbase_GetCurrentProcess(void) 758{ 759 return (HANDLE)~(ULONG_PTR)0; 760} 761 762 763/*********************************************************************** 764 * GetCurrentProcessId (kernelbase.@) 765 */ 766DWORD WINAPI kernelbase_GetCurrentProcessId(void) 767{ 768 return HandleToULong( NtCurrentTeb()->ClientId.UniqueProcess ); 769} 770 771 772/*********************************************************************** 773 * GetErrorMode (kernelbase.@) 774 */ 775UINT WINAPI DECLSPEC_HOTPATCH GetErrorMode(void) 776{ 777 UINT mode; 778 779 NtQueryInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode, 780 &mode, sizeof(mode), NULL ); 781 return mode; 782} 783 784 785/*********************************************************************** 786 * GetExitCodeProcess (kernelbase.@) 787 */ 788BOOL WINAPI DECLSPEC_HOTPATCH GetExitCodeProcess( HANDLE process, LPDWORD exit_code ) 789{ 790 NTSTATUS status; 791 PROCESS_BASIC_INFORMATION pbi; 792 793 status = NtQueryInformationProcess( process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL ); 794 if (!status && exit_code) *exit_code = pbi.ExitStatus; 795 return set_ntstatus( status ); 796} 797 798 799/********************************************************************* 800 * GetHandleInformation (kernelbase.@) 801 */ 802BOOL WINAPI DECLSPEC_HOTPATCH GetHandleInformation( HANDLE handle, DWORD *flags ) 803{ 804 OBJECT_HANDLE_FLAG_INFORMATION info; 805 806 if (!set_ntstatus( NtQueryObject( handle, ObjectHandleFlagInformation, &info, sizeof(info), NULL ))) 807 return FALSE; 808 809 if (flags) 810 { 811 *flags = 0; 812 if (info.Inherit) *flags |= HANDLE_FLAG_INHERIT; 813 if (info.ProtectFromClose) *flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE; 814 } 815 return TRUE; 816} 817 818 819/*********************************************************************** 820 * GetPriorityClass (kernelbase.@) 821 */ 822DWORD WINAPI DECLSPEC_HOTPATCH GetPriorityClass( HANDLE process ) 823{ 824 PROCESS_BASIC_INFORMATION pbi; 825 826 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation, 827 &pbi, sizeof(pbi), NULL ))) 828 return 0; 829 830 switch (pbi.BasePriority) 831 { 832 case PROCESS_PRIOCLASS_IDLE: return IDLE_PRIORITY_CLASS; 833 case PROCESS_PRIOCLASS_BELOW_NORMAL: return BELOW_NORMAL_PRIORITY_CLASS; 834 case PROCESS_PRIOCLASS_NORMAL: return NORMAL_PRIORITY_CLASS; 835 case PROCESS_PRIOCLASS_ABOVE_NORMAL: return ABOVE_NORMAL_PRIORITY_CLASS; 836 case PROCESS_PRIOCLASS_HIGH: return HIGH_PRIORITY_CLASS; 837 case PROCESS_PRIOCLASS_REALTIME: return REALTIME_PRIORITY_CLASS; 838 default: return 0; 839 } 840} 841 842 843/*********************************************************************** 844 * GetProcessGroupAffinity (kernelbase.@) 845 */ 846BOOL WINAPI DECLSPEC_HOTPATCH GetProcessGroupAffinity( HANDLE process, USHORT *count, USHORT *array ) 847{ 848 FIXME( "(%p,%p,%p): stub\n", process, count, array ); 849 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 850 return FALSE; 851} 852 853 854/****************************************************************** 855 * GetProcessHandleCount (kernelbase.@) 856 */ 857BOOL WINAPI DECLSPEC_HOTPATCH GetProcessHandleCount( HANDLE process, DWORD *count ) 858{ 859 return set_ntstatus( NtQueryInformationProcess( process, ProcessHandleCount, 860 count, sizeof(*count), NULL )); 861} 862 863 864/*********************************************************************** 865 * GetProcessHeap (kernelbase.@) 866 */ 867HANDLE WINAPI kernelbase_GetProcessHeap(void) 868{ 869 return NtCurrentTeb()->Peb->ProcessHeap; 870} 871 872 873/********************************************************************* 874 * GetProcessId (kernelbase.@) 875 */ 876DWORD WINAPI DECLSPEC_HOTPATCH GetProcessId( HANDLE process ) 877{ 878 PROCESS_BASIC_INFORMATION pbi; 879 880 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation, 881 &pbi, sizeof(pbi), NULL ))) 882 return 0; 883 return pbi.UniqueProcessId; 884} 885 886 887/********************************************************************** 888 * GetProcessMitigationPolicy (kernelbase.@) 889 */ 890BOOL WINAPI /* DECLSPEC_HOTPATCH */ GetProcessMitigationPolicy( HANDLE process, PROCESS_MITIGATION_POLICY policy, 891 void *buffer, SIZE_T length ) 892{ 893 FIXME( "(%p, %u, %p, %Iu): stub\n", process, policy, buffer, length ); 894 return TRUE; 895} 896 897 898/*********************************************************************** 899 * GetProcessPriorityBoost (kernelbase.@) 900 */ 901BOOL WINAPI DECLSPEC_HOTPATCH GetProcessPriorityBoost( HANDLE process, PBOOL disable ) 902{ 903 FIXME( "(%p,%p): semi-stub\n", process, disable ); 904 *disable = FALSE; /* report that no boost is present */ 905 return TRUE; 906} 907 908 909/*********************************************************************** 910 * GetProcessShutdownParameters (kernelbase.@) 911 */ 912BOOL WINAPI DECLSPEC_HOTPATCH GetProcessShutdownParameters( LPDWORD level, LPDWORD flags ) 913{ 914 *level = shutdown_priority; 915 *flags = shutdown_flags; 916 return TRUE; 917} 918 919 920/********************************************************************* 921 * GetProcessTimes (kernelbase.@) 922 */ 923BOOL WINAPI DECLSPEC_HOTPATCH GetProcessTimes( HANDLE process, FILETIME *create, FILETIME *exit, 924 FILETIME *kernel, FILETIME *user ) 925{ 926 KERNEL_USER_TIMES time; 927 928 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessTimes, &time, sizeof(time), NULL ))) 929 return FALSE; 930 931 create->dwLowDateTime = time.CreateTime.u.LowPart; 932 create->dwHighDateTime = time.CreateTime.u.HighPart; 933 exit->dwLowDateTime = time.ExitTime.u.LowPart; 934 exit->dwHighDateTime = time.ExitTime.u.HighPart; 935 kernel->dwLowDateTime = time.KernelTime.u.LowPart; 936 kernel->dwHighDateTime = time.KernelTime.u.HighPart; 937 user->dwLowDateTime = time.UserTime.u.LowPart; 938 user->dwHighDateTime = time.UserTime.u.HighPart; 939 return TRUE; 940} 941 942 943/*********************************************************************** 944 * GetProcessVersion (kernelbase.@) 945 */ 946DWORD WINAPI DECLSPEC_HOTPATCH GetProcessVersion( DWORD pid ) 947{ 948 SECTION_IMAGE_INFORMATION info; 949 NTSTATUS status; 950 HANDLE process; 951 952 if (pid && pid != GetCurrentProcessId()) 953 { 954 if (!(process = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid ))) return 0; 955 status = NtQueryInformationProcess( process, ProcessImageInformation, &info, sizeof(info), NULL ); 956 CloseHandle( process ); 957 } 958 else status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation, 959 &info, sizeof(info), NULL ); 960 961 if (!set_ntstatus( status )) return 0; 962 return MAKELONG( info.MinorSubsystemVersion, info.MajorSubsystemVersion ); 963} 964 965 966/*********************************************************************** 967 * GetProcessWorkingSetSizeEx (kernelbase.@) 968 */ 969BOOL WINAPI DECLSPEC_HOTPATCH GetProcessWorkingSetSizeEx( HANDLE process, SIZE_T *minset, 970 SIZE_T *maxset, DWORD *flags) 971{ 972 FIXME( "(%p,%p,%p,%p): stub\n", process, minset, maxset, flags ); 973 /* 32 MB working set size */ 974 if (minset) *minset = 32*1024*1024; 975 if (maxset) *maxset = 32*1024*1024; 976 if (flags) *flags = QUOTA_LIMITS_HARDWS_MIN_DISABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE; 977 return TRUE; 978} 979 980 981/****************************************************************************** 982 * IsProcessInJob (kernelbase.@) 983 */ 984BOOL WINAPI DECLSPEC_HOTPATCH IsProcessInJob( HANDLE process, HANDLE job, BOOL *result ) 985{ 986 NTSTATUS status = NtIsProcessInJob( process, job ); 987 988 switch (status) 989 { 990 case STATUS_PROCESS_IN_JOB: 991 *result = TRUE; 992 return TRUE; 993 case STATUS_PROCESS_NOT_IN_JOB: 994 *result = FALSE; 995 return TRUE; 996 default: 997 return set_ntstatus( status ); 998 } 999} 1000 1001 1002/*********************************************************************** 1003 * IsProcessorFeaturePresent (kernelbase.@) 1004 */ 1005BOOL WINAPI DECLSPEC_HOTPATCH IsProcessorFeaturePresent ( DWORD feature ) 1006{ 1007 return RtlIsProcessorFeaturePresent( feature ); 1008} 1009 1010 1011/********************************************************************** 1012 * IsWow64Process2 (kernelbase.@) 1013 */ 1014BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process2( HANDLE process, USHORT *machine, USHORT *native_machine ) 1015{ 1016 return set_ntstatus( RtlWow64GetProcessMachines( process, machine, native_machine )); 1017} 1018 1019 1020/********************************************************************** 1021 * IsWow64Process (kernelbase.@) 1022 */ 1023BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process( HANDLE process, PBOOL wow64 ) 1024{ 1025 ULONG_PTR pbi; 1026 NTSTATUS status; 1027 1028 status = NtQueryInformationProcess( process, ProcessWow64Information, &pbi, sizeof(pbi), NULL ); 1029 if (!status) *wow64 = !!pbi; 1030 return set_ntstatus( status ); 1031} 1032 1033/********************************************************************* 1034 * GetProcessInformation (kernelbase.@) 1035 */ 1036BOOL WINAPI GetProcessInformation( HANDLE process, PROCESS_INFORMATION_CLASS info_class, void *data, DWORD size ) 1037{ 1038 switch (info_class) 1039 { 1040 case ProcessMachineTypeInfo: 1041 { 1042 PROCESS_MACHINE_INFORMATION *mi = data; 1043 SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION machines[8]; 1044 NTSTATUS status; 1045 ULONG i; 1046 1047 if (size != sizeof(*mi)) 1048 { 1049 SetLastError(ERROR_BAD_LENGTH); 1050 return FALSE; 1051 } 1052 1053 status = NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process), 1054 machines, sizeof(machines), NULL ); 1055 if (status) return set_ntstatus( status ); 1056 1057 for (i = 0; machines[i].Machine; i++) 1058 { 1059 if (machines[i].Process) 1060 { 1061 mi->ProcessMachine = machines[i].Machine; 1062 mi->Res0 = 0; 1063 mi->MachineAttributes = 0; 1064 if (machines[i].KernelMode) 1065 mi->MachineAttributes |= KernelEnabled; 1066 if (machines[i].UserMode) 1067 mi->MachineAttributes |= UserEnabled; 1068 if (machines[i].WoW64Container) 1069 mi->MachineAttributes |= Wow64Container; 1070 1071 return TRUE; 1072 } 1073 } 1074 1075 break; 1076 } 1077 default: 1078 FIXME("Unsupported information class %d.\n", info_class); 1079 } 1080 1081 return FALSE; 1082} 1083 1084 1085/********************************************************************* 1086 * OpenProcess (kernelbase.@) 1087 */ 1088HANDLE WINAPI DECLSPEC_HOTPATCH OpenProcess( DWORD access, BOOL inherit, DWORD id ) 1089{ 1090 HANDLE handle; 1091 OBJECT_ATTRIBUTES attr; 1092 CLIENT_ID cid; 1093 1094 if (GetVersion() & 0x80000000) access = PROCESS_ALL_ACCESS; 1095 1096 attr.Length = sizeof(OBJECT_ATTRIBUTES); 1097 attr.RootDirectory = 0; 1098 attr.Attributes = inherit ? OBJ_INHERIT : 0; 1099 attr.ObjectName = NULL; 1100 attr.SecurityDescriptor = NULL; 1101 attr.SecurityQualityOfService = NULL; 1102 1103 cid.UniqueProcess = ULongToHandle(id); 1104 cid.UniqueThread = 0; 1105 1106 if (!set_ntstatus( NtOpenProcess( &handle, access, &attr, &cid ))) return NULL; 1107 return handle; 1108} 1109 1110 1111/*********************************************************************** 1112 * ProcessIdToSessionId (kernelbase.@) 1113 */ 1114BOOL WINAPI DECLSPEC_HOTPATCH ProcessIdToSessionId( DWORD pid, DWORD *id ) 1115{ 1116 HANDLE process; 1117 NTSTATUS status; 1118 1119 if (pid == GetCurrentProcessId()) 1120 { 1121 *id = NtCurrentTeb()->Peb->SessionId; 1122 return TRUE; 1123 } 1124 if (!(process = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid ))) return FALSE; 1125 status = NtQueryInformationProcess( process, ProcessSessionInformation, id, sizeof(*id), NULL ); 1126 CloseHandle( process ); 1127 return set_ntstatus( status ); 1128} 1129 1130 1131/*********************************************************************** 1132 * QueryProcessCycleTime (kernelbase.@) 1133 */ 1134BOOL WINAPI DECLSPEC_HOTPATCH QueryProcessCycleTime( HANDLE process, ULONG64 *cycle ) 1135{ 1136 PROCESS_CYCLE_TIME_INFORMATION time; 1137 1138 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessCycleTime, &time, sizeof(time), NULL ) )) 1139 return FALSE; 1140 1141 *cycle = time.AccumulatedCycles; 1142 return TRUE; 1143} 1144 1145 1146/*********************************************************************** 1147 * SetErrorMode (kernelbase.@) 1148 */ 1149UINT WINAPI DECLSPEC_HOTPATCH SetErrorMode( UINT mode ) 1150{ 1151 UINT old = GetErrorMode(); 1152 1153 NtSetInformationProcess( GetCurrentProcess(), ProcessDefaultHardErrorMode, 1154 &mode, sizeof(mode) ); 1155 return old; 1156} 1157 1158 1159/************************************************************************* 1160 * SetHandleCount (kernelbase.@) 1161 */ 1162UINT WINAPI DECLSPEC_HOTPATCH SetHandleCount( UINT count ) 1163{ 1164 return count; 1165} 1166 1167 1168/********************************************************************* 1169 * SetHandleInformation (kernelbase.@) 1170 */ 1171BOOL WINAPI DECLSPEC_HOTPATCH SetHandleInformation( HANDLE handle, DWORD mask, DWORD flags ) 1172{ 1173 OBJECT_HANDLE_FLAG_INFORMATION info; 1174 1175 /* if not setting both fields, retrieve current value first */ 1176 if ((mask & (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE)) != 1177 (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE)) 1178 { 1179 if (!set_ntstatus( NtQueryObject( handle, ObjectHandleFlagInformation, &info, sizeof(info), NULL ))) 1180 return FALSE; 1181 } 1182 if (mask & HANDLE_FLAG_INHERIT) 1183 info.Inherit = (flags & HANDLE_FLAG_INHERIT) != 0; 1184 if (mask & HANDLE_FLAG_PROTECT_FROM_CLOSE) 1185 info.ProtectFromClose = (flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; 1186 1187 return set_ntstatus( NtSetInformationObject( handle, ObjectHandleFlagInformation, &info, sizeof(info) )); 1188} 1189 1190 1191/*********************************************************************** 1192 * SetPriorityClass (kernelbase.@) 1193 */ 1194BOOL WINAPI DECLSPEC_HOTPATCH SetPriorityClass( HANDLE process, DWORD class ) 1195{ 1196 PROCESS_PRIORITY_CLASS ppc; 1197 1198 ppc.Foreground = FALSE; 1199 switch (class) 1200 { 1201 case IDLE_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_IDLE; break; 1202 case BELOW_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_BELOW_NORMAL; break; 1203 case NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_NORMAL; break; 1204 case ABOVE_NORMAL_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_ABOVE_NORMAL; break; 1205 case HIGH_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_HIGH; break; 1206 case REALTIME_PRIORITY_CLASS: ppc.PriorityClass = PROCESS_PRIOCLASS_REALTIME; break; 1207 default: 1208 SetLastError( ERROR_INVALID_PARAMETER ); 1209 return FALSE; 1210 } 1211 return set_ntstatus( NtSetInformationProcess( process, ProcessPriorityClass, &ppc, sizeof(ppc) )); 1212} 1213 1214 1215/*********************************************************************** 1216 * SetProcessAffinityUpdateMode (kernelbase.@) 1217 */ 1218BOOL WINAPI DECLSPEC_HOTPATCH SetProcessAffinityUpdateMode( HANDLE process, DWORD flags ) 1219{ 1220 FIXME( "(%p,0x%08lx): stub\n", process, flags ); 1221 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 1222 return FALSE; 1223} 1224 1225 1226/*********************************************************************** 1227 * SetProcessGroupAffinity (kernelbase.@) 1228 */ 1229BOOL WINAPI DECLSPEC_HOTPATCH SetProcessGroupAffinity( HANDLE process, const GROUP_AFFINITY *new, 1230 GROUP_AFFINITY *old ) 1231{ 1232 FIXME( "(%p,%p,%p): stub\n", process, new, old ); 1233 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 1234 return FALSE; 1235} 1236 1237 1238/********************************************************************** 1239 * SetProcessMitigationPolicy (kernelbase.@) 1240 */ 1241BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessMitigationPolicy( PROCESS_MITIGATION_POLICY policy, 1242 void *buffer, SIZE_T length ) 1243{ 1244 FIXME( "(%d, %p, %Iu): stub\n", policy, buffer, length ); 1245 return TRUE; 1246} 1247 1248 1249/*********************************************************************** 1250 * SetProcessPriorityBoost (kernelbase.@) 1251 */ 1252BOOL WINAPI /* DECLSPEC_HOTPATCH */ SetProcessPriorityBoost( HANDLE process, BOOL disable ) 1253{ 1254 FIXME( "(%p,%d): stub\n", process, disable ); 1255 return TRUE; 1256} 1257 1258 1259/*********************************************************************** 1260 * SetProcessShutdownParameters (kernelbase.@) 1261 */ 1262BOOL WINAPI DECLSPEC_HOTPATCH SetProcessShutdownParameters( DWORD level, DWORD flags ) 1263{ 1264 FIXME( "(%08lx, %08lx): partial stub.\n", level, flags ); 1265 shutdown_flags = flags; 1266 shutdown_priority = level; 1267 return TRUE; 1268} 1269 1270 1271/*********************************************************************** 1272 * SetProcessWorkingSetSizeEx (kernelbase.@) 1273 */ 1274BOOL WINAPI DECLSPEC_HOTPATCH SetProcessWorkingSetSizeEx( HANDLE process, SIZE_T minset, 1275 SIZE_T maxset, DWORD flags ) 1276{ 1277 return TRUE; 1278} 1279 1280 1281/****************************************************************************** 1282 * TerminateProcess (kernelbase.@) 1283 */ 1284BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code ) 1285{ 1286 if (!handle) 1287 { 1288 SetLastError( ERROR_INVALID_HANDLE ); 1289 return FALSE; 1290 } 1291 return set_ntstatus( NtTerminateProcess( handle, exit_code )); 1292} 1293 1294 1295/*********************************************************************** 1296 * Process startup information 1297 ***********************************************************************/ 1298 1299 1300static char *command_lineA; 1301static WCHAR *command_lineW; 1302 1303/****************************************************************** 1304 * init_startup_info 1305 */ 1306void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params ) 1307{ 1308 ANSI_STRING ansi; 1309 1310 command_lineW = params->CommandLine.Buffer; 1311 if (!RtlUnicodeStringToAnsiString( &ansi, &params->CommandLine, TRUE )) command_lineA = ansi.Buffer; 1312} 1313 1314 1315/********************************************************************** 1316 * BaseFlushAppcompatCache (kernelbase.@) 1317 */ 1318BOOL WINAPI BaseFlushAppcompatCache(void) 1319{ 1320 FIXME( "stub\n" ); 1321 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 1322 return FALSE; 1323} 1324 1325 1326/*********************************************************************** 1327 * GetCommandLineA (kernelbase.@) 1328 */ 1329LPSTR WINAPI GetCommandLineA(void) 1330{ 1331 return command_lineA; 1332} 1333 1334 1335/*********************************************************************** 1336 * GetCommandLineW (kernelbase.@) 1337 */ 1338LPWSTR WINAPI GetCommandLineW(void) 1339{ 1340 return command_lineW; 1341} 1342 1343 1344/*********************************************************************** 1345 * GetStartupInfoW (kernelbase.@) 1346 */ 1347void WINAPI DECLSPEC_HOTPATCH GetStartupInfoW( STARTUPINFOW *info ) 1348{ 1349 RTL_USER_PROCESS_PARAMETERS *params; 1350 1351 RtlAcquirePebLock(); 1352 1353 params = RtlGetCurrentPeb()->ProcessParameters; 1354 1355 info->cb = sizeof(*info); 1356 info->lpReserved = NULL; 1357 info->lpDesktop = params->Desktop.Buffer; 1358 info->lpTitle = params->WindowTitle.Buffer; 1359 info->dwX = params->dwX; 1360 info->dwY = params->dwY; 1361 info->dwXSize = params->dwXSize; 1362 info->dwYSize = params->dwYSize; 1363 info->dwXCountChars = params->dwXCountChars; 1364 info->dwYCountChars = params->dwYCountChars; 1365 info->dwFillAttribute = params->dwFillAttribute; 1366 info->dwFlags = params->dwFlags; 1367 info->wShowWindow = params->wShowWindow; 1368 info->cbReserved2 = params->RuntimeInfo.MaximumLength; 1369 info->lpReserved2 = params->RuntimeInfo.MaximumLength ? (void *)params->RuntimeInfo.Buffer : NULL; 1370 if (params->dwFlags & STARTF_USESTDHANDLES) 1371 { 1372 info->hStdInput = params->hStdInput; 1373 info->hStdOutput = params->hStdOutput; 1374 info->hStdError = params->hStdError; 1375 } 1376 RtlReleasePebLock(); 1377} 1378 1379 1380/*********************************************************************** 1381 * GetStdHandle (kernelbase.@) 1382 */ 1383HANDLE WINAPI DECLSPEC_HOTPATCH GetStdHandle( DWORD std_handle ) 1384{ 1385 switch (std_handle) 1386 { 1387 case STD_INPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdInput; 1388 case STD_OUTPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; 1389 case STD_ERROR_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdError; 1390 } 1391 SetLastError( ERROR_INVALID_HANDLE ); 1392 return INVALID_HANDLE_VALUE; 1393} 1394 1395 1396/*********************************************************************** 1397 * SetStdHandle (kernelbase.@) 1398 */ 1399BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle( DWORD std_handle, HANDLE handle ) 1400{ 1401 switch (std_handle) 1402 { 1403 case STD_INPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdInput = handle; return TRUE; 1404 case STD_OUTPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdOutput = handle; return TRUE; 1405 case STD_ERROR_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdError = handle; return TRUE; 1406 } 1407 SetLastError( ERROR_INVALID_HANDLE ); 1408 return FALSE; 1409} 1410 1411 1412/*********************************************************************** 1413 * SetStdHandleEx (kernelbase.@) 1414 */ 1415BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandleEx( DWORD std_handle, HANDLE handle, HANDLE *prev ) 1416{ 1417 HANDLE *ptr; 1418 1419 switch (std_handle) 1420 { 1421 case STD_INPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdInput; break; 1422 case STD_OUTPUT_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdOutput; break; 1423 case STD_ERROR_HANDLE: ptr = &NtCurrentTeb()->Peb->ProcessParameters->hStdError; break; 1424 default: 1425 SetLastError( ERROR_INVALID_HANDLE ); 1426 return FALSE; 1427 } 1428 if (prev) *prev = *ptr; 1429 *ptr = handle; 1430 return TRUE; 1431} 1432 1433 1434/*********************************************************************** 1435 * Process environment 1436 ***********************************************************************/ 1437 1438 1439static inline SIZE_T get_env_length( const WCHAR *env ) 1440{ 1441 const WCHAR *end = env; 1442 while (*end) end += lstrlenW(end) + 1; 1443 return end + 1 - env; 1444} 1445 1446/*********************************************************************** 1447 * ExpandEnvironmentStringsA (kernelbase.@) 1448 */ 1449DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, DWORD count ) 1450{ 1451 UNICODE_STRING us_src; 1452 PWSTR dstW = NULL; 1453 DWORD count_neededW; 1454 DWORD count_neededA = 0; 1455 1456 RtlCreateUnicodeStringFromAsciiz( &us_src, src ); 1457 1458 /* We always need to call ExpandEnvironmentStringsW, since we need the result to calculate the needed buffer size */ 1459 count_neededW = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0 ); 1460 if (!(dstW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, count_neededW * sizeof(WCHAR) ))) goto cleanup; 1461 count_neededW = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count_neededW ); 1462 1463 /* Calculate needed buffer */ 1464 count_neededA = WideCharToMultiByte( CP_ACP, 0, dstW, count_neededW, NULL, 0, NULL, NULL ); 1465 1466 /* If provided buffer is enough, do actual conversion */ 1467 if (count > count_neededA) 1468 count_neededA = WideCharToMultiByte( CP_ACP, 0, dstW, count_neededW, dst, count, NULL, NULL ); 1469 else if(dst) 1470 *dst = 0; 1471 1472cleanup: 1473 RtlFreeUnicodeString( &us_src ); 1474 HeapFree( GetProcessHeap(), 0, dstW ); 1475 1476 if (count_neededA >= count) /* When the buffer is too small, native over-reports by one byte */ 1477 return count_neededA + 1; 1478 return count_neededA; 1479} 1480 1481 1482/*********************************************************************** 1483 * ExpandEnvironmentStringsW (kernelbase.@) 1484 */ 1485DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len ) 1486{ 1487 UNICODE_STRING us_src, us_dst; 1488 NTSTATUS status; 1489 DWORD res; 1490 1491 TRACE( "(%s %p %lu)\n", debugstr_w(src), dst, len ); 1492 1493 RtlInitUnicodeString( &us_src, src ); 1494 1495 /* make sure we don't overflow the maximum UNICODE_STRING size */ 1496 len = min( len, UNICODE_STRING_MAX_CHARS ); 1497 1498 us_dst.Length = 0; 1499 us_dst.MaximumLength = len * sizeof(WCHAR); 1500 us_dst.Buffer = dst; 1501 1502 res = 0; 1503 status = RtlExpandEnvironmentStrings_U( NULL, &us_src, &us_dst, &res ); 1504 res /= sizeof(WCHAR); 1505 if (status != STATUS_BUFFER_TOO_SMALL) 1506 { 1507 if(!set_ntstatus( status )) 1508 return 0; 1509 } 1510 return res; 1511} 1512 1513 1514/*********************************************************************** 1515 * GetEnvironmentStrings (kernelbase.@) 1516 * GetEnvironmentStringsA (kernelbase.@) 1517 */ 1518LPSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsA(void) 1519{ 1520 LPWSTR env; 1521 LPSTR ret; 1522 SIZE_T lenA, lenW; 1523 1524 RtlAcquirePebLock(); 1525 env = NtCurrentTeb()->Peb->ProcessParameters->Environment; 1526 lenW = get_env_length( env ); 1527 lenA = WideCharToMultiByte( CP_ACP, 0, env, lenW, NULL, 0, NULL, NULL ); 1528 if ((ret = HeapAlloc( GetProcessHeap(), 0, lenA ))) 1529 WideCharToMultiByte( CP_ACP, 0, env, lenW, ret, lenA, NULL, NULL ); 1530 RtlReleasePebLock(); 1531 return ret; 1532} 1533 1534 1535/*********************************************************************** 1536 * GetEnvironmentStringsW (kernelbase.@) 1537 */ 1538LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void) 1539{ 1540 LPWSTR ret; 1541 SIZE_T len; 1542 1543 RtlAcquirePebLock(); 1544 len = get_env_length( NtCurrentTeb()->Peb->ProcessParameters->Environment ) * sizeof(WCHAR); 1545 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) 1546 memcpy( ret, NtCurrentTeb()->Peb->ProcessParameters->Environment, len ); 1547 RtlReleasePebLock(); 1548 return ret; 1549} 1550 1551 1552/*********************************************************************** 1553 * SetEnvironmentStringsA (kernelbase.@) 1554 */ 1555BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsA( char *env ) 1556{ 1557 WCHAR *envW; 1558 const char *p = env; 1559 DWORD len; 1560 BOOL ret; 1561 1562 for (p = env; *p; p += strlen( p ) + 1); 1563 1564 len = MultiByteToWideChar( CP_ACP, 0, env, p - env, NULL, 0 ); 1565 if (!(envW = HeapAlloc( GetProcessHeap(), 0, len ))) 1566 { 1567 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 1568 return FALSE; 1569 } 1570 MultiByteToWideChar( CP_ACP, 0, env, p - env, envW, len ); 1571 ret = SetEnvironmentStringsW( envW ); 1572 HeapFree( GetProcessHeap(), 0, envW ); 1573 return ret; 1574} 1575 1576 1577/*********************************************************************** 1578 * SetEnvironmentStringsW (kernelbase.@) 1579 */ 1580BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsW( WCHAR *env ) 1581{ 1582 WCHAR *p; 1583 WCHAR *new_env; 1584 NTSTATUS status; 1585 1586 for (p = env; *p; p += wcslen( p ) + 1) 1587 { 1588 const WCHAR *eq = wcschr( p, '=' ); 1589 if (!eq || eq == p) 1590 { 1591 SetLastError( ERROR_INVALID_PARAMETER ); 1592 return FALSE; 1593 } 1594 } 1595 1596 if ((status = RtlCreateEnvironment( FALSE, &new_env ))) 1597 return set_ntstatus( status ); 1598 1599 for (p = env; *p; p += wcslen( p ) + 1) 1600 { 1601 const WCHAR *eq = wcschr( p, '=' ); 1602 UNICODE_STRING var, value; 1603 var.Buffer = p; 1604 var.Length = (eq - p) * sizeof(WCHAR); 1605 RtlInitUnicodeString( &value, eq + 1 ); 1606 if ((status = RtlSetEnvironmentVariable( &new_env, &var, &value ))) 1607 { 1608 RtlDestroyEnvironment( new_env ); 1609 return set_ntstatus( status ); 1610 } 1611 } 1612 1613 RtlSetCurrentEnvironment( new_env, NULL ); 1614 return TRUE; 1615} 1616 1617 1618/*********************************************************************** 1619 * GetEnvironmentVariableA (kernelbase.@) 1620 */ 1621DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size ) 1622{ 1623 UNICODE_STRING us_name, us_value; 1624 PWSTR valueW; 1625 NTSTATUS status; 1626 DWORD len, ret; 1627 1628 /* limit the size to sane values */ 1629 size = min( size, 32767 ); 1630 if (!(valueW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0; 1631 1632 RtlCreateUnicodeStringFromAsciiz( &us_name, name ); 1633 us_value.Length = 0; 1634 us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR); 1635 us_value.Buffer = valueW; 1636 1637 status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value ); 1638 len = us_value.Length / sizeof(WCHAR); 1639 if (status == STATUS_BUFFER_TOO_SMALL) ret = len + 1; 1640 else if (!set_ntstatus( status )) ret = 0; 1641 else if (!size) ret = len + 1; 1642 else 1643 { 1644 if (len) WideCharToMultiByte( CP_ACP, 0, valueW, len + 1, value, size, NULL, NULL ); 1645 value[len] = 0; 1646 ret = len; 1647 } 1648 1649 RtlFreeUnicodeString( &us_name ); 1650 HeapFree( GetProcessHeap(), 0, valueW ); 1651 return ret; 1652} 1653 1654 1655/*********************************************************************** 1656 * GetEnvironmentVariableW (kernelbase.@) 1657 */ 1658DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size ) 1659{ 1660 UNICODE_STRING us_name, us_value; 1661 NTSTATUS status; 1662 DWORD len; 1663 1664 TRACE( "(%s %p %lu)\n", debugstr_w(name), val, size ); 1665 1666 RtlInitUnicodeString( &us_name, name ); 1667 us_value.Length = 0; 1668 us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR); 1669 us_value.Buffer = val; 1670 1671 status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value ); 1672 len = us_value.Length / sizeof(WCHAR); 1673 if (status == STATUS_BUFFER_TOO_SMALL) return len + 1; 1674 if (!set_ntstatus( status )) return 0; 1675 if (!size) return len + 1; 1676 val[len] = 0; 1677 return len; 1678} 1679 1680 1681/*********************************************************************** 1682 * FreeEnvironmentStringsA (kernelbase.@) 1683 * FreeEnvironmentStringsW (kernelbase.@) 1684 */ 1685BOOL WINAPI DECLSPEC_HOTPATCH FreeEnvironmentStringsW( LPWSTR ptr ) 1686{ 1687 return HeapFree( GetProcessHeap(), 0, ptr ); 1688} 1689 1690 1691/*********************************************************************** 1692 * SetEnvironmentVariableA (kernelbase.@) 1693 */ 1694BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA( LPCSTR name, LPCSTR value ) 1695{ 1696 UNICODE_STRING us_name, us_value; 1697 BOOL ret; 1698 1699 if (!name) 1700 { 1701 SetLastError( ERROR_ENVVAR_NOT_FOUND ); 1702 return FALSE; 1703 } 1704 1705 RtlCreateUnicodeStringFromAsciiz( &us_name, name ); 1706 if (value) 1707 { 1708 RtlCreateUnicodeStringFromAsciiz( &us_value, value ); 1709 ret = SetEnvironmentVariableW( us_name.Buffer, us_value.Buffer ); 1710 RtlFreeUnicodeString( &us_value ); 1711 } 1712 else ret = SetEnvironmentVariableW( us_name.Buffer, NULL ); 1713 RtlFreeUnicodeString( &us_name ); 1714 return ret; 1715} 1716 1717 1718/*********************************************************************** 1719 * SetEnvironmentVariableW (kernelbase.@) 1720 */ 1721BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value ) 1722{ 1723 UNICODE_STRING us_name, us_value; 1724 NTSTATUS status; 1725 1726 TRACE( "(%s %s)\n", debugstr_w(name), debugstr_w(value) ); 1727 1728 if (!name) 1729 { 1730 SetLastError( ERROR_ENVVAR_NOT_FOUND ); 1731 return FALSE; 1732 } 1733 1734 RtlInitUnicodeString( &us_name, name ); 1735 if (value) 1736 { 1737 RtlInitUnicodeString( &us_value, value ); 1738 status = RtlSetEnvironmentVariable( NULL, &us_name, &us_value ); 1739 } 1740 else status = RtlSetEnvironmentVariable( NULL, &us_name, NULL ); 1741 1742 return set_ntstatus( status ); 1743} 1744 1745 1746/*********************************************************************** 1747 * Process/thread attribute lists 1748 ***********************************************************************/ 1749 1750/*********************************************************************** 1751 * InitializeProcThreadAttributeList (kernelbase.@) 1752 */ 1753BOOL WINAPI DECLSPEC_HOTPATCH InitializeProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list, 1754 DWORD count, DWORD flags, SIZE_T *size ) 1755{ 1756 SIZE_T needed; 1757 BOOL ret = FALSE; 1758 1759 TRACE( "(%p %ld %lx %p)\n", list, count, flags, size ); 1760 1761 needed = FIELD_OFFSET( struct _PROC_THREAD_ATTRIBUTE_LIST, attrs[count] ); 1762 if (list && *size >= needed) 1763 { 1764 list->mask = 0; 1765 list->size = count; 1766 list->count = 0; 1767 list->unk = 0; 1768 ret = TRUE; 1769 } 1770 else SetLastError( ERROR_INSUFFICIENT_BUFFER ); 1771 1772 *size = needed; 1773 return ret; 1774} 1775 1776 1777static inline DWORD validate_proc_thread_attribute( DWORD_PTR attr, SIZE_T size ) 1778{ 1779 switch (attr) 1780 { 1781 case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: 1782 if (size != sizeof(HANDLE)) return ERROR_BAD_LENGTH; 1783 break; 1784 case PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS: 1785 if (size != sizeof(ULONG)) return ERROR_BAD_LENGTH; 1786 break; 1787 case PROC_THREAD_ATTRIBUTE_HANDLE_LIST: 1788 if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size) return ERROR_BAD_LENGTH; 1789 break; 1790 case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR: 1791 if (size != sizeof(PROCESSOR_NUMBER)) return ERROR_BAD_LENGTH; 1792 break; 1793 case PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY: 1794 if (size != sizeof(DWORD) && size != sizeof(DWORD64)) return ERROR_BAD_LENGTH; 1795 break; 1796 case PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY: 1797 if (size != sizeof(DWORD) && size != sizeof(DWORD64) && size != sizeof(DWORD64) * 2) 1798 return ERROR_BAD_LENGTH; 1799 break; 1800 case PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: 1801 if (size != sizeof(HPCON)) return ERROR_BAD_LENGTH; 1802 break; 1803 case PROC_THREAD_ATTRIBUTE_JOB_LIST: 1804 if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size) return ERROR_BAD_LENGTH; 1805 break; 1806 case PROC_THREAD_ATTRIBUTE_MACHINE_TYPE: 1807 if (size != sizeof(USHORT)) return ERROR_BAD_LENGTH; 1808 break; 1809 default: 1810 FIXME( "Unhandled attribute %Iu\n", attr & PROC_THREAD_ATTRIBUTE_NUMBER ); 1811 return ERROR_NOT_SUPPORTED; 1812 } 1813 return 0; 1814} 1815 1816 1817/*********************************************************************** 1818 * UpdateProcThreadAttribute (kernelbase.@) 1819 */ 1820BOOL WINAPI DECLSPEC_HOTPATCH UpdateProcThreadAttribute( struct _PROC_THREAD_ATTRIBUTE_LIST *list, 1821 DWORD flags, DWORD_PTR attr, void *value, 1822 SIZE_T size, void *prev_ret, SIZE_T *size_ret ) 1823{ 1824 DWORD mask, err; 1825 struct proc_thread_attr *entry; 1826 1827 TRACE( "(%p %lx %08Ix %p %Id %p %p)\n", list, flags, attr, value, size, prev_ret, size_ret ); 1828 1829 if (list->count >= list->size) 1830 { 1831 SetLastError( ERROR_GEN_FAILURE ); 1832 return FALSE; 1833 } 1834 if ((err = validate_proc_thread_attribute( attr, size ))) 1835 { 1836 SetLastError( err ); 1837 return FALSE; 1838 } 1839 1840 mask = 1 << (attr & PROC_THREAD_ATTRIBUTE_NUMBER); 1841 if (list->mask & mask) 1842 { 1843 SetLastError( ERROR_OBJECT_NAME_EXISTS ); 1844 return FALSE; 1845 } 1846 list->mask |= mask; 1847 1848 entry = list->attrs + list->count; 1849 entry->attr = attr; 1850 entry->size = size; 1851 entry->value = value; 1852 list->count++; 1853 return TRUE; 1854} 1855 1856 1857/*********************************************************************** 1858 * DeleteProcThreadAttributeList (kernelbase.@) 1859 */ 1860void WINAPI DECLSPEC_HOTPATCH DeleteProcThreadAttributeList( struct _PROC_THREAD_ATTRIBUTE_LIST *list ) 1861{ 1862 return; 1863} 1864 1865 1866/*********************************************************************** 1867 * CompareObjectHandles (kernelbase.@) 1868 */ 1869BOOL WINAPI DECLSPEC_HOTPATCH CompareObjectHandles( HANDLE first, HANDLE second ) 1870{ 1871 return set_ntstatus( NtCompareObjects( first, second )); 1872}