winmm: Avoid explicitly casting the pointer returned from Heap(Re)Alloc.
[wine.git] / dlls / wow64 / process.c
blob880b7623b1067e9e9b6ed76dbfebd9a688001e91
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/asm.h"
31 #include "wine/exception.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wow);
37 static BOOL is_process_wow64( HANDLE handle )
39 ULONG_PTR info;
41 if (handle == GetCurrentProcess()) return TRUE;
42 if (NtQueryInformationProcess( handle, ProcessWow64Information, &info, sizeof(info), NULL ))
43 return FALSE;
44 return !!info;
48 static BOOL is_process_id_wow64( const CLIENT_ID *id )
50 HANDLE handle;
51 BOOL ret = FALSE;
53 if (id->UniqueProcess == ULongToHandle(GetCurrentProcessId())) return TRUE;
54 if (!NtOpenProcess( &handle, PROCESS_QUERY_LIMITED_INFORMATION, NULL, id ))
56 ret = is_process_wow64( handle );
57 NtClose( handle );
59 return ret;
63 static RTL_USER_PROCESS_PARAMETERS *process_params_32to64( RTL_USER_PROCESS_PARAMETERS **params,
64 RTL_USER_PROCESS_PARAMETERS32 *params32 )
66 UNICODE_STRING image, dllpath, curdir, cmdline, title, desktop, shell, runtime;
67 RTL_USER_PROCESS_PARAMETERS *ret;
69 *params = NULL;
70 if (RtlCreateProcessParametersEx( &ret, unicode_str_32to64( &image, &params32->ImagePathName ),
71 unicode_str_32to64( &dllpath, &params32->DllPath ),
72 unicode_str_32to64( &curdir, &params32->CurrentDirectory.DosPath ),
73 unicode_str_32to64( &cmdline, &params32->CommandLine ),
74 ULongToPtr( params32->Environment ),
75 unicode_str_32to64( &title, &params32->WindowTitle ),
76 unicode_str_32to64( &desktop, &params32->Desktop ),
77 unicode_str_32to64( &shell, &params32->ShellInfo ),
78 unicode_str_32to64( &runtime, &params32->RuntimeInfo ),
79 PROCESS_PARAMS_FLAG_NORMALIZED ))
80 return NULL;
82 ret->DebugFlags = params32->DebugFlags;
83 ret->ConsoleHandle = LongToHandle( params32->ConsoleHandle );
84 ret->ConsoleFlags = params32->ConsoleFlags;
85 ret->hStdInput = LongToHandle( params32->hStdInput );
86 ret->hStdOutput = LongToHandle( params32->hStdOutput );
87 ret->hStdError = LongToHandle( params32->hStdError );
88 ret->dwX = params32->dwX;
89 ret->dwY = params32->dwY;
90 ret->dwXSize = params32->dwXSize;
91 ret->dwYSize = params32->dwYSize;
92 ret->dwXCountChars = params32->dwXCountChars;
93 ret->dwYCountChars = params32->dwYCountChars;
94 ret->dwFillAttribute = params32->dwFillAttribute;
95 ret->dwFlags = params32->dwFlags;
96 ret->wShowWindow = params32->wShowWindow;
97 ret->EnvironmentVersion = params32->EnvironmentVersion;
98 ret->PackageDependencyData = ULongToPtr( params32->PackageDependencyData );
99 ret->ProcessGroupId = params32->ProcessGroupId;
100 ret->LoaderThreads = params32->LoaderThreads;
101 *params = ret;
102 return ret;
106 static void put_ps_create_info( PS_CREATE_INFO32 *info32, const PS_CREATE_INFO *info )
108 info32->State = info->State;
109 switch (info->State)
111 case PsCreateInitialState:
112 info32->InitState.InitFlags = info->InitState.InitFlags;
113 info32->InitState.AdditionalFileAccess = info->InitState.AdditionalFileAccess;
114 break;
115 case PsCreateFailOnSectionCreate:
116 info32->FailSection.FileHandle = HandleToLong( info->FailSection.FileHandle );
117 break;
118 case PsCreateFailExeFormat:
119 info32->ExeFormat.DllCharacteristics = info->ExeFormat.DllCharacteristics;
120 break;
121 case PsCreateFailExeName:
122 info32->ExeName.IFEOKey = HandleToLong( info->ExeName.IFEOKey );
123 break;
124 case PsCreateSuccess:
125 info32->SuccessState.OutputFlags = info->SuccessState.OutputFlags;
126 info32->SuccessState.FileHandle = HandleToLong( info->SuccessState.FileHandle );
127 info32->SuccessState.SectionHandle = HandleToLong( info->SuccessState.SectionHandle );
128 info32->SuccessState.UserProcessParametersNative = info->SuccessState.UserProcessParametersNative;
129 info32->SuccessState.UserProcessParametersWow64 = info->SuccessState.UserProcessParametersWow64;
130 info32->SuccessState.CurrentParameterFlags = info->SuccessState.CurrentParameterFlags;
131 info32->SuccessState.PebAddressNative = info->SuccessState.PebAddressNative;
132 info32->SuccessState.PebAddressWow64 = info->SuccessState.PebAddressWow64;
133 info32->SuccessState.ManifestAddress = info->SuccessState.ManifestAddress;
134 info32->SuccessState.ManifestSize = info->SuccessState.ManifestSize;
135 break;
136 default:
137 break;
142 static PS_ATTRIBUTE_LIST *ps_attributes_32to64( PS_ATTRIBUTE_LIST **attr, const PS_ATTRIBUTE_LIST32 *attr32 )
144 PS_ATTRIBUTE_LIST *ret;
145 ULONG i, count;
147 if (!attr32) return NULL;
148 count = (attr32->TotalLength - sizeof(attr32->TotalLength)) / sizeof(PS_ATTRIBUTE32);
149 ret = Wow64AllocateTemp( offsetof(PS_ATTRIBUTE_LIST, Attributes[count]) );
150 ret->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[count] );
151 for (i = 0; i < count; i++)
153 ret->Attributes[i].Attribute = attr32->Attributes[i].Attribute;
154 ret->Attributes[i].Size = attr32->Attributes[i].Size;
155 ret->Attributes[i].Value = attr32->Attributes[i].Value;
156 ret->Attributes[i].ReturnLength = NULL;
157 switch (ret->Attributes[i].Attribute)
159 case PS_ATTRIBUTE_IMAGE_NAME:
161 OBJECT_ATTRIBUTES attr;
162 UNICODE_STRING path;
164 path.Length = ret->Attributes[i].Size;
165 path.Buffer = ret->Attributes[i].ValuePtr;
166 InitializeObjectAttributes( &attr, &path, OBJ_CASE_INSENSITIVE, 0, 0 );
167 if (get_file_redirect( &attr ))
169 ret->Attributes[i].Size = attr.ObjectName->Length;
170 ret->Attributes[i].ValuePtr = attr.ObjectName->Buffer;
173 break;
174 case PS_ATTRIBUTE_HANDLE_LIST:
175 case PS_ATTRIBUTE_JOB_LIST:
177 ULONG j, handles_count = attr32->Attributes[i].Size / sizeof(ULONG);
179 ret->Attributes[i].Size = handles_count * sizeof(HANDLE);
180 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
181 for (j = 0; j < handles_count; j++)
182 ((HANDLE *)ret->Attributes[i].ValuePtr)[j] =
183 LongToHandle( ((LONG *)ULongToPtr(attr32->Attributes[i].Value))[j] );
185 break;
186 case PS_ATTRIBUTE_PARENT_PROCESS:
187 case PS_ATTRIBUTE_DEBUG_PORT:
188 case PS_ATTRIBUTE_TOKEN:
189 ret->Attributes[i].Size = sizeof(HANDLE);
190 ret->Attributes[i].ValuePtr = LongToHandle( attr32->Attributes[i].Value );
191 break;
192 case PS_ATTRIBUTE_CLIENT_ID:
193 ret->Attributes[i].Size = sizeof(CLIENT_ID);
194 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
195 break;
196 case PS_ATTRIBUTE_IMAGE_INFO:
197 ret->Attributes[i].Size = sizeof(SECTION_IMAGE_INFORMATION);
198 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
199 break;
200 case PS_ATTRIBUTE_TEB_ADDRESS:
201 ret->Attributes[i].Size = sizeof(TEB *);
202 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
203 break;
206 *attr = ret;
207 return ret;
211 static void put_ps_attributes( PS_ATTRIBUTE_LIST32 *attr32, const PS_ATTRIBUTE_LIST *attr )
213 ULONG i;
215 if (!attr32) return;
216 for (i = 0; i < (attr32->TotalLength - sizeof(attr32->TotalLength)) / sizeof(PS_ATTRIBUTE32); i++)
218 switch (attr->Attributes[i].Attribute)
220 case PS_ATTRIBUTE_CLIENT_ID:
222 CLIENT_ID32 id32;
223 ULONG size = min( attr32->Attributes[i].Size, sizeof(id32) );
224 put_client_id( &id32, attr->Attributes[i].ValuePtr );
225 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &id32, size );
226 if (attr32->Attributes[i].ReturnLength)
227 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
228 break;
230 case PS_ATTRIBUTE_IMAGE_INFO:
232 SECTION_IMAGE_INFORMATION32 info32;
233 ULONG size = min( attr32->Attributes[i].Size, sizeof(info32) );
234 put_section_image_info( &info32, attr->Attributes[i].ValuePtr );
235 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &info32, size );
236 if (attr32->Attributes[i].ReturnLength)
237 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
238 break;
240 case PS_ATTRIBUTE_TEB_ADDRESS:
242 TEB **teb = attr->Attributes[i].ValuePtr;
243 ULONG teb32 = PtrToUlong( *teb ) + 0x2000;
244 ULONG size = min( attr->Attributes[i].Size, sizeof(teb32) );
245 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &teb32, size );
246 if (attr32->Attributes[i].ReturnLength)
247 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
248 break;
255 void put_vm_counters( VM_COUNTERS_EX32 *info32, const VM_COUNTERS_EX *info, ULONG size )
257 info32->PeakVirtualSize = info->PeakVirtualSize;
258 info32->VirtualSize = info->VirtualSize;
259 info32->PageFaultCount = info->PageFaultCount;
260 info32->PeakWorkingSetSize = info->PeakWorkingSetSize;
261 info32->WorkingSetSize = info->WorkingSetSize;
262 info32->QuotaPeakPagedPoolUsage = info->QuotaPeakPagedPoolUsage;
263 info32->QuotaPagedPoolUsage = info->QuotaPagedPoolUsage;
264 info32->QuotaPeakNonPagedPoolUsage = info->QuotaPeakNonPagedPoolUsage;
265 info32->QuotaNonPagedPoolUsage = info->QuotaNonPagedPoolUsage;
266 info32->PagefileUsage = info->PagefileUsage;
267 info32->PeakPagefileUsage = info->PeakPagefileUsage;
268 if (size == sizeof(VM_COUNTERS_EX32)) info32->PrivateUsage = info->PrivateUsage;
272 /**********************************************************************
273 * wow64_NtAlertResumeThread
275 NTSTATUS WINAPI wow64_NtAlertResumeThread( UINT *args )
277 HANDLE handle = get_handle( &args );
278 ULONG *count = get_ptr( &args );
280 return NtAlertResumeThread( handle, count );
284 /**********************************************************************
285 * wow64_NtAlertThread
287 NTSTATUS WINAPI wow64_NtAlertThread( UINT *args )
289 HANDLE handle = get_handle( &args );
291 return NtAlertThread( handle );
295 /**********************************************************************
296 * wow64_NtAlertThreadByThreadId
298 NTSTATUS WINAPI wow64_NtAlertThreadByThreadId( UINT *args )
300 HANDLE tid = get_handle( &args );
302 return NtAlertThreadByThreadId( tid );
306 /**********************************************************************
307 * wow64_NtAssignProcessToJobObject
309 NTSTATUS WINAPI wow64_NtAssignProcessToJobObject( UINT *args )
311 HANDLE job = get_handle( &args );
312 HANDLE process = get_handle( &args );
314 return NtAssignProcessToJobObject( job, process );
318 /**********************************************************************
319 * wow64_NtCreateThread
321 NTSTATUS WINAPI wow64_NtCreateThread( UINT *args )
323 ULONG *handle_ptr = get_ptr( &args );
324 ACCESS_MASK access = get_ulong( &args );
325 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
326 HANDLE process = get_handle( &args );
327 CLIENT_ID32 *id32 = get_ptr( &args );
328 I386_CONTEXT *context = get_ptr( &args );
329 void *initial_teb = get_ptr( &args );
330 BOOLEAN suspended = get_ulong( &args );
332 FIXME( "%p %lx %p %p %p %p %p %u: stub\n", handle_ptr, access, attr32, process,
333 id32, context, initial_teb, suspended );
334 return STATUS_NOT_IMPLEMENTED;
338 /**********************************************************************
339 * wow64_NtCreateThreadEx
341 NTSTATUS WINAPI wow64_NtCreateThreadEx( UINT *args )
343 ULONG *handle_ptr = get_ptr( &args );
344 ACCESS_MASK access = get_ulong( &args );
345 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
346 HANDLE process = get_handle( &args );
347 PRTL_THREAD_START_ROUTINE start = get_ptr( &args );
348 void *param = get_ptr( &args );
349 ULONG flags = get_ulong( &args );
350 ULONG_PTR zero_bits = get_ulong( &args );
351 SIZE_T stack_commit = get_ulong( &args );
352 SIZE_T stack_reserve = get_ulong( &args );
353 PS_ATTRIBUTE_LIST32 *attr_list32 = get_ptr( &args );
355 struct object_attr64 attr;
356 PS_ATTRIBUTE_LIST *attr_list;
357 HANDLE handle = 0;
358 NTSTATUS status;
360 *handle_ptr = 0;
361 if (is_process_wow64( process ))
363 status = NtCreateThreadEx( &handle, access, objattr_32to64( &attr, attr32 ), process,
364 start, param, flags, get_zero_bits( zero_bits ),
365 stack_commit, stack_reserve,
366 ps_attributes_32to64( &attr_list, attr_list32 ));
367 put_ps_attributes( attr_list32, attr_list );
369 else status = STATUS_ACCESS_DENIED;
371 put_handle( handle_ptr, handle );
372 return status;
376 /**********************************************************************
377 * wow64_NtCreateUserProcess
379 NTSTATUS WINAPI wow64_NtCreateUserProcess( UINT *args )
381 ULONG *process_handle_ptr = get_ptr( &args );
382 ULONG *thread_handle_ptr = get_ptr( &args );
383 ACCESS_MASK process_access = get_ulong( &args );
384 ACCESS_MASK thread_access = get_ulong( &args );
385 OBJECT_ATTRIBUTES32 *process_attr32 = get_ptr( &args );
386 OBJECT_ATTRIBUTES32 *thread_attr32 = get_ptr( &args );
387 ULONG process_flags = get_ulong( &args );
388 ULONG thread_flags = get_ulong( &args );
389 RTL_USER_PROCESS_PARAMETERS32 *params32 = get_ptr( &args );
390 PS_CREATE_INFO32 *info32 = get_ptr( &args );
391 PS_ATTRIBUTE_LIST32 *attr32 = get_ptr( &args );
393 struct object_attr64 process_attr, thread_attr;
394 RTL_USER_PROCESS_PARAMETERS *params;
395 PS_CREATE_INFO info;
396 PS_ATTRIBUTE_LIST *attr;
397 HANDLE process_handle = 0, thread_handle = 0;
399 NTSTATUS status;
401 *process_handle_ptr = *thread_handle_ptr = 0;
402 status = NtCreateUserProcess( &process_handle, &thread_handle, process_access, thread_access,
403 objattr_32to64( &process_attr, process_attr32 ),
404 objattr_32to64( &thread_attr, thread_attr32 ),
405 process_flags, thread_flags,
406 process_params_32to64( &params, params32),
407 &info, ps_attributes_32to64( &attr, attr32 ));
408 put_handle( process_handle_ptr, process_handle );
409 put_handle( thread_handle_ptr, thread_handle );
410 put_ps_create_info( info32, &info );
411 put_ps_attributes( attr32, attr );
412 RtlDestroyProcessParameters( params );
413 return status;
417 /**********************************************************************
418 * wow64_NtDebugActiveProcess
420 NTSTATUS WINAPI wow64_NtDebugActiveProcess( UINT *args )
422 HANDLE process = get_handle( &args );
423 HANDLE debug = get_handle( &args );
425 return NtDebugActiveProcess( process, debug );
429 /**********************************************************************
430 * wow64_NtFlushProcessWriteBuffers
432 NTSTATUS WINAPI wow64_NtFlushProcessWriteBuffers( UINT *args )
434 NtFlushProcessWriteBuffers();
435 return STATUS_SUCCESS;
439 /**********************************************************************
440 * wow64_NtGetNextThread
442 NTSTATUS WINAPI wow64_NtGetNextThread( UINT *args )
444 HANDLE process = get_handle( &args );
445 HANDLE thread = get_handle( &args );
446 ACCESS_MASK access = get_ulong( &args );
447 ULONG attributes = get_ulong( &args );
448 ULONG flags = get_ulong( &args );
449 ULONG *handle_ptr = get_ptr( &args );
451 HANDLE handle = 0;
452 NTSTATUS status;
454 *handle_ptr = 0;
455 status = NtGetNextThread( process, thread, access, attributes, flags, &handle );
456 put_handle( handle_ptr, handle );
457 return status;
461 /**********************************************************************
462 * wow64_NtIsProcessInJob
464 NTSTATUS WINAPI wow64_NtIsProcessInJob( UINT *args )
466 HANDLE process = get_handle( &args );
467 HANDLE job = get_handle( &args );
469 return NtIsProcessInJob( process, job );
473 /**********************************************************************
474 * wow64_NtOpenProcess
476 NTSTATUS WINAPI wow64_NtOpenProcess( UINT *args )
478 ULONG *handle_ptr = get_ptr( &args );
479 ACCESS_MASK access = get_ulong( &args );
480 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
481 CLIENT_ID32 *id32 = get_ptr( &args );
483 struct object_attr64 attr;
484 HANDLE handle = 0;
485 CLIENT_ID id;
486 NTSTATUS status;
488 *handle_ptr = 0;
489 status = NtOpenProcess( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
490 put_handle( handle_ptr, handle );
491 return status;
495 /**********************************************************************
496 * wow64_NtOpenThread
498 NTSTATUS WINAPI wow64_NtOpenThread( UINT *args )
500 ULONG *handle_ptr = get_ptr( &args );
501 ACCESS_MASK access = get_ulong( &args );
502 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
503 CLIENT_ID32 *id32 = get_ptr( &args );
505 struct object_attr64 attr;
506 HANDLE handle = 0;
507 CLIENT_ID id;
508 NTSTATUS status;
510 *handle_ptr = 0;
511 status = NtOpenThread( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
512 put_handle( handle_ptr, handle );
513 return status;
517 /**********************************************************************
518 * wow64_NtQueryInformationProcess
520 NTSTATUS WINAPI wow64_NtQueryInformationProcess( UINT *args )
522 HANDLE handle = get_handle( &args );
523 PROCESSINFOCLASS class = get_ulong( &args );
524 void *ptr = get_ptr( &args );
525 ULONG len = get_ulong( &args );
526 ULONG *retlen = get_ptr( &args );
528 NTSTATUS status;
530 switch (class)
532 case ProcessBasicInformation: /* PROCESS_BASIC_INFORMATION */
533 if (len == sizeof(PROCESS_BASIC_INFORMATION32))
535 PROCESS_BASIC_INFORMATION info;
536 PROCESS_BASIC_INFORMATION32 *info32 = ptr;
538 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
540 if (is_process_wow64( handle ))
541 info32->PebBaseAddress = PtrToUlong( info.PebBaseAddress ) + 0x1000;
542 else
543 info32->PebBaseAddress = 0;
544 info32->ExitStatus = info.ExitStatus;
545 info32->AffinityMask = info.AffinityMask;
546 info32->BasePriority = info.BasePriority;
547 info32->UniqueProcessId = info.UniqueProcessId;
548 info32->InheritedFromUniqueProcessId = info.InheritedFromUniqueProcessId;
549 if (retlen) *retlen = sizeof(*info32);
551 return status;
553 if (retlen) *retlen = sizeof(PROCESS_BASIC_INFORMATION32);
554 return STATUS_INFO_LENGTH_MISMATCH;
556 case ProcessIoCounters: /* IO_COUNTERS */
557 case ProcessTimes: /* KERNEL_USER_TIMES */
558 case ProcessDefaultHardErrorMode: /* ULONG */
559 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
560 case ProcessHandleCount: /* ULONG */
561 case ProcessSessionInformation: /* ULONG */
562 case ProcessDebugFlags: /* ULONG */
563 case ProcessExecuteFlags: /* ULONG */
564 case ProcessCookie: /* ULONG */
565 case ProcessCycleTime: /* PROCESS_CYCLE_TIME_INFORMATION */
566 /* FIXME: check buffer alignment */
567 return NtQueryInformationProcess( handle, class, ptr, len, retlen );
569 case ProcessVmCounters: /* VM_COUNTERS_EX */
570 if (len == sizeof(VM_COUNTERS32) || len == sizeof(VM_COUNTERS_EX32))
572 VM_COUNTERS_EX info;
573 VM_COUNTERS_EX32 *info32 = ptr;
575 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
577 put_vm_counters( info32, &info, len );
578 if (retlen) *retlen = len;
580 return status;
582 if (retlen) *retlen = sizeof(VM_COUNTERS_EX32);
583 return STATUS_INFO_LENGTH_MISMATCH;
585 case ProcessDebugPort: /* ULONG_PTR */
586 case ProcessAffinityMask: /* ULONG_PTR */
587 case ProcessWow64Information: /* ULONG_PTR */
588 case ProcessDebugObjectHandle: /* HANDLE */
589 if (len == sizeof(ULONG))
591 ULONG_PTR data;
593 if (!(status = NtQueryInformationProcess( handle, class, &data, sizeof(data), NULL )))
595 *(ULONG *)ptr = data;
596 if (retlen) *retlen = sizeof(ULONG);
598 else if (status == STATUS_PORT_NOT_SET)
600 *(ULONG *)ptr = 0;
601 if (retlen) *retlen = sizeof(ULONG);
603 return status;
605 return STATUS_INFO_LENGTH_MISMATCH;
607 case ProcessImageFileName:
608 case ProcessImageFileNameWin32: /* UNICODE_STRING + string */
610 ULONG retsize, size = len + sizeof(UNICODE_STRING) - sizeof(UNICODE_STRING32);
611 UNICODE_STRING *str = Wow64AllocateTemp( size );
612 UNICODE_STRING32 *str32 = ptr;
614 if (!(status = NtQueryInformationProcess( handle, class, str, size, &retsize )))
616 str32->Length = str->Length;
617 str32->MaximumLength = str->MaximumLength;
618 str32->Buffer = PtrToUlong( str32 + 1 );
619 memcpy( str32 + 1, str->Buffer, str->MaximumLength );
621 if (retlen) *retlen = retsize + sizeof(UNICODE_STRING32) - sizeof(UNICODE_STRING);
622 return status;
625 case ProcessImageInformation: /* SECTION_IMAGE_INFORMATION */
626 if (len == sizeof(SECTION_IMAGE_INFORMATION32))
628 SECTION_IMAGE_INFORMATION info;
629 SECTION_IMAGE_INFORMATION32 *info32 = ptr;
631 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
633 put_section_image_info( info32, &info );
634 if (retlen) *retlen = sizeof(*info32);
636 return status;
638 if (retlen) *retlen = sizeof(SECTION_IMAGE_INFORMATION32);
639 return STATUS_INFO_LENGTH_MISMATCH;
641 case ProcessWineLdtCopy:
642 return STATUS_NOT_IMPLEMENTED;
644 default:
645 FIXME( "unsupported class %u\n", class );
646 return STATUS_INVALID_INFO_CLASS;
651 /**********************************************************************
652 * wow64_NtQueryInformationThread
654 NTSTATUS WINAPI wow64_NtQueryInformationThread( UINT *args )
656 HANDLE handle = get_handle( &args );
657 THREADINFOCLASS class = get_ulong( &args );
658 void *ptr = get_ptr( &args );
659 ULONG len = get_ulong( &args );
660 ULONG *retlen = get_ptr( &args );
662 NTSTATUS status;
664 switch (class)
666 case ThreadBasicInformation: /* THREAD_BASIC_INFORMATION */
668 THREAD_BASIC_INFORMATION32 info32;
669 THREAD_BASIC_INFORMATION info;
671 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
672 if (!status)
674 info32.ExitStatus = info.ExitStatus;
675 info32.TebBaseAddress = is_process_id_wow64( &info.ClientId ) ?
676 PtrToUlong(info.TebBaseAddress) + 0x2000 : 0;
677 info32.ClientId.UniqueProcess = HandleToULong( info.ClientId.UniqueProcess );
678 info32.ClientId.UniqueThread = HandleToULong( info.ClientId.UniqueThread );
679 info32.AffinityMask = info.AffinityMask;
680 info32.Priority = info.Priority;
681 info32.BasePriority = info.BasePriority;
682 memcpy( ptr, &info32, min( len, sizeof(info32) ));
683 if (retlen) *retlen = min( len, sizeof(info32) );
685 return status;
688 case ThreadTimes: /* KERNEL_USER_TIMES */
689 case ThreadEnableAlignmentFaultFixup: /* set only */
690 case ThreadAmILastThread: /* ULONG */
691 case ThreadIsIoPending: /* ULONG */
692 case ThreadHideFromDebugger: /* BOOLEAN */
693 case ThreadSuspendCount: /* ULONG */
694 case ThreadPriorityBoost: /* ULONG */
695 /* FIXME: check buffer alignment */
696 return NtQueryInformationThread( handle, class, ptr, len, retlen );
698 case ThreadAffinityMask: /* ULONG_PTR */
699 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
701 ULONG_PTR data;
703 status = NtQueryInformationThread( handle, class, &data, sizeof(data), NULL );
704 if (!status)
706 memcpy( ptr, &data, min( len, sizeof(ULONG) ));
707 if (retlen) *retlen = min( len, sizeof(ULONG) );
709 return status;
712 case ThreadDescriptorTableEntry: /* THREAD_DESCRIPTOR_INFORMATION */
713 return RtlWow64GetThreadSelectorEntry( handle, ptr, len, retlen );
715 case ThreadWow64Context: /* WOW64_CONTEXT* */
716 return STATUS_INVALID_INFO_CLASS;
718 case ThreadGroupInformation: /* GROUP_AFFINITY */
720 GROUP_AFFINITY info;
722 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
723 if (!status)
725 GROUP_AFFINITY32 info32 = { info.Mask, info.Group };
726 memcpy( ptr, &info32, min( len, sizeof(info32) ));
727 if (retlen) *retlen = min( len, sizeof(info32) );
729 return status;
732 case ThreadNameInformation: /* THREAD_NAME_INFORMATION */
734 THREAD_NAME_INFORMATION *info;
735 THREAD_NAME_INFORMATION32 *info32 = ptr;
736 ULONG size, ret_size;
738 if (len >= sizeof(*info32))
740 size = sizeof(*info) + len - sizeof(*info32);
741 info = Wow64AllocateTemp( size );
742 status = NtQueryInformationThread( handle, class, info, size, &ret_size );
743 if (!status)
745 info32->ThreadName.Length = info->ThreadName.Length;
746 info32->ThreadName.MaximumLength = info->ThreadName.MaximumLength;
747 info32->ThreadName.Buffer = PtrToUlong( info32 + 1 );
748 memcpy( info32 + 1, info + 1, min( len, info->ThreadName.MaximumLength ));
751 else status = NtQueryInformationThread( handle, class, NULL, 0, &ret_size );
753 if (retlen && (status == STATUS_SUCCESS || status == STATUS_BUFFER_TOO_SMALL))
754 *retlen = sizeof(*info32) + ret_size - sizeof(*info);
755 return status;
758 default:
759 FIXME( "unsupported class %u\n", class );
760 return STATUS_INVALID_INFO_CLASS;
765 /**********************************************************************
766 * wow64_NtQueueApcThread
768 NTSTATUS WINAPI wow64_NtQueueApcThread( UINT *args )
770 HANDLE handle = get_handle( &args );
771 ULONG func = get_ulong( &args );
772 ULONG arg1 = get_ulong( &args );
773 ULONG arg2 = get_ulong( &args );
774 ULONG arg3 = get_ulong( &args );
776 return NtQueueApcThread( handle, apc_32to64( func ),
777 (ULONG_PTR)apc_param_32to64( func, arg1 ), arg2, arg3 );
781 /**********************************************************************
782 * wow64_NtRemoveProcessDebug
784 NTSTATUS WINAPI wow64_NtRemoveProcessDebug( UINT *args )
786 HANDLE process = get_handle( &args );
787 HANDLE debug = get_handle( &args );
789 return NtRemoveProcessDebug( process, debug );
793 /**********************************************************************
794 * wow64_NtResumeProcess
796 NTSTATUS WINAPI wow64_NtResumeProcess( UINT *args )
798 HANDLE handle = get_handle( &args );
800 return NtResumeProcess( handle );
804 /**********************************************************************
805 * wow64_NtResumeThread
807 NTSTATUS WINAPI wow64_NtResumeThread( UINT *args )
809 HANDLE handle = get_handle( &args );
810 ULONG *count = get_ptr( &args );
812 return NtResumeThread( handle, count );
816 /**********************************************************************
817 * wow64_NtSetInformationProcess
819 NTSTATUS WINAPI wow64_NtSetInformationProcess( UINT *args )
821 HANDLE handle = get_handle( &args );
822 PROCESSINFOCLASS class = get_ulong( &args );
823 void *ptr = get_ptr( &args );
824 ULONG len = get_ulong( &args );
826 NTSTATUS status;
828 switch (class)
830 case ProcessDefaultHardErrorMode: /* ULONG */
831 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
832 case ProcessExecuteFlags: /* ULONG */
833 case ProcessPagePriority: /* MEMORY_PRIORITY_INFORMATION */
834 case ProcessPowerThrottlingState: /* PROCESS_POWER_THROTTLING_STATE */
835 case ProcessLeapSecondInformation: /* PROCESS_LEAP_SECOND_INFO */
836 return NtSetInformationProcess( handle, class, ptr, len );
838 case ProcessAffinityMask: /* ULONG_PTR */
839 if (len == sizeof(ULONG))
841 ULONG_PTR mask = *(ULONG *)ptr;
842 return NtSetInformationProcess( handle, class, &mask, sizeof(mask) );
844 else return STATUS_INVALID_PARAMETER;
846 case ProcessInstrumentationCallback: /* PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION */
847 if (len == sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION32))
849 FIXME( "ProcessInstrumentationCallback stub\n" );
850 return STATUS_SUCCESS;
852 else return STATUS_INFO_LENGTH_MISMATCH;
854 case ProcessThreadStackAllocation: /* PROCESS_STACK_ALLOCATION_INFORMATION(_EX) */
855 if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX32))
857 PROCESS_STACK_ALLOCATION_INFORMATION_EX32 *stack = ptr;
858 PROCESS_STACK_ALLOCATION_INFORMATION_EX info;
860 info.PreferredNode = stack->PreferredNode;
861 info.Reserved0 = stack->Reserved0;
862 info.Reserved1 = stack->Reserved1;
863 info.Reserved2 = stack->Reserved2;
864 info.AllocInfo.ReserveSize = stack->AllocInfo.ReserveSize;
865 info.AllocInfo.ZeroBits = get_zero_bits( stack->AllocInfo.ZeroBits );
866 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
867 stack->AllocInfo.StackBase = PtrToUlong( info.AllocInfo.StackBase );
868 return status;
870 else if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION32))
872 PROCESS_STACK_ALLOCATION_INFORMATION32 *stack = ptr;
873 PROCESS_STACK_ALLOCATION_INFORMATION info;
875 info.ReserveSize = stack->ReserveSize;
876 info.ZeroBits = get_zero_bits( stack->ZeroBits );
877 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
878 stack->StackBase = PtrToUlong( info.StackBase );
879 return status;
881 else return STATUS_INFO_LENGTH_MISMATCH;
883 case ProcessWineMakeProcessSystem: /* HANDLE* */
884 if (len == sizeof(ULONG))
886 HANDLE event = 0;
887 status = NtSetInformationProcess( handle, class, &event, sizeof(HANDLE *) );
888 put_handle( ptr, event );
889 return status;
891 else return STATUS_INFO_LENGTH_MISMATCH;
893 default:
894 FIXME( "unsupported class %u\n", class );
895 return STATUS_INVALID_INFO_CLASS;
900 /**********************************************************************
901 * wow64_NtSetInformationThread
903 NTSTATUS WINAPI wow64_NtSetInformationThread( UINT *args )
905 HANDLE handle = get_handle( &args );
906 THREADINFOCLASS class = get_ulong( &args );
907 void *ptr = get_ptr( &args );
908 ULONG len = get_ulong( &args );
910 switch (class)
912 case ThreadZeroTlsCell: /* ULONG */
913 case ThreadBasePriority: /* ULONG */
914 case ThreadHideFromDebugger: /* void */
915 case ThreadEnableAlignmentFaultFixup: /* BOOLEAN */
916 case ThreadPowerThrottlingState: /* THREAD_POWER_THROTTLING_STATE */
917 case ThreadIdealProcessor: /* ULONG */
918 case ThreadPriorityBoost: /* ULONG */
919 return NtSetInformationThread( handle, class, ptr, len );
921 case ThreadImpersonationToken: /* HANDLE */
922 if (len == sizeof(ULONG))
924 HANDLE token = LongToHandle( *(ULONG *)ptr );
925 return NtSetInformationThread( handle, class, &token, sizeof(token) );
927 else return STATUS_INVALID_PARAMETER;
929 case ThreadAffinityMask: /* ULONG_PTR */
930 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
931 if (len == sizeof(ULONG))
933 ULONG_PTR mask = *(ULONG *)ptr;
934 return NtSetInformationThread( handle, class, &mask, sizeof(mask) );
936 else return STATUS_INVALID_PARAMETER;
938 case ThreadWow64Context: /* WOW64_CONTEXT* */
939 return STATUS_INVALID_INFO_CLASS;
941 case ThreadGroupInformation: /* GROUP_AFFINITY */
942 if (len == sizeof(GROUP_AFFINITY32))
944 GROUP_AFFINITY32 *info32 = ptr;
945 GROUP_AFFINITY info = { info32->Mask, info32->Group };
947 return NtSetInformationThread( handle, class, &info, sizeof(info) );
949 else return STATUS_INVALID_PARAMETER;
951 case ThreadNameInformation: /* THREAD_NAME_INFORMATION */
952 case ThreadWineNativeThreadName:
953 if (len == sizeof(THREAD_NAME_INFORMATION32))
955 THREAD_NAME_INFORMATION32 *info32 = ptr;
956 THREAD_NAME_INFORMATION info;
958 if (!unicode_str_32to64( &info.ThreadName, &info32->ThreadName ))
959 return STATUS_ACCESS_VIOLATION;
960 return NtSetInformationThread( handle, class, &info, sizeof(info) );
962 else return STATUS_INFO_LENGTH_MISMATCH;
964 default:
965 FIXME( "unsupported class %u\n", class );
966 return STATUS_INVALID_INFO_CLASS;
971 /**********************************************************************
972 * wow64_NtSetThreadExecutionState
974 NTSTATUS WINAPI wow64_NtSetThreadExecutionState( UINT *args )
976 EXECUTION_STATE new_state = get_ulong( &args );
977 EXECUTION_STATE *old_state = get_ptr( &args );
979 return NtSetThreadExecutionState( new_state, old_state );
983 /**********************************************************************
984 * wow64_NtSuspendProcess
986 NTSTATUS WINAPI wow64_NtSuspendProcess( UINT *args )
988 HANDLE handle = get_handle( &args );
990 return NtSuspendProcess( handle );
994 /**********************************************************************
995 * wow64_NtSuspendThread
997 NTSTATUS WINAPI wow64_NtSuspendThread( UINT *args )
999 HANDLE handle = get_handle( &args );
1000 ULONG *count = get_ptr( &args );
1002 return NtSuspendThread( handle, count );
1006 /**********************************************************************
1007 * wow64_NtTerminateProcess
1009 NTSTATUS WINAPI wow64_NtTerminateProcess( UINT *args )
1011 HANDLE handle = get_handle( &args );
1012 LONG exit_code = get_ulong( &args );
1014 return NtTerminateProcess( handle, exit_code );
1018 /**********************************************************************
1019 * wow64_NtTerminateThread
1021 NTSTATUS WINAPI wow64_NtTerminateThread( UINT *args )
1023 HANDLE handle = get_handle( &args );
1024 LONG exit_code = get_ulong( &args );
1026 if (pBTCpuThreadTerm) pBTCpuThreadTerm( handle );
1028 return NtTerminateThread( handle, exit_code );