📄 genport.c.bak
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation, All Rights Reserved
Module Name:
genport.c
Abstract: Generic Port I/O driver for Windows 2000
Author: Author: Robert R. Howell January 8, 1993
Environment:
Kernel mode
Revision History:
Robert B. Nelson (Microsoft) January 12, 1993
Cleaned up comments
Enabled and tested resource reporting
Added code to retrieve I/O address and port count from the Registry.
Robert B. Nelson (Microsoft) March 1, 1993
Added support for byte, word, and long I/O.
Added support for MIPS.
Fixed resource reporting.
Robert B. Nelson (Microsoft) May 1, 1993
Fixed port number validation.
Robert B. Nelson (Microsoft) Oct 25, 1993
Fixed MIPS support.
Eliyas Yakub
Fixed AddressSpace Bug Nov 30, 1997
Eliyas Yakub
Converted to Windows 2000 Dec 29, 1998
--*/
#include "genport.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, GpdAddDevice)
#pragma alloc_text (PAGE, GpdDispatchPnp)
#pragma alloc_text (PAGE, GpdDispatchSystemControl)
#pragma alloc_text (PAGE, GpdUnload)
#pragma alloc_text (PAGE, GpdDispatch)
#pragma alloc_text (PAGE, GpdIoctlReadPort)
#pragma alloc_text (PAGE, GpdIoctlWritePort)
#pragma alloc_text (PAGE, GpdStartDevice)
#endif
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
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
--*/
{
UNREFERENCED_PARAMETER (RegistryPath);
DebugPrint (("Entered Driver Entry\n"));
//
// Create dispatch points for the IRPs.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = GpdDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = GpdDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = GpdDispatch;
DriverObject->DriverUnload = GpdUnload;
DriverObject->MajorFunction[IRP_MJ_PNP] = GpdDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = GpdDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = GpdDispatchSystemControl;
DriverObject->DriverExtension->AddDevice = GpdAddDevice;
return STATUS_SUCCESS;
}
NTSTATUS
GpdAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
The Plug & Play subsystem is handing us a brand new PDO, for which we
(by means of INF registration) have been asked to provide a driver.
We need to determine if we need to be in the driver stack for the device.
Create a functional device object to attach to the stack
Initialize that device object
Return status success.
Remember: we can NOT actually send ANY non pnp IRPS to the given driver
stack, UNTIL we have received an IRP_MN_START_DEVICE.
Arguments:
DeviceObject - pointer to a device object.
PhysicalDeviceObject - pointer to a device object created by the
underlying bus driver.
Return Value:
NT status code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PLOCAL_DEVICE_INFO deviceInfo;
UNICODE_STRING ntDeviceName;
UNICODE_STRING win32DeviceName;
PAGED_CODE();
RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME);
//
// Create a device object.
//
status = IoCreateDevice (DriverObject,
sizeof (LOCAL_DEVICE_INFO),
&ntDeviceName,
GPD_TYPE,
0,
FALSE,
&deviceObject);
if (!NT_SUCCESS (status)) {
//
// Either not enough memory to create a deviceobject or another
// deviceobject with the same name exits. This could happen
// if you install another instance of this device.
//
return status;
}
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
if (!NT_SUCCESS(status)) // If we we couldn't create the link then
{ // abort installation.
IoDeleteDevice(deviceObject);
return status;
}
deviceInfo = (PLOCAL_DEVICE_INFO) deviceObject->DeviceExtension;
deviceInfo->NextLowerDriver = IoAttachDeviceToDeviceStack (
deviceObject,
PhysicalDeviceObject);
if(NULL == deviceInfo->NextLowerDriver) {
IoDeleteSymbolicLink(&win32DeviceName);
IoDeleteDevice(deviceObject);
return STATUS_NO_SUCH_DEVICE;
}
IoInitializeRemoveLock (&deviceInfo->RemoveLock ,
PORTIO_TAG,
1, // MaxLockedMinutes
5); // HighWatermark, this parameter is
// used only on checked build.
//
// Set the flag if the device is not holding a pagefile
// crashdump file or hibernate file.
//
deviceObject->Flags |= DO_POWER_PAGABLE;
deviceInfo->DeviceObject = deviceObject;
deviceInfo->Removed = FALSE;
deviceInfo->Started = FALSE;
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// This values is based on the hardware design.
// Let us assume the address is in I/O space.
//
deviceInfo->PortMemoryType = 1;
DebugPrint(("AddDevice: %p to %p->%p \n", deviceObject,
deviceInfo->NextLowerDriver,
PhysicalDeviceObject));
return STATUS_SUCCESS;
}
NTSTATUS
GpdCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
The completion routine for plug & play irps that needs to be
processed first by the lower drivers.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Context - pointer to an event object.
Return Value:
NT status code
--*/
{
PKEVENT event;
event = (PKEVENT) Context;
UNREFERENCED_PARAMETER(DeviceObject);
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
//
// We could switch on the major and minor functions of the IRP to perform
// different functions, but we know that Context is an event that needs
// to be set.
//
KeSetEvent(event, 0, FALSE);
//
// Allows the caller to reuse the IRP
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
GpdDispatchPnp (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these the driver will completely ignore.
In all cases it must pass the IRP to the next lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
KEVENT event;
UNICODE_STRING win32DeviceName;
PLOCAL_DEVICE_INFO deviceInfo;
UNICODE_STRING devName;
OBJECT_ATTRIBUTES OA;
HANDLE fd;
IO_STATUS_BLOCK ISB;
IO_STATUS_BLOCK IoStatus;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE FileHandle;
UNICODE_STRING fileName;
PAGED_CODE();
deviceInfo = (PLOCAL_DEVICE_INFO) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
status = IoAcquireRemoveLock (&deviceInfo->RemoveLock, NULL);
if (!NT_SUCCESS (status)) {
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
DebugPrint(("%s\n",PnPMinorFunctionString(irpStack->MinorFunction)));
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// The device is starting.
//
// We cannot touch the device (send it any non pnp irps) until a
// start device has been passed down to the lower drivers.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
KeInitializeEvent(&event,
NotificationEvent,
FALSE
);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE) GpdCompletionRoutine,
&event,
TRUE,
TRUE,
TRUE);
status = IoCallDriver(deviceInfo->NextLowerDriver, Irp);
if (STATUS_PENDING == status) {
KeWaitForSingleObject(
&event,
Executive, // Waiting for reason of a driver
KernelMode, // Must be kernelmode if event memory is in stack
FALSE, // No allert
NULL); // No timeout
}
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
status = GpdStartDevice(DeviceObject, Irp);
if(NT_SUCCESS(status))
{
//
// As we are successfully now back from our start device
// we can do work.
//
deviceInfo->Started = TRUE;
deviceInfo->Removed = FALSE;
}
}
//
// We must now complete the IRP, since we stopped it in the
// completion routine with STATUS_MORE_PROCESSING_REQUIRED.
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_STOP_DEVICE:
__asm{
int 3;
};
fileName.Length = 0;
fileName.MaximumLength = sizeof(TEST_PIPE_NAME) + sizeof(UNICODE_NULL);
fileName.Buffer = ExAllocatePool(PagedPool, fileName.MaximumLength );
RtlZeroMemory(fileName.Buffer, fileName.MaximumLength);
status = RtlAppendUnicodeToString(&fileName, (PWSTR)TEST_PIPE_NAME);
InitializeObjectAttributes (&objectAttributes,
(PUNICODE_STRING)&fileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = ZwCreateFile( &FileHandle,
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
&objectAttributes,
&IoStatus,
0,
FILE_ATTRIBUTE_SYSTEM,
FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if (NT_SUCCESS(status) ){
char ut[20];
LARGE_INTEGER ll;
LARGE_INTEGER byteOffset;
byteOffset.LowPart = byteOffset.HighPart = 0;
status = ZwReadFile( FileHandle, NULL, NULL, NULL, &ISB, ut, 20, &ll, NULL );
status = ZwWriteFile( FileHandle, NULL, NULL, NULL, &ISB, ut, 20, &ll, NULL );
ZwClose( FileHandle );
}
//
// Fail the query stop to prevent the system from taking away hardware
// resources. If you do support this you must have a queue to hold
// incoming requests between stop and subsequent start with new set of
// resources.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -