From: Sebastian Lackner Subject: [4/5] ntoskrnl.exe: Explicitly set MappedSystemVa for MDLs. Message-Id: Date: Sun, 16 Oct 2016 08:57:21 +0200 Signed-off-by: Sebastian Lackner --- We do not have a general mechanism to lock pages yet. For now, manually set MappedSystemVa and the MDL_MAPPED_TO_SYSTEM_VA flag. This patch also adds the definition of MmGetSystemAddressForMdlSafe() which is how drivers should access the buffer. After this patch, the following test executable which uses a METHOD_OUT_DIRECT ioctl should work fine in Wine (produce identical results): https://newtestbot.winehq.org/JobDetails.pl?Key=26184 dlls/ntoskrnl.exe/ntoskrnl.c | 26 ++++++++++++++++++++++++-- include/ddk/wdm.h | 9 +++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index eac81f7..854d68d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -820,6 +820,7 @@ PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device, { PIRP irp; PIO_STACK_LOCATION irpsp; + MDL *mdl; TRACE( "%x, %p, %p, %u, %p, %u, %u, %p, %p\n", code, device, in_buff, in_len, out_buff, out_len, internal, event, iosb ); @@ -847,7 +848,16 @@ PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device, case METHOD_IN_DIRECT: case METHOD_OUT_DIRECT: irp->AssociatedIrp.SystemBuffer = in_buff; - IoAllocateMdl( out_buff, out_len, FALSE, FALSE, irp ); + + mdl = IoAllocateMdl( out_buff, out_len, FALSE, FALSE, irp ); + if (!mdl) + { + IoFreeIrp( irp ); + return NULL; + } + + mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; + mdl->MappedSystemVa = out_buff; break; case METHOD_NEITHER: irpsp->Parameters.DeviceIoControl.Type3InputBuffer = in_buff; @@ -882,7 +892,19 @@ PIRP WINAPI IoBuildSynchronousFsdRequest(ULONG majorfunc, PDEVICE_OBJECT device, irpsp->CompletionRoutine = NULL; irp->AssociatedIrp.SystemBuffer = buffer; - if (device->Flags & DO_DIRECT_IO) IoAllocateMdl( buffer, length, FALSE, FALSE, irp ); + + if (device->Flags & DO_DIRECT_IO) + { + MDL *mdl = IoAllocateMdl( buffer, length, FALSE, FALSE, irp ); + if (!mdl) + { + IoFreeIrp( irp ); + return NULL; + } + + mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; + mdl->MappedSystemVa = buffer; + } switch (majorfunc) { diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 61de490..3dda667 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1305,8 +1305,17 @@ PVOID WINAPI MmAllocateContiguousMemory(SIZE_T,PHYSICAL_ADDRESS); PVOID WINAPI MmAllocateNonCachedMemory(SIZE_T); PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS,PHYSICAL_ADDRESS,PHYSICAL_ADDRESS,SIZE_T); void WINAPI MmFreeNonCachedMemory(PVOID,SIZE_T); +PVOID WINAPI MmMapLockedPagesSpecifyCache(PMDL,KPROCESSOR_MODE,MEMORY_CACHING_TYPE,PVOID,ULONG,ULONG); MM_SYSTEMSIZE WINAPI MmQuerySystemSize(void); +static inline void *MmGetSystemAddressForMdlSafe(MDL *mdl, ULONG priority) +{ + if (mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) + return mdl->MappedSystemVa; + else + return MmMapLockedPagesSpecifyCache(mdl, KernelMode, MmCached, NULL, FALSE, priority); +} + void WINAPI ObDereferenceObject(void*); NTSTATUS WINAPI ObReferenceObjectByHandle(HANDLE,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,PVOID*,POBJECT_HANDLE_INFORMATION); NTSTATUS WINAPI ObReferenceObjectByName(UNICODE_STRING*,ULONG,ACCESS_STATE*,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,void*,void**); -- 2.9.0