wow64: Add thunks for the process/thread set information syscalls.
[wine.git] / dlls / wow64 / process.c
blob44380535d9ca800ca8bd46976a8f8a7a0848ea33
1 /*
2 * WoW64 process (and thread) functions
4 * Copyright 2021 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnt.h"
28 #include "winternl.h"
29 #include "wow64_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wow);
35 static SIZE_T get_machine_context_size( USHORT machine )
37 switch (machine)
39 case IMAGE_FILE_MACHINE_I386: return sizeof(I386_CONTEXT);
40 case IMAGE_FILE_MACHINE_ARMNT: return sizeof(ARM_CONTEXT);
41 case IMAGE_FILE_MACHINE_AMD64: return sizeof(AMD64_CONTEXT);
42 case IMAGE_FILE_MACHINE_ARM64: return sizeof(ARM64_NT_CONTEXT);
43 default: return 0;
48 static BOOL is_process_wow64( HANDLE handle )
50 ULONG_PTR info;
52 if (handle == GetCurrentProcess()) return TRUE;
53 if (NtQueryInformationProcess( handle, ProcessWow64Information, &info, sizeof(info), NULL ))
54 return FALSE;
55 return !!info;
59 static BOOL is_process_id_wow64( const CLIENT_ID *id )
61 HANDLE handle;
62 BOOL ret = FALSE;
64 if (id->UniqueProcess == ULongToHandle(GetCurrentProcessId())) return TRUE;
65 if (!NtOpenProcess( &handle, PROCESS_QUERY_LIMITED_INFORMATION, NULL, id ))
67 ret = is_process_wow64( handle );
68 NtClose( handle );
70 return ret;
74 static RTL_USER_PROCESS_PARAMETERS *process_params_32to64( RTL_USER_PROCESS_PARAMETERS **params,
75 RTL_USER_PROCESS_PARAMETERS32 *params32 )
77 UNICODE_STRING image, dllpath, curdir, cmdline, title, desktop, shell, runtime;
78 RTL_USER_PROCESS_PARAMETERS *ret;
80 *params = NULL;
81 if (RtlCreateProcessParametersEx( &ret, unicode_str_32to64( &image, &params32->ImagePathName ),
82 unicode_str_32to64( &dllpath, &params32->DllPath ),
83 unicode_str_32to64( &curdir, &params32->CurrentDirectory.DosPath ),
84 unicode_str_32to64( &cmdline, &params32->CommandLine ),
85 ULongToPtr( params32->Environment ),
86 unicode_str_32to64( &title, &params32->WindowTitle ),
87 unicode_str_32to64( &desktop, &params32->Desktop ),
88 unicode_str_32to64( &shell, &params32->ShellInfo ),
89 unicode_str_32to64( &runtime, &params32->RuntimeInfo ),
90 PROCESS_PARAMS_FLAG_NORMALIZED ))
91 return NULL;
93 ret->DebugFlags = params32->DebugFlags;
94 ret->ConsoleHandle = LongToHandle( params32->ConsoleHandle );
95 ret->ConsoleFlags = params32->ConsoleFlags;
96 ret->hStdInput = LongToHandle( params32->hStdInput );
97 ret->hStdOutput = LongToHandle( params32->hStdOutput );
98 ret->hStdError = LongToHandle( params32->hStdError );
99 ret->dwX = params32->dwX;
100 ret->dwY = params32->dwY;
101 ret->dwXSize = params32->dwXSize;
102 ret->dwYSize = params32->dwYSize;
103 ret->dwXCountChars = params32->dwXCountChars;
104 ret->dwYCountChars = params32->dwYCountChars;
105 ret->dwFillAttribute = params32->dwFillAttribute;
106 ret->dwFlags = params32->dwFlags;
107 ret->wShowWindow = params32->wShowWindow;
108 ret->EnvironmentVersion = params32->EnvironmentVersion;
109 ret->PackageDependencyData = ULongToPtr( params32->PackageDependencyData );
110 ret->ProcessGroupId = params32->ProcessGroupId;
111 ret->LoaderThreads = params32->LoaderThreads;
112 *params = ret;
113 return ret;
117 static void put_ps_create_info( PS_CREATE_INFO32 *info32, const PS_CREATE_INFO *info )
119 info32->State = info->State;
120 switch (info->State)
122 case PsCreateInitialState:
123 info32->InitState.InitFlags = info->InitState.InitFlags;
124 info32->InitState.AdditionalFileAccess = info->InitState.AdditionalFileAccess;
125 break;
126 case PsCreateFailOnSectionCreate:
127 info32->FailSection.FileHandle = HandleToLong( info->FailSection.FileHandle );
128 break;
129 case PsCreateFailExeFormat:
130 info32->ExeFormat.DllCharacteristics = info->ExeFormat.DllCharacteristics;
131 break;
132 case PsCreateFailExeName:
133 info32->ExeName.IFEOKey = HandleToLong( info->ExeName.IFEOKey );
134 break;
135 case PsCreateSuccess:
136 info32->SuccessState.OutputFlags = info->SuccessState.OutputFlags;
137 info32->SuccessState.FileHandle = HandleToLong( info->SuccessState.FileHandle );
138 info32->SuccessState.SectionHandle = HandleToLong( info->SuccessState.SectionHandle );
139 info32->SuccessState.UserProcessParametersNative = info->SuccessState.UserProcessParametersNative;
140 info32->SuccessState.UserProcessParametersWow64 = info->SuccessState.UserProcessParametersWow64;
141 info32->SuccessState.CurrentParameterFlags = info->SuccessState.CurrentParameterFlags;
142 info32->SuccessState.PebAddressNative = info->SuccessState.PebAddressNative;
143 info32->SuccessState.PebAddressWow64 = info->SuccessState.PebAddressWow64;
144 info32->SuccessState.ManifestAddress = info->SuccessState.ManifestAddress;
145 info32->SuccessState.ManifestSize = info->SuccessState.ManifestSize;
146 break;
147 default:
148 break;
153 static PS_ATTRIBUTE_LIST *ps_attributes_32to64( PS_ATTRIBUTE_LIST **attr, const PS_ATTRIBUTE_LIST32 *attr32 )
155 PS_ATTRIBUTE_LIST *ret;
156 ULONG i, count;
158 if (!attr32) return NULL;
159 count = (attr32->TotalLength - sizeof(attr32->TotalLength)) / sizeof(PS_ATTRIBUTE32);
160 ret = Wow64AllocateTemp( offsetof(PS_ATTRIBUTE_LIST, Attributes[count]) );
161 ret->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[count] );
162 for (i = 0; i < count; i++)
164 ret->Attributes[i].Attribute = attr32->Attributes[i].Attribute;
165 ret->Attributes[i].Size = attr32->Attributes[i].Size;
166 ret->Attributes[i].Value = attr32->Attributes[i].Value;
167 ret->Attributes[i].ReturnLength = NULL;
168 switch (ret->Attributes[i].Attribute)
170 case PS_ATTRIBUTE_IMAGE_NAME:
172 OBJECT_ATTRIBUTES attr;
173 UNICODE_STRING path;
175 path.Length = ret->Attributes[i].Size;
176 path.Buffer = ret->Attributes[i].ValuePtr;
177 InitializeObjectAttributes( &attr, &path, OBJ_CASE_INSENSITIVE, 0, 0 );
178 if (get_file_redirect( &attr ))
180 ret->Attributes[i].Size = attr.ObjectName->Length;
181 ret->Attributes[i].ValuePtr = attr.ObjectName->Buffer;
184 break;
185 case PS_ATTRIBUTE_HANDLE_LIST:
186 case PS_ATTRIBUTE_JOB_LIST:
188 ULONG j, handles_count = attr32->Attributes[i].Size / sizeof(ULONG);
190 ret->Attributes[i].Size = handles_count * sizeof(HANDLE);
191 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
192 for (j = 0; j < handles_count; j++)
193 ((HANDLE *)ret->Attributes[i].ValuePtr)[j] =
194 LongToHandle( ((LONG *)ULongToPtr(attr32->Attributes[i].Value))[j] );
196 break;
197 case PS_ATTRIBUTE_CLIENT_ID:
198 ret->Attributes[i].Size = sizeof(CLIENT_ID);
199 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
200 break;
201 case PS_ATTRIBUTE_IMAGE_INFO:
202 ret->Attributes[i].Size = sizeof(SECTION_IMAGE_INFORMATION);
203 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
204 break;
205 case PS_ATTRIBUTE_TEB_ADDRESS:
206 ret->Attributes[i].Size = sizeof(TEB *);
207 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
208 break;
211 *attr = ret;
212 return ret;
216 static void put_ps_attributes( PS_ATTRIBUTE_LIST32 *attr32, const PS_ATTRIBUTE_LIST *attr )
218 ULONG i;
220 if (!attr32) return;
221 for (i = 0; i < (attr32->TotalLength - sizeof(attr32->TotalLength)) / sizeof(PS_ATTRIBUTE32); i++)
223 switch (attr->Attributes[i].Attribute)
225 case PS_ATTRIBUTE_CLIENT_ID:
227 CLIENT_ID32 id32;
228 ULONG size = min( attr32->Attributes[i].Size, sizeof(id32) );
229 put_client_id( &id32, attr->Attributes[i].ValuePtr );
230 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &id32, size );
231 if (attr32->Attributes[i].ReturnLength)
232 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
233 break;
235 case PS_ATTRIBUTE_IMAGE_INFO:
237 SECTION_IMAGE_INFORMATION32 info32;
238 ULONG size = min( attr32->Attributes[i].Size, sizeof(info32) );
239 put_section_image_info( &info32, attr->Attributes[i].ValuePtr );
240 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &info32, size );
241 if (attr32->Attributes[i].ReturnLength)
242 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
243 break;
245 case PS_ATTRIBUTE_TEB_ADDRESS:
247 TEB **teb = attr->Attributes[i].ValuePtr;
248 ULONG teb32 = PtrToUlong( *teb ) + 0x2000;
249 ULONG size = min( attr->Attributes[i].Size, sizeof(teb32) );
250 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &teb32, size );
251 if (attr32->Attributes[i].ReturnLength)
252 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
253 break;
260 void put_vm_counters( VM_COUNTERS_EX32 *info32, const VM_COUNTERS_EX *info, ULONG size )
262 info32->PeakVirtualSize = info->PeakVirtualSize;
263 info32->VirtualSize = info->VirtualSize;
264 info32->PageFaultCount = info->PageFaultCount;
265 info32->PeakWorkingSetSize = info->PeakWorkingSetSize;
266 info32->WorkingSetSize = info->WorkingSetSize;
267 info32->QuotaPeakPagedPoolUsage = info->QuotaPeakPagedPoolUsage;
268 info32->QuotaPagedPoolUsage = info->QuotaPagedPoolUsage;
269 info32->QuotaPeakNonPagedPoolUsage = info->QuotaPeakNonPagedPoolUsage;
270 info32->QuotaNonPagedPoolUsage = info->QuotaNonPagedPoolUsage;
271 info32->PagefileUsage = info->PagefileUsage;
272 info32->PeakPagefileUsage = info->PeakPagefileUsage;
273 if (size == sizeof(VM_COUNTERS_EX32)) info32->PrivateUsage = info->PrivateUsage;
277 /**********************************************************************
278 * wow64_NtAlertResumeThread
280 NTSTATUS WINAPI wow64_NtAlertResumeThread( UINT *args )
282 HANDLE handle = get_handle( &args );
283 ULONG *count = get_ptr( &args );
285 return NtAlertResumeThread( handle, count );
289 /**********************************************************************
290 * wow64_NtAlertThread
292 NTSTATUS WINAPI wow64_NtAlertThread( UINT *args )
294 HANDLE handle = get_handle( &args );
296 return NtAlertThread( handle );
300 /**********************************************************************
301 * wow64_NtAssignProcessToJobObject
303 NTSTATUS WINAPI wow64_NtAssignProcessToJobObject( UINT *args )
305 HANDLE job = get_handle( &args );
306 HANDLE process = get_handle( &args );
308 return NtAssignProcessToJobObject( job, process );
312 /**********************************************************************
313 * wow64_NtCreateThread
315 NTSTATUS WINAPI wow64_NtCreateThread( UINT *args )
317 ULONG *handle_ptr = get_ptr( &args );
318 ACCESS_MASK access = get_ulong( &args );
319 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
320 HANDLE process = get_handle( &args );
321 CLIENT_ID32 *id32 = get_ptr( &args );
322 I386_CONTEXT *context = get_ptr( &args );
323 void *initial_teb = get_ptr( &args );
324 BOOLEAN suspended = get_ulong( &args );
326 FIXME( "%p %x %p %p %p %p %p %u: stub\n", handle_ptr, access, attr32, process,
327 id32, context, initial_teb, suspended );
328 return STATUS_NOT_IMPLEMENTED;
332 /**********************************************************************
333 * wow64_NtCreateThreadEx
335 NTSTATUS WINAPI wow64_NtCreateThreadEx( UINT *args )
337 ULONG *handle_ptr = get_ptr( &args );
338 ACCESS_MASK access = get_ulong( &args );
339 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
340 HANDLE process = get_handle( &args );
341 PRTL_THREAD_START_ROUTINE start = get_ptr( &args );
342 void *param = get_ptr( &args );
343 ULONG flags = get_ulong( &args );
344 ULONG_PTR zero_bits = get_ulong( &args );
345 SIZE_T stack_commit = get_ulong( &args );
346 SIZE_T stack_reserve = get_ulong( &args );
347 PS_ATTRIBUTE_LIST32 *attr_list32 = get_ptr( &args );
349 struct object_attr64 attr;
350 PS_ATTRIBUTE_LIST *attr_list;
351 HANDLE handle = 0;
352 NTSTATUS status;
354 *handle_ptr = 0;
355 if (is_process_wow64( process ))
357 status = NtCreateThreadEx( &handle, access, objattr_32to64( &attr, attr32 ), process,
358 start, param, flags, get_zero_bits( zero_bits ),
359 stack_commit, stack_reserve,
360 ps_attributes_32to64( &attr_list, attr_list32 ));
361 put_ps_attributes( attr_list32, attr_list );
363 else status = STATUS_ACCESS_DENIED;
365 put_handle( handle_ptr, handle );
366 return status;
370 /**********************************************************************
371 * wow64_NtCreateUserProcess
373 NTSTATUS WINAPI wow64_NtCreateUserProcess( UINT *args )
375 ULONG *process_handle_ptr = get_ptr( &args );
376 ULONG *thread_handle_ptr = get_ptr( &args );
377 ACCESS_MASK process_access = get_ulong( &args );
378 ACCESS_MASK thread_access = get_ulong( &args );
379 OBJECT_ATTRIBUTES32 *process_attr32 = get_ptr( &args );
380 OBJECT_ATTRIBUTES32 *thread_attr32 = get_ptr( &args );
381 ULONG process_flags = get_ulong( &args );
382 ULONG thread_flags = get_ulong( &args );
383 RTL_USER_PROCESS_PARAMETERS32 *params32 = get_ptr( &args );
384 PS_CREATE_INFO32 *info32 = get_ptr( &args );
385 PS_ATTRIBUTE_LIST32 *attr32 = get_ptr( &args );
387 struct object_attr64 process_attr, thread_attr;
388 RTL_USER_PROCESS_PARAMETERS *params;
389 PS_CREATE_INFO info;
390 PS_ATTRIBUTE_LIST *attr;
391 HANDLE process_handle = 0, thread_handle = 0;
393 NTSTATUS status;
395 *process_handle_ptr = *thread_handle_ptr = 0;
396 status = NtCreateUserProcess( &process_handle, &thread_handle, process_access, thread_access,
397 objattr_32to64( &process_attr, process_attr32 ),
398 objattr_32to64( &thread_attr, thread_attr32 ),
399 process_flags, thread_flags,
400 process_params_32to64( &params, params32),
401 &info, ps_attributes_32to64( &attr, attr32 ));
402 put_handle( process_handle_ptr, process_handle );
403 put_handle( thread_handle_ptr, thread_handle );
404 put_ps_create_info( info32, &info );
405 put_ps_attributes( attr32, attr );
406 RtlDestroyProcessParameters( params );
407 return status;
411 /**********************************************************************
412 * wow64_NtDebugActiveProcess
414 NTSTATUS WINAPI wow64_NtDebugActiveProcess( UINT *args )
416 HANDLE process = get_handle( &args );
417 HANDLE debug = get_handle( &args );
419 return NtDebugActiveProcess( process, debug );
423 /**********************************************************************
424 * wow64_NtFlushInstructionCache
426 NTSTATUS WINAPI wow64_NtFlushInstructionCache( UINT *args )
428 HANDLE process = get_handle( &args );
429 const void *addr = get_ptr( &args );
430 SIZE_T size = get_ulong( &args );
432 return NtFlushInstructionCache( process, addr, size );
436 /**********************************************************************
437 * wow64_NtFlushProcessWriteBuffers
439 NTSTATUS WINAPI wow64_NtFlushProcessWriteBuffers( UINT *args )
441 NtFlushProcessWriteBuffers();
442 return STATUS_SUCCESS;
446 /**********************************************************************
447 * wow64_NtGetContextThread
449 NTSTATUS WINAPI wow64_NtGetContextThread( UINT *args )
451 HANDLE handle = get_handle( &args );
452 WOW64_CONTEXT *context = get_ptr( &args );
454 return NtQueryInformationThread( handle, ThreadWow64Context, context,
455 get_machine_context_size( current_machine ), NULL );
459 /**********************************************************************
460 * wow64_NtIsProcessInJob
462 NTSTATUS WINAPI wow64_NtIsProcessInJob( UINT *args )
464 HANDLE process = get_handle( &args );
465 HANDLE job = get_handle( &args );
467 return NtIsProcessInJob( process, job );
471 /**********************************************************************
472 * wow64_NtOpenProcess
474 NTSTATUS WINAPI wow64_NtOpenProcess( UINT *args )
476 ULONG *handle_ptr = get_ptr( &args );
477 ACCESS_MASK access = get_ulong( &args );
478 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
479 CLIENT_ID32 *id32 = get_ptr( &args );
481 struct object_attr64 attr;
482 HANDLE handle = 0;
483 CLIENT_ID id;
484 NTSTATUS status;
486 *handle_ptr = 0;
487 status = NtOpenProcess( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
488 put_handle( handle_ptr, handle );
489 return status;
493 /**********************************************************************
494 * wow64_NtOpenThread
496 NTSTATUS WINAPI wow64_NtOpenThread( UINT *args )
498 ULONG *handle_ptr = get_ptr( &args );
499 ACCESS_MASK access = get_ulong( &args );
500 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
501 CLIENT_ID32 *id32 = get_ptr( &args );
503 struct object_attr64 attr;
504 HANDLE handle = 0;
505 CLIENT_ID id;
506 NTSTATUS status;
508 *handle_ptr = 0;
509 status = NtOpenThread( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
510 put_handle( handle_ptr, handle );
511 return status;
515 /**********************************************************************
516 * wow64_NtQueryInformationProcess
518 NTSTATUS WINAPI wow64_NtQueryInformationProcess( UINT *args )
520 HANDLE handle = get_handle( &args );
521 PROCESSINFOCLASS class = get_ulong( &args );
522 void *ptr = get_ptr( &args );
523 ULONG len = get_ulong( &args );
524 ULONG *retlen = get_ptr( &args );
526 NTSTATUS status;
528 switch (class)
530 case ProcessBasicInformation: /* PROCESS_BASIC_INFORMATION */
531 if (len == sizeof(PROCESS_BASIC_INFORMATION32))
533 PROCESS_BASIC_INFORMATION info;
534 PROCESS_BASIC_INFORMATION32 *info32 = ptr;
536 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
538 if (is_process_wow64( handle ))
539 info32->PebBaseAddress = PtrToUlong( info.PebBaseAddress ) + 0x1000;
540 else
541 info32->PebBaseAddress = 0;
542 info32->ExitStatus = info.ExitStatus;
543 info32->AffinityMask = info.AffinityMask;
544 info32->BasePriority = info.BasePriority;
545 info32->UniqueProcessId = info.UniqueProcessId;
546 info32->InheritedFromUniqueProcessId = info.InheritedFromUniqueProcessId;
547 if (retlen) *retlen = sizeof(*info32);
549 return status;
551 if (retlen) *retlen = sizeof(PROCESS_BASIC_INFORMATION32);
552 return STATUS_INFO_LENGTH_MISMATCH;
554 case ProcessIoCounters: /* IO_COUNTERS */
555 case ProcessTimes: /* KERNEL_USER_TIMES */
556 case ProcessDefaultHardErrorMode: /* ULONG */
557 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
558 case ProcessHandleCount: /* ULONG */
559 case ProcessSessionInformation: /* ULONG */
560 case ProcessDebugFlags: /* ULONG */
561 case ProcessExecuteFlags: /* ULONG */
562 case ProcessCookie: /* ULONG */
563 /* FIXME: check buffer alignment */
564 return NtQueryInformationProcess( handle, class, ptr, len, retlen );
566 case ProcessVmCounters: /* VM_COUNTERS_EX */
567 if (len == sizeof(VM_COUNTERS32) || len == sizeof(VM_COUNTERS_EX32))
569 VM_COUNTERS_EX info;
570 VM_COUNTERS_EX32 *info32 = ptr;
572 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
574 put_vm_counters( info32, &info, len );
575 if (retlen) *retlen = len;
577 return status;
579 if (retlen) *retlen = sizeof(VM_COUNTERS_EX32);
580 return STATUS_INFO_LENGTH_MISMATCH;
582 case ProcessDebugPort: /* ULONG_PTR */
583 case ProcessAffinityMask: /* ULONG_PTR */
584 case ProcessWow64Information: /* ULONG_PTR */
585 case ProcessDebugObjectHandle: /* HANDLE */
586 if (len == sizeof(ULONG))
588 ULONG_PTR data;
590 if (!(status = NtQueryInformationProcess( handle, class, &data, sizeof(data), NULL )))
592 *(ULONG *)ptr = data;
593 if (retlen) *retlen = sizeof(ULONG);
595 else if (status == STATUS_PORT_NOT_SET) *(ULONG *)ptr = 0;
596 return status;
598 if (retlen) *retlen = sizeof(ULONG);
599 return STATUS_INFO_LENGTH_MISMATCH;
601 case ProcessImageFileName:
602 case ProcessImageFileNameWin32: /* UNICODE_STRING + string */
604 ULONG retsize, size = len + sizeof(UNICODE_STRING) - sizeof(UNICODE_STRING32);
605 UNICODE_STRING *str = Wow64AllocateTemp( size );
606 UNICODE_STRING32 *str32 = ptr;
608 if (!(status = NtQueryInformationProcess( handle, class, str, size, &retsize )))
610 str32->Length = str->Length;
611 str32->MaximumLength = str->MaximumLength;
612 str32->Buffer = PtrToUlong( str32 + 1 );
613 memcpy( str32 + 1, str->Buffer, str->MaximumLength );
615 if (retlen) *retlen = retsize + sizeof(UNICODE_STRING32) - sizeof(UNICODE_STRING);
616 return status;
619 case ProcessImageInformation: /* SECTION_IMAGE_INFORMATION */
620 if (len == sizeof(SECTION_IMAGE_INFORMATION32))
622 SECTION_IMAGE_INFORMATION info;
623 SECTION_IMAGE_INFORMATION32 *info32 = ptr;
625 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
627 put_section_image_info( info32, &info );
628 if (retlen) *retlen = sizeof(*info32);
630 return status;
632 if (retlen) *retlen = sizeof(SECTION_IMAGE_INFORMATION32);
633 return STATUS_INFO_LENGTH_MISMATCH;
635 default:
636 FIXME( "unsupported class %u\n", class );
637 return STATUS_INVALID_INFO_CLASS;
642 /**********************************************************************
643 * wow64_NtQueryInformationThread
645 NTSTATUS WINAPI wow64_NtQueryInformationThread( UINT *args )
647 HANDLE handle = get_handle( &args );
648 THREADINFOCLASS class = get_ulong( &args );
649 void *ptr = get_ptr( &args );
650 ULONG len = get_ulong( &args );
651 ULONG *retlen = get_ptr( &args );
653 NTSTATUS status;
655 switch (class)
657 case ThreadBasicInformation: /* THREAD_BASIC_INFORMATION */
659 THREAD_BASIC_INFORMATION32 info32;
660 THREAD_BASIC_INFORMATION info;
662 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
663 if (!status)
665 info32.ExitStatus = info.ExitStatus;
666 info32.TebBaseAddress = is_process_id_wow64( &info.ClientId ) ?
667 PtrToUlong(info.TebBaseAddress) + 0x2000 : 0;
668 info32.ClientId.UniqueProcess = HandleToULong( info.ClientId.UniqueProcess );
669 info32.ClientId.UniqueThread = HandleToULong( info.ClientId.UniqueThread );
670 info32.AffinityMask = info.AffinityMask;
671 info32.Priority = info.Priority;
672 info32.BasePriority = info.BasePriority;
673 memcpy( ptr, &info32, min( len, sizeof(info32) ));
674 if (retlen) *retlen = min( len, sizeof(info32) );
676 return status;
679 case ThreadTimes: /* KERNEL_USER_TIMES */
680 case ThreadEnableAlignmentFaultFixup: /* set only */
681 case ThreadAmILastThread: /* ULONG */
682 case ThreadIsIoPending: /* ULONG */
683 case ThreadHideFromDebugger: /* BOOLEAN */
684 case ThreadSuspendCount: /* ULONG */
685 /* FIXME: check buffer alignment */
686 return NtQueryInformationThread( handle, class, ptr, len, retlen );
688 case ThreadAffinityMask: /* ULONG_PTR */
689 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
691 ULONG_PTR data;
693 status = NtQueryInformationThread( handle, class, &data, sizeof(data), NULL );
694 if (!status)
696 memcpy( ptr, &data, min( len, sizeof(ULONG) ));
697 if (retlen) *retlen = min( len, sizeof(ULONG) );
699 return status;
702 case ThreadDescriptorTableEntry: /* THREAD_DESCRIPTOR_INFORMATION */
703 return RtlWow64GetThreadSelectorEntry( handle, ptr, len, retlen );
705 case ThreadWow64Context: /* WOW64_CONTEXT* */
706 return STATUS_INVALID_INFO_CLASS;
708 case ThreadGroupInformation: /* GROUP_AFFINITY */
710 GROUP_AFFINITY info;
712 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
713 if (!status)
715 GROUP_AFFINITY32 info32 = { info.Mask, info.Group };
716 memcpy( ptr, &info32, min( len, sizeof(info32) ));
717 if (retlen) *retlen = min( len, sizeof(info32) );
719 return status;
722 case ThreadDescription: /* THREAD_DESCRIPTION_INFORMATION */
724 THREAD_DESCRIPTION_INFORMATION *info;
725 THREAD_DESCRIPTION_INFORMATION32 *info32 = ptr;
726 ULONG size, ret_size;
728 if (len >= sizeof(*info32))
730 size = sizeof(*info) + len - sizeof(*info32);
731 info = Wow64AllocateTemp( size );
732 status = NtQueryInformationThread( handle, class, info, size, &ret_size );
733 if (!status)
735 info32->Description.Length = info->Description.Length;
736 info32->Description.MaximumLength = info->Description.MaximumLength;
737 info32->Description.Buffer = PtrToUlong( info32 + 1 );
738 memcpy( info32 + 1, info + 1, min( len, info->Description.MaximumLength ));
741 else status = NtQueryInformationThread( handle, class, NULL, 0, &ret_size );
743 if (retlen && (status == STATUS_SUCCESS || status == STATUS_BUFFER_TOO_SMALL))
744 *retlen = sizeof(*info32) + ret_size - sizeof(*info);
745 return status;
748 default:
749 FIXME( "unsupported class %u\n", class );
750 return STATUS_INVALID_INFO_CLASS;
755 /**********************************************************************
756 * wow64_NtQueueApcThread
758 NTSTATUS WINAPI wow64_NtQueueApcThread( UINT *args )
760 HANDLE handle = get_handle( &args );
761 ULONG func = get_ulong( &args );
762 ULONG arg1 = get_ulong( &args );
763 ULONG arg2 = get_ulong( &args );
764 ULONG arg3 = get_ulong( &args );
766 return NtQueueApcThread( handle, apc_32to64( func ),
767 (ULONG_PTR)apc_param_32to64( func, arg1 ), arg2, arg3 );
771 /**********************************************************************
772 * wow64_NtRemoveProcessDebug
774 NTSTATUS WINAPI wow64_NtRemoveProcessDebug( UINT *args )
776 HANDLE process = get_handle( &args );
777 HANDLE debug = get_handle( &args );
779 return NtRemoveProcessDebug( process, debug );
783 /**********************************************************************
784 * wow64_NtResumeProcess
786 NTSTATUS WINAPI wow64_NtResumeProcess( UINT *args )
788 HANDLE handle = get_handle( &args );
790 return NtResumeProcess( handle );
794 /**********************************************************************
795 * wow64_NtResumeThread
797 NTSTATUS WINAPI wow64_NtResumeThread( UINT *args )
799 HANDLE handle = get_handle( &args );
800 ULONG *count = get_ptr( &args );
802 return NtResumeThread( handle, count );
806 /**********************************************************************
807 * wow64_NtSetContextThread
809 NTSTATUS WINAPI wow64_NtSetContextThread( UINT *args )
811 HANDLE handle = get_handle( &args );
812 WOW64_CONTEXT *context = get_ptr( &args );
814 return NtSetInformationThread( handle, ThreadWow64Context,
815 context, get_machine_context_size( current_machine ));
819 /**********************************************************************
820 * wow64_NtSetInformationProcess
822 NTSTATUS WINAPI wow64_NtSetInformationProcess( UINT *args )
824 HANDLE handle = get_handle( &args );
825 PROCESSINFOCLASS class = get_ulong( &args );
826 void *ptr = get_ptr( &args );
827 ULONG len = get_ulong( &args );
829 NTSTATUS status;
831 switch (class)
833 case ProcessDefaultHardErrorMode: /* ULONG */
834 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
835 return NtSetInformationProcess( handle, class, ptr, len );
837 case ProcessAffinityMask: /* ULONG_PTR */
838 if (len == sizeof(ULONG))
840 ULONG_PTR mask = *(ULONG *)ptr;
841 return NtSetInformationProcess( handle, class, &mask, sizeof(mask) );
843 else return STATUS_INVALID_PARAMETER;
845 case ProcessExecuteFlags: /* ULONG */
846 return STATUS_ACCESS_DENIED;
848 case ProcessInstrumentationCallback: /* PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION */
849 if (len == sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION32))
851 FIXME( "ProcessInstrumentationCallback stub\n" );
852 return STATUS_SUCCESS;
854 else return STATUS_INFO_LENGTH_MISMATCH;
856 case ProcessThreadStackAllocation: /* PROCESS_STACK_ALLOCATION_INFORMATION(_EX) */
857 if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX32))
859 PROCESS_STACK_ALLOCATION_INFORMATION_EX32 *stack = ptr;
860 PROCESS_STACK_ALLOCATION_INFORMATION_EX info;
862 info.PreferredNode = stack->PreferredNode;
863 info.Reserved0 = stack->Reserved0;
864 info.Reserved1 = stack->Reserved1;
865 info.Reserved2 = stack->Reserved2;
866 info.AllocInfo.ReserveSize = stack->AllocInfo.ReserveSize;
867 info.AllocInfo.ZeroBits = get_zero_bits( stack->AllocInfo.ZeroBits );
868 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
869 stack->AllocInfo.StackBase = PtrToUlong( info.AllocInfo.StackBase );
870 return status;
872 else if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION32))
874 PROCESS_STACK_ALLOCATION_INFORMATION32 *stack = ptr;
875 PROCESS_STACK_ALLOCATION_INFORMATION info;
877 info.ReserveSize = stack->ReserveSize;
878 info.ZeroBits = stack->ZeroBits ? stack->ZeroBits : 0x7fffffff;
879 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
880 stack->StackBase = PtrToUlong( info.StackBase );
881 return status;
883 else return STATUS_INFO_LENGTH_MISMATCH;
885 case ProcessWineMakeProcessSystem: /* HANDLE* */
886 if (len == sizeof(ULONG))
888 HANDLE event = 0;
889 status = NtSetInformationProcess( handle, class, &event, sizeof(HANDLE *) );
890 put_handle( ptr, event );
891 return status;
893 else return STATUS_INFO_LENGTH_MISMATCH;
895 default:
896 FIXME( "unsupported class %u\n", class );
897 return STATUS_INVALID_INFO_CLASS;
902 /**********************************************************************
903 * wow64_NtSetInformationThread
905 NTSTATUS WINAPI wow64_NtSetInformationThread( UINT *args )
907 HANDLE handle = get_handle( &args );
908 THREADINFOCLASS class = get_ulong( &args );
909 void *ptr = get_ptr( &args );
910 ULONG len = get_ulong( &args );
912 switch (class)
914 case ThreadZeroTlsCell: /* ULONG */
915 case ThreadBasePriority: /* ULONG */
916 case ThreadHideFromDebugger: /* void */
917 case ThreadEnableAlignmentFaultFixup: /* BOOLEAN */
918 return NtSetInformationThread( handle, class, ptr, len );
920 case ThreadImpersonationToken: /* HANDLE */
921 if (len == sizeof(ULONG))
923 HANDLE token = LongToHandle( *(ULONG *)ptr );
924 return NtSetInformationThread( handle, class, &token, sizeof(token) );
926 else return STATUS_INVALID_PARAMETER;
928 case ThreadAffinityMask: /* ULONG_PTR */
929 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
930 if (len == sizeof(ULONG))
932 ULONG_PTR mask = *(ULONG *)ptr;
933 return NtSetInformationThread( handle, class, &mask, sizeof(mask) );
935 else return STATUS_INVALID_PARAMETER;
937 case ThreadWow64Context: /* WOW64_CONTEXT* */
938 return STATUS_INVALID_INFO_CLASS;
940 case ThreadGroupInformation: /* GROUP_AFFINITY */
941 if (len == sizeof(GROUP_AFFINITY32))
943 GROUP_AFFINITY32 *info32 = ptr;
944 GROUP_AFFINITY info = { info32->Mask, info32->Group };
946 return NtSetInformationThread( handle, class, &info, sizeof(info) );
948 else return STATUS_INVALID_PARAMETER;
950 case ThreadDescription: /* THREAD_DESCRIPTION_INFORMATION */
951 if (len == sizeof(THREAD_DESCRIPTION_INFORMATION32))
953 THREAD_DESCRIPTION_INFORMATION32 *info32 = ptr;
954 THREAD_DESCRIPTION_INFORMATION info;
956 if (!unicode_str_32to64( &info.Description, &info32->Description ))
957 return STATUS_ACCESS_VIOLATION;
958 return NtSetInformationThread( handle, class, &info, sizeof(info) );
960 else return STATUS_INFO_LENGTH_MISMATCH;
962 default:
963 FIXME( "unsupported class %u\n", class );
964 return STATUS_INVALID_INFO_CLASS;
969 /**********************************************************************
970 * wow64_NtSetThreadExecutionState
972 NTSTATUS WINAPI wow64_NtSetThreadExecutionState( UINT *args )
974 EXECUTION_STATE new_state = get_ulong( &args );
975 EXECUTION_STATE *old_state = get_ptr( &args );
977 return NtSetThreadExecutionState( new_state, old_state );
981 /**********************************************************************
982 * wow64_NtSuspendProcess
984 NTSTATUS WINAPI wow64_NtSuspendProcess( UINT *args )
986 HANDLE handle = get_handle( &args );
988 return NtSuspendProcess( handle );
992 /**********************************************************************
993 * wow64_NtSuspendThread
995 NTSTATUS WINAPI wow64_NtSuspendThread( UINT *args )
997 HANDLE handle = get_handle( &args );
998 ULONG *count = get_ptr( &args );
1000 return NtSuspendThread( handle, count );
1004 /**********************************************************************
1005 * wow64_NtTerminateProcess
1007 NTSTATUS WINAPI wow64_NtTerminateProcess( UINT *args )
1009 HANDLE handle = get_handle( &args );
1010 LONG exit_code = get_ulong( &args );
1012 return NtTerminateProcess( handle, exit_code );
1016 /**********************************************************************
1017 * wow64_NtTerminateThread
1019 NTSTATUS WINAPI wow64_NtTerminateThread( UINT *args )
1021 HANDLE handle = get_handle( &args );
1022 LONG exit_code = get_ulong( &args );
1024 return NtTerminateThread( handle, exit_code );