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 BOOL
is_process_wow64( HANDLE handle
)
41 if (handle
== GetCurrentProcess()) return TRUE
;
42 if (NtQueryInformationProcess( handle
, ProcessWow64Information
, &info
, sizeof(info
), NULL
))
48 static BOOL
is_process_id_wow64( const CLIENT_ID
*id
)
53 if (id
->UniqueProcess
== ULongToHandle(GetCurrentProcessId())) return TRUE
;
54 if (!NtOpenProcess( &handle
, PROCESS_QUERY_LIMITED_INFORMATION
, NULL
, id
))
56 ret
= is_process_wow64( handle
);
63 static RTL_USER_PROCESS_PARAMETERS
*process_params_32to64( RTL_USER_PROCESS_PARAMETERS
**params
,
64 RTL_USER_PROCESS_PARAMETERS32
*params32
)
66 UNICODE_STRING image
, dllpath
, curdir
, cmdline
, title
, desktop
, shell
, runtime
;
67 RTL_USER_PROCESS_PARAMETERS
*ret
;
70 if (RtlCreateProcessParametersEx( &ret
, unicode_str_32to64( &image
, ¶ms32
->ImagePathName
),
71 unicode_str_32to64( &dllpath
, ¶ms32
->DllPath
),
72 unicode_str_32to64( &curdir
, ¶ms32
->CurrentDirectory
.DosPath
),
73 unicode_str_32to64( &cmdline
, ¶ms32
->CommandLine
),
74 ULongToPtr( params32
->Environment
),
75 unicode_str_32to64( &title
, ¶ms32
->WindowTitle
),
76 unicode_str_32to64( &desktop
, ¶ms32
->Desktop
),
77 unicode_str_32to64( &shell
, ¶ms32
->ShellInfo
),
78 unicode_str_32to64( &runtime
, ¶ms32
->RuntimeInfo
),
79 PROCESS_PARAMS_FLAG_NORMALIZED
))
82 ret
->DebugFlags
= params32
->DebugFlags
;
83 ret
->ConsoleHandle
= LongToHandle( params32
->ConsoleHandle
);
84 ret
->ConsoleFlags
= params32
->ConsoleFlags
;
85 ret
->hStdInput
= LongToHandle( params32
->hStdInput
);
86 ret
->hStdOutput
= LongToHandle( params32
->hStdOutput
);
87 ret
->hStdError
= LongToHandle( params32
->hStdError
);
88 ret
->dwX
= params32
->dwX
;
89 ret
->dwY
= params32
->dwY
;
90 ret
->dwXSize
= params32
->dwXSize
;
91 ret
->dwYSize
= params32
->dwYSize
;
92 ret
->dwXCountChars
= params32
->dwXCountChars
;
93 ret
->dwYCountChars
= params32
->dwYCountChars
;
94 ret
->dwFillAttribute
= params32
->dwFillAttribute
;
95 ret
->dwFlags
= params32
->dwFlags
;
96 ret
->wShowWindow
= params32
->wShowWindow
;
97 ret
->EnvironmentVersion
= params32
->EnvironmentVersion
;
98 ret
->PackageDependencyData
= ULongToPtr( params32
->PackageDependencyData
);
99 ret
->ProcessGroupId
= params32
->ProcessGroupId
;
100 ret
->LoaderThreads
= params32
->LoaderThreads
;
106 static void put_ps_create_info( PS_CREATE_INFO32
*info32
, const PS_CREATE_INFO
*info
)
108 info32
->State
= info
->State
;
111 case PsCreateInitialState
:
112 info32
->InitState
.InitFlags
= info
->InitState
.InitFlags
;
113 info32
->InitState
.AdditionalFileAccess
= info
->InitState
.AdditionalFileAccess
;
115 case PsCreateFailOnSectionCreate
:
116 info32
->FailSection
.FileHandle
= HandleToLong( info
->FailSection
.FileHandle
);
118 case PsCreateFailExeFormat
:
119 info32
->ExeFormat
.DllCharacteristics
= info
->ExeFormat
.DllCharacteristics
;
121 case PsCreateFailExeName
:
122 info32
->ExeName
.IFEOKey
= HandleToLong( info
->ExeName
.IFEOKey
);
124 case PsCreateSuccess
:
125 info32
->SuccessState
.OutputFlags
= info
->SuccessState
.OutputFlags
;
126 info32
->SuccessState
.FileHandle
= HandleToLong( info
->SuccessState
.FileHandle
);
127 info32
->SuccessState
.SectionHandle
= HandleToLong( info
->SuccessState
.SectionHandle
);
128 info32
->SuccessState
.UserProcessParametersNative
= info
->SuccessState
.UserProcessParametersNative
;
129 info32
->SuccessState
.UserProcessParametersWow64
= info
->SuccessState
.UserProcessParametersWow64
;
130 info32
->SuccessState
.CurrentParameterFlags
= info
->SuccessState
.CurrentParameterFlags
;
131 info32
->SuccessState
.PebAddressNative
= info
->SuccessState
.PebAddressNative
;
132 info32
->SuccessState
.PebAddressWow64
= info
->SuccessState
.PebAddressWow64
;
133 info32
->SuccessState
.ManifestAddress
= info
->SuccessState
.ManifestAddress
;
134 info32
->SuccessState
.ManifestSize
= info
->SuccessState
.ManifestSize
;
142 static PS_ATTRIBUTE_LIST
*ps_attributes_32to64( PS_ATTRIBUTE_LIST
**attr
, const PS_ATTRIBUTE_LIST32
*attr32
)
144 PS_ATTRIBUTE_LIST
*ret
;
147 if (!attr32
) return NULL
;
148 count
= (attr32
->TotalLength
- sizeof(attr32
->TotalLength
)) / sizeof(PS_ATTRIBUTE32
);
149 ret
= Wow64AllocateTemp( offsetof(PS_ATTRIBUTE_LIST
, Attributes
[count
]) );
150 ret
->TotalLength
= offsetof( PS_ATTRIBUTE_LIST
, Attributes
[count
] );
151 for (i
= 0; i
< count
; i
++)
153 ret
->Attributes
[i
].Attribute
= attr32
->Attributes
[i
].Attribute
;
154 ret
->Attributes
[i
].Size
= attr32
->Attributes
[i
].Size
;
155 ret
->Attributes
[i
].Value
= attr32
->Attributes
[i
].Value
;
156 ret
->Attributes
[i
].ReturnLength
= NULL
;
157 switch (ret
->Attributes
[i
].Attribute
)
159 case PS_ATTRIBUTE_IMAGE_NAME
:
161 OBJECT_ATTRIBUTES attr
;
164 path
.Length
= ret
->Attributes
[i
].Size
;
165 path
.Buffer
= ret
->Attributes
[i
].ValuePtr
;
166 InitializeObjectAttributes( &attr
, &path
, OBJ_CASE_INSENSITIVE
, 0, 0 );
167 if (get_file_redirect( &attr
))
169 ret
->Attributes
[i
].Size
= attr
.ObjectName
->Length
;
170 ret
->Attributes
[i
].ValuePtr
= attr
.ObjectName
->Buffer
;
174 case PS_ATTRIBUTE_HANDLE_LIST
:
175 case PS_ATTRIBUTE_JOB_LIST
:
177 ULONG j
, handles_count
= attr32
->Attributes
[i
].Size
/ sizeof(ULONG
);
179 ret
->Attributes
[i
].Size
= handles_count
* sizeof(HANDLE
);
180 ret
->Attributes
[i
].ValuePtr
= Wow64AllocateTemp( ret
->Attributes
[i
].Size
);
181 for (j
= 0; j
< handles_count
; j
++)
182 ((HANDLE
*)ret
->Attributes
[i
].ValuePtr
)[j
] =
183 LongToHandle( ((LONG
*)ULongToPtr(attr32
->Attributes
[i
].Value
))[j
] );
186 case PS_ATTRIBUTE_PARENT_PROCESS
:
187 case PS_ATTRIBUTE_DEBUG_PORT
:
188 case PS_ATTRIBUTE_TOKEN
:
189 ret
->Attributes
[i
].Size
= sizeof(HANDLE
);
190 ret
->Attributes
[i
].ValuePtr
= LongToHandle( attr32
->Attributes
[i
].Value
);
192 case PS_ATTRIBUTE_CLIENT_ID
:
193 ret
->Attributes
[i
].Size
= sizeof(CLIENT_ID
);
194 ret
->Attributes
[i
].ValuePtr
= Wow64AllocateTemp( ret
->Attributes
[i
].Size
);
196 case PS_ATTRIBUTE_IMAGE_INFO
:
197 ret
->Attributes
[i
].Size
= sizeof(SECTION_IMAGE_INFORMATION
);
198 ret
->Attributes
[i
].ValuePtr
= Wow64AllocateTemp( ret
->Attributes
[i
].Size
);
200 case PS_ATTRIBUTE_TEB_ADDRESS
:
201 ret
->Attributes
[i
].Size
= sizeof(TEB
*);
202 ret
->Attributes
[i
].ValuePtr
= Wow64AllocateTemp( ret
->Attributes
[i
].Size
);
211 static void put_ps_attributes( PS_ATTRIBUTE_LIST32
*attr32
, const PS_ATTRIBUTE_LIST
*attr
)
216 for (i
= 0; i
< (attr32
->TotalLength
- sizeof(attr32
->TotalLength
)) / sizeof(PS_ATTRIBUTE32
); i
++)
218 switch (attr
->Attributes
[i
].Attribute
)
220 case PS_ATTRIBUTE_CLIENT_ID
:
223 ULONG size
= min( attr32
->Attributes
[i
].Size
, sizeof(id32
) );
224 put_client_id( &id32
, attr
->Attributes
[i
].ValuePtr
);
225 memcpy( ULongToPtr( attr32
->Attributes
[i
].Value
), &id32
, size
);
226 if (attr32
->Attributes
[i
].ReturnLength
)
227 *(ULONG
*)ULongToPtr(attr32
->Attributes
[i
].ReturnLength
) = size
;
230 case PS_ATTRIBUTE_IMAGE_INFO
:
232 SECTION_IMAGE_INFORMATION32 info32
;
233 ULONG size
= min( attr32
->Attributes
[i
].Size
, sizeof(info32
) );
234 put_section_image_info( &info32
, attr
->Attributes
[i
].ValuePtr
);
235 memcpy( ULongToPtr( attr32
->Attributes
[i
].Value
), &info32
, size
);
236 if (attr32
->Attributes
[i
].ReturnLength
)
237 *(ULONG
*)ULongToPtr(attr32
->Attributes
[i
].ReturnLength
) = size
;
240 case PS_ATTRIBUTE_TEB_ADDRESS
:
242 TEB
**teb
= attr
->Attributes
[i
].ValuePtr
;
243 ULONG teb32
= PtrToUlong( *teb
) + 0x2000;
244 ULONG size
= min( attr
->Attributes
[i
].Size
, sizeof(teb32
) );
245 memcpy( ULongToPtr( attr32
->Attributes
[i
].Value
), &teb32
, size
);
246 if (attr32
->Attributes
[i
].ReturnLength
)
247 *(ULONG
*)ULongToPtr(attr32
->Attributes
[i
].ReturnLength
) = size
;
255 void put_vm_counters( VM_COUNTERS_EX32
*info32
, const VM_COUNTERS_EX
*info
, ULONG size
)
257 info32
->PeakVirtualSize
= info
->PeakVirtualSize
;
258 info32
->VirtualSize
= info
->VirtualSize
;
259 info32
->PageFaultCount
= info
->PageFaultCount
;
260 info32
->PeakWorkingSetSize
= info
->PeakWorkingSetSize
;
261 info32
->WorkingSetSize
= info
->WorkingSetSize
;
262 info32
->QuotaPeakPagedPoolUsage
= info
->QuotaPeakPagedPoolUsage
;
263 info32
->QuotaPagedPoolUsage
= info
->QuotaPagedPoolUsage
;
264 info32
->QuotaPeakNonPagedPoolUsage
= info
->QuotaPeakNonPagedPoolUsage
;
265 info32
->QuotaNonPagedPoolUsage
= info
->QuotaNonPagedPoolUsage
;
266 info32
->PagefileUsage
= info
->PagefileUsage
;
267 info32
->PeakPagefileUsage
= info
->PeakPagefileUsage
;
268 if (size
== sizeof(VM_COUNTERS_EX32
)) info32
->PrivateUsage
= info
->PrivateUsage
;
272 /**********************************************************************
273 * wow64_NtAlertResumeThread
275 NTSTATUS WINAPI
wow64_NtAlertResumeThread( UINT
*args
)
277 HANDLE handle
= get_handle( &args
);
278 ULONG
*count
= get_ptr( &args
);
280 return NtAlertResumeThread( handle
, count
);
284 /**********************************************************************
285 * wow64_NtAlertThread
287 NTSTATUS WINAPI
wow64_NtAlertThread( UINT
*args
)
289 HANDLE handle
= get_handle( &args
);
291 return NtAlertThread( handle
);
295 /**********************************************************************
296 * wow64_NtAlertThreadByThreadId
298 NTSTATUS WINAPI
wow64_NtAlertThreadByThreadId( UINT
*args
)
300 HANDLE tid
= get_handle( &args
);
302 return NtAlertThreadByThreadId( tid
);
306 /**********************************************************************
307 * wow64_NtAssignProcessToJobObject
309 NTSTATUS WINAPI
wow64_NtAssignProcessToJobObject( UINT
*args
)
311 HANDLE job
= get_handle( &args
);
312 HANDLE process
= get_handle( &args
);
314 return NtAssignProcessToJobObject( job
, process
);
318 /**********************************************************************
319 * wow64_NtCreateThread
321 NTSTATUS WINAPI
wow64_NtCreateThread( UINT
*args
)
323 ULONG
*handle_ptr
= get_ptr( &args
);
324 ACCESS_MASK access
= get_ulong( &args
);
325 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
326 HANDLE process
= get_handle( &args
);
327 CLIENT_ID32
*id32
= get_ptr( &args
);
328 I386_CONTEXT
*context
= get_ptr( &args
);
329 void *initial_teb
= get_ptr( &args
);
330 BOOLEAN suspended
= get_ulong( &args
);
332 FIXME( "%p %lx %p %p %p %p %p %u: stub\n", handle_ptr
, access
, attr32
, process
,
333 id32
, context
, initial_teb
, suspended
);
334 return STATUS_NOT_IMPLEMENTED
;
338 /**********************************************************************
339 * wow64_NtCreateThreadEx
341 NTSTATUS WINAPI
wow64_NtCreateThreadEx( UINT
*args
)
343 ULONG
*handle_ptr
= get_ptr( &args
);
344 ACCESS_MASK access
= get_ulong( &args
);
345 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
346 HANDLE process
= get_handle( &args
);
347 PRTL_THREAD_START_ROUTINE start
= get_ptr( &args
);
348 void *param
= get_ptr( &args
);
349 ULONG flags
= get_ulong( &args
);
350 ULONG_PTR zero_bits
= get_ulong( &args
);
351 SIZE_T stack_commit
= get_ulong( &args
);
352 SIZE_T stack_reserve
= get_ulong( &args
);
353 PS_ATTRIBUTE_LIST32
*attr_list32
= get_ptr( &args
);
355 struct object_attr64 attr
;
356 PS_ATTRIBUTE_LIST
*attr_list
;
361 if (is_process_wow64( process
))
363 status
= NtCreateThreadEx( &handle
, access
, objattr_32to64( &attr
, attr32
), process
,
364 start
, param
, flags
, get_zero_bits( zero_bits
),
365 stack_commit
, stack_reserve
,
366 ps_attributes_32to64( &attr_list
, attr_list32
));
367 put_ps_attributes( attr_list32
, attr_list
);
369 else status
= STATUS_ACCESS_DENIED
;
371 put_handle( handle_ptr
, handle
);
376 /**********************************************************************
377 * wow64_NtCreateUserProcess
379 NTSTATUS WINAPI
wow64_NtCreateUserProcess( UINT
*args
)
381 ULONG
*process_handle_ptr
= get_ptr( &args
);
382 ULONG
*thread_handle_ptr
= get_ptr( &args
);
383 ACCESS_MASK process_access
= get_ulong( &args
);
384 ACCESS_MASK thread_access
= get_ulong( &args
);
385 OBJECT_ATTRIBUTES32
*process_attr32
= get_ptr( &args
);
386 OBJECT_ATTRIBUTES32
*thread_attr32
= get_ptr( &args
);
387 ULONG process_flags
= get_ulong( &args
);
388 ULONG thread_flags
= get_ulong( &args
);
389 RTL_USER_PROCESS_PARAMETERS32
*params32
= get_ptr( &args
);
390 PS_CREATE_INFO32
*info32
= get_ptr( &args
);
391 PS_ATTRIBUTE_LIST32
*attr32
= get_ptr( &args
);
393 struct object_attr64 process_attr
, thread_attr
;
394 RTL_USER_PROCESS_PARAMETERS
*params
;
396 PS_ATTRIBUTE_LIST
*attr
;
397 HANDLE process_handle
= 0, thread_handle
= 0;
401 *process_handle_ptr
= *thread_handle_ptr
= 0;
402 status
= NtCreateUserProcess( &process_handle
, &thread_handle
, process_access
, thread_access
,
403 objattr_32to64( &process_attr
, process_attr32
),
404 objattr_32to64( &thread_attr
, thread_attr32
),
405 process_flags
, thread_flags
,
406 process_params_32to64( ¶ms
, params32
),
407 &info
, ps_attributes_32to64( &attr
, attr32
));
408 put_handle( process_handle_ptr
, process_handle
);
409 put_handle( thread_handle_ptr
, thread_handle
);
410 put_ps_create_info( info32
, &info
);
411 put_ps_attributes( attr32
, attr
);
412 RtlDestroyProcessParameters( params
);
417 /**********************************************************************
418 * wow64_NtDebugActiveProcess
420 NTSTATUS WINAPI
wow64_NtDebugActiveProcess( UINT
*args
)
422 HANDLE process
= get_handle( &args
);
423 HANDLE debug
= get_handle( &args
);
425 return NtDebugActiveProcess( process
, debug
);
429 /**********************************************************************
430 * wow64_NtFlushInstructionCache
432 NTSTATUS WINAPI
wow64_NtFlushInstructionCache( UINT
*args
)
434 HANDLE process
= get_handle( &args
);
435 const void *addr
= get_ptr( &args
);
436 SIZE_T size
= get_ulong( &args
);
438 return NtFlushInstructionCache( process
, addr
, size
);
442 /**********************************************************************
443 * wow64_NtFlushProcessWriteBuffers
445 NTSTATUS WINAPI
wow64_NtFlushProcessWriteBuffers( UINT
*args
)
447 NtFlushProcessWriteBuffers();
448 return STATUS_SUCCESS
;
452 /**********************************************************************
453 * wow64_NtGetNextThread
455 NTSTATUS WINAPI
wow64_NtGetNextThread( UINT
*args
)
457 HANDLE process
= get_handle( &args
);
458 HANDLE thread
= get_handle( &args
);
459 ACCESS_MASK access
= get_ulong( &args
);
460 ULONG attributes
= get_ulong( &args
);
461 ULONG flags
= get_ulong( &args
);
462 ULONG
*handle_ptr
= get_ptr( &args
);
468 status
= NtGetNextThread( process
, thread
, access
, attributes
, flags
, &handle
);
469 put_handle( handle_ptr
, handle
);
474 /**********************************************************************
475 * wow64_NtIsProcessInJob
477 NTSTATUS WINAPI
wow64_NtIsProcessInJob( UINT
*args
)
479 HANDLE process
= get_handle( &args
);
480 HANDLE job
= get_handle( &args
);
482 return NtIsProcessInJob( process
, job
);
486 /**********************************************************************
487 * wow64_NtOpenProcess
489 NTSTATUS WINAPI
wow64_NtOpenProcess( UINT
*args
)
491 ULONG
*handle_ptr
= get_ptr( &args
);
492 ACCESS_MASK access
= get_ulong( &args
);
493 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
494 CLIENT_ID32
*id32
= get_ptr( &args
);
496 struct object_attr64 attr
;
502 status
= NtOpenProcess( &handle
, access
, objattr_32to64( &attr
, attr32
), client_id_32to64( &id
, id32
));
503 put_handle( handle_ptr
, handle
);
508 /**********************************************************************
511 NTSTATUS WINAPI
wow64_NtOpenThread( UINT
*args
)
513 ULONG
*handle_ptr
= get_ptr( &args
);
514 ACCESS_MASK access
= get_ulong( &args
);
515 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
516 CLIENT_ID32
*id32
= get_ptr( &args
);
518 struct object_attr64 attr
;
524 status
= NtOpenThread( &handle
, access
, objattr_32to64( &attr
, attr32
), client_id_32to64( &id
, id32
));
525 put_handle( handle_ptr
, handle
);
530 /**********************************************************************
531 * wow64_NtQueryInformationProcess
533 NTSTATUS WINAPI
wow64_NtQueryInformationProcess( UINT
*args
)
535 HANDLE handle
= get_handle( &args
);
536 PROCESSINFOCLASS
class = get_ulong( &args
);
537 void *ptr
= get_ptr( &args
);
538 ULONG len
= get_ulong( &args
);
539 ULONG
*retlen
= get_ptr( &args
);
545 case ProcessBasicInformation
: /* PROCESS_BASIC_INFORMATION */
546 if (len
== sizeof(PROCESS_BASIC_INFORMATION32
))
548 PROCESS_BASIC_INFORMATION info
;
549 PROCESS_BASIC_INFORMATION32
*info32
= ptr
;
551 if (!(status
= NtQueryInformationProcess( handle
, class, &info
, sizeof(info
), NULL
)))
553 if (is_process_wow64( handle
))
554 info32
->PebBaseAddress
= PtrToUlong( info
.PebBaseAddress
) + 0x1000;
556 info32
->PebBaseAddress
= 0;
557 info32
->ExitStatus
= info
.ExitStatus
;
558 info32
->AffinityMask
= info
.AffinityMask
;
559 info32
->BasePriority
= info
.BasePriority
;
560 info32
->UniqueProcessId
= info
.UniqueProcessId
;
561 info32
->InheritedFromUniqueProcessId
= info
.InheritedFromUniqueProcessId
;
562 if (retlen
) *retlen
= sizeof(*info32
);
566 if (retlen
) *retlen
= sizeof(PROCESS_BASIC_INFORMATION32
);
567 return STATUS_INFO_LENGTH_MISMATCH
;
569 case ProcessIoCounters
: /* IO_COUNTERS */
570 case ProcessTimes
: /* KERNEL_USER_TIMES */
571 case ProcessDefaultHardErrorMode
: /* ULONG */
572 case ProcessPriorityClass
: /* PROCESS_PRIORITY_CLASS */
573 case ProcessHandleCount
: /* ULONG */
574 case ProcessSessionInformation
: /* ULONG */
575 case ProcessDebugFlags
: /* ULONG */
576 case ProcessExecuteFlags
: /* ULONG */
577 case ProcessCookie
: /* ULONG */
578 case ProcessCycleTime
: /* PROCESS_CYCLE_TIME_INFORMATION */
579 /* FIXME: check buffer alignment */
580 return NtQueryInformationProcess( handle
, class, ptr
, len
, retlen
);
582 case ProcessVmCounters
: /* VM_COUNTERS_EX */
583 if (len
== sizeof(VM_COUNTERS32
) || len
== sizeof(VM_COUNTERS_EX32
))
586 VM_COUNTERS_EX32
*info32
= ptr
;
588 if (!(status
= NtQueryInformationProcess( handle
, class, &info
, sizeof(info
), NULL
)))
590 put_vm_counters( info32
, &info
, len
);
591 if (retlen
) *retlen
= len
;
595 if (retlen
) *retlen
= sizeof(VM_COUNTERS_EX32
);
596 return STATUS_INFO_LENGTH_MISMATCH
;
598 case ProcessDebugPort
: /* ULONG_PTR */
599 case ProcessAffinityMask
: /* ULONG_PTR */
600 case ProcessWow64Information
: /* ULONG_PTR */
601 case ProcessDebugObjectHandle
: /* HANDLE */
602 if (len
== sizeof(ULONG
))
606 if (!(status
= NtQueryInformationProcess( handle
, class, &data
, sizeof(data
), NULL
)))
608 *(ULONG
*)ptr
= data
;
609 if (retlen
) *retlen
= sizeof(ULONG
);
611 else if (status
== STATUS_PORT_NOT_SET
) *(ULONG
*)ptr
= 0;
614 if (retlen
) *retlen
= sizeof(ULONG
);
615 return STATUS_INFO_LENGTH_MISMATCH
;
617 case ProcessImageFileName
:
618 case ProcessImageFileNameWin32
: /* UNICODE_STRING + string */
620 ULONG retsize
, size
= len
+ sizeof(UNICODE_STRING
) - sizeof(UNICODE_STRING32
);
621 UNICODE_STRING
*str
= Wow64AllocateTemp( size
);
622 UNICODE_STRING32
*str32
= ptr
;
624 if (!(status
= NtQueryInformationProcess( handle
, class, str
, size
, &retsize
)))
626 str32
->Length
= str
->Length
;
627 str32
->MaximumLength
= str
->MaximumLength
;
628 str32
->Buffer
= PtrToUlong( str32
+ 1 );
629 memcpy( str32
+ 1, str
->Buffer
, str
->MaximumLength
);
631 if (retlen
) *retlen
= retsize
+ sizeof(UNICODE_STRING32
) - sizeof(UNICODE_STRING
);
635 case ProcessImageInformation
: /* SECTION_IMAGE_INFORMATION */
636 if (len
== sizeof(SECTION_IMAGE_INFORMATION32
))
638 SECTION_IMAGE_INFORMATION info
;
639 SECTION_IMAGE_INFORMATION32
*info32
= ptr
;
641 if (!(status
= NtQueryInformationProcess( handle
, class, &info
, sizeof(info
), NULL
)))
643 put_section_image_info( info32
, &info
);
644 if (retlen
) *retlen
= sizeof(*info32
);
648 if (retlen
) *retlen
= sizeof(SECTION_IMAGE_INFORMATION32
);
649 return STATUS_INFO_LENGTH_MISMATCH
;
651 case ProcessWineLdtCopy
:
652 return STATUS_NOT_IMPLEMENTED
;
655 FIXME( "unsupported class %u\n", class );
656 return STATUS_INVALID_INFO_CLASS
;
661 /**********************************************************************
662 * wow64_NtQueryInformationThread
664 NTSTATUS WINAPI
wow64_NtQueryInformationThread( UINT
*args
)
666 HANDLE handle
= get_handle( &args
);
667 THREADINFOCLASS
class = get_ulong( &args
);
668 void *ptr
= get_ptr( &args
);
669 ULONG len
= get_ulong( &args
);
670 ULONG
*retlen
= get_ptr( &args
);
676 case ThreadBasicInformation
: /* THREAD_BASIC_INFORMATION */
678 THREAD_BASIC_INFORMATION32 info32
;
679 THREAD_BASIC_INFORMATION info
;
681 status
= NtQueryInformationThread( handle
, class, &info
, sizeof(info
), NULL
);
684 info32
.ExitStatus
= info
.ExitStatus
;
685 info32
.TebBaseAddress
= is_process_id_wow64( &info
.ClientId
) ?
686 PtrToUlong(info
.TebBaseAddress
) + 0x2000 : 0;
687 info32
.ClientId
.UniqueProcess
= HandleToULong( info
.ClientId
.UniqueProcess
);
688 info32
.ClientId
.UniqueThread
= HandleToULong( info
.ClientId
.UniqueThread
);
689 info32
.AffinityMask
= info
.AffinityMask
;
690 info32
.Priority
= info
.Priority
;
691 info32
.BasePriority
= info
.BasePriority
;
692 memcpy( ptr
, &info32
, min( len
, sizeof(info32
) ));
693 if (retlen
) *retlen
= min( len
, sizeof(info32
) );
698 case ThreadTimes
: /* KERNEL_USER_TIMES */
699 case ThreadEnableAlignmentFaultFixup
: /* set only */
700 case ThreadAmILastThread
: /* ULONG */
701 case ThreadIsIoPending
: /* ULONG */
702 case ThreadHideFromDebugger
: /* BOOLEAN */
703 case ThreadSuspendCount
: /* ULONG */
704 case ThreadPriorityBoost
: /* ULONG */
705 /* FIXME: check buffer alignment */
706 return NtQueryInformationThread( handle
, class, ptr
, len
, retlen
);
708 case ThreadAffinityMask
: /* ULONG_PTR */
709 case ThreadQuerySetWin32StartAddress
: /* PRTL_THREAD_START_ROUTINE */
713 status
= NtQueryInformationThread( handle
, class, &data
, sizeof(data
), NULL
);
716 memcpy( ptr
, &data
, min( len
, sizeof(ULONG
) ));
717 if (retlen
) *retlen
= min( len
, sizeof(ULONG
) );
722 case ThreadDescriptorTableEntry
: /* THREAD_DESCRIPTOR_INFORMATION */
723 return RtlWow64GetThreadSelectorEntry( handle
, ptr
, len
, retlen
);
725 case ThreadWow64Context
: /* WOW64_CONTEXT* */
726 return STATUS_INVALID_INFO_CLASS
;
728 case ThreadGroupInformation
: /* GROUP_AFFINITY */
732 status
= NtQueryInformationThread( handle
, class, &info
, sizeof(info
), NULL
);
735 GROUP_AFFINITY32 info32
= { info
.Mask
, info
.Group
};
736 memcpy( ptr
, &info32
, min( len
, sizeof(info32
) ));
737 if (retlen
) *retlen
= min( len
, sizeof(info32
) );
742 case ThreadNameInformation
: /* THREAD_NAME_INFORMATION */
744 THREAD_NAME_INFORMATION
*info
;
745 THREAD_NAME_INFORMATION32
*info32
= ptr
;
746 ULONG size
, ret_size
;
748 if (len
>= sizeof(*info32
))
750 size
= sizeof(*info
) + len
- sizeof(*info32
);
751 info
= Wow64AllocateTemp( size
);
752 status
= NtQueryInformationThread( handle
, class, info
, size
, &ret_size
);
755 info32
->ThreadName
.Length
= info
->ThreadName
.Length
;
756 info32
->ThreadName
.MaximumLength
= info
->ThreadName
.MaximumLength
;
757 info32
->ThreadName
.Buffer
= PtrToUlong( info32
+ 1 );
758 memcpy( info32
+ 1, info
+ 1, min( len
, info
->ThreadName
.MaximumLength
));
761 else status
= NtQueryInformationThread( handle
, class, NULL
, 0, &ret_size
);
763 if (retlen
&& (status
== STATUS_SUCCESS
|| status
== STATUS_BUFFER_TOO_SMALL
))
764 *retlen
= sizeof(*info32
) + ret_size
- sizeof(*info
);
769 FIXME( "unsupported class %u\n", class );
770 return STATUS_INVALID_INFO_CLASS
;
775 /**********************************************************************
776 * wow64_NtQueueApcThread
778 NTSTATUS WINAPI
wow64_NtQueueApcThread( UINT
*args
)
780 HANDLE handle
= get_handle( &args
);
781 ULONG func
= get_ulong( &args
);
782 ULONG arg1
= get_ulong( &args
);
783 ULONG arg2
= get_ulong( &args
);
784 ULONG arg3
= get_ulong( &args
);
786 return NtQueueApcThread( handle
, apc_32to64( func
),
787 (ULONG_PTR
)apc_param_32to64( func
, arg1
), arg2
, arg3
);
791 /**********************************************************************
792 * wow64_NtRemoveProcessDebug
794 NTSTATUS WINAPI
wow64_NtRemoveProcessDebug( UINT
*args
)
796 HANDLE process
= get_handle( &args
);
797 HANDLE debug
= get_handle( &args
);
799 return NtRemoveProcessDebug( process
, debug
);
803 /**********************************************************************
804 * wow64_NtResumeProcess
806 NTSTATUS WINAPI
wow64_NtResumeProcess( UINT
*args
)
808 HANDLE handle
= get_handle( &args
);
810 return NtResumeProcess( handle
);
814 /**********************************************************************
815 * wow64_NtResumeThread
817 NTSTATUS WINAPI
wow64_NtResumeThread( UINT
*args
)
819 HANDLE handle
= get_handle( &args
);
820 ULONG
*count
= get_ptr( &args
);
822 return NtResumeThread( handle
, count
);
826 /**********************************************************************
827 * wow64_NtSetInformationProcess
829 NTSTATUS WINAPI
wow64_NtSetInformationProcess( UINT
*args
)
831 HANDLE handle
= get_handle( &args
);
832 PROCESSINFOCLASS
class = get_ulong( &args
);
833 void *ptr
= get_ptr( &args
);
834 ULONG len
= get_ulong( &args
);
840 case ProcessDefaultHardErrorMode
: /* ULONG */
841 case ProcessPriorityClass
: /* PROCESS_PRIORITY_CLASS */
842 case ProcessExecuteFlags
: /* ULONG */
843 case ProcessPagePriority
: /* MEMORY_PRIORITY_INFORMATION */
844 case ProcessPowerThrottlingState
: /* PROCESS_POWER_THROTTLING_STATE */
845 case ProcessLeapSecondInformation
: /* PROCESS_LEAP_SECOND_INFO */
846 return NtSetInformationProcess( handle
, class, ptr
, len
);
848 case ProcessAffinityMask
: /* ULONG_PTR */
849 if (len
== sizeof(ULONG
))
851 ULONG_PTR mask
= *(ULONG
*)ptr
;
852 return NtSetInformationProcess( handle
, class, &mask
, sizeof(mask
) );
854 else return STATUS_INVALID_PARAMETER
;
856 case ProcessInstrumentationCallback
: /* PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION */
857 if (len
== sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION32
))
859 FIXME( "ProcessInstrumentationCallback stub\n" );
860 return STATUS_SUCCESS
;
862 else return STATUS_INFO_LENGTH_MISMATCH
;
864 case ProcessThreadStackAllocation
: /* PROCESS_STACK_ALLOCATION_INFORMATION(_EX) */
865 if (len
== sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX32
))
867 PROCESS_STACK_ALLOCATION_INFORMATION_EX32
*stack
= ptr
;
868 PROCESS_STACK_ALLOCATION_INFORMATION_EX info
;
870 info
.PreferredNode
= stack
->PreferredNode
;
871 info
.Reserved0
= stack
->Reserved0
;
872 info
.Reserved1
= stack
->Reserved1
;
873 info
.Reserved2
= stack
->Reserved2
;
874 info
.AllocInfo
.ReserveSize
= stack
->AllocInfo
.ReserveSize
;
875 info
.AllocInfo
.ZeroBits
= get_zero_bits( stack
->AllocInfo
.ZeroBits
);
876 if (!(status
= NtSetInformationProcess( handle
, class, &info
, sizeof(info
) )))
877 stack
->AllocInfo
.StackBase
= PtrToUlong( info
.AllocInfo
.StackBase
);
880 else if (len
== sizeof(PROCESS_STACK_ALLOCATION_INFORMATION32
))
882 PROCESS_STACK_ALLOCATION_INFORMATION32
*stack
= ptr
;
883 PROCESS_STACK_ALLOCATION_INFORMATION info
;
885 info
.ReserveSize
= stack
->ReserveSize
;
886 info
.ZeroBits
= get_zero_bits( stack
->ZeroBits
);
887 if (!(status
= NtSetInformationProcess( handle
, class, &info
, sizeof(info
) )))
888 stack
->StackBase
= PtrToUlong( info
.StackBase
);
891 else return STATUS_INFO_LENGTH_MISMATCH
;
893 case ProcessWineMakeProcessSystem
: /* HANDLE* */
894 if (len
== sizeof(ULONG
))
897 status
= NtSetInformationProcess( handle
, class, &event
, sizeof(HANDLE
*) );
898 put_handle( ptr
, event
);
901 else return STATUS_INFO_LENGTH_MISMATCH
;
904 FIXME( "unsupported class %u\n", class );
905 return STATUS_INVALID_INFO_CLASS
;
910 /**********************************************************************
911 * wow64_NtSetInformationThread
913 NTSTATUS WINAPI
wow64_NtSetInformationThread( UINT
*args
)
915 HANDLE handle
= get_handle( &args
);
916 THREADINFOCLASS
class = get_ulong( &args
);
917 void *ptr
= get_ptr( &args
);
918 ULONG len
= get_ulong( &args
);
922 case ThreadZeroTlsCell
: /* ULONG */
923 case ThreadBasePriority
: /* ULONG */
924 case ThreadHideFromDebugger
: /* void */
925 case ThreadEnableAlignmentFaultFixup
: /* BOOLEAN */
926 case ThreadPowerThrottlingState
: /* THREAD_POWER_THROTTLING_STATE */
927 case ThreadIdealProcessor
: /* ULONG */
928 case ThreadPriorityBoost
: /* ULONG */
929 return NtSetInformationThread( handle
, class, ptr
, len
);
931 case ThreadImpersonationToken
: /* HANDLE */
932 if (len
== sizeof(ULONG
))
934 HANDLE token
= LongToHandle( *(ULONG
*)ptr
);
935 return NtSetInformationThread( handle
, class, &token
, sizeof(token
) );
937 else return STATUS_INVALID_PARAMETER
;
939 case ThreadAffinityMask
: /* ULONG_PTR */
940 case ThreadQuerySetWin32StartAddress
: /* PRTL_THREAD_START_ROUTINE */
941 if (len
== sizeof(ULONG
))
943 ULONG_PTR mask
= *(ULONG
*)ptr
;
944 return NtSetInformationThread( handle
, class, &mask
, sizeof(mask
) );
946 else return STATUS_INVALID_PARAMETER
;
948 case ThreadWow64Context
: /* WOW64_CONTEXT* */
949 return STATUS_INVALID_INFO_CLASS
;
951 case ThreadGroupInformation
: /* GROUP_AFFINITY */
952 if (len
== sizeof(GROUP_AFFINITY32
))
954 GROUP_AFFINITY32
*info32
= ptr
;
955 GROUP_AFFINITY info
= { info32
->Mask
, info32
->Group
};
957 return NtSetInformationThread( handle
, class, &info
, sizeof(info
) );
959 else return STATUS_INVALID_PARAMETER
;
961 case ThreadNameInformation
: /* THREAD_NAME_INFORMATION */
962 case ThreadWineNativeThreadName
:
963 if (len
== sizeof(THREAD_NAME_INFORMATION32
))
965 THREAD_NAME_INFORMATION32
*info32
= ptr
;
966 THREAD_NAME_INFORMATION info
;
968 if (!unicode_str_32to64( &info
.ThreadName
, &info32
->ThreadName
))
969 return STATUS_ACCESS_VIOLATION
;
970 return NtSetInformationThread( handle
, class, &info
, sizeof(info
) );
972 else return STATUS_INFO_LENGTH_MISMATCH
;
975 FIXME( "unsupported class %u\n", class );
976 return STATUS_INVALID_INFO_CLASS
;
981 /**********************************************************************
982 * wow64_NtSetThreadExecutionState
984 NTSTATUS WINAPI
wow64_NtSetThreadExecutionState( UINT
*args
)
986 EXECUTION_STATE new_state
= get_ulong( &args
);
987 EXECUTION_STATE
*old_state
= get_ptr( &args
);
989 return NtSetThreadExecutionState( new_state
, old_state
);
993 /**********************************************************************
994 * wow64_NtSuspendProcess
996 NTSTATUS WINAPI
wow64_NtSuspendProcess( UINT
*args
)
998 HANDLE handle
= get_handle( &args
);
1000 return NtSuspendProcess( handle
);
1004 /**********************************************************************
1005 * wow64_NtSuspendThread
1007 NTSTATUS WINAPI
wow64_NtSuspendThread( UINT
*args
)
1009 HANDLE handle
= get_handle( &args
);
1010 ULONG
*count
= get_ptr( &args
);
1012 return NtSuspendThread( handle
, count
);
1016 /**********************************************************************
1017 * wow64_NtTerminateProcess
1019 NTSTATUS WINAPI
wow64_NtTerminateProcess( UINT
*args
)
1021 HANDLE handle
= get_handle( &args
);
1022 LONG exit_code
= get_ulong( &args
);
1024 return NtTerminateProcess( handle
, exit_code
);
1028 /**********************************************************************
1029 * wow64_NtTerminateThread
1031 NTSTATUS WINAPI
wow64_NtTerminateThread( UINT
*args
)
1033 HANDLE handle
= get_handle( &args
);
1034 LONG exit_code
= get_ulong( &args
);
1036 return NtTerminateThread( handle
, exit_code
);