/** * Remove a PDO node from a bus. Internal. * * @v bus The bus to remove the node from. * @v node The PDO node to remove from its parent bus. * * Don't call this function yourself. It doesn't perform any error-checking. */ static VOID STDCALL WvlBusRemoveNode_( WVL_SP_BUS_T bus, WVL_SP_BUS_NODE node ) { KIRQL irql; DBG( "Removing PDO 0x%08X from bus 0x%08X.\n", (PVOID) node->BusPrivate_.Pdo, (PVOID) bus ); KeAcquireSpinLock(&bus->BusPrivate_.NodeLock, &irql); RemoveEntryList(&node->BusPrivate_.Link); bus->BusPrivate_.NodeCount--; KeReleaseSpinLock(&bus->BusPrivate_.NodeLock, irql); node->Linked = FALSE; ObDereferenceObject(node->BusPrivate_.Pdo); /* We might be floating. */ if (bus->Pdo) IoInvalidateDeviceRelations(bus->Pdo, BusRelations); /* Hack: Use the new method for the main bus */ if (bus == &WvBus) WvlRemoveDeviceFromMainBus(node->BusPrivate_.Pdo); return; }
/** * Add a PDO node to a bus' list of children. Internal. * * @v bus The bus to add the node to. * @v new_node The PDO node to add to the bus. * * Don't call this function yourself. It doesn't perform any error-checking. */ static VOID STDCALL WvlBusAddNode_(WVL_SP_BUS_T bus, WVL_SP_BUS_NODE new_node) { PLIST_ENTRY walker; KIRQL irql; DBG( "Adding PDO %p to bus %p.\n", (PVOID) new_node->BusPrivate_.Pdo, (PVOID) bus ); ObReferenceObject(new_node->BusPrivate_.Pdo); /* It's too bad about having both linked list and bus ref. */ new_node->BusPrivate_.Bus = bus; /* Find a slot for the new child. */ walker = &bus->BusPrivate_.Nodes; new_node->BusPrivate_.Num = 0; KeAcquireSpinLock(&bus->BusPrivate_.NodeLock, &irql); while ((walker = walker->Flink) != &bus->BusPrivate_.Nodes) { WVL_SP_BUS_NODE node = CONTAINING_RECORD( walker, WVL_S_BUS_NODE, BusPrivate_.Link ); if ( node->BusPrivate_.Num && (node->BusPrivate_.Link.Blink == &bus->BusPrivate_.Nodes) ) { /* The first node's unit number is != 0. Insert here. */ break; } if (node->BusPrivate_.Num > new_node->BusPrivate_.Num) { /* There is a gap so insert here. */ break; } /* Continue trying to find a slot. */ new_node->BusPrivate_.Num++; } /* while */ /* Insert before walker. */ InsertTailList(walker, &new_node->BusPrivate_.Link); bus->BusPrivate_.NodeCount++; KeReleaseSpinLock(&bus->BusPrivate_.NodeLock, irql); new_node->Linked = TRUE; /* We might be floating. */ if (bus->Pdo) IoInvalidateDeviceRelations(bus->Pdo, BusRelations); /* Hack: Use the new method for the main bus */ if (bus == &WvBus) WvlAddDeviceToMainBus(new_node->BusPrivate_.Pdo); return; }
NTSTATUS StartIrpClose( IN PC0C_IO_PORT pIoPort, IN PLIST_ENTRY pQueueToComplete) { UNREFERENCED_PARAMETER(pQueueToComplete); if (!pIoPort->exclusiveMode) { PIRP pIrp; InterlockedDecrement(&pIoPort->pDevExt->openCount); pIrp = pIoPort->irpQueues[C0C_QUEUE_CLOSE].pCurrent; pIrp->IoStatus.Information = 0; return STATUS_SUCCESS; } IoInvalidateDeviceRelations(pIoPort->pPhDevObj, BusRelations); SetCloseTimeout(pIoPort); return STATUS_PENDING; }
NTSTATUS FdoPortClose(IN PC0C_FDOPORT_EXTENSION pDevExt, IN PIRP pIrp) { NTSTATUS status; LIST_ENTRY queueToComplete; KIRQL oldIrql; PC0C_IO_PORT pIoPort; pIoPort = pDevExt->pIoPortLocal; pIoPort->isOpen = FALSE; if (pIoPort->pIoPortRemote->plugInMode) IoInvalidateDeviceRelations(pIoPort->pIoPortRemote->pPhDevObj, BusRelations); InitializeListHead(&queueToComplete); KeAcquireSpinLock(pIoPort->pIoLock, &oldIrql); pIoPort->escapeChar = 0; pIoPort->writeHoldingRemote = 0; pIoPort->sendXonXoff = 0; SetModemControl(pIoPort, C0C_MCR_OUT2, C0C_MCR_MASK | C0C_MCR_OPEN, &queueToComplete); FreeBuffer(&pIoPort->readBuf); SetBreakHolding(pIoPort, FALSE, &queueToComplete); KeReleaseSpinLock(pIoPort->pIoLock, oldIrql); FdoPortCompleteQueue(&queueToComplete); status = FdoPortStartIrp(pIoPort, pIrp, C0C_QUEUE_CLOSE, StartIrpClose); if (status != STATUS_PENDING) { pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return status; }
NTSTATUS bus_unplug_dev ( int addr, PFDO_DEVICE_DATA fdodata ) { PLIST_ENTRY entry; PPDO_DEVICE_DATA pdodata; int found=0, all; PAGED_CODE (); if(addr<0||addr>127) return STATUS_INVALID_PARAMETER; all = (0 == addr); ExAcquireFastMutex (&fdodata->Mutex); if (all) { Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE, ("Plugging out all the devices!\n")); } else { Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE, ("Plugging out %d\n", addr)); } if (fdodata->NumPDOs == 0) { // // We got a 2nd plugout...somebody in user space isn't playing nice!!! // Bus_KdPrint (fdodata, BUS_DBG_IOCTL_ERROR, ("BAD BAD BAD...2 removes!!! Send only one!\n")); ExReleaseFastMutex (&fdodata->Mutex); return STATUS_NO_SUCH_DEVICE; } for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE, ("found device %d\n", pdodata->SerialNo)); if (all || addr == pdodata->SerialNo) { Bus_KdPrint (fdodata, BUS_DBG_IOCTL_INFO, ("Plugged out %d\n", pdodata->SerialNo)); pdodata->Present = FALSE; complete_pending_read_irp(pdodata); found = 1; if (!all) { break; } } } ExReleaseFastMutex (&fdodata->Mutex); if (found) { IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations); ExAcquireFastMutex (&fdodata->Mutex); for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if( pdodata->Present ==FALSE){ complete_pending_irp(pdodata); } } ExReleaseFastMutex (&fdodata->Mutex); Bus_KdPrint (fdodata, BUS_DBG_IOCTL_ERROR, ("Device %d is not present\n", addr)); return STATUS_SUCCESS; } return STATUS_INVALID_PARAMETER; }
NTSTATUS bus_plugin_dev(ioctl_usbvbus_plugin * plugin, PFDO_DEVICE_DATA fdodata, PFILE_OBJECT fo) { PDEVICE_OBJECT pdo; PPDO_DEVICE_DATA pdodata, old_pdodata; NTSTATUS status; ULONG len; PLIST_ENTRY entry; unsigned long i; PAGED_CODE (); Bus_KdPrint (fdodata, BUS_DBG_PNP_INFO, ("Exposing PDO\n" "======addr: %d\n" "======vendor:product: %04x:%04x\n", plugin->addr, plugin->vendor, plugin->product)); if(plugin->addr <= 0) return STATUS_INVALID_PARAMETER; ExAcquireFastMutex (&fdodata->Mutex); for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if (plugin->addr == pdodata->SerialNo && pdodata->DevicePnPState != SurpriseRemovePending) { ExReleaseFastMutex (&fdodata->Mutex); return STATUS_INVALID_PARAMETER; } } ExReleaseFastMutex (&fdodata->Mutex); // Create the PDO // Bus_KdPrint(fdodata, BUS_DBG_PNP_NOISE, ("fdodata->NextLowerDriver = 0x%p\n", fdodata->NextLowerDriver)); // // PDO must have a name. You should let the system auto generate a // name by specifying FILE_AUTOGENERATED_DEVICE_NAME in the // DeviceCharacteristics parameter. Let us create a secure deviceobject, // in case the child gets installed as a raw device (RawDeviceOK), to prevent // an unpriviledged user accessing our device. This function is avaliable // in a static WDMSEC.LIB and can be used in Win2k, XP, and Server 2003 // Just make sure that the GUID specified here is not a setup class GUID. // If you specify a setup class guid, you must make sure that class is // installed before enumerating the PDO. // status = IoCreateDeviceSecure(fdodata->Self->DriverObject, sizeof (PDO_DEVICE_DATA), NULL, FILE_DEVICE_BUS_EXTENDER, FILE_AUTOGENERATED_DEVICE_NAME |FILE_DEVICE_SECURE_OPEN, FALSE, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL, // read wdmsec.h for more info (LPCGUID)&GUID_SD_BUSENUM_PDO, &pdo); if (!NT_SUCCESS (status)) { return status; } pdodata = (PPDO_DEVICE_DATA) pdo->DeviceExtension; #define HARDWARE_IDS_TPL L"USB\\Vid_%04x&Pid_%04x&Rev_%04xZUSB\\Vid_%04x&Pid_%04xZ" len = sizeof(HARDWARE_IDS_TPL); pdodata->HardwareIDs = ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG); if (NULL == pdodata->HardwareIDs) { IoDeleteDevice(pdo); return STATUS_INSUFFICIENT_RESOURCES; } RtlStringCchPrintfW(pdodata->HardwareIDs, len/sizeof(wchar_t), HARDWARE_IDS_TPL, plugin->vendor, plugin->product, plugin->version, plugin->vendor, plugin->product); for(i=0;i<sizeof(HARDWARE_IDS_TPL);i++){ if('Z'==pdodata->HardwareIDs[i]) pdodata->HardwareIDs[i]=0; } #define COMPATIBLE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZ" #define COMPATIBLE_COMPOSITE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZUSB\\COMPOSITEZ" if(plugin->inum>1) len = sizeof(COMPATIBLE_COMPOSITE_IDS_TPL); else len = sizeof(COMPATIBLE_IDS_TPL); pdodata->compatible_ids = ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG); RtlZeroMemory(pdodata->compatible_ids, len); if (NULL == pdodata->compatible_ids) { ExFreePool(pdodata->HardwareIDs); IoDeleteDevice(pdo); return STATUS_INSUFFICIENT_RESOURCES; } pdodata->compatible_ids_len = len; RtlStringCchPrintfW(pdodata->compatible_ids, len/sizeof(wchar_t), (plugin->inum>1)?COMPATIBLE_COMPOSITE_IDS_TPL:COMPATIBLE_IDS_TPL, plugin->int0_class, plugin->int0_subclass, plugin->int0_protocol, plugin->int0_class, plugin->int0_subclass, plugin->int0_class); for(i=0;i<len;i++){ if('Z'==pdodata->compatible_ids[i]) pdodata->compatible_ids[i]=0; } old_pdodata = (PPDO_DEVICE_DATA) InterlockedCompareExchange(&((LONG)fo->FsContext), (LONG) pdodata, 0); if(old_pdodata){ KdPrint(("you can't plugin again")); ExFreePool(pdodata->HardwareIDs); ExFreePool(pdodata->compatible_ids); IoDeleteDevice(pdo); return STATUS_INVALID_PARAMETER; } pdodata->SerialNo = plugin->addr; pdodata->fo = fo; pdodata->devid = plugin->devid; pdodata->speed = plugin->speed; bus_init_pdo (pdo, fdodata); // // Device Relation changes if a new pdo is created. So let // the PNP system now about that. This forces it to send bunch of pnp // queries and cause the function driver to be loaded. // IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations); return status; }
NTSTATUS Serenum_InternIoCtl ( PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; PCOMMON_DEVICE_DATA commonData; PPDO_DEVICE_DATA pdoData; // PAGED_CODE(); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; status=IoAcquireRemoveLock(&commonData->RemoveLock,Irp); if(!NT_SUCCESS(status)){ Irp->IoStatus.Information=0; Irp->IoStatus.Status=status; IoCompleteRequest(Irp,IO_NO_INCREMENT); return status; } status = STATUS_SUCCESS; irpStack = IoGetCurrentIrpStackLocation (Irp); ASSERT (IRP_MJ_INTERNAL_DEVICE_CONTROL == irpStack->MajorFunction); pdoData = (PPDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Internal Device Control requests for the PDO. // That is the objects on the bus (representing the serial ports) // // We do pass on the irp if this comes into the fdo, but not if it comes // into the pdo. // if (commonData->IsFDO) { return Serenum_DispatchPassThroughWithoutAcquire( DeviceObject, Irp); }else{ //buffer = Irp->UserBuffer; switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_INTERNAL_SERENUM_REMOVE_SELF: Serenum_KdPrint(pdoData, SER_DBG_SS_TRACE, ("Remove self\n")); ((PFDO_DEVICE_DATA) pdoData->ParentFdo->DeviceExtension)-> PDOForcedRemove = TRUE; Serenum_PDO_EnumMarkMissing(pdoData->ParentFdo->DeviceExtension, DeviceObject->DeviceExtension); IoInvalidateDeviceRelations( ((PFDO_DEVICE_DATA) pdoData->ParentFdo->DeviceExtension)-> UnderlyingPDO, BusRelations ); status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; break; default: // // Pass it through // return Serenum_DispatchPassThroughWithoutAcquire(DeviceObject, Irp); } } Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); IoReleaseRemoveLock(&commonData->RemoveLock,Irp); return status; }
void add_volume_device(superblock* sb, PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath, UINT64 length, ULONG disk_num, ULONG part_num) { NTSTATUS Status; LIST_ENTRY* le; PDEVICE_OBJECT DeviceObject; volume_child* vc; PFILE_OBJECT FileObject; UNICODE_STRING devpath2; BOOL inserted = FALSE, new_pdo = FALSE; pdo_device_extension* pdode = NULL; PDEVICE_OBJECT pdo = NULL; if (devpath->Length == 0) return; ExAcquireResourceExclusiveLite(&pdo_list_lock, TRUE); le = pdo_list.Flink; while (le != &pdo_list) { pdo_device_extension* pdode2 = CONTAINING_RECORD(le, pdo_device_extension, list_entry); if (RtlCompareMemory(&pdode2->uuid, &sb->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { pdode = pdode2; break; } le = le->Flink; } Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); if (!NT_SUCCESS(Status)) { ERR("IoGetDeviceObjectPointer returned %08x\n", Status); ExReleaseResourceLite(&pdo_list_lock); return; } if (!pdode) { if (no_pnp) { Status = IoReportDetectedDevice(drvobj, InterfaceTypeUndefined, 0xFFFFFFFF, 0xFFFFFFFF, NULL, NULL, 0, &pdo); if (!NT_SUCCESS(Status)) { ERR("IoReportDetectedDevice returned %08x\n", Status); ExReleaseResourceLite(&pdo_list_lock); return; } pdode = ExAllocatePoolWithTag(NonPagedPool, sizeof(pdo_device_extension), ALLOC_TAG); if (!pdode) { ERR("out of memory\n"); ExReleaseResourceLite(&pdo_list_lock); return; } } else { Status = IoCreateDevice(drvobj, sizeof(pdo_device_extension), NULL, FILE_DEVICE_DISK, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &pdo); if (!NT_SUCCESS(Status)) { ERR("IoCreateDevice returned %08x\n", Status); ExReleaseResourceLite(&pdo_list_lock); goto fail; } pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; pdode = pdo->DeviceExtension; } RtlZeroMemory(pdode, sizeof(pdo_device_extension)); pdode->type = VCB_TYPE_PDO; pdode->pdo = pdo; pdode->uuid = sb->uuid; ExInitializeResourceLite(&pdode->child_lock); InitializeListHead(&pdode->children); pdode->num_children = sb->num_devices; pdode->children_loaded = 0; pdo->Flags &= ~DO_DEVICE_INITIALIZING; pdo->SectorSize = (USHORT)sb->sector_size; ExAcquireResourceExclusiveLite(&pdode->child_lock, TRUE); new_pdo = TRUE; } else { ExAcquireResourceExclusiveLite(&pdode->child_lock, TRUE); ExConvertExclusiveToSharedLite(&pdo_list_lock); le = pdode->children.Flink; while (le != &pdode->children) { volume_child* vc2 = CONTAINING_RECORD(le, volume_child, list_entry); if (RtlCompareMemory(&vc2->uuid, &sb->dev_item.device_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { // duplicate, ignore ExReleaseResourceLite(&pdode->child_lock); ExReleaseResourceLite(&pdo_list_lock); goto fail; } le = le->Flink; } } vc = ExAllocatePoolWithTag(PagedPool, sizeof(volume_child), ALLOC_TAG); if (!vc) { ERR("out of memory\n"); ExReleaseResourceLite(&pdode->child_lock); ExReleaseResourceLite(&pdo_list_lock); goto fail; } vc->uuid = sb->dev_item.device_uuid; vc->devid = sb->dev_item.dev_id; vc->generation = sb->generation; vc->notification_entry = NULL; Status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange, 0, FileObject, drvobj, pnp_removal, pdode, &vc->notification_entry); if (!NT_SUCCESS(Status)) WARN("IoRegisterPlugPlayNotification returned %08x\n", Status); vc->devobj = DeviceObject; vc->fileobj = FileObject; devpath2 = *devpath; // The PNP path sometimes begins \\?\ and sometimes \??\. We need to remove this prefix // so we can compare properly if the device is removed. if (devpath->Length > 4 * sizeof(WCHAR) && devpath->Buffer[0] == '\\' && (devpath->Buffer[1] == '\\' || devpath->Buffer[1] == '?') && devpath->Buffer[2] == '?' && devpath->Buffer[3] == '\\') { devpath2.Buffer = &devpath2.Buffer[3]; devpath2.Length -= 3 * sizeof(WCHAR); devpath2.MaximumLength -= 3 * sizeof(WCHAR); } vc->pnp_name.Length = vc->pnp_name.MaximumLength = devpath2.Length; vc->pnp_name.Buffer = ExAllocatePoolWithTag(PagedPool, devpath2.Length, ALLOC_TAG); if (vc->pnp_name.Buffer) RtlCopyMemory(vc->pnp_name.Buffer, devpath2.Buffer, devpath2.Length); else { ERR("out of memory\n"); vc->pnp_name.Length = vc->pnp_name.MaximumLength = 0; } vc->size = length; vc->seeding = sb->flags & BTRFS_SUPERBLOCK_FLAGS_SEEDING ? TRUE : FALSE; vc->disk_num = disk_num; vc->part_num = part_num; vc->had_drive_letter = FALSE; le = pdode->children.Flink; while (le != &pdode->children) { volume_child* vc2 = CONTAINING_RECORD(le, volume_child, list_entry); if (vc2->generation < vc->generation) { if (le == pdode->children.Flink) pdode->num_children = sb->num_devices; InsertHeadList(vc2->list_entry.Blink, &vc->list_entry); inserted = TRUE; break; } le = le->Flink; } if (!inserted) InsertTailList(&pdode->children, &vc->list_entry); pdode->children_loaded++; if (pdode->vde && pdode->vde->mounted_device) { device_extension* Vcb = pdode->vde->mounted_device->DeviceExtension; ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE); le = Vcb->devices.Flink; while (le != &Vcb->devices) { device* dev = CONTAINING_RECORD(le, device, list_entry); if (!dev->devobj && RtlCompareMemory(&dev->devitem.device_uuid, &sb->dev_item.device_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { dev->devobj = DeviceObject; dev->disk_num = disk_num; dev->part_num = part_num; init_device(Vcb, dev, FALSE); break; } le = le->Flink; } ExReleaseResourceLite(&Vcb->tree_lock); } if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { pdode->removable = TRUE; if (pdode->vde && pdode->vde->device) pdode->vde->device->Characteristics |= FILE_REMOVABLE_MEDIA; } if (pdode->num_children == pdode->children_loaded || (pdode->children_loaded == 1 && allow_degraded_mount(&sb->uuid))) { if (pdode->num_children == 1) { Status = remove_drive_letter(mountmgr, devpath); if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) WARN("remove_drive_letter returned %08x\n", Status); vc->had_drive_letter = NT_SUCCESS(Status); } else { le = pdode->children.Flink; while (le != &pdode->children) { UNICODE_STRING name; vc = CONTAINING_RECORD(le, volume_child, list_entry); name.Length = name.MaximumLength = vc->pnp_name.Length + (3 * sizeof(WCHAR)); name.Buffer = ExAllocatePoolWithTag(PagedPool, name.Length, ALLOC_TAG); if (!name.Buffer) { ERR("out of memory\n"); ExReleaseResourceLite(&pdode->child_lock); ExReleaseResourceLite(&pdo_list_lock); goto fail; } RtlCopyMemory(name.Buffer, L"\\??", 3 * sizeof(WCHAR)); RtlCopyMemory(&name.Buffer[3], vc->pnp_name.Buffer, vc->pnp_name.Length); Status = remove_drive_letter(mountmgr, &name); if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) WARN("remove_drive_letter returned %08x\n", Status); ExFreePool(name.Buffer); vc->had_drive_letter = NT_SUCCESS(Status); le = le->Flink; } } if ((!new_pdo || !no_pnp) && pdode->vde) { Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, TRUE); if (!NT_SUCCESS(Status)) WARN("IoSetDeviceInterfaceState returned %08x\n", Status); } } ExReleaseResourceLite(&pdode->child_lock); if (new_pdo) { control_device_extension* cde = master_devobj->DeviceExtension; InsertTailList(&pdo_list, &pdode->list_entry); if (!no_pnp) IoInvalidateDeviceRelations(cde->buspdo, BusRelations); } ExReleaseResourceLite(&pdo_list_lock); if (new_pdo && no_pnp) AddDevice(drvobj, pdo); return; fail: ObDereferenceObject(FileObject); }
NTSTATUS FdoPortOpen(IN PC0C_FDOPORT_EXTENSION pDevExt) { LIST_ENTRY queueToComplete; PUCHAR pBase; ULONG size; KIRQL oldIrql; PC0C_IO_PORT pIoPort; if (InterlockedIncrement(&pDevExt->openCount) != 1) { InterlockedDecrement(&pDevExt->openCount); return STATUS_ACCESS_DENIED; } pIoPort = pDevExt->pIoPortLocal; if (pIoPort->plugInMode && !pIoPort->pIoPortRemote->isOpen) { InterlockedDecrement(&pDevExt->openCount); return STATUS_ACCESS_DENIED; } if (pIoPort->exclusiveMode) IoInvalidateDeviceRelations(pIoPort->pPhDevObj, BusRelations); switch (MmQuerySystemSize()) { case MmLargeSystem: size = 4096; pBase = (PUCHAR)C0C_ALLOCATE_POOL(NonPagedPool, size); if (pBase) break; case MmMediumSystem: size = 1024; pBase = (PUCHAR)C0C_ALLOCATE_POOL(NonPagedPool, size); if (pBase) break; case MmSmallSystem: size = 128; pBase = (PUCHAR)C0C_ALLOCATE_POOL(NonPagedPool, size); if (pBase) break; default: size = 0; pBase = NULL; } InitializeListHead(&queueToComplete); #if ENABLE_TRACING if (pIoPort->amountInWriteQueue) { NTSTATUS status; UNICODE_STRING msg; status = STATUS_SUCCESS; RtlInitUnicodeString(&msg, NULL); StrAppendStr0(&status, &msg, L"!!!WARNING!!! amountInWriteQueue = "); StrAppendNum(&status, &msg, pIoPort->amountInWriteQueue, 10); Trace0((PC0C_COMMON_EXTENSION)pDevExt, msg.Buffer); StrFree(&msg); } #endif /* ENABLE_TRACING */ KeAcquireSpinLock(pIoPort->pIoLock, &oldIrql); InitBuffer(&pIoPort->readBuf, pBase, size); pIoPort->amountInWriteQueue = 0; pIoPort->tryWrite = FALSE; pIoPort->errors = 0; pIoPort->waitMask = 0; pIoPort->eventMask = 0; RtlZeroMemory(&pIoPort->perfStats, sizeof(pIoPort->perfStats)); pIoPort->handFlow.XoffLimit = size >> 3; pIoPort->handFlow.XonLimit = size >> 1; pIoPort->pIoPortRemote->brokeIdleChars = 0; SetHandFlow(pIoPort, NULL, &queueToComplete); SetModemControl(pIoPort, C0C_MCR_OPEN, C0C_MCR_OPEN, &queueToComplete); if (pIoPort->pIoPortRemote->pWriteDelay && pIoPort->pIoPortRemote->brokeCharsProbability > 0) StartWriteDelayTimer(pIoPort->pIoPortRemote->pWriteDelay); KeReleaseSpinLock(pIoPort->pIoLock, oldIrql); pIoPort->isOpen = TRUE; if (pIoPort->pIoPortRemote->plugInMode) IoInvalidateDeviceRelations(pIoPort->pIoPortRemote->pPhDevObj, BusRelations); FdoPortCompleteQueue(&queueToComplete); return STATUS_SUCCESS; }
NTSTATUS NdasPortFdoDeviceControlPlugInLogicalUnit( __in PNDASPORT_FDO_EXTENSION FdoExtension, __in PNDAS_LOGICALUNIT_DESCRIPTOR LogicalUnitDescriptor, __in ULONG InternalFlags) { NTSTATUS status; PDEVICE_OBJECT physicalDeviceObject; PNDASPORT_PDO_EXTENSION pdoExtension; NDAS_LOGICALUNIT_INTERFACE logicalUnitInterface; ULONG logicalUnitExtensionSize; ULONG logicalUnitSrbExtensionSize; NDASPORT_PDO_EXTENSION tmp = {0}; PNDAS_LU_QUERY_NDAS_LOGICALUNIT_INTERFACE logicalUnitInterfaceQuery; PFILE_OBJECT externalFileObject; PDEVICE_OBJECT externalDeviceObject; PLIST_ENTRY entry; PAGED_CODE(); NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_INFORMATION, "PlugInLogicalUnit: Fdo=%p, Descriptor=%p (%d,%d,%d,%d)\n", FdoExtension->DeviceObject, LogicalUnitDescriptor, LogicalUnitDescriptor->Address.PortNumber, LogicalUnitDescriptor->Address.PathId, LogicalUnitDescriptor->Address.TargetId, LogicalUnitDescriptor->Address.Lun); if (LogicalUnitDescriptor->Address.PortNumber != FdoExtension->PortNumber) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR, "Port Number is not invalid. UserPortNumber=%d, PortNumber=%d\n", LogicalUnitDescriptor->Address.PortNumber, FdoExtension->PortNumber); return STATUS_INVALID_PARAMETER_1; } // // Following code walks the PDO list to check whether // the input serial number is unique. // Let's first assume it's unique // tmp.IsTemporary = TRUE; tmp.LogicalUnitAddress = LogicalUnitDescriptor->Address; // // Just be aware: If a user unplugs and plugs in the device // immediately, in a split second, even before we had a chance to // clean up the previous PDO completely, we might fail to // accept the device. // ExAcquireFastMutex (&FdoExtension->Mutex); for (entry = FdoExtension->ListOfPDOs.Flink; entry != &FdoExtension->ListOfPDOs; entry = entry->Flink) { PNDASPORT_PDO_EXTENSION pdoEntry; pdoEntry = CONTAINING_RECORD(entry, NDASPORT_PDO_EXTENSION, Link); if (tmp.LogicalUnitAddress.Address == pdoEntry->LogicalUnitAddress.Address) { ExReleaseFastMutex (&FdoExtension->Mutex); return STATUS_OBJECT_NAME_COLLISION; } } // // We adds a temporary LU for the place holder // InsertTailList(&FdoExtension->ListOfPDOs, &tmp.Link); ++(FdoExtension->NumberOfPDOs); ExReleaseFastMutex (&FdoExtension->Mutex); // // Save the information to the registry // if (!TestFlag(InternalFlags, NDASPORT_FDO_PLUGIN_FLAG_NO_REGISTRY)) { status = NdasPortFdoRegSaveLogicalUnit( FdoExtension, LogicalUnitDescriptor); if (!NT_SUCCESS(status)) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR, "NdasPortFdoGetExtendedInterface failed, Status=%x\n", status); // // Delete the temporary LU // ExAcquireFastMutex (&FdoExtension->Mutex); RemoveEntryList(&tmp.Link); --(FdoExtension->NumberOfPDOs); ExReleaseFastMutex (&FdoExtension->Mutex); return status; } } // // Create the PDO // status = STATUS_INVALID_PARAMETER; logicalUnitInterface.Version = NDAS_LOGICALUNIT_INTERFACE_VERSION; logicalUnitInterface.Size = sizeof(NDAS_LOGICALUNIT_INTERFACE); externalFileObject = NULL; externalDeviceObject = NULL; if (LogicalUnitDescriptor->Type & NdasExternalType) { status = NdasPortFdoGetExtendedInterface( &LogicalUnitDescriptor->ExternalTypeGuid, &externalFileObject, &externalDeviceObject, &logicalUnitInterfaceQuery); if (!NT_SUCCESS(status)) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR, "NdasPortFdoGetExtendedInterface failed, Status=%x\n", status); } else { status = (*logicalUnitInterfaceQuery)( LogicalUnitDescriptor, &logicalUnitInterface, &logicalUnitExtensionSize, &logicalUnitSrbExtensionSize); } // // Be sure to call ObDereferenceObject(externalFileObject) // on failure in this function or later when the PDO is destroyed // } else { switch (LogicalUnitDescriptor->Type) { case NdasDiskDevice: case NdasAtaDevice: logicalUnitInterfaceQuery = NdasAtaDeviceGetNdasLogicalUnitInterface; break; default: logicalUnitInterfaceQuery = NULL; break; } if (NULL == logicalUnitInterfaceQuery) { status = STATUS_NOT_SUPPORTED; } else { status = (*logicalUnitInterfaceQuery)( LogicalUnitDescriptor, &logicalUnitInterface, &logicalUnitExtensionSize, &logicalUnitSrbExtensionSize); } } if (!NT_SUCCESS(status)) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR, "GetNdasLogicalUnitInterface failed for %d, Status=%x\n", LogicalUnitDescriptor->Type, status); // // Delete the temporary LU // ExAcquireFastMutex (&FdoExtension->Mutex); RemoveEntryList(&tmp.Link); --(FdoExtension->NumberOfPDOs); ExReleaseFastMutex (&FdoExtension->Mutex); // // Dereference External File Object if it is external // if (NULL != externalFileObject) { ObDereferenceObject(externalFileObject); externalFileObject = NULL; externalDeviceObject = NULL; } return status; } status = NdasPortPdoCreatePhysicalDeviceObject( FdoExtension, &logicalUnitInterface, LogicalUnitDescriptor, logicalUnitExtensionSize, logicalUnitSrbExtensionSize, externalDeviceObject, externalFileObject, &physicalDeviceObject); if (!NT_SUCCESS(status)) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR, "NdasPortPdoCreatePhysicalDeviceObject failed, Status=%08X\n", status); // // Delete the temporary LU // ExAcquireFastMutex (&FdoExtension->Mutex); RemoveEntryList(&tmp.Link); --(FdoExtension->NumberOfPDOs); ExReleaseFastMutex (&FdoExtension->Mutex); // // Dereference External File Object if it is external // if (NULL != externalFileObject) { ObDereferenceObject(externalFileObject); externalFileObject = NULL; externalDeviceObject = NULL; } return status; } // // Remove the temporary entry and add the actual entry // We don't need to change the counter (-1 + +1 = 0 !) // pdoExtension = NdasPortPdoGetExtension(physicalDeviceObject); ExAcquireFastMutex(&FdoExtension->Mutex); RemoveEntryList(&tmp.Link); InsertTailList(&FdoExtension->ListOfPDOs, &pdoExtension->Link); ExReleaseFastMutex(&FdoExtension->Mutex); // // This should be the last step in initialization. // physicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_INFORMATION, "Child physical device object created, Pdo=%p\n", physicalDeviceObject); // // Device Relation changes if a new pdo is created. So let // the PNP system now about that. This forces it to send bunch of PNP // queries and cause the function driver to be loaded. // NdasPortFdoNotifyPnpEvent( FdoExtension, NdasPortLogicalUnitIsReady, LogicalUnitDescriptor->Address); NdasPortPdoNotifyWmiEvent( FdoExtension, NdasPortLogicalUnitIsReady, LogicalUnitDescriptor->Address); IoInvalidateDeviceRelations(FdoExtension->LowerPdo, BusRelations); return STATUS_SUCCESS; }
NTSTATUS NdasPortFdoDeviceControlEjectOrUnplugLogicalUnit( PNDASPORT_FDO_EXTENSION FdoExtension, PNDAS_LOGICALUNIT_ADDRESS LogicalUnitAddress, ULONG Flags, BOOLEAN Eject) { NTSTATUS status; PNDASPORT_PDO_EXTENSION targetPdo; PLIST_ENTRY entry; PAGED_CODE(); LogicalUnitAddress->PortNumber = FdoExtension->PortNumber; status = STATUS_DEVICE_DOES_NOT_EXIST; ExAcquireFastMutex (&FdoExtension->Mutex); for (entry = FdoExtension->ListOfPDOs.Flink; entry != &FdoExtension->ListOfPDOs; entry = entry->Flink) { targetPdo = CONTAINING_RECORD(entry, NDASPORT_PDO_EXTENSION, Link); if (LogicalUnitAddress->Address == targetPdo->LogicalUnitAddress.Address) { // // Temporary pdo is regarded as none // if (targetPdo->IsTemporary) { status = STATUS_DEVICE_NOT_READY; break; } if (!targetPdo->IsDeviceRelationReported) { // // Pdo is not yet reported to Pnp bus relations. // If we call IoRequestDeviceEject before completing // the bus relation query, it will lead pnp bug check. // status = STATUS_DEVICE_BUSY; break; } status = STATUS_SUCCESS; if (Eject) { // Nothing to do here } else { // // To be unplugged in the next invalidate device relations // targetPdo->Present = FALSE; } break; } } ExReleaseFastMutex (&FdoExtension->Mutex); if (NT_SUCCESS(status)) { if (Eject) { IoRequestDeviceEject(targetPdo->DeviceObject); } else { IoInvalidateDeviceRelations( FdoExtension->LowerPdo, BusRelations); } } return status; }
NTSTATUS FDO_StartDevice( PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS Status; PFDO_DEVICE_EXTENSION FDODeviceExtension; /* Get device extension */ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ASSERT(FDODeviceExtension->Common.IsFDO); /* First start lower device */ Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp); if (!NT_SUCCESS(Status)) { /* Failed to start lower device */ DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status); return Status; } /* Get descriptors */ Status = USBCCGP_GetDescriptors(DeviceObject); if (!NT_SUCCESS(Status)) { /* Failed to start lower device */ DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status); return Status; } /* Get capabilities */ Status = FDO_QueryCapabilities(DeviceObject, &FDODeviceExtension->Capabilities); if (!NT_SUCCESS(Status)) { /* Failed to start lower device */ DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status); return Status; } /* Now select the configuration */ Status = USBCCGP_SelectConfiguration(DeviceObject, FDODeviceExtension); if (!NT_SUCCESS(Status)) { /* Failed to select interface */ DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status); return Status; } /* Query bus interface */ USBCCGP_QueryInterface(FDODeviceExtension->NextDeviceObject, &FDODeviceExtension->BusInterface); /* Now enumerate the functions */ Status = USBCCGP_EnumerateFunctions(DeviceObject); if (!NT_SUCCESS(Status)) { /* Failed to enumerate functions */ DPRINT1("Failed to enumerate functions with %x\n", Status); return Status; } /* Sanity checks */ ASSERT(FDODeviceExtension->FunctionDescriptorCount); ASSERT(FDODeviceExtension->FunctionDescriptor); DumpFunctionDescriptor(FDODeviceExtension->FunctionDescriptor, FDODeviceExtension->FunctionDescriptorCount); /* Now create the pdo */ Status = FDO_CreateChildPdo(DeviceObject); if (!NT_SUCCESS(Status)) { /* Failed */ DPRINT1("FDO_CreateChildPdo failed with %x\n", Status); return Status; } /* Inform pnp manager of new device objects */ IoInvalidateDeviceRelations(FDODeviceExtension->PhysicalDeviceObject, BusRelations); /* Done */ DPRINT("[USBCCGP] FDO initialized successfully\n"); return Status; }
VOID NTAPI WorkerThread(IN PVOID Context) { PHUB_DEVICE_EXTENSION DeviceExtension; PDEVICE_OBJECT DeviceObject, Pdo; PHUB_CHILDDEVICE_EXTENSION PdoExtension; PURB Urb = NULL; PORTSTATUSANDCHANGE PortStatusAndChange; int PortLoop, DeviceCount; NTSTATUS Status; USB_DEVICE_DESCRIPTOR DevDesc; USB_CONFIGURATION_DESCRIPTOR ConfigDesc; ULONG DevDescSize, ConfigDescSize; PUSB_STRING_DESCRIPTOR StringDesc; USB_STRING_DESCRIPTOR LanguageIdDescriptor; PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context; DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context; DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; /* Determine where in the children array to store this device info */ for (DeviceCount = 0; DeviceCount < USB_MAXCHILDREN; DeviceCount++) { if (DeviceExtension->UsbChildren[DeviceCount] == NULL) { break; } } Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); if (!Urb) { DPRINT1("Failed to allocate memory for URB!\n"); ASSERT(FALSE); } RtlZeroMemory(Urb, sizeof(URB)); for (PortLoop = 0; PortLoop < DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) { /* Get the port status */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_OUT, 0, USB_REQUEST_GET_STATUS, 0, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get PortStatus!\n"); goto CleanUp; } DPRINT("Notification Port %x:\n", PortLoop + 1); DPRINT("Status %x\n", PortStatusAndChange.Status); DPRINT("Change %x\n", PortStatusAndChange.Change); if (PortStatusAndChange.Change == USB_PORT_STATUS_RESET) { /* Clear the Reset */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Clear the Port Reset with Status %x!\n", Status); goto CleanUp; } UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_OUT, 0, USB_REQUEST_GET_STATUS, 0, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT("Status %x\n", PortStatusAndChange.Status); DPRINT("Change %x\n", PortStatusAndChange.Change); /* Create the UsbDevice */ Status = DeviceExtension->HubInterface.CreateUsbDevice(DeviceExtension->RootHubPdo, (PVOID)&DeviceExtension->UsbChildren[DeviceCount], DeviceExtension->RootHubUsbDevice, PortStatusAndChange.Status, PortLoop + 1); DPRINT1("CreateUsbDevice Status %x\n", Status); Status = DeviceExtension->HubInterface.InitializeUsbDevice(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount]); DPRINT1("InitializeUsbDevice Status %x\n", Status); DevDescSize = sizeof(USB_DEVICE_DESCRIPTOR); ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); Status = DeviceExtension->HubInterface.GetUsbDescriptors(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount], (PUCHAR)&DevDesc, &DevDescSize, (PUCHAR)&ConfigDesc, &ConfigDescSize); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Get Usb Deccriptors %x!\n", Status); } DumpDeviceDescriptor(&DevDesc); Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(HUB_CHILDDEVICE_EXTENSION), NULL, FILE_DEVICE_CONTROLLER, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &DeviceExtension->Children[DeviceCount]); if (!NT_SUCCESS(Status)) { DPRINT1("UsbHub; IoCreateDevice failed with status %x\n",Status); goto CleanUp; } Pdo = DeviceExtension->Children[DeviceCount]; DPRINT1("Created New Device with %x\n", Pdo); Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; PdoExtension = Pdo->DeviceExtension; RtlZeroMemory(PdoExtension, sizeof(HUB_CHILDDEVICE_EXTENSION)); PdoExtension->DeviceId = ExAllocatePoolWithTag(NonPagedPool, 32 * sizeof(WCHAR), USB_HUB_TAG); RtlZeroMemory(PdoExtension->DeviceId, 32 * sizeof(WCHAR)); swprintf(PdoExtension->DeviceId, L"USB\\Vid_%04x&Pid_%04x", DevDesc.idVendor, DevDesc.idProduct); /* Get the LANGids */ RtlZeroMemory(&LanguageIdDescriptor, sizeof(USB_STRING_DESCRIPTOR)); UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, 0, 0, &LanguageIdDescriptor, NULL, sizeof(USB_STRING_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); /* Get the length of the SerialNumber */ StringDesc = ExAllocatePoolWithTag(PagedPool, 64, USB_HUB_TAG); RtlZeroMemory(StringDesc, 64); StringDesc->bLength = 0; StringDesc->bDescriptorType = 0; UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, DevDesc.iSerialNumber, LanguageIdDescriptor.bString[0], StringDesc, NULL, 64, NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); PdoExtension->InstanceId = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); DPRINT1("PdoExtension->InstanceId %x\n",PdoExtension->InstanceId); RtlZeroMemory(PdoExtension->InstanceId, (StringDesc->bLength + 1) * sizeof(WCHAR)); RtlCopyMemory(PdoExtension->InstanceId, &StringDesc->bString[0], StringDesc->bLength); DPRINT1("------>SerialNumber %S\n", PdoExtension->InstanceId); RtlZeroMemory(StringDesc, 64); StringDesc->bLength = 0; StringDesc->bDescriptorType = 0; UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, DevDesc.iProduct, LanguageIdDescriptor.bString[0], StringDesc, NULL, 64, NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); PdoExtension->TextDescription = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); RtlZeroMemory(PdoExtension->TextDescription, (StringDesc->bLength + 1) * sizeof(WCHAR)); RtlCopyMemory(PdoExtension->TextDescription, &StringDesc->bString[0], StringDesc->bLength); ExFreePool(StringDesc); DPRINT1("------>TextDescription %S\n", PdoExtension->TextDescription); PdoExtension->IsFDO = FALSE; PdoExtension->Parent = DeviceObject; Pdo->Flags &= ~DO_DEVICE_INITIALIZING; ExFreePool(WorkItemData); ExFreePool(Urb); IoInvalidateDeviceRelations(DeviceExtension->RootHubPdo, BusRelations); return; } /* Is a device connected to this port */ if (PortStatusAndChange.Change == USB_PORT_STATUS_CONNECT) { /* Clear the Connect from ProtChange */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Clear the Port Connect!\n"); goto CleanUp; } /* Send the miniport controller a SCE request so when the port resets we can be informed */ WaitForUsbDeviceArrivalNotification(DeviceObject); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_SET_FEATURE, PORT_RESET, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Reset the port!\n"); goto CleanUp; } /* At this point the miniport will complete another SCE to inform of Reset completed */ } } CleanUp: ExFreePool(WorkItemData); ExFreePool(Urb); }
int body() { if( NT_SUCCESS( status ) ) { ExAcquireFastMutex(); SetFlags(); ExReleaseFastMutex(); WarmPollPeriod = HtRegGetDword(); if( WarmPollPeriod < 5 ) { WarmPollPeriod = 5; } else { if( WarmPollPeriod > 20 ) { WarmPollPeriod = 20; } } { if (nondet()) { // We've got it. Now get a pointer to it. polling = 1; if(nondet()) { //--------------------------------------------- { LARGE_INTEGER timeOut1; NTSTATUS status; UCHAR deviceStatus; PCHAR devId; BOOLEAN requestRescan; const ULONG pollingFailureThreshold = 10; //pick an arbitrary but reasonable number do { if( PowerStateIsAC ) { } else { } status = KeWaitForSingleObject(); if( nondet() ) { break; } if( !PowerStateIsAC ) { goto loc_continue; } if( STATUS_TIMEOUT == status ) { if( nondet() ) { // try to acquire port if( HtTryAllocatePort() ) { requestRescan = FALSE; // check for something connected deviceStatus = GetStatus(); if( nondet()) { } else { // we might have something connected // try a device ID to confirm devId = P4ReadRawIeee1284DeviceId(); if( devId ) { PCHAR mfg, mdl, cls, des, aid, cid; // RawIeee1284 string includes 2 bytes of length data at beginning HTPnpFindDeviceIdKeys(); if( mfg && mdl ) { requestRescan = TRUE; } } else { } if( requestRescan ) { } else { if(nondet() ) { } } } HtFreePort( ); if( requestRescan ) { IoInvalidateDeviceRelations(); } } else { } } else { } } loc_continue: { int ddd; ddd = ddd; } } while( TRUE ); } //--------------------------------------------- polling = 0; } else { polling = 0; // error } } else { } } } // Failsafe polling = 1; while (1) { HTPnpFindDeviceIdKeys(); } }
// device io control for bus fdo NTSTATUS DispatchIoControl(PDEVICE_OBJECT pDevice,PIRP pIrp) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; PFdoExt pFdoExt = static_cast<PFdoExt>(pDevice->DeviceExtension); if(pFdoExt->m_bFdo) { BOOLEAN bCallNext = TRUE; IncIoCount(pFdoExt); PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp); switch(pIoStack->Parameters.DeviceIoControl.IoControlCode) { // add a scsi device,input is a miniport config struct case IOCTL_TIAMO_BUS_PLUGIN: status = STATUS_INVALID_PARAMETER; bCallNext = FALSE; if(pIoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(MiniportConfig)) { PMiniportConfig pMiniportConfig = static_cast<PMiniportConfig>(pIrp->AssociatedIrp.SystemBuffer); if(pMiniportConfig && pMiniportConfig->m_ulDevices > 0 && pMiniportConfig->m_ulDevices < 5) { ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo); // create the only one pdo if(!pFdoExt->m_pEnumPdo) { PDEVICE_OBJECT pdo; status = IoCreateDevice(pDevice->DriverObject,sizeof(PdoExt),NULL,FILE_DEVICE_BUS_EXTENDER, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,FALSE,&pdo); if(NT_SUCCESS(status)) { // set the pdo ext PPdoExt pPdoExt = static_cast<PPdoExt>(pdo->DeviceExtension); RtlZeroMemory(pPdoExt,sizeof(PdoExt)); pPdoExt->m_bFdo = FALSE; // save the fdo here pPdoExt->m_pParentFdo = pDevice; pPdoExt->m_ulCurrentPnpState = pPdoExt->m_ulPrevPnpState = -1; pPdoExt->m_sysPowerState = PowerSystemWorking; pPdoExt->m_devPowerState = PowerDeviceD3; pPdoExt->m_bPresent = TRUE; //pdo->Flags |= DO_POWER_PAGABLE; pFdoExt->m_pEnumPdo = pdo; RtlMoveMemory(pPdoExt->m_szImageFileName,pMiniportConfig->m_szImageFileName,1024 * sizeof(WCHAR)); pPdoExt->m_ulDevices = pMiniportConfig->m_ulDevices; pdo->Flags &= ~DO_DEVICE_INITIALIZING; devDebugPrint(DRIVER_NAME"*******IOCTL_TIAMO_BUS_PLUGIN detected new device and created a pdo.\n"); } } else { status = STATUS_DEVICE_ALREADY_ATTACHED; } ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo); if(NT_SUCCESS(status)) IoInvalidateDeviceRelations(pFdoExt->m_pPhysicalDevice,BusRelations); } } break; // miniport get config case IOCTL_TIAMO_BUS_MINIPORT_GET_CONFIG: status = STATUS_INVALID_PARAMETER; bCallNext = FALSE; if(pIoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(MiniportConfig)) { ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo); if(pFdoExt->m_pEnumPdo) { PPdoExt pPdoExt = static_cast<PPdoExt>(pFdoExt->m_pEnumPdo->DeviceExtension); if(pPdoExt) { RtlMoveMemory(pIrp->AssociatedIrp.SystemBuffer,&pPdoExt->m_ulDevices,sizeof(MiniportConfig)); pIrp->IoStatus.Information = sizeof(MiniportConfig); status = STATUS_SUCCESS; devDebugPrint(DRIVER_NAME"*******IOCTL_TIAMO_BUS_MINIPORT_GET_CONFIG upper miniport fdo get it's pdo configuration\n"); } } else { status = STATUS_NO_SUCH_DEVICE; } ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo); } break; } DecIoCount(pFdoExt); if(bCallNext) return IoCallDriver(pFdoExt->m_pLowerDevice,pIrp); } pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp,IO_NO_INCREMENT); return status; }
VOID NdasPortBindingChangeHandler( __in TDI_PNP_OPCODE PnPOpcode, __in PUNICODE_STRING TransportName, __in PWSTR BindingList) { PNDASPORT_DRIVER_EXTENSION driverExtension; PAGED_CODE(); driverExtension = (PNDASPORT_DRIVER_EXTENSION) IoGetDriverObjectExtension( NdasPortDriverObject, &NdasPortDriverExtensionTag); ASSERT(NULL != driverExtension); DebugPrint((1, "NdasPortBindingChangeHandler: PnPOpcode=%s(%x), TransportName=%wZ,\n", DbgTdiPnpOpCodeString(PnPOpcode), PnPOpcode, TransportName)); NdasPortTrace(NDASPORT_GENERAL, TRACE_LEVEL_INFORMATION, "NdasPortBindingChangeHandler: PnpOpCode=%s(%x), TransportName=%wZ,\n", DbgTdiPnpOpCodeString(PnPOpcode), PnPOpcode, TransportName); switch (PnPOpcode) { case TDI_PNP_OP_ADD: case TDI_PNP_OP_DEL: case TDI_PNP_OP_PROVIDERREADY: break; case TDI_PNP_OP_NETREADY: { BOOLEAN previouslyReady; previouslyReady = driverExtension->IsNetworkReady; driverExtension->IsNetworkReady = TRUE; // // State change from network "not ready" to // network "ready" state. Will initialize // device detection // if (previouslyReady == FALSE) { KIRQL oldIrql; PLIST_ENTRY entry; DebugPrint((3, "Network is now ready!\n")); // // Request device enumeration request from PnP. // KeAcquireSpinLock(&driverExtension->FdoListSpinLock, &oldIrql); for (entry = driverExtension->FdoList.Flink; entry != &driverExtension->FdoList; entry = entry->Flink) { PNDASPORT_FDO_EXTENSION fdoExtension; fdoExtension = CONTAINING_RECORD(entry, NDASPORT_FDO_EXTENSION, Link); IoInvalidateDeviceRelations( fdoExtension->LowerPdo, BusRelations); } KeReleaseSpinLock(&driverExtension->FdoListSpinLock, oldIrql); } break; } default: { break; } } return; }