windows-nt/Source/XPSP1/NT/net/irda/comm/irenum/pdo.c

574 lines
15 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include <internal.h>
#define INITGUID
#include <guiddef.h>
#include <wdmguid.h>
#pragma alloc_text(PAGE,IrEnumPdoPnp)
#pragma alloc_text(PAGE,IrEnumPdoPower)
#pragma alloc_text(PAGE,IrEnumPdoWmi)
#define CHILD_DEVICE_TEXT L"IR Communication Device"
#define HARDWARE_ID_PREFIX L"IRENUM\\"
//#define HARDWARE_ID L"IRENUM\\PNP0501"
NTSTATUS
IrEnumPdoPnp (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handle requests from the PlugPlay system for the devices on the BUS
--*/
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PPDO_DEVICE_EXTENSION PdoDeviceExtension=DeviceObject->DeviceExtension;
PDEVICE_CAPABILITIES deviceCapabilities;
ULONG information;
PWCHAR buffer=NULL;
ULONG length, i, j;
NTSTATUS status;
PAGED_CODE ();
status = Irp->IoStatus.Status;
switch (IrpSp->MinorFunction) {
case IRP_MN_QUERY_CAPABILITIES:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_CAPABILITIES\n");)
//
// Get the packet.
//
deviceCapabilities=IrpSp->Parameters.DeviceCapabilities.Capabilities;
//
// Set the capabilities.
//
deviceCapabilities->Version = 1;
deviceCapabilities->Size = sizeof (DEVICE_CAPABILITIES);
// We cannot wake the system.
deviceCapabilities->SystemWake = PowerSystemUnspecified;
deviceCapabilities->DeviceWake = PowerDeviceUnspecified;
// We have no latencies
deviceCapabilities->D1Latency = 0;
deviceCapabilities->D2Latency = 0;
deviceCapabilities->D3Latency = 0;
// No locking or ejection
deviceCapabilities->LockSupported = FALSE;
deviceCapabilities->EjectSupported = FALSE;
// Device can be physically removed.
// Technically there is no physical device to remove, but this bus
// driver can yank the PDO from the PlugPlay system, when ever it
// receives an IOCTL_SERENUM_REMOVE_PORT device control command.
// deviceCapabilities->Removable = TRUE;
deviceCapabilities->SurpriseRemovalOK=TRUE;
if (PdoDeviceExtension->DeviceDescription->Printer) {
//
// there is no server for printers
//
deviceCapabilities->RawDeviceOK=TRUE;
}
// not Docking device
deviceCapabilities->DockDevice = FALSE;
// deviceCapabilities->UniqueID = TRUE;
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_DEVICE_TEXT:
if (IrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
ULONG BufferLength=0;
if (PdoDeviceExtension->DeviceDescription->Name != NULL) {
BufferLength += wcslen(PdoDeviceExtension->DeviceDescription->Name)*sizeof(WCHAR);
}
if (BufferLength > 0) {
//
// we have a name or manufacturer
//
buffer=ALLOCATE_PAGED_POOL((BufferLength+sizeof(UNICODE_NULL)+sizeof(L" ")));
if (buffer != NULL) {
buffer[0]=L'\0';
if (PdoDeviceExtension->DeviceDescription->Name != NULL) {
wcscat(buffer,PdoDeviceExtension->DeviceDescription->Name);
}
status=STATUS_SUCCESS;
} else {
status=STATUS_INSUFFICIENT_RESOURCES;
}
} else {
//
// no pnp info, just make something up
//
buffer=ALLOCATE_PAGED_POOL(sizeof(CHILD_DEVICE_TEXT));
if (buffer != NULL) {
RtlCopyMemory(buffer,CHILD_DEVICE_TEXT,sizeof(CHILD_DEVICE_TEXT));
status=STATUS_SUCCESS;
} else {
status=STATUS_INSUFFICIENT_RESOURCES;
}
}
Irp->IoStatus.Status=status;
Irp->IoStatus.Information = (ULONG_PTR) buffer;
}
break;
case IRP_MN_QUERY_ID:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_ID\n");)
// Query the IDs of the device
switch (IrpSp->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.
//
ULONG Length;
Length=wcslen(PdoDeviceExtension->DeviceDescription->DeviceName)*sizeof(WCHAR);
buffer = ALLOCATE_PAGED_POOL( Length + sizeof(WCHAR));
if (buffer) {
RtlZeroMemory(buffer, Length + sizeof(WCHAR));
RtlCopyMemory (buffer, PdoDeviceExtension->DeviceDescription->DeviceName, Length);
status=STATUS_SUCCESS;
} else {
status=STATUS_NO_MEMORY;
}
Irp->IoStatus.Status=status;
Irp->IoStatus.Information = (ULONG_PTR) buffer;
break;
}
case BusQueryDeviceID:
case BusQueryHardwareIDs: {
//
// return a multi WCHAR (null terminated) string (null terminated)
// array for use in matching hardare ids in inf files;
//
//
// the device reported and hardware id
//
ULONG Length;
//
// figure out the length, it is multi sz so we need a double null,
//
Length=wcslen(PdoDeviceExtension->DeviceDescription->HardwareId)*sizeof(WCHAR) + (sizeof(UNICODE_NULL)*2) + sizeof(HARDWARE_ID_PREFIX);
buffer = ALLOCATE_PAGED_POOL( Length );
if (buffer != NULL) {
//
// build the hardware is by concatenating irenuum\ with the value retuned by the device
//
RtlZeroMemory(buffer,Length);
if ((IrpSp->Parameters.QueryId.IdType == BusQueryDeviceID) || !PdoDeviceExtension->DeviceDescription->Printer) {
//
// prepend IRENUM\ for the device ID always and for the HARDWARE id when it isn't a printer
//
wcscpy(buffer,HARDWARE_ID_PREFIX);
}
wcscat(buffer,PdoDeviceExtension->DeviceDescription->HardwareId);
status=STATUS_SUCCESS;
} else {
status=STATUS_NO_MEMORY;
}
Irp->IoStatus.Information = (ULONG_PTR) buffer;
break;
}
case BusQueryCompatibleIDs: {
//
// The generic ids for installation of this pdo.
//
ULONG Length=0;
LONG i;
for (i=0; i< PdoDeviceExtension->DeviceDescription->CompatIdCount; i++) {
Length += (wcslen(PdoDeviceExtension->DeviceDescription->CompatId[i])+1)*sizeof(WCHAR)+sizeof(IRENUM_PREFIX);
}
Length += sizeof(WCHAR)*2;
buffer = ALLOCATE_PAGED_POOL(Length);
if (buffer != NULL) {
LONG Index=0;
RtlZeroMemory (buffer, Length);
for (i=0; i< PdoDeviceExtension->DeviceDescription->CompatIdCount; i++) {
if (!PdoDeviceExtension->DeviceDescription->Printer) {
//
// for printers we don't prepend our enumerator name
//
wcscpy(&buffer[Index],IRENUM_PREFIX);
}
wcscat(
&buffer[Index],
PdoDeviceExtension->DeviceDescription->CompatId[i]
);
//
// figure out where the next string should go
//
Index += wcslen(&buffer[Index]) +1 ;
}
status = STATUS_SUCCESS;
} else {
status=STATUS_INSUFFICIENT_RESOURCES;
}
Irp->IoStatus.Information = (ULONG_PTR) buffer;
break;
}
break;
default:
//
// not supported
//
break;
}
break;
case IRP_MN_START_DEVICE: {
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_START_DEVICE\n");)
if (PdoDeviceExtension->DeviceDescription->Printer) {
//
// Need to set a value in the devices parameters key for printers
//
HANDLE Handle;
status=IoOpenDeviceRegistryKey(
DeviceObject,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_READ,
&Handle
);
if (NT_SUCCESS(status)) {
UNICODE_STRING KeyName;
RtlInitUnicodeString(&KeyName,L"PortName");
ZwSetValueKey(
Handle,
&KeyName,
0,
REG_SZ,
L"IR",
sizeof(L"IR")
);
ZwClose(Handle);
}
}
status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_STOP_DEVICE:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_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:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_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_STOP_DEVICE:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_STOP_DEVICE\n");)
// Here we shut down the device. The opposite of start.
status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_SURPRISE_REMOVAL\n");)
status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE: {
PFDO_DEVICE_EXTENSION FdoDeviceExtension=PdoDeviceExtension->ParentFdo->DeviceExtension;
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_REMOVE_DEVICE: %08lx\n",DeviceObject);)
RemoveDevice(FdoDeviceExtension->EnumHandle,PdoDeviceExtension->DeviceDescription);
status=STATUS_SUCCESS;
}
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_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:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_CANCEL_REMOVE_DEVICE\n");)
//
// Clean up a remove that did not go through, just like cancel STOP.
//
status = STATUS_SUCCESS;
break;
case IRP_MN_READ_CONFIG:
D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_READ_CONFIG: Space=%d\n",IrpSp->Parameters.ReadWriteConfig.WhichSpace);)
switch ( IrpSp->Parameters.ReadWriteConfig.WhichSpace ) {
case IRENUM_CONFIG_SPACE_INFO:
if ((IrpSp->Parameters.ReadWriteConfig.Length >= sizeof(IRCOMM_BUS_INFO))) {
IRCOMM_BUS_INFO BusInfo;
BusInfo.DeviceAddress= PdoDeviceExtension->DeviceDescription->DeviceId;
BusInfo.OutGoingConnection=!PdoDeviceExtension->DeviceDescription->Static;
RtlCopyMemory(
IrpSp->Parameters.ReadWriteConfig.Buffer,
&BusInfo,
sizeof(BusInfo)
);
status = STATUS_SUCCESS;
Irp->IoStatus.Information=sizeof(BusInfo);
break;
}
status=STATUS_BUFFER_TOO_SMALL;
break;
default:
break;
}
break;
case IRP_MN_QUERY_BUS_INFORMATION: {
PPNP_BUS_INFORMATION BusInfo;
BusInfo = ALLOCATE_PAGED_POOL( sizeof(*BusInfo));
if (BusInfo != NULL) {
BusInfo->BusTypeGuid = GUID_BUS_TYPE_IRDA;
BusInfo->LegacyBusType=PNPBus;
BusInfo->BusNumber=0;
Irp->IoStatus.Information=(ULONG_PTR)BusInfo;
status = STATUS_SUCCESS;
} else {
status=STATUS_INSUFFICIENT_RESOURCES;
}
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: {
PDEVICE_RELATIONS CurrentRelations;
switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
case TargetDeviceRelation:
CurrentRelations=ALLOCATE_PAGED_POOL(sizeof(DEVICE_RELATIONS));
if (CurrentRelations != NULL) {
ObReferenceObject(DeviceObject);
CurrentRelations->Objects[0]=DeviceObject;
CurrentRelations->Count=1;
Irp->IoStatus.Information=(ULONG_PTR)CurrentRelations;
status=STATUS_SUCCESS;
} else {
status=STATUS_INSUFFICIENT_RESOURCES;
}
break;
default:
break;
}
break;
}
default:
//
// we aren't handling this irp
// just complete it
//
break;
}
//
// the irp has been handled in some way or the other
// complete it now
//
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
IrEnumPdoPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
PAGED_CODE();
D_POWER(DbgPrint("IRENUM: PDO: Power IRP, MN func=%d\n",irpSp->MinorFunction);)
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
IrEnumPdoWmi(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS Status=Irp->IoStatus.Status;
D_WMI(DbgPrint("IRENUM: PDO: Wmi\n");)
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return Status;
}