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_NtFlushProcessWriteBuffers
432 NTSTATUS WINAPI
wow64_NtFlushProcessWriteBuffers( UINT
*args
)
434 NtFlushProcessWriteBuffers();
435 return STATUS_SUCCESS
;
439 /**********************************************************************
440 * wow64_NtGetNextThread
442 NTSTATUS WINAPI
wow64_NtGetNextThread( UINT
*args
)
444 HANDLE process
= get_handle( &args
);
445 HANDLE thread
= get_handle( &args
);
446 ACCESS_MASK access
= get_ulong( &args
);
447 ULONG attributes
= get_ulong( &args
);
448 ULONG flags
= get_ulong( &args
);
449 ULONG
*handle_ptr
= get_ptr( &args
);
455 status
= NtGetNextThread( process
, thread
, access
, attributes
, flags
, &handle
);
456 put_handle( handle_ptr
, handle
);
461 /**********************************************************************
462 * wow64_NtIsProcessInJob
464 NTSTATUS WINAPI
wow64_NtIsProcessInJob( UINT
*args
)
466 HANDLE process
= get_handle( &args
);
467 HANDLE job
= get_handle( &args
);
469 return NtIsProcessInJob( process
, job
);
473 /**********************************************************************
474 * wow64_NtOpenProcess
476 NTSTATUS WINAPI
wow64_NtOpenProcess( UINT
*args
)
478 ULONG
*handle_ptr
= get_ptr( &args
);
479 ACCESS_MASK access
= get_ulong( &args
);
480 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
481 CLIENT_ID32
*id32
= get_ptr( &args
);
483 struct object_attr64 attr
;
489 status
= NtOpenProcess( &handle
, access
, objattr_32to64( &attr
, attr32
), client_id_32to64( &id
, id32
));
490 put_handle( handle_ptr
, handle
);
495 /**********************************************************************
498 NTSTATUS WINAPI
wow64_NtOpenThread( UINT
*args
)
500 ULONG
*handle_ptr
= get_ptr( &args
);
501 ACCESS_MASK access
= get_ulong( &args
);
502 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
503 CLIENT_ID32
*id32
= get_ptr( &args
);
505 struct object_attr64 attr
;
511 status
= NtOpenThread( &handle
, access
, objattr_32to64( &attr
, attr32
), client_id_32to64( &id
, id32
));
512 put_handle( handle_ptr
, handle
);
517 /**********************************************************************
518 * wow64_NtQueryInformationProcess
520 NTSTATUS WINAPI
wow64_NtQueryInformationProcess( UINT
*args
)
522 HANDLE handle
= get_handle( &args
);
523 PROCESSINFOCLASS
class = get_ulong( &args
);
524 void *ptr
= get_ptr( &args
);
525 ULONG len
= get_ulong( &args
);
526 ULONG
*retlen
= get_ptr( &args
);
532 case ProcessBasicInformation
: /* PROCESS_BASIC_INFORMATION */
533 if (len
== sizeof(PROCESS_BASIC_INFORMATION32
))
535 PROCESS_BASIC_INFORMATION info
;
536 PROCESS_BASIC_INFORMATION32
*info32
= ptr
;
538 if (!(status
= NtQueryInformationProcess( handle
, class, &info
, sizeof(info
), NULL
)))
540 if (is_process_wow64( handle
))
541 info32
->PebBaseAddress
= PtrToUlong( info
.PebBaseAddress
) + 0x1000;
543 info32
->PebBaseAddress
= 0;
544 info32
->ExitStatus
= info
.ExitStatus
;
545 info32
->AffinityMask
= info
.AffinityMask
;
546 info32
->BasePriority
= info
.BasePriority
;
547 info32
->UniqueProcessId
= info
.UniqueProcessId
;
548 info32
->InheritedFromUniqueProcessId
= info
.InheritedFromUniqueProcessId
;
549 if (retlen
) *retlen
= sizeof(*info32
);
553 if (retlen
) *retlen
= sizeof(PROCESS_BASIC_INFORMATION32
);
554 return STATUS_INFO_LENGTH_MISMATCH
;
556 case ProcessIoCounters
: /* IO_COUNTERS */
557 case ProcessTimes
: /* KERNEL_USER_TIMES */
558 case ProcessDefaultHardErrorMode
: /* ULONG */
559 case ProcessPriorityClass
: /* PROCESS_PRIORITY_CLASS */
560 case ProcessHandleCount
: /* ULONG */
561 case ProcessSessionInformation
: /* ULONG */
562 case ProcessDebugFlags
: /* ULONG */
563 case ProcessExecuteFlags
: /* ULONG */
564 case ProcessCookie
: /* ULONG */
565 case ProcessCycleTime
: /* PROCESS_CYCLE_TIME_INFORMATION */
566 /* FIXME: check buffer alignment */
567 return NtQueryInformationProcess( handle
, class, ptr
, len
, retlen
);
569 case ProcessVmCounters
: /* VM_COUNTERS_EX */
570 if (len
== sizeof(VM_COUNTERS32
) || len
== sizeof(VM_COUNTERS_EX32
))
573 VM_COUNTERS_EX32
*info32
= ptr
;
575 if (!(status
= NtQueryInformationProcess( handle
, class, &info
, sizeof(info
), NULL
)))
577 put_vm_counters( info32
, &info
, len
);
578 if (retlen
) *retlen
= len
;
582 if (retlen
) *retlen
= sizeof(VM_COUNTERS_EX32
);
583 return STATUS_INFO_LENGTH_MISMATCH
;
585 case ProcessDebugPort
: /* ULONG_PTR */
586 case ProcessAffinityMask
: /* ULONG_PTR */
587 case ProcessWow64Information
: /* ULONG_PTR */
588 case ProcessDebugObjectHandle
: /* HANDLE */
589 if (len
== sizeof(ULONG
))
593 if (!(status
= NtQueryInformationProcess( handle
, class, &data
, sizeof(data
), NULL
)))
595 *(ULONG
*)ptr
= data
;
596 if (retlen
) *retlen
= sizeof(ULONG
);
598 else if (status
== STATUS_PORT_NOT_SET
)
601 if (retlen
) *retlen
= sizeof(ULONG
);
605 return STATUS_INFO_LENGTH_MISMATCH
;
607 case ProcessImageFileName
:
608 case ProcessImageFileNameWin32
: /* UNICODE_STRING + string */
610 ULONG retsize
, size
= len
+ sizeof(UNICODE_STRING
) - sizeof(UNICODE_STRING32
);
611 UNICODE_STRING
*str
= Wow64AllocateTemp( size
);
612 UNICODE_STRING32
*str32
= ptr
;
614 if (!(status
= NtQueryInformationProcess( handle
, class, str
, size
, &retsize
)))
616 str32
->Length
= str
->Length
;
617 str32
->MaximumLength
= str
->MaximumLength
;
618 str32
->Buffer
= PtrToUlong( str32
+ 1 );
619 memcpy( str32
+ 1, str
->Buffer
, str
->MaximumLength
);
621 if (retlen
) *retlen
= retsize
+ sizeof(UNICODE_STRING32
) - sizeof(UNICODE_STRING
);
625 case ProcessImageInformation
: /* SECTION_IMAGE_INFORMATION */
626 if (len
== sizeof(SECTION_IMAGE_INFORMATION32
))
628 SECTION_IMAGE_INFORMATION info
;
629 SECTION_IMAGE_INFORMATION32
*info32
= ptr
;
631 if (!(status
= NtQueryInformationProcess( handle
, class, &info
, sizeof(info
), NULL
)))
633 put_section_image_info( info32
, &info
);
634 if (retlen
) *retlen
= sizeof(*info32
);
638 if (retlen
) *retlen
= sizeof(SECTION_IMAGE_INFORMATION32
);
639 return STATUS_INFO_LENGTH_MISMATCH
;
641 case ProcessWineLdtCopy
:
642 return STATUS_NOT_IMPLEMENTED
;
645 FIXME( "unsupported class %u\n", class );
646 return STATUS_INVALID_INFO_CLASS
;
651 /**********************************************************************
652 * wow64_NtQueryInformationThread
654 NTSTATUS WINAPI
wow64_NtQueryInformationThread( UINT
*args
)
656 HANDLE handle
= get_handle( &args
);
657 THREADINFOCLASS
class = get_ulong( &args
);
658 void *ptr
= get_ptr( &args
);
659 ULONG len
= get_ulong( &args
);
660 ULONG
*retlen
= get_ptr( &args
);
666 case ThreadBasicInformation
: /* THREAD_BASIC_INFORMATION */
668 THREAD_BASIC_INFORMATION32 info32
;
669 THREAD_BASIC_INFORMATION info
;
671 status
= NtQueryInformationThread( handle
, class, &info
, sizeof(info
), NULL
);
674 info32
.ExitStatus
= info
.ExitStatus
;
675 info32
.TebBaseAddress
= is_process_id_wow64( &info
.ClientId
) ?
676 PtrToUlong(info
.TebBaseAddress
) + 0x2000 : 0;
677 info32
.ClientId
.UniqueProcess
= HandleToULong( info
.ClientId
.UniqueProcess
);
678 info32
.ClientId
.UniqueThread
= HandleToULong( info
.ClientId
.UniqueThread
);
679 info32
.AffinityMask
= info
.AffinityMask
;
680 info32
.Priority
= info
.Priority
;
681 info32
.BasePriority
= info
.BasePriority
;
682 memcpy( ptr
, &info32
, min( len
, sizeof(info32
) ));
683 if (retlen
) *retlen
= min( len
, sizeof(info32
) );
688 case ThreadTimes
: /* KERNEL_USER_TIMES */
689 case ThreadEnableAlignmentFaultFixup
: /* set only */
690 case ThreadAmILastThread
: /* ULONG */
691 case ThreadIsIoPending
: /* ULONG */
692 case ThreadHideFromDebugger
: /* BOOLEAN */
693 case ThreadSuspendCount
: /* ULONG */
694 case ThreadPriorityBoost
: /* ULONG */
695 /* FIXME: check buffer alignment */
696 return NtQueryInformationThread( handle
, class, ptr
, len
, retlen
);
698 case ThreadAffinityMask
: /* ULONG_PTR */
699 case ThreadQuerySetWin32StartAddress
: /* PRTL_THREAD_START_ROUTINE */
703 status
= NtQueryInformationThread( handle
, class, &data
, sizeof(data
), NULL
);
706 memcpy( ptr
, &data
, min( len
, sizeof(ULONG
) ));
707 if (retlen
) *retlen
= min( len
, sizeof(ULONG
) );
712 case ThreadDescriptorTableEntry
: /* THREAD_DESCRIPTOR_INFORMATION */
713 return RtlWow64GetThreadSelectorEntry( handle
, ptr
, len
, retlen
);
715 case ThreadWow64Context
: /* WOW64_CONTEXT* */
716 return STATUS_INVALID_INFO_CLASS
;
718 case ThreadGroupInformation
: /* GROUP_AFFINITY */
722 status
= NtQueryInformationThread( handle
, class, &info
, sizeof(info
), NULL
);
725 GROUP_AFFINITY32 info32
= { info
.Mask
, info
.Group
};
726 memcpy( ptr
, &info32
, min( len
, sizeof(info32
) ));
727 if (retlen
) *retlen
= min( len
, sizeof(info32
) );
732 case ThreadNameInformation
: /* THREAD_NAME_INFORMATION */
734 THREAD_NAME_INFORMATION
*info
;
735 THREAD_NAME_INFORMATION32
*info32
= ptr
;
736 ULONG size
, ret_size
;
738 if (len
>= sizeof(*info32
))
740 size
= sizeof(*info
) + len
- sizeof(*info32
);
741 info
= Wow64AllocateTemp( size
);
742 status
= NtQueryInformationThread( handle
, class, info
, size
, &ret_size
);
745 info32
->ThreadName
.Length
= info
->ThreadName
.Length
;
746 info32
->ThreadName
.MaximumLength
= info
->ThreadName
.MaximumLength
;
747 info32
->ThreadName
.Buffer
= PtrToUlong( info32
+ 1 );
748 memcpy( info32
+ 1, info
+ 1, min( len
, info
->ThreadName
.MaximumLength
));
751 else status
= NtQueryInformationThread( handle
, class, NULL
, 0, &ret_size
);
753 if (retlen
&& (status
== STATUS_SUCCESS
|| status
== STATUS_BUFFER_TOO_SMALL
))
754 *retlen
= sizeof(*info32
) + ret_size
- sizeof(*info
);
759 FIXME( "unsupported class %u\n", class );
760 return STATUS_INVALID_INFO_CLASS
;
765 /**********************************************************************
766 * wow64_NtQueueApcThread
768 NTSTATUS WINAPI
wow64_NtQueueApcThread( UINT
*args
)
770 HANDLE handle
= get_handle( &args
);
771 ULONG func
= get_ulong( &args
);
772 ULONG arg1
= get_ulong( &args
);
773 ULONG arg2
= get_ulong( &args
);
774 ULONG arg3
= get_ulong( &args
);
776 return NtQueueApcThread( handle
, apc_32to64( func
),
777 (ULONG_PTR
)apc_param_32to64( func
, arg1
), arg2
, arg3
);
781 /**********************************************************************
782 * wow64_NtRemoveProcessDebug
784 NTSTATUS WINAPI
wow64_NtRemoveProcessDebug( UINT
*args
)
786 HANDLE process
= get_handle( &args
);
787 HANDLE debug
= get_handle( &args
);
789 return NtRemoveProcessDebug( process
, debug
);
793 /**********************************************************************
794 * wow64_NtResumeProcess
796 NTSTATUS WINAPI
wow64_NtResumeProcess( UINT
*args
)
798 HANDLE handle
= get_handle( &args
);
800 return NtResumeProcess( handle
);
804 /**********************************************************************
805 * wow64_NtResumeThread
807 NTSTATUS WINAPI
wow64_NtResumeThread( UINT
*args
)
809 HANDLE handle
= get_handle( &args
);
810 ULONG
*count
= get_ptr( &args
);
812 return NtResumeThread( handle
, count
);
816 /**********************************************************************
817 * wow64_NtSetInformationProcess
819 NTSTATUS WINAPI
wow64_NtSetInformationProcess( UINT
*args
)
821 HANDLE handle
= get_handle( &args
);
822 PROCESSINFOCLASS
class = get_ulong( &args
);
823 void *ptr
= get_ptr( &args
);
824 ULONG len
= get_ulong( &args
);
830 case ProcessDefaultHardErrorMode
: /* ULONG */
831 case ProcessPriorityClass
: /* PROCESS_PRIORITY_CLASS */
832 case ProcessExecuteFlags
: /* ULONG */
833 case ProcessPagePriority
: /* MEMORY_PRIORITY_INFORMATION */
834 case ProcessPowerThrottlingState
: /* PROCESS_POWER_THROTTLING_STATE */
835 case ProcessLeapSecondInformation
: /* PROCESS_LEAP_SECOND_INFO */
836 return NtSetInformationProcess( handle
, class, ptr
, len
);
838 case ProcessAffinityMask
: /* ULONG_PTR */
839 if (len
== sizeof(ULONG
))
841 ULONG_PTR mask
= *(ULONG
*)ptr
;
842 return NtSetInformationProcess( handle
, class, &mask
, sizeof(mask
) );
844 else return STATUS_INVALID_PARAMETER
;
846 case ProcessInstrumentationCallback
: /* PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION */
847 if (len
== sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION32
))
849 FIXME( "ProcessInstrumentationCallback stub\n" );
850 return STATUS_SUCCESS
;
852 else return STATUS_INFO_LENGTH_MISMATCH
;
854 case ProcessThreadStackAllocation
: /* PROCESS_STACK_ALLOCATION_INFORMATION(_EX) */
855 if (len
== sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX32
))
857 PROCESS_STACK_ALLOCATION_INFORMATION_EX32
*stack
= ptr
;
858 PROCESS_STACK_ALLOCATION_INFORMATION_EX info
;
860 info
.PreferredNode
= stack
->PreferredNode
;
861 info
.Reserved0
= stack
->Reserved0
;
862 info
.Reserved1
= stack
->Reserved1
;
863 info
.Reserved2
= stack
->Reserved2
;
864 info
.AllocInfo
.ReserveSize
= stack
->AllocInfo
.ReserveSize
;
865 info
.AllocInfo
.ZeroBits
= get_zero_bits( stack
->AllocInfo
.ZeroBits
);
866 if (!(status
= NtSetInformationProcess( handle
, class, &info
, sizeof(info
) )))
867 stack
->AllocInfo
.StackBase
= PtrToUlong( info
.AllocInfo
.StackBase
);
870 else if (len
== sizeof(PROCESS_STACK_ALLOCATION_INFORMATION32
))
872 PROCESS_STACK_ALLOCATION_INFORMATION32
*stack
= ptr
;
873 PROCESS_STACK_ALLOCATION_INFORMATION info
;
875 info
.ReserveSize
= stack
->ReserveSize
;
876 info
.ZeroBits
= get_zero_bits( stack
->ZeroBits
);
877 if (!(status
= NtSetInformationProcess( handle
, class, &info
, sizeof(info
) )))
878 stack
->StackBase
= PtrToUlong( info
.StackBase
);
881 else return STATUS_INFO_LENGTH_MISMATCH
;
883 case ProcessWineMakeProcessSystem
: /* HANDLE* */
884 if (len
== sizeof(ULONG
))
887 status
= NtSetInformationProcess( handle
, class, &event
, sizeof(HANDLE
*) );
888 put_handle( ptr
, event
);
891 else return STATUS_INFO_LENGTH_MISMATCH
;
894 FIXME( "unsupported class %u\n", class );
895 return STATUS_INVALID_INFO_CLASS
;
900 /**********************************************************************
901 * wow64_NtSetInformationThread
903 NTSTATUS WINAPI
wow64_NtSetInformationThread( UINT
*args
)
905 HANDLE handle
= get_handle( &args
);
906 THREADINFOCLASS
class = get_ulong( &args
);
907 void *ptr
= get_ptr( &args
);
908 ULONG len
= get_ulong( &args
);
912 case ThreadZeroTlsCell
: /* ULONG */
913 case ThreadBasePriority
: /* ULONG */
914 case ThreadHideFromDebugger
: /* void */
915 case ThreadEnableAlignmentFaultFixup
: /* BOOLEAN */
916 case ThreadPowerThrottlingState
: /* THREAD_POWER_THROTTLING_STATE */
917 case ThreadIdealProcessor
: /* ULONG */
918 case ThreadPriorityBoost
: /* ULONG */
919 return NtSetInformationThread( handle
, class, ptr
, len
);
921 case ThreadImpersonationToken
: /* HANDLE */
922 if (len
== sizeof(ULONG
))
924 HANDLE token
= LongToHandle( *(ULONG
*)ptr
);
925 return NtSetInformationThread( handle
, class, &token
, sizeof(token
) );
927 else return STATUS_INVALID_PARAMETER
;
929 case ThreadAffinityMask
: /* ULONG_PTR */
930 case ThreadQuerySetWin32StartAddress
: /* PRTL_THREAD_START_ROUTINE */
931 if (len
== sizeof(ULONG
))
933 ULONG_PTR mask
= *(ULONG
*)ptr
;
934 return NtSetInformationThread( handle
, class, &mask
, sizeof(mask
) );
936 else return STATUS_INVALID_PARAMETER
;
938 case ThreadWow64Context
: /* WOW64_CONTEXT* */
939 return STATUS_INVALID_INFO_CLASS
;
941 case ThreadGroupInformation
: /* GROUP_AFFINITY */
942 if (len
== sizeof(GROUP_AFFINITY32
))
944 GROUP_AFFINITY32
*info32
= ptr
;
945 GROUP_AFFINITY info
= { info32
->Mask
, info32
->Group
};
947 return NtSetInformationThread( handle
, class, &info
, sizeof(info
) );
949 else return STATUS_INVALID_PARAMETER
;
951 case ThreadNameInformation
: /* THREAD_NAME_INFORMATION */
952 case ThreadWineNativeThreadName
:
953 if (len
== sizeof(THREAD_NAME_INFORMATION32
))
955 THREAD_NAME_INFORMATION32
*info32
= ptr
;
956 THREAD_NAME_INFORMATION info
;
958 if (!unicode_str_32to64( &info
.ThreadName
, &info32
->ThreadName
))
959 return STATUS_ACCESS_VIOLATION
;
960 return NtSetInformationThread( handle
, class, &info
, sizeof(info
) );
962 else return STATUS_INFO_LENGTH_MISMATCH
;
965 FIXME( "unsupported class %u\n", class );
966 return STATUS_INVALID_INFO_CLASS
;
971 /**********************************************************************
972 * wow64_NtSetThreadExecutionState
974 NTSTATUS WINAPI
wow64_NtSetThreadExecutionState( UINT
*args
)
976 EXECUTION_STATE new_state
= get_ulong( &args
);
977 EXECUTION_STATE
*old_state
= get_ptr( &args
);
979 return NtSetThreadExecutionState( new_state
, old_state
);
983 /**********************************************************************
984 * wow64_NtSuspendProcess
986 NTSTATUS WINAPI
wow64_NtSuspendProcess( UINT
*args
)
988 HANDLE handle
= get_handle( &args
);
990 return NtSuspendProcess( handle
);
994 /**********************************************************************
995 * wow64_NtSuspendThread
997 NTSTATUS WINAPI
wow64_NtSuspendThread( UINT
*args
)
999 HANDLE handle
= get_handle( &args
);
1000 ULONG
*count
= get_ptr( &args
);
1002 return NtSuspendThread( handle
, count
);
1006 /**********************************************************************
1007 * wow64_NtTerminateProcess
1009 NTSTATUS WINAPI
wow64_NtTerminateProcess( UINT
*args
)
1011 HANDLE handle
= get_handle( &args
);
1012 LONG exit_code
= get_ulong( &args
);
1014 return NtTerminateProcess( handle
, exit_code
);
1018 /**********************************************************************
1019 * wow64_NtTerminateThread
1021 NTSTATUS WINAPI
wow64_NtTerminateThread( UINT
*args
)
1023 HANDLE handle
= get_handle( &args
);
1024 LONG exit_code
= get_ulong( &args
);
1026 if (pBTCpuThreadTerm
) pBTCpuThreadTerm( handle
);
1028 return NtTerminateThread( handle
, exit_code
);