📄 pnp.c
字号:
status = Irp->IoStatus.Status;
//
// NB: since we are a bus enumerator, we have no one to whom we could
// defer these irps. Therefore we do not pass them down but merely
// return them.
//
switch (IrpStack->MinorFunction) {
case IRP_MN_QUERY_CAPABILITIES:
Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Query Caps \n"));
//
// Get the packet.
//
deviceCapabilities=IrpStack->Parameters.DeviceCapabilities.Capabilities;
//
// Set the capabilities.
//
deviceCapabilities->Version = 1;
deviceCapabilities->Size = sizeof (DEVICE_CAPABILITIES);
//
// We cannot wake the system.
//
deviceCapabilities->SystemWake = ((PFDO_DEVICE_DATA)DeviceData->ParentFdo->DeviceExtension)->SystemWake;
deviceCapabilities->DeviceWake = ((PFDO_DEVICE_DATA)DeviceData->ParentFdo->DeviceExtension)->DeviceWake;
//
// We have no latencies
//
deviceCapabilities->D1Latency = 0;
deviceCapabilities->D2Latency = 0;
deviceCapabilities->D3Latency = 0;
deviceCapabilities->UniqueID = FALSE;
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_DEVICE_TEXT: {
if ((IrpStack->Parameters.QueryDeviceText.DeviceTextType
!= DeviceTextDescription) || DeviceData->DevDesc.Buffer == NULL) {
break;
}
returnBuffer = ExAllocatePool(PagedPool, DeviceData->DevDesc.Length);
if (returnBuffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
status = STATUS_SUCCESS;
RtlCopyMemory(returnBuffer, DeviceData->DevDesc.Buffer,
DeviceData->DevDesc.Length);
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE,
("TextID: buf 0x%x\n", returnBuffer));
Irp->IoStatus.Information = (ULONG_PTR)returnBuffer;
break;
}
case IRP_MN_QUERY_ID:
//
// Query the IDs of the device
//
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE,
("QueryID: 0x%x\n", IrpStack->Parameters.QueryId.IdType));
switch (IrpStack->Parameters.QueryId.IdType) {
case BusQueryInstanceID:
//
// Build an instance ID. This is what PnP uses to tell if it has
// seen this thing before or not. Build it from the first hardware
// id and the port number.
//
// NB since we do not incorperate the port number
// this method does not produce unique ids;
//
// return 0000 for all devices and have the flag set to not unique
//
status = STATUS_SUCCESS;
length = SERENUM_INSTANCE_IDS_LENGTH * sizeof(WCHAR);
returnBuffer = ExAllocatePool(PagedPool, length);
if (returnBuffer != NULL) {
RtlCopyMemory(returnBuffer, SERENUM_INSTANCE_IDS, length);
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE,
("InstanceID: buf 0x%x\n", returnBuffer));
Irp->IoStatus.Information = (ULONG_PTR)returnBuffer;
break;
//
// The other ID's we just copy from the buffers and are done.
//
case BusQueryDeviceID:
case BusQueryHardwareIDs:
case BusQueryCompatibleIDs:
{
PUNICODE_STRING pId;
status = STATUS_SUCCESS;
switch (IrpStack->Parameters.QueryId.IdType) {
case BusQueryDeviceID:
pId = &DeviceData->DeviceIDs;
break;
case BusQueryHardwareIDs:
pId = &DeviceData->HardwareIDs;
break;
case BusQueryCompatibleIDs:
pId = &DeviceData->CompIDs;
break;
}
buffer = pId->Buffer;
if (buffer != NULL) {
length = pId->Length;
returnBuffer = ExAllocatePool(PagedPool, length);
if (returnBuffer != NULL) {
#if DBG
RtlFillMemory(returnBuffer, length, 0xff);
#endif
RtlCopyMemory(returnBuffer, buffer, pId->Length);
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE,
("ID: Unicode 0x%x\n", pId));
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE,
("ID: buf 0x%x\n", returnBuffer));
Irp->IoStatus.Information = (ULONG_PTR)returnBuffer;
}
break;
}
break;
case IRP_MN_QUERY_BUS_INFORMATION: {
PPNP_BUS_INFORMATION pBusInfo;
ASSERTMSG("Serenum appears not to be the sole bus?!?",
Irp->IoStatus.Information == (ULONG_PTR)NULL);
pBusInfo = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
if (pBusInfo == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
pBusInfo->BusTypeGuid = GUID_BUS_TYPE_SERENUM;
pBusInfo->LegacyBusType = PNPBus;
//
// We really can't track our bus number since we can be torn
// down with our bus
//
pBusInfo->BusNumber = 0;
Irp->IoStatus.Information = (ULONG_PTR)pBusInfo;
status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
switch (IrpStack->Parameters.QueryDeviceRelations.Type) {
case TargetDeviceRelation: {
PDEVICE_RELATIONS pDevRel;
//
// No one else should respond to this since we are the PDO
//
ASSERT(Irp->IoStatus.Information == 0);
if (Irp->IoStatus.Information != 0) {
break;
}
pDevRel = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
if (pDevRel == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
pDevRel->Count = 1;
pDevRel->Objects[0] = DeviceObject;
ObReferenceObject(DeviceObject);
status = STATUS_SUCCESS;
Irp->IoStatus.Information = (ULONG_PTR)pDevRel;
break;
}
default:
break;
}
break;
case IRP_MN_START_DEVICE:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("Start Device\n"));
//
// Here we do what ever initialization and ``turning on'' that is
// required to allow others to access this device.
//
//
// Set the polling period value in the registry for this device.
// This value is the same as the Parent FDO's polling period.
//
status = IoOpenDeviceRegistryKey(DeviceObject, PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_WRITE, &keyHandle);
if (!NT_SUCCESS(status)) {
//
// This is a fatal error. If we can't get to our registry key,
// we are sunk.
//
Serenum_KdPrint(DeviceData, SER_DBG_SS_ERROR,
("IoOpenDeviceRegistryKey failed - %x\n", status));
} else {
RtlInitUnicodeString(&keyName, L"DeviceDetectionTimeout");
PollingPeriod =
((PFDO_DEVICE_DATA)DeviceData->ParentFdo->DeviceExtension)->
PollingPeriod;
//
// Doesn't matter whether this works or not.
//
ZwSetValueKey(keyHandle, &keyName, 0, REG_DWORD, &PollingPeriod,
sizeof(ULONG));
ZwClose(keyHandle);
}
DeviceData->Started = TRUE;
status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("Stop Device\n"));
//
// Here we shut down the device. The opposite of start.
//
DeviceData->Started = FALSE;
status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("Remove Device\n"));
//
// Attached is only set to FALSE by the enumeration process.
//
if (!DeviceData->Attached) {
status = Serenum_PnPRemove(DeviceObject, DeviceData);
}
else {
//
// Succeed the remove
///
status = STATUS_SUCCESS;
}
break;
case IRP_MN_QUERY_STOP_DEVICE:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("Query Stop Device\n"));
//
// No reason here why we can't stop the device.
// If there were a reason we should speak now for answering success
// here may result in a stop device irp.
//
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_STOP_DEVICE:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("Cancel Stop Device\n"));
//
// The stop was canceled. Whatever state we set, or resources we put
// on hold in anticipation of the forcoming STOP device IRP should be
// put back to normal. Someone, in the long list of concerned parties,
// has failed the stop device query.
//
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("Query Remove Device\n"));
//
// Just like Query Stop only now the impending doom is the remove irp
//
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("Cancel Remove Device"
"\n"));
//
// Clean up a remove that did not go through, just like cancel STOP.
//
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
case IRP_MN_READ_CONFIG:
case IRP_MN_WRITE_CONFIG: // we have no config space
case IRP_MN_EJECT:
case IRP_MN_SET_LOCK:
case IRP_MN_QUERY_INTERFACE: // We do not have any non IRP based interfaces.
default:
Serenum_KdPrint(DeviceData, SER_DBG_PNP_TRACE, ("PNP Not handled 0x%x\n",
IrpStack->MinorFunction));
// For PnP requests to the PDO that we do not understand we should
// return the IRP WITHOUT setting the status or information fields.
// They may have already been set by a filter (eg acpi).
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
Serenum_PnPRemove (PDEVICE_OBJECT Device, PPDO_DEVICE_DATA PdoData)
/*++
Routine Description:
The PlugPlay subsystem has instructed that this PDO should be removed.
We should therefore
- Complete any requests queued in the driver
- If the device is still attached to the system,
then complete the request and return.
- Otherwise, cleanup device specific allocations, memory, events...
- Call IoDeleteDevice
- Return from the dispatch routine.
Note that if the device is still connected to the bus (IE in this case
the control panel has not yet told us that the serial device has
disappeared) then the PDO must remain around, and must be returned during
any query Device relaions IRPS.
--*/
{
Serenum_KdPrint(PdoData, SER_DBG_PNP_TRACE,
("Serenum_PnPRemove: 0x%x\n", Device));
ASSERT(PdoData->Removed == FALSE);
PdoData->Removed = TRUE;
//
// Complete any outstanding requests with STATUS_DELETE_PENDING.
//
// Serenum does not queue any irps at this time so we have nothing to do.
//
if (PdoData->Attached) {
return STATUS_SUCCESS;
}
//
// Free any resources.
//
RtlFreeUnicodeString(&PdoData->HardwareIDs);
RtlFreeUnicodeString(&PdoData->CompIDs);
RtlFreeUnicodeString(&PdoData->DeviceIDs);
Serenum_KdPrint(PdoData, SER_DBG_PNP_INFO,
("IoDeleteDevice: 0x%x\n", Device));
IoDeleteDevice(Device);
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -