NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pUsRegPath) { UCHAR ucCnt = 0; DkDbgStr("3"); pDrvObj->DriverUnload = DkUnload; pDrvObj->DriverExtension->AddDevice = AddDevice; for (ucCnt = 0; ucCnt < IRP_MJ_MAXIMUM_FUNCTION; ucCnt++) { pDrvObj->MajorFunction[ucCnt] = DkDefault; } pDrvObj->MajorFunction[IRP_MJ_CREATE] = pDrvObj->MajorFunction[IRP_MJ_CLEANUP] = pDrvObj->MajorFunction[IRP_MJ_CLOSE] = DkCreateClose; pDrvObj->MajorFunction[IRP_MJ_READ] = pDrvObj->MajorFunction[IRP_MJ_WRITE] = DkReadWrite; pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DkDevCtl; pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DkInDevCtl; pDrvObj->MajorFunction[IRP_MJ_PNP] = DkPnP; pDrvObj->MajorFunction[IRP_MJ_POWER] = DkPower; g_controlId = (ULONG)0; return STATUS_SUCCESS; }
/* * Writes data to buffer. * * Caller must have acquired buffer spin lock. */ static NTSTATUS USBPcapBufferWrite(PUSBPCAP_ROOTHUB_DATA pData, PVOID data, UINT32 length) { if (length == 0) { DkDbgStr("Cannot write empty data."); return STATUS_INVALID_PARAMETER; } if (USBPcapGetBufferFree(pData) < length) { DkDbgStr("No free space left."); return STATUS_INSUFFICIENT_RESOURCES; } USBPcapBufferWriteUnsafe(pData, data, length); return STATUS_SUCCESS; }
NTSTATUS USBPcapBufferWritePacket(PUSBPCAP_ROOTHUB_DATA pRootData, PUSBPCAP_BUFFER_PACKET_HEADER header, PVOID buffer) { UINT32 bytes; UINT32 bytesFree; KIRQL irql; NTSTATUS status; PDEVICE_EXTENSION pControlExt; PIRP pIrp = NULL; pcaprec_hdr_t pcapHeader; pControlExt = (PDEVICE_EXTENSION)pRootData->controlDevice->DeviceExtension; ASSERT(pControlExt->deviceMagic == USBPCAP_MAGIC_CONTROL); bytes = header->headerLen + header->dataLength; KeAcquireSpinLock(&pRootData->bufferLock, &irql); USBPcapInitializePcapHeader(pRootData, &pcapHeader, bytes); /* pcapHeader.incl_len contains the number of bytes to write */ bytes = pcapHeader.incl_len; status = STATUS_SUCCESS; bytesFree = USBPcapGetBufferFree(pRootData); if ((pRootData->buffer == NULL) || (bytesFree < sizeof(pcaprec_hdr_t)) || ((bytesFree - sizeof(pcaprec_hdr_t)) < bytes)) { DkDbgStr("No enough free space left."); status = STATUS_INSUFFICIENT_RESOURCES; } else { UINT32 tmp; /* Write Packet Header */ USBPcapBufferWriteUnsafe(pRootData, (PVOID) &pcapHeader, (UINT32) sizeof(pcaprec_hdr_t)); /* Write USBPCAP_BUFFER_PACKET_HEADER */ tmp = min(bytes, (UINT32)header->headerLen); if (tmp > 0) { USBPcapBufferWriteUnsafe(pRootData, (PVOID) header, tmp); } bytes -= tmp; if (bytes > 0 && header->dataLength > 0) { /* Write data */ tmp = min(bytes, header->dataLength); USBPcapBufferWriteUnsafe(pRootData, buffer, tmp); } } KeReleaseSpinLock(&pRootData->bufferLock, irql); if (NT_SUCCESS(status)) { pIrp = IoCsqRemoveNextIrp(&pControlExt->context.control.ioCsq, NULL); if (pIrp != NULL) { PVOID buffer; UINT32 bufferLength; UINT32 bytesRead; /* * Only IRPs with non-zero buffer are being queued. * * Since control device has DO_DIRECT_IO bit set the MDL is already * probed and locked */ buffer = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); if (buffer == NULL) { pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; bytes = 0; } else { UINT32 bufferLength = MmGetMdlByteCount(pIrp->MdlAddress); if (bufferLength != 0) { KeAcquireSpinLock(&pRootData->bufferLock, &irql); bytes = USBPcapBufferRead(pRootData, buffer, bufferLength); KeReleaseSpinLock(&pRootData->bufferLock, irql); } else { bytes = 0; } pIrp->IoStatus.Status = STATUS_SUCCESS; } pIrp->IoStatus.Information = (ULONG_PTR) bytes; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } } return status; }
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; }
VOID DkUnload(PDRIVER_OBJECT pDrvObj) { DkDbgStr("2"); }
//////////////////////////////////////////////////////////////////////////// // 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; }