📄 pnp.c
字号:
IRP_MJ_PNP major code (plug-and-play IRPs).
Arguments:
PDevObj - Pointer to the device object for this device
PIrp - Pointer to the IRP for the current request
Return Value:
The function value is the final status of the call
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
NTSTATUS status;
PDEVICE_CAPABILITIES pDevCaps;
PAGED_CODE();
if ((status = SerialIRPPrologue(PIrp, pDevExt)) != STATUS_SUCCESS) {
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return status;
}
switch (pIrpStack->MinorFunction) {
case IRP_MN_QUERY_CAPABILITIES: {
PKEVENT pQueryCapsEvent;
SYSTEM_POWER_STATE cap;
SerialDbgPrintEx(SERPNPPOWER,
"Got IRP_MN_QUERY_DEVICE_CAPABILITIES IRP\n");
pQueryCapsEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
if (pQueryCapsEvent == NULL) {
PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent(pQueryCapsEvent, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(PIrp);
IoSetCompletionRoutine(PIrp, SerialSyncCompletion, pQueryCapsEvent,
TRUE, TRUE, TRUE);
status = IoCallDriver(pLowerDevObj, PIrp);
//
// Wait for lower drivers to be done with the Irp
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject(pQueryCapsEvent, Executive, KernelMode, FALSE,
NULL);
}
ExFreePool(pQueryCapsEvent);
status = PIrp->IoStatus.Status;
if (pIrpStack->Parameters.DeviceCapabilities.Capabilities == NULL) {
goto errQueryCaps;
}
//
// Save off their power capabilities
//
SerialDbgPrintEx(SERPNPPOWER, "Mapping power capabilities\n");
pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
pDevCaps = pIrpStack->Parameters.DeviceCapabilities.Capabilities;
for (cap = PowerSystemSleeping1; cap < PowerSystemMaximum;
cap++) {
#if DBG
SerialDbgPrintEx(SERPNPPOWER, " %d: %s <--> %s\n",
cap, SerSystemCapString[cap],
SerDeviceCapString[pDevCaps->DeviceState[cap]]);
#endif // DBG
pDevExt->DeviceStateMap[cap] = pDevCaps->DeviceState[cap];
}
pDevExt->DeviceStateMap[PowerSystemUnspecified]
= PowerDeviceUnspecified;
pDevExt->DeviceStateMap[PowerSystemWorking]
= PowerDeviceD0;
pDevExt->SystemWake = pDevCaps->SystemWake;
pDevExt->DeviceWake = pDevCaps->DeviceWake;
errQueryCaps:;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return status;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
//
// We just pass this down -- serenum enumerates our bus for us.
//
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_DEVICE_RELATIONS Irp\n");
switch (pIrpStack->Parameters.QueryDeviceRelations.Type) {
case BusRelations:
SerialDbgPrintEx(SERPNPPOWER, "------- BusRelations Query\n");
break;
case EjectionRelations:
SerialDbgPrintEx(SERPNPPOWER, "------- EjectionRelations Query\n");
break;
case PowerRelations:
SerialDbgPrintEx(SERPNPPOWER, "------- PowerRelations Query\n");
break;
case RemovalRelations:
SerialDbgPrintEx(SERPNPPOWER, "------- RemovalRelations Query\n");
break;
case TargetDeviceRelation:
SerialDbgPrintEx(SERPNPPOWER, "------- TargetDeviceRelation Query\n");
break;
default:
SerialDbgPrintEx(SERPNPPOWER, "------- Unknown Query\n");
break;
}
IoSkipCurrentIrpStackLocation(PIrp);
status = SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
return status;
case IRP_MN_QUERY_INTERFACE:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_INTERFACE Irp\n");
break;
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp"
"\n");
break;
case IRP_MN_START_DEVICE: {
PVOID startLockPtr;
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_START_DEVICE Irp\n");
//
// SerialStartDevice will pass this Irp to the next driver,
// and process it as completion so just complete it here.
//
SerialLockPagableSectionByHandle(SerialGlobals.PAGESER_Handle);
//
// We used to make sure the stack was powered up, but now it
// is supposed to be done implicitly by start_device.
// If that wasn't the case we would just make this call:
//
// status = SerialGotoPowerState(PDevObj, pDevExt, PowerDeviceD0);
//
pDevExt->PowerState = PowerDeviceD0;
status = SerialStartDevice(PDevObj, PIrp);
if(!pDevExt->RetainPowerOnClose) {
(void)SerialGotoPowerState(PDevObj, pDevExt, PowerDeviceD3);
}
SerialUnlockPagableImageSection(SerialGlobals.PAGESER_Handle);
PIrp->IoStatus.Status = status;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return status;
}
case IRP_MN_READ_CONFIG:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_READ_CONFIG Irp\n");
break;
case IRP_MN_WRITE_CONFIG:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_WRITE_CONFIG Irp\n");
break;
case IRP_MN_EJECT:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_EJECT Irp\n");
break;
case IRP_MN_SET_LOCK:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_SET_LOCK Irp\n");
break;
case IRP_MN_QUERY_ID: {
UNICODE_STRING pIdBuf;
PWCHAR pPnpIdStr;
ULONG pnpIdStrLen;
ULONG isMulti = 0;
HANDLE pnpKey;
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_ID Irp\n");
if (((pIrpStack->Parameters.QueryId.IdType != BusQueryHardwareIDs)
&& (pIrpStack->Parameters.QueryId.IdType != BusQueryCompatibleIDs))
|| ((pDevExt->Flags & SERIAL_FLAGS_LEGACY_ENUMED) == 0)) {
IoSkipCurrentIrpStackLocation(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
if (pIrpStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) {
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_WRITE, &pnpKey);
if (!NT_SUCCESS(status)) {
PIrp->IoStatus.Status = status;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return status;
}
isMulti = 0;
status = SerialGetRegistryKeyValue(pnpKey, L"MultiportDevice",
sizeof(L"MultiportDevice"),
&isMulti, sizeof(ULONG));
ZwClose(pnpKey);
pPnpIdStr = isMulti ? SERIAL_PNP_MULTI_ID_STR : SERIAL_PNP_ID_STR;
pnpIdStrLen = isMulti ? sizeof(SERIAL_PNP_MULTI_ID_STR)
: sizeof(SERIAL_PNP_ID_STR);
if (PIrp->IoStatus.Information != 0) {
ULONG curStrLen;
ULONG allocLen = 0;
PWSTR curStr = (PWSTR)PIrp->IoStatus.Information;
//
// We have to walk the strings to count the amount of space to
// reallocate
//
while ((curStrLen = wcslen(curStr)) != 0) {
allocLen += curStrLen * sizeof(WCHAR) + sizeof(UNICODE_NULL);
curStr += curStrLen + 1;
}
allocLen += sizeof(UNICODE_NULL);
pIdBuf.Buffer = ExAllocatePool(PagedPool, allocLen
+ pnpIdStrLen
+ sizeof(WCHAR));
if (pIdBuf.Buffer == NULL) {
//
// Clean up after other drivers since we are
// sending the irp back up.
//
ExFreePool((PWSTR)PIrp->IoStatus.Information);
PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
PIrp->IoStatus.Information = 0;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
pIdBuf.MaximumLength = (USHORT)(allocLen + pnpIdStrLen);
pIdBuf.Length = (USHORT)allocLen - sizeof(UNICODE_NULL);
RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR));
RtlCopyMemory(pIdBuf.Buffer, (PWSTR)PIrp->IoStatus.Information,
allocLen);
RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);
//
// Free what the previous driver allocated
//
ExFreePool((PWSTR)PIrp->IoStatus.Information);
} else {
SerialDbgPrintEx(SERPNPPOWER, "ID is sole ID\n");
pIdBuf.Buffer = ExAllocatePool(PagedPool, pnpIdStrLen
+ sizeof(WCHAR) * 2);
if (pIdBuf.Buffer == NULL) {
PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
PIrp->IoStatus.Information = 0;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
pIdBuf.MaximumLength = (USHORT)pnpIdStrLen;
pIdBuf.Length = 0;
RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR)
* 2);
RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);
}
PIrp->IoStatus.Information = (ULONG_PTR)pIdBuf.Buffer;
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: {
HANDLE pnpKey;
PKEVENT pResFiltEvent;
ULONG isMulti = 0;
PIO_RESOURCE_REQUIREMENTS_LIST pReqList;
PIO_RESOURCE_LIST pResList;
PIO_RESOURCE_DESCRIPTOR pResDesc;
ULONG i, j;
ULONG reqCnt;
ULONG gotISR;
ULONG gotInt;
ULONG listNum;
SerialDbgPrintEx(SERPNPPOWER, "Got "
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
pResFiltEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
if (pResFiltEvent == NULL) {
PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent(pResFiltEvent, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(PIrp);
IoSetCompletionRoutine(PIrp, SerialSyncCompletion, pResFiltEvent,
TRUE, TRUE, TRUE);
status = IoCallDriver(pLowerDevObj, PIrp);
//
// Wait for lower drivers to be done with the Irp
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject (pResFiltEvent, Executive, KernelMode, FALSE,
NULL);
}
ExFreePool(pResFiltEvent);
if (PIrp->IoStatus.Information == 0) {
if (pIrpStack->Parameters.FilterResourceRequirements
.IoResourceRequirementList == 0) {
SerialDbgPrintEx(SERPNPPOWER, "Can't filter NULL resources!\n");
status = PIrp->IoStatus.Status;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return status;
}
PIrp->IoStatus.Information = (ULONG_PTR)pIrpStack->Parameters
.FilterResourceRequirements
.IoResourceRequirementList;
}
status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_WRITE, &pnpKey);
if (!NT_SUCCESS(status)) {
PIrp->IoStatus.Status = status;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return status;
}
//
// No matter what we add our filter if we can and return success.
//
status = SerialGetRegistryKeyValue (pnpKey, L"MultiportDevice",
sizeof(L"MultiportDevice"),
&isMulti,
sizeof (ULONG));
ZwClose(pnpKey);
//
// Force ISR ports in IO_RES_REQ_LIST to shared status
// Force interrupts to shared status
//
//
// We will only process the first list -- multiport boards
// should not have alternative resources
//
pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)PIrp->IoStatus.Information;
pResList = &pReqList->List[0];
SerialDbgPrintEx(SERPNPPOWER, "List has %x lists (including "
"alternatives)\n", pReqList->AlternativeLists);
for (listNum = 0; listNum < (pReqList->AlternativeLists);
listNum++) {
gotISR = 0;
gotInt = 0;
SerialDbgPrintEx(SERPNPPOWER, "List has %x resources in it\n",
pResList->Count);
for (j = 0; (j < pResList->Count); j++) {
pResDesc = &pResList->Descriptors[j];
switch (pResDesc->Type) {
case CmResourceTypePort:
if (isMulti
&& (pResDesc->u.Port.Length == SERIAL_STATUS_LENGTH)
&& !gotISR) {
gotISR = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -