ntdll: Validate blocks in the heap pending free request list.
[wine.git] / dlls / wow64 / process.c
blob97dbfdef7614f9db0285589dd04a41fac98a51ef
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 SIZE_T get_machine_context_size( USHORT machine )
39 switch (machine)
41 case IMAGE_FILE_MACHINE_I386: return sizeof(I386_CONTEXT);
42 case IMAGE_FILE_MACHINE_ARMNT: return sizeof(ARM_CONTEXT);
43 case IMAGE_FILE_MACHINE_AMD64: return sizeof(AMD64_CONTEXT);
44 case IMAGE_FILE_MACHINE_ARM64: return sizeof(ARM64_NT_CONTEXT);
45 default: return 0;
50 static BOOL is_process_wow64( HANDLE handle )
52 ULONG_PTR info;
54 if (handle == GetCurrentProcess()) return TRUE;
55 if (NtQueryInformationProcess( handle, ProcessWow64Information, &info, sizeof(info), NULL ))
56 return FALSE;
57 return !!info;
61 static BOOL is_process_id_wow64( const CLIENT_ID *id )
63 HANDLE handle;
64 BOOL ret = FALSE;
66 if (id->UniqueProcess == ULongToHandle(GetCurrentProcessId())) return TRUE;
67 if (!NtOpenProcess( &handle, PROCESS_QUERY_LIMITED_INFORMATION, NULL, id ))
69 ret = is_process_wow64( handle );
70 NtClose( handle );
72 return ret;
76 static EXCEPTION_RECORD *exception_record_32to64( const EXCEPTION_RECORD32 *rec32 )
78 EXCEPTION_RECORD *rec;
79 unsigned int i;
81 rec = Wow64AllocateTemp( sizeof(*rec) );
82 rec->ExceptionCode = rec32->ExceptionCode;
83 rec->ExceptionFlags = rec32->ExceptionFlags;
84 rec->ExceptionRecord = rec32->ExceptionRecord ? exception_record_32to64( ULongToPtr(rec32->ExceptionRecord) ) : NULL;
85 rec->ExceptionAddress = ULongToPtr( rec32->ExceptionAddress );
86 rec->NumberParameters = rec32->NumberParameters;
87 for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
88 rec->ExceptionInformation[i] = rec32->ExceptionInformation[i];
89 return rec;
93 static RTL_USER_PROCESS_PARAMETERS *process_params_32to64( RTL_USER_PROCESS_PARAMETERS **params,
94 RTL_USER_PROCESS_PARAMETERS32 *params32 )
96 UNICODE_STRING image, dllpath, curdir, cmdline, title, desktop, shell, runtime;
97 RTL_USER_PROCESS_PARAMETERS *ret;
99 *params = NULL;
100 if (RtlCreateProcessParametersEx( &ret, unicode_str_32to64( &image, &params32->ImagePathName ),
101 unicode_str_32to64( &dllpath, &params32->DllPath ),
102 unicode_str_32to64( &curdir, &params32->CurrentDirectory.DosPath ),
103 unicode_str_32to64( &cmdline, &params32->CommandLine ),
104 ULongToPtr( params32->Environment ),
105 unicode_str_32to64( &title, &params32->WindowTitle ),
106 unicode_str_32to64( &desktop, &params32->Desktop ),
107 unicode_str_32to64( &shell, &params32->ShellInfo ),
108 unicode_str_32to64( &runtime, &params32->RuntimeInfo ),
109 PROCESS_PARAMS_FLAG_NORMALIZED ))
110 return NULL;
112 ret->DebugFlags = params32->DebugFlags;
113 ret->ConsoleHandle = LongToHandle( params32->ConsoleHandle );
114 ret->ConsoleFlags = params32->ConsoleFlags;
115 ret->hStdInput = LongToHandle( params32->hStdInput );
116 ret->hStdOutput = LongToHandle( params32->hStdOutput );
117 ret->hStdError = LongToHandle( params32->hStdError );
118 ret->dwX = params32->dwX;
119 ret->dwY = params32->dwY;
120 ret->dwXSize = params32->dwXSize;
121 ret->dwYSize = params32->dwYSize;
122 ret->dwXCountChars = params32->dwXCountChars;
123 ret->dwYCountChars = params32->dwYCountChars;
124 ret->dwFillAttribute = params32->dwFillAttribute;
125 ret->dwFlags = params32->dwFlags;
126 ret->wShowWindow = params32->wShowWindow;
127 ret->EnvironmentVersion = params32->EnvironmentVersion;
128 ret->PackageDependencyData = ULongToPtr( params32->PackageDependencyData );
129 ret->ProcessGroupId = params32->ProcessGroupId;
130 ret->LoaderThreads = params32->LoaderThreads;
131 *params = ret;
132 return ret;
136 static void put_ps_create_info( PS_CREATE_INFO32 *info32, const PS_CREATE_INFO *info )
138 info32->State = info->State;
139 switch (info->State)
141 case PsCreateInitialState:
142 info32->InitState.InitFlags = info->InitState.InitFlags;
143 info32->InitState.AdditionalFileAccess = info->InitState.AdditionalFileAccess;
144 break;
145 case PsCreateFailOnSectionCreate:
146 info32->FailSection.FileHandle = HandleToLong( info->FailSection.FileHandle );
147 break;
148 case PsCreateFailExeFormat:
149 info32->ExeFormat.DllCharacteristics = info->ExeFormat.DllCharacteristics;
150 break;
151 case PsCreateFailExeName:
152 info32->ExeName.IFEOKey = HandleToLong( info->ExeName.IFEOKey );
153 break;
154 case PsCreateSuccess:
155 info32->SuccessState.OutputFlags = info->SuccessState.OutputFlags;
156 info32->SuccessState.FileHandle = HandleToLong( info->SuccessState.FileHandle );
157 info32->SuccessState.SectionHandle = HandleToLong( info->SuccessState.SectionHandle );
158 info32->SuccessState.UserProcessParametersNative = info->SuccessState.UserProcessParametersNative;
159 info32->SuccessState.UserProcessParametersWow64 = info->SuccessState.UserProcessParametersWow64;
160 info32->SuccessState.CurrentParameterFlags = info->SuccessState.CurrentParameterFlags;
161 info32->SuccessState.PebAddressNative = info->SuccessState.PebAddressNative;
162 info32->SuccessState.PebAddressWow64 = info->SuccessState.PebAddressWow64;
163 info32->SuccessState.ManifestAddress = info->SuccessState.ManifestAddress;
164 info32->SuccessState.ManifestSize = info->SuccessState.ManifestSize;
165 break;
166 default:
167 break;
172 static PS_ATTRIBUTE_LIST *ps_attributes_32to64( PS_ATTRIBUTE_LIST **attr, const PS_ATTRIBUTE_LIST32 *attr32 )
174 PS_ATTRIBUTE_LIST *ret;
175 ULONG i, count;
177 if (!attr32) return NULL;
178 count = (attr32->TotalLength - sizeof(attr32->TotalLength)) / sizeof(PS_ATTRIBUTE32);
179 ret = Wow64AllocateTemp( offsetof(PS_ATTRIBUTE_LIST, Attributes[count]) );
180 ret->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[count] );
181 for (i = 0; i < count; i++)
183 ret->Attributes[i].Attribute = attr32->Attributes[i].Attribute;
184 ret->Attributes[i].Size = attr32->Attributes[i].Size;
185 ret->Attributes[i].Value = attr32->Attributes[i].Value;
186 ret->Attributes[i].ReturnLength = NULL;
187 switch (ret->Attributes[i].Attribute)
189 case PS_ATTRIBUTE_IMAGE_NAME:
191 OBJECT_ATTRIBUTES attr;
192 UNICODE_STRING path;
194 path.Length = ret->Attributes[i].Size;
195 path.Buffer = ret->Attributes[i].ValuePtr;
196 InitializeObjectAttributes( &attr, &path, OBJ_CASE_INSENSITIVE, 0, 0 );
197 if (get_file_redirect( &attr ))
199 ret->Attributes[i].Size = attr.ObjectName->Length;
200 ret->Attributes[i].ValuePtr = attr.ObjectName->Buffer;
203 break;
204 case PS_ATTRIBUTE_HANDLE_LIST:
205 case PS_ATTRIBUTE_JOB_LIST:
207 ULONG j, handles_count = attr32->Attributes[i].Size / sizeof(ULONG);
209 ret->Attributes[i].Size = handles_count * sizeof(HANDLE);
210 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
211 for (j = 0; j < handles_count; j++)
212 ((HANDLE *)ret->Attributes[i].ValuePtr)[j] =
213 LongToHandle( ((LONG *)ULongToPtr(attr32->Attributes[i].Value))[j] );
215 break;
216 case PS_ATTRIBUTE_PARENT_PROCESS:
217 ret->Attributes[i].Size = sizeof(HANDLE);
218 ret->Attributes[i].ValuePtr = LongToHandle( attr32->Attributes[i].Value );
219 break;
220 case PS_ATTRIBUTE_CLIENT_ID:
221 ret->Attributes[i].Size = sizeof(CLIENT_ID);
222 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
223 break;
224 case PS_ATTRIBUTE_IMAGE_INFO:
225 ret->Attributes[i].Size = sizeof(SECTION_IMAGE_INFORMATION);
226 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
227 break;
228 case PS_ATTRIBUTE_TEB_ADDRESS:
229 ret->Attributes[i].Size = sizeof(TEB *);
230 ret->Attributes[i].ValuePtr = Wow64AllocateTemp( ret->Attributes[i].Size );
231 break;
234 *attr = ret;
235 return ret;
239 static void put_ps_attributes( PS_ATTRIBUTE_LIST32 *attr32, const PS_ATTRIBUTE_LIST *attr )
241 ULONG i;
243 if (!attr32) return;
244 for (i = 0; i < (attr32->TotalLength - sizeof(attr32->TotalLength)) / sizeof(PS_ATTRIBUTE32); i++)
246 switch (attr->Attributes[i].Attribute)
248 case PS_ATTRIBUTE_CLIENT_ID:
250 CLIENT_ID32 id32;
251 ULONG size = min( attr32->Attributes[i].Size, sizeof(id32) );
252 put_client_id( &id32, attr->Attributes[i].ValuePtr );
253 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &id32, size );
254 if (attr32->Attributes[i].ReturnLength)
255 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
256 break;
258 case PS_ATTRIBUTE_IMAGE_INFO:
260 SECTION_IMAGE_INFORMATION32 info32;
261 ULONG size = min( attr32->Attributes[i].Size, sizeof(info32) );
262 put_section_image_info( &info32, attr->Attributes[i].ValuePtr );
263 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &info32, size );
264 if (attr32->Attributes[i].ReturnLength)
265 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
266 break;
268 case PS_ATTRIBUTE_TEB_ADDRESS:
270 TEB **teb = attr->Attributes[i].ValuePtr;
271 ULONG teb32 = PtrToUlong( *teb ) + 0x2000;
272 ULONG size = min( attr->Attributes[i].Size, sizeof(teb32) );
273 memcpy( ULongToPtr( attr32->Attributes[i].Value ), &teb32, size );
274 if (attr32->Attributes[i].ReturnLength)
275 *(ULONG *)ULongToPtr(attr32->Attributes[i].ReturnLength) = size;
276 break;
283 void put_vm_counters( VM_COUNTERS_EX32 *info32, const VM_COUNTERS_EX *info, ULONG size )
285 info32->PeakVirtualSize = info->PeakVirtualSize;
286 info32->VirtualSize = info->VirtualSize;
287 info32->PageFaultCount = info->PageFaultCount;
288 info32->PeakWorkingSetSize = info->PeakWorkingSetSize;
289 info32->WorkingSetSize = info->WorkingSetSize;
290 info32->QuotaPeakPagedPoolUsage = info->QuotaPeakPagedPoolUsage;
291 info32->QuotaPagedPoolUsage = info->QuotaPagedPoolUsage;
292 info32->QuotaPeakNonPagedPoolUsage = info->QuotaPeakNonPagedPoolUsage;
293 info32->QuotaNonPagedPoolUsage = info->QuotaNonPagedPoolUsage;
294 info32->PagefileUsage = info->PagefileUsage;
295 info32->PeakPagefileUsage = info->PeakPagefileUsage;
296 if (size == sizeof(VM_COUNTERS_EX32)) info32->PrivateUsage = info->PrivateUsage;
300 static void call_user_exception_dispatcher( EXCEPTION_RECORD32 *rec, void *ctx32_ptr, void *ctx64_ptr )
302 switch (current_machine)
304 case IMAGE_FILE_MACHINE_I386:
306 struct stack_layout
308 ULONG rec_ptr; /* first arg for KiUserExceptionDispatcher */
309 ULONG context_ptr; /* second arg for KiUserExceptionDispatcher */
310 EXCEPTION_RECORD32 rec;
311 I386_CONTEXT context;
312 } *stack;
313 I386_CONTEXT *context, ctx = { CONTEXT_I386_ALL };
314 CONTEXT_EX *context_ex, *src_ex = NULL;
315 ULONG size, flags;
317 NtQueryInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx), NULL );
319 if (ctx32_ptr)
321 I386_CONTEXT *ctx32 = ctx32_ptr;
323 if ((ctx32->ContextFlags & CONTEXT_I386_XSTATE) == CONTEXT_I386_XSTATE)
324 src_ex = (CONTEXT_EX *)(ctx32 + 1);
326 else if (native_machine == IMAGE_FILE_MACHINE_AMD64)
328 AMD64_CONTEXT *ctx64 = ctx64_ptr;
330 if ((ctx64->ContextFlags & CONTEXT_AMD64_FLOATING_POINT) == CONTEXT_AMD64_FLOATING_POINT)
331 memcpy( ctx.ExtendedRegisters, &ctx64->FltSave, sizeof(ctx.ExtendedRegisters) );
332 if ((ctx64->ContextFlags & CONTEXT_AMD64_XSTATE) == CONTEXT_AMD64_XSTATE)
333 src_ex = (CONTEXT_EX *)(ctx64 + 1);
336 flags = ctx.ContextFlags;
337 if (src_ex) flags |= CONTEXT_I386_XSTATE;
338 RtlGetExtendedContextLength( flags, &size );
339 size = ((size + 15) & ~15) + offsetof(struct stack_layout,context);
341 stack = (struct stack_layout *)(ULONG_PTR)(ctx.Esp - size);
342 stack->rec_ptr = PtrToUlong( &stack->rec );
343 stack->rec = *rec;
344 RtlInitializeExtendedContext( &stack->context, flags, &context_ex );
345 context = RtlLocateLegacyContext( context_ex, NULL );
346 *context = ctx;
347 context->ContextFlags = flags;
348 stack->context_ptr = PtrToUlong( context );
350 if (src_ex)
352 XSTATE *src_xs = (XSTATE *)((char *)src_ex + src_ex->XState.Offset);
353 XSTATE *dst_xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
355 dst_xs->Mask = src_xs->Mask & ~(ULONG64)3;
356 dst_xs->CompactionMask = src_xs->CompactionMask;
357 if ((dst_xs->Mask & 4) &&
358 src_ex->XState.Length >= sizeof(XSTATE) &&
359 context_ex->XState.Length >= sizeof(XSTATE))
360 memcpy( &dst_xs->YmmContext, &src_xs->YmmContext, sizeof(dst_xs->YmmContext) );
363 ctx.Esp = PtrToUlong( stack );
364 ctx.Eip = pLdrSystemDllInitBlock->pKiUserExceptionDispatcher;
365 ctx.EFlags &= ~(0x100|0x400|0x40000);
366 NtSetInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx) );
368 TRACE( "exception %08lx dispatcher %08lx stack %08lx eip %08lx\n",
369 rec->ExceptionCode, ctx.Eip, ctx.Esp, stack->context.Eip );
371 break;
373 case IMAGE_FILE_MACHINE_ARMNT:
375 struct stack_layout
377 ARM_CONTEXT context;
378 EXCEPTION_RECORD32 rec;
379 } *stack;
380 ARM_CONTEXT ctx = { CONTEXT_ARM_ALL };
382 NtQueryInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx), NULL );
383 stack = (struct stack_layout *)(ULONG_PTR)(ctx.Sp & ~3) - 1;
384 stack->rec = *rec;
385 stack->context = ctx;
387 ctx.R0 = PtrToUlong( &stack->rec ); /* first arg for KiUserExceptionDispatcher */
388 ctx.R1 = PtrToUlong( &stack->context ); /* second arg for KiUserExceptionDispatcher */
389 ctx.Sp = PtrToUlong( stack );
390 ctx.Pc = pLdrSystemDllInitBlock->pKiUserExceptionDispatcher;
391 if (ctx.Pc & 1) ctx.Cpsr |= 0x20;
392 else ctx.Cpsr &= ~0x20;
393 NtSetInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx) );
395 TRACE( "exception %08lx dispatcher %08lx stack %08lx pc %08lx\n",
396 rec->ExceptionCode, ctx.Pc, ctx.Sp, stack->context.Sp );
398 break;
403 /* based on RtlRaiseException: call NtRaiseException with context setup to return to caller */
404 void WINAPI raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) DECLSPEC_HIDDEN;
405 #ifdef __x86_64__
406 __ASM_GLOBAL_FUNC( raise_exception,
407 "sub $0x28,%rsp\n\t"
408 __ASM_SEH(".seh_stackalloc 0x28\n\t")
409 __ASM_SEH(".seh_endprologue\n\t")
410 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
411 "movq %rcx,(%rsp)\n\t"
412 "movq %rdx,%rcx\n\t"
413 "call " __ASM_NAME("RtlCaptureContext") "\n\t"
414 "leaq 0x30(%rsp),%rax\n\t" /* orig stack pointer */
415 "movq %rax,0x98(%rdx)\n\t" /* context->Rsp */
416 "movq (%rsp),%rcx\n\t" /* original first parameter */
417 "movq 0x28(%rsp),%rax\n\t" /* return address */
418 "movq %rax,0xf8(%rdx)\n\t" /* context->Rip */
419 "movq %rax,0x10(%rcx)\n\t" /* rec->ExceptionAddress */
420 "call " __ASM_NAME("NtRaiseException") )
421 #elif defined(__aarch64__)
422 __ASM_GLOBAL_FUNC( raise_exception,
423 "stp x29, x30, [sp, #-32]!\n\t"
424 __ASM_SEH(".seh_save_fplr_x 32\n\t")
425 __ASM_SEH(".seh_endprologue\n\t")
426 __ASM_CFI(".cfi_def_cfa x29, 32\n\t")
427 __ASM_CFI(".cfi_offset x30, -24\n\t")
428 __ASM_CFI(".cfi_offset x29, -32\n\t")
429 "mov x29, sp\n\t"
430 "stp x0, x1, [sp, #16]\n\t"
431 "mov x0, x1\n\t"
432 "bl " __ASM_NAME("RtlCaptureContext") "\n\t"
433 "ldp x0, x1, [sp, #16]\n\t" /* orig parameters */
434 "ldp x4, x5, [sp]\n\t" /* frame pointer, return address */
435 "stp x4, x5, [x1, #0xf0]\n\t" /* context->Fp, Lr */
436 "add x4, sp, #32\n\t" /* orig stack pointer */
437 "stp x4, x5, [x1, #0x100]\n\t" /* context->Sp, Pc */
438 "str x5, [x0, #0x10]\n\t" /* rec->ExceptionAddress */
439 "bl " __ASM_NAME("NtRaiseException") )
440 #endif
443 /**********************************************************************
444 * wow64_NtAlertResumeThread
446 NTSTATUS WINAPI wow64_NtAlertResumeThread( UINT *args )
448 HANDLE handle = get_handle( &args );
449 ULONG *count = get_ptr( &args );
451 return NtAlertResumeThread( handle, count );
455 /**********************************************************************
456 * wow64_NtAlertThread
458 NTSTATUS WINAPI wow64_NtAlertThread( UINT *args )
460 HANDLE handle = get_handle( &args );
462 return NtAlertThread( handle );
466 /**********************************************************************
467 * wow64_NtAlertThreadByThreadId
469 NTSTATUS WINAPI wow64_NtAlertThreadByThreadId( UINT *args )
471 HANDLE tid = get_handle( &args );
473 return NtAlertThreadByThreadId( tid );
477 /**********************************************************************
478 * wow64_NtAssignProcessToJobObject
480 NTSTATUS WINAPI wow64_NtAssignProcessToJobObject( UINT *args )
482 HANDLE job = get_handle( &args );
483 HANDLE process = get_handle( &args );
485 return NtAssignProcessToJobObject( job, process );
489 /**********************************************************************
490 * wow64_NtContinue
492 NTSTATUS WINAPI wow64_NtContinue( UINT *args )
494 void *context = get_ptr( &args );
495 BOOLEAN alertable = get_ulong( &args );
497 NtSetInformationThread( GetCurrentThread(), ThreadWow64Context,
498 context, get_machine_context_size( current_machine ));
499 if (alertable) NtTestAlert();
500 return STATUS_SUCCESS;
504 /**********************************************************************
505 * wow64_NtCreateThread
507 NTSTATUS WINAPI wow64_NtCreateThread( UINT *args )
509 ULONG *handle_ptr = get_ptr( &args );
510 ACCESS_MASK access = get_ulong( &args );
511 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
512 HANDLE process = get_handle( &args );
513 CLIENT_ID32 *id32 = get_ptr( &args );
514 I386_CONTEXT *context = get_ptr( &args );
515 void *initial_teb = get_ptr( &args );
516 BOOLEAN suspended = get_ulong( &args );
518 FIXME( "%p %lx %p %p %p %p %p %u: stub\n", handle_ptr, access, attr32, process,
519 id32, context, initial_teb, suspended );
520 return STATUS_NOT_IMPLEMENTED;
524 /**********************************************************************
525 * wow64_NtCreateThreadEx
527 NTSTATUS WINAPI wow64_NtCreateThreadEx( UINT *args )
529 ULONG *handle_ptr = get_ptr( &args );
530 ACCESS_MASK access = get_ulong( &args );
531 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
532 HANDLE process = get_handle( &args );
533 PRTL_THREAD_START_ROUTINE start = get_ptr( &args );
534 void *param = get_ptr( &args );
535 ULONG flags = get_ulong( &args );
536 ULONG_PTR zero_bits = get_ulong( &args );
537 SIZE_T stack_commit = get_ulong( &args );
538 SIZE_T stack_reserve = get_ulong( &args );
539 PS_ATTRIBUTE_LIST32 *attr_list32 = get_ptr( &args );
541 struct object_attr64 attr;
542 PS_ATTRIBUTE_LIST *attr_list;
543 HANDLE handle = 0;
544 NTSTATUS status;
546 *handle_ptr = 0;
547 if (is_process_wow64( process ))
549 status = NtCreateThreadEx( &handle, access, objattr_32to64( &attr, attr32 ), process,
550 start, param, flags, get_zero_bits( zero_bits ),
551 stack_commit, stack_reserve,
552 ps_attributes_32to64( &attr_list, attr_list32 ));
553 put_ps_attributes( attr_list32, attr_list );
555 else status = STATUS_ACCESS_DENIED;
557 put_handle( handle_ptr, handle );
558 return status;
562 /**********************************************************************
563 * wow64_NtCreateUserProcess
565 NTSTATUS WINAPI wow64_NtCreateUserProcess( UINT *args )
567 ULONG *process_handle_ptr = get_ptr( &args );
568 ULONG *thread_handle_ptr = get_ptr( &args );
569 ACCESS_MASK process_access = get_ulong( &args );
570 ACCESS_MASK thread_access = get_ulong( &args );
571 OBJECT_ATTRIBUTES32 *process_attr32 = get_ptr( &args );
572 OBJECT_ATTRIBUTES32 *thread_attr32 = get_ptr( &args );
573 ULONG process_flags = get_ulong( &args );
574 ULONG thread_flags = get_ulong( &args );
575 RTL_USER_PROCESS_PARAMETERS32 *params32 = get_ptr( &args );
576 PS_CREATE_INFO32 *info32 = get_ptr( &args );
577 PS_ATTRIBUTE_LIST32 *attr32 = get_ptr( &args );
579 struct object_attr64 process_attr, thread_attr;
580 RTL_USER_PROCESS_PARAMETERS *params;
581 PS_CREATE_INFO info;
582 PS_ATTRIBUTE_LIST *attr;
583 HANDLE process_handle = 0, thread_handle = 0;
585 NTSTATUS status;
587 *process_handle_ptr = *thread_handle_ptr = 0;
588 status = NtCreateUserProcess( &process_handle, &thread_handle, process_access, thread_access,
589 objattr_32to64( &process_attr, process_attr32 ),
590 objattr_32to64( &thread_attr, thread_attr32 ),
591 process_flags, thread_flags,
592 process_params_32to64( &params, params32),
593 &info, ps_attributes_32to64( &attr, attr32 ));
594 put_handle( process_handle_ptr, process_handle );
595 put_handle( thread_handle_ptr, thread_handle );
596 put_ps_create_info( info32, &info );
597 put_ps_attributes( attr32, attr );
598 RtlDestroyProcessParameters( params );
599 return status;
603 /**********************************************************************
604 * wow64_NtDebugActiveProcess
606 NTSTATUS WINAPI wow64_NtDebugActiveProcess( UINT *args )
608 HANDLE process = get_handle( &args );
609 HANDLE debug = get_handle( &args );
611 return NtDebugActiveProcess( process, debug );
615 /**********************************************************************
616 * wow64_NtFlushInstructionCache
618 NTSTATUS WINAPI wow64_NtFlushInstructionCache( UINT *args )
620 HANDLE process = get_handle( &args );
621 const void *addr = get_ptr( &args );
622 SIZE_T size = get_ulong( &args );
624 return NtFlushInstructionCache( process, addr, size );
628 /**********************************************************************
629 * wow64_NtFlushProcessWriteBuffers
631 NTSTATUS WINAPI wow64_NtFlushProcessWriteBuffers( UINT *args )
633 NtFlushProcessWriteBuffers();
634 return STATUS_SUCCESS;
638 /**********************************************************************
639 * wow64_NtGetContextThread
641 NTSTATUS WINAPI wow64_NtGetContextThread( UINT *args )
643 HANDLE handle = get_handle( &args );
644 WOW64_CONTEXT *context = get_ptr( &args );
646 return NtQueryInformationThread( handle, ThreadWow64Context, context,
647 get_machine_context_size( current_machine ), NULL );
651 /**********************************************************************
652 * wow64_NtGetNextThread
654 NTSTATUS WINAPI wow64_NtGetNextThread( UINT *args )
656 HANDLE process = get_handle( &args );
657 HANDLE thread = get_handle( &args );
658 ACCESS_MASK access = get_ulong( &args );
659 ULONG attributes = get_ulong( &args );
660 ULONG flags = get_ulong( &args );
661 ULONG *handle_ptr = get_ptr( &args );
663 HANDLE handle = 0;
664 NTSTATUS status;
666 *handle_ptr = 0;
667 status = NtGetNextThread( process, thread, access, attributes, flags, &handle );
668 put_handle( handle_ptr, handle );
669 return status;
673 /**********************************************************************
674 * wow64_NtIsProcessInJob
676 NTSTATUS WINAPI wow64_NtIsProcessInJob( UINT *args )
678 HANDLE process = get_handle( &args );
679 HANDLE job = get_handle( &args );
681 return NtIsProcessInJob( process, job );
685 /**********************************************************************
686 * wow64_NtOpenProcess
688 NTSTATUS WINAPI wow64_NtOpenProcess( UINT *args )
690 ULONG *handle_ptr = get_ptr( &args );
691 ACCESS_MASK access = get_ulong( &args );
692 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
693 CLIENT_ID32 *id32 = get_ptr( &args );
695 struct object_attr64 attr;
696 HANDLE handle = 0;
697 CLIENT_ID id;
698 NTSTATUS status;
700 *handle_ptr = 0;
701 status = NtOpenProcess( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
702 put_handle( handle_ptr, handle );
703 return status;
707 /**********************************************************************
708 * wow64_NtOpenThread
710 NTSTATUS WINAPI wow64_NtOpenThread( UINT *args )
712 ULONG *handle_ptr = get_ptr( &args );
713 ACCESS_MASK access = get_ulong( &args );
714 OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args );
715 CLIENT_ID32 *id32 = get_ptr( &args );
717 struct object_attr64 attr;
718 HANDLE handle = 0;
719 CLIENT_ID id;
720 NTSTATUS status;
722 *handle_ptr = 0;
723 status = NtOpenThread( &handle, access, objattr_32to64( &attr, attr32 ), client_id_32to64( &id, id32 ));
724 put_handle( handle_ptr, handle );
725 return status;
729 /**********************************************************************
730 * wow64_NtQueryInformationProcess
732 NTSTATUS WINAPI wow64_NtQueryInformationProcess( UINT *args )
734 HANDLE handle = get_handle( &args );
735 PROCESSINFOCLASS class = get_ulong( &args );
736 void *ptr = get_ptr( &args );
737 ULONG len = get_ulong( &args );
738 ULONG *retlen = get_ptr( &args );
740 NTSTATUS status;
742 switch (class)
744 case ProcessBasicInformation: /* PROCESS_BASIC_INFORMATION */
745 if (len == sizeof(PROCESS_BASIC_INFORMATION32))
747 PROCESS_BASIC_INFORMATION info;
748 PROCESS_BASIC_INFORMATION32 *info32 = ptr;
750 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
752 if (is_process_wow64( handle ))
753 info32->PebBaseAddress = PtrToUlong( info.PebBaseAddress ) + 0x1000;
754 else
755 info32->PebBaseAddress = 0;
756 info32->ExitStatus = info.ExitStatus;
757 info32->AffinityMask = info.AffinityMask;
758 info32->BasePriority = info.BasePriority;
759 info32->UniqueProcessId = info.UniqueProcessId;
760 info32->InheritedFromUniqueProcessId = info.InheritedFromUniqueProcessId;
761 if (retlen) *retlen = sizeof(*info32);
763 return status;
765 if (retlen) *retlen = sizeof(PROCESS_BASIC_INFORMATION32);
766 return STATUS_INFO_LENGTH_MISMATCH;
768 case ProcessIoCounters: /* IO_COUNTERS */
769 case ProcessTimes: /* KERNEL_USER_TIMES */
770 case ProcessDefaultHardErrorMode: /* ULONG */
771 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
772 case ProcessHandleCount: /* ULONG */
773 case ProcessSessionInformation: /* ULONG */
774 case ProcessDebugFlags: /* ULONG */
775 case ProcessExecuteFlags: /* ULONG */
776 case ProcessCookie: /* ULONG */
777 /* FIXME: check buffer alignment */
778 return NtQueryInformationProcess( handle, class, ptr, len, retlen );
780 case ProcessVmCounters: /* VM_COUNTERS_EX */
781 if (len == sizeof(VM_COUNTERS32) || len == sizeof(VM_COUNTERS_EX32))
783 VM_COUNTERS_EX info;
784 VM_COUNTERS_EX32 *info32 = ptr;
786 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
788 put_vm_counters( info32, &info, len );
789 if (retlen) *retlen = len;
791 return status;
793 if (retlen) *retlen = sizeof(VM_COUNTERS_EX32);
794 return STATUS_INFO_LENGTH_MISMATCH;
796 case ProcessDebugPort: /* ULONG_PTR */
797 case ProcessAffinityMask: /* ULONG_PTR */
798 case ProcessWow64Information: /* ULONG_PTR */
799 case ProcessDebugObjectHandle: /* HANDLE */
800 if (len == sizeof(ULONG))
802 ULONG_PTR data;
804 if (!(status = NtQueryInformationProcess( handle, class, &data, sizeof(data), NULL )))
806 *(ULONG *)ptr = data;
807 if (retlen) *retlen = sizeof(ULONG);
809 else if (status == STATUS_PORT_NOT_SET) *(ULONG *)ptr = 0;
810 return status;
812 if (retlen) *retlen = sizeof(ULONG);
813 return STATUS_INFO_LENGTH_MISMATCH;
815 case ProcessImageFileName:
816 case ProcessImageFileNameWin32: /* UNICODE_STRING + string */
818 ULONG retsize, size = len + sizeof(UNICODE_STRING) - sizeof(UNICODE_STRING32);
819 UNICODE_STRING *str = Wow64AllocateTemp( size );
820 UNICODE_STRING32 *str32 = ptr;
822 if (!(status = NtQueryInformationProcess( handle, class, str, size, &retsize )))
824 str32->Length = str->Length;
825 str32->MaximumLength = str->MaximumLength;
826 str32->Buffer = PtrToUlong( str32 + 1 );
827 memcpy( str32 + 1, str->Buffer, str->MaximumLength );
829 if (retlen) *retlen = retsize + sizeof(UNICODE_STRING32) - sizeof(UNICODE_STRING);
830 return status;
833 case ProcessImageInformation: /* SECTION_IMAGE_INFORMATION */
834 if (len == sizeof(SECTION_IMAGE_INFORMATION32))
836 SECTION_IMAGE_INFORMATION info;
837 SECTION_IMAGE_INFORMATION32 *info32 = ptr;
839 if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL )))
841 put_section_image_info( info32, &info );
842 if (retlen) *retlen = sizeof(*info32);
844 return status;
846 if (retlen) *retlen = sizeof(SECTION_IMAGE_INFORMATION32);
847 return STATUS_INFO_LENGTH_MISMATCH;
849 case ProcessWineLdtCopy:
850 return STATUS_NOT_IMPLEMENTED;
852 default:
853 FIXME( "unsupported class %u\n", class );
854 return STATUS_INVALID_INFO_CLASS;
859 /**********************************************************************
860 * wow64_NtQueryInformationThread
862 NTSTATUS WINAPI wow64_NtQueryInformationThread( UINT *args )
864 HANDLE handle = get_handle( &args );
865 THREADINFOCLASS class = get_ulong( &args );
866 void *ptr = get_ptr( &args );
867 ULONG len = get_ulong( &args );
868 ULONG *retlen = get_ptr( &args );
870 NTSTATUS status;
872 switch (class)
874 case ThreadBasicInformation: /* THREAD_BASIC_INFORMATION */
876 THREAD_BASIC_INFORMATION32 info32;
877 THREAD_BASIC_INFORMATION info;
879 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
880 if (!status)
882 info32.ExitStatus = info.ExitStatus;
883 info32.TebBaseAddress = is_process_id_wow64( &info.ClientId ) ?
884 PtrToUlong(info.TebBaseAddress) + 0x2000 : 0;
885 info32.ClientId.UniqueProcess = HandleToULong( info.ClientId.UniqueProcess );
886 info32.ClientId.UniqueThread = HandleToULong( info.ClientId.UniqueThread );
887 info32.AffinityMask = info.AffinityMask;
888 info32.Priority = info.Priority;
889 info32.BasePriority = info.BasePriority;
890 memcpy( ptr, &info32, min( len, sizeof(info32) ));
891 if (retlen) *retlen = min( len, sizeof(info32) );
893 return status;
896 case ThreadTimes: /* KERNEL_USER_TIMES */
897 case ThreadEnableAlignmentFaultFixup: /* set only */
898 case ThreadAmILastThread: /* ULONG */
899 case ThreadIsIoPending: /* ULONG */
900 case ThreadHideFromDebugger: /* BOOLEAN */
901 case ThreadSuspendCount: /* ULONG */
902 case ThreadPriorityBoost: /* ULONG */
903 /* FIXME: check buffer alignment */
904 return NtQueryInformationThread( handle, class, ptr, len, retlen );
906 case ThreadAffinityMask: /* ULONG_PTR */
907 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
909 ULONG_PTR data;
911 status = NtQueryInformationThread( handle, class, &data, sizeof(data), NULL );
912 if (!status)
914 memcpy( ptr, &data, min( len, sizeof(ULONG) ));
915 if (retlen) *retlen = min( len, sizeof(ULONG) );
917 return status;
920 case ThreadDescriptorTableEntry: /* THREAD_DESCRIPTOR_INFORMATION */
921 return RtlWow64GetThreadSelectorEntry( handle, ptr, len, retlen );
923 case ThreadWow64Context: /* WOW64_CONTEXT* */
924 return STATUS_INVALID_INFO_CLASS;
926 case ThreadGroupInformation: /* GROUP_AFFINITY */
928 GROUP_AFFINITY info;
930 status = NtQueryInformationThread( handle, class, &info, sizeof(info), NULL );
931 if (!status)
933 GROUP_AFFINITY32 info32 = { info.Mask, info.Group };
934 memcpy( ptr, &info32, min( len, sizeof(info32) ));
935 if (retlen) *retlen = min( len, sizeof(info32) );
937 return status;
940 case ThreadNameInformation: /* THREAD_NAME_INFORMATION */
942 THREAD_NAME_INFORMATION *info;
943 THREAD_NAME_INFORMATION32 *info32 = ptr;
944 ULONG size, ret_size;
946 if (len >= sizeof(*info32))
948 size = sizeof(*info) + len - sizeof(*info32);
949 info = Wow64AllocateTemp( size );
950 status = NtQueryInformationThread( handle, class, info, size, &ret_size );
951 if (!status)
953 info32->ThreadName.Length = info->ThreadName.Length;
954 info32->ThreadName.MaximumLength = info->ThreadName.MaximumLength;
955 info32->ThreadName.Buffer = PtrToUlong( info32 + 1 );
956 memcpy( info32 + 1, info + 1, min( len, info->ThreadName.MaximumLength ));
959 else status = NtQueryInformationThread( handle, class, NULL, 0, &ret_size );
961 if (retlen && (status == STATUS_SUCCESS || status == STATUS_BUFFER_TOO_SMALL))
962 *retlen = sizeof(*info32) + ret_size - sizeof(*info);
963 return status;
966 default:
967 FIXME( "unsupported class %u\n", class );
968 return STATUS_INVALID_INFO_CLASS;
973 /**********************************************************************
974 * wow64_NtQueueApcThread
976 NTSTATUS WINAPI wow64_NtQueueApcThread( UINT *args )
978 HANDLE handle = get_handle( &args );
979 ULONG func = get_ulong( &args );
980 ULONG arg1 = get_ulong( &args );
981 ULONG arg2 = get_ulong( &args );
982 ULONG arg3 = get_ulong( &args );
984 return NtQueueApcThread( handle, apc_32to64( func ),
985 (ULONG_PTR)apc_param_32to64( func, arg1 ), arg2, arg3 );
989 /**********************************************************************
990 * wow64_NtRaiseException
992 NTSTATUS WINAPI wow64_NtRaiseException( UINT *args )
994 EXCEPTION_RECORD32 *rec32 = get_ptr( &args );
995 void *context32 = get_ptr( &args );
996 BOOL first_chance = get_ulong( &args );
998 EXCEPTION_RECORD *rec = exception_record_32to64( rec32 );
999 CONTEXT context;
1001 NtSetInformationThread( GetCurrentThread(), ThreadWow64Context,
1002 context32, get_machine_context_size( current_machine ));
1004 __TRY
1006 raise_exception( rec, &context, first_chance );
1008 __EXCEPT_ALL
1010 call_user_exception_dispatcher( rec32, context32, &context );
1012 __ENDTRY
1013 return STATUS_SUCCESS;
1017 /**********************************************************************
1018 * wow64_NtRemoveProcessDebug
1020 NTSTATUS WINAPI wow64_NtRemoveProcessDebug( UINT *args )
1022 HANDLE process = get_handle( &args );
1023 HANDLE debug = get_handle( &args );
1025 return NtRemoveProcessDebug( process, debug );
1029 /**********************************************************************
1030 * wow64_NtResumeProcess
1032 NTSTATUS WINAPI wow64_NtResumeProcess( UINT *args )
1034 HANDLE handle = get_handle( &args );
1036 return NtResumeProcess( handle );
1040 /**********************************************************************
1041 * wow64_NtResumeThread
1043 NTSTATUS WINAPI wow64_NtResumeThread( UINT *args )
1045 HANDLE handle = get_handle( &args );
1046 ULONG *count = get_ptr( &args );
1048 return NtResumeThread( handle, count );
1052 /**********************************************************************
1053 * wow64_NtSetContextThread
1055 NTSTATUS WINAPI wow64_NtSetContextThread( UINT *args )
1057 HANDLE handle = get_handle( &args );
1058 WOW64_CONTEXT *context = get_ptr( &args );
1060 return NtSetInformationThread( handle, ThreadWow64Context,
1061 context, get_machine_context_size( current_machine ));
1065 /**********************************************************************
1066 * wow64_NtSetInformationProcess
1068 NTSTATUS WINAPI wow64_NtSetInformationProcess( UINT *args )
1070 HANDLE handle = get_handle( &args );
1071 PROCESSINFOCLASS class = get_ulong( &args );
1072 void *ptr = get_ptr( &args );
1073 ULONG len = get_ulong( &args );
1075 NTSTATUS status;
1077 switch (class)
1079 case ProcessDefaultHardErrorMode: /* ULONG */
1080 case ProcessPriorityClass: /* PROCESS_PRIORITY_CLASS */
1081 case ProcessExecuteFlags: /* ULONG */
1082 case ProcessPagePriority: /* MEMORY_PRIORITY_INFORMATION */
1083 case ProcessPowerThrottlingState: /* PROCESS_POWER_THROTTLING_STATE */
1084 case ProcessLeapSecondInformation: /* PROCESS_LEAP_SECOND_INFO */
1085 return NtSetInformationProcess( handle, class, ptr, len );
1087 case ProcessAffinityMask: /* ULONG_PTR */
1088 if (len == sizeof(ULONG))
1090 ULONG_PTR mask = *(ULONG *)ptr;
1091 return NtSetInformationProcess( handle, class, &mask, sizeof(mask) );
1093 else return STATUS_INVALID_PARAMETER;
1095 case ProcessInstrumentationCallback: /* PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION */
1096 if (len == sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION32))
1098 FIXME( "ProcessInstrumentationCallback stub\n" );
1099 return STATUS_SUCCESS;
1101 else return STATUS_INFO_LENGTH_MISMATCH;
1103 case ProcessThreadStackAllocation: /* PROCESS_STACK_ALLOCATION_INFORMATION(_EX) */
1104 if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX32))
1106 PROCESS_STACK_ALLOCATION_INFORMATION_EX32 *stack = ptr;
1107 PROCESS_STACK_ALLOCATION_INFORMATION_EX info;
1109 info.PreferredNode = stack->PreferredNode;
1110 info.Reserved0 = stack->Reserved0;
1111 info.Reserved1 = stack->Reserved1;
1112 info.Reserved2 = stack->Reserved2;
1113 info.AllocInfo.ReserveSize = stack->AllocInfo.ReserveSize;
1114 info.AllocInfo.ZeroBits = get_zero_bits( stack->AllocInfo.ZeroBits );
1115 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
1116 stack->AllocInfo.StackBase = PtrToUlong( info.AllocInfo.StackBase );
1117 return status;
1119 else if (len == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION32))
1121 PROCESS_STACK_ALLOCATION_INFORMATION32 *stack = ptr;
1122 PROCESS_STACK_ALLOCATION_INFORMATION info;
1124 info.ReserveSize = stack->ReserveSize;
1125 info.ZeroBits = get_zero_bits( stack->ZeroBits );
1126 if (!(status = NtSetInformationProcess( handle, class, &info, sizeof(info) )))
1127 stack->StackBase = PtrToUlong( info.StackBase );
1128 return status;
1130 else return STATUS_INFO_LENGTH_MISMATCH;
1132 case ProcessWineMakeProcessSystem: /* HANDLE* */
1133 if (len == sizeof(ULONG))
1135 HANDLE event = 0;
1136 status = NtSetInformationProcess( handle, class, &event, sizeof(HANDLE *) );
1137 put_handle( ptr, event );
1138 return status;
1140 else return STATUS_INFO_LENGTH_MISMATCH;
1142 default:
1143 FIXME( "unsupported class %u\n", class );
1144 return STATUS_INVALID_INFO_CLASS;
1149 /**********************************************************************
1150 * wow64_NtSetInformationThread
1152 NTSTATUS WINAPI wow64_NtSetInformationThread( UINT *args )
1154 HANDLE handle = get_handle( &args );
1155 THREADINFOCLASS class = get_ulong( &args );
1156 void *ptr = get_ptr( &args );
1157 ULONG len = get_ulong( &args );
1159 switch (class)
1161 case ThreadZeroTlsCell: /* ULONG */
1162 case ThreadBasePriority: /* ULONG */
1163 case ThreadHideFromDebugger: /* void */
1164 case ThreadEnableAlignmentFaultFixup: /* BOOLEAN */
1165 case ThreadPowerThrottlingState: /* THREAD_POWER_THROTTLING_STATE */
1166 case ThreadIdealProcessor: /* ULONG */
1167 case ThreadPriorityBoost: /* ULONG */
1168 return NtSetInformationThread( handle, class, ptr, len );
1170 case ThreadImpersonationToken: /* HANDLE */
1171 if (len == sizeof(ULONG))
1173 HANDLE token = LongToHandle( *(ULONG *)ptr );
1174 return NtSetInformationThread( handle, class, &token, sizeof(token) );
1176 else return STATUS_INVALID_PARAMETER;
1178 case ThreadAffinityMask: /* ULONG_PTR */
1179 case ThreadQuerySetWin32StartAddress: /* PRTL_THREAD_START_ROUTINE */
1180 if (len == sizeof(ULONG))
1182 ULONG_PTR mask = *(ULONG *)ptr;
1183 return NtSetInformationThread( handle, class, &mask, sizeof(mask) );
1185 else return STATUS_INVALID_PARAMETER;
1187 case ThreadWow64Context: /* WOW64_CONTEXT* */
1188 return STATUS_INVALID_INFO_CLASS;
1190 case ThreadGroupInformation: /* GROUP_AFFINITY */
1191 if (len == sizeof(GROUP_AFFINITY32))
1193 GROUP_AFFINITY32 *info32 = ptr;
1194 GROUP_AFFINITY info = { info32->Mask, info32->Group };
1196 return NtSetInformationThread( handle, class, &info, sizeof(info) );
1198 else return STATUS_INVALID_PARAMETER;
1200 case ThreadNameInformation: /* THREAD_NAME_INFORMATION */
1201 if (len == sizeof(THREAD_NAME_INFORMATION32))
1203 THREAD_NAME_INFORMATION32 *info32 = ptr;
1204 THREAD_NAME_INFORMATION info;
1206 if (!unicode_str_32to64( &info.ThreadName, &info32->ThreadName ))
1207 return STATUS_ACCESS_VIOLATION;
1208 return NtSetInformationThread( handle, class, &info, sizeof(info) );
1210 else return STATUS_INFO_LENGTH_MISMATCH;
1212 default:
1213 FIXME( "unsupported class %u\n", class );
1214 return STATUS_INVALID_INFO_CLASS;
1219 /**********************************************************************
1220 * wow64_NtSetThreadExecutionState
1222 NTSTATUS WINAPI wow64_NtSetThreadExecutionState( UINT *args )
1224 EXECUTION_STATE new_state = get_ulong( &args );
1225 EXECUTION_STATE *old_state = get_ptr( &args );
1227 return NtSetThreadExecutionState( new_state, old_state );
1231 /**********************************************************************
1232 * wow64_NtSuspendProcess
1234 NTSTATUS WINAPI wow64_NtSuspendProcess( UINT *args )
1236 HANDLE handle = get_handle( &args );
1238 return NtSuspendProcess( handle );
1242 /**********************************************************************
1243 * wow64_NtSuspendThread
1245 NTSTATUS WINAPI wow64_NtSuspendThread( UINT *args )
1247 HANDLE handle = get_handle( &args );
1248 ULONG *count = get_ptr( &args );
1250 return NtSuspendThread( handle, count );
1254 /**********************************************************************
1255 * wow64_NtTerminateProcess
1257 NTSTATUS WINAPI wow64_NtTerminateProcess( UINT *args )
1259 HANDLE handle = get_handle( &args );
1260 LONG exit_code = get_ulong( &args );
1262 return NtTerminateProcess( handle, exit_code );
1266 /**********************************************************************
1267 * wow64_NtTerminateThread
1269 NTSTATUS WINAPI wow64_NtTerminateThread( UINT *args )
1271 HANDLE handle = get_handle( &args );
1272 LONG exit_code = get_ulong( &args );
1274 return NtTerminateThread( handle, exit_code );
1278 /**********************************************************************
1279 * Wow64PassExceptionToGuest (wow64.@)
1281 void WINAPI Wow64PassExceptionToGuest( EXCEPTION_POINTERS *ptrs )
1283 EXCEPTION_RECORD *rec = ptrs->ExceptionRecord;
1284 EXCEPTION_RECORD32 rec32;
1285 ULONG i;
1287 rec32.ExceptionCode = rec->ExceptionCode;
1288 rec32.ExceptionFlags = rec->ExceptionFlags;
1289 rec32.ExceptionRecord = PtrToUlong( rec->ExceptionRecord );
1290 rec32.ExceptionAddress = PtrToUlong( rec->ExceptionAddress );
1291 rec32.NumberParameters = rec->NumberParameters;
1292 for (i = 0; i < rec->NumberParameters; i++)
1293 rec32.ExceptionInformation[i] = rec->ExceptionInformation[i];
1295 call_user_exception_dispatcher( &rec32, NULL, ptrs->ContextRecord );