📄 comeml.c
字号:
//////////////////////////////////////////////////////////////////////
//
// File: comeml.c
// $Archive: /ComemL/Host/Driver/WinNT/comeml.c $
//
// Purpose:
// main module for the Windows NT comem lite device driver
//
// Environment:
// kernel mode
//
// $Author: Markm $
//
// $History: comeml.c $
//
// ***************** Version 1 *****************
// User: Markm Date: 1/27/99 Time: 10:47a
// Created in $/ComemL/Host/Driver/WinNT
// initial revision - based on Comem driver
//
//
// Copyright (c) 1997 Anchor Chips, Inc. May not be reproduced without
// permission. See the license agreement for more details.
//
//////////////////////////////////////////////////////////////////////
#include "ntddk.h"
#include "comemdrv.h"
#include "stdarg.h"
NTSTATUS
CoMemCreateDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT *DeviceObject,
IN PUNICODE_STRING RegistryPath,
LONG Instance
);
NTSTATUS
CoMemGetVendorId(
IN PUNICODE_STRING RegistryPath,
OUT WORD * vendorId
);
NTSTATUS
CoMemGetDeviceId(
IN PUNICODE_STRING RegistryPath,
OUT WORD * deviceId
);
NTSTATUS
CoMemDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
CoMemUnload(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
CoMemAllocContigMemory(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
void
CoMemDeAllocContigMemory(
IN PDEVICE_OBJECT DeviceObject
);
PVOID
CoMemGetLinearPointer(
IN PVOID SystemAddress,
IN ULONG Length
);
NTSTATUS
CoMemGetPciConfig(
IN WORD VendorId,
IN WORD DeviceId,
IN int Instance,
OUT PCI_CONFIG_HEADER_0 *PciCfgHdr
);
NTSTATUS
CoMemSetPciConfig(
IN WORD VendorId,
IN WORD DeviceId,
IN int Instance,
IN PCI_CONFIG_HEADER_0 *PciCfgHdr
);
NTSTATUS
CoMemMapBars(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
void
CoMemUnmapBars(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
GetLinearBarPointer(
IN ULONG PhysicalBarAddress,
IN ULONG Length,
IN OUT PVOID *LinearBarAddress
);
#if DBG
#define CoMemKdPrint(arg) DbgPrint arg
#else
#define CoMemKdPrint(arg)
#endif
#define COMEM_NAME_MAX 64
//
// The device Extension
//
typedef struct
{
WORD vendorId; // PCI vendor ID for this comem device
WORD deviceId; // PCI device ID for this comem device
int instance; // Instance ofthis comem device
ULONG baseAddresses[COMEM_MAX_BARS]; // PCI base address registers for this comem device
PVOID linearBaseAddr[COMEM_MAX_BARS]; // user mode BAR pointers
//
// The whole idea of this driver is to allocate a contiguous buffer that can be
// used for DMA transfers and can be accessed from a user mode app. To accomplish
// this, we need to keep track of three different "pointers" to the buffer.
//
// A kernel mode pointer to the DMA buffer. It
// is above 2GB, so it can't be accessed from user mode.
// This is the pointer that the driver will use to access the
// buffer
//
PVOID systemAddr;
//
// A user mode pointer to the DMA buffer. This is the pointer that a user
// can use to access the DMA buffer. This pointer is only valid in the context of
// the user mode process that allocated the buffer.
//
PVOID linearAddr;
//
// Actual physical address of the DMA buffer.
//
DWORD physAddr;
//
// The size of the DMA buffer.
//
ULONG bufferSize;
ULONG referenceCount; // the number of open handles to this device
// Name buffer for our named Functional device object link
WCHAR DeviceLinkNameBuffer[COMEM_NAME_MAX];
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
// Installable driver initialization entry point.
// This entry point is called directly by the I/O system.
//
// Arguments:
//
// DriverObject - pointer to the driver object
//
// RegistryPath - pointer to a unicode string representing the path
// to driver-specific key in the registry
//
// Return Value:
//
// STATUS_SUCCESS if successful,
// STATUS_UNSUCCESSFUL otherwise
//
//////////////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PDEVICE_OBJECT deviceObject = NULL;
int instance = 0;
CoMemKdPrint (("COMEM.SYS: entering DriverEntry\n"));
//
// Create dispatch points for device control, create, close.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CoMemDispatch;
DriverObject->DriverUnload = CoMemUnload;
//
// create a device object for the comem device. For now create
// a single device object. This driver will eventually be updated
// to search for Comem devices in the system and will create
// a device object for each one
//
//
// Create a device object for each comem device in the system
//
while (NT_SUCCESS(CoMemCreateDeviceObject(DriverObject,&deviceObject, RegistryPath, instance++)));
CoMemKdPrint (("COMEM.SYS: exiting DriverEntry\n"));
return STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// STATUS_SUCCESS if successful,
// STATUS_UNSUCCESSFUL otherwise
//
//////////////////////////////////////////////////////////////////////////
NTSTATUS
CoMemCreateDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT *DeviceObject,
IN PUNICODE_STRING RegistryPath,
LONG Instance
)
{
WCHAR deviceNameBuffer[] = L"\\Device\\COMEM-0";
UNICODE_STRING deviceNameUnicodeString;
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\COMEM-0";
UNICODE_STRING deviceLinkUnicodeString;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
PCI_CONFIG_HEADER_0 pciCfg;
int i;
WORD vendorId = 0;
WORD deviceId = 0;
CoMemKdPrint (("COMEM.SYS: entering CoMemCreateDeviceObject\n"));
//
// Fix up the device name based on Instance
//
deviceLinkBuffer[18] = (USHORT) ('0' + Instance);
deviceNameBuffer[14] = (USHORT) ('0' + Instance);
RtlInitUnicodeString (&deviceNameUnicodeString,
deviceNameBuffer);
ntStatus = IoCreateDevice (DriverObject,
sizeof(DEVICE_EXTENSION),
&deviceNameUnicodeString,
FILE_DEVICE_COMEM,
0,
FALSE,
DeviceObject);
CoMemKdPrint (("COMEM.SYS: returned from IoCreateDevice\n"));
if (NT_SUCCESS(ntStatus))
{
//
// initialize the Device Extension
//
deviceExtension = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);
RtlZeroMemory((PVOID)deviceExtension,sizeof(DEVICE_EXTENSION));
deviceExtension->referenceCount = 0;
//
// fill in pci information about this device in the device extension.
// First get the target vendor and device ID's from the registry
// (CoMemGetVendorId(), CoMemGetDeviceId()), then try to find them
// them on the PCI bus (CoMemGetPciConfig()).
//
CoMemGetVendorId(RegistryPath, &vendorId);
CoMemGetDeviceId(RegistryPath, &deviceId);
ntStatus = CoMemGetPciConfig(vendorId, deviceId, Instance, &pciCfg);
if (!NT_SUCCESS(ntStatus))
{
CoMemKdPrint (("COMEM.SYS: Unable to locate comem device\n"));
IoDeleteDevice (*DeviceObject);
return ntStatus;
}
else
{
deviceExtension->vendorId = pciCfg.VendorID;
deviceExtension->deviceId = pciCfg.DeviceID;
deviceExtension->instance = Instance;
for (i = 0; i < COMEM_MAX_BARS; i++)
{
deviceExtension->baseAddresses[i] = pciCfg.BaseAddresses[i];
}
}
//
// Create a symbolic link, e.g. a name that a Win32 app can specify
// to open the device
//
RtlInitUnicodeString(&deviceLinkUnicodeString,
deviceLinkBuffer);
ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
&deviceNameUnicodeString);
RtlCopyMemory(deviceExtension->DeviceLinkNameBuffer,
deviceLinkBuffer,
sizeof(deviceLinkBuffer));
if (!NT_SUCCESS(ntStatus))
{
//
// Symbolic link creation failed- note this & then delete the
// device object (it's useless if a Win32 app can't get at it).
//
CoMemKdPrint (("COMEM.SYS: IoCreateSymbolicLink failed\n"));
IoDeleteDevice (*DeviceObject);
return ntStatus;
}
}
else
{
CoMemKdPrint (("COMEM.SYS: IoCreateDevice failed\n"));
}
CoMemKdPrint (("COMEM.SYS: exiting CoMemCreateDeviceObject\n"));
return ntStatus;
}
NTSTATUS
CoMemGetVendorId(
IN PUNICODE_STRING RegistryPath,
OUT WORD * vendorId
)
{
UNICODE_STRING paramPath;
static WCHAR SubKeyString[] = L"\\Parameters";
RTL_QUERY_REGISTRY_TABLE paramTable[2];
ULONG zero = 0;
CoMemKdPrint (("COMEM.SYS: Enter CoMemGetVendorId\n"));
//
// The registry path parameter points to our key, we will append
// the Parameters key and look for any additional configuration items
// there. We add room for a trailing NUL for those routines which
// require it.
paramPath.MaximumLength = RegistryPath->Length + sizeof(SubKeyString);
paramPath.Buffer = ExAllocatePool(PagedPool, paramPath.MaximumLength);
if (paramPath.Buffer != NULL)
{
RtlCopyMemory(paramPath.Buffer, RegistryPath->Buffer, RegistryPath->Length);
RtlCopyMemory(¶mPath.Buffer[RegistryPath->Length / 2], SubKeyString,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -