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
24 #define WIN32_NO_STATUS
29 #include "wow64_private.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
)
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
);
50 static BOOL
is_process_wow64( HANDLE handle
)
54 if (handle
== GetCurrentProcess()) return TRUE
;
55 if (NtQueryInformationProcess( handle
, ProcessWow64Information
, &info
, sizeof(info
), NULL
))
61 static BOOL
is_process_id_wow64( const CLIENT_ID
*id
)
66 if (id
->UniqueProcess
== ULongToHandle(GetCurrentProcessId())) return TRUE
;
67 if (!NtOpenProcess( &handle
, PROCESS_QUERY_LIMITED_INFORMATION
, NULL
, id
))
69 ret
= is_process_wow64( handle
);
76 static EXCEPTION_RECORD
*exception_record_32to64( const EXCEPTION_RECORD32
*rec32
)
78 EXCEPTION_RECORD
*rec
;
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
];
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
;
100 if (RtlCreateProcessParametersEx( &ret
, unicode_str_32to64( &image
, ¶ms32
->ImagePathName
),
101 unicode_str_32to64( &dllpath
, ¶ms32
->DllPath
),
102 unicode_str_32to64( &curdir
, ¶ms32
->CurrentDirectory
.DosPath
),
103 unicode_str_32to64( &cmdline
, ¶ms32
->CommandLine
),
104 ULongToPtr( params32
->Environment
),
105 unicode_str_32to64( &title
, ¶ms32
->WindowTitle
),
106 unicode_str_32to64( &desktop
, ¶ms32
->Desktop
),
107 unicode_str_32to64( &shell
, ¶ms32
->ShellInfo
),
108 unicode_str_32to64( &runtime
, ¶ms32
->RuntimeInfo
),
109 PROCESS_PARAMS_FLAG_NORMALIZED
))
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
;
136 static void put_ps_create_info( PS_CREATE_INFO32
*info32
, const PS_CREATE_INFO
*info
)
138 info32
->State
= info
->State
;
141 case PsCreateInitialState
:
142 info32
->InitState
.InitFlags
= info
->InitState
.InitFlags
;
143 info32
->InitState
.AdditionalFileAccess
= info
->InitState
.AdditionalFileAccess
;
145 case PsCreateFailOnSectionCreate
:
146 info32
->FailSection
.FileHandle
= HandleToLong( info
->FailSection
.FileHandle
);
148 case PsCreateFailExeFormat
:
149 info32
->ExeFormat
.DllCharacteristics
= info
->ExeFormat
.DllCharacteristics
;
151 case PsCreateFailExeName
:
152 info32
->ExeName
.IFEOKey
= HandleToLong( info
->ExeName
.IFEOKey
);
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
;
172 static PS_ATTRIBUTE_LIST
*ps_attributes_32to64( PS_ATTRIBUTE_LIST
**attr
, const PS_ATTRIBUTE_LIST32
*attr32
)
174 PS_ATTRIBUTE_LIST
*ret
;
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
;
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
;
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
] );
216 case PS_ATTRIBUTE_PARENT_PROCESS
:
217 ret
->Attributes
[i
].Size
= sizeof(HANDLE
);
218 ret
->Attributes
[i
].ValuePtr
= LongToHandle( attr32
->Attributes
[i
].Value
);
220 case PS_ATTRIBUTE_CLIENT_ID
:
221 ret
->Attributes
[i
].Size
= sizeof(CLIENT_ID
);
222 ret
->Attributes
[i
].ValuePtr
= Wow64AllocateTemp( ret
->Attributes
[i
].Size
);
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
);
228 case PS_ATTRIBUTE_TEB_ADDRESS
:
229 ret
->Attributes
[i
].Size
= sizeof(TEB
*);
230 ret
->Attributes
[i
].ValuePtr
= Wow64AllocateTemp( ret
->Attributes
[i
].Size
);
239 static void put_ps_attributes( PS_ATTRIBUTE_LIST32
*attr32
, const PS_ATTRIBUTE_LIST
*attr
)
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
:
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
;
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
;
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
;
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
:
308 ULONG rec_ptr
; /* first arg for KiUserExceptionDispatcher */
309 ULONG context_ptr
; /* second arg for KiUserExceptionDispatcher */
310 EXCEPTION_RECORD32 rec
;
311 I386_CONTEXT context
;
313 I386_CONTEXT
*context
, ctx
= { CONTEXT_I386_ALL
};
314 CONTEXT_EX
*context_ex
, *src_ex
= NULL
;
317 NtQueryInformationThread( GetCurrentThread(), ThreadWow64Context
, &ctx
, sizeof(ctx
), NULL
);
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
);
344 RtlInitializeExtendedContext( &stack
->context
, flags
, &context_ex
);
345 context
= RtlLocateLegacyContext( context_ex
, NULL
);
347 context
->ContextFlags
= flags
;
348 stack
->context_ptr
= PtrToUlong( context
);
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
);
373 case IMAGE_FILE_MACHINE_ARMNT
:
378 EXCEPTION_RECORD32 rec
;
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;
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
);
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
;
406 __ASM_GLOBAL_FUNC( raise_exception
,
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"
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")
430 "stp x0, x1, [sp, #16]\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") )
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 /**********************************************************************
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
;
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
);
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
;
582 PS_ATTRIBUTE_LIST
*attr
;
583 HANDLE process_handle
= 0, thread_handle
= 0;
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( ¶ms
, 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
);
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
);
667 status
= NtGetNextThread( process
, thread
, access
, attributes
, flags
, &handle
);
668 put_handle( handle_ptr
, handle
);
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
;
701 status
= NtOpenProcess( &handle
, access
, objattr_32to64( &attr
, attr32
), client_id_32to64( &id
, id32
));
702 put_handle( handle_ptr
, handle
);
707 /**********************************************************************
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
;
723 status
= NtOpenThread( &handle
, access
, objattr_32to64( &attr
, attr32
), client_id_32to64( &id
, id32
));
724 put_handle( handle_ptr
, handle
);
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
);
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;
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
);
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
))
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
;
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
))
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;
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
);
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
);
846 if (retlen
) *retlen
= sizeof(SECTION_IMAGE_INFORMATION32
);
847 return STATUS_INFO_LENGTH_MISMATCH
;
849 case ProcessWineLdtCopy
:
850 return STATUS_NOT_IMPLEMENTED
;
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
);
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
);
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
) );
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 /* FIXME: check buffer alignment */
903 return NtQueryInformationThread( handle
, class, ptr
, len
, retlen
);
905 case ThreadAffinityMask
: /* ULONG_PTR */
906 case ThreadQuerySetWin32StartAddress
: /* PRTL_THREAD_START_ROUTINE */
910 status
= NtQueryInformationThread( handle
, class, &data
, sizeof(data
), NULL
);
913 memcpy( ptr
, &data
, min( len
, sizeof(ULONG
) ));
914 if (retlen
) *retlen
= min( len
, sizeof(ULONG
) );
919 case ThreadDescriptorTableEntry
: /* THREAD_DESCRIPTOR_INFORMATION */
920 return RtlWow64GetThreadSelectorEntry( handle
, ptr
, len
, retlen
);
922 case ThreadWow64Context
: /* WOW64_CONTEXT* */
923 return STATUS_INVALID_INFO_CLASS
;
925 case ThreadGroupInformation
: /* GROUP_AFFINITY */
929 status
= NtQueryInformationThread( handle
, class, &info
, sizeof(info
), NULL
);
932 GROUP_AFFINITY32 info32
= { info
.Mask
, info
.Group
};
933 memcpy( ptr
, &info32
, min( len
, sizeof(info32
) ));
934 if (retlen
) *retlen
= min( len
, sizeof(info32
) );
939 case ThreadNameInformation
: /* THREAD_NAME_INFORMATION */
941 THREAD_NAME_INFORMATION
*info
;
942 THREAD_NAME_INFORMATION32
*info32
= ptr
;
943 ULONG size
, ret_size
;
945 if (len
>= sizeof(*info32
))
947 size
= sizeof(*info
) + len
- sizeof(*info32
);
948 info
= Wow64AllocateTemp( size
);
949 status
= NtQueryInformationThread( handle
, class, info
, size
, &ret_size
);
952 info32
->ThreadName
.Length
= info
->ThreadName
.Length
;
953 info32
->ThreadName
.MaximumLength
= info
->ThreadName
.MaximumLength
;
954 info32
->ThreadName
.Buffer
= PtrToUlong( info32
+ 1 );
955 memcpy( info32
+ 1, info
+ 1, min( len
, info
->ThreadName
.MaximumLength
));
958 else status
= NtQueryInformationThread( handle
, class, NULL
, 0, &ret_size
);
960 if (retlen
&& (status
== STATUS_SUCCESS
|| status
== STATUS_BUFFER_TOO_SMALL
))
961 *retlen
= sizeof(*info32
) + ret_size
- sizeof(*info
);
966 FIXME( "unsupported class %u\n", class );
967 return STATUS_INVALID_INFO_CLASS
;
972 /**********************************************************************
973 * wow64_NtQueueApcThread
975 NTSTATUS WINAPI
wow64_NtQueueApcThread( UINT
*args
)
977 HANDLE handle
= get_handle( &args
);
978 ULONG func
= get_ulong( &args
);
979 ULONG arg1
= get_ulong( &args
);
980 ULONG arg2
= get_ulong( &args
);
981 ULONG arg3
= get_ulong( &args
);
983 return NtQueueApcThread( handle
, apc_32to64( func
),
984 (ULONG_PTR
)apc_param_32to64( func
, arg1
), arg2
, arg3
);
988 /**********************************************************************
989 * wow64_NtRaiseException
991 NTSTATUS WINAPI
wow64_NtRaiseException( UINT
*args
)
993 EXCEPTION_RECORD32
*rec32
= get_ptr( &args
);
994 void *context32
= get_ptr( &args
);
995 BOOL first_chance
= get_ulong( &args
);
997 EXCEPTION_RECORD
*rec
= exception_record_32to64( rec32
);
1000 NtSetInformationThread( GetCurrentThread(), ThreadWow64Context
,
1001 context32
, get_machine_context_size( current_machine
));
1005 raise_exception( rec
, &context
, first_chance
);
1009 call_user_exception_dispatcher( rec32
, context32
, &context
);
1012 return STATUS_SUCCESS
;
1016 /**********************************************************************
1017 * wow64_NtRemoveProcessDebug
1019 NTSTATUS WINAPI
wow64_NtRemoveProcessDebug( UINT
*args
)
1021 HANDLE process
= get_handle( &args
);
1022 HANDLE debug
= get_handle( &args
);
1024 return NtRemoveProcessDebug( process
, debug
);
1028 /**********************************************************************
1029 * wow64_NtResumeProcess
1031 NTSTATUS WINAPI
wow64_NtResumeProcess( UINT
*args
)
1033 HANDLE handle
= get_handle( &args
);
1035 return NtResumeProcess( handle
);
1039 /**********************************************************************
1040 * wow64_NtResumeThread
1042 NTSTATUS WINAPI
wow64_NtResumeThread( UINT
*args
)
1044 HANDLE handle
= get_handle( &args
);
1045 ULONG
*count
= get_ptr( &args
);
1047 return NtResumeThread( handle
, count
);
1051 /**********************************************************************
1052 * wow64_NtSetContextThread
1054 NTSTATUS WINAPI
wow64_NtSetContextThread( UINT
*args
)
1056 HANDLE handle
= get_handle( &args
);
1057 WOW64_CONTEXT
*context
= get_ptr( &args
);
1059 return NtSetInformationThread( handle
, ThreadWow64Context
,
1060 context
, get_machine_context_size( current_machine
));
1064 /**********************************************************************
1065 * wow64_NtSetInformationProcess
1067 NTSTATUS WINAPI
wow64_NtSetInformationProcess( UINT
*args
)
1069 HANDLE handle
= get_handle( &args
);
1070 PROCESSINFOCLASS
class = get_ulong( &args
);
1071 void *ptr
= get_ptr( &args
);
1072 ULONG len
= get_ulong( &args
);
1078 case ProcessDefaultHardErrorMode
: /* ULONG */
1079 case ProcessPriorityClass
: /* PROCESS_PRIORITY_CLASS */
1080 case ProcessExecuteFlags
: /* ULONG */
1081 return NtSetInformationProcess( handle
, class, ptr
, len
);
1083 case ProcessAffinityMask
: /* ULONG_PTR */
1084 if (len
== sizeof(ULONG
))
1086 ULONG_PTR mask
= *(ULONG
*)ptr
;
1087 return NtSetInformationProcess( handle
, class, &mask
, sizeof(mask
) );
1089 else return STATUS_INVALID_PARAMETER
;
1091 case ProcessInstrumentationCallback
: /* PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION */
1092 if (len
== sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION32
))
1094 FIXME( "ProcessInstrumentationCallback stub\n" );
1095 return STATUS_SUCCESS
;
1097 else return STATUS_INFO_LENGTH_MISMATCH
;
1099 case ProcessThreadStackAllocation
: /* PROCESS_STACK_ALLOCATION_INFORMATION(_EX) */
1100 if (len
== sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX32
))
1102 PROCESS_STACK_ALLOCATION_INFORMATION_EX32
*stack
= ptr
;
1103 PROCESS_STACK_ALLOCATION_INFORMATION_EX info
;
1105 info
.PreferredNode
= stack
->PreferredNode
;
1106 info
.Reserved0
= stack
->Reserved0
;
1107 info
.Reserved1
= stack
->Reserved1
;
1108 info
.Reserved2
= stack
->Reserved2
;
1109 info
.AllocInfo
.ReserveSize
= stack
->AllocInfo
.ReserveSize
;
1110 info
.AllocInfo
.ZeroBits
= get_zero_bits( stack
->AllocInfo
.ZeroBits
);
1111 if (!(status
= NtSetInformationProcess( handle
, class, &info
, sizeof(info
) )))
1112 stack
->AllocInfo
.StackBase
= PtrToUlong( info
.AllocInfo
.StackBase
);
1115 else if (len
== sizeof(PROCESS_STACK_ALLOCATION_INFORMATION32
))
1117 PROCESS_STACK_ALLOCATION_INFORMATION32
*stack
= ptr
;
1118 PROCESS_STACK_ALLOCATION_INFORMATION info
;
1120 info
.ReserveSize
= stack
->ReserveSize
;
1121 info
.ZeroBits
= get_zero_bits( stack
->ZeroBits
);
1122 if (!(status
= NtSetInformationProcess( handle
, class, &info
, sizeof(info
) )))
1123 stack
->StackBase
= PtrToUlong( info
.StackBase
);
1126 else return STATUS_INFO_LENGTH_MISMATCH
;
1128 case ProcessWineMakeProcessSystem
: /* HANDLE* */
1129 if (len
== sizeof(ULONG
))
1132 status
= NtSetInformationProcess( handle
, class, &event
, sizeof(HANDLE
*) );
1133 put_handle( ptr
, event
);
1136 else return STATUS_INFO_LENGTH_MISMATCH
;
1139 FIXME( "unsupported class %u\n", class );
1140 return STATUS_INVALID_INFO_CLASS
;
1145 /**********************************************************************
1146 * wow64_NtSetInformationThread
1148 NTSTATUS WINAPI
wow64_NtSetInformationThread( UINT
*args
)
1150 HANDLE handle
= get_handle( &args
);
1151 THREADINFOCLASS
class = get_ulong( &args
);
1152 void *ptr
= get_ptr( &args
);
1153 ULONG len
= get_ulong( &args
);
1157 case ThreadZeroTlsCell
: /* ULONG */
1158 case ThreadBasePriority
: /* ULONG */
1159 case ThreadHideFromDebugger
: /* void */
1160 case ThreadEnableAlignmentFaultFixup
: /* BOOLEAN */
1161 case ThreadPowerThrottlingState
: /* THREAD_POWER_THROTTLING_STATE */
1162 return NtSetInformationThread( handle
, class, ptr
, len
);
1164 case ThreadImpersonationToken
: /* HANDLE */
1165 if (len
== sizeof(ULONG
))
1167 HANDLE token
= LongToHandle( *(ULONG
*)ptr
);
1168 return NtSetInformationThread( handle
, class, &token
, sizeof(token
) );
1170 else return STATUS_INVALID_PARAMETER
;
1172 case ThreadAffinityMask
: /* ULONG_PTR */
1173 case ThreadQuerySetWin32StartAddress
: /* PRTL_THREAD_START_ROUTINE */
1174 if (len
== sizeof(ULONG
))
1176 ULONG_PTR mask
= *(ULONG
*)ptr
;
1177 return NtSetInformationThread( handle
, class, &mask
, sizeof(mask
) );
1179 else return STATUS_INVALID_PARAMETER
;
1181 case ThreadWow64Context
: /* WOW64_CONTEXT* */
1182 return STATUS_INVALID_INFO_CLASS
;
1184 case ThreadGroupInformation
: /* GROUP_AFFINITY */
1185 if (len
== sizeof(GROUP_AFFINITY32
))
1187 GROUP_AFFINITY32
*info32
= ptr
;
1188 GROUP_AFFINITY info
= { info32
->Mask
, info32
->Group
};
1190 return NtSetInformationThread( handle
, class, &info
, sizeof(info
) );
1192 else return STATUS_INVALID_PARAMETER
;
1194 case ThreadNameInformation
: /* THREAD_NAME_INFORMATION */
1195 if (len
== sizeof(THREAD_NAME_INFORMATION32
))
1197 THREAD_NAME_INFORMATION32
*info32
= ptr
;
1198 THREAD_NAME_INFORMATION info
;
1200 if (!unicode_str_32to64( &info
.ThreadName
, &info32
->ThreadName
))
1201 return STATUS_ACCESS_VIOLATION
;
1202 return NtSetInformationThread( handle
, class, &info
, sizeof(info
) );
1204 else return STATUS_INFO_LENGTH_MISMATCH
;
1207 FIXME( "unsupported class %u\n", class );
1208 return STATUS_INVALID_INFO_CLASS
;
1213 /**********************************************************************
1214 * wow64_NtSetThreadExecutionState
1216 NTSTATUS WINAPI
wow64_NtSetThreadExecutionState( UINT
*args
)
1218 EXECUTION_STATE new_state
= get_ulong( &args
);
1219 EXECUTION_STATE
*old_state
= get_ptr( &args
);
1221 return NtSetThreadExecutionState( new_state
, old_state
);
1225 /**********************************************************************
1226 * wow64_NtSuspendProcess
1228 NTSTATUS WINAPI
wow64_NtSuspendProcess( UINT
*args
)
1230 HANDLE handle
= get_handle( &args
);
1232 return NtSuspendProcess( handle
);
1236 /**********************************************************************
1237 * wow64_NtSuspendThread
1239 NTSTATUS WINAPI
wow64_NtSuspendThread( UINT
*args
)
1241 HANDLE handle
= get_handle( &args
);
1242 ULONG
*count
= get_ptr( &args
);
1244 return NtSuspendThread( handle
, count
);
1248 /**********************************************************************
1249 * wow64_NtTerminateProcess
1251 NTSTATUS WINAPI
wow64_NtTerminateProcess( UINT
*args
)
1253 HANDLE handle
= get_handle( &args
);
1254 LONG exit_code
= get_ulong( &args
);
1256 return NtTerminateProcess( handle
, exit_code
);
1260 /**********************************************************************
1261 * wow64_NtTerminateThread
1263 NTSTATUS WINAPI
wow64_NtTerminateThread( UINT
*args
)
1265 HANDLE handle
= get_handle( &args
);
1266 LONG exit_code
= get_ulong( &args
);
1268 return NtTerminateThread( handle
, exit_code
);
1272 /**********************************************************************
1273 * Wow64PassExceptionToGuest (wow64.@)
1275 void WINAPI
Wow64PassExceptionToGuest( EXCEPTION_POINTERS
*ptrs
)
1277 EXCEPTION_RECORD
*rec
= ptrs
->ExceptionRecord
;
1278 EXCEPTION_RECORD32 rec32
;
1281 rec32
.ExceptionCode
= rec
->ExceptionCode
;
1282 rec32
.ExceptionFlags
= rec
->ExceptionFlags
;
1283 rec32
.ExceptionRecord
= PtrToUlong( rec
->ExceptionRecord
);
1284 rec32
.ExceptionAddress
= PtrToUlong( rec
->ExceptionAddress
);
1285 rec32
.NumberParameters
= rec
->NumberParameters
;
1286 for (i
= 0; i
< rec
->NumberParameters
; i
++)
1287 rec32
.ExceptionInformation
[i
] = rec
->ExceptionInformation
[i
];
1289 call_user_exception_dispatcher( &rec32
, NULL
, ptrs
->ContextRecord
);