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