|
|
#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, 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 k;
for (k=0; k< PdoDeviceExtension->DeviceDescription->CompatIdCount; k++) {
Length += (wcslen(PdoDeviceExtension->DeviceDescription->CompatId[k])+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 (k=0; k< PdoDeviceExtension->DeviceDescription->CompatIdCount; k++) {
if (!PdoDeviceExtension->DeviceDescription->Printer) { //
// for printers we don't prepend our enumerator name
//
wcscpy(&buffer[Index],IRENUM_PREFIX); }
wcscat( &buffer[Index], PdoDeviceExtension->DeviceDescription->CompatId[k] );
//
// 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 = STATUS_SUCCESS;
status=IoOpenDeviceRegistryKey( DeviceObject, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_READ, &Handle );
if (NT_SUCCESS(status)) {
UNICODE_STRING KeyName;
RtlInitUnicodeString(&KeyName,L"PortName");
status = ZwSetValueKey( Handle, &KeyName, 0, REG_SZ, L"IR", sizeof(L"IR") );
if ( !NT_SUCCESS(status) ) { D_PNP(DbgPrint("IRENUM : ZwSetValueKey failed : 0x%x\n", status); )
}
ZwClose(Handle); }
}
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 )
{ NTSTATUS Status=Irp->IoStatus.Status; PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
PAGED_CODE();
D_POWER(DbgPrint("IRENUM: PDO: Power IRP, MN func=%d\n",irpSp->MinorFunction);)
PoStartNextPowerIrp(Irp);
switch (irpSp->MinorFunction) {
case IRP_MN_SET_POWER: case IRP_MN_QUERY_POWER: //
// we under stand these two
//
Status=STATUS_SUCCESS; break;
default: //
// don't do wait wake or others
//
break; }
Irp->IoStatus.Status = Status; IoCompleteRequest (Irp, IO_NO_INCREMENT);
return Status; }
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; }
|