void bus_init_pdo ( PDEVICE_OBJECT pdo, PFDO_DEVICE_DATA fdodata ) { PPDO_DEVICE_DATA pdodata; unsigned int pdo_num; PAGED_CODE (); pdodata = (PPDO_DEVICE_DATA) pdo->DeviceExtension; Bus_KdPrint(pdodata, BUS_DBG_SS_NOISE, ("pdo 0x%p, extension 0x%p\n", pdo, pdodata)); // // Initialize the rest // pdodata->IsFDO = FALSE; pdodata->Self = pdo; pdodata->DebugLevel = BusEnumDebugLevel; pdodata->ParentFdo = fdodata->Self; pdodata->Present = TRUE; // attached to the bus pdodata->ReportedMissing = FALSE; // not yet reported missing INITIALIZE_PNP_STATE(pdodata); // // PDO's usually start their life at D3 // pdodata->DevicePowerState = PowerDeviceD3; pdodata->SystemPowerState = PowerSystemWorking; InitializeListHead(&pdodata->ioctl_q); KeInitializeSpinLock(&pdodata->q_lock); pdo->Flags |= DO_POWER_PAGABLE|DO_DIRECT_IO; ExAcquireFastMutex (&fdodata->Mutex); InsertTailList(&fdodata->ListOfPDOs, &pdodata->Link); fdodata->NumPDOs++; ExReleaseFastMutex (&fdodata->Mutex); // This should be the last step in initialization. pdo->Flags &= ~DO_DEVICE_INITIALIZING; }
NTSTATUS Bus_AddDevice( __in PDRIVER_OBJECT DriverObject, __in PDEVICE_OBJECT PhysicalDeviceObject ) /*++ Routine Description. Our Toaster bus has been found. Attach our FDO to it. Allocate any required resources. Set things up. And be prepared for the ``start device'' Arguments: DriverObject - pointer to driver object. PhysicalDeviceObject - Device object representing the bus to which we will attach a new FDO. --*/ { NTSTATUS status; PDEVICE_OBJECT deviceObject = NULL; PFDO_DEVICE_DATA deviceData = NULL; PWCHAR deviceName = NULL; ULONG nameLength; PKTIMER timer; PKDPC dpc; PAGED_CODE (); Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Add Device: 0x%p\n", PhysicalDeviceObject)); status = IoCreateDevice ( DriverObject, // our driver object sizeof (FDO_DEVICE_DATA), // device object extension size NULL, // FDOs do not have names FILE_DEVICE_BUS_EXTENDER, // We are a bus FILE_DEVICE_SECURE_OPEN, // TRUE, // our FDO is exclusive &deviceObject); // The device object created if (!NT_SUCCESS (status)) { goto End; } deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension; RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA)); // // Set the initial state of the FDO // INITIALIZE_PNP_STATE(deviceData); deviceData->DebugLevel = BusEnumDebugLevel; deviceData->IsFDO = TRUE; deviceData->Self = deviceObject; ExInitializeFastMutex (&deviceData->Mutex); InitializeListHead (&deviceData->ListOfPDOs); // Set the PDO for use with PlugPlay functions deviceData->UnderlyingPDO = PhysicalDeviceObject; // // Set the initial powerstate of the FDO // deviceData->DevicePowerState = PowerDeviceUnspecified; deviceData->SystemPowerState = PowerSystemWorking; // // Biased to 1. Transition to zero during remove device // means IO is finished. Transition to 1 means the device // can be stopped. // deviceData->OutstandingIO = 1; // // Initialize the remove event to Not-Signaled. This event // will be set when the OutstandingIO will become 0. // KeInitializeEvent(&deviceData->RemoveEvent, SynchronizationEvent, FALSE); // // Initialize the stop event to Signaled: // there are no Irps that prevent the device from being // stopped. This event will be set when the OutstandingIO // will become 0. // KeInitializeEvent(&deviceData->StopEvent, SynchronizationEvent, TRUE); deviceObject->Flags |= DO_POWER_PAGABLE|DO_BUFFERED_IO; // // Tell the Plug & Play system that this device will need a // device interface. // status = IoRegisterDeviceInterface ( PhysicalDeviceObject, (LPGUID) &GUID_DEVINTERFACE_BUSENUM_TOASTER, NULL, &deviceData->InterfaceName); if (!NT_SUCCESS (status)) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice: IoRegisterDeviceInterface failed (%x)", status)); goto End; } // // Attach our FDO to the device stack. // The return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. // deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack ( deviceObject, PhysicalDeviceObject); if (NULL == deviceData->NextLowerDriver) { status = STATUS_NO_SUCH_DEVICE; goto End; } #if DBG // // We will demonstrate here the step to retrieve the name of the PDO // status = IoGetDeviceProperty (PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &nameLength); if (status != STATUS_BUFFER_TOO_SMALL) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice:IoGDP failed (0x%x)\n", status)); goto End; } deviceName = ExAllocatePoolWithTag (NonPagedPool, nameLength, BUSENUM_POOL_TAG); if (NULL == deviceName) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength)); status = STATUS_INSUFFICIENT_RESOURCES; goto End; } status = IoGetDeviceProperty (PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, nameLength, deviceName, &nameLength); if (!NT_SUCCESS (status)) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice:IoGDP(2) failed (0x%x)", status)); goto End; } Bus_KdPrint (deviceData, BUS_DBG_SS_TRACE, ("AddDevice: %p to %p->%p (%ws) \n", deviceObject, deviceData->NextLowerDriver, PhysicalDeviceObject, deviceName)); #endif // // We are done with initializing, so let's indicate that and return. // This should be the final step in the AddDevice process. // deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; End: if (deviceName){ ExFreePool(deviceName); } if (!NT_SUCCESS(status) && deviceObject){ if (deviceData && deviceData->NextLowerDriver){ IoDetachDevice (deviceData->NextLowerDriver); } IoDeleteDevice (deviceObject); } return status; }
//======================================================================================== // Function: WDMAddDevice // Purpose: // Return Value: //======================================================================================== NTSTATUS WDMAddDevice( IN PDRIVER_OBJECT dro, IN PDEVICE_OBJECT pdo ) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT fido = NULL; PDEVICE_EXTENSION dx; UNICODE_STRING devNameU; UNICODE_STRING win32NameU; PAGED_CODE(); RtlInitUnicodeString(&devNameU, NT_DEVICE_NAME); // Note: // It will crash the system if it has more than one PCI bus, // device name should change to PciBusFilter01, 02, ... ntStatus = IoCreateDevice(dro, sizeof(DEVICE_EXTENSION), &devNameU, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &fido); if (!NT_SUCCESS(ntStatus)) { return ntStatus; } RtlInitUnicodeString(&win32NameU, DOS_DEVICE_NAME); ntStatus = IoCreateSymbolicLink(&win32NameU, &devNameU); if (!NT_SUCCESS(ntStatus)) // If we we couldn't create the link then abort installation. { IoDeleteDevice(fido); KdPrint(("<-- "__FUNCTION__"() IoCreateSymbolicLink() Status code: 0x%08x\n", ntStatus)); return ntStatus; } dx = (PDEVICE_EXTENSION)fido->DeviceExtension; IoInitializeRemoveLock(&dx->rmLock, DEV_TAG, 1, 5); dx->lowerdo = IoAttachDeviceToDeviceStack(fido, pdo); //attach to PCI bus driver if(dx->lowerdo == NULL) { //Failure for attachment is an indication of a broken plug & play system. IoDeleteDevice(fido); return STATUS_UNSUCCESSFUL; } //flags needs inherit from lower device object(pci bus driver) fido->Flags|=(dx->lowerdo->Flags & (DO_BUFFERED_IO|DO_DIRECT_IO|DO_POWER_PAGABLE)); //update device type fido->DeviceType = dx->lowerdo->DeviceType; //update device characteristics fido->Characteristics = dx->lowerdo->Characteristics; //save physical device object dx->pdo = pdo; //set the initial state of the Filter DO INITIALIZE_PNP_STATE(dx); KdPrint(("PCI pdo=0x%x, fdo=0x%x, fido=0x%x", pdo, dx->lowerdo, fido)); fido->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; }
VOID Bus_InitializePdo ( PDEVICE_OBJECT Pdo, PFDO_DEVICE_DATA FdoData ) { PPDO_DEVICE_DATA pdoData; int acpistate; DEVICE_POWER_STATE ntState; PAGED_CODE (); pdoData = (PPDO_DEVICE_DATA) Pdo->DeviceExtension; DPRINT("pdo 0x%p, extension 0x%p\n", Pdo, pdoData); if (pdoData->AcpiHandle) acpi_bus_get_power(pdoData->AcpiHandle, &acpistate); else acpistate = ACPI_STATE_D0; switch(acpistate) { case ACPI_STATE_D0: ntState = PowerDeviceD0; break; case ACPI_STATE_D1: ntState = PowerDeviceD1; break; case ACPI_STATE_D2: ntState = PowerDeviceD2; break; case ACPI_STATE_D3: ntState = PowerDeviceD3; break; default: DPRINT1("Unknown power state (%d) returned by acpi\n",acpistate); ntState = PowerDeviceUnspecified; break; } // // Initialize the rest // pdoData->Common.IsFDO = FALSE; pdoData->Common.Self = Pdo; pdoData->ParentFdo = FdoData->Common.Self; INITIALIZE_PNP_STATE(pdoData->Common); pdoData->Common.DevicePowerState = ntState; pdoData->Common.SystemPowerState = FdoData->Common.SystemPowerState; ExAcquireFastMutex (&FdoData->Mutex); InsertTailList(&FdoData->ListOfPDOs, &pdoData->Link); FdoData->NumPDOs++; ExReleaseFastMutex (&FdoData->Mutex); // This should be the last step in initialization. Pdo->Flags &= ~DO_DEVICE_INITIALIZING; }
NTSTATUS NTAPI Bus_AddDevice( PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject ) { NTSTATUS status; PDEVICE_OBJECT deviceObject = NULL; PFDO_DEVICE_DATA deviceData = NULL; PWCHAR deviceName = NULL; #ifndef NDEBUG ULONG nameLength; #endif PAGED_CODE (); DPRINT("Add Device: 0x%p\n", PhysicalDeviceObject); DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n"); status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_DATA), NULL, FILE_DEVICE_ACPI, FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject); if (!NT_SUCCESS(status)) { DPRINT1("IoCreateDevice() failed with status 0x%X\n", status); goto End; } deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension; RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA)); // // Set the initial state of the FDO // INITIALIZE_PNP_STATE(deviceData->Common); deviceData->Common.IsFDO = TRUE; deviceData->Common.Self = deviceObject; ExInitializeFastMutex (&deviceData->Mutex); InitializeListHead (&deviceData->ListOfPDOs); // Set the PDO for use with PlugPlay functions deviceData->UnderlyingPDO = PhysicalDeviceObject; // // Set the initial powerstate of the FDO // deviceData->Common.DevicePowerState = PowerDeviceUnspecified; deviceData->Common.SystemPowerState = PowerSystemWorking; deviceObject->Flags |= DO_POWER_PAGABLE; // // Attach our FDO to the device stack. // The return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. // deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack ( deviceObject, PhysicalDeviceObject); if (NULL == deviceData->NextLowerDriver) { status = STATUS_NO_SUCH_DEVICE; goto End; } #ifndef NDEBUG // // We will demonstrate here the step to retrieve the name of the PDO // status = IoGetDeviceProperty (PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &nameLength); if (status != STATUS_BUFFER_TOO_SMALL) { DPRINT1("AddDevice:IoGDP failed (0x%x)\n", status); goto End; } deviceName = ExAllocatePoolWithTag (NonPagedPool, nameLength, 'IPCA'); if (NULL == deviceName) { DPRINT1("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength); status = STATUS_INSUFFICIENT_RESOURCES; goto End; } status = IoGetDeviceProperty (PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, nameLength, deviceName, &nameLength); if (!NT_SUCCESS (status)) { DPRINT1("AddDevice:IoGDP(2) failed (0x%x)", status); goto End; } DPRINT("AddDevice: %p to %p->%p (%ws) \n", deviceObject, deviceData->NextLowerDriver, PhysicalDeviceObject, deviceName); #endif // // We are done with initializing, so let's indicate that and return. // This should be the final step in the AddDevice process. // deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; End: if (deviceName){ ExFreePool(deviceName); } if (!NT_SUCCESS(status) && deviceObject){ if (deviceData && deviceData->NextLowerDriver){ IoDetachDevice (deviceData->NextLowerDriver); } IoDeleteDevice (deviceObject); } return status; }
// AddDevice, called when an instance of our supported hardware is found // Returning anything other than NT_SUCCESS here causes the device to fail // to initialise NTSTATUS NTAPI FreeBT_AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { NTSTATUS ntStatus; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION deviceExtension; POWER_STATE state; KIRQL oldIrql; UNICODE_STRING uniDeviceName; WCHAR wszDeviceName[255]={0}; UNICODE_STRING uniDosDeviceName; LONG instanceNumber=0; FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Entered\n")); deviceObject = NULL; swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber); RtlInitUnicodeString(&uniDeviceName, wszDeviceName); ntStatus=STATUS_OBJECT_NAME_COLLISION; while (instanceNumber<99 && !NT_SUCCESS(ntStatus)) { swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber); uniDeviceName.Length = wcslen(wszDeviceName) * sizeof(WCHAR); FreeBT_DbgPrint(1, ("FBTUSB: Attempting to create device %ws\n", wszDeviceName)); ntStatus = IoCreateDevice( DriverObject, // our driver object sizeof(DEVICE_EXTENSION), // extension size for us &uniDeviceName, // name for this device FILE_DEVICE_UNKNOWN, 0, // device characteristics FALSE, // Not exclusive &deviceObject); // Our device object if (!NT_SUCCESS(ntStatus)) instanceNumber++; } if (!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: Failed to create device object\n")); return ntStatus; } FreeBT_DbgPrint(1, ("FBTUSB: Created device %ws\n", wszDeviceName)); deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; deviceExtension->FunctionalDeviceObject = deviceObject; deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; deviceObject->Flags |= DO_DIRECT_IO; swprintf(deviceExtension->wszDosDeviceName, L"\\DosDevices\\FbtUsb%02d", instanceNumber); RtlInitUnicodeString(&uniDosDeviceName, deviceExtension->wszDosDeviceName); ntStatus=IoCreateSymbolicLink(&uniDosDeviceName, &uniDeviceName); if (!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: Failed to create symbolic link %ws to %ws, status=0x%08x\n", deviceExtension->wszDosDeviceName, wszDeviceName, ntStatus)); IoDeleteDevice(deviceObject); return ntStatus; } FreeBT_DbgPrint(1, ("FBTUSB: Created symbolic link %ws\n", deviceExtension->wszDosDeviceName)); KeInitializeSpinLock(&deviceExtension->DevStateLock); INITIALIZE_PNP_STATE(deviceExtension); deviceExtension->OpenHandleCount = 0; // Initialize the selective suspend variables KeInitializeSpinLock(&deviceExtension->IdleReqStateLock); deviceExtension->IdleReqPend = 0; deviceExtension->PendingIdleIrp = NULL; // Hold requests until the device is started deviceExtension->QueueState = HoldRequests; // Initialize the queue and the queue spin lock InitializeListHead(&deviceExtension->NewRequestsQueue); KeInitializeSpinLock(&deviceExtension->QueueLock); // Initialize the remove event to not-signaled. KeInitializeEvent(&deviceExtension->RemoveEvent, SynchronizationEvent, FALSE); // Initialize the stop event to signaled. // This event is signaled when the OutstandingIO becomes 1 KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, TRUE); // OutstandingIo count biased to 1. // Transition to 0 during remove device means IO is finished. // Transition to 1 means the device can be stopped deviceExtension->OutStandingIO = 1; KeInitializeSpinLock(&deviceExtension->IOCountLock); #ifdef ENABLE_WMI // Delegating to WMILIB ntStatus = FreeBT_WmiRegistration(deviceExtension); if (!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WmiRegistration failed with %X\n", ntStatus)); IoDeleteDevice(deviceObject); IoDeleteSymbolicLink(&uniDosDeviceName); return ntStatus; } #endif // Set the flags as underlying PDO if (PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) { deviceObject->Flags |= DO_POWER_PAGABLE; } // Typically, the function driver for a device is its // power policy owner, although for some devices another // driver or system component may assume this role. // Set the initial power state of the device, if known, by calling // PoSetPowerState. deviceExtension->DevPower = PowerDeviceD0; deviceExtension->SysPower = PowerSystemWorking; state.DeviceState = PowerDeviceD0; PoSetPowerState(deviceObject, DevicePowerState, state); // attach our driver to device stack // The return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. deviceExtension->TopOfStackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); if (NULL == deviceExtension->TopOfStackDeviceObject) { #ifdef ENABLE_WMI FreeBT_WmiDeRegistration(deviceExtension); #endif IoDeleteDevice(deviceObject); IoDeleteSymbolicLink(&uniDosDeviceName); return STATUS_NO_SUCH_DEVICE; } // Register device interfaces ntStatus = IoRegisterDeviceInterface(deviceExtension->PhysicalDeviceObject, &GUID_CLASS_FREEBT_USB, NULL, &deviceExtension->InterfaceName); if (!NT_SUCCESS(ntStatus)) { #ifdef ENABLE_WMI FreeBT_WmiDeRegistration(deviceExtension); #endif IoDetachDevice(deviceExtension->TopOfStackDeviceObject); IoDeleteDevice(deviceObject); IoDeleteSymbolicLink(&uniDosDeviceName); return ntStatus; } if (IoIsWdmVersionAvailable(1, 0x20)) { deviceExtension->WdmVersion = WinXpOrBetter; } else if (IoIsWdmVersionAvailable(1, 0x10)) { deviceExtension->WdmVersion = Win2kOrBetter; } else if (IoIsWdmVersionAvailable(1, 0x5)) { deviceExtension->WdmVersion = WinMeOrBetter; } else if (IoIsWdmVersionAvailable(1, 0x0)) { deviceExtension->WdmVersion = Win98OrBetter; } deviceExtension->SSRegistryEnable = 0; deviceExtension->SSEnable = 0; // WinXP only: check the registry flag indicating whether // the device should selectively suspend when idle if (WinXpOrBetter == deviceExtension->WdmVersion) { FreeBT_GetRegistryDword(FREEBT_REGISTRY_PARAMETERS_PATH, L"BulkUsbEnable", (PULONG)(&deviceExtension->SSRegistryEnable)); if (deviceExtension->SSRegistryEnable) { // initialize DPC KeInitializeDpc(&deviceExtension->DeferredProcCall, DpcRoutine, deviceObject); // initialize the timer. // the DPC and the timer in conjunction, // monitor the state of the device to // selectively suspend the device. KeInitializeTimerEx(&deviceExtension->Timer, NotificationTimer); // Initialize the NoDpcWorkItemPendingEvent to signaled state. // This event is cleared when a Dpc is fired and signaled // on completion of the work-item. KeInitializeEvent(&deviceExtension->NoDpcWorkItemPendingEvent, NotificationEvent, TRUE); // Initialize the NoIdleReqPendEvent to ensure that the idle request // is indeed complete before we unload the drivers. KeInitializeEvent(&deviceExtension->NoIdleReqPendEvent, NotificationEvent, TRUE); } } // Initialize the NoIdleReqPendEvent to ensure that the idle request // is indeed complete before we unload the drivers. KeInitializeEvent(&deviceExtension->DelayEvent, NotificationEvent, FALSE); // Clear the DO_DEVICE_INITIALIZING flag. // Note: Do not clear this flag until the driver has set the // device power state and the power DO flags. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; InterlockedIncrement(&instanceNumber); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Leaving\n")); return ntStatus; }
NTSTATUS MobiUsb_AddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ) /*++ Description: Arguments: DriverObject - Store the pointer to the object representing us. PhysicalDeviceObject - Pointer to the device object created by the undelying bus driver. Return: STATUS_SUCCESS - if successful STATUS_UNSUCCESSFUL - otherwise --*/ { NTSTATUS ntStatus; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION deviceExtension; POWER_STATE state; KIRQL oldIrql; MobiUsb_DbgPrint(3, ("file mobiusb: MobiUsb_AddDevice - begins\n")); deviceObject = NULL; ntStatus = IoCreateDevice( DriverObject, // our driver object sizeof(DEVICE_EXTENSION), // extension size for us NULL, // name for this device FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics FALSE, // Not exclusive &deviceObject); // Our device object if(!NT_SUCCESS(ntStatus)) { // // returning failure here prevents the entire stack from functioning, // but most likely the rest of the stack will not be able to create // device objects either, so it is still OK. // MobiUsb_DbgPrint(1, ("file mobiusb: Failed to create device object\n")); return ntStatus; } // // Initialize the device extension // deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; deviceExtension->FunctionalDeviceObject = deviceObject; deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; #ifdef MOBI_DIRECT_IO deviceObject->Flags |= DO_DIRECT_IO; #else deviceObject->Flags |= DO_BUFFERED_IO; #endif // // initialize the device state lock and set the device state // KeInitializeSpinLock(&deviceExtension->DevStateLock); INITIALIZE_PNP_STATE(deviceExtension); // //initialize OpenHandleCount // deviceExtension->OpenHandleCount = 0; // // Initialize the selective suspend variables // KeInitializeSpinLock(&deviceExtension->IdleReqStateLock); deviceExtension->IdleReqPend = 0; deviceExtension->PendingIdleIrp = NULL; // // Initialize the vendor command semaphore // KeInitializeSemaphore(&deviceExtension->CallUSBSemaphore, 1, 1); // // Hold requests until the device is started // deviceExtension->QueueState = HoldRequests; // // Initialize the queue and the queue spin lock // InitializeListHead(&deviceExtension->NewRequestsQueue); KeInitializeSpinLock(&deviceExtension->QueueLock); // // Initialize the remove event to not-signaled. // KeInitializeEvent(&deviceExtension->RemoveEvent, SynchronizationEvent, FALSE); // // Initialize the stop event to signaled. // This event is signaled when the OutstandingIO becomes 1 // KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, TRUE); // // OutstandingIo count biased to 1. // Transition to 0 during remove device means IO is finished. // Transition to 1 means the device can be stopped // deviceExtension->OutStandingIO = 1; KeInitializeSpinLock(&deviceExtension->IOCountLock); // // Delegating to WMILIB // ntStatus = MobiUsb_WmiRegistration(deviceExtension); if(!NT_SUCCESS(ntStatus)) { MobiUsb_DbgPrint(1, ("file mobiusb: MobiUsb_WmiRegistration failed with %X\n", ntStatus)); IoDeleteDevice(deviceObject); return ntStatus; } // // set the flags as underlying PDO // if(PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) { deviceObject->Flags |= DO_POWER_PAGABLE; } // // Typically, the function driver for a device is its // power policy owner, although for some devices another // driver or system component may assume this role. // Set the initial power state of the device, if known, by calling // PoSetPowerState. // deviceExtension->DevPower = PowerDeviceD0; deviceExtension->SysPower = PowerSystemWorking; state.DeviceState = PowerDeviceD0; PoSetPowerState(deviceObject, DevicePowerState, state); // // attach our driver to device stack // The return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. // deviceExtension->TopOfStackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); if(NULL == deviceExtension->TopOfStackDeviceObject) { MobiUsb_WmiDeRegistration(deviceExtension); IoDeleteDevice(deviceObject); return STATUS_NO_SUCH_DEVICE; } // // Register device interfaces // ntStatus = IoRegisterDeviceInterface(deviceExtension->PhysicalDeviceObject, &GUID_CLASS_VCMOBI_MOBI, NULL, &deviceExtension->InterfaceName); if(!NT_SUCCESS(ntStatus)) { MobiUsb_WmiDeRegistration(deviceExtension); IoDetachDevice(deviceExtension->TopOfStackDeviceObject); IoDeleteDevice(deviceObject); return ntStatus; } //MobiUsb_DbgPrint(3, ("file mobiusb: interfacename: Filename = %ws nameLength = %d\n", deviceExtension->InterfaceName.Buffer, deviceExtension->InterfaceName.Length / sizeof(WCHAR))); if(IoIsWdmVersionAvailable(1, 0x20)) { deviceExtension->WdmVersion = WinXpOrBetter; } else if(IoIsWdmVersionAvailable(1, 0x10)) { deviceExtension->WdmVersion = Win2kOrBetter; } else if(IoIsWdmVersionAvailable(1, 0x5)) { deviceExtension->WdmVersion = WinMeOrBetter; } else if(IoIsWdmVersionAvailable(1, 0x0)) { deviceExtension->WdmVersion = Win98OrBetter; } MobiUsb_DbgPrint(3, ("file mobiusb: WdmVersion = %d\n", deviceExtension->WdmVersion)); deviceExtension->SSRegistryEnable = 0; deviceExtension->SSEnable = 0; // // WinXP only // check the registry flag - // whether the device should selectively // suspend when idle // if(WinXpOrBetter == deviceExtension->WdmVersion) { MobiUsb_GetRegistryDword(MOBIUSB_REGISTRY_PARAMETERS_PATH, L"VCMobiEnable", &deviceExtension->SSRegistryEnable); if(deviceExtension->SSRegistryEnable) { // // initialize DPC // KeInitializeDpc(&deviceExtension->DeferredProcCall, DpcRoutine, deviceObject); // // initialize the timer. // the DPC and the timer in conjunction, // monitor the state of the device to // selectively suspend the device. // KeInitializeTimerEx(&deviceExtension->Timer, NotificationTimer); // // Initialize the NoDpcWorkItemPendingEvent to signaled state. // This event is cleared when a Dpc is fired and signaled // on completion of the work-item. // KeInitializeEvent(&deviceExtension->NoDpcWorkItemPendingEvent, NotificationEvent, TRUE); // // Initialize the NoIdleReqPendEvent to ensure that the idle request // is indeed complete before we unload the drivers. // KeInitializeEvent(&deviceExtension->NoIdleReqPendEvent, NotificationEvent, TRUE); } } // // Clear the DO_DEVICE_INITIALIZING flag. // Note: Do not clear this flag until the driver has set the // device power state and the power DO flags. // deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; MobiUsb_DbgPrint(3, ("file mobiusb: MobiUsb_AddDevice - ends\n")); return ntStatus; }
NTSTATUS FilterAddDevice( __in PDRIVER_OBJECT DriverObject, __in PDEVICE_OBJECT PhysicalDeviceObject ) /*++ Routine Description: The Plug & Play subsystem is handing us a brand new PDO, for which we (by means of INF registration) have been asked to provide a driver. We need to determine if we need to be in the driver stack for the device. Create a function device object to attach to the stack Initialize that device object Return status success. Remember: We can NOT actually send ANY non pnp IRPS to the given driver stack, UNTIL we have received an IRP_MN_START_DEVICE. Arguments: DeviceObject - pointer to a device object. PhysicalDeviceObject - pointer to a device object created by the underlying bus driver. Return Value: NT status code. --*/ { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; PDEVICE_EXTENSION deviceExtension; ULONG deviceType = FILE_DEVICE_UNKNOWN; PAGED_CODE (); // // IoIsWdmVersionAvailable(1, 0x20) returns TRUE on os after Windows 2000. // if (RtlIsNtDdiVersionAvailable(NTDDI_WINXP)) { // // Win2K system bugchecks if the filter attached to a storage device // doesn't specify the same DeviceType as the device it's attaching // to. This bugcheck happens in the filesystem when you disable // the devicestack whose top level deviceobject doesn't have a VPB. // To workaround we will get the toplevel object's DeviceType and // specify that in IoCreateDevice. // deviceObject = IoGetAttachedDeviceReference(PhysicalDeviceObject); deviceType = deviceObject->DeviceType; ObDereferenceObject(deviceObject); } // // Create a filter device object. // status = IoCreateDevice (DriverObject, sizeof (DEVICE_EXTENSION), NULL, // No Name deviceType, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject); if (!NT_SUCCESS (status)) { // // Returning failure here prevents the entire stack from functioning, // but most likely the rest of the stack will not be able to create // device objects either, so it is still OK. // return status; } DebugPrint (("AddDevice PDO (0x%p) FDO (0x%p)\n", PhysicalDeviceObject, deviceObject)); deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; deviceExtension->Common.Type = DEVICE_TYPE_FIDO; deviceExtension->NextLowerDriver = IoAttachDeviceToDeviceStack ( deviceObject, PhysicalDeviceObject); // // Failure for attachment is an indication of a broken plug & play system. // if (NULL == deviceExtension->NextLowerDriver) { IoDeleteDevice(deviceObject); return STATUS_UNSUCCESSFUL; } deviceObject->Flags |= deviceExtension->NextLowerDriver->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE ); deviceObject->DeviceType = deviceExtension->NextLowerDriver->DeviceType; deviceObject->Characteristics = deviceExtension->NextLowerDriver->Characteristics; deviceExtension->Self = deviceObject; // // Let us use remove lock to keep count of IRPs so that we don't // deteach and delete our deviceobject until all pending I/Os in our // devstack are completed. Remlock is required to protect us from // various race conditions where our driver can get unloaded while we // are still running dispatch or completion code. // IoInitializeRemoveLock (&deviceExtension->RemoveLock , POOL_TAG, 1, // MaxLockedMinutes 100); // HighWatermark, this parameter is // used only on checked build. Specifies // the maximum number of outstanding // acquisitions allowed on the lock // // Set the initial state of the Filter DO // INITIALIZE_PNP_STATE(deviceExtension); DebugPrint(("AddDevice: %p to %p->%p \n", deviceObject, deviceExtension->NextLowerDriver, PhysicalDeviceObject)); deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; }
NTSTATUS Bus_AddDevice(__in PDRIVER_OBJECT DriverObject, __in PDEVICE_OBJECT PhysicalDeviceObject) { NTSTATUS status; PDEVICE_OBJECT deviceObject = NULL; PFDO_DEVICE_DATA deviceData = NULL; PWCHAR deviceName = NULL; ULONG nameLength; UNREFERENCED_PARAMETER(nameLength); PAGED_CODE(); Bus_KdPrint(("Add Device: 0x%p\n", PhysicalDeviceObject)); status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_DATA), NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject); if (!NT_SUCCESS (status)) { goto End; } deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension; RtlZeroMemory(deviceData, sizeof (FDO_DEVICE_DATA)); INITIALIZE_PNP_STATE(deviceData); deviceData->IsFDO = TRUE; deviceData->Self = deviceObject; ExInitializeFastMutex(&deviceData->Mutex); InitializeListHead(&deviceData->ListOfPDOs); deviceData->UnderlyingPDO = PhysicalDeviceObject; deviceData->DevicePowerState = PowerDeviceUnspecified; deviceData->SystemPowerState = PowerSystemWorking; deviceData->OutstandingIO = 1; KeInitializeEvent(&deviceData->RemoveEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&deviceData->StopEvent, SynchronizationEvent, TRUE); deviceObject->Flags |= DO_POWER_PAGABLE; status = IoRegisterDeviceInterface(PhysicalDeviceObject, (LPGUID) &GUID_DEVINTERFACE_SCPVBUS, NULL, &deviceData->InterfaceName); if (!NT_SUCCESS(status)) { Bus_KdPrint(("AddDevice: IoRegisterDeviceInterface failed (%x)", status)); goto End; } deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); if (deviceData->NextLowerDriver == NULL) { status = STATUS_NO_SUCH_DEVICE; goto End; } deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; End: if (deviceName) { ExFreePool(deviceName); } if (!NT_SUCCESS(status) && deviceObject) { if (deviceData && deviceData->NextLowerDriver) { IoDetachDevice(deviceData->NextLowerDriver); } IoDeleteDevice(deviceObject); } return status; }