kernelbase: Let GetModuleBaseName succeed on 64bit modules in wow64.
[wine.git] / dlls / wow64 / process.c
blob2a14ef4cc3cab9683d54f14f5ba0a305525f40e9
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 ret->Attributes[i].Size = sizeof(HANDLE);
188 ret->Attributes[i].ValuePtr = LongToHandle( attr32->Attributes[i].Value );
189 break;
190 case PS_ATTRIBUTE_CLIENT_ID:
191 ret->Attributes[i].Size = sizeof(CLIENT_ID);
192 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
193 break;
194 case PS_ATTRIBUTE_IMAGE_INFO:
195 ret->Attributes[i].Size = sizeof(SECTION_IMAGE_INFORMATION);
196 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
197 break;
198 case PS_ATTRIBUTE_TEB_ADDRESS:
199 ret->Attributes[i].Size = sizeof(TEB *);
200 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
201 break;
204 *attr = ret;
205 return ret;
209 static void put_ps_attributes( PS_ATTRIBUTE_LIST32 *attr32, const PS_ATTRIBUTE_LIST *attr )
211 ULONG i;
213 if (!attr32) return;
214 for (i = 0; i < (attr32->TotalLength - sizeof(attr32->TotalLength)) / sizeof(PS_ATTRIBUTE32); i++)
216 switch (attr->Attributes[i].Attribute)
218 case PS_ATTRIBUTE_CLIENT_ID:
220 CLIENT_ID32 id32;
221 ULONG size = min( attr32->Attributes[i].Size, sizeof(id32) );
222 put_client_id( &id32, attr->Attributes[i].ValuePtr );
223 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &id32, size );
224 if (attr32->Attributes[i].ReturnLength)
225 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
226 break;
228 case PS_ATTRIBUTE_IMAGE_INFO:
230 SECTION_IMAGE_INFORMATION32 info32;
231 ULONG size = min( attr32->Attributes[i].Size, sizeof(info32) );
232 put_section_image_info( &info32, attr->Attributes[i].ValuePtr );
233 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &info32, size );
234 if (attr32->Attributes[i].ReturnLength)
235 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
236 break;
238 case PS_ATTRIBUTE_TEB_ADDRESS:
240 TEB **teb = attr->Attributes[i].ValuePtr;
241 ULONG teb32 = PtrToUlong( *teb ) + 0x2000;
242 ULONG size = min( attr->Attributes[i].Size, sizeof(teb32) );
243 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &teb32, size );
244 if (attr32->Attributes[i].ReturnLength)
245 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
246 break;
253 void put_vm_counters( VM_COUNTERS_EX32 *info32, const VM_COUNTERS_EX *info, ULONG size )
255 info32->PeakVirtualSize = info->PeakVirtualSize;
256 info32->VirtualSize = info->VirtualSize;
257 info32->PageFaultCount = info->PageFaultCount;
258 info32->PeakWorkingSetSize = info->PeakWorkingSetSize;
259 info32->WorkingSetSize = info->WorkingSetSize;
260 info32->QuotaPeakPagedPoolUsage = info->QuotaPeakPagedPoolUsage;
261 info32->QuotaPagedPoolUsage = info->QuotaPagedPoolUsage;
262 info32->QuotaPeakNonPagedPoolUsage = info->QuotaPeakNonPagedPoolUsage;
263 info32->QuotaNonPagedPoolUsage = info->QuotaNonPagedPoolUsage;
264 info32->PagefileUsage = info->PagefileUsage;
265 info32->PeakPagefileUsage = info->PeakPagefileUsage;
266 if (size == sizeof(VM_COUNTERS_EX32)) info32->PrivateUsage = info->PrivateUsage;
270 /**********************************************************************
271 * wow64_NtAlertResumeThread
273 NTSTATUS WINAPI wow64_NtAlertResumeThread( UINT *args )
275 HANDLE handle = get_handle( &args );
276 ULONG *count = get_ptr( &args );
278 return NtAlertResumeThread( handle, count );
282 /**********************************************************************
283 * wow64_NtAlertThread
285 NTSTATUS WINAPI wow64_NtAlertThread( UINT *args )
287 HANDLE handle = get_handle( &args );
289 return NtAlertThread( handle );
293 /**********************************************************************
294 * wow64_NtAlertThreadByThreadId
296 NTSTATUS WINAPI wow64_NtAlertThreadByThreadId( UINT *args )
298 HANDLE tid = get_handle( &args );
300 return NtAlertThreadByThreadId( tid );
304 /**********************************************************************
305 * wow64_NtAssignProcessToJobObject
307 NTSTATUS WINAPI wow64_NtAssignProcessToJobObject( UINT *args )
309 HANDLE job = get_handle( &args );
310 HANDLE process = get_handle( &args );
312 return NtAssignProcessToJobObject( job, process );
316 /**********************************************************************
317 * wow64_NtCreateThread
319 NTSTATUS WINAPI wow64_NtCreateThread( UINT *args )
321 ULONG *handle_ptr = get_ptr( &args );
322 ACCESS_MASK access = get_ulong( &args );
323 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
324 HANDLE process = get_handle( &args );
325 CLIENT_ID32 *id32 = get_ptr( &args );
326 I386_CONTEXT *context = get_ptr( &args );
327 void *initial_teb = get_ptr( &args );
328 BOOLEAN suspended = get_ulong( &args );
330 FIXME( "%p %lx %p %p %p %p %p %u: stub\n", handle_ptr, access, attr32, process,
331 id32, context, initial_teb, suspended );
332 return STATUS_NOT_IMPLEMENTED;
336 /**********************************************************************
337 * wow64_NtCreateThreadEx
339 NTSTATUS WINAPI wow64_NtCreateThreadEx( UINT *args )
341 ULONG *handle_ptr = get_ptr( &args );
342 ACCESS_MASK access = get_ulong( &args );
343 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
344 HANDLE process = get_handle( &args );
345 PRTL_THREAD_START_ROUTINE start = get_ptr( &args );
346 void *param = get_ptr( &args );
347 ULONG flags = get_ulong( &args );
348 ULONG_PTR zero_bits = get_ulong( &args );
349 SIZE_T stack_commit = get_ulong( &args );
350 SIZE_T stack_reserve = get_ulong( &args );
351 PS_ATTRIBUTE_LIST32 *attr_list32 = get_ptr( &args );
353 struct object_attr64 attr;
354 PS_ATTRIBUTE_LIST *attr_list;
355 HANDLE handle = 0;
356 NTSTATUS status;
358 *handle_ptr = 0;
359 if (is_process_wow64( process ))
361 status = NtCreateThreadEx( &handle, access, objattr_32to64( &attr, attr32 ), process,
362 start, param, flags, get_zero_bits( zero_bits ),
363 stack_commit, stack_reserve,
364 ps_attributes_32to64( &attr_list, attr_list32 ));
365 put_ps_attributes( attr_list32, attr_list );
367 else status = STATUS_ACCESS_DENIED;
369 put_handle( handle_ptr, handle );
370 return status;
374 /**********************************************************************
375 * wow64_NtCreateUserProcess
377 NTSTATUS WINAPI wow64_NtCreateUserProcess( UINT *args )
379 ULONG *process_handle_ptr = get_ptr( &args );
380 ULONG *thread_handle_ptr = get_ptr( &args );
381 ACCESS_MASK process_access = get_ulong( &args );
382 ACCESS_MASK thread_access = get_ulong( &args );
383 OBJECT_ATTRIBUTES32 *process_attr32 = get_ptr( &args );
384 OBJECT_ATTRIBUTES32 *thread_attr32 = get_ptr( &args );
385 ULONG process_flags = get_ulong( &args );
386 ULONG thread_flags = get_ulong( &args );
387 RTL_USER_PROCESS_PARAMETERS32 *params32 = get_ptr( &args );
388 PS_CREATE_INFO32 *info32 = get_ptr( &args );
389 PS_ATTRIBUTE_LIST32 *attr32 = get_ptr( &args );
391 struct object_attr64 process_attr, thread_attr;
392 RTL_USER_PROCESS_PARAMETERS *params;
393 PS_CREATE_INFO info;
394 PS_ATTRIBUTE_LIST *attr;
395 HANDLE process_handle = 0, thread_handle = 0;
397 NTSTATUS status;
399 *process_handle_ptr = *thread_handle_ptr = 0;
400 status = NtCreateUserProcess( &process_handle, &thread_handle, process_access, thread_access,
401 objattr_32to64( &process_attr, process_attr32 ),
402 objattr_32to64( &thread_attr, thread_attr32 ),
403 process_flags, thread_flags,
404 process_params_32to64( &params, params32),
405 &info, ps_attributes_32to64( &attr, attr32 ));
406 put_handle( process_handle_ptr, process_handle );
407 put_handle( thread_handle_ptr, thread_handle );
408 put_ps_create_info( info32, &info );
409 put_ps_attributes( attr32, attr );
410 RtlDestroyProcessParameters( params );
411 return status;
415 /**********************************************************************
416 * wow64_NtDebugActiveProcess
418 NTSTATUS WINAPI wow64_NtDebugActiveProcess( UINT *args )
420 HANDLE process = get_handle( &args );
421 HANDLE debug = get_handle( &args );
423 return NtDebugActiveProcess( process, debug );
427 /**********************************************************************
428 * wow64_NtFlushInstructionCache
430 NTSTATUS WINAPI wow64_NtFlushInstructionCache( UINT *args )
432 HANDLE process = get_handle( &args );
433 const void *addr = get_ptr( &args );
434 SIZE_T size = get_ulong( &args );
436 return NtFlushInstructionCache( process, addr, size );
440 /**********************************************************************
441 * wow64_NtFlushProcessWriteBuffers
443 NTSTATUS WINAPI wow64_NtFlushProcessWriteBuffers( UINT *args )
445 NtFlushProcessWriteBuffers();
446 return STATUS_SUCCESS;
450 /**********************************************************************
451 * wow64_NtGetNextThread
453 NTSTATUS WINAPI wow64_NtGetNextThread( UINT *args )
455 HANDLE process = get_handle( &args );
456 HANDLE thread = get_handle( &args );
457 ACCESS_MASK access = get_ulong( &args );
458 ULONG attributes = get_ulong( &args );
459 ULONG flags = get_ulong( &args );
460 ULONG *handle_ptr = get_ptr( &args );
462 HANDLE handle = 0;
463 NTSTATUS status;
465 *handle_ptr = 0;
466 status = NtGetNextThread( process, thread, access, attributes, flags, &handle );
467 put_handle( handle_ptr, handle );
468 return status;
472 /**********************************************************************
473 * wow64_NtIsProcessInJob
475 NTSTATUS WINAPI wow64_NtIsProcessInJob( UINT *args )
477 HANDLE process = get_handle( &args );
478 HANDLE job = get_handle( &args );
480 return NtIsProcessInJob( process, job );
484 /**********************************************************************
485 * wow64_NtOpenProcess
487 NTSTATUS WINAPI wow64_NtOpenProcess( UINT *args )
489 ULONG *handle_ptr = get_ptr( &args );
490 ACCESS_MASK access = get_ulong( &args );
491 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
492 CLIENT_ID32 *id32 = get_ptr( &args );
494 struct object_attr64 attr;
495 HANDLE handle = 0;
496 CLIENT_ID id;
497 NTSTATUS status;
499 *handle_ptr = 0;
500 status = NtOpenProcess( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
501 put_handle( handle_ptr, handle );
502 return status;
506 /**********************************************************************
507 * wow64_NtOpenThread
509 NTSTATUS WINAPI wow64_NtOpenThread( UINT *args )
511 ULONG *handle_ptr = get_ptr( &args );
512 ACCESS_MASK access = get_ulong( &args );
513 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
514 CLIENT_ID32 *id32 = get_ptr( &args );
516 struct object_attr64 attr;
517 HANDLE handle = 0;
518 CLIENT_ID id;
519 NTSTATUS status;
521 *handle_ptr = 0;
522 status = NtOpenThread( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
523 put_handle( handle_ptr, handle );
524 return status;
528 /**********************************************************************
529 * wow64_NtQueryInformationProcess
531 NTSTATUS WINAPI wow64_NtQueryInformationProcess( UINT *args )
533 HANDLE handle = get_handle( &args );
534 PROCESSINFOCLASS class = get_ulong( &args );
535 void *ptr = get_ptr( &args );
536 ULONG len = get_ulong( &args );
537 ULONG *retlen = get_ptr( &args );
539 NTSTATUS status;
541 switch (class)
543 case ProcessBasicInformation: /* PROCESS_BASIC_INFORMATION */
544 if (len == sizeof(PROCESS_BASIC_INFORMATION32))
546 PROCESS_BASIC_INFORMATION info;
547 PROCESS_BASIC_INFORMATION32 *info32 = ptr;
549 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
551 if (is_process_wow64( handle ))
552 info32->PebBaseAddress = PtrToUlong( info.PebBaseAddress ) + 0x1000;
553 else
554 info32->PebBaseAddress = 0;
555 info32->ExitStatus = info.ExitStatus;
556 info32->AffinityMask = info.AffinityMask;
557 info32->BasePriority = info.BasePriority;
558 info32->UniqueProcessId = info.UniqueProcessId;
559 info32->InheritedFromUniqueProcessId = info.InheritedFromUniqueProcessId;
560 if (retlen) *retlen = sizeof(*info32);
562 return status;
564 if (retlen) *retlen = sizeof(PROCESS_BASIC_INFORMATION32);
565 return STATUS_INFO_LENGTH_MISMATCH;
567 case ProcessIoCounters: /* IO_COUNTERS */
568 case ProcessTimes: /* KERNEL_USER_TIMES */
569 case ProcessDefaultHardErrorMode: /* ULONG */
570 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
571 case ProcessHandleCount: /* ULONG */
572 case ProcessSessionInformation: /* ULONG */
573 case ProcessDebugFlags: /* ULONG */
574 case ProcessExecuteFlags: /* ULONG */
575 case ProcessCookie: /* ULONG */
576 case ProcessCycleTime: /* PROCESS_CYCLE_TIME_INFORMATION */
577 /* FIXME: check buffer alignment */
578 return NtQueryInformationProcess( handle, class, ptr, len, retlen );
580 case ProcessVmCounters: /* VM_COUNTERS_EX */
581 if (len == sizeof(VM_COUNTERS32) || len == sizeof(VM_COUNTERS_EX32))
583 VM_COUNTERS_EX info;
584 VM_COUNTERS_EX32 *info32 = ptr;
586 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
588 put_vm_counters( info32, &info, len );
589 if (retlen) *retlen = len;
591 return status;
593 if (retlen) *retlen = sizeof(VM_COUNTERS_EX32);
594 return STATUS_INFO_LENGTH_MISMATCH;
596 case ProcessDebugPort: /* ULONG_PTR */
597 case ProcessAffinityMask: /* ULONG_PTR */
598 case ProcessWow64Information: /* ULONG_PTR */
599 case ProcessDebugObjectHandle: /* HANDLE */
600 if (len == sizeof(ULONG))
602 ULONG_PTR data;
604 if (!(status = NtQueryInformationProcess( handle, class, &data, sizeof(data), NULL )))
606 *(ULONG *)ptr = data;
607 if (retlen) *retlen = sizeof(ULONG);
609 else if (status == STATUS_PORT_NOT_SET) *(ULONG *)ptr = 0;
610 return status;
612 if (retlen) *retlen = sizeof(ULONG);
613 return STATUS_INFO_LENGTH_MISMATCH;
615 case ProcessImageFileName:
616 case ProcessImageFileNameWin32: /* UNICODE_STRING + string */
618 ULONG retsize, size = len + sizeof(UNICODE_STRING) - sizeof(UNICODE_STRING32);
619 UNICODE_STRING *str = Wow64AllocateTemp( size );
620 UNICODE_STRING32 *str32 = ptr;
622 if (!(status = NtQueryInformationProcess( handle, class, str, size, &retsize )))
624 str32->Length = str->Length;
625 str32->MaximumLength = str->MaximumLength;
626 str32->Buffer = PtrToUlong( str32 + 1 );
627 memcpy( str32 + 1, str->Buffer, str->MaximumLength );
629 if (retlen) *retlen = retsize + sizeof(UNICODE_STRING32) - sizeof(UNICODE_STRING);
630 return status;
633 case ProcessImageInformation: /* SECTION_IMAGE_INFORMATION */
634 if (len == sizeof(SECTION_IMAGE_INFORMATION32))
636 SECTION_IMAGE_INFORMATION info;
637 SECTION_IMAGE_INFORMATION32 *info32 = ptr;
639 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
641 put_section_image_info( info32, &info );
642 if (retlen) *retlen = sizeof(*info32);
644 return status;
646 if (retlen) *retlen = sizeof(SECTION_IMAGE_INFORMATION32);
647 return STATUS_INFO_LENGTH_MISMATCH;
649 case ProcessWineLdtCopy:
650 return STATUS_NOT_IMPLEMENTED;
652 default:
653 FIXME( "unsupported class %u\n", class );
654 return STATUS_INVALID_INFO_CLASS;
659 /**********************************************************************
660 * wow64_NtQueryInformationThread
662 NTSTATUS WINAPI wow64_NtQueryInformationThread( UINT *args )
664 HANDLE handle = get_handle( &args );
665 THREADINFOCLASS class = get_ulong( &args );
666 void *ptr = get_ptr( &args );
667 ULONG len = get_ulong( &args );
668 ULONG *retlen = get_ptr( &args );
670 NTSTATUS status;
672 switch (class)
674 case ThreadBasicInformation: /* THREAD_BASIC_INFORMATION */
676 THREAD_BASIC_INFORMATION32 info32;
677 THREAD_BASIC_INFORMATION info;
679 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
680 if (!status)
682 info32.ExitStatus = info.ExitStatus;
683 info32.TebBaseAddress = is_process_id_wow64( &info.ClientId ) ?
684 PtrToUlong(info.TebBaseAddress) + 0x2000 : 0;
685 info32.ClientId.UniqueProcess = HandleToULong( info.ClientId.UniqueProcess );
686 info32.ClientId.UniqueThread = HandleToULong( info.ClientId.UniqueThread );
687 info32.AffinityMask = info.AffinityMask;
688 info32.Priority = info.Priority;
689 info32.BasePriority = info.BasePriority;
690 memcpy( ptr, &info32, min( len, sizeof(info32) ));
691 if (retlen) *retlen = min( len, sizeof(info32) );
693 return status;
696 case ThreadTimes: /* KERNEL_USER_TIMES */
697 case ThreadEnableAlignmentFaultFixup: /* set only */
698 case ThreadAmILastThread: /* ULONG */
699 case ThreadIsIoPending: /* ULONG */
700 case ThreadHideFromDebugger: /* BOOLEAN */
701 case ThreadSuspendCount: /* ULONG */
702 case ThreadPriorityBoost: /* ULONG */
703 /* FIXME: check buffer alignment */
704 return NtQueryInformationThread( handle, class, ptr, len, retlen );
706 case ThreadAffinityMask: /* ULONG_PTR */
707 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
709 ULONG_PTR data;
711 status = NtQueryInformationThread( handle, class, &data, sizeof(data), NULL );
712 if (!status)
714 memcpy( ptr, &data, min( len, sizeof(ULONG) ));
715 if (retlen) *retlen = min( len, sizeof(ULONG) );
717 return status;
720 case ThreadDescriptorTableEntry: /* THREAD_DESCRIPTOR_INFORMATION */
721 return RtlWow64GetThreadSelectorEntry( handle, ptr, len, retlen );
723 case ThreadWow64Context: /* WOW64_CONTEXT* */
724 return STATUS_INVALID_INFO_CLASS;
726 case ThreadGroupInformation: /* GROUP_AFFINITY */
728 GROUP_AFFINITY info;
730 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
731 if (!status)
733 GROUP_AFFINITY32 info32 = { info.Mask, info.Group };
734 memcpy( ptr, &info32, min( len, sizeof(info32) ));
735 if (retlen) *retlen = min( len, sizeof(info32) );
737 return status;
740 case ThreadNameInformation: /* THREAD_NAME_INFORMATION */
742 THREAD_NAME_INFORMATION *info;
743 THREAD_NAME_INFORMATION32 *info32 = ptr;
744 ULONG size, ret_size;
746 if (len >= sizeof(*info32))
748 size = sizeof(*info) + len - sizeof(*info32);
749 info = Wow64AllocateTemp( size );
750 status = NtQueryInformationThread( handle, class, info, size, &ret_size );
751 if (!status)
753 info32->ThreadName.Length = info->ThreadName.Length;
754 info32->ThreadName.MaximumLength = info->ThreadName.MaximumLength;
755 info32->ThreadName.Buffer = PtrToUlong( info32 + 1 );
756 memcpy( info32 + 1, info + 1, min( len, info->ThreadName.MaximumLength ));
759 else status = NtQueryInformationThread( handle, class, NULL, 0, &ret_size );
761 if (retlen && (status == STATUS_SUCCESS || status == STATUS_BUFFER_TOO_SMALL))
762 *retlen = sizeof(*info32) + ret_size - sizeof(*info);
763 return status;
766 default:
767 FIXME( "unsupported class %u\n", class );
768 return STATUS_INVALID_INFO_CLASS;
773 /**********************************************************************
774 * wow64_NtQueueApcThread
776 NTSTATUS WINAPI wow64_NtQueueApcThread( UINT *args )
778 HANDLE handle = get_handle( &args );
779 ULONG func = get_ulong( &args );
780 ULONG arg1 = get_ulong( &args );
781 ULONG arg2 = get_ulong( &args );
782 ULONG arg3 = get_ulong( &args );
784 return NtQueueApcThread( handle, apc_32to64( func ),
785 (ULONG_PTR)apc_param_32to64( func, arg1 ), arg2, arg3 );
789 /**********************************************************************
790 * wow64_NtRemoveProcessDebug
792 NTSTATUS WINAPI wow64_NtRemoveProcessDebug( UINT *args )
794 HANDLE process = get_handle( &args );
795 HANDLE debug = get_handle( &args );
797 return NtRemoveProcessDebug( process, debug );
801 /**********************************************************************
802 * wow64_NtResumeProcess
804 NTSTATUS WINAPI wow64_NtResumeProcess( UINT *args )
806 HANDLE handle = get_handle( &args );
808 return NtResumeProcess( handle );
812 /**********************************************************************
813 * wow64_NtResumeThread
815 NTSTATUS WINAPI wow64_NtResumeThread( UINT *args )
817 HANDLE handle = get_handle( &args );
818 ULONG *count = get_ptr( &args );
820 return NtResumeThread( handle, count );
824 /**********************************************************************
825 * wow64_NtSetInformationProcess
827 NTSTATUS WINAPI wow64_NtSetInformationProcess( UINT *args )
829 HANDLE handle = get_handle( &args );
830 PROCESSINFOCLASS class = get_ulong( &args );
831 void *ptr = get_ptr( &args );
832 ULONG len = get_ulong( &args );
834 NTSTATUS status;
836 switch (class)
838 case ProcessDefaultHardErrorMode: /* ULONG */
839 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
840 case ProcessExecuteFlags: /* ULONG */
841 case ProcessPagePriority: /* MEMORY_PRIORITY_INFORMATION */
842 case ProcessPowerThrottlingState: /* PROCESS_POWER_THROTTLING_STATE */
843 case ProcessLeapSecondInformation: /* PROCESS_LEAP_SECOND_INFO */
844 return NtSetInformationProcess( handle, class, ptr, len );
846 case ProcessAffinityMask: /* ULONG_PTR */
847 if (len == sizeof(ULONG))
849 ULONG_PTR mask = *(ULONG *)ptr;
850 return NtSetInformationProcess( handle, class, &mask, sizeof(mask) );
852 else return STATUS_INVALID_PARAMETER;
854 case ProcessInstrumentationCallback: /* PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION */
855 if (len == sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION32))
857 FIXME( "ProcessInstrumentationCallback stub\n" );
858 return STATUS_SUCCESS;
860 else return STATUS_INFO_LENGTH_MISMATCH;
862 case ProcessThreadStackAllocation: /* PROCESS_STACK_ALLOCATION_INFORMATION(_EX) */
863 if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX32))
865 PROCESS_STACK_ALLOCATION_INFORMATION_EX32 *stack = ptr;
866 PROCESS_STACK_ALLOCATION_INFORMATION_EX info;
868 info.PreferredNode = stack->PreferredNode;
869 info.Reserved0 = stack->Reserved0;
870 info.Reserved1 = stack->Reserved1;
871 info.Reserved2 = stack->Reserved2;
872 info.AllocInfo.ReserveSize = stack->AllocInfo.ReserveSize;
873 info.AllocInfo.ZeroBits = get_zero_bits( stack->AllocInfo.ZeroBits );
874 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
875 stack->AllocInfo.StackBase = PtrToUlong( info.AllocInfo.StackBase );
876 return status;
878 else if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION32))
880 PROCESS_STACK_ALLOCATION_INFORMATION32 *stack = ptr;
881 PROCESS_STACK_ALLOCATION_INFORMATION info;
883 info.ReserveSize = stack->ReserveSize;
884 info.ZeroBits = get_zero_bits( stack->ZeroBits );
885 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
886 stack->StackBase = PtrToUlong( info.StackBase );
887 return status;
889 else return STATUS_INFO_LENGTH_MISMATCH;
891 case ProcessWineMakeProcessSystem: /* HANDLE* */
892 if (len == sizeof(ULONG))
894 HANDLE event = 0;
895 status = NtSetInformationProcess( handle, class, &event, sizeof(HANDLE *) );
896 put_handle( ptr, event );
897 return status;
899 else return STATUS_INFO_LENGTH_MISMATCH;
901 default:
902 FIXME( "unsupported class %u\n", class );
903 return STATUS_INVALID_INFO_CLASS;
908 /**********************************************************************
909 * wow64_NtSetInformationThread
911 NTSTATUS WINAPI wow64_NtSetInformationThread( UINT *args )
913 HANDLE handle = get_handle( &args );
914 THREADINFOCLASS class = get_ulong( &args );
915 void *ptr = get_ptr( &args );
916 ULONG len = get_ulong( &args );
918 switch (class)
920 case ThreadZeroTlsCell: /* ULONG */
921 case ThreadBasePriority: /* ULONG */
922 case ThreadHideFromDebugger: /* void */
923 case ThreadEnableAlignmentFaultFixup: /* BOOLEAN */
924 case ThreadPowerThrottlingState: /* THREAD_POWER_THROTTLING_STATE */
925 case ThreadIdealProcessor: /* ULONG */
926 case ThreadPriorityBoost: /* ULONG */
927 return NtSetInformationThread( handle, class, ptr, len );
929 case ThreadImpersonationToken: /* HANDLE */
930 if (len == sizeof(ULONG))
932 HANDLE token = LongToHandle( *(ULONG *)ptr );
933 return NtSetInformationThread( handle, class, &token, sizeof(token) );
935 else return STATUS_INVALID_PARAMETER;
937 case ThreadAffinityMask: /* ULONG_PTR */
938 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
939 if (len == sizeof(ULONG))
941 ULONG_PTR mask = *(ULONG *)ptr;
942 return NtSetInformationThread( handle, class, &mask, sizeof(mask) );
944 else return STATUS_INVALID_PARAMETER;
946 case ThreadWow64Context: /* WOW64_CONTEXT* */
947 return STATUS_INVALID_INFO_CLASS;
949 case ThreadGroupInformation: /* GROUP_AFFINITY */
950 if (len == sizeof(GROUP_AFFINITY32))
952 GROUP_AFFINITY32 *info32 = ptr;
953 GROUP_AFFINITY info = { info32->Mask, info32->Group };
955 return NtSetInformationThread( handle, class, &info, sizeof(info) );
957 else return STATUS_INVALID_PARAMETER;
959 case ThreadNameInformation: /* THREAD_NAME_INFORMATION */
960 if (len == sizeof(THREAD_NAME_INFORMATION32))
962 THREAD_NAME_INFORMATION32 *info32 = ptr;
963 THREAD_NAME_INFORMATION info;
965 if (!unicode_str_32to64( &info.ThreadName, &info32->ThreadName ))
966 return STATUS_ACCESS_VIOLATION;
967 return NtSetInformationThread( handle, class, &info, sizeof(info) );
969 else return STATUS_INFO_LENGTH_MISMATCH;
971 default:
972 FIXME( "unsupported class %u\n", class );
973 return STATUS_INVALID_INFO_CLASS;
978 /**********************************************************************
979 * wow64_NtSetThreadExecutionState
981 NTSTATUS WINAPI wow64_NtSetThreadExecutionState( UINT *args )
983 EXECUTION_STATE new_state = get_ulong( &args );
984 EXECUTION_STATE *old_state = get_ptr( &args );
986 return NtSetThreadExecutionState( new_state, old_state );
990 /**********************************************************************
991 * wow64_NtSuspendProcess
993 NTSTATUS WINAPI wow64_NtSuspendProcess( UINT *args )
995 HANDLE handle = get_handle( &args );
997 return NtSuspendProcess( handle );
1001 /**********************************************************************
1002 * wow64_NtSuspendThread
1004 NTSTATUS WINAPI wow64_NtSuspendThread( UINT *args )
1006 HANDLE handle = get_handle( &args );
1007 ULONG *count = get_ptr( &args );
1009 return NtSuspendThread( handle, count );
1013 /**********************************************************************
1014 * wow64_NtTerminateProcess
1016 NTSTATUS WINAPI wow64_NtTerminateProcess( UINT *args )
1018 HANDLE handle = get_handle( &args );
1019 LONG exit_code = get_ulong( &args );
1021 return NtTerminateProcess( handle, exit_code );
1025 /**********************************************************************
1026 * wow64_NtTerminateThread
1028 NTSTATUS WINAPI wow64_NtTerminateThread( UINT *args )
1030 HANDLE handle = get_handle( &args );
1031 LONG exit_code = get_ulong( &args );
1033 return NtTerminateThread( handle, exit_code );