2 * WoW64 virtual memory 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
30 #include "wow64_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wow
);
35 static BOOL WINAPIV
send_cross_process_notification( HANDLE process
, UINT id
, const void *addr
, SIZE_T size
,
38 CROSS_PROCESS_WORK_LIST
*list
;
39 CROSS_PROCESS_WORK_ENTRY
*entry
;
45 RtlOpenCrossProcessEmulatorWorkConnection( process
, §ion
, (void **)&list
);
46 if (!list
) return FALSE
;
47 if ((entry
= RtlWow64PopCrossProcessWorkFromFreeList( &list
->free_list
)))
50 entry
->addr
= (ULONG_PTR
)addr
;
54 va_start( args
, nb_args
);
55 for (i
= 0; i
< nb_args
; i
++) entry
->args
[i
] = va_arg( args
, int );
58 RtlWow64PushCrossProcessWorkOntoWorkList( &list
->work_list
, entry
, &unused
);
60 NtUnmapViewOfSection( GetCurrentProcess(), list
);
66 static MEMORY_RANGE_ENTRY
*memory_range_entry_array_32to64( const MEMORY_RANGE_ENTRY32
*addresses32
,
69 MEMORY_RANGE_ENTRY
*addresses
= Wow64AllocateTemp( sizeof(MEMORY_RANGE_ENTRY
) * count
);
72 for (i
= 0; i
< count
; i
++)
74 addresses
[i
].VirtualAddress
= ULongToPtr( addresses32
[i
].VirtualAddress
);
75 addresses
[i
].NumberOfBytes
= addresses32
[i
].NumberOfBytes
;
81 static NTSTATUS
mem_extended_parameters_32to64( MEM_EXTENDED_PARAMETER
**ret_params
,
82 const MEM_EXTENDED_PARAMETER32
*params32
, ULONG
*count
,
86 MEM_EXTENDED_PARAMETER
*params
;
87 MEM_ADDRESS_REQUIREMENTS
*req
;
88 MEM_ADDRESS_REQUIREMENTS32
*req32
= NULL
;
90 if (*count
&& !params32
) return STATUS_INVALID_PARAMETER
;
92 params
= Wow64AllocateTemp( (*count
+ 1) * sizeof(*params
) + sizeof(*req
) );
93 req
= (MEM_ADDRESS_REQUIREMENTS
*)(params
+ *count
+ 1);
95 for (i
= 0; i
< *count
; i
++)
97 params
[i
].Type
= params32
[i
].Type
;
98 params
[i
].Reserved
= 0;
99 switch (params
[i
].Type
)
101 case MemExtendedParameterAddressRequirements
:
102 req32
= ULongToPtr( params32
[i
].Pointer
);
103 params
[i
].Pointer
= req
;
105 case MemExtendedParameterAttributeFlags
:
106 case MemExtendedParameterNumaNode
:
107 case MemExtendedParameterImageMachine
:
108 params
[i
].ULong
= params32
[i
].ULong
;
110 case MemExtendedParameterPartitionHandle
:
111 case MemExtendedParameterUserPhysicalHandle
:
112 params
[i
].Handle
= ULongToHandle( params32
[i
].Handle
);
119 if (req32
->HighestEndingAddress
> highest_user_address
) return STATUS_INVALID_PARAMETER
;
120 req
->LowestStartingAddress
= ULongToPtr( req32
->LowestStartingAddress
);
121 req
->HighestEndingAddress
= ULongToPtr( req32
->HighestEndingAddress
);
122 req
->Alignment
= req32
->Alignment
;
126 req
->LowestStartingAddress
= NULL
;
127 req
->HighestEndingAddress
= (void *)highest_user_address
;
130 params
[i
].Type
= MemExtendedParameterAddressRequirements
;
131 params
[i
].Reserved
= 0;
132 params
[i
].Pointer
= req
;
135 *ret_params
= params
;
136 return STATUS_SUCCESS
;
139 /**********************************************************************
140 * wow64_NtAllocateVirtualMemory
142 NTSTATUS WINAPI
wow64_NtAllocateVirtualMemory( UINT
*args
)
144 HANDLE process
= get_handle( &args
);
145 ULONG
*addr32
= get_ptr( &args
);
146 ULONG_PTR zero_bits
= get_ulong( &args
);
147 ULONG
*size32
= get_ptr( &args
);
148 ULONG type
= get_ulong( &args
);
149 ULONG protect
= get_ulong( &args
);
151 void *addr
= ULongToPtr( *addr32
);
152 SIZE_T size
= *size32
;
153 BOOL is_current
= RtlIsCurrentProcess( process
);
156 if (!addr
&& (type
& MEM_COMMIT
)) type
|= MEM_RESERVE
;
158 if (!is_current
) send_cross_process_notification( process
, CrossProcessPreVirtualAlloc
,
159 addr
, size
, 3, type
, protect
, 0 );
160 else if (pBTCpuNotifyMemoryAlloc
) pBTCpuNotifyMemoryAlloc( addr
, size
, type
, protect
, FALSE
, 0 );
162 status
= NtAllocateVirtualMemory( process
, &addr
, get_zero_bits( zero_bits
), &size
, type
, protect
);
164 if (!is_current
) send_cross_process_notification( process
, CrossProcessPostVirtualAlloc
,
165 addr
, size
, 3, type
, protect
, status
);
166 else if (pBTCpuNotifyMemoryAlloc
) pBTCpuNotifyMemoryAlloc( addr
, size
, type
, protect
, TRUE
, status
);
170 put_addr( addr32
, addr
);
171 put_size( size32
, size
);
177 /**********************************************************************
178 * wow64_NtAllocateVirtualMemoryEx
180 NTSTATUS WINAPI
wow64_NtAllocateVirtualMemoryEx( UINT
*args
)
182 HANDLE process
= get_handle( &args
);
183 ULONG
*addr32
= get_ptr( &args
);
184 ULONG
*size32
= get_ptr( &args
);
185 ULONG type
= get_ulong( &args
);
186 ULONG protect
= get_ulong( &args
);
187 MEM_EXTENDED_PARAMETER32
*params32
= get_ptr( &args
);
188 ULONG count
= get_ulong( &args
);
190 void *addr
= ULongToPtr( *addr32
);
191 SIZE_T size
= *size32
;
193 MEM_EXTENDED_PARAMETER
*params64
;
194 BOOL is_current
= RtlIsCurrentProcess( process
);
195 BOOL set_limit
= (!*addr32
&& is_current
);
197 if (!addr
) type
|= MEM_RESERVE
;
199 if ((status
= mem_extended_parameters_32to64( ¶ms64
, params32
, &count
, set_limit
))) return status
;
201 if (!is_current
) send_cross_process_notification( process
, CrossProcessPreVirtualAlloc
,
202 addr
, size
, 3, type
, protect
, 0 );
203 else if (pBTCpuNotifyMemoryAlloc
) pBTCpuNotifyMemoryAlloc( addr
, size
, type
, protect
, FALSE
, 0 );
205 status
= NtAllocateVirtualMemoryEx( process
, &addr
, &size
, type
, protect
, params64
, count
);
207 if (!is_current
) send_cross_process_notification( process
, CrossProcessPostVirtualAlloc
,
208 addr
, size
, 3, type
, protect
, status
);
209 else if (pBTCpuNotifyMemoryAlloc
) pBTCpuNotifyMemoryAlloc( addr
, size
, type
, protect
, TRUE
, status
);
213 put_addr( addr32
, addr
);
214 put_size( size32
, size
);
220 /**********************************************************************
221 * wow64_NtAreMappedFilesTheSame
223 NTSTATUS WINAPI
wow64_NtAreMappedFilesTheSame( UINT
*args
)
225 void *ptr1
= get_ptr( &args
);
226 void *ptr2
= get_ptr( &args
);
228 return NtAreMappedFilesTheSame( ptr1
, ptr2
);
232 /**********************************************************************
233 * wow64_NtFlushInstructionCache
235 NTSTATUS WINAPI
wow64_NtFlushInstructionCache( UINT
*args
)
237 HANDLE process
= get_handle( &args
);
238 const void *addr
= get_ptr( &args
);
239 SIZE_T size
= get_ulong( &args
);
241 if (RtlIsCurrentProcess( process
))
243 if (pBTCpuFlushInstructionCache2
) pBTCpuFlushInstructionCache2( addr
, size
);
245 else send_cross_process_notification( process
, CrossProcessFlushCache
, addr
, size
, 0 );
247 return NtFlushInstructionCache( process
, addr
, size
);
251 /**********************************************************************
252 * wow64_NtFlushVirtualMemory
254 NTSTATUS WINAPI
wow64_NtFlushVirtualMemory( UINT
*args
)
256 HANDLE process
= get_handle( &args
);
257 ULONG
*addr32
= get_ptr( &args
);
258 ULONG
*size32
= get_ptr( &args
);
259 ULONG unknown
= get_ulong( &args
);
265 status
= NtFlushVirtualMemory( process
, (const void **)addr_32to64( &addr
, addr32
),
266 size_32to64( &size
, size32
), unknown
);
269 put_addr( addr32
, addr
);
270 put_size( size32
, size
);
276 /**********************************************************************
277 * wow64_NtFreeVirtualMemory
279 NTSTATUS WINAPI
wow64_NtFreeVirtualMemory( UINT
*args
)
281 HANDLE process
= get_handle( &args
);
282 ULONG
*addr32
= get_ptr( &args
);
283 ULONG
*size32
= get_ptr( &args
);
284 ULONG type
= get_ulong( &args
);
286 void *addr
= ULongToPtr( *addr32
);
287 SIZE_T size
= *size32
;
288 BOOL is_current
= RtlIsCurrentProcess( process
);
291 if (!is_current
) send_cross_process_notification( process
, CrossProcessPreVirtualFree
,
292 addr
, size
, 2, type
, 0 );
293 else if (pBTCpuNotifyMemoryFree
) pBTCpuNotifyMemoryFree( addr
, size
, type
, FALSE
, 0 );
295 status
= NtFreeVirtualMemory( process
, &addr
, &size
, type
);
297 if (!is_current
) send_cross_process_notification( process
, CrossProcessPostVirtualFree
,
298 addr
, size
, 2, type
, status
);
299 else if (pBTCpuNotifyMemoryFree
) pBTCpuNotifyMemoryFree( addr
, size
, type
, TRUE
, status
);
303 put_addr( addr32
, addr
);
304 put_size( size32
, size
);
310 /**********************************************************************
311 * wow64_NtGetNlsSectionPtr
313 NTSTATUS WINAPI
wow64_NtGetNlsSectionPtr( UINT
*args
)
315 ULONG type
= get_ulong( &args
);
316 ULONG id
= get_ulong( &args
);
317 void *unknown
= get_ptr( &args
);
318 ULONG
*addr32
= get_ptr( &args
);
319 ULONG
*size32
= get_ptr( &args
);
325 status
= NtGetNlsSectionPtr( type
, id
, unknown
, addr_32to64( &addr
, addr32
),
326 size_32to64( &size
, size32
));
329 put_addr( addr32
, addr
);
330 put_size( size32
, size
);
336 /**********************************************************************
337 * wow64_NtGetWriteWatch
339 NTSTATUS WINAPI
wow64_NtGetWriteWatch( UINT
*args
)
341 HANDLE handle
= get_handle( &args
);
342 ULONG flags
= get_ulong( &args
);
343 void *base
= get_ptr( &args
);
344 SIZE_T size
= get_ulong( &args
);
345 ULONG
*addr_ptr
= get_ptr( &args
);
346 ULONG
*count_ptr
= get_ptr( &args
);
347 ULONG
*granularity
= get_ptr( &args
);
349 ULONG_PTR i
, count
= *count_ptr
;
353 if (!count
|| !size
) return STATUS_INVALID_PARAMETER
;
354 if (flags
& ~WRITE_WATCH_FLAG_RESET
) return STATUS_INVALID_PARAMETER
;
355 if (!addr_ptr
) return STATUS_ACCESS_VIOLATION
;
357 addresses
= Wow64AllocateTemp( count
* sizeof(*addresses
) );
358 if (!(status
= NtGetWriteWatch( handle
, flags
, base
, size
, addresses
, &count
, granularity
)))
360 for (i
= 0; i
< count
; i
++) addr_ptr
[i
] = PtrToUlong( addresses
[i
] );
367 /**********************************************************************
368 * wow64_NtInitializeNlsFiles
370 NTSTATUS WINAPI
wow64_NtInitializeNlsFiles( UINT
*args
)
372 ULONG
*addr32
= get_ptr( &args
);
373 LCID
*lcid
= get_ptr( &args
);
374 LARGE_INTEGER
*size
= get_ptr( &args
);
379 status
= NtInitializeNlsFiles( addr_32to64( &addr
, addr32
), lcid
, size
);
380 if (!status
) put_addr( addr32
, addr
);
385 /**********************************************************************
386 * wow64_NtLockVirtualMemory
388 NTSTATUS WINAPI
wow64_NtLockVirtualMemory( UINT
*args
)
390 HANDLE process
= get_handle( &args
);
391 ULONG
*addr32
= get_ptr( &args
);
392 ULONG
*size32
= get_ptr( &args
);
393 ULONG unknown
= get_ulong( &args
);
399 status
= NtLockVirtualMemory( process
, addr_32to64( &addr
, addr32
),
400 size_32to64( &size
, size32
), unknown
);
403 put_addr( addr32
, addr
);
404 put_size( size32
, size
);
410 static void notify_map_view_of_section( HANDLE handle
, void *addr
, SIZE_T size
, ULONG alloc
,
411 ULONG protect
, NTSTATUS
*ret_status
)
413 SECTION_IMAGE_INFORMATION info
;
416 if (!NtCurrentTeb()->Tib
.ArbitraryUserPointer
) return;
417 if (NtQuerySection( handle
, SectionImageInformation
, &info
, sizeof(info
), NULL
)) return;
418 if (info
.Machine
!= current_machine
) return;
419 init_image_mapping( addr
);
420 if (!pBTCpuNotifyMapViewOfSection
) return;
421 status
= pBTCpuNotifyMapViewOfSection( NULL
, addr
, NULL
, size
, alloc
, protect
);
422 if (NT_SUCCESS(status
)) return;
423 NtUnmapViewOfSection( GetCurrentProcess(), addr
);
424 *ret_status
= status
;
427 /**********************************************************************
428 * wow64_NtMapViewOfSection
430 NTSTATUS WINAPI
wow64_NtMapViewOfSection( UINT
*args
)
432 HANDLE handle
= get_handle( &args
);
433 HANDLE process
= get_handle( &args
);
434 ULONG
*addr32
= get_ptr( &args
);
435 ULONG_PTR zero_bits
= get_ulong( &args
);
436 SIZE_T commit
= get_ulong( &args
);
437 const LARGE_INTEGER
*offset
= get_ptr( &args
);
438 ULONG
*size32
= get_ptr( &args
);
439 SECTION_INHERIT inherit
= get_ulong( &args
);
440 ULONG alloc
= get_ulong( &args
);
441 ULONG protect
= get_ulong( &args
);
446 void *prev
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
448 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ULongToPtr( NtCurrentTeb32()->Tib
.ArbitraryUserPointer
);
449 status
= NtMapViewOfSection( handle
, process
, addr_32to64( &addr
, addr32
), get_zero_bits( zero_bits
),
450 commit
, offset
, size_32to64( &size
, size32
), inherit
, alloc
, protect
);
451 if (NT_SUCCESS(status
))
453 put_addr( addr32
, addr
);
454 put_size( size32
, size
);
455 if (RtlIsCurrentProcess( process
))
456 notify_map_view_of_section( handle
, addr
, size
, alloc
, protect
, &status
);
458 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= prev
;
462 /**********************************************************************
463 * wow64_NtMapViewOfSectionEx
465 NTSTATUS WINAPI
wow64_NtMapViewOfSectionEx( UINT
*args
)
467 HANDLE handle
= get_handle( &args
);
468 HANDLE process
= get_handle( &args
);
469 ULONG
*addr32
= get_ptr( &args
);
470 const LARGE_INTEGER
*offset
= get_ptr( &args
);
471 ULONG
*size32
= get_ptr( &args
);
472 ULONG alloc
= get_ulong( &args
);
473 ULONG protect
= get_ulong( &args
);
474 MEM_EXTENDED_PARAMETER32
*params32
= get_ptr( &args
);
475 ULONG count
= get_ulong( &args
);
480 MEM_EXTENDED_PARAMETER
*params64
;
481 BOOL is_current
= RtlIsCurrentProcess( process
);
482 BOOL set_limit
= (!*addr32
&& is_current
);
483 void *prev
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
485 if ((status
= mem_extended_parameters_32to64( ¶ms64
, params32
, &count
, set_limit
))) return status
;
487 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ULongToPtr( NtCurrentTeb32()->Tib
.ArbitraryUserPointer
);
488 status
= NtMapViewOfSectionEx( handle
, process
, addr_32to64( &addr
, addr32
), offset
,
489 size_32to64( &size
, size32
), alloc
, protect
, params64
, count
);
490 if (NT_SUCCESS(status
))
492 put_addr( addr32
, addr
);
493 put_size( size32
, size
);
494 if (is_current
) notify_map_view_of_section( handle
, addr
, size
, alloc
, protect
, &status
);
496 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= prev
;
500 /**********************************************************************
501 * wow64_NtProtectVirtualMemory
503 NTSTATUS WINAPI
wow64_NtProtectVirtualMemory( UINT
*args
)
505 HANDLE process
= get_handle( &args
);
506 ULONG
*addr32
= get_ptr( &args
);
507 ULONG
*size32
= get_ptr( &args
);
508 ULONG new_prot
= get_ulong( &args
);
509 ULONG
*old_prot
= get_ptr( &args
);
511 void *addr
= ULongToPtr( *addr32
);
512 SIZE_T size
= *size32
;
513 BOOL is_current
= RtlIsCurrentProcess( process
);
516 if (!is_current
) send_cross_process_notification( process
, CrossProcessPreVirtualProtect
,
517 addr
, size
, 2, new_prot
, 0 );
518 else if (pBTCpuNotifyMemoryProtect
) pBTCpuNotifyMemoryProtect( addr
, size
, new_prot
, FALSE
, 0 );
520 status
= NtProtectVirtualMemory( process
, &addr
, &size
, new_prot
, old_prot
);
522 if (!is_current
) send_cross_process_notification( process
, CrossProcessPostVirtualProtect
,
523 addr
, size
, 2, new_prot
, status
);
524 else if (pBTCpuNotifyMemoryProtect
) pBTCpuNotifyMemoryProtect( addr
, size
, new_prot
, TRUE
, status
);
528 put_addr( addr32
, addr
);
529 put_size( size32
, size
);
535 /**********************************************************************
536 * wow64_NtQueryVirtualMemory
538 NTSTATUS WINAPI
wow64_NtQueryVirtualMemory( UINT
*args
)
540 HANDLE handle
= get_handle( &args
);
541 void *addr
= get_ptr( &args
);
542 MEMORY_INFORMATION_CLASS
class = get_ulong( &args
);
543 void *ptr
= get_ptr( &args
);
544 ULONG len
= get_ulong( &args
);
545 ULONG
*retlen
= get_ptr( &args
);
552 case MemoryBasicInformation
: /* MEMORY_BASIC_INFORMATION */
553 if (len
< sizeof(MEMORY_BASIC_INFORMATION32
))
554 status
= STATUS_INFO_LENGTH_MISMATCH
;
555 else if ((ULONG_PTR
)addr
> highest_user_address
)
556 status
= STATUS_INVALID_PARAMETER
;
559 MEMORY_BASIC_INFORMATION info
;
560 MEMORY_BASIC_INFORMATION32
*info32
= ptr
;
562 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, &info
, sizeof(info
), &res_len
)))
564 info32
->BaseAddress
= PtrToUlong( info
.BaseAddress
);
565 info32
->AllocationBase
= PtrToUlong( info
.AllocationBase
);
566 info32
->AllocationProtect
= info
.AllocationProtect
;
567 info32
->RegionSize
= info
.RegionSize
;
568 info32
->State
= info
.State
;
569 info32
->Protect
= info
.Protect
;
570 info32
->Type
= info
.Type
;
571 if ((ULONG_PTR
)info
.BaseAddress
+ info
.RegionSize
> highest_user_address
)
572 info32
->RegionSize
= highest_user_address
- (ULONG_PTR
)info
.BaseAddress
+ 1;
575 res_len
= sizeof(MEMORY_BASIC_INFORMATION32
);
578 case MemoryMappedFilenameInformation
: /* MEMORY_SECTION_NAME */
580 MEMORY_SECTION_NAME
*info
;
581 MEMORY_SECTION_NAME32
*info32
= ptr
;
582 SIZE_T size
= len
+ sizeof(*info
) - sizeof(*info32
);
584 info
= Wow64AllocateTemp( size
);
585 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, info
, size
, &res_len
)))
587 info32
->SectionFileName
.Length
= info
->SectionFileName
.Length
;
588 info32
->SectionFileName
.MaximumLength
= info
->SectionFileName
.MaximumLength
;
589 info32
->SectionFileName
.Buffer
= PtrToUlong( info32
+ 1 );
590 memcpy( info32
+ 1, info
->SectionFileName
.Buffer
, info
->SectionFileName
.MaximumLength
);
592 res_len
+= sizeof(*info32
) - sizeof(*info
);
596 case MemoryRegionInformation
: /* MEMORY_REGION_INFORMATION */
598 if (len
< sizeof(MEMORY_REGION_INFORMATION32
))
599 status
= STATUS_INFO_LENGTH_MISMATCH
;
600 else if ((ULONG_PTR
)addr
> highest_user_address
)
601 status
= STATUS_INVALID_PARAMETER
;
604 MEMORY_REGION_INFORMATION info
;
605 MEMORY_REGION_INFORMATION32
*info32
= ptr
;
607 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, &info
, sizeof(info
), &res_len
)))
609 info32
->AllocationBase
= PtrToUlong( info
.AllocationBase
);
610 info32
->AllocationProtect
= info
.AllocationProtect
;
611 info32
->RegionType
= info
.RegionType
;
612 info32
->RegionSize
= info
.RegionSize
;
613 info32
->CommitSize
= info
.CommitSize
;
614 info32
->PartitionId
= info
.PartitionId
;
615 info32
->NodePreference
= info
.NodePreference
;
616 if ((ULONG_PTR
)info
.AllocationBase
+ info
.RegionSize
> highest_user_address
)
617 info32
->RegionSize
= highest_user_address
- (ULONG_PTR
)info
.AllocationBase
+ 1;
620 res_len
= sizeof(MEMORY_REGION_INFORMATION32
);
624 case MemoryWorkingSetExInformation
: /* MEMORY_WORKING_SET_EX_INFORMATION */
626 MEMORY_WORKING_SET_EX_INFORMATION32
*info32
= ptr
;
627 MEMORY_WORKING_SET_EX_INFORMATION
*info
;
628 ULONG i
, count
= len
/ sizeof(*info32
);
630 if (len
< sizeof(*info32
)) return STATUS_INFO_LENGTH_MISMATCH
;
632 info
= Wow64AllocateTemp( count
* sizeof(*info
) );
633 for (i
= 0; i
< count
; i
++) info
[i
].VirtualAddress
= ULongToPtr( info32
[i
].VirtualAddress
);
634 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, info
, count
* sizeof(*info
), &res_len
)))
636 count
= res_len
/ sizeof(*info
);
637 for (i
= 0; i
< count
; i
++) info32
[i
].VirtualAttributes
.Flags
= info
[i
].VirtualAttributes
.Flags
;
638 res_len
= count
* sizeof(*info32
);
643 case MemoryImageInformation
: /* MEMORY_IMAGE_INFORMATION */
645 if (len
< sizeof(MEMORY_IMAGE_INFORMATION32
)) return STATUS_INFO_LENGTH_MISMATCH
;
647 if ((ULONG_PTR
)addr
> highest_user_address
) status
= STATUS_INVALID_PARAMETER
;
650 MEMORY_IMAGE_INFORMATION info
;
651 MEMORY_IMAGE_INFORMATION32
*info32
= ptr
;
653 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, &info
, sizeof(info
), &res_len
)))
655 info32
->ImageBase
= PtrToUlong( info
.ImageBase
);
656 info32
->SizeOfImage
= info
.SizeOfImage
;
657 info32
->ImageFlags
= info
.ImageFlags
;
660 res_len
= sizeof(MEMORY_IMAGE_INFORMATION32
);
664 case MemoryWineUnixWow64Funcs
:
665 return STATUS_INVALID_INFO_CLASS
;
667 case MemoryWineUnixFuncs
:
668 status
= NtQueryVirtualMemory( handle
, addr
, MemoryWineUnixWow64Funcs
, ptr
, len
, &res_len
);
672 FIXME( "unsupported class %u\n", class );
673 return STATUS_INVALID_INFO_CLASS
;
675 if (!status
|| status
== STATUS_INFO_LENGTH_MISMATCH
) put_size( retlen
, res_len
);
680 /**********************************************************************
681 * wow64_NtReadVirtualMemory
683 NTSTATUS WINAPI
wow64_NtReadVirtualMemory( UINT
*args
)
685 HANDLE process
= get_handle( &args
);
686 const void *addr
= get_ptr( &args
);
687 void *buffer
= get_ptr( &args
);
688 SIZE_T size
= get_ulong( &args
);
689 ULONG
*retlen
= get_ptr( &args
);
694 status
= NtReadVirtualMemory( process
, addr
, buffer
, size
, &ret_size
);
695 put_size( retlen
, ret_size
);
700 /**********************************************************************
701 * wow64_NtResetWriteWatch
703 NTSTATUS WINAPI
wow64_NtResetWriteWatch( UINT
*args
)
705 HANDLE process
= get_handle( &args
);
706 void *base
= get_ptr( &args
);
707 SIZE_T size
= get_ulong( &args
);
709 return NtResetWriteWatch( process
, base
, size
);
713 /**********************************************************************
714 * wow64_NtSetInformationVirtualMemory
716 NTSTATUS WINAPI
wow64_NtSetInformationVirtualMemory( UINT
*args
)
718 HANDLE process
= get_handle( &args
);
719 VIRTUAL_MEMORY_INFORMATION_CLASS info_class
= get_ulong( &args
);
720 ULONG count
= get_ulong( &args
);
721 MEMORY_RANGE_ENTRY32
*addresses32
= get_ptr( &args
);
722 PVOID ptr
= get_ptr( &args
);
723 ULONG len
= get_ulong( &args
);
725 MEMORY_RANGE_ENTRY
*addresses
;
727 if (!count
) return STATUS_INVALID_PARAMETER_3
;
728 addresses
= memory_range_entry_array_32to64( addresses32
, count
);
732 case VmPrefetchInformation
:
735 FIXME( "(%p,info_class=%u,%lu,%p,%p,%lu): not implemented\n",
736 process
, info_class
, count
, addresses32
, ptr
, len
);
737 return STATUS_INVALID_PARAMETER_2
;
740 return NtSetInformationVirtualMemory( process
, info_class
, count
, addresses
, ptr
, len
);
744 /**********************************************************************
745 * wow64_NtSetLdtEntries
747 NTSTATUS WINAPI
wow64_NtSetLdtEntries( UINT
*args
)
749 ULONG sel1
= get_ulong( &args
);
750 ULONG entry1_low
= get_ulong( &args
);
751 ULONG entry1_high
= get_ulong( &args
);
752 ULONG sel2
= get_ulong( &args
);
753 ULONG entry2_low
= get_ulong( &args
);
754 ULONG entry2_high
= get_ulong( &args
);
756 FIXME( "%04lx %08lx %08lx %04lx %08lx %08lx: stub\n",
757 sel1
, entry1_low
, entry1_high
, sel2
, entry2_low
, entry2_high
);
758 return STATUS_NOT_IMPLEMENTED
;
762 /**********************************************************************
763 * wow64_NtUnlockVirtualMemory
765 NTSTATUS WINAPI
wow64_NtUnlockVirtualMemory( UINT
*args
)
767 HANDLE process
= get_handle( &args
);
768 ULONG
*addr32
= get_ptr( &args
);
769 ULONG
*size32
= get_ptr( &args
);
770 ULONG unknown
= get_ulong( &args
);
776 status
= NtUnlockVirtualMemory( process
, addr_32to64( &addr
, addr32
),
777 size_32to64( &size
, size32
), unknown
);
780 put_addr( addr32
, addr
);
781 put_size( size32
, size
);
787 /**********************************************************************
788 * wow64_NtUnmapViewOfSection
790 NTSTATUS WINAPI
wow64_NtUnmapViewOfSection( UINT
*args
)
792 HANDLE process
= get_handle( &args
);
793 void *addr
= get_ptr( &args
);
795 BOOL is_current
= RtlIsCurrentProcess( process
);
798 if (is_current
&& pBTCpuNotifyUnmapViewOfSection
) pBTCpuNotifyUnmapViewOfSection( addr
, FALSE
, 0 );
799 status
= NtUnmapViewOfSection( process
, addr
);
800 if (is_current
&& pBTCpuNotifyUnmapViewOfSection
) pBTCpuNotifyUnmapViewOfSection( addr
, TRUE
, status
);
805 /**********************************************************************
806 * wow64_NtUnmapViewOfSectionEx
808 NTSTATUS WINAPI
wow64_NtUnmapViewOfSectionEx( UINT
*args
)
810 HANDLE process
= get_handle( &args
);
811 void *addr
= get_ptr( &args
);
812 ULONG flags
= get_ulong( &args
);
814 BOOL is_current
= RtlIsCurrentProcess( process
);
817 if (is_current
&& pBTCpuNotifyUnmapViewOfSection
) pBTCpuNotifyUnmapViewOfSection( addr
, FALSE
, 0 );
818 status
= NtUnmapViewOfSectionEx( process
, addr
, flags
);
819 if (is_current
&& pBTCpuNotifyUnmapViewOfSection
) pBTCpuNotifyUnmapViewOfSection( addr
, TRUE
, status
);
824 /**********************************************************************
825 * wow64_NtWow64AllocateVirtualMemory64
827 NTSTATUS WINAPI
wow64_NtWow64AllocateVirtualMemory64( UINT
*args
)
829 HANDLE process
= get_handle( &args
);
830 void **addr
= get_ptr( &args
);
831 ULONG_PTR zero_bits
= get_ulong64( &args
);
832 SIZE_T
*size
= get_ptr( &args
);
833 ULONG type
= get_ulong( &args
);
834 ULONG protect
= get_ulong( &args
);
836 return NtAllocateVirtualMemory( process
, addr
, zero_bits
, size
, type
, protect
);
840 /**********************************************************************
841 * wow64_NtWow64ReadVirtualMemory64
843 NTSTATUS WINAPI
wow64_NtWow64ReadVirtualMemory64( UINT
*args
)
845 HANDLE process
= get_handle( &args
);
846 void *addr
= (void *)(ULONG_PTR
)get_ulong64( &args
);
847 void *buffer
= get_ptr( &args
);
848 SIZE_T size
= get_ulong64( &args
);
849 SIZE_T
*ret_size
= get_ptr( &args
);
851 return NtReadVirtualMemory( process
, addr
, buffer
, size
, ret_size
);
855 /**********************************************************************
856 * wow64_NtWow64WriteVirtualMemory64
858 NTSTATUS WINAPI
wow64_NtWow64WriteVirtualMemory64( UINT
*args
)
860 HANDLE process
= get_handle( &args
);
861 void *addr
= (void *)(ULONG_PTR
)get_ulong64( &args
);
862 const void *buffer
= get_ptr( &args
);
863 SIZE_T size
= get_ulong64( &args
);
864 SIZE_T
*ret_size
= get_ptr( &args
);
866 return NtWriteVirtualMemory( process
, addr
, buffer
, size
, ret_size
);
870 /**********************************************************************
871 * wow64_NtWriteVirtualMemory
873 NTSTATUS WINAPI
wow64_NtWriteVirtualMemory( UINT
*args
)
875 HANDLE process
= get_handle( &args
);
876 void *addr
= get_ptr( &args
);
877 const void *buffer
= get_ptr( &args
);
878 SIZE_T size
= get_ulong( &args
);
879 ULONG
*retlen
= get_ptr( &args
);
884 status
= NtWriteVirtualMemory( process
, addr
, buffer
, size
, &ret_size
);
885 put_size( retlen
, ret_size
);