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
);
36 static MEMORY_RANGE_ENTRY
*memory_range_entry_array_32to64( const MEMORY_RANGE_ENTRY32
*addresses32
,
39 MEMORY_RANGE_ENTRY
*addresses
= Wow64AllocateTemp( sizeof(MEMORY_RANGE_ENTRY
) * count
);
42 for (i
= 0; i
< count
; i
++)
44 addresses
[i
].VirtualAddress
= ULongToPtr( addresses32
[i
].VirtualAddress
);
45 addresses
[i
].NumberOfBytes
= addresses32
[i
].NumberOfBytes
;
51 /**********************************************************************
52 * wow64_NtAllocateVirtualMemory
54 NTSTATUS WINAPI
wow64_NtAllocateVirtualMemory( UINT
*args
)
56 HANDLE process
= get_handle( &args
);
57 ULONG
*addr32
= get_ptr( &args
);
58 ULONG_PTR zero_bits
= get_ulong( &args
);
59 ULONG
*size32
= get_ptr( &args
);
60 ULONG type
= get_ulong( &args
);
61 ULONG protect
= get_ulong( &args
);
67 status
= NtAllocateVirtualMemory( process
, addr_32to64( &addr
, addr32
), get_zero_bits( zero_bits
),
68 size_32to64( &size
, size32
), type
, protect
);
71 put_addr( addr32
, addr
);
72 put_size( size32
, size
);
78 /**********************************************************************
79 * wow64_NtAllocateVirtualMemoryEx
81 NTSTATUS WINAPI
wow64_NtAllocateVirtualMemoryEx( UINT
*args
)
83 HANDLE process
= get_handle( &args
);
84 ULONG
*addr32
= get_ptr( &args
);
85 ULONG
*size32
= get_ptr( &args
);
86 ULONG type
= get_ulong( &args
);
87 ULONG protect
= get_ulong( &args
);
88 MEM_EXTENDED_PARAMETER
*params
= get_ptr( &args
);
89 ULONG count
= get_ulong( &args
);
95 if (count
) FIXME( "%ld extended parameters %p\n", count
, params
);
96 status
= NtAllocateVirtualMemoryEx( process
, addr_32to64( &addr
, addr32
), size_32to64( &size
, size32
),
97 type
, protect
, params
, count
);
100 put_addr( addr32
, addr
);
101 put_size( size32
, size
);
107 /**********************************************************************
108 * wow64_NtAreMappedFilesTheSame
110 NTSTATUS WINAPI
wow64_NtAreMappedFilesTheSame( UINT
*args
)
112 void *ptr1
= get_ptr( &args
);
113 void *ptr2
= get_ptr( &args
);
115 return NtAreMappedFilesTheSame( ptr1
, ptr2
);
119 /**********************************************************************
120 * wow64_NtFlushVirtualMemory
122 NTSTATUS WINAPI
wow64_NtFlushVirtualMemory( UINT
*args
)
124 HANDLE process
= get_handle( &args
);
125 ULONG
*addr32
= get_ptr( &args
);
126 ULONG
*size32
= get_ptr( &args
);
127 ULONG unknown
= get_ulong( &args
);
133 status
= NtFlushVirtualMemory( process
, (const void **)addr_32to64( &addr
, addr32
),
134 size_32to64( &size
, size32
), unknown
);
137 put_addr( addr32
, addr
);
138 put_size( size32
, size
);
144 /**********************************************************************
145 * wow64_NtFreeVirtualMemory
147 NTSTATUS WINAPI
wow64_NtFreeVirtualMemory( UINT
*args
)
149 HANDLE process
= get_handle( &args
);
150 ULONG
*addr32
= get_ptr( &args
);
151 ULONG
*size32
= get_ptr( &args
);
152 ULONG type
= get_ulong( &args
);
158 status
= NtFreeVirtualMemory( process
, addr_32to64( &addr
, addr32
),
159 size_32to64( &size
, size32
), type
);
162 put_addr( addr32
, addr
);
163 put_size( size32
, size
);
169 /**********************************************************************
170 * wow64_NtGetNlsSectionPtr
172 NTSTATUS WINAPI
wow64_NtGetNlsSectionPtr( UINT
*args
)
174 ULONG type
= get_ulong( &args
);
175 ULONG id
= get_ulong( &args
);
176 void *unknown
= get_ptr( &args
);
177 ULONG
*addr32
= get_ptr( &args
);
178 ULONG
*size32
= get_ptr( &args
);
184 status
= NtGetNlsSectionPtr( type
, id
, unknown
, addr_32to64( &addr
, addr32
),
185 size_32to64( &size
, size32
));
188 put_addr( addr32
, addr
);
189 put_size( size32
, size
);
195 /**********************************************************************
196 * wow64_NtGetWriteWatch
198 NTSTATUS WINAPI
wow64_NtGetWriteWatch( UINT
*args
)
200 HANDLE handle
= get_handle( &args
);
201 ULONG flags
= get_ulong( &args
);
202 void *base
= get_ptr( &args
);
203 SIZE_T size
= get_ulong( &args
);
204 ULONG
*addr_ptr
= get_ptr( &args
);
205 ULONG
*count_ptr
= get_ptr( &args
);
206 ULONG
*granularity
= get_ptr( &args
);
208 ULONG_PTR i
, count
= *count_ptr
;
212 if (!count
|| !size
) return STATUS_INVALID_PARAMETER
;
213 if (flags
& ~WRITE_WATCH_FLAG_RESET
) return STATUS_INVALID_PARAMETER
;
214 if (!addr_ptr
) return STATUS_ACCESS_VIOLATION
;
216 addresses
= Wow64AllocateTemp( count
* sizeof(*addresses
) );
217 if (!(status
= NtGetWriteWatch( handle
, flags
, base
, size
, addresses
, &count
, granularity
)))
219 for (i
= 0; i
< count
; i
++) addr_ptr
[i
] = PtrToUlong( addresses
[i
] );
226 /**********************************************************************
227 * wow64_NtInitializeNlsFiles
229 NTSTATUS WINAPI
wow64_NtInitializeNlsFiles( UINT
*args
)
231 ULONG
*addr32
= get_ptr( &args
);
232 LCID
*lcid
= get_ptr( &args
);
233 LARGE_INTEGER
*size
= get_ptr( &args
);
238 status
= NtInitializeNlsFiles( addr_32to64( &addr
, addr32
), lcid
, size
);
239 if (!status
) put_addr( addr32
, addr
);
244 /**********************************************************************
245 * wow64_NtLockVirtualMemory
247 NTSTATUS WINAPI
wow64_NtLockVirtualMemory( UINT
*args
)
249 HANDLE process
= get_handle( &args
);
250 ULONG
*addr32
= get_ptr( &args
);
251 ULONG
*size32
= get_ptr( &args
);
252 ULONG unknown
= get_ulong( &args
);
258 status
= NtLockVirtualMemory( process
, addr_32to64( &addr
, addr32
),
259 size_32to64( &size
, size32
), unknown
);
262 put_addr( addr32
, addr
);
263 put_size( size32
, size
);
269 /**********************************************************************
270 * wow64_NtMapViewOfSection
272 NTSTATUS WINAPI
wow64_NtMapViewOfSection( UINT
*args
)
274 HANDLE handle
= get_handle( &args
);
275 HANDLE process
= get_handle( &args
);
276 ULONG
*addr32
= get_ptr( &args
);
277 ULONG_PTR zero_bits
= get_ulong( &args
);
278 SIZE_T commit
= get_ulong( &args
);
279 const LARGE_INTEGER
*offset
= get_ptr( &args
);
280 ULONG
*size32
= get_ptr( &args
);
281 SECTION_INHERIT inherit
= get_ulong( &args
);
282 ULONG alloc
= get_ulong( &args
);
283 ULONG protect
= get_ulong( &args
);
289 status
= NtMapViewOfSection( handle
, process
, addr_32to64( &addr
, addr32
), get_zero_bits( zero_bits
),
290 commit
, offset
, size_32to64( &size
, size32
), inherit
, alloc
, protect
);
291 if (NT_SUCCESS(status
))
293 SECTION_IMAGE_INFORMATION info
;
295 if (!NtQuerySection( handle
, SectionImageInformation
, &info
, sizeof(info
), NULL
))
297 if (info
.Machine
== current_machine
) init_image_mapping( addr
);
299 put_addr( addr32
, addr
);
300 put_size( size32
, size
);
305 /**********************************************************************
306 * wow64_NtMapViewOfSectionEx
308 NTSTATUS WINAPI
wow64_NtMapViewOfSectionEx( UINT
*args
)
310 HANDLE handle
= get_handle( &args
);
311 HANDLE process
= get_handle( &args
);
312 ULONG
*addr32
= get_ptr( &args
);
313 const LARGE_INTEGER
*offset
= get_ptr( &args
);
314 ULONG
*size32
= get_ptr( &args
);
315 ULONG alloc
= get_ulong( &args
);
316 ULONG protect
= get_ulong( &args
);
317 MEM_EXTENDED_PARAMETER
*params
= get_ptr( &args
);
318 ULONG params_count
= get_ulong( &args
);
324 status
= NtMapViewOfSectionEx( handle
, process
, addr_32to64( &addr
, addr32
), offset
, size_32to64( &size
, size32
), alloc
,
325 protect
, params
, params_count
);
326 if (NT_SUCCESS(status
))
328 SECTION_IMAGE_INFORMATION info
;
330 if (!NtQuerySection( handle
, SectionImageInformation
, &info
, sizeof(info
), NULL
))
332 if (info
.Machine
== current_machine
) init_image_mapping( addr
);
334 put_addr( addr32
, addr
);
335 put_size( size32
, size
);
340 /**********************************************************************
341 * wow64_NtProtectVirtualMemory
343 NTSTATUS WINAPI
wow64_NtProtectVirtualMemory( UINT
*args
)
345 HANDLE process
= get_handle( &args
);
346 ULONG
*addr32
= get_ptr( &args
);
347 ULONG
*size32
= get_ptr( &args
);
348 ULONG new_prot
= get_ulong( &args
);
349 ULONG
*old_prot
= get_ptr( &args
);
355 status
= NtProtectVirtualMemory( process
, addr_32to64( &addr
, addr32
),
356 size_32to64( &size
, size32
), new_prot
, old_prot
);
359 put_addr( addr32
, addr
);
360 put_size( size32
, size
);
366 /**********************************************************************
367 * wow64_NtQueryVirtualMemory
369 NTSTATUS WINAPI
wow64_NtQueryVirtualMemory( UINT
*args
)
371 HANDLE handle
= get_handle( &args
);
372 void *addr
= get_ptr( &args
);
373 MEMORY_INFORMATION_CLASS
class = get_ulong( &args
);
374 void *ptr
= get_ptr( &args
);
375 ULONG len
= get_ulong( &args
);
376 ULONG
*retlen
= get_ptr( &args
);
383 case MemoryBasicInformation
: /* MEMORY_BASIC_INFORMATION */
384 if (len
< sizeof(MEMORY_BASIC_INFORMATION32
))
385 status
= STATUS_INFO_LENGTH_MISMATCH
;
386 else if ((ULONG_PTR
)addr
> highest_user_address
)
387 status
= STATUS_INVALID_PARAMETER
;
390 MEMORY_BASIC_INFORMATION info
;
391 MEMORY_BASIC_INFORMATION32
*info32
= ptr
;
393 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, &info
, sizeof(info
), &res_len
)))
395 info32
->BaseAddress
= PtrToUlong( info
.BaseAddress
);
396 info32
->AllocationBase
= PtrToUlong( info
.AllocationBase
);
397 info32
->AllocationProtect
= info
.AllocationProtect
;
398 info32
->RegionSize
= info
.RegionSize
;
399 info32
->State
= info
.State
;
400 info32
->Protect
= info
.Protect
;
401 info32
->Type
= info
.Type
;
404 res_len
= sizeof(MEMORY_BASIC_INFORMATION32
);
407 case MemoryMappedFilenameInformation
: /* MEMORY_SECTION_NAME */
409 MEMORY_SECTION_NAME
*info
;
410 MEMORY_SECTION_NAME32
*info32
= ptr
;
411 SIZE_T size
= len
+ sizeof(*info
) - sizeof(*info32
);
413 info
= Wow64AllocateTemp( size
);
414 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, info
, size
, &res_len
)))
416 info32
->SectionFileName
.Length
= info
->SectionFileName
.Length
;
417 info32
->SectionFileName
.MaximumLength
= info
->SectionFileName
.MaximumLength
;
418 info32
->SectionFileName
.Buffer
= PtrToUlong( info32
+ 1 );
419 memcpy( info32
+ 1, info
->SectionFileName
.Buffer
, info
->SectionFileName
.MaximumLength
);
421 res_len
+= sizeof(*info32
) - sizeof(*info
);
425 case MemoryWorkingSetExInformation
: /* MEMORY_WORKING_SET_EX_INFORMATION */
427 MEMORY_WORKING_SET_EX_INFORMATION32
*info32
= ptr
;
428 MEMORY_WORKING_SET_EX_INFORMATION
*info
;
429 ULONG i
, count
= len
/ sizeof(*info32
);
431 info
= Wow64AllocateTemp( count
* sizeof(*info
) );
432 for (i
= 0; i
< count
; i
++) info
[i
].VirtualAddress
= ULongToPtr( info32
[i
].VirtualAddress
);
433 if (!(status
= NtQueryVirtualMemory( handle
, addr
, class, info
, count
* sizeof(*info
), &res_len
)))
435 count
= res_len
/ sizeof(*info
);
436 for (i
= 0; i
< count
; i
++) info32
[i
].VirtualAttributes
.Flags
= info
[i
].VirtualAttributes
.Flags
;
437 res_len
= count
* sizeof(*info32
);
442 case MemoryWineUnixWow64Funcs
:
443 return STATUS_INVALID_INFO_CLASS
;
445 case MemoryWineUnixFuncs
:
446 status
= NtQueryVirtualMemory( handle
, addr
, MemoryWineUnixWow64Funcs
, ptr
, len
, &res_len
);
450 FIXME( "unsupported class %u\n", class );
451 return STATUS_INVALID_INFO_CLASS
;
453 if (!status
|| status
== STATUS_INFO_LENGTH_MISMATCH
) put_size( retlen
, res_len
);
458 /**********************************************************************
459 * wow64_NtReadVirtualMemory
461 NTSTATUS WINAPI
wow64_NtReadVirtualMemory( UINT
*args
)
463 HANDLE process
= get_handle( &args
);
464 const void *addr
= get_ptr( &args
);
465 void *buffer
= get_ptr( &args
);
466 SIZE_T size
= get_ulong( &args
);
467 ULONG
*retlen
= get_ptr( &args
);
472 status
= NtReadVirtualMemory( process
, addr
, buffer
, size
, &ret_size
);
473 put_size( retlen
, ret_size
);
478 /**********************************************************************
479 * wow64_NtResetWriteWatch
481 NTSTATUS WINAPI
wow64_NtResetWriteWatch( UINT
*args
)
483 HANDLE process
= get_handle( &args
);
484 void *base
= get_ptr( &args
);
485 SIZE_T size
= get_ulong( &args
);
487 return NtResetWriteWatch( process
, base
, size
);
491 /**********************************************************************
492 * wow64_NtSetInformationVirtualMemory
494 NTSTATUS WINAPI
wow64_NtSetInformationVirtualMemory( UINT
*args
)
496 HANDLE process
= get_handle( &args
);
497 VIRTUAL_MEMORY_INFORMATION_CLASS info_class
= get_ulong( &args
);
498 ULONG count
= get_ulong( &args
);
499 MEMORY_RANGE_ENTRY32
*addresses32
= get_ptr( &args
);
500 PVOID ptr
= get_ptr( &args
);
501 ULONG len
= get_ulong( &args
);
503 MEMORY_RANGE_ENTRY
*addresses
;
505 if (!count
) return STATUS_INVALID_PARAMETER_3
;
506 addresses
= memory_range_entry_array_32to64( addresses32
, count
);
510 case VmPrefetchInformation
:
513 FIXME( "(%p,info_class=%u,%lu,%p,%p,%lu): not implemented\n",
514 process
, info_class
, count
, addresses32
, ptr
, len
);
515 return STATUS_INVALID_PARAMETER_2
;
518 return NtSetInformationVirtualMemory( process
, info_class
, count
, addresses
, ptr
, len
);
522 /**********************************************************************
523 * wow64_NtSetLdtEntries
525 NTSTATUS WINAPI
wow64_NtSetLdtEntries( UINT
*args
)
527 ULONG sel1
= get_ulong( &args
);
528 ULONG entry1_low
= get_ulong( &args
);
529 ULONG entry1_high
= get_ulong( &args
);
530 ULONG sel2
= get_ulong( &args
);
531 ULONG entry2_low
= get_ulong( &args
);
532 ULONG entry2_high
= get_ulong( &args
);
534 FIXME( "%04lx %08lx %08lx %04lx %08lx %08lx: stub\n",
535 sel1
, entry1_low
, entry1_high
, sel2
, entry2_low
, entry2_high
);
536 return STATUS_NOT_IMPLEMENTED
;
540 /**********************************************************************
541 * wow64_NtUnlockVirtualMemory
543 NTSTATUS WINAPI
wow64_NtUnlockVirtualMemory( UINT
*args
)
545 HANDLE process
= get_handle( &args
);
546 ULONG
*addr32
= get_ptr( &args
);
547 ULONG
*size32
= get_ptr( &args
);
548 ULONG unknown
= get_ulong( &args
);
554 status
= NtUnlockVirtualMemory( process
, addr_32to64( &addr
, addr32
),
555 size_32to64( &size
, size32
), unknown
);
558 put_addr( addr32
, addr
);
559 put_size( size32
, size
);
565 /**********************************************************************
566 * wow64_NtUnmapViewOfSection
568 NTSTATUS WINAPI
wow64_NtUnmapViewOfSection( UINT
*args
)
570 HANDLE process
= get_handle( &args
);
571 void *addr
= get_ptr( &args
);
573 return NtUnmapViewOfSection( process
, addr
);
577 /**********************************************************************
578 * wow64_NtUnmapViewOfSectionEx
580 NTSTATUS WINAPI
wow64_NtUnmapViewOfSectionEx( UINT
*args
)
582 HANDLE process
= get_handle( &args
);
583 void *addr
= get_ptr( &args
);
584 ULONG flags
= get_ulong( &args
);
586 return NtUnmapViewOfSectionEx( process
, addr
, flags
);
590 /**********************************************************************
591 * wow64_NtWow64AllocateVirtualMemory64
593 NTSTATUS WINAPI
wow64_NtWow64AllocateVirtualMemory64( UINT
*args
)
595 HANDLE process
= get_handle( &args
);
596 void **addr
= get_ptr( &args
);
597 ULONG_PTR zero_bits
= get_ulong64( &args
);
598 SIZE_T
*size
= get_ptr( &args
);
599 ULONG type
= get_ulong( &args
);
600 ULONG protect
= get_ulong( &args
);
602 return NtAllocateVirtualMemory( process
, addr
, zero_bits
, size
, type
, protect
);
606 /**********************************************************************
607 * wow64_NtWow64ReadVirtualMemory64
609 NTSTATUS WINAPI
wow64_NtWow64ReadVirtualMemory64( UINT
*args
)
611 HANDLE process
= get_handle( &args
);
612 void *addr
= (void *)(ULONG_PTR
)get_ulong64( &args
);
613 void *buffer
= get_ptr( &args
);
614 SIZE_T size
= get_ulong64( &args
);
615 SIZE_T
*ret_size
= get_ptr( &args
);
617 return NtReadVirtualMemory( process
, addr
, buffer
, size
, ret_size
);
621 /**********************************************************************
622 * wow64_NtWow64WriteVirtualMemory64
624 NTSTATUS WINAPI
wow64_NtWow64WriteVirtualMemory64( UINT
*args
)
626 HANDLE process
= get_handle( &args
);
627 void *addr
= (void *)(ULONG_PTR
)get_ulong64( &args
);
628 const void *buffer
= get_ptr( &args
);
629 SIZE_T size
= get_ulong64( &args
);
630 SIZE_T
*ret_size
= get_ptr( &args
);
632 return NtWriteVirtualMemory( process
, addr
, buffer
, size
, ret_size
);
636 /**********************************************************************
637 * wow64_NtWriteVirtualMemory
639 NTSTATUS WINAPI
wow64_NtWriteVirtualMemory( UINT
*args
)
641 HANDLE process
= get_handle( &args
);
642 void *addr
= get_ptr( &args
);
643 const void *buffer
= get_ptr( &args
);
644 SIZE_T size
= get_ulong( &args
);
645 ULONG
*retlen
= get_ptr( &args
);
650 status
= NtWriteVirtualMemory( process
, addr
, buffer
, size
, &ret_size
);
651 put_size( retlen
, ret_size
);