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