📄 util.c
字号:
#pragma warning( disable : 4054 4055 4152 )
return IoSetCancelRoutine(Irp, CancelRoutine);
// #pragma warning( pop )
}
BOOLEAN
CheckPort(
IN PUCHAR wPortAddr,
IN UCHAR bMask,
IN UCHAR bValue,
IN USHORT usTimeDelay
)
/*++
Routine Description:
This routine will loop for a given time period (actual time is
passed in as an arguement) and wait for the dsr to match
predetermined value (dsr value is passed in).
Arguments:
wPortAddr - Supplies the base address of the parallel port + some offset.
This will have us point directly to the dsr (controller + 1).
bMask - Mask used to determine which bits we are looking at
bValue - Value we are looking for.
usTimeDelay - Max time to wait for peripheral response (in us)
Return Value:
TRUE if a dsr match was found.
FALSE if the time period expired before a match was found.
--*/
{
UCHAR dsr;
LARGE_INTEGER Wait;
LARGE_INTEGER Start;
LARGE_INTEGER End;
// Do a quick check in case we have one stinkingly fast peripheral!
dsr = READ_PORT_UCHAR(wPortAddr);
if ((dsr & bMask) == bValue)
return TRUE;
Wait.QuadPart = (usTimeDelay * 10 * 10) + KeQueryTimeIncrement();
KeQueryTickCount(&Start);
CheckPort_Start:
KeQueryTickCount(&End);
dsr = READ_PORT_UCHAR(wPortAddr);
if ((dsr & bMask) == bValue)
return TRUE;
if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart)
{
// We timed out!!!
#if DBG
PptDump2(PARERRORS, ("CheckPort: Timeout\n"));
PptDump2(PARERRORS, ("<==========================================================\n"));
{
int i;
for (i = 3; i < 8; i++) {
if ((bMask >> i) & 1) {
if (((bValue >> i) & 1) != ((dsr >> i) & 1)) {
PptDump2(PARERRORS, ("\t\t Bit %d is %d and should be %d!!!\n",
i, (dsr >> i) & 1, (bValue >> i) & 1));
}
}
}
}
PptDump2(PARERRORS, ("<==========================================================\n"));
#endif
goto CheckPort_TimeOut;
}
goto CheckPort_Start;
CheckPort_TimeOut:
return FALSE;
}
NTSTATUS
PptBuildParallelPortDeviceName(
IN ULONG Number,
OUT PUNICODE_STRING DeviceName
)
/*++
Routine Description:
Build a Device Name of the form: \Device\ParallelPortN
*** On success this function returns allocated memory that must be freed by the caller
Arguments:
DriverObject - ParPort driver object
PhysicalDeviceObject - PDO whose stack the ParPort FDO will attach to
DeviceObject - ParPort FDO
UniNameString - the DeviceName (e.g., \Device\ParallelPortN)
PortName - the "LPTx" PortName from the devnode
PortNumber - the "N" in \Device\ParallelPortN
Return Value:
STATUS_SUCCESS on success
error status otherwise
--*/
{
UNICODE_STRING uniDeviceString;
UNICODE_STRING uniBaseNameString;
UNICODE_STRING uniPortNumberString;
WCHAR wcPortNum[10];
NTSTATUS status;
PptDump2(PARPNP1, ("util::PptBuildParallelPortDeviceName - Enter - Number=%d\n", Number) );
//
// Init strings
//
RtlInitUnicodeString( DeviceName, NULL );
RtlInitUnicodeString( &uniDeviceString, (PWSTR)L"\\Device\\" );
RtlInitUnicodeString( &uniBaseNameString, (PWSTR)DD_PARALLEL_PORT_BASE_NAME_U );
//
// Convert Port Number to UNICODE_STRING
//
uniPortNumberString.Length = 0;
uniPortNumberString.MaximumLength = sizeof( wcPortNum );
uniPortNumberString.Buffer = wcPortNum;
status = RtlIntegerToUnicodeString( Number, 10, &uniPortNumberString);
if( !NT_SUCCESS( status ) ) {
PptDump2(PARERRORS, ("util::PptBuildParallelPortDeviceName - RtlIntegerToUnicodeString FAILED\n") );
return status;
}
//
// Compute size required and alloc a buffer
//
DeviceName->MaximumLength = (USHORT)( uniDeviceString.Length +
uniBaseNameString.Length +
uniPortNumberString.Length +
sizeof(UNICODE_NULL) );
DeviceName->Buffer = ExAllocatePool( PagedPool, DeviceName->MaximumLength );
if( NULL == DeviceName->Buffer ) {
PptDump2(PARERRORS, ("util::PptBuildParallelPortDeviceName - Alloc Buffer FAILED\n") );
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( DeviceName->Buffer, DeviceName->MaximumLength );
//
// Catenate the parts to construct the DeviceName
//
RtlAppendUnicodeStringToString(DeviceName, &uniDeviceString);
RtlAppendUnicodeStringToString(DeviceName, &uniBaseNameString);
RtlAppendUnicodeStringToString(DeviceName, &uniPortNumberString);
return STATUS_SUCCESS;
}
NTSTATUS
PptInitializeDeviceExtension(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING UniNameString,
IN PWSTR PortName,
IN ULONG PortNumber
)
/*++
Routine Description:
Initialize a ParPort FDO DeviceExtension
Arguments:
DriverObject - ParPort driver object
PhysicalDeviceObject - PDO whose stack the ParPort FDO will attach to
DeviceObject - ParPort FDO
UniNameString - the DeviceName (e.g., \Device\ParallelPortN)
PortName - the "LPTx" PortName from the devnode
PortNumber - the "N" in \Device\ParallelPortN
Return Value:
STATUS_SUCCESS on success
error status otherwise
--*/
{
PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
RtlZeroMemory( Extension, sizeof(DEVICE_EXTENSION) );
//
// ExtensionSignature helps confirm that we are looking at a Parport DeviceExtension
//
Extension->ExtensionSignatureBegin = 0x78877887;
Extension->ExtensionSignatureEnd = 0x87788778;
//
// Standard Info
//
Extension->DriverObject = DriverObject;
Extension->PhysicalDeviceObject = PhysicalDeviceObject;
Extension->DeviceObject = DeviceObject;
Extension->PnpInfo.PortNumber = PortNumber; // this is the "N" in \Device\ParallelPortN
//
// Mutual Exclusion initialization
//
IoInitializeRemoveLock(&Extension->RemoveLock, PARPORT_POOL_TAG, 1, 10);
ExInitializeFastMutex(&Extension->OpenCloseMutex);
ExInitializeFastMutex(&Extension->ExtensionFastMutex);
//
// chipset detection initialization - redundant, but safer
//
Extension->NationalChipFound = FALSE;
Extension->NationalChecked = FALSE;
//
// Initialize 'WorkQueue' - a Queue for Allocate and Select requests
//
InitializeListHead(&Extension->WorkQueue);
Extension->WorkQueueCount = -1;
//
// Initialize Exports - Exported via Internal IOCTLs
//
Extension->PortInfo.FreePort = PptFreePort;
Extension->PortInfo.TryAllocatePort = PptTryAllocatePort;
Extension->PortInfo.QueryNumWaiters = PptQueryNumWaiters;
Extension->PortInfo.Context = Extension;
Extension->PnpInfo.HardwareCapabilities = PPT_NO_HARDWARE_PRESENT;
Extension->PnpInfo.TrySetChipMode = PptSetChipMode;
Extension->PnpInfo.ClearChipMode = PptClearChipMode;
Extension->PnpInfo.TrySelectDevice = PptTrySelectDevice;
Extension->PnpInfo.DeselectDevice = PptDeselectDevice;
Extension->PnpInfo.Context = Extension;
Extension->PnpInfo.PortName = PortName;
//
// List of devices to report in reponse to
// QUERY_DEVICE_RELATIONS/RemovalRelations
//
InitializeListHead( &Extension->RemovalRelationsList );
//
// Empty list of interrupt service routines, interrupt NOT connected
//
InitializeListHead( &Extension->IsrList );
Extension->InterruptObject = NULL;
Extension->InterruptRefCount = 0;
//
// Initialize the free port DPC.
//
KeInitializeDpc( &Extension->FreePortDpc, PptFreePortDpc, Extension );
//
// Save Device Name in our extension
//
{
ULONG bufferLength = UniNameString->MaximumLength + sizeof(UNICODE_NULL);
Extension->DeviceName.Buffer = ExAllocatePool(NonPagedPool, bufferLength);
if( !Extension->DeviceName.Buffer ) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( Extension->DeviceName.Buffer, bufferLength );
Extension->DeviceName.Length = 0;
Extension->DeviceName.MaximumLength = UniNameString->MaximumLength;
RtlCopyUnicodeString( &Extension->DeviceName, UniNameString );
}
//
// Port is in default mode and mode has not been set
// by a lower filter driver
//
Extension->PnpInfo.CurrentMode = INITIAL_MODE;
Extension->FilterMode = FALSE;
return STATUS_SUCCESS;
}
NTSTATUS
PptGetPortNumberFromLptName(
IN PWSTR PortName,
OUT PULONG PortNumber
)
/*++
Routine Description:
Verify that the LptName is of the form LPTn, if so then return
the integer value of n
Arguments:
PortName - the PortName extracted from the devnode - expected to be
of the form: "LPTn"
PortNumber - points to the UNLONG that will hold the result on success
Return Value:
STATUS_SUCCESS on success - *PortNumber will contain the integer value of n
error status otherwise
--*/
{
NTSTATUS status;
UNICODE_STRING str;
//
// Verify that the PortName looks like LPTx where x is a number
//
if( PortName[0] != L'L' || PortName[1] != L'P' || PortName[2] != L'T' ) {
PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - name prefix doesn't look like LPT\n"));
return STATUS_UNSUCCESSFUL;
}
//
// prefix is LPT, check for integer suffix with value > 0
//
RtlInitUnicodeString( &str, (PWSTR)&PortName[3] );
status = RtlUnicodeStringToInteger( &str, 10, PortNumber );
if( !NT_SUCCESS( status ) ) {
PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - name suffix doesn't look like an integer\n"));
return STATUS_UNSUCCESSFUL;
}
if( *PortNumber == 0 ) {
PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - name suffix == 0 - FAIL - Invalid value\n"));
return STATUS_UNSUCCESSFUL;
}
PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - LPT name suffix= %d\n", *PortNumber));
return STATUS_SUCCESS;
}
PDEVICE_OBJECT
PptBuildDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine constructs and initializes a parport FDO
Arguments:
DriverObject - Pointer to the parport driver object
PhysicalDeviceObject - Pointer to the PDO whose stack we will attach to
Return Value:
Pointer to the new ParPort Device Object on Success
NULL otherwise
--*/
{
UNICODE_STRING uniNameString = {0,0,0};
ULONG portNumber = 0;
PWSTR portName = NULL;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Enter\n"));
//
// Get the LPTx name for this port from the registry.
//
// The initial LPTx name for a port is determined by the ports class installer
// msports.dll, but the name can subsequently be changed by the user via
// a device manager property page.
//
portName = PptGetPortNameFromPhysicalDeviceObject( PhysicalDeviceObject );
if( NULL == portName ) {
PptDump2(PARERRORS, ("util::PptBuildDeviceObject - get LPTx Name from registry - FAILED\n") );
goto targetExit;
}
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - portName = <%S>\n", portName));
//
// Extract the preferred port number N to use for the \Device\ParallelPortN
// DeviceName from the LPTx name
//
// Preferred DeviceName for LPT(n) is ParallelPort(n-1) - e.g., LPT3 -> ParallelPort2
//
status = PptGetPortNumberFromLptName( portName, &portNumber );
if( !NT_SUCCESS( status ) ) {
PptDump2(PARERRORS, ("util::PptBuildDeviceObject - extract portNumber from LPTx Name - FAILED\n") );
ExFreePool( portName );
goto targetExit;
}
--portNumber; // convert 1 (LPT) based number to 0 (ParallelPort) based number
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - portNumber (after decrement) = %d\n", portNumber));
//
// Build a DeviceName of the form: \Device\ParallelPortN
//
status = PptBuildParallelPortDeviceName(portNumber, &uniNameString);
if( !NT_SUCCESS( status ) ) {
// we couldn't make up a name - bail out
PptDump2(PARERRORS, ("util::PptBuildDeviceObject - Build ParallelPort DeviceName - FAILED\n") );
ExFreePool( portName );
goto targetExit;
}
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - uniNameString = <%wZ>\n", &uniNameString));
//
// Create the device object for this device.
//
status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &uniNameString,
FILE_DEVICE_PARALLEL_PORT, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);
if( STATUS_OBJECT_NAME_COLLISION == status ) {
//
// Preferred DeviceName already exists - try made up names
//
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Initial Device Creation FAILED - Name Collision\n"));
//
// use an offset so that our made up names won't collide with
// the preferred names of ports that have not yet started
// (start with ParallelPort8)
//
#define PPT_CLASSNAME_OFFSET 7
portNumber = PPT_CLASSNAME_OFFSET;
do {
RtlFreeUnicodeString( &uniNameString );
++portNumber;
status = PptBuildParallelPortDeviceName(portNumber, &uniNameString);
if( !NT_SUCCESS( status ) ) {
// we couldn't make up a name - bail out
PptDump2(PARERRORS, ("util::PptBuildDeviceObject - Build ParallelPort DeviceName - FAILED\n") );
ExFreePool( portName );
goto targetExit;
}
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Trying Device Creation <%wZ>\n", &uniNameString));
status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &uniNameString,
FILE_DEVICE_PARALLEL_PORT, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);
} while( STATUS_OBJECT_NAME_COLLISION == status );
}
if( !NT_SUCCESS( status ) ) {
// we got a failure other than a name collision - bail out
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Device Creation FAILED - status=%x\n", status));
deviceObject = NULL;
ExFreePool( portName );
goto targetExit;
}
//
// We have a deviceObject - Initialize DeviceExtension
//
status = PptInitializeDeviceExtension( DriverObject, PhysicalDeviceObject, deviceObject,
&uniNameString, portName, portNumber );
if( !NT_SUCCESS( status ) ) {
// failure initializing the device extension - clean up and bail out
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Device Initialization FAILED - status=%x\n", status));
IoDeleteDevice( deviceObject );
deviceObject = NULL;
ExFreePool( portName );
goto targetExit;
}
//
// Propagate the power pagable flag of the PDO to our new FDO
//
if( PhysicalDeviceObject->Flags & DO_POWER_PAGABLE ) {
deviceObject->Flags |= DO_POWER_PAGABLE;
}
PptDump2(PARPNP1, ("util::PptBuildDeviceObject - SUCCESS - deviceObject= %x\n", deviceObject));
targetExit:
RtlFreeUnicodeString( &uniNameString );
return deviceObject;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -