You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
9.5 KiB
433 lines
9.5 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
initunlo.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code that is very specific to initialization
|
|
and unload operations in the irenum driver
|
|
|
|
Author:
|
|
|
|
Brian Lieuallen, 7-13-2000
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History :
|
|
|
|
--*/
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
IrCommAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo
|
|
)
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
ULONG Incoming;
|
|
|
|
PDEVICE_OBJECT Fdo = NULL;
|
|
|
|
PDEVICE_OBJECT LowerDevice=NULL;
|
|
|
|
//
|
|
// Pointer to the device extension created for this
|
|
// device
|
|
//
|
|
PFDO_DEVICE_EXTENSION DeviceExtension = NULL;
|
|
|
|
D_PNP(DbgPrint("IrComm: AddDevice\n");)
|
|
|
|
|
|
//
|
|
// Create the device object for this device.
|
|
//
|
|
|
|
Status = IoCreateDevice(
|
|
DriverObject,
|
|
sizeof(FDO_DEVICE_EXTENSION),
|
|
NULL,
|
|
FILE_DEVICE_NULL,
|
|
FILE_AUTOGENERATED_DEVICE_NAME,
|
|
FALSE,
|
|
&Fdo
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return Status;
|
|
}
|
|
|
|
DeviceExtension=Fdo->DeviceExtension;
|
|
|
|
LowerDevice=IoAttachDeviceToDeviceStack(
|
|
Fdo,
|
|
Pdo
|
|
);
|
|
|
|
if (LowerDevice == NULL) {
|
|
|
|
D_ERROR(DbgPrint("IRCOMM: Could not attach to PDO\n");)
|
|
|
|
Status=STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto CleanUp;
|
|
}
|
|
|
|
Fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
Fdo->StackSize=LowerDevice->StackSize+1;
|
|
|
|
|
|
|
|
RtlZeroMemory(DeviceExtension,sizeof(*DeviceExtension));
|
|
|
|
D_ERROR(DbgPrint("IRCOMM: Device Extension %p\n",DeviceExtension);)
|
|
|
|
DeviceExtension->DeviceObject = Fdo;
|
|
DeviceExtension->Pdo=Pdo;
|
|
DeviceExtension->LowerDevice=LowerDevice;
|
|
|
|
KeInitializeTimer(
|
|
&DeviceExtension->Read.IntervalTimer
|
|
);
|
|
|
|
KeInitializeDpc(
|
|
&DeviceExtension->Read.IntervalTimerDpc,
|
|
IntervalTimeProc,
|
|
DeviceExtension
|
|
);
|
|
|
|
KeInitializeTimer(
|
|
&DeviceExtension->Read.TotalTimer
|
|
);
|
|
|
|
KeInitializeDpc(
|
|
&DeviceExtension->Read.TotalTimerDpc,
|
|
TotalTimerProc,
|
|
DeviceExtension
|
|
);
|
|
|
|
|
|
KeInitializeSpinLock(
|
|
&DeviceExtension->SpinLock
|
|
);
|
|
|
|
|
|
|
|
KeInitializeSpinLock(
|
|
&DeviceExtension->Read.ReadLock
|
|
);
|
|
|
|
|
|
KeInitializeSpinLock(
|
|
&DeviceExtension->Mask.Lock
|
|
);
|
|
|
|
|
|
|
|
IrCommHandleSymbolicLink(
|
|
Pdo,
|
|
&DeviceExtension->InterfaceName,
|
|
TRUE
|
|
);
|
|
|
|
|
|
//
|
|
// see if this is going to be instance of the driver is going to accept
|
|
// incoming connection instead outgoing connections.
|
|
//
|
|
// default of outgoing if the key can't be read
|
|
//
|
|
DeviceExtension->OutgoingConnection=TRUE;
|
|
|
|
Status=GetRegistryKeyValue(
|
|
Pdo,
|
|
PLUGPLAY_REGKEY_DRIVER,
|
|
L"ListenForIncommingConnections",
|
|
REG_DWORD,
|
|
&Incoming,
|
|
sizeof(Incoming)
|
|
);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
DeviceExtension->OutgoingConnection= (Incoming == 0) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// open the file handles to the irda stack here in the system process context.
|
|
// The handles will only be used to close the object during remove.
|
|
//
|
|
DeviceExtension->TdiObjects=OpenTdiObjects(
|
|
"IrDA:IrCOMM",
|
|
DeviceExtension->OutgoingConnection
|
|
);
|
|
|
|
if (DeviceExtension->TdiObjects == NULL) {
|
|
|
|
D_ERROR(DbgPrint("IRCOMM: Could not open tdi objects\n");)
|
|
|
|
Status=STATUS_INSUFFICIENT_RESOURCES;
|
|
goto CleanUp;
|
|
}
|
|
|
|
|
|
InitializePacketQueue(
|
|
&DeviceExtension->Write.Queue,
|
|
DeviceExtension,
|
|
WriteStartRoutine
|
|
);
|
|
|
|
InitializePacketQueue(
|
|
&DeviceExtension->Read.Queue,
|
|
DeviceExtension,
|
|
ReadStartRoutine
|
|
);
|
|
|
|
InitializePacketQueue(
|
|
&DeviceExtension->Mask.Queue,
|
|
DeviceExtension,
|
|
MaskStartRoutine
|
|
);
|
|
|
|
InitializePacketQueue(
|
|
&DeviceExtension->Uart.Queue,
|
|
DeviceExtension,
|
|
UartStartRoutine
|
|
);
|
|
|
|
#if 0
|
|
DeviceExtension->LineControl.StopBits=1;
|
|
DeviceExtension->LineControl.Parity=0;
|
|
DeviceExtension->LineControl.WordLength=8;
|
|
|
|
DeviceExtension->BaudRate=115200;
|
|
#endif
|
|
DeviceExtension->Read.BytesInBuffer=0;
|
|
DeviceExtension->Read.NextFilledByte=&DeviceExtension->Read.InputBuffer[0];
|
|
DeviceExtension->Read.NextEmptyByte=&DeviceExtension->Read.InputBuffer[0];
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
CleanUp:
|
|
|
|
if (DeviceExtension->InterfaceName.Buffer != NULL) {
|
|
|
|
IrCommHandleSymbolicLink(
|
|
DeviceExtension->Pdo,
|
|
&DeviceExtension->InterfaceName,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
|
|
if (DeviceExtension->LowerDevice != NULL) {
|
|
|
|
IoDetachDevice(DeviceExtension->LowerDevice);
|
|
}
|
|
|
|
IoDeleteDevice(Fdo);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrCommPnP(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
{
|
|
|
|
PFDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
|
|
|
|
|
|
switch (irpSp->MinorFunction) {
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRCOMM: IRP_MN_START_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRCOMM: IRP_MN_QUERY_STOP_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRCOMM: IRP_MN_CANCEL_STOP_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRCOMM: IRP_MN_STOP_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IrComm: IRP_MN_QUERY_REMOVE_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IrComm: IRP_MN_CANCEL_REMOVE_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL: {
|
|
|
|
D_PNP(DbgPrint("IrComm: IRP_MN_SURPRISE_REMOVAL\n");)
|
|
|
|
DeviceExtension->Removing=TRUE;
|
|
|
|
//
|
|
// now that new io is blocked, flush out all pended irps
|
|
//
|
|
CleanupIoRequests(DeviceExtension);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case IRP_MN_REMOVE_DEVICE: {
|
|
|
|
ULONG NewReferenceCount;
|
|
|
|
D_PNP(DbgPrint("IrComm: IRP_MN_REMOVE_DEVICE\n");)
|
|
//
|
|
// removing now for sure
|
|
//
|
|
DeviceExtension->Removing=TRUE;
|
|
DeviceExtension->Removed=TRUE;
|
|
|
|
|
|
if (DeviceExtension->InterfaceName.Buffer != NULL) {
|
|
|
|
IrCommHandleSymbolicLink(
|
|
DeviceExtension->Pdo,
|
|
&DeviceExtension->InterfaceName,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
if (DeviceExtension->TdiObjects != NULL) {
|
|
//
|
|
// close the tdi objects that we opened during AddDevice(). This has to
|
|
// be done in the same process as they were opened which is the system process
|
|
//
|
|
CloseTdiObjects(DeviceExtension->TdiObjects);
|
|
}
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
status=IoCallDriver(DeviceExtension->LowerDevice, Irp);
|
|
|
|
//
|
|
// detach from the driver below
|
|
//
|
|
IoDetachDevice(DeviceExtension->LowerDevice);
|
|
|
|
//
|
|
// delete our device object
|
|
//
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
D_PNP(DbgPrint("IrComm: IRP_MN_REMOVE_DEVICE exit, %08lx\n",status);)
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
D_PNP(DbgPrint("IrComm: Sending to PDO PnP IRP, MN func=%d\n",irpSp->MinorFunction);)
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
}
|
|
|
|
|
|
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrCommPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
{
|
|
PFDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return PoCallDriver(DeviceExtension->LowerDevice, Irp);
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrCommWmi(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
{
|
|
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|