上篇教程我们学习了通过Section在用户进程和内核驱动程序之间共享信息的方法,但是这种方法有一个缺点,就是驱动程序被硬性限制在具体进程的地址上下文中,即驱动程序所使用的虚拟地址位于此进程的地址空间中。我们在本例中使用的方法将没有这个缺点。对于驱动程序来说,这种方法更为自然些。
首先来看看驱动程序。
首先来看看驱动程序。
unit SharingMemory; interface uses nt_status, ntoskrnl, native, winioctl, fcall, macros; function _DriverEntry(pDriverObject:PDRIVER_OBJECT; pusRegistryPath:PUNICODE_STRING): NTSTATUS; stdcall; implementation uses seh; var g_pSharedMemory: PVOID; g_pMdl: PVOID; g_pUserAddress: PVOID; g_fTimerStarted: boolean; g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING; {更新系统时间到共享内存} procedure UpdateTime; stdcall; var SysTime:LARGE_INTEGER; begin KeQuerySystemTime(@SysTime); ExSystemTimeToLocalTime(@SysTime, g_pSharedMemory); end; procedure TimerRoutine(pDeviceObject:PDEVICE_OBJECT; pContext:PVOID); stdcall; begin UpdateTime; end; {清理过程--释放资源} procedure Cleanup(pDeviceObject:PDEVICE_OBJECT); stdcall; begin if g_fTimerStarted then begin IoStopTimer(pDeviceObject); DbgPrint('SharingMemory: Timer stopped'#13#10); end; if (g_pUserAddress <> nil) and (g_pMdl <> nil) then begin MmUnmapLockedPages(g_pUserAddress, g_pMdl); DbgPrint('SharingMemory: Memory at address %08X unmapped'#13#10, g_pUserAddress); g_pUserAddress := nil; end; if g_pMdl <> nil then begin IoFreeMdl(g_pMdl); DbgPrint('SharingMemory: MDL at address %08X freed'#13#10, g_pMdl); g_pMdl := nil; end; if g_pSharedMemory <> nil then begin ExFreePool(g_pSharedMemory); DbgPrint('SharingMemory: Memory at address %08X released'#13#10, g_pSharedMemory); g_pSharedMemory := nil; end; end; function DispatchCleanup(pDeviceObject:PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall; begin DbgPrint(#13#10'SharingMemory: Entering DispatchCleanup'#13#10); Cleanup(pDeviceObject); p_Irp^.IoStatus.Status := STATUS_SUCCESS; p_Irp^.IoStatus.Information := 0; IofCompleteRequest(p_Irp, IO_NO_INCREMENT); DbgPrint('SharingMemory: Leaving DispatchCleanup'#13#10); result := STATUS_SUCCESS; end; function DispatchCreateClose(p_DeviceObject:PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall; begin p_Irp^.IoStatus.Status := STATUS_SUCCESS; p_Irp^.IoStatus.Information := 0; IofCompleteRequest(p_Irp, IO_NO_INCREMENT); result := STATUS_SUCCESS; end; function DispatchControl(p_DeviceObject: PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall; label SafePlace; var dwContext:DWORD; psl:PIO_STACK_LOCATION; IOCTL_GIVE_ME_YOUR_MEMORY: DWORD; pSystemBuffer: PVOID; begin DbgPrint(#13#10'SharingMemory: Entering DispatchControl'#13#10); IOCTL_GIVE_ME_YOUR_MEMORY := CTL_CODE(FILE_DEVICE_UNKNOWN, $800, METHOD_BUFFERED, FILE_READ_ACCESS); p_Irp^.IoStatus.Status := STATUS_UNSUCCESSFUL; p_Irp^.IoStatus.Information := 0; psl := IoGetCurrentIrpStackLocation(p_Irp); {取IRP的stack location的指针} if psl^.Parameters.DeviceIoControl.IoControlCode = IOCTL_GIVE_ME_YOUR_MEMORY then begin {是我们控制码就开始处理} if psl^.Parameters.DeviceIoControl.OutputBufferLength >= sizeof(PVOID) then begin g_pSharedMemory := ExAllocatePool(NonPagedPool, PAGE_SIZE); if g_pSharedMemory <> nil then begin DbgPrint('SharingMemory: %X bytes of nonpaged memory allocated at address %08X'#13#10, PAGE_SIZE, g_pSharedMemory); g_pMdl := IoAllocateMdl(g_pSharedMemory, PAGE_SIZE, false, false, nil); if g_pMdl <> nil then begin DbgPrint('SharingMemory: MDL allocated at address %08X'#13#10, |