diff --git a/reactos/drivers/ksfilter/directory.rbuild b/reactos/drivers/ksfilter/directory.rbuild index db069940a31..f74ff5d9226 100644 --- a/reactos/drivers/ksfilter/directory.rbuild +++ b/reactos/drivers/ksfilter/directory.rbuild @@ -4,8 +4,8 @@ - + diff --git a/reactos/drivers/ksfilter/ks/allocators.c b/reactos/drivers/ksfilter/ks/allocators.c index 5a4970f1b58..b3fbbbe20d5 100644 --- a/reactos/drivers/ksfilter/ks/allocators.c +++ b/reactos/drivers/ksfilter/ks/allocators.c @@ -163,7 +163,7 @@ IKsAllocator_fnDeviceIoControl( /* complete and forget irps */ Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NOT_IMPLEMENTED; } @@ -172,7 +172,7 @@ IKsAllocator_fnDeviceIoControl( { /* invalid request */ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } @@ -190,7 +190,7 @@ IKsAllocator_fnDeviceIoControl( Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE); /* complete and forget irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_BUFFER_TOO_SMALL; } if (!(Property->Flags & KSPROPERTY_TYPE_GET)) @@ -198,7 +198,7 @@ IKsAllocator_fnDeviceIoControl( /* only support retrieving the property */ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; /* complete and forget irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } @@ -212,7 +212,7 @@ IKsAllocator_fnDeviceIoControl( Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE); /* complete request */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } else if (Property->Id == KSPROPERTY_STREAMALLOCATOR_STATUS) @@ -223,7 +223,7 @@ IKsAllocator_fnDeviceIoControl( Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = sizeof(KSPROPERTY_STREAMALLOCATOR_STATUS); /* complete and forget irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_BUFFER_TOO_SMALL; } if (!(Property->Flags & KSPROPERTY_TYPE_GET)) @@ -231,7 +231,7 @@ IKsAllocator_fnDeviceIoControl( /* only support retrieving the property */ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; /* complete and forget irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } @@ -246,14 +246,14 @@ IKsAllocator_fnDeviceIoControl( Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_STATUS); /* complete request */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } } /* unhandled request */ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NOT_SUPPORTED; } @@ -501,7 +501,7 @@ IKsAllocator_DispatchDeviceIoControl( /* complete request */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -523,7 +523,7 @@ IKsAllocator_DispatchClose( /* complete request */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } diff --git a/reactos/drivers/ksfilter/ks/api.c b/reactos/drivers/ksfilter/ks/api.c index 64c341c20b3..3a037bfa168 100644 --- a/reactos/drivers/ksfilter/ks/api.c +++ b/reactos/drivers/ksfilter/ks/api.c @@ -1332,7 +1332,7 @@ KopDispatchClose( /* complete request */ Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } @@ -1416,7 +1416,7 @@ KopDispatchCreate( IoStack->FileObject->FsContext2 = (PVOID)Header; Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; @@ -1429,7 +1429,7 @@ cleanup: FreeItem(Header); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -1703,7 +1703,7 @@ KsCompletePendingRequest( if (IoStack->MajorFunction != IRP_MJ_CLOSE) { /* can be completed immediately */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return; } @@ -1711,7 +1711,7 @@ KsCompletePendingRequest( if (!NT_SUCCESS(Irp->IoStatus.Status)) { /* closing failed, complete irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return; } @@ -1723,136 +1723,8 @@ KsCompletePendingRequest( } -/* - @implemented -*/ -KSDDKAPI NTSTATUS NTAPI -KsCreateBusEnumObject( - IN PWCHAR BusIdentifier, - IN PDEVICE_OBJECT BusDeviceObject, - IN PDEVICE_OBJECT PhysicalDeviceObject, - IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL, - IN REFGUID InterfaceGuid OPTIONAL, - IN PWCHAR ServiceRelativePath OPTIONAL) -{ - ULONG Length; - NTSTATUS Status = STATUS_SUCCESS; - UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); - PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; - PDEVICE_EXTENSION DeviceExtension; - - /* calculate sizeof bus enum device extension */ - Length = wcslen(BusIdentifier) * sizeof(WCHAR); - Length += sizeof(BUS_ENUM_DEVICE_EXTENSION); - - BusDeviceExtension = AllocateItem(NonPagedPool, Length); - if (!BusDeviceExtension) - { - /* not enough memory */ - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* zero device extension */ - RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION)); - - /* initialize bus device extension */ - wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier); - - /* allocate service path string */ - Length = ServiceKeyPath.MaximumLength; - Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength; - - if (ServiceRelativePath) - { - /* relative path for devices */ - Length += wcslen(ServiceRelativePath) + 2 * sizeof(WCHAR); - } - - BusDeviceExtension->ServicePath.Length = 0; - BusDeviceExtension->ServicePath.MaximumLength = Length; - BusDeviceExtension->ServicePath.Buffer = AllocateItem(NonPagedPool, Length); - - if (!BusDeviceExtension->ServicePath.Buffer) - { - /* not enough memory */ - FreeItem(BusDeviceExtension); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath); - RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName); - - if (ServiceRelativePath) - { - RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\"); - RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath); - } - - if (InterfaceGuid) - { - /* register an device interface */ - Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->SymbolicLinkName); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - FreeItem(BusDeviceExtension->ServicePath.Buffer); - FreeItem(BusDeviceExtension); - return Status; - } - - /* now enable device interface */ - Status = IoSetDeviceInterfaceState(&BusDeviceExtension->SymbolicLinkName, TRUE); - - if (!NT_SUCCESS(Status)) - { - FreeItem(BusDeviceExtension->ServicePath.Buffer); - FreeItem(BusDeviceExtension); - return Status; - } - - /* set state enabled */ - BusDeviceExtension->Enabled = TRUE; - } - - /* store device objects */ - BusDeviceExtension->BusDeviceObject = BusDeviceObject; - BusDeviceExtension->PnpDeviceObject = PnpDeviceObject; - BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; - - if (!PnpDeviceObject) - { - BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject); - - if (!BusDeviceExtension->PnpDeviceObject) - { - /* failed to attach device */ - if (BusDeviceExtension->Enabled) - { - IoSetDeviceInterfaceState(&BusDeviceExtension->SymbolicLinkName, FALSE); - RtlFreeUnicodeString(&BusDeviceExtension->SymbolicLinkName); - } - - /* free device extension */ - FreeItem(BusDeviceExtension->ServicePath.Buffer); - FreeItem(BusDeviceExtension); - - return STATUS_DEVICE_REMOVED; - } - } - - /* attach device extension */ - DeviceExtension = (PDEVICE_EXTENSION)BusDeviceObject->DeviceExtension; - DeviceExtension->DeviceHeader = (PKSIDEVICE_HEADER)BusDeviceExtension; - - /* FIXME scan bus and invalidate device relations */ - return Status; -} - - NTSTATUS -NTAPI KspSetGetBusDataCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, @@ -1979,47 +1851,6 @@ KsDeviceRegisterAdapterObject( } -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsGetBusEnumIdentifier( - IN PIRP Irp) -{ - UNIMPLEMENTED - - return STATUS_UNSUCCESSFUL; -} - -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsGetBusEnumParentFDOFromChildPDO( - IN PDEVICE_OBJECT DeviceObject, - OUT PDEVICE_OBJECT *FunctionalDeviceObject) -{ - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; -} - -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsGetBusEnumPnpDeviceObject( - IN PDEVICE_OBJECT DeviceObject, - IN PDEVICE_OBJECT *PnpDeviceObject) -{ - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; -} /* @implemented @@ -2061,33 +1892,6 @@ KsGetNextSibling( return (PVOID)BasicHeader->Next.Pin; } -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsInstallBusEnumInterface( - PIRP Irp) -{ - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; -} - -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsIsBusEnumChildDevice( - IN PDEVICE_OBJECT DeviceObject, - OUT PBOOLEAN ChildDevice) -{ - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; -} - ULONG KspCountMethodSets( IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, @@ -2598,104 +2402,6 @@ cleanup: return STATUS_INSUFFICIENT_RESOURCES; } -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsServiceBusEnumCreateRequest( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) -{ - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; -} - - -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsServiceBusEnumPnpRequest( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) -{ - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; -} - -VOID -NTAPI -KspRemoveBusInterface( - PVOID Ctx) -{ - PKSREMOVE_BUS_INTERFACE_CTX Context =(PKSREMOVE_BUS_INTERFACE_CTX)Ctx; - - /* TODO - * get SWENUM_INSTALL_INTERFACE struct - * open device key and delete the keys - */ - - UNIMPLEMENTED - - /* set status */ - Context->Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - - - /* signal completion */ - KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE); -} - -/* - @unimplemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsRemoveBusEnumInterface( - IN PIRP Irp) -{ - KPROCESSOR_MODE Mode; - LUID luid; - KSREMOVE_BUS_INTERFACE_CTX Ctx; - WORK_QUEUE_ITEM WorkItem; - - /* get previous mode */ - Mode = ExGetPreviousMode(); - - /* convert to luid */ - luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); - - /* perform access check */ - if (!SeSinglePrivilegeCheck(luid, Mode)) - { - /* insufficient privileges */ - return STATUS_PRIVILEGE_NOT_HELD; - } - /* initialize event */ - KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE); - - /* store irp in ctx */ - Ctx.Irp = Irp; - - /* initialize work item */ - ExInitializeWorkItem(&WorkItem, KspRemoveBusInterface, (PVOID)&Ctx); - - /* now queue the work item */ - ExQueueWorkItem(&WorkItem, DelayedWorkQueue); - - /* wait for completion */ - KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL); - - /* return result */ - return Ctx.Irp->IoStatus.Status; - -} - - /* @unimplemented */ diff --git a/reactos/drivers/ksfilter/ks/clocks.c b/reactos/drivers/ksfilter/ks/clocks.c index 05064be740a..2e3f03f0b55 100644 --- a/reactos/drivers/ksfilter/ks/clocks.c +++ b/reactos/drivers/ksfilter/ks/clocks.c @@ -339,7 +339,7 @@ IKsClock_DispatchDeviceIoControl( Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } @@ -353,7 +353,7 @@ IKsClock_DispatchClose( UNIMPLEMENTED Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } diff --git a/reactos/drivers/ksfilter/ks/device.c b/reactos/drivers/ksfilter/ks/device.c index 432548c6d91..49d5787820e 100644 --- a/reactos/drivers/ksfilter/ks/device.c +++ b/reactos/drivers/ksfilter/ks/device.c @@ -282,8 +282,6 @@ IKsDevice_PnpStartDevice( NTSTATUS Status; PCM_RESOURCE_LIST TranslatedResourceList; PCM_RESOURCE_LIST UntranslatedResourceList; - PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor; - ULONG Index; /* get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -302,42 +300,14 @@ IKsDevice_PnpStartDevice( { DPRINT1("NextDevice object failed to start with %x\n", Status); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated; UntranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResources; - DPRINT("ResourceDescriptorCount %lu\n", TranslatedResourceList->List[0].PartialResourceList.Count); - for (Index = 0; Index < TranslatedResourceList->List[0].PartialResourceList.Count; Index ++ ) - { - PartialDescriptor = &TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index]; - UnPartialDescriptor = &UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index]; - DPRINT("Descriptor Type %u\n", PartialDescriptor->Type); - - if (PartialDescriptor->Type == CmResourceTypeInterrupt) - { - DPRINT("CmResourceTypeInterrupt Index %u TRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\n", Index, PartialDescriptor->u.Interrupt.Affinity, PartialDescriptor->u.Interrupt.Level, PartialDescriptor->u.Interrupt.Vector, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition); - DPRINT("CmResourceTypeInterrupt Index %u UNTRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\\n", Index, UnPartialDescriptor->u.Interrupt.Affinity, UnPartialDescriptor->u.Interrupt.Level, UnPartialDescriptor->u.Interrupt.Vector, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition); - - } - else if (PartialDescriptor->Type == CmResourceTypePort) - { - DPRINT("CmResourceTypePort Index %u TRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, PartialDescriptor->u.Port.Length, PartialDescriptor->u.Port.Start.HighPart, PartialDescriptor->u.Port.Start.LowPart, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition); - DPRINT("CmResourceTypePort Index %u UNTRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Port.Length, UnPartialDescriptor->u.Port.Start.HighPart, UnPartialDescriptor->u.Port.Start.LowPart, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition); - } - else if (PartialDescriptor->Type == CmResourceTypeMemory) - { - DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, PartialDescriptor->u.Memory.Start.LowPart, PartialDescriptor->u.Memory.Length, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition); - DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Memory.Start.LowPart, UnPartialDescriptor->u.Memory.Length, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition); - } - } - ASSERT(DeviceHeader->KsDevice.Descriptor); - ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch); - ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch->Start); - /* do we have a device descriptor */ if (DeviceHeader->KsDevice.Descriptor) @@ -361,7 +331,7 @@ IKsDevice_PnpStartDevice( { DPRINT1("Driver: failed to start %x\n", Status); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -406,12 +376,17 @@ IKsDevice_PnpStartDevice( Status = KspSetFilterFactoriesState(DeviceHeader, TRUE); } } + else + { + /* set state to run */ + DeviceHeader->KsDevice.Started = TRUE; + } } /* store result */ Irp->IoStatus.Status = Status; /* complete request */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); if (Ctx) { @@ -420,7 +395,7 @@ IKsDevice_PnpStartDevice( } /* return result */ - DPRINT1("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx); + DPRINT("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx); return Status; } @@ -477,7 +452,7 @@ IKsDevice_Pnp( { DPRINT1("Driver: query stop failed %x\n", Status); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -487,7 +462,7 @@ IKsDevice_Pnp( DPRINT("Next Device: Status %x\n", Status); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -513,7 +488,7 @@ IKsDevice_Pnp( Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } case IRP_MN_QUERY_INTERFACE: @@ -536,7 +511,7 @@ IKsDevice_Pnp( /* driver supports a private interface */ DPRINT1("IRP_MN_QUERY_INTERFACE Device supports interface\n"); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -545,7 +520,7 @@ IKsDevice_Pnp( DPRINT1("IRP_MN_QUERY_INTERFACE Next Device: Status %x\n", Status); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } case IRP_MN_QUERY_DEVICE_RELATIONS: @@ -556,7 +531,7 @@ IKsDevice_Pnp( DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS Next Device: Status %x\n", Status); //Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: @@ -567,7 +542,7 @@ IKsDevice_Pnp( DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status); //Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: @@ -578,7 +553,7 @@ IKsDevice_Pnp( DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } default: @@ -587,7 +562,7 @@ IKsDevice_Pnp( Status = KspForwardIrpSynchronous(DeviceObject, Irp); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } } @@ -604,7 +579,7 @@ IKsDevice_Power( Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } @@ -669,17 +644,10 @@ IKsDevice_Create( } } - /* acquire list lock */ + /* release list lock */ IKsDevice_fnReleaseDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown); - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Information = 0; - /* set return status */ - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - + /* done */ return Status; @@ -703,7 +671,7 @@ KsInitializeDevice( PKSIOBJECT_BAG Bag; NTSTATUS Status = STATUS_SUCCESS; - DPRINT("KsInitializeDevice Descriptor %p\n", Descriptor); + DPRINT1("KsInitializeDevice Descriptor %p\n", Descriptor); /* get device extension */ DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension; @@ -714,7 +682,7 @@ KsInitializeDevice( /* point to allocated header */ Header = DeviceExtension->DeviceHeader; - DPRINT("DeviceHeader %p\n", DeviceExtension->DeviceHeader); + DPRINT1("DeviceHeader %p\n", DeviceExtension->DeviceHeader); if (Descriptor && Descriptor->Dispatch) { @@ -896,7 +864,7 @@ KsDereferenceSoftwareBusObject( IKsDevice * Device; PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header; - DPRINT1("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header); + DPRINT("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header); /* get device interface */ Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown; diff --git a/reactos/drivers/ksfilter/ks/filter.c b/reactos/drivers/ksfilter/ks/filter.c index 5f4a74b9b64..1e6ebbf661e 100644 --- a/reactos/drivers/ksfilter/ks/filter.c +++ b/reactos/drivers/ksfilter/ks/filter.c @@ -16,6 +16,7 @@ typedef struct IKsControlVtbl *lpVtblKsControl; IKsFilterFactory * FilterFactory; + IKsProcessingObjectVtbl * lpVtblKsProcessingObject; LONG ref; PKSIOBJECT_HEADER ObjectHeader; @@ -25,6 +26,9 @@ typedef struct KMUTEX ControlMutex; KMUTEX ProcessingMutex; + PKSWORKER Worker; + WORK_QUEUE_ITEM WorkItem; + KSGATE Gate; PFNKSFILTERPOWER Sleep; PFNKSFILTERPOWER Wake; @@ -70,6 +74,196 @@ KSPROPERTY_SET FilterPropertySet[] = } }; +NTSTATUS +NTAPI +IKsProcessingObject_fnQueryInterface( + IKsProcessingObject * iface, + IN REFIID refiid, + OUT PVOID* Output) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + if (IsEqualGUIDAligned(refiid, &IID_IUnknown)) + { + *Output = &This->Header.OuterUnknown; + _InterlockedIncrement(&This->ref); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + +ULONG +NTAPI +IKsProcessingObject_fnAddRef( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + return InterlockedIncrement(&This->ref); +} + +ULONG +NTAPI +IKsProcessingObject_fnRelease( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + InterlockedDecrement(&This->ref); + + /* Return new reference count */ + return This->ref; +} + +VOID +NTAPI +IKsProcessingObject_fnProcessingObjectWork( + IKsProcessingObject * iface) +{ + NTSTATUS Status; + LARGE_INTEGER TimeOut; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + DPRINT1("processing object\n"); + /* first check if running at passive level */ + if (KeGetCurrentIrql() == PASSIVE_LEVEL) + { + /* acquire processing mutex */ + KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, NULL); + } + else + { + /* dispatch level processing */ + if (KeReadStateMutex(&This->ControlMutex) == 0) + { + /* some thread was faster */ + DPRINT1("processing object too slow\n"); + return; + } + + /* acquire processing mutex */ + TimeOut.QuadPart = 0LL; + Status = KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, &TimeOut); + + if (Status == STATUS_TIMEOUT) + { + /* some thread was faster */ + DPRINT1("processing object too slow\n"); + return; + } + } + + do + { + + /* check if the and-gate has been enabled again */ + if (&This->Gate.Count != 0) + { + /* gate is open */ + DPRINT1("processing object gate open\n"); + break; + } + + DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n"); + ASSERT(0); + + }while(TRUE); + + /* release process mutex */ + KeReleaseMutex(&This->ProcessingMutex, FALSE); +} + +PKSGATE +NTAPI +IKsProcessingObject_fnGetAndGate( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + /* return and gate */ + return &This->Gate; +} + +VOID +NTAPI +IKsProcessingObject_fnProcess( + IKsProcessingObject * iface, + IN BOOLEAN Asynchronous) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + /* should the action be asynchronous */ + if (Asynchronous) + { + /* queue work item */ + KsQueueWorkItem(This->Worker, &This->WorkItem); +DPRINT1("queueing\n"); + /* done */ + return; + } + + /* does the filter require explicit deferred processing */ + if ((This->Filter.Descriptor->Flags & (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING | KSFILTER_FLAG_CRITICAL_PROCESSING | KSFILTER_FLAG_HYPERCRITICAL_PROCESSING)) && + KeGetCurrentIrql() > PASSIVE_LEVEL) + { + /* queue work item */ + KsQueueWorkItem(This->Worker, &This->WorkItem); +DPRINT1("queueing\n"); + /* done */ + return; + } +DPRINT1("invoke\n"); + /* call worker routine directly */ + iface->lpVtbl->ProcessingObjectWork(iface); +} + +VOID +NTAPI +IKsProcessingObject_fnReset( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + /* acquire processing mutex */ + KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL); + + /* check if the filter supports dispatch routines */ + if (This->Filter.Descriptor->Dispatch) + { + /* has the filter a reset routine */ + if (This->Filter.Descriptor->Dispatch->Reset) + { + /* reset filter */ + This->Filter.Descriptor->Dispatch->Reset(&This->Filter); + } + } + + /* release process mutex */ + KeReleaseMutex(&This->ProcessingMutex, FALSE); +} + +VOID +NTAPI +IKsProcessingObject_fnTriggerNotification( + IKsProcessingObject * iface) +{ + +} + +static IKsProcessingObjectVtbl vt_IKsProcessingObject = +{ + IKsProcessingObject_fnQueryInterface, + IKsProcessingObject_fnAddRef, + IKsProcessingObject_fnRelease, + IKsProcessingObject_fnProcessingObjectWork, + IKsProcessingObject_fnGetAndGate, + IKsProcessingObject_fnProcess, + IKsProcessingObject_fnReset, + IKsProcessingObject_fnTriggerNotification +}; + + +//--------------------------------------------------------------------------------------------------------- NTSTATUS NTAPI IKsControl_fnQueryInterface( @@ -485,7 +679,7 @@ IKsFilter_GetFilterFromIrp( Irp->IoStatus.Status = Status; /* complete and forget irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } return Status; @@ -522,7 +716,7 @@ IKsFilter_DispatchClose( /* save the result */ Irp->IoStatus.Status = Status; /* complete irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); /* remove our instance from the filter factory */ IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory); @@ -535,7 +729,7 @@ IKsFilter_DispatchClose( /* complete and forget */ Irp->IoStatus.Status = Status; /* complete irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } /* done */ @@ -881,7 +1075,7 @@ IKsFilter_DispatchDeviceIoControl( if (Status != STATUS_PENDING) { Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } /* done */ @@ -1227,7 +1421,7 @@ IKsFilter_DispatchCreatePin( { /* complete request */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } /* done */ @@ -1243,7 +1437,7 @@ IKsFilter_DispatchCreateNode( { UNIMPLEMENTED Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } @@ -1356,6 +1550,20 @@ IKsFilter_RemoveFilterFromFilterFactory( }while(TRUE); } +VOID +NTAPI +IKsFilter_FilterCentricWorker( + IN PVOID Ctx) +{ + IKsProcessingObject * Object = (IKsProcessingObject*)Ctx; + + /* sanity check */ + ASSERT(Object); + + /* perform work */ + Object->lpVtbl->ProcessingObjectWork(Object); +} + NTSTATUS NTAPI KspCreateFilter( @@ -1377,17 +1585,27 @@ KspCreateFilter( /* get the filter factory */ Factory = iface->lpVtbl->GetStruct(iface); - if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create) + if (!Factory || !Factory->FilterDescriptor) { /* Sorry it just will not work */ return STATUS_UNSUCCESSFUL; } + if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS) + { + if (Irp->RequestorMode == UserMode) + { + /* filter not accessible from user mode */ + DPRINT1("Access denied\n"); + return STATUS_UNSUCCESSFUL; + } + } + /* allocate filter instance */ This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl)); if (!This) { - DPRINT("KspCreateFilter OutOfMemory\n"); + DPRINT1("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } @@ -1397,7 +1615,7 @@ KspCreateFilter( { /* no memory */ FreeItem(This); - DPRINT("KspCreateFilter OutOfMemory\n"); + DPRINT1("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown; @@ -1424,12 +1642,10 @@ KspCreateFilter( /* no memory */ FreeItem(This->Filter.Bag); FreeItem(This); - DPRINT("KspCreateFilter OutOfMemory\n"); + DPRINT1("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } - DPRINT("KspCreateFilter Flags %lx\n", Factory->FilterDescriptor->Flags); - /* initialize pin create item */ CreateItem[0].Create = IKsFilter_DispatchCreatePin; CreateItem[0].Context = (PVOID)This; @@ -1446,11 +1662,13 @@ KspCreateFilter( This->ref = 1; This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter; This->lpVtblKsControl = &vt_IKsControl; + This->lpVtblKsProcessingObject = &vt_IKsProcessingObject; This->Factory = Factory; This->FilterFactory = iface; This->FileObject = IoStack->FileObject; KeInitializeMutex(&This->ProcessingMutex, 0); + /* initialize basic header */ This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice; This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface); @@ -1460,17 +1678,39 @@ KspCreateFilter( InitializeListHead(&This->Header.EventList); KeInitializeSpinLock(&This->Header.EventListLock); + /* initialize and gate */ + KsGateInitializeAnd(&This->Gate, NULL); + + /* FIXME initialize and gate based on pin flags */ + + /* initialize work item */ + ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject); + + /* allocate counted work item */ + Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker); + if (!NT_SUCCESS(Status)) + { + /* what can go wrong, goes wrong */ + DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status); + FreeItem(This); + FreeItem(CreateItem); + return Status; + } + /* allocate the stream descriptors */ Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor); if (!NT_SUCCESS(Status)) { /* what can go wrong, goes wrong */ + DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status); + KsUnregisterWorker(This->Worker); FreeItem(This); FreeItem(CreateItem); - DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status); return Status; } + + /* does the filter have a filter dispatch */ if (Factory->FilterDescriptor->Dispatch) { @@ -1489,6 +1729,7 @@ KspCreateFilter( DPRINT1("Driver: Status %x\n", Status); /* free filter instance */ + KsUnregisterWorker(This->Worker); FreeItem(This); FreeItem(CreateItem); return Status; @@ -1515,7 +1756,7 @@ KspCreateFilter( IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory); /* completed initialization */ - DPRINT("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice); + DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice); return Status; } @@ -1599,7 +1840,7 @@ KsFilterAddTopologyConnections ( } /* - @unimplemented + @implemented */ KSDDKAPI VOID @@ -1608,7 +1849,20 @@ KsFilterAttemptProcessing( IN PKSFILTER Filter, IN BOOLEAN Asynchronous) { - UNIMPLEMENTED + PKSGATE Gate; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); + + /* get gate */ + Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject); + + if (!KsGateCaptureThreshold(Gate)) + { + /* filter control gate is closed */ + return; + } +DPRINT1("processing\n"); + /* try initiate processing */ + This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous); } /* @@ -1710,8 +1964,10 @@ NTAPI KsFilterGetAndGate( IN PKSFILTER Filter) { - UNIMPLEMENTED - return NULL; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); + + /* return and-gate */ + return &This->Gate; } /* diff --git a/reactos/drivers/ksfilter/ks/filterfactory.c b/reactos/drivers/ksfilter/ks/filterfactory.c index e60bfc41e81..51c9a65d273 100644 --- a/reactos/drivers/ksfilter/ks/filterfactory.c +++ b/reactos/drivers/ksfilter/ks/filterfactory.c @@ -69,7 +69,7 @@ IKsFilterFactory_Create( { Irp->IoStatus.Information = 0; Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } return Status; diff --git a/reactos/drivers/ksfilter/ks/irp.c b/reactos/drivers/ksfilter/ks/irp.c index fb36d6df78a..2fa100af098 100644 --- a/reactos/drivers/ksfilter/ks/irp.c +++ b/reactos/drivers/ksfilter/ks/irp.c @@ -34,7 +34,7 @@ KsDispatchQuerySecurity( { /* no create item */ Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_SECURITY_ON_OBJECT; } @@ -50,7 +50,7 @@ KsDispatchQuerySecurity( Irp->IoStatus.Status = Status; Irp->IoStatus.Information = Length; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -80,7 +80,7 @@ KsDispatchSetSecurity( { /* no create item */ Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_SECURITY_ON_OBJECT; } @@ -109,7 +109,7 @@ KsDispatchSetSecurity( /* store result */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -1154,7 +1154,7 @@ KsDispatchInvalidDeviceRequest( IN PIRP Irp) { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } @@ -1198,7 +1198,7 @@ KsDefaultDeviceIoCompletion( /* complete request */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; @@ -1643,14 +1643,15 @@ KsAddIrpToCancelableQueue( /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); - DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel); + DPRINT1("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel); // HACK for ms portcls if (IoStack->MajorFunction == IRP_MJ_CREATE) { // complete the request + DPRINT1("MS HACK\n"); Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return; } @@ -1736,7 +1737,7 @@ KsCancelRoutine( { /* let's complete it */ Irp->IoStatus.Status = STATUS_CANCELLED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } } @@ -1795,14 +1796,12 @@ FindMatchingCreateItem( continue; } - ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer); - DPRINT("CreateItem %S Length %u Request %wZ %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer, CreateItemEntry->CreateItem->ObjectClass.Length, &RefString, - BufferSize); + RefString.Length); - if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize) + if (CreateItemEntry->CreateItem->ObjectClass.Length > RefString.Length) { /* create item doesnt match in length */ Entry = Entry->Flink; @@ -1853,7 +1852,7 @@ KspCreate( Irp->IoStatus.Information = 0; /* set return status */ Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } @@ -1893,7 +1892,7 @@ KspCreate( Irp->IoStatus.Information = 0; /* set return status */ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } @@ -1929,7 +1928,7 @@ KspDispatchIrp( Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; /* complete and forget */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } @@ -2036,6 +2035,7 @@ KsDispatchIrp( /* get device extension */ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + /* get device header */ DeviceHeader = DeviceExtension->DeviceHeader; diff --git a/reactos/drivers/ksfilter/ks/ks.rbuild b/reactos/drivers/ksfilter/ks/ks.rbuild index 57ded213d3b..ffa517843bf 100644 --- a/reactos/drivers/ksfilter/ks/ks.rbuild +++ b/reactos/drivers/ksfilter/ks/ks.rbuild @@ -32,4 +32,5 @@ unknown.c worker.c kcom.c + swenum.c diff --git a/reactos/drivers/ksfilter/ks/ksfunc.h b/reactos/drivers/ksfilter/ks/ksfunc.h index 6a4d85df867..1c51a8c1c80 100644 --- a/reactos/drivers/ksfilter/ks/ksfunc.h +++ b/reactos/drivers/ksfilter/ks/ksfunc.h @@ -6,6 +6,13 @@ #define TAG_KSDEVICE 'DESK' #define TAG_KSOBJECT_TAG 'HOSK' +VOID +CompleteRequest( + PIRP Irp, + CCHAR PriorityBoost); + + + NTSTATUS NTAPI KspCreateObjectType( diff --git a/reactos/drivers/ksfilter/ks/ksiface.h b/reactos/drivers/ksfilter/ks/ksiface.h index ad95fc9a922..f5e388887ba 100644 --- a/reactos/drivers/ksfilter/ks/ksiface.h +++ b/reactos/drivers/ksfilter/ks/ksiface.h @@ -307,3 +307,34 @@ DECLARE_INTERFACE_(IKsDevice, IUnknown) STDMETHOD_(NTSTATUS, CheckIoCapability)(THIS_ IN ULONG Unknown)PURE; }; + +#undef INTERFACE + + +/***************************************************************************** + * IKsProcessingObject + ***************************************************************************** + */ + +#undef INTERFACE +#define INTERFACE IKsProcessingObject + +DECLARE_INTERFACE_(IKsProcessingObject, IUnknown) +{ + DEFINE_ABSTRACT_UNKNOWN() + + STDMETHOD_(VOID, ProcessingObjectWork)(THIS) PURE; + + STDMETHOD_(PKSGATE, GetAndGate)(THIS) PURE; + + STDMETHOD_(VOID, Process)(THIS_ + IN BOOLEAN Asynchronous)PURE; + + STDMETHOD_(VOID, Reset)(THIS) PURE; + + STDMETHOD_(VOID, TriggerNotification)(THIS) PURE; + +}; + +#undef INTERFACE + diff --git a/reactos/drivers/ksfilter/ks/kstypes.h b/reactos/drivers/ksfilter/ks/kstypes.h index 0e64312e095..0be5956264c 100644 --- a/reactos/drivers/ksfilter/ks/kstypes.h +++ b/reactos/drivers/ksfilter/ks/kstypes.h @@ -134,12 +134,6 @@ typedef struct PIO_WORKITEM WorkItem; }PNP_POSTSTART_CONTEXT, *PPNP_POSTSTART_CONTEXT; -typedef struct -{ - PIRP Irp; - KEVENT Event; -}KSREMOVE_BUS_INTERFACE_CTX, *PKSREMOVE_BUS_INTERFACE_CTX; - typedef struct { PLIST_ENTRY List; @@ -150,20 +144,97 @@ typedef struct typedef BOOLEAN (NTAPI *PKSEVENT_SYNCHRONIZED_ROUTINE)(PKSEVENT_CTX Context); +struct __BUS_ENUM_DEVICE_EXTENSION__; +struct __BUS_DEVICE_ENTRY__; + typedef struct { - BOOLEAN Enabled; + LIST_ENTRY Entry; + ULONG IsBus; + union + { + PDEVICE_OBJECT DeviceObject; + ULONG DeviceReferenceCount; + }; + union + { + struct __BUS_DEVICE_ENTRY__* DeviceEntry; + ULONG Dummy1; + }; + struct __BUS_ENUM_DEVICE_EXTENSION__ *BusDeviceExtension; + ULONG DeviceObjectReferenceCount; +}COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; - PDEVICE_OBJECT PnpDeviceObject; +typedef struct +{ + PCOMMON_DEVICE_EXTENSION Ext; +}DEV_EXTENSION, *PDEV_EXTENSION; + +typedef struct +{ + LIST_ENTRY Entry; + GUID InterfaceGuid; + UNICODE_STRING SymbolicLink; +}BUS_INSTANCE_ENTRY, *PBUS_INSTANCE_ENTRY; + + + +typedef enum +{ + NotStarted = 0, // Not started yet + Started, // Device has received the START_DEVICE IRP + StopPending, // Device has received the QUERY_STOP IRP + Stopped, // Device has received the STOP_DEVICE IRP + RemovePending, // Device has received the QUERY_REMOVE IRP + SurpriseRemovePending, // Device has received the SURPRISE_REMOVE IRP + Deleted +}DEVICE_STATE; + + +typedef struct __BUS_DEVICE_ENTRY__ +{ + LIST_ENTRY Entry; + LIST_ENTRY DeviceInterfaceList; + LIST_ENTRY IrpPendingList; + PDEVICE_OBJECT PDO; + DEVICE_STATE DeviceState; + GUID DeviceGuid; + LPWSTR PDODeviceName; + LPWSTR DeviceName; + LPWSTR BusId; + LARGE_INTEGER TimeCreated; + LARGE_INTEGER TimeExpired; + LPWSTR Instance; +}BUS_DEVICE_ENTRY, *PBUS_DEVICE_ENTRY; + +typedef struct __BUS_ENUM_DEVICE_EXTENSION__ +{ + COMMON_DEVICE_EXTENSION Common; + KSPIN_LOCK Lock; + KEVENT Event; + UNICODE_STRING DeviceInterfaceLink; PDEVICE_OBJECT PhysicalDeviceObject; + PDEVICE_OBJECT PnpDeviceObject; PDEVICE_OBJECT BusDeviceObject; - + ULONG PdoCreated; + KTIMER Timer; + KDPC Dpc; + WORK_QUEUE_ITEM WorkItem; + ULONG DeviceAttached; UNICODE_STRING ServicePath; - UNICODE_STRING SymbolicLinkName; WCHAR BusIdentifier[1]; }BUS_ENUM_DEVICE_EXTENSION, *PBUS_ENUM_DEVICE_EXTENSION; +typedef struct +{ + PIRP Irp; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + KEVENT Event; + NTSTATUS Status; + WORK_QUEUE_ITEM WorkItem; +}BUS_INSTALL_ENUM_CONTEXT, *PBUS_INSTALL_ENUM_CONTEXT; + typedef struct { PUCHAR FilterData; diff --git a/reactos/drivers/ksfilter/ks/misc.c b/reactos/drivers/ksfilter/ks/misc.c index 057103d3414..9ba4b2611b5 100644 --- a/reactos/drivers/ksfilter/ks/misc.c +++ b/reactos/drivers/ksfilter/ks/misc.c @@ -9,6 +9,19 @@ #include "priv.h" +VOID +CompleteRequest( + PIRP Irp, + CCHAR PriorityBoost) +{ + DPRINT("Completing IRP %p Status %x\n", Irp, Irp->IoStatus.Status); + + ASSERT(Irp->IoStatus.Status != STATUS_PENDING); + + + IoCompleteRequest(Irp, PriorityBoost); +} + PVOID AllocateItem( IN POOL_TYPE PoolType, diff --git a/reactos/drivers/ksfilter/ks/pin.c b/reactos/drivers/ksfilter/ks/pin.c index a6caeb30de0..883f098b43d 100644 --- a/reactos/drivers/ksfilter/ks/pin.c +++ b/reactos/drivers/ksfilter/ks/pin.c @@ -1875,7 +1875,7 @@ IKsPin_DispatchKsStream( DPRINT1("KsProbeStreamIrp failed with %x\n", Status); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -1888,7 +1888,7 @@ IKsPin_DispatchKsStream( { DPRINT("NoHeader Canceling Irp %p\n", Irp); Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -1911,7 +1911,7 @@ IKsPin_DispatchKsStream( { DPRINT("NoHeader->Data Canceling Irp %p\n", Irp); Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -1960,7 +1960,7 @@ IKsPin_DispatchKsStream( /* invalid device request */ DPRINT("Filter Centric Processing No Process Routine\n"); Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } @@ -2095,7 +2095,7 @@ IKsPin_DispatchDeviceIoControl( if (Status != STATUS_PENDING) { Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } /* done */ @@ -2135,7 +2135,7 @@ IKsPin_Close( { /* abort closing */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -2145,7 +2145,7 @@ IKsPin_Close( if (Status != STATUS_PENDING) { Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } } @@ -2162,7 +2162,7 @@ IKsPin_DispatchCreateAllocator( UNIMPLEMENTED; Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NOT_IMPLEMENTED; } @@ -2244,7 +2244,7 @@ IKsPin_DispatchCreateClock( /* done */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -2257,7 +2257,7 @@ IKsPin_DispatchCreateNode( UNIMPLEMENTED; Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NOT_IMPLEMENTED; } diff --git a/reactos/drivers/ksfilter/ks/priv.h b/reactos/drivers/ksfilter/ks/priv.h index 75b514158cc..8eb1959c288 100644 --- a/reactos/drivers/ksfilter/ks/priv.h +++ b/reactos/drivers/ksfilter/ks/priv.h @@ -19,6 +19,8 @@ #include "ksmedia.h" #include "bdamedia.h" +#include + #define TAG_DEVICE_HEADER 'KSDH' #define REG_PINFLAG_B_MANY 0x4 /* strmif.h */ diff --git a/reactos/drivers/ksfilter/ks/swenum.c b/reactos/drivers/ksfilter/ks/swenum.c new file mode 100644 index 00000000000..08d5286bd58 --- /dev/null +++ b/reactos/drivers/ksfilter/ks/swenum.c @@ -0,0 +1,2174 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel Streaming + * FILE: drivers/ksfilter/ks/swenum.c + * PURPOSE: KS Software BUS functions + * PROGRAMMER: Johannes Anderwald + */ + + +#include "priv.h" + +LONG KsDeviceCount = 0; + +typedef NTSTATUS (NTAPI *PKSP_BUS_ENUM_CALLBACK)( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DummyEntry, + IN LPWSTR RootName, + IN LPWSTR DirectoryName); + +NTSTATUS +KspCreatePDO( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry, + OUT PDEVICE_OBJECT * OutDeviceObject) +{ + PDEVICE_OBJECT DeviceObject; + WCHAR Buffer[50]; + ULONG CurDeviceId; + UNICODE_STRING DeviceName; + NTSTATUS Status; + PCOMMON_DEVICE_EXTENSION DeviceExtension; + + /* increment device count */ + CurDeviceId = InterlockedIncrement(&KsDeviceCount); + + /* generate new device id */ + swprintf(Buffer, L"\\Device\\KSENUM%08x", CurDeviceId); + + /* initialize new device name */ + RtlInitUnicodeString(&DeviceName, Buffer); + + /* create new device object */ + Status = IoCreateDevice(BusDeviceExtension->BusDeviceObject->DriverObject, sizeof(PVOID), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed to create pdo */ + return Status; + } + + /* now allocate device extension */ + DeviceExtension = (PCOMMON_DEVICE_EXTENSION)AllocateItem(NonPagedPool, sizeof(COMMON_DEVICE_EXTENSION)); + if (!DeviceExtension) + { + /* no memory */ + IoDeleteDevice(DeviceObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* store device extension */ + *((PVOID*)DeviceObject->DeviceExtension) = DeviceExtension; + + /* initialize device extension */ + DeviceExtension->IsBus = FALSE; + DeviceExtension->DeviceObject = DeviceObject; + DeviceExtension->DeviceEntry = DeviceEntry; + DeviceExtension->BusDeviceExtension = BusDeviceExtension; + + /* TODO: update last creation time in bus device extension */ + + /* setup flags */ + DeviceObject->Flags |= DO_POWER_PAGABLE; + DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; + /* TODO: fire time when expired */ + + *OutDeviceObject = DeviceObject; + + return STATUS_SUCCESS; +} + +NTSTATUS +KspRegisterDeviceAssociation( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry, + IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry) +{ + NTSTATUS Status; + UNICODE_STRING ReferenceString; + + /* initialize reference string */ + RtlInitUnicodeString(&ReferenceString, DeviceEntry->DeviceName); + + /* register device interface */ + Status = IoRegisterDeviceInterface(BusDeviceExtension->PhysicalDeviceObject, &BusInstanceEntry->InterfaceGuid, &ReferenceString, &BusInstanceEntry->SymbolicLink); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed */ + return Status; + } + + /* now enable the interface */ + Status = IoSetDeviceInterfaceState(&BusInstanceEntry->SymbolicLink, TRUE); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed, free memory */ + FreeItem(BusInstanceEntry->SymbolicLink.Buffer); + return Status; + } + + DPRINT1("Registered DeviceInterface %wZ\n", &BusInstanceEntry->SymbolicLink); + + + /* done */ + return Status; +} + +VOID +KspRemoveDeviceAssociations( + IN PBUS_DEVICE_ENTRY DeviceEntry) +{ + PLIST_ENTRY Entry; + PBUS_INSTANCE_ENTRY CurEntry; + + /* remove all entries */ + Entry = DeviceEntry->DeviceInterfaceList.Flink; + + while(Entry != &DeviceEntry->DeviceInterfaceList) + { + /* get offset */ + CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); + + /* sanity check */ + ASSERT(CurEntry->SymbolicLink.Buffer); + + /* de-register interface */ + IoSetDeviceInterfaceState(&CurEntry->SymbolicLink, FALSE); + + /* free symbolic link buffer */ + FreeItem(CurEntry->SymbolicLink.Buffer); + + /* remove entry from list */ + RemoveEntryList(Entry); + + /* move to next entry */ + Entry = Entry->Flink; + + /* free entry */ + FreeItem(CurEntry); + } +} + +NTSTATUS +KspEnumerateBusRegistryKeys( + IN HANDLE hKey, + IN LPWSTR ReferenceString, + IN PKSP_BUS_ENUM_CALLBACK Callback, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry) +{ + UNICODE_STRING String; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hNewKey; + NTSTATUS Status; + ULONG ResultLength, Index, KeyInfoLength; + KEY_FULL_INFORMATION KeyInformation; + PKEY_BASIC_INFORMATION KeyInfo; + + /* initialize key name */ + RtlInitUnicodeString(&String, ReferenceString); + + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &String, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); + + /* open new key */ + Status = ZwOpenKey(&hNewKey, GENERIC_READ, &ObjectAttributes); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed to open key */ + + return Status; + } + + /* query key stats */ + Status = ZwQueryKey(hNewKey, KeyFullInformation, &KeyInformation, sizeof(KeyInformation), &ResultLength); + + if (!NT_SUCCESS(Status)) + { + /* close key */ + ZwClose(hNewKey); + + /* done */ + return Status; + } + + /* calculate key info length */ + KeyInfoLength = KeyInformation.MaxNameLen + sizeof(KEY_BASIC_INFORMATION) + 1 * sizeof(WCHAR); + + /* allocate buffer */ + KeyInfo = (PKEY_BASIC_INFORMATION)AllocateItem(NonPagedPool, KeyInfoLength); + if (!KeyInfo) + { + + /* no memory */ + ZwClose(hNewKey); + + /* done */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* enumerate all keys */ + for(Index = 0; Index < KeyInformation.SubKeys; Index++) + { + + /* query sub key */ + Status = ZwEnumerateKey(hNewKey, Index, KeyBasicInformation, (PVOID)KeyInfo, KeyInfoLength, &ResultLength); + + /* check for success */ + if (NT_SUCCESS(Status)) + { + /* perform callback */ + Status = Callback(hNewKey, BusDeviceExtension, DeviceEntry, ReferenceString, KeyInfo->Name); + + /* should enumeration stop */ + if (!NT_SUCCESS(Status)) + break; + } + } + + /* free info buffer */ + FreeItem(KeyInfo); + + /* close key */ + ZwClose(hNewKey); + + /* done */ + return Status; +} + +NTSTATUS +NTAPI +KspCreateDeviceAssociation( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry, + IN LPWSTR ReferenceString, + IN LPWSTR InterfaceString) +{ + GUID DeviceGuid; + NTSTATUS Status; + PLIST_ENTRY Entry; + PBUS_INSTANCE_ENTRY CurEntry; + UNICODE_STRING DeviceName; + + /* initialize interface string */ + RtlInitUnicodeString(&DeviceName, InterfaceString); + + /* first convert device name to guid */ + RtlGUIDFromString(&DeviceName, &DeviceGuid); + + /* check if the device is already present */ + Entry = DeviceEntry->DeviceInterfaceList.Flink; + + while(Entry != &DeviceEntry->DeviceInterfaceList) + { + /* get offset */ + CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); + + if (IsEqualGUIDAligned(&CurEntry->InterfaceGuid, &DeviceGuid)) + { + /* entry already exists */ + return STATUS_SUCCESS; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* time to allocate new entry */ + CurEntry = (PBUS_INSTANCE_ENTRY)AllocateItem(NonPagedPool, sizeof(BUS_INSTANCE_ENTRY)); + + if (!CurEntry) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* store guid */ + RtlMoveMemory(&CurEntry->InterfaceGuid, &DeviceGuid, sizeof(GUID)); + + /* now register the association */ + Status = KspRegisterDeviceAssociation(BusDeviceExtension, DeviceEntry, CurEntry); + + /* check for success */ + if (NT_SUCCESS(Status)) + { + /* store entry */ + InsertTailList(&DeviceEntry->DeviceInterfaceList, &CurEntry->Entry); + } + else + { + /* failed to associated device */ + FreeItem(CurEntry); + } + + /* done */ + return Status; +} + +NTSTATUS +NTAPI +KspCreateDeviceReference( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DummyEntry, + IN LPWSTR DeviceCategory, + IN LPWSTR ReferenceString) +{ + LPWSTR DeviceName; + ULONG Length; + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */ + BOOLEAN ItemExists = FALSE; + UNICODE_STRING String; + NTSTATUS Status; + KIRQL OldLevel; + + /* first construct device name & reference guid */ + Length = wcslen(DeviceCategory) + wcslen(ReferenceString); + + /* append '&' and null byte */ + Length += 2; + + /* allocate device name */ + DeviceName = AllocateItem(NonPagedPool, Length * sizeof(WCHAR)); + + if (!DeviceName) + { + /* not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* construct device name */ + swprintf(DeviceName, L"%s&%s", DeviceCategory, ReferenceString); + + /* scan list and check if it is already present */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get real offset */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* check if name matches */ + if (!wcsicmp(DeviceEntry->DeviceName, DeviceName)) + { + /* item already exists */ + ItemExists = TRUE; + break; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + if (!ItemExists) + { + /* allocate new device entry */ + DeviceEntry = AllocateItem(NonPagedPool, sizeof(BUS_DEVICE_ENTRY)); + if (!DeviceEntry) + { + /* no memory */ + FreeItem(DeviceName); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* initialize device entry */ + InitializeListHead(&DeviceEntry->DeviceInterfaceList); + InitializeListHead(&DeviceEntry->IrpPendingList); + + /* copy device guid */ + RtlInitUnicodeString(&String, ReferenceString); + RtlGUIDFromString(&String, &DeviceEntry->DeviceGuid); + + /* copy device names */ + DeviceEntry->DeviceName = DeviceName; + DeviceEntry->Instance = (DeviceName + wcslen(DeviceCategory) + 1); + + /* copy name */ + DeviceEntry->BusId = AllocateItem(NonPagedPool, (wcslen(DeviceCategory) + 1) * sizeof(WCHAR)); + if (!DeviceEntry->BusId) + { + /* no memory */ + FreeItem(DeviceName); + FreeItem(DeviceEntry); + return STATUS_INSUFFICIENT_RESOURCES; + } + wcscpy(DeviceEntry->BusId, DeviceCategory); + } + + /* now enumerate the devices */ + Status = KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceAssociation, BusDeviceExtension, DeviceEntry); + + /* check if list is empty */ + if (IsListEmpty(&DeviceEntry->DeviceInterfaceList)) + { + /* invalid device settings */ + FreeItem(DeviceEntry->BusId); + FreeItem(DeviceEntry->DeviceName); + FreeItem(DeviceEntry); + + ASSERT(ItemExists == FALSE); + + return STATUS_INVALID_DEVICE_STATE; + } + + /* check if enumeration failed */ + if (!NT_SUCCESS(Status)) + { + /* failed */ + KspRemoveDeviceAssociations(DeviceEntry); + FreeItem(DeviceEntry->BusId); + FreeItem(DeviceEntry->DeviceName); + FreeItem(DeviceEntry); + + ASSERT(ItemExists == FALSE); + + /* done */ + return Status; + } + + if (!ItemExists) + { + /* acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* successfully initialized entry */ + InsertTailList(&BusDeviceExtension->Common.Entry, &DeviceEntry->Entry); + + /* release lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + } + + /* done */ + return Status; +} + +NTSTATUS +NTAPI +KspCreateDeviceReferenceTrampoline( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DummyEntry, + IN LPWSTR DeviceCategory, + IN LPWSTR ReferenceString) +{ + return KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceReference, BusDeviceExtension, DummyEntry); +} + + +NTSTATUS +KspOpenBusRegistryKey( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + OUT PHANDLE hKey) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &BusDeviceExtension->ServicePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + return ZwCreateKey(hKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); +} + +NTSTATUS +KspScanBus( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension) +{ + HANDLE hKey; + NTSTATUS Status; + + /* first open key */ + Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* no success */ + + return Status; + } + + /* TODO clear reference marks */ + + /* construct device entries */ + Status = KspEnumerateBusRegistryKeys(hKey, NULL, KspCreateDeviceReferenceTrampoline, BusDeviceExtension, NULL); + + /* TODO: delete unreferenced devices */ + + /* close handle */ + ZwClose(hKey); + + /* done */ + return Status; +} + + +NTSTATUS +NTAPI +KspBusQueryReferenceString( + IN PVOID Context, + IN OUT PWCHAR *String) +{ + LPWSTR Name; + ULONG Length; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context; + + /* sanity checks */ + ASSERT(BusDeviceExtension); + ASSERT(BusDeviceExtension->BusIdentifier); + + /* calculate length */ + Length = wcslen(BusDeviceExtension->BusIdentifier) + 1; + + /* allocate buffer */ + Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); + + if (!Name) + { + /* failed to allocate buffer */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy buffer */ + wcscpy(Name, BusDeviceExtension->BusIdentifier); + + /* store result */ + *String = Name; + + /* done */ + return STATUS_SUCCESS; +} + +VOID +NTAPI +KspBusDeviceReference( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); +} + +VOID +NTAPI +KspBusDeviceDereference( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); +} + +VOID +NTAPI +KspBusReferenceDeviceObject( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); +} + +VOID +NTAPI +KspBusDereferenceDeviceObject( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); +} + +NTSTATUS +KspQueryBusDeviceInterface( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PBUS_INTERFACE_SWENUM Interface; + PIO_STACK_LOCATION IoStack; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(IoStack->Parameters.QueryInterface.Size == sizeof(BUS_INTERFACE_SWENUM)); + ASSERT(IoStack->Parameters.QueryInterface.Interface); + + /* fill in interface */ + Interface = (PBUS_INTERFACE_SWENUM)IoStack->Parameters.QueryInterface.Interface; + Interface->Interface.Size = sizeof(BUS_INTERFACE_SWENUM); + Interface->Interface.Version = BUS_INTERFACE_SWENUM_VERSION; + Interface->Interface.Context = ChildDeviceExtension; + Interface->Interface.InterfaceReference = KspBusDeviceReference; + Interface->Interface.InterfaceDereference = KspBusDeviceDereference; + Interface->ReferenceDeviceObject = KspBusReferenceDeviceObject; + Interface->DereferenceDeviceObject = KspBusDereferenceDeviceObject; + Interface->QueryReferenceString = KspBusQueryReferenceString; + + return STATUS_SUCCESS; +} + +NTSTATUS +KspEnableBusDeviceInterface( + PBUS_DEVICE_ENTRY DeviceEntry, + BOOLEAN bEnable) +{ + PLIST_ENTRY Entry; + PBUS_INSTANCE_ENTRY InstanceEntry; + NTSTATUS Status = STATUS_SUCCESS; + + /* enable now all interfaces */ + Entry = DeviceEntry->DeviceInterfaceList.Flink; + + while(Entry != &DeviceEntry->DeviceInterfaceList) + { + /* get bus instance entry */ + InstanceEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); + DPRINT1("Enabling %u %wZ Irql %u\n", bEnable, &InstanceEntry->SymbolicLink, KeGetCurrentIrql()); + + /* set interface state */ + Status = IoSetDeviceInterfaceState(&InstanceEntry->SymbolicLink, bEnable); + + if (!NT_SUCCESS(Status)) + { + /* failed to set interface */ + break; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* done */ + return Status; +} + +NTSTATUS +KspDoReparseForIrp( + PIRP Irp, + PBUS_DEVICE_ENTRY DeviceEntry) +{ + ULONG Length; + LPWSTR Buffer; + PIO_STACK_LOCATION IoStack; + + /* get stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(DeviceEntry->PDODeviceName); + ASSERT(DeviceEntry->Instance); + ASSERT(IoStack->FileObject); + ASSERT(IoStack->FileObject->FileName.Buffer); + + /* calculate length */ + Length = wcslen(DeviceEntry->PDODeviceName); + Length += wcslen(DeviceEntry->Instance); + + /* zero byte and '\\' */ + Length += 2; + + /* allocate buffer */ + Buffer = AllocateItem(NonPagedPool, Length * sizeof(WCHAR)); + if (!Buffer) + { + /* no resources */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* construct buffer */ + swprintf(Buffer, L"%s\\%s", DeviceEntry->PDODeviceName, DeviceEntry->Instance); + + ExFreePool(IoStack->FileObject->FileName.Buffer); + + /* store new file name */ + RtlInitUnicodeString(&IoStack->FileObject->FileName, Buffer); + + /* done */ + return STATUS_REPARSE; +} + +VOID +KspCompletePendingIrps( + IN PBUS_DEVICE_ENTRY DeviceEntry, + IN OUT NTSTATUS ResultCode) +{ + PLIST_ENTRY Entry; + PIRP Irp; + NTSTATUS Status; + + /* go through list */ + while(!IsListEmpty(&DeviceEntry->IrpPendingList)) + { + /* get first entry */ + Entry = RemoveHeadList(&DeviceEntry->IrpPendingList); + + /* get irp */ + Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); + + if (ResultCode == STATUS_REPARSE) + { + /* construct reparse information */ + Status = KspDoReparseForIrp(Irp, DeviceEntry); + } + else + { + /* use default code */ + Status = ResultCode; + } + + /* store result code */ + Irp->IoStatus.Status = Status; + + DPRINT1("Completing IRP %p Status %x\n", Irp, Status); + + /* complete the request */ + CompleteRequest(Irp, IO_NO_INCREMENT); + } + +} + + + +NTSTATUS +KspStartBusDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + WCHAR PDOName[256]; + NTSTATUS Status; + ULONG ResultLength; + LPWSTR Name; + PBUS_DEVICE_ENTRY DeviceEntry; + + /* FIXME handle pending remove */ + + /* get full device name */ + Status = IoGetDeviceProperty(DeviceObject, DevicePropertyPhysicalDeviceObjectName, sizeof(PDOName), (PVOID)PDOName, &ResultLength); + + if (!NT_SUCCESS(Status)) + { + /* failed to get device name */ + return Status; + } + + /* allocate device name buffer */ + Name = AllocateItem(NonPagedPool, (ResultLength + 1) * sizeof(WCHAR)); + if (!Name) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy name */ + wcscpy(Name, PDOName); + + /* TODO: time stamp creation time */ + + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)ChildDeviceExtension->DeviceEntry; + + /* sanity check */ + ASSERT(DeviceEntry); + + /* store device name */ + DeviceEntry->PDODeviceName = Name; + + /* mark device as started */ + DeviceEntry->DeviceState = Started; + + /* reference start time */ + KeQuerySystemTime(&DeviceEntry->TimeCreated); + + DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name, DeviceEntry->DeviceName, DeviceEntry->Instance); + + /* enable device classes */ + //KspEnableBusDeviceInterface(DeviceEntry, TRUE); + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryBusDeviceCapabilities( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PDEVICE_CAPABILITIES Capabilities; + PIO_STACK_LOCATION IoStack; + + /* get stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* get capabilities */ + Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; + + RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES)); + + /* setup capabilities */ + Capabilities->UniqueID = TRUE; + Capabilities->SilentInstall = TRUE; + Capabilities->SurpriseRemovalOK = TRUE; + Capabilities->Address = 0; + Capabilities->UINumber = 0; + Capabilities->SystemWake = PowerSystemWorking; /* FIXME common device extension */ + Capabilities->DeviceWake = PowerDeviceD0; + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryBusInformation( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PPNP_BUS_INFORMATION BusInformation; + + /* allocate bus information */ + BusInformation = (PPNP_BUS_INFORMATION)AllocateItem(PagedPool, sizeof(PNP_BUS_INFORMATION)); + + if (!BusInformation) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* return info */ + BusInformation->BusNumber = 0; + BusInformation->LegacyBusType = InterfaceTypeUndefined; + RtlMoveMemory(&BusInformation->BusTypeGuid, &KSMEDIUMSETID_Standard, sizeof(GUID)); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)BusInformation; + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryBusDevicePnpState( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + /* set device flags */ + Irp->IoStatus.Information = PNP_DEVICE_DONT_DISPLAY_IN_UI | PNP_DEVICE_NOT_DISABLEABLE; + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryId( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PBUS_DEVICE_ENTRY DeviceEntry; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + LPWSTR Name; + ULONG Length; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID) + { + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; + + /* sanity check */ + ASSERT(DeviceEntry); + ASSERT(DeviceEntry->Instance); + + /* calculate length */ + Length = wcslen(DeviceEntry->Instance) + 1; + + /* allocate buffer */ + Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); + + if (!Name) + { + /* failed to allocate buffer */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy buffer */ + wcscpy(Name, DeviceEntry->Instance); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)Name; + + /* done */ + return STATUS_SUCCESS; + } + else if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID || + IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) + { + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION) ChildDeviceExtension->BusDeviceExtension; + + /* sanity check */ + ASSERT(DeviceEntry); + ASSERT(DeviceEntry->BusId); + ASSERT(BusDeviceExtension); + ASSERT(BusDeviceExtension->BusIdentifier); + + /* calculate length */ + Length = wcslen(BusDeviceExtension->BusIdentifier); + Length += wcslen(DeviceEntry->BusId); + + /* extra length for '\\' and zero byte */ + Length += 2; + + /* allocate buffer */ + Name = ExAllocatePool(PagedPool, Length * sizeof(WCHAR)); + if (!Name) + { + /* failed to allocate buffer */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* construct id */ + swprintf(Name, L"%s\\%s", BusDeviceExtension->BusIdentifier, DeviceEntry->BusId); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)Name; + + /* done */ + return STATUS_SUCCESS; + } + else + { + /* other ids are not supported */ + //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType); + return Irp->IoStatus.Status; + } +} + +NTSTATUS +KspInstallInterface( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PSWENUM_INSTALL_INTERFACE InstallInterface) +{ + ULONG Length, Index; + UNICODE_STRING DeviceString, InterfaceString, ReferenceString; + HANDLE hKey, hDeviceKey, hInterfaceKey, hReferenceKey; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + + /* sanity check */ + ASSERT(InstallInterface); + + /* calculate length */ + Length = wcslen(InstallInterface->ReferenceString); + + /* check for invalid characters */ + for(Index = 0; Index < Length; Index++) + { + if (InstallInterface->ReferenceString[Index] <= L' ' || + InstallInterface->ReferenceString[Index] > L'~' || + InstallInterface->ReferenceString[Index] == L',' || + InstallInterface->ReferenceString[Index] == L'\\' || + InstallInterface->ReferenceString[Index] == L'/') + { + /* invalid character */ + return STATUS_INVALID_PARAMETER; + } + } + + /* open bus key */ + Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); + if (NT_SUCCESS(Status)) + { + /* convert device guid to string */ + Status = RtlStringFromGUID(&InstallInterface->DeviceId, &DeviceString); + if (NT_SUCCESS(Status)) + { + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &DeviceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); + + /* construct device key */ + Status = ZwCreateKey(&hDeviceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + /* initialize reference string */ + RtlInitUnicodeString(&ReferenceString, InstallInterface->ReferenceString); + + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &ReferenceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceKey, NULL); + + /* construct device key */ + Status = ZwCreateKey(&hReferenceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + /* convert interface guid to string */ + Status = RtlStringFromGUID(&InstallInterface->InterfaceId, &InterfaceString); + if (NT_SUCCESS(Status)) + { + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &InterfaceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hReferenceKey, NULL); + + /* construct device key */ + Status = ZwCreateKey(&hInterfaceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + /* close key */ + ZwClose(hInterfaceKey); + } + /* free interface string */ + RtlFreeUnicodeString(&InterfaceString); + } + /* close reference key */ + ZwClose(hReferenceKey); + } + /* close device key */ + ZwClose(hDeviceKey); + } + /* free device string */ + RtlFreeUnicodeString(&DeviceString); + } + /* close bus key */ + ZwClose(hKey); + } + + /* done */ + return Status; + } + +VOID +NTAPI +KspInstallBusEnumInterface( + IN PVOID Ctx) +{ + PIO_STACK_LOCATION IoStack; + NTSTATUS Status; + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry; + PSWENUM_INSTALL_INTERFACE InstallInterface; + KIRQL OldLevel; + PBUS_INSTALL_ENUM_CONTEXT Context = (PBUS_INSTALL_ENUM_CONTEXT)Ctx; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Context->Irp); + + /* get install request */ + InstallInterface = (PSWENUM_INSTALL_INTERFACE)Context->Irp->AssociatedIrp.SystemBuffer; + + /* sanity check */ + ASSERT(InstallInterface); + ASSERT(Context->BusDeviceExtension); + + if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SWENUM_INSTALL_INTERFACE)) + { + /* buffer too small */ + Context->Status = STATUS_INVALID_PARAMETER; + + /* signal completion */ + KeSetEvent(&Context->Event, 0, FALSE); + + /* done */ + return; + } + + /* FIXME locks */ + + /* now install the interface */ + Status = KspInstallInterface(Context->BusDeviceExtension, InstallInterface); + if (!NT_SUCCESS(Status)) + { + /* failed to install interface */ + Context->Status = Status; + + /* signal completion */ + KeSetEvent(&Context->Event, 0, FALSE); + + /* done */ + return; + } + + /* acquire device entry lock */ + KeAcquireSpinLock(&Context->BusDeviceExtension->Lock, &OldLevel); + + /* now iterate all device entries */ + Entry = Context->BusDeviceExtension->Common.Entry.Flink; + while(Entry != &Context->BusDeviceExtension->Common.Entry) + { + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + if (IsEqualGUIDAligned(&DeviceEntry->DeviceGuid, &InstallInterface->DeviceId) && + !wcsicmp(DeviceEntry->Instance, InstallInterface->ReferenceString)) + { + if (!DeviceEntry->PDO) + { + /* create pdo */ + Status = KspCreatePDO(Context->BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); + + /* done */ + break; + } + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* release device entry lock */ + KeReleaseSpinLock(&Context->BusDeviceExtension->Lock, OldLevel); + + /* signal that bus driver relations has changed */ + IoInvalidateDeviceRelations(Context->BusDeviceExtension->PhysicalDeviceObject, BusRelations); + + /* update status */ + Context->Status = Status; + + /* signal completion */ + KeSetEvent(&Context->Event, 0, FALSE); +} + + +VOID +NTAPI +KspBusWorkerRoutine( + IN PVOID Parameter) +{ + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PBUS_DEVICE_ENTRY DeviceEntry; + PLIST_ENTRY Entry; + LARGE_INTEGER Time, Diff; + BOOLEAN DoInvalidate = FALSE; + KIRQL OldLevel; + + /* acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* get device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Parameter; + + /* get current time */ + KeQuerySystemTime(&Time); + + /* enumerate all device entries */ + Entry = BusDeviceExtension->Common.Entry.Flink; + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get offset to device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* sanity check */ + ASSERT(DeviceEntry); + + //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState); + + if (DeviceEntry->PDO) + { + if (DeviceEntry->DeviceState == NotStarted) + { + Diff.QuadPart = Time.QuadPart - DeviceEntry->TimeCreated.QuadPart; + + if (Diff.QuadPart > Int32x32To64(15000, 10000)) + { + DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry->DeviceName, DeviceEntry->Instance, DeviceEntry->TimeCreated.QuadPart, Time.QuadPart, Diff.QuadPart); + + /* release spin lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + + /* deactivate interfaces */ + //KspEnableBusDeviceInterface(DeviceEntry, FALSE); + + /* re-acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* pending remove device object */ + DeviceEntry->DeviceState = StopPending; + + /* perform invalidation */ + DoInvalidate = TRUE; + } + } + else if (DeviceEntry->DeviceState == Started) + { + /* found pending irps */ + KspCompletePendingIrps(DeviceEntry, STATUS_REPARSE); + } + } + + + /* move to next */ + Entry = Entry->Flink; + } + + /* release lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + + if (DoInvalidate) + { + /* invalidate device relations */ + IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); + } + + Time.QuadPart = Int32x32To64(5000, -10000); + KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); +} + +VOID +NTAPI +KspBusDpcRoutine( + IN PKDPC Dpc, + IN PVOID DeferredContext OPTIONAL, + IN PVOID SystemArgument1 OPTIONAL, + IN PVOID SystemArgument2 OPTIONAL) +{ + /* get device extension */ + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeferredContext; + + /* queue the item */ + ExQueueWorkItem(&BusDeviceExtension->WorkItem, DelayedWorkQueue); +} + +VOID +NTAPI +KspRemoveBusInterface( + PVOID Ctx) +{ + PBUS_INSTALL_ENUM_CONTEXT Context =(PBUS_INSTALL_ENUM_CONTEXT)Ctx; + + /* TODO + * get SWENUM_INSTALL_INTERFACE struct + * open device key and delete the keys + */ + + UNIMPLEMENTED + + /* set status */ + Context->Status = STATUS_NOT_IMPLEMENTED; + + + /* signal completion */ + KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE); +} + +NTSTATUS +KspQueryBusRelations( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PIRP Irp) +{ + PDEVICE_RELATIONS DeviceRelations; + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry; + ULONG Count = 0, Length; + KIRQL OldLevel; + + /* acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* first scan all device entries */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get offset to device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* is there a pdo yet */ + if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) + { + /* increment count */ + Count++; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* calculate length */ + Length = sizeof(DEVICE_RELATIONS) + (Count > 1 ? sizeof(PDEVICE_OBJECT) * (Count-1) : 0); + + /* allocate device relations */ + DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(NonPagedPool, Length); + + if (!DeviceRelations) + { + /* not enough memory */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* rescan device entries */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get offset to device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* is there a pdo yet */ + if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) + { + /* store pdo */ + DeviceRelations->Objects[DeviceRelations->Count] = DeviceEntry->PDO; + + /* reference device object */ + ObReferenceObject(DeviceEntry->PDO); + + /* increment pdo count */ + DeviceRelations->Count++; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* release lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + + /* FIXME handle existing device relations */ + ASSERT(Irp->IoStatus.Information == 0); + + /* store device relations */ + Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; + + /* done */ + return STATUS_SUCCESS; +} + +//------------------------------------------------------------------------------------ + +/* + @implemented +*/ + +KSDDKAPI +NTSTATUS +NTAPI +KsGetBusEnumIdentifier( + IN PIRP Irp) +{ + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PIO_STACK_LOCATION IoStack; + ULONG Length; + NTSTATUS Status; + LPWSTR Buffer; + + DPRINT1("KsGetBusEnumIdentifier\n"); + + /* get stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(IoStack->DeviceObject); + ASSERT(IoStack->DeviceObject->DeviceExtension); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + /* sanity checks */ + ASSERT(BusDeviceExtension); + ASSERT(BusDeviceExtension->Common.IsBus); + + if (!BusDeviceExtension) + { + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; + } + + /* get length */ + Length = (wcslen(BusDeviceExtension->BusIdentifier)+1) * sizeof(WCHAR); + + /* is there an output buffer provided */ + if (IoStack->Parameters.DeviceIoControl.InputBufferLength) + { + if (Length > IoStack->Parameters.DeviceIoControl.InputBufferLength) + { + /* buffer is too small */ + return STATUS_BUFFER_TOO_SMALL; + } + + /* now allocate buffer */ + Buffer = AllocateItem(NonPagedPool, Length); + if (!Buffer) + { + /* no memory */ + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + /* copy bus identifier */ + wcscpy(Buffer, BusDeviceExtension->BusIdentifier); + + /* store buffer */ + Irp->AssociatedIrp.SystemBuffer = Buffer; + + /* set flag that buffer gets copied back */ + Irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION; + + /* done */ + Status = STATUS_SUCCESS; + } + } + else + { + /* no buffer provided */ + Status = STATUS_BUFFER_OVERFLOW; + } + + /* done */ + Irp->IoStatus.Status = Status; + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsGetBusEnumParentFDOFromChildPDO( + IN PDEVICE_OBJECT DeviceObject, + OUT PDEVICE_OBJECT *FunctionalDeviceObject) +{ + PDEV_EXTENSION DeviceExtension; + + DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n"); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* check if this is child pdo */ + if (DeviceExtension->Ext->IsBus == FALSE) + { + /* return bus device object */ + *FunctionalDeviceObject = DeviceExtension->Ext->BusDeviceExtension->BusDeviceObject; + + /* done */ + return STATUS_SUCCESS; + } + + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; +} + + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsCreateBusEnumObject( + IN PWCHAR BusIdentifier, + IN PDEVICE_OBJECT BusDeviceObject, + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL, + IN REFGUID InterfaceGuid OPTIONAL, + IN PWCHAR ServiceRelativePath OPTIONAL) +{ + ULONG Length; + NTSTATUS Status = STATUS_SUCCESS; + UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PDEV_EXTENSION DeviceExtension; + + DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath, BusDeviceObject); + + /* calculate sizeof bus enum device extension */ + Length = wcslen(BusIdentifier) * sizeof(WCHAR); + Length += sizeof(BUS_ENUM_DEVICE_EXTENSION); + + BusDeviceExtension = AllocateItem(NonPagedPool, Length); + if (!BusDeviceExtension) + { + /* not enough memory */ + + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)BusDeviceObject->DeviceExtension; + + DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); + + /* store bus device extension */ + DeviceExtension->Ext = (PCOMMON_DEVICE_EXTENSION)BusDeviceExtension; + + DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); + + + /* zero device extension */ + RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION)); + + /* initialize bus device extension */ + wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier); + + /* allocate service path string */ + Length = ServiceKeyPath.MaximumLength; + Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength; + + if (ServiceRelativePath) + { + /* relative path for devices */ + Length += (wcslen(ServiceRelativePath) + 2) * sizeof(WCHAR); + } + + BusDeviceExtension->ServicePath.Length = 0; + BusDeviceExtension->ServicePath.MaximumLength = Length; + BusDeviceExtension->ServicePath.Buffer = AllocateItem(NonPagedPool, Length); + + if (!BusDeviceExtension->ServicePath.Buffer) + { + /* not enough memory */ + FreeItem(BusDeviceExtension); + + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath); + RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName); + + if (ServiceRelativePath) + { + RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\"); + RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath); + } + + if (InterfaceGuid) + { + /* register an device interface */ + Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->DeviceInterfaceLink); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + return Status; + } + + /* now enable device interface */ + Status = IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, TRUE); + + if (!NT_SUCCESS(Status)) + { + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + return Status; + } + } + + /* initialize common device extension */ + BusDeviceExtension->Common.BusDeviceExtension = NULL; + BusDeviceExtension->Common.DeviceObjectReferenceCount = 1; + BusDeviceExtension->Common.DeviceReferenceCount = 1; + BusDeviceExtension->Common.IsBus = TRUE; + InitializeListHead(&BusDeviceExtension->Common.Entry); + + /* store device objects */ + BusDeviceExtension->BusDeviceObject = BusDeviceObject; + BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; + + /* initialize lock */ + KeInitializeSpinLock(&BusDeviceExtension->Lock); + + /* initialize timer */ + KeInitializeTimer(&BusDeviceExtension->Timer); + + /* initialize dpc */ + KeInitializeDpc(&BusDeviceExtension->Dpc, KspBusDpcRoutine, (PVOID)BusDeviceExtension); + + /* initialize event */ + KeInitializeEvent(&BusDeviceExtension->Event, SynchronizationEvent, FALSE); + + /* initialize work item */ + ExInitializeWorkItem(&BusDeviceExtension->WorkItem, KspBusWorkerRoutine, (PVOID)BusDeviceExtension); + + if (!PnpDeviceObject) + { + /* attach device */ + BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject); + + if (!BusDeviceExtension->PnpDeviceObject) + { + /* failed to attach device */ + if (BusDeviceExtension->DeviceInterfaceLink.Buffer) + { + IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); + RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); + } + + /* free device extension */ + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + + return STATUS_DEVICE_REMOVED; + } + + /* mark device as attached */ + BusDeviceExtension->DeviceAttached = TRUE; + } + else + { + /* directly attach */ + BusDeviceExtension->PnpDeviceObject = PnpDeviceObject; + } + + /* now scan the bus */ + Status = KspScanBus(BusDeviceExtension); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed to scan bus */ + if (BusDeviceExtension->DeviceInterfaceLink.Buffer) + { + IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); + RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); + } + + if (BusDeviceExtension->DeviceAttached) + { + /* detach device */ + IoDetachDevice(BusDeviceExtension->PnpDeviceObject); + } + + /* free device extension */ + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + } + + DPRINT("KsCreateBusEnumObject Status %x\n", Status); + /* done */ + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsGetBusEnumPnpDeviceObject( + IN PDEVICE_OBJECT DeviceObject, + IN PDEVICE_OBJECT *PnpDeviceObject) +{ + PDEV_EXTENSION DeviceExtension; + PCOMMON_DEVICE_EXTENSION CommonDeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + + DPRINT("KsGetBusEnumPnpDeviceObject\n"); + + if (!DeviceObject->DeviceExtension) + { + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; + } + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get common device extension */ + CommonDeviceExtension = DeviceExtension->Ext; + + if (!CommonDeviceExtension) + { + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; + } + + if (!CommonDeviceExtension->IsBus) + { + /* getting pnp device object is only supported for software bus device object */ + return STATUS_INVALID_PARAMETER; + } + + /* sanity checks */ + ASSERT(CommonDeviceExtension); + ASSERT(CommonDeviceExtension->IsBus); + + /* cast to bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)CommonDeviceExtension; + + /* store result */ + *PnpDeviceObject = BusDeviceExtension->PnpDeviceObject; + + /* done */ + return STATUS_SUCCESS; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsInstallBusEnumInterface( + PIRP Irp) +{ + BUS_INSTALL_ENUM_CONTEXT Context; + KPROCESSOR_MODE Mode; + LUID luid; + PIO_STACK_LOCATION IoStack; + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + + DPRINT1("KsInstallBusEnumInterface\n"); + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* get previous mode */ + Mode = ExGetPreviousMode(); + + /* convert to luid */ + luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); + + /* perform access check */ + if (!SeSinglePrivilegeCheck(luid, Mode)) + { + /* insufficient privileges */ + return STATUS_PRIVILEGE_NOT_HELD; + } + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + + /* initialize context */ + Context.Irp = Irp; + KeInitializeEvent(&Context.Event, NotificationEvent, FALSE); + Context.BusDeviceExtension = BusDeviceExtension; + ExInitializeWorkItem(&Context.WorkItem, KspInstallBusEnumInterface, (PVOID)&Context); + + /* queue the work item */ + ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); + /* wait for completion */ + KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL); + + /* store result */ + Irp->IoStatus.Status = Context.Status; + + /* done */ + return Context.Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsIsBusEnumChildDevice( + IN PDEVICE_OBJECT DeviceObject, + OUT PBOOLEAN ChildDevice) +{ + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + + DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + if (!BusDeviceExtension) + { + /* not a bus device */ + return STATUS_INVALID_PARAMETER; + } + + /* store result */ + *ChildDevice = (BusDeviceExtension->Common.IsBus == FALSE); + + return STATUS_SUCCESS; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsServiceBusEnumCreateRequest( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PIRP Irp) +{ + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* fix gcc */ + PIO_STACK_LOCATION IoStack; + BOOLEAN ItemExists = FALSE; + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; + NTSTATUS Status; + LARGE_INTEGER Time; + + /* FIXME: locks */ + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(IoStack->FileObject); + ASSERT(IoStack->FileObject->FileName.Buffer); + + DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp, &IoStack->FileObject->FileName); + + /* scan list and check if it is already present */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get real offset */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* check if name matches */ + if (!wcsicmp(DeviceEntry->DeviceName, IoStack->FileObject->FileName.Buffer + 1)) + { + /* item already exists */ + ItemExists = TRUE; + break; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + if (!ItemExists) + { + /* interface not registered */ + DPRINT1("Interface %wZ not registered\n", &IoStack->FileObject->FileName); + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* is there a pdo yet */ + if (DeviceEntry->PDO) + { + if (DeviceEntry->DeviceState == Started) + { + /* issue reparse */ + Status = KspDoReparseForIrp(Irp, DeviceEntry); + DPRINT("REPARSE Irp %p '%wZ'\n", Irp, &IoStack->FileObject->FileName); + + Irp->IoStatus.Status = Status; + return Status; + } + + /* delay processing until pnp is finished with enumeration */ + IoMarkIrpPending(Irp); + + /* insert into irp pending list */ + InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); + + Time.QuadPart = Int32x32To64(1500, -10000); + DbgPrint("PENDING Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); + + /* query current time */ + KeQuerySystemTime(&DeviceEntry->TimeCreated); + + /* set timer */ + KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); + + /* done for now */ + return STATUS_PENDING; + + } + else + { + /* time to create PDO */ + Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); + + if (!NT_SUCCESS(Status)) + { + /* failed to create PDO */ + DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status); + return Status; + } + DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); + + /* delay processing until pnp is finished with enumeration */ + IoMarkIrpPending(Irp); + + /* insert into irp pending list */ + InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); + + /* get current time */ + KeQuerySystemTime(&DeviceEntry->TimeCreated); + + /* invalidate device relations */ + IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); + + /* done for now */ + return STATUS_PENDING; + } +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsServiceBusEnumPnpRequest( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PIRP Irp) +{ + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; + PIO_STACK_LOCATION IoStack; + NTSTATUS Status; + LARGE_INTEGER Time; + PDEVICE_RELATIONS DeviceRelation; + PBUS_DEVICE_ENTRY DeviceEntry; + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (BusDeviceExtension->Common.IsBus) + { + if (IoStack->MinorFunction == IRP_MN_START_DEVICE) + { + /* no op for bus driver */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS) + { + /* handle bus device relations */ + ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == BusRelations); + + Status = KspQueryBusRelations(BusDeviceExtension, Irp); + } + else + { + /* get default status */ + Status = Irp->IoStatus.Status; + } + } + else + { + /* get child device extension */ + ChildDeviceExtension = DeviceExtension->Ext; + + /* get bus device extension */ + BusDeviceExtension = ChildDeviceExtension->BusDeviceExtension; + + if (IoStack->MinorFunction == IRP_MN_QUERY_ID) + { + /* query id */ + Status = KspQueryId(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE) + { + ASSERT(ChildDeviceExtension->DeviceEntry->DeviceState != Started || ChildDeviceExtension->DeviceEntry->DeviceState == NotStarted); + ASSERT(ChildDeviceExtension->DeviceEntry->PDO == DeviceObject); + + /* backup device entry */ + DeviceEntry = ChildDeviceExtension->DeviceEntry; + + /* free device extension */ + FreeItem(ChildDeviceExtension); + + /* clear PDO reference */ + DeviceEntry->PDO = NULL; + + /* delete the device */ + IoDeleteDevice(DeviceObject); + + if (DeviceEntry->PDODeviceName) + { + /* delete pdo device name */ + FreeItem(DeviceEntry->PDODeviceName); + + /* set to null */ + DeviceEntry->PDODeviceName = NULL; + } + + /* set state no notstarted */ + DeviceEntry->DeviceState = NotStarted; + + /* time to create PDO */ + KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); + + /* invalidate device relations */ + IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); + + /* done */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION) + { + /* query bus information */ + Status = KspQueryBusInformation(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES) + { + /* no op */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS) + { + /* no op */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_START_DEVICE) + { + /* start bus */ + Status = KspStartBusDevice(DeviceObject, ChildDeviceExtension, Irp); + + /* set time out */ + Time.QuadPart = Int32x32To64(1500, -10000); + + /* sanity check */ + ASSERT(BusDeviceExtension); + + /* set timer */ + KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES) + { + /* query capabilities */ + Status = KspQueryBusDeviceCapabilities(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE) + { + /* query pnp state */ + Status = KspQueryBusDevicePnpState(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE) + { + /* query interface */ + Status = KspQueryBusDeviceInterface(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS && IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) + { + /* handle target device relations */ + ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation); + ASSERT(Irp->IoStatus.Information == 0); + + /* allocate device relation */ + DeviceRelation = AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); + if (DeviceRelation) + { + DeviceRelation->Count = 1; + DeviceRelation->Objects[0] = DeviceObject; + + /* reference self */ + ObReferenceObject(DeviceObject); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; + + /* done */ + Status = STATUS_SUCCESS; + } + else + { + /* no memory */ + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + /* get default status */ + Status = Irp->IoStatus.Status; + } + } + + DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject, BusDeviceExtension->Common.IsBus, IoStack->MinorFunction, Status); + Irp->IoStatus.Status = Status; + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsRemoveBusEnumInterface( + IN PIRP Irp) +{ + KPROCESSOR_MODE Mode; + LUID luid; + BUS_INSTALL_ENUM_CONTEXT Ctx; + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PIO_STACK_LOCATION IoStack; + + DPRINT1("KsRemoveBusEnumInterface\n"); + + /* get io stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = DeviceExtension->Ext->BusDeviceExtension; + + /* get previous mode */ + Mode = ExGetPreviousMode(); + + /* convert to luid */ + luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); + + /* perform access check */ + if (!SeSinglePrivilegeCheck(luid, Mode)) + { + /* insufficient privileges */ + return STATUS_PRIVILEGE_NOT_HELD; + } + + /* initialize context */ + KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE); + Ctx.Irp = Irp; + Ctx.BusDeviceExtension = BusDeviceExtension; + ExInitializeWorkItem(&Ctx.WorkItem, KspRemoveBusInterface, (PVOID)&Ctx); + + /* now queue the work item */ + ExQueueWorkItem(&Ctx.WorkItem, DelayedWorkQueue); + + /* wait for completion */ + KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL); + + /* return result */ + return Ctx.Status; +} diff --git a/reactos/drivers/ksfilter/swenum/swenum.c b/reactos/drivers/ksfilter/swenum/swenum.c index 459e60b377f..c2aeaad5ea3 100644 --- a/reactos/drivers/ksfilter/swenum/swenum.c +++ b/reactos/drivers/ksfilter/swenum/swenum.c @@ -18,8 +18,56 @@ SwDispatchPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + NTSTATUS Status, PnpStatus; + BOOLEAN ChildDevice; + PIO_STACK_LOCATION IoStack; + PDEVICE_OBJECT PnpDeviceObject = NULL; - UNIMPLEMENTED; + /* get current stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* check if the device object is a child device */ + Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice); + + /* get bus enum pnp object */ + PnpStatus = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject); + + /* check for success */ + if (!NT_SUCCESS(Status) || !NT_SUCCESS(PnpStatus)) + { + /* start next power irp */ + PoStartNextPowerIrp(Irp); + + /* just complete the irp */ + Irp->IoStatus.Status = STATUS_SUCCESS; + + /* complete the irp */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* done */ + return STATUS_SUCCESS; + } + + if (IoStack->MinorFunction == IRP_MN_SET_POWER || IoStack->MinorFunction == IRP_MN_QUERY_POWER) + { + /* fake success */ + Irp->IoStatus.Status = STATUS_SUCCESS; + } + + if (!ChildDevice) + { + /* forward to pnp device object */ + PoStartNextPowerIrp(Irp); + + /* skip current location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* done */ + return PoCallDriver(PnpDeviceObject, Irp); + } + + /* start next power irp */ + PoStartNextPowerIrp(Irp); /* just complete the irp */ Irp->IoStatus.Status = STATUS_SUCCESS; @@ -29,7 +77,6 @@ SwDispatchPower( /* done */ return STATUS_SUCCESS; - } NTSTATUS @@ -43,6 +90,9 @@ SwDispatchPnp( PIO_STACK_LOCATION IoStack; PDEVICE_OBJECT PnpDeviceObject = NULL; + /* get current stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + /* check if the device object is a child device */ Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice); @@ -55,10 +105,30 @@ SwDispatchPnp( return Status; } + DPRINT("SwDispatchPnp ChildDevice %u Request %x\n", ChildDevice, IoStack->MinorFunction); + /* let ks handle it */ Status = KsServiceBusEnumPnpRequest(DeviceObject, Irp); - if (!NT_SUCCESS(Status)) + /* check if the request was for a pdo */ + if (!ChildDevice) + { + if (Status != STATUS_NOT_SUPPORTED) + { + /* store result */ + Irp->IoStatus.Status = Status; + } + + /* complete request */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* done */ + return Status; + } + + DPRINT("SwDispatchPnp KsServiceBusEnumPnpRequest Status %x\n", Status); + + if (NT_SUCCESS(Status)) { /* invalid request or not supported */ Irp->IoStatus.Status = Status; @@ -69,6 +139,8 @@ SwDispatchPnp( /* get bus enum pnp object */ Status = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject); + DPRINT("SwDispatchPnp KsGetBusEnumPnpDeviceObject Status %x\n", Status); + /* check for success */ if (!NT_SUCCESS(Status)) { @@ -89,11 +161,49 @@ SwDispatchPnp( /* delete the device */ IoDeleteDevice(DeviceObject); } + else + { + if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES || IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS) + { + /* no resources required */ + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; - /* skip current location */ - IoSkipCurrentIrpStackLocation(Irp); - /* call the pnp device object */ - return IoCallDriver(PnpDeviceObject, Irp); + /* skip current location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* call the pnp device object */ + return IoCallDriver(PnpDeviceObject, Irp); + } + + if (IoStack->MajorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE) + { + /* device cannot be disabled */ + Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; + Irp->IoStatus.Status = STATUS_SUCCESS; + + /* skip current location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* call the pnp device object */ + return IoCallDriver(PnpDeviceObject, Irp); + } + + if (Status == STATUS_NOT_SUPPORTED) + { + /* skip current location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* call the pnp device object */ + return IoCallDriver(PnpDeviceObject, Irp); + } + } + + /* complete the request */ + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; } NTSTATUS @@ -149,7 +259,7 @@ SwDispatchDeviceControl( IN PIRP Irp) { PIO_STACK_LOCATION IoStack; - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; /* get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -158,16 +268,25 @@ SwDispatchDeviceControl( { /* install interface */ Status = KsInstallBusEnumInterface(Irp); + DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_INSTALL_INTERFACE %x\n", Status); } else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_REMOVE_INTERFACE) { /* remove interface */ Status = KsRemoveBusEnumInterface(Irp); + DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_REMOVE_INTERFACE %x\n", Status); + } else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_GET_BUS_ID) { /* get bus id */ - return KsGetBusEnumIdentifier(Irp); + Status = KsGetBusEnumIdentifier(Irp); + DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_GET_BUS_ID %x\n", Status); + } + else + { + DPRINT("SwDispatchDeviceControl Unknown IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + Status = STATUS_INVALID_PARAMETER; } /* store result */ @@ -193,6 +312,8 @@ SwDispatchCreate( /* check if the device object is a child device */ Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice); + DPRINT("SwDispatchCreate %x\n", Status); + /* check for success */ if (NT_SUCCESS(Status)) { @@ -205,6 +326,7 @@ SwDispatchCreate( } /* perform the create request */ Status = KsServiceBusEnumCreateRequest(DeviceObject, Irp); + DPRINT("SwDispatchCreate %x\n", Status); } /* check the irp is pending */ @@ -245,6 +367,7 @@ SwAddDevice( NTSTATUS Status; PDEVICE_OBJECT FunctionalDeviceObject; + DPRINT("SWENUM AddDevice\n"); /* create the device */ Status = IoCreateDevice(DriverObject, sizeof(KSDEVICE_HEADER), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &FunctionalDeviceObject); @@ -303,7 +426,7 @@ DriverEntry( DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SwDispatchDeviceControl; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SwDispatchSystemControl; - + DPRINT("SWENUM loaded\n"); return STATUS_SUCCESS; } diff --git a/reactos/drivers/ksfilter/swenum/swenum.rbuild b/reactos/drivers/ksfilter/swenum/swenum.rbuild index 0978c11a1b2..462a0f6824d 100644 --- a/reactos/drivers/ksfilter/swenum/swenum.rbuild +++ b/reactos/drivers/ksfilter/swenum/swenum.rbuild @@ -1,6 +1,7 @@ + ntoskrnl ks swenum.c