NTSTATUS DkDefault(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS ntStat = STATUS_SUCCESS; PDEVICE_EXTENSION pDevExt = NULL; PIO_STACK_LOCATION pStack = NULL; PDEVICE_OBJECT pNextDevObj = NULL; pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error acquire lock!", ntStat); DkCompleteRequest(pIrp, ntStat, 0); return ntStat; } pStack = IoGetCurrentIrpStackLocation(pIrp); DkDbgVal("DkDefault", pStack->MajorFunction); pNextDevObj = pDevExt->pNextDevObj; IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pNextDevObj, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; }
////////////////////////////////////////////////////////////////////////// // Function to get USB Root Hub device name, e.g., \Device\USBPDO-4 // NTSTATUS DkGetHubDevName(PIO_STACK_LOCATION pStack, PIRP pIrp, PULONG pUlRes) { NTSTATUS ntStat = STATUS_SUCCESS, clStat = STATUS_SUCCESS; HANDLE hObj; OBJECT_ATTRIBUTES oa; UNICODE_STRING usHubPath, usTgtDev; ULONG ulRet; RtlInitUnicodeString(&usHubPath, (PCWSTR) pIrp->AssociatedIrp.SystemBuffer); InitializeObjectAttributes(&oa, &usHubPath, OBJ_KERNEL_HANDLE, NULL, NULL); ntStat = ZwOpenSymbolicLinkObject(&hObj, GENERIC_ALL, &oa); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error open symbolic link!", ntStat); return ntStat; } usTgtDev.Length = 0; usTgtDev.MaximumLength = 512; usTgtDev.Buffer = (PWSTR) ExAllocatePoolWithTag(NonPagedPool, 512, DKPORT_MTAG); RtlFillMemory(usTgtDev.Buffer, 512, '\0'); ntStat = ZwQuerySymbolicLinkObject(hObj, &usTgtDev, &ulRet); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error query symbolic link!", ntStat); pIrp->IoStatus.Status = ntStat; *pUlRes = 0; } else { RtlFillMemory(pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength, '\0'); RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, usTgtDev.Buffer, 512); pIrp->IoStatus.Information = usTgtDev.Length; pIrp->IoStatus.Status = ntStat; *pUlRes = (ULONG) usTgtDev.Length; } ExFreePoolWithTag(usTgtDev.Buffer, DKPORT_MTAG); clStat = ZwClose(hObj); if (!NT_SUCCESS(clStat)) { DkDbgVal("Error close symbolic link!", clStat); } return ntStat; }
NTSTATUS USBPcapSetUpBuffer(PUSBPCAP_ROOTHUB_DATA pData, UINT32 bytes) { NTSTATUS status; KIRQL irql; PVOID buffer; /* Minimum buffer size is 4 KiB, maximum 128 MiB */ if (bytes < 4096 || bytes > 134217728) { return STATUS_INVALID_PARAMETER; } buffer = ExAllocatePoolWithTag(NonPagedPool, (SIZE_T) bytes, USBPCAP_BUFFER_TAG); if (buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } status = STATUS_SUCCESS; KeAcquireSpinLock(&pData->bufferLock, &irql); if (pData->buffer == NULL) { pData->buffer = buffer; pData->bufferSize = bytes; pData->readOffset = 0; pData->writeOffset = 0; USBPcapWriteGlobalHeader(pData); DkDbgVal("Created new buffer", bytes); } else { UINT32 allocated = USBPcapGetBufferAllocated(pData); if (allocated >= bytes) { status = STATUS_BUFFER_TOO_SMALL; } else { /* Copy (if any) unread data to new buffer */ if (allocated > 0) { USBPcapBufferRead(pData, buffer, bytes); } /* Free the old buffer */ ExFreePool(pData->buffer); pData->buffer = buffer; pData->readOffset = 0; pData->writeOffset = allocated; } } KeReleaseSpinLock(&pData->bufferLock, irql); return status; }
NTSTATUS DkPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS ntStat = STATUS_SUCCESS; PDEVICE_EXTENSION pDevExt = NULL; PIO_STACK_LOCATION pStack = NULL; pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; pStack = IoGetCurrentIrpStackLocation(pIrp); if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB) { return DkHubFltPnP(pDevExt, pStack, pIrp); } else if (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE) { return DkTgtPnP(pDevExt, pStack, pIrp); } else { // Do nothing } ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error acquire lock!", ntStat); DkCompleteRequest(pIrp, ntStat, 0); return ntStat; } IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; }
NTSTATUS DkHubFltPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) { NTSTATUS ntStat = STATUS_SUCCESS; ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error lock!", ntStat); DkCompleteRequest(pIrp, ntStat, 0); return ntStat; } switch (pStack->MinorFunction) { case IRP_MN_START_DEVICE: DkDbgStr("IRP_MN_START_DEVICE"); ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; case IRP_MN_REMOVE_DEVICE: { PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; DkDbgStr("IRP_MN_REMOVE_DEVICE"); IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); if (pDeviceData != NULL && pDeviceData->pRootData != NULL && pDeviceData->pRootData->controlDevice != NULL) { USBPcapDeleteRootHubControlDevice(pDeviceData->pRootData->controlDevice); } IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp); DkDetachAndDeleteHubFilt(pDevExt); return ntStat; } case IRP_MN_QUERY_DEVICE_RELATIONS: DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS"); ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; default: DkDbgVal("", pStack->MinorFunction); break; } IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; }
NTSTATUS DkHubFltPnpHandleQryDevRels(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) { NTSTATUS ntStat = STATUS_SUCCESS; PDEVICE_RELATIONS pDevRel = NULL; PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; ULONG i; ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error lock!", ntStat); DkCompleteRequest(pIrp, ntStat, 0); return ntStat; } /* PnP manager sends this at PASSIVE_LEVEL */ switch (pStack->Parameters.QueryDeviceRelations.Type) { case BusRelations: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: BusRelations"); ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); // After we forward the request, the bus driver have created or deleted // a child device object. When bus driver created one (or more), this is the PDO // of our target device, we create and attach a filter object to it. // Note that we only attach the last detected USB device on it's Hub. if (NT_SUCCESS(ntStat)) { pDevRel = (PDEVICE_RELATIONS) pIrp->IoStatus.Information; if (pDevRel) { USBPcapPrintUSBPChildrenInformation(pDevExt->pNextDevObj); DkDbgVal("Child(s) number", pDevRel->Count); for (i = 0; i < pDevRel->Count; i++) { PDEVICE_OBJECT *child; BOOLEAN found = FALSE; child = pDeviceData->previousChildren; /* Search only if there are any children */ if (child != NULL) { while (*child != NULL) { if (*child == pDevRel->Objects[i]) { found = TRUE; break; } child++; } } if (found == FALSE) { /* New device attached */ DkCreateAndAttachTgt(pDevExt, pDevRel->Objects[i]); } } /* Free old children information */ if (pDeviceData->previousChildren != NULL) { ExFreePool(pDeviceData->previousChildren); pDeviceData->previousChildren = NULL; } if (pDevRel->Count > 0) { PDEVICE_OBJECT *children; children = ExAllocatePoolWithTag(NonPagedPool, sizeof(PDEVICE_OBJECT) * (pDevRel->Count + 1), DKPORT_MTAG); if (children != NULL) { for (i = 0; i < pDevRel->Count; i++) { children[i] = pDevRel->Objects[i]; } /* NULL-terminate the array */ children[pDevRel->Count] = NULL; pDeviceData->previousChildren = children; } else { /* Failed to allocate memory. Just leave it * as it. In next pass we won't check for * new devices (probably will miss some). * But it's probably the best we can do. */ DkDbgStr("Failed to allocate previousChildren"); } } } } IoCompleteRequest(pIrp, IO_NO_INCREMENT); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; case EjectionRelations: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: EjectionRelations"); break; case RemovalRelations: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: RemovalRelations"); break; case TargetDeviceRelation: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: TargetDeviceRelation"); break; case PowerRelations: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: PowerRelations"); break; case SingleBusRelations: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: SingleBusRelations"); break; case TransportRelations: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: TransportRelations"); break; default: DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: Unknown query relation type"); break; } IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; }
NTSTATUS DkTgtPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) { NTSTATUS ntStat = STATUS_SUCCESS; PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error lock!", ntStat); DkCompleteRequest(pIrp, ntStat, 0); return ntStat; } switch (pStack->MinorFunction) { case IRP_MN_START_DEVICE: /* IRP_MN_START_DEVICE is sent at PASSIVE_LEVEL */ DkDbgStr("IRP_MN_START_DEVICE"); ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); if (NT_SUCCESS(USBPcapGetDeviceUSBInfo(pDevExt))) { DkDbgVal("Started device", pDeviceData->deviceAddress); } else { DkDbgStr("Failed to get info of started device"); } IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; case IRP_MN_QUERY_DEVICE_RELATIONS: /* Keep track of, and create child devices only for hubs. * Do not create child filters for composite devices. */ if (pDeviceData->isHub == TRUE) { DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS"); ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; } else { break; } case IRP_MN_REMOVE_DEVICE: DkDbgStr("IRP_MN_REMOVE_DEVICE"); IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp); DkDetachAndDeleteTgt(pDevExt); return ntStat; default: DkDbgVal("", pStack->MinorFunction); break; } IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; }
NTSTATUS USBPcapCreateRootHubControlDevice(IN PDEVICE_EXTENSION hubExt, OUT PDEVICE_OBJECT *control, OUT USHORT *busId) { UNICODE_STRING ntDeviceName; UNICODE_STRING symbolicLinkName; PDEVICE_OBJECT controlDevice = NULL; PDEVICE_EXTENSION controlExt = NULL; NTSTATUS status; USHORT id; PWCHAR ntNameBuffer[MAX_NTNAME_LEN]; PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN]; ASSERT(hubExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB); /* Acquire the control device ID */ id = (USHORT) InterlockedIncrement(&g_controlId); ntDeviceName.Length = 0; ntDeviceName.MaximumLength = MAX_NTNAME_LEN; ntDeviceName.Buffer = (PWSTR)ntNameBuffer; symbolicLinkName.Length = 0; symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN; symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer; status = RtlUnicodeStringPrintf(&ntDeviceName, NTNAME_PREFIX L"%hu", id); if (!NT_SUCCESS(status)) { return status; } status = RtlUnicodeStringPrintf(&symbolicLinkName, SYMBOLIC_PREFIX L"%hu", id); if (!NT_SUCCESS(status)) { return status; } KdPrint(("Creating device %wZ (%wZ)\n", &ntDeviceName, &symbolicLinkName)); status = IoCreateDeviceSecure(hubExt->pDrvObj, sizeof(DEVICE_EXTENSION), &ntDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, TRUE, /* Exclusive device */ &SDDL_DEVOBJ_SYS_ALL_ADM_ALL_EVERYONE_ANY, NULL, &controlDevice); if (NT_SUCCESS(status)) { controlDevice->Flags |= DO_DIRECT_IO; status = IoCreateSymbolicLink(&symbolicLinkName, &ntDeviceName); if (!NT_SUCCESS(status)) { IoDeleteDevice(controlDevice); KdPrint(("IoCreateSymbolicLink failed %x\n", status)); return status; } controlExt = (PDEVICE_EXTENSION)controlDevice->DeviceExtension; controlExt->deviceMagic = USBPCAP_MAGIC_CONTROL; controlExt->pThisDevObj = controlDevice; controlExt->pNextDevObj = NULL; controlExt->pDrvObj = hubExt->pDrvObj; IoInitializeRemoveLock(&controlExt->removeLock, 0, 0, 0); controlExt->parentRemoveLock = &hubExt->removeLock; /* Initialize USBPcap control context */ controlExt->context.control.id = id; controlExt->context.control.pRootHubObject = hubExt->pThisDevObj; KeInitializeSpinLock(&controlExt->context.control.csqSpinLock); InitializeListHead(&controlExt->context.control.lePendIrp); status = IoCsqInitialize(&controlExt->context.control.ioCsq, DkCsqInsertIrp, DkCsqRemoveIrp, DkCsqPeekNextIrp, DkCsqAcquireLock, DkCsqReleaseLock, DkCsqCompleteCanceledIrp); if (!NT_SUCCESS(status)) { DkDbgVal("Error initialize Cancel-safe queue!", status); goto End; } controlDevice->Flags &= ~DO_DEVICE_INITIALIZING; } else { KdPrint(("IoCreateDevice failed %x\n", status)); } End: if ((!NT_SUCCESS(status)) || (controlExt == NULL)) { if (controlDevice != NULL) { IoDeleteSymbolicLink(&symbolicLinkName); IoDeleteDevice(controlDevice); } } else { IoAcquireRemoveLock(controlExt->parentRemoveLock, NULL); *control = controlDevice; *busId = id; } return status; }
//////////////////////////////////////////////////////////////////////////// // Functions to attach and detach target device object // NTSTATUS DkCreateAndAttachTgt(PDEVICE_EXTENSION pParentDevExt, PDEVICE_OBJECT pTgtDevObj) { NTSTATUS ntStat = STATUS_SUCCESS; PDEVICE_OBJECT pDeviceObject = NULL; PDEVICE_EXTENSION pDevExt = NULL; // 1. Create filter object for target device object ntStat = IoCreateDevice(pParentDevExt->pDrvObj, sizeof(DEVICE_EXTENSION), NULL, pTgtDevObj->DeviceType, 0, FALSE, &pDeviceObject); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error create target device!", ntStat); return ntStat; } if (pDeviceObject == NULL) { DkDbgStr("IoCreateDevice() succeeded but pDeviceObject was not set."); return ntStat; } pDevExt = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension; pDevExt->deviceMagic = USBPCAP_MAGIC_DEVICE; pDevExt->pThisDevObj = pDeviceObject; pDevExt->parentRemoveLock = &pParentDevExt->removeLock; pDevExt->pDrvObj = pParentDevExt->pDrvObj; ntStat = USBPcapAllocateDeviceData(pDevExt, pParentDevExt); if (!NT_SUCCESS(ntStat)) { goto EndAttDev; } // 2. Initilize remove lock for filter object of target device IoInitializeRemoveLock(&pDevExt->removeLock, 0, 0, 0); // 3. Attach to target device pDevExt->pNextDevObj = NULL; pDevExt->pNextDevObj = IoAttachDeviceToDeviceStack(pDevExt->pThisDevObj, pTgtDevObj); if (pDevExt->pNextDevObj == NULL) { DkDbgStr("Error attach target device!"); ntStat = STATUS_NO_SUCH_DEVICE; goto EndAttDev; } // 4. Set up some filter device object flags pDevExt->pThisDevObj->Flags |= (pDevExt->pNextDevObj->Flags & (DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_DIRECT_IO)); pDevExt->pThisDevObj->Flags &= ~DO_DEVICE_INITIALIZING; IoAcquireRemoveLock(pDevExt->parentRemoveLock, NULL); EndAttDev: if (!NT_SUCCESS(ntStat)) { USBPcapFreeDeviceData(pDevExt); if (pDeviceObject) { IoDeleteDevice(pDeviceObject); pDeviceObject = NULL; } } return ntStat; }
NTSTATUS AddDevice(IN PDRIVER_OBJECT pDrvObj, IN PDEVICE_OBJECT pTgtDevObj) { NTSTATUS ntStat = STATUS_SUCCESS; UNICODE_STRING usTgtName; PDEVICE_OBJECT pHubFilter = NULL; PDEVICE_EXTENSION pDevExt = NULL; BOOLEAN isRootHub; // 1. Check if device is Root Hub isRootHub = USBPcapIsDeviceRootHub(pTgtDevObj); if (isRootHub == FALSE) { /* Do not attach to non-RootHub devices */ return STATUS_SUCCESS; } // 2. Create filter object ntStat = IoCreateDevice(pDrvObj, sizeof(DEVICE_EXTENSION), NULL, GetDeviceTypeToUse(pTgtDevObj), 0, FALSE, &pHubFilter); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error create Hub Filter!", ntStat); goto EndFunc; } pDevExt = (PDEVICE_EXTENSION) pHubFilter->DeviceExtension; pDevExt->deviceMagic = USBPCAP_MAGIC_ROOTHUB; pDevExt->pThisDevObj = pHubFilter; pDevExt->pDrvObj = pDrvObj; pDevExt->parentRemoveLock = NULL; IoInitializeRemoveLock(&pDevExt->removeLock, 0, 0, 0); ntStat = USBPcapAllocateDeviceData(pDevExt, NULL); if (!NT_SUCCESS(ntStat)) { goto EndFunc; } // 3. Attach to bus driver pDevExt->pNextDevObj = NULL; pDevExt->pNextDevObj = IoAttachDeviceToDeviceStack(pHubFilter, pTgtDevObj); if (pDevExt->pNextDevObj == NULL) { ntStat = STATUS_NO_SUCH_DEVICE; DkDbgStr("Error attach device!"); goto EndFunc; } pHubFilter->Flags |= (pDevExt->pNextDevObj->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE)); pHubFilter->Flags &= ~DO_DEVICE_INITIALIZING; if (NT_SUCCESS(ntStat)) { PDEVICE_OBJECT control = NULL; PUSBPCAP_ROOTHUB_DATA pRootData; USHORT id; ntStat = USBPcapCreateRootHubControlDevice(pDevExt, &control, &id); pRootData = pDevExt->context.usb.pDeviceData->pRootData; pRootData->controlDevice = control; pRootData->busId = id; } EndFunc: // If something bad happened if (!NT_SUCCESS(ntStat)) { USBPcapFreeDeviceData(pDevExt); if (pHubFilter) { IoDeleteDevice(pHubFilter); pHubFilter = NULL; } } return ntStat; }