/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel Streaming * FILE: drivers/ksfilter/ks/factory.c * PURPOSE: KS Allocator functions * PROGRAMMER: Johannes Anderwald */ #include "precomp.h" #include #define NDEBUG #include /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsDispatchQuerySecurity( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PKSOBJECT_CREATE_ITEM CreateItem; PIO_STACK_LOCATION IoStack; NTSTATUS Status; ULONG Length; /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); /* get create item */ CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); if (!CreateItem || !CreateItem->SecurityDescriptor) { /* no create item */ Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT; CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_SECURITY_ON_OBJECT; } /* get input length */ Length = IoStack->Parameters.QuerySecurity.Length; /* clone the security descriptor */ Status = SeQuerySecurityDescriptorInfo(&IoStack->Parameters.QuerySecurity.SecurityInformation, (PSECURITY_DESCRIPTOR)Irp->UserBuffer, &Length, &CreateItem->SecurityDescriptor); DPRINT("SeQuerySecurityDescriptorInfo Status %x\n", Status); /* store result */ Irp->IoStatus.Status = Status; Irp->IoStatus.Information = Length; CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsDispatchSetSecurity( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PKSOBJECT_CREATE_ITEM CreateItem; PIO_STACK_LOCATION IoStack; PGENERIC_MAPPING Mapping; PSECURITY_DESCRIPTOR Descriptor; NTSTATUS Status; /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); /* get create item */ CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); if (!CreateItem || !CreateItem->SecurityDescriptor) { /* no create item */ Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT; CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_SECURITY_ON_OBJECT; } /* backup old descriptor */ Descriptor = CreateItem->SecurityDescriptor; /* get generic mapping */ Mapping = IoGetFileObjectGenericMapping(); /* change security descriptor */ Status = SeSetSecurityDescriptorInfo(NULL, /*FIXME */ &IoStack->Parameters.SetSecurity.SecurityInformation, IoStack->Parameters.SetSecurity.SecurityDescriptor, &CreateItem->SecurityDescriptor, NonPagedPool, Mapping); if (NT_SUCCESS(Status)) { /* free old descriptor */ FreeItem(Descriptor); /* mark create item as changed */ CreateItem->Flags |= KSCREATE_ITEM_SECURITYCHANGED; } /* store result */ Irp->IoStatus.Status = Status; CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } /* @unimplemented */ KSDDKAPI NTSTATUS NTAPI KsDispatchSpecificMethod( IN PIRP Irp, IN PFNKSHANDLER Handler) { UNIMPLEMENTED; return STATUS_UNSUCCESSFUL; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsReadFile( IN PFILE_OBJECT FileObject, IN PKEVENT Event OPTIONAL, IN PVOID PortContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN ULONG Key OPTIONAL, IN KPROCESSOR_MODE RequestorMode) { PDEVICE_OBJECT DeviceObject; PIRP Irp; NTSTATUS Status; BOOLEAN Result; KEVENT LocalEvent; if (Event) { /* make sure event is reset */ KeClearEvent(Event); } if (RequestorMode == UserMode) { /* probe the user buffer */ _SEH2_TRY { ProbeForWrite(Buffer, Length, sizeof(UCHAR)); Status = STATUS_SUCCESS; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { DPRINT1("Invalid user buffer provided\n"); return Status; } } /* get corresponding device object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); /* fast-io read is only available for kernel mode clients */ if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode && DeviceObject->DriverObject->FastIoDispatch->FastIoRead) { /* call fast io write */ Result = DeviceObject->DriverObject->FastIoDispatch->FastIoRead(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject); if (Result && NT_SUCCESS(IoStatusBlock->Status)) { /* request was handled and succeeded */ return STATUS_SUCCESS; } } /* do the slow way */ if (!Event) { /* initialize temp event */ KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE); Event = &LocalEvent; } /* build the irp packet */ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock); if (!Irp) { /* not enough resources */ return STATUS_INSUFFICIENT_RESOURCES; } /* send the packet */ Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { /* operation is pending, is sync file object */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { /* it is so wait */ KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL); Status = IoStatusBlock->Status; } } /* return result */ return Status; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsWriteFile( IN PFILE_OBJECT FileObject, IN PKEVENT Event OPTIONAL, IN PVOID PortContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN ULONG Key OPTIONAL, IN KPROCESSOR_MODE RequestorMode) { PDEVICE_OBJECT DeviceObject; PIRP Irp; NTSTATUS Status; BOOLEAN Result; KEVENT LocalEvent; if (Event) { /* make sure event is reset */ KeClearEvent(Event); } if (RequestorMode == UserMode) { /* probe the user buffer */ _SEH2_TRY { ProbeForRead(Buffer, Length, sizeof(UCHAR)); Status = STATUS_SUCCESS; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { DPRINT1("Invalid user buffer provided\n"); return Status; } } /* get corresponding device object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); /* fast-io write is only available for kernel mode clients */ if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode && DeviceObject->DriverObject->FastIoDispatch->FastIoWrite) { /* call fast io write */ Result = DeviceObject->DriverObject->FastIoDispatch->FastIoWrite(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject); if (Result && NT_SUCCESS(IoStatusBlock->Status)) { /* request was handled and succeeded */ return STATUS_SUCCESS; } } /* do the slow way */ if (!Event) { /* initialize temp event */ KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE); Event = &LocalEvent; } /* build the irp packet */ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock); if (!Irp) { /* not enough resources */ return STATUS_INSUFFICIENT_RESOURCES; } /* send the packet */ Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { /* operation is pending, is sync file object */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { /* it is so wait */ KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL); Status = IoStatusBlock->Status; } } /* return result */ return Status; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsQueryInformationFile( IN PFILE_OBJECT FileObject, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass) { PDEVICE_OBJECT DeviceObject; PFAST_IO_DISPATCH FastIoDispatch; PIRP Irp; PIO_STACK_LOCATION IoStack; IO_STATUS_BLOCK IoStatusBlock; KEVENT Event; LARGE_INTEGER Offset; NTSTATUS Status; /* get related file object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); /* get fast i/o table */ FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch; /* is there a fast table */ if (FastIoDispatch) { /* check the class */ if (FileInformationClass == FileBasicInformation) { /* use FastIoQueryBasicInfo routine */ if (FastIoDispatch->FastIoQueryBasicInfo != NULL && FastIoDispatch->FastIoQueryBasicInfo( FileObject, TRUE, (PFILE_BASIC_INFORMATION)FileInformation, &IoStatusBlock, DeviceObject)) { /* request was handled */ return IoStatusBlock.Status; } } else if (FileInformationClass == FileStandardInformation) { /* use FastIoQueryStandardInfo routine */ if (FastIoDispatch->FastIoQueryStandardInfo != NULL && FastIoDispatch->FastIoQueryStandardInfo( FileObject, TRUE, (PFILE_STANDARD_INFORMATION)FileInformation, &IoStatusBlock, DeviceObject)) { /* request was handled */ return IoStatusBlock.Status; } } } /* clear event */ KeClearEvent(&FileObject->Event); /* initialize event */ KeInitializeEvent(&Event, NotificationEvent, FALSE); /* set offset to zero */ Offset.QuadPart = 0L; /* build the request */ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION, IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event, &IoStatusBlock); if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; /* get next stack location */ IoStack = IoGetNextIrpStackLocation(Irp); /* setup parameters */ IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass; IoStack->Parameters.QueryFile.Length = Length; Irp->AssociatedIrp.SystemBuffer = FileInformation; /* call the driver */ Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); if (Status == STATUS_PENDING) { /* wait for the operation to complete */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); /* is object sync */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) Status = FileObject->FinalStatus; else Status = IoStatusBlock.Status; } /* done */ return Status; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsSetInformationFile( IN PFILE_OBJECT FileObject, IN PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass) { PIO_STACK_LOCATION IoStack; PDEVICE_OBJECT DeviceObject; PIRP Irp; PVOID Buffer; KEVENT Event; LARGE_INTEGER Offset; IO_STATUS_BLOCK IoStatus; NTSTATUS Status; /* get related device object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); /* copy file information */ Buffer = AllocateItem(NonPagedPool, Length); if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES; _SEH2_TRY { ProbeForRead(Buffer, Length, sizeof(UCHAR)); RtlMoveMemory(Buffer, FileInformation, Length); Status = STATUS_SUCCESS; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { /* invalid user buffer */ FreeItem(Buffer); return Status; } /* initialize the event */ KeInitializeEvent(&Event, SynchronizationEvent, FALSE); /* zero offset */ Offset.QuadPart = 0LL; /* build the irp */ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_INFORMATION, DeviceObject, NULL, 0, &Offset, &Event, &IoStatus); if (!Irp) { /* failed to allocate irp */ FreeItem(Buffer); return STATUS_INSUFFICIENT_RESOURCES; } /* get next stack location */ IoStack = IoGetNextIrpStackLocation(Irp); /* set irp parameters */ IoStack->Parameters.SetFile.FileInformationClass = FileInformationClass; IoStack->Parameters.SetFile.Length = Length; IoStack->Parameters.SetFile.FileObject = FileObject; Irp->AssociatedIrp.SystemBuffer = Buffer; Irp->UserBuffer = FileInformation; /* dispatch the irp */ Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { /* wait untill the operation has completed */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); /* is a sync file object */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) Status = FileObject->FinalStatus; else Status = IoStatus.Status; } /* done */ return Status; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsStreamIo( IN PFILE_OBJECT FileObject, IN PKEVENT Event OPTIONAL, IN PVOID PortContext OPTIONAL, IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL, IN PVOID CompletionContext OPTIONAL, IN KSCOMPLETION_INVOCATION CompletionInvocationFlags OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN OUT PVOID StreamHeaders, IN ULONG Length, IN ULONG Flags, IN KPROCESSOR_MODE RequestorMode) { PIRP Irp; PIO_STACK_LOCATION IoStack; PDEVICE_OBJECT DeviceObject; NTSTATUS Status; LARGE_INTEGER Offset; PKSIOBJECT_HEADER ObjectHeader; BOOLEAN Ret; /* get related device object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); /* sanity check */ ASSERT(DeviceObject != NULL); /* is there a event provided */ if (Event) { /* reset event */ KeClearEvent(Event); } if (RequestorMode || ExGetPreviousMode() == KernelMode) { /* requestor is from kernel land */ ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2; if (ObjectHeader) { /* there is a object header */ if (Flags == KSSTREAM_READ) { /* is fast read supported */ if (ObjectHeader->DispatchTable.FastRead) { /* call fast read dispatch routine */ Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject); if (Ret) { /* the request was handled */ return IoStatusBlock->Status; } } } else if (Flags == KSSTREAM_WRITE) { /* is fast write supported */ if (ObjectHeader->DispatchTable.FastWrite) { /* call fast write dispatch routine */ Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject); if (Ret) { /* the request was handled */ return IoStatusBlock->Status; } } } } } /* clear file object event */ KeClearEvent(&FileObject->Event); /* set the offset to zero */ Offset.QuadPart = 0LL; /* now build the irp */ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL, DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock); if (!Irp) { /* not enough memory */ return STATUS_INSUFFICIENT_RESOURCES; } /* setup irp parameters */ Irp->RequestorMode = RequestorMode; Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext; Irp->Tail.Overlay.OriginalFileObject = FileObject; Irp->UserBuffer = StreamHeaders; /* get next irp stack location */ IoStack = IoGetNextIrpStackLocation(Irp); /* setup stack parameters */ IoStack->FileObject = FileObject; IoStack->Parameters.DeviceIoControl.InputBufferLength = Length; IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders; IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); if (CompletionRoutine) { /* setup completion routine for async processing */ IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel)); } /* now call the driver */ Status = IoCallDriver(DeviceObject, Irp); /* done */ return Status; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsProbeStreamIrp( IN PIRP Irp, IN ULONG ProbeFlags, IN ULONG HeaderSize) { PMDL Mdl; PVOID Buffer; LOCK_OPERATION Operation; NTSTATUS Status = STATUS_SUCCESS; PKSSTREAM_HEADER StreamHeader; PIO_STACK_LOCATION IoStack; ULONG Length; //BOOLEAN AllocateMdl = FALSE; /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength; if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer) { if (Irp->RequestorMode == KernelMode) { /* no need to allocate stream header */ Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer; } AllocMdl: /* check if alloc mdl flag is passed */ if (!(ProbeFlags & KSPROBE_ALLOCATEMDL)) { /* nothing more to do */ return STATUS_SUCCESS; } if (Irp->MdlAddress) { ProbeMdl: if (ProbeFlags & KSPROBE_PROBEANDLOCK) { if (Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_SOURCE_IS_NONPAGED_POOL)) { if (ProbeFlags & KSPROBE_SYSTEMADDRESS) { _SEH2_TRY { /* loop through all mdls and probe them */ Mdl = Irp->MdlAddress; do { /* the mapping can fail */ Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) { /* no need to probe these pages */ Buffer = Mdl->MappedSystemVa; } else { /* probe that mdl */ Buffer = MmMapLockedPages(Mdl, KernelMode); } /* check if the mapping succeeded */ if (!Buffer) { /* raise exception we'll catch */ ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); } /* iterate to next mdl */ Mdl = Mdl->Next; }while(Mdl); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; } } else { _SEH2_TRY { /* loop through all mdls and probe them */ Mdl = Irp->MdlAddress; /* determine operation */ if (!(ProbeFlags & KSPROBE_STREAMWRITE) || (ProbeFlags & KSPROBE_MODIFY)) { /* operation is read / modify stream, need write access */ Operation = IoWriteAccess; } else { /* operation is write to device, so we need read access */ Operation = IoReadAccess; } do { /* probe the pages */ MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation); if (ProbeFlags & KSPROBE_SYSTEMADDRESS) { /* the mapping can fail */ Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) { /* no need to probe these pages */ Buffer = Mdl->MappedSystemVa; } else { /* probe that mdl */ Buffer = MmMapLockedPages(Mdl, KernelMode); } /* check if the mapping succeeded */ if (!Buffer) { /* raise exception we'll catch */ ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); } } /* iterate to next mdl */ Mdl = Mdl->Next; }while(Mdl); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; } } return Status; } /* check all stream headers */ StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; ASSERT(StreamHeader); _SEH2_TRY { do { if (HeaderSize) { /* does the supplied header size match stream header size and no type changed */ if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) { /* invalid stream header */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } else { /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */ if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) { /* invalid stream header */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } if (Length < StreamHeader->Size) { /* length is too short */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } if (ProbeFlags & KSPROBE_STREAMWRITE) { if (StreamHeader->DataUsed > StreamHeader->FrameExtent) { /* frame extend can never be smaller */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } /* is this stream change packet */ if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) { if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) { /* stream changed - must be send in a single packet */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE)) { /* caller does not permit format changes */ ExRaiseStatus(STATUS_INVALID_PARAMETER); } if (StreamHeader->FrameExtent) { /* allocate an mdl */ Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp); if (!Mdl) { /* not enough memory */ ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); } /* break-out to probe for the irp */ break; } } } else { if (StreamHeader->DataUsed) { /* DataUsed must be zero for stream read operation */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } if (StreamHeader->OptionsFlags) { /* no flags supported for reading */ ExRaiseStatus(STATUS_INVALID_PARAMETER); } } if (StreamHeader->FrameExtent) { /* allocate an mdl */ ASSERT(Irp->MdlAddress == NULL); Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp); if (!Mdl) { /* not enough memory */ ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); } } /* move to next stream header */ Length -= StreamHeader->Size; StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); }while(Length); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); }_SEH2_END; /* now probe the allocated mdl's */ if (!NT_SUCCESS(Status)) { DPRINT("Status %x\n", Status); return Status; } else goto ProbeMdl; } /* probe user mode buffers */ if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) ) { /* allocate stream header buffer */ Irp->AssociatedIrp.SystemBuffer = AllocateItem(NonPagedPool, Length); if (!Irp->AssociatedIrp.SystemBuffer) { /* no memory */ return STATUS_INSUFFICIENT_RESOURCES; } /* mark irp as buffered so that changes the stream headers are propagated back */ Irp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO; _SEH2_TRY { if (ProbeFlags & KSPROBE_STREAMWRITE) { if (ProbeFlags & KSPROBE_MODIFY) ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); else ProbeForRead(Irp->UserBuffer, Length, sizeof(UCHAR)); } else { /* stream reads means writing */ ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); /* set input operation flags */ Irp->Flags |= IRP_INPUT_OPERATION; } /* copy stream buffer */ RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Length); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); }_SEH2_END; if (!NT_SUCCESS(Status)) { /* failed */ return Status; } if (ProbeFlags & KSPROBE_ALLOCATEMDL) { /* alloc mdls */ goto AllocMdl; } /* check all stream headers */ StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; _SEH2_TRY { do { if (HeaderSize) { /* does the supplied header size match stream header size and no type changed */ if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) { /* invalid stream header */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } else { /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */ if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) { /* invalid stream header */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } if (Length < StreamHeader->Size) { /* length is too short */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } if (ProbeFlags & KSPROBE_STREAMWRITE) { if (StreamHeader->DataUsed > StreamHeader->FrameExtent) { /* frame extend can never be smaller */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } /* is this stream change packet */ if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) { if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) { /* stream changed - must be send in a single packet */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE)) { /* caller does not permit format changes */ ExRaiseStatus(STATUS_INVALID_PARAMETER); } if (StreamHeader->FrameExtent) { /* allocate an mdl */ Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp); if (!Mdl) { /* not enough memory */ ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); } /* break out to probe for the irp */ //AllocateMdl = TRUE; break; } } } else { if (StreamHeader->DataUsed) { /* DataUsed must be zero for stream read operation */ ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } if (StreamHeader->OptionsFlags) { /* no flags supported for reading */ ExRaiseStatus(STATUS_INVALID_PARAMETER); } } /* move to next stream header */ Length -= StreamHeader->Size; StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); }while(Length); }_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); }_SEH2_END; /* now probe the allocated mdl's */ if (NT_SUCCESS(Status)) goto AllocMdl; else return Status; } return STATUS_INVALID_BUFFER_SIZE; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsAllocateExtraData( IN PIRP Irp, IN ULONG ExtraSize, OUT PVOID* ExtraBuffer) { PIO_STACK_LOCATION IoStack; ULONG Count, Index; PUCHAR Buffer, BufferOrg; PKSSTREAM_HEADER Header; NTSTATUS Status = STATUS_SUCCESS; /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); /* sanity check */ ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER)); /* get total length */ Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER); /* allocate buffer */ Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize)); if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES; _SEH2_TRY { /* get input buffer */ Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; for(Index = 0; Index < Count; Index++) { /* copy stream header */ RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER)); /* move to next header */ Header++; /* increment output buffer offset */ Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Exception, get the error code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { /* free buffer on exception */ FreeItem(Buffer); return Status; } /* store result */ *ExtraBuffer = BufferOrg; /* done */ return STATUS_SUCCESS; } /* @implemented */ KSDDKAPI VOID NTAPI KsNullDriverUnload( IN PDRIVER_OBJECT DriverObject) { } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsDispatchInvalidDeviceRequest( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsDefaultDeviceIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; NTSTATUS Status; /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY && IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD && IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_ENABLE_EVENT && IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_DISABLE_EVENT) { if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE) { /* fake success */ Status = STATUS_SUCCESS; } else { /* request unsupported */ Status = STATUS_INVALID_DEVICE_REQUEST; } } else { /* property / method / event not found */ Status = STATUS_PROPSET_NOT_FOUND; } /* complete request */ Irp->IoStatus.Status = Status; CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } /* @implemented */ KSDDKAPI BOOLEAN NTAPI KsDispatchFastIoDeviceControlFailure( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject) { return FALSE; } /* @implemented */ KSDDKAPI BOOLEAN NTAPI KsDispatchFastReadFailure( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject) { return FALSE; } /* @implemented */ KSDDKAPI VOID NTAPI KsCancelIo( IN OUT PLIST_ENTRY QueueHead, IN PKSPIN_LOCK SpinLock) { PDRIVER_CANCEL OldDriverCancel; PIO_STACK_LOCATION IoStack; PLIST_ENTRY Entry; PLIST_ENTRY NextEntry; PIRP Irp; KIRQL OldLevel; /* acquire spinlock */ KeAcquireSpinLock(SpinLock, &OldLevel); /* point to first entry */ Entry = QueueHead->Flink; /* loop all items */ while(Entry != QueueHead) { /* get irp offset */ Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); /* get next entry */ NextEntry = Entry->Flink; /* set cancelled bit */ Irp->Cancel = TRUE; /* now set the cancel routine */ OldDriverCancel = IoSetCancelRoutine(Irp, NULL); if (OldDriverCancel) { /* this irp hasnt been yet used, so free to cancel */ KeReleaseSpinLock(SpinLock, OldLevel); /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); /* acquire cancel spinlock */ IoAcquireCancelSpinLock(&Irp->CancelIrql); /* call provided cancel routine */ OldDriverCancel(IoStack->DeviceObject, Irp); /* re-acquire spinlock */ KeAcquireSpinLock(SpinLock, &OldLevel); } /* move on to next entry */ Entry = NextEntry; } /* the irp has already been canceled */ KeReleaseSpinLock(SpinLock, OldLevel); } /* @implemented */ KSDDKAPI VOID NTAPI KsReleaseIrpOnCancelableQueue( IN PIRP Irp, IN PDRIVER_CANCEL DriverCancel OPTIONAL) { PKSPIN_LOCK SpinLock; PDRIVER_CANCEL OldDriverCancel; PIO_STACK_LOCATION IoStack; KIRQL OldLevel; /* check for required parameters */ if (!Irp) return; if (!DriverCancel) { /* default to KsCancelRoutine */ DriverCancel = KsCancelRoutine; } /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); /* get internal queue lock */ SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp); /* acquire spinlock */ KeAcquireSpinLock(SpinLock, &OldLevel); /* now set the cancel routine */ OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel); if (Irp->Cancel && OldDriverCancel == NULL) { /* the irp has already been canceled */ KeReleaseSpinLock(SpinLock, OldLevel); /* cancel routine requires that cancel spinlock is held */ IoAcquireCancelSpinLock(&Irp->CancelIrql); /* cancel irp */ DriverCancel(IoStack->DeviceObject, Irp); } else { /* done */ KeReleaseSpinLock(SpinLock, OldLevel); } } /* @implemented */ KSDDKAPI PIRP NTAPI KsRemoveIrpFromCancelableQueue( IN OUT PLIST_ENTRY QueueHead, IN PKSPIN_LOCK SpinLock, IN KSLIST_ENTRY_LOCATION ListLocation, IN KSIRP_REMOVAL_OPERATION RemovalOperation) { PIRP Irp; PLIST_ENTRY CurEntry; KIRQL OldIrql; DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation); /* check parameters */ if (!QueueHead || !SpinLock) return NULL; /* check if parameter ListLocation is valid */ if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead) return NULL; /* acquire list lock */ KeAcquireSpinLock(SpinLock, &OldIrql); /* point to queue head */ CurEntry = QueueHead; do { /* reset irp to null */ Irp = NULL; /* iterate to next entry */ if (ListLocation == KsListEntryHead) CurEntry = CurEntry->Flink; else CurEntry = CurEntry->Blink; /* is the end of list reached */ if (CurEntry == QueueHead) { /* reached end of list */ break; } /* get irp offset */ Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry); if (Irp->Cancel) { /* irp has been canceled */ break; } if (Irp->CancelRoutine) { /* remove cancel routine */ Irp->CancelRoutine = NULL; if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem) { /* remove irp from list */ RemoveEntryList(&Irp->Tail.Overlay.ListEntry); } if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem) break; } }while(TRUE); /* release lock */ KeReleaseSpinLock(SpinLock, OldIrql); if (!Irp || Irp->CancelRoutine == NULL) { /* either an irp has been acquired or nothing found */ return Irp; } /* time to remove the canceled irp */ IoAcquireCancelSpinLock(&OldIrql); /* acquire list lock */ KeAcquireSpinLockAtDpcLevel(SpinLock); if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem) { /* remove it */ RemoveEntryList(&Irp->Tail.Overlay.ListEntry); } /* release list lock */ KeReleaseSpinLockFromDpcLevel(SpinLock); /* release cancel spinlock */ IoReleaseCancelSpinLock(OldIrql); /* no non canceled irp has been found */ return NULL; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsMoveIrpsOnCancelableQueue( IN OUT PLIST_ENTRY SourceList, IN PKSPIN_LOCK SourceLock, IN OUT PLIST_ENTRY DestinationList, IN PKSPIN_LOCK DestinationLock OPTIONAL, IN KSLIST_ENTRY_LOCATION ListLocation, IN PFNKSIRPLISTCALLBACK ListCallback, IN PVOID Context) { KIRQL OldLevel; PLIST_ENTRY SrcEntry; PIRP Irp; NTSTATUS Status = STATUS_SUCCESS; if (!DestinationLock) { /* no destination lock just acquire the source lock */ KeAcquireSpinLock(SourceLock, &OldLevel); } else { /* acquire cancel spinlock */ IoAcquireCancelSpinLock(&OldLevel); /* now acquire source lock */ KeAcquireSpinLockAtDpcLevel(SourceLock); /* now acquire destination lock */ KeAcquireSpinLockAtDpcLevel(DestinationLock); } /* point to list head */ SrcEntry = SourceList; /* now move all irps */ while(TRUE) { if (ListLocation == KsListEntryTail) { /* move queue downwards */ SrcEntry = SrcEntry->Flink; } else { /* move queue upwards */ SrcEntry = SrcEntry->Blink; } if (SrcEntry == SourceList) { /* eof list reached */ break; } /* get irp offset */ Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry); /* now check if irp can be moved */ Status = ListCallback(Irp, Context); /* check if irp can be moved */ if (Status == STATUS_SUCCESS) { /* remove irp from src list */ RemoveEntryList(&Irp->Tail.Overlay.ListEntry); if (ListLocation == KsListEntryTail) { /* insert irp end of list */ InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry); } else { /* insert irp head of list */ InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry); } /* do we need to update the irp lock */ if (DestinationLock) { /* update irp lock */ KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock; } } else { if (Status != STATUS_NO_MATCH) { /* callback decided to stop enumeration */ break; } /* reset return value */ Status = STATUS_SUCCESS; } } if (!DestinationLock) { /* release source lock */ KeReleaseSpinLock(SourceLock, OldLevel); } else { /* now release destination lock */ KeReleaseSpinLockFromDpcLevel(DestinationLock); /* now release source lock */ KeReleaseSpinLockFromDpcLevel(SourceLock); /* now release cancel spinlock */ IoReleaseCancelSpinLock(OldLevel); } /* done */ return Status; } /* @implemented */ KSDDKAPI VOID NTAPI KsRemoveSpecificIrpFromCancelableQueue( IN PIRP Irp) { PKSPIN_LOCK SpinLock; KIRQL OldLevel; DPRINT("KsRemoveSpecificIrpFromCancelableQueue %p\n", Irp); /* get internal queue lock */ SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp); /* acquire spinlock */ KeAcquireSpinLock(SpinLock, &OldLevel); /* remove the irp from the list */ RemoveEntryList(&Irp->Tail.Overlay.ListEntry); /* release spinlock */ KeReleaseSpinLock(SpinLock, OldLevel); } /* @implemented */ KSDDKAPI VOID NTAPI KsAddIrpToCancelableQueue( IN OUT PLIST_ENTRY QueueHead, IN PKSPIN_LOCK SpinLock, IN PIRP Irp, IN KSLIST_ENTRY_LOCATION ListLocation, IN PDRIVER_CANCEL DriverCancel OPTIONAL) { PDRIVER_CANCEL OldDriverCancel; PIO_STACK_LOCATION IoStack; KIRQL OldLevel; /* check for required parameters */ if (!QueueHead || !SpinLock || !Irp) return; /* 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); // HACK for ms portcls if (IoStack->MajorFunction == IRP_MJ_CREATE) { // complete the request DPRINT1("MS HACK\n"); Irp->IoStatus.Status = STATUS_SUCCESS; CompleteRequest(Irp, IO_NO_INCREMENT); return; } if (!DriverCancel) { /* default to KsCancelRoutine */ DriverCancel = KsCancelRoutine; } /* acquire spinlock */ KeAcquireSpinLock(SpinLock, &OldLevel); if (ListLocation == KsListEntryTail) { /* insert irp to tail of list */ InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry); } else { /* insert irp to head of list */ InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry); } /* store internal queue lock */ KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock; /* now set the cancel routine */ OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel); if (Irp->Cancel && OldDriverCancel == NULL) { /* the irp has already been canceled */ KeReleaseSpinLock(SpinLock, OldLevel); /* cancel routine requires that cancel spinlock is held */ IoAcquireCancelSpinLock(&Irp->CancelIrql); /* cancel irp */ DriverCancel(IoStack->DeviceObject, Irp); } else { /* done */ KeReleaseSpinLock(SpinLock, OldLevel); } } /* @implemented */ KSDDKAPI VOID NTAPI KsCancelRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PKSPIN_LOCK SpinLock; /* get internal queue lock */ SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp); /* acquire spinlock */ KeAcquireSpinLockAtDpcLevel(SpinLock); /* sanity check */ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); /* release cancel spinlock */ IoReleaseCancelSpinLock(Irp->CancelIrql); /* remove the irp from the list */ RemoveEntryList(&Irp->Tail.Overlay.ListEntry); /* release spinlock */ KeReleaseSpinLock(SpinLock, Irp->CancelIrql); /* has the irp already been canceled */ if (Irp->IoStatus.Status != STATUS_CANCELLED) { /* let's complete it */ Irp->IoStatus.Status = STATUS_CANCELLED; CompleteRequest(Irp, IO_NO_INCREMENT); } } NTSTATUS FindMatchingCreateItem( PLIST_ENTRY ListHead, PUNICODE_STRING String, OUT PCREATE_ITEM_ENTRY *OutCreateItem) { PLIST_ENTRY Entry; PCREATE_ITEM_ENTRY CreateItemEntry; UNICODE_STRING RefString; LPWSTR pStr; ULONG Count; /* Copy the input string */ RefString = *String; /* Check if the string starts with a backslash */ if (String->Buffer[0] == L'\\') { /* Skip backslash */ RefString.Buffer++; RefString.Length -= sizeof(WCHAR); } else { /* get terminator */ pStr = String->Buffer; Count = String->Length / sizeof(WCHAR); while ((Count > 0) && (*pStr != L'\\')) { pStr++; Count--; } /* sanity check */ ASSERT(Count != 0); // request is for pin / node / allocator RefString.Length = (USHORT)((PCHAR)pStr - (PCHAR)String->Buffer); } /* point to first entry */ Entry = ListHead->Flink; /* loop all device items */ while (Entry != ListHead) { /* get create item entry */ CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry); ASSERT(CreateItemEntry->CreateItem); if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD) { /* create item is default */ *OutCreateItem = CreateItemEntry; return STATUS_SUCCESS; } if (!CreateItemEntry->CreateItem->Create) { /* skip free create item */ Entry = Entry->Flink; continue; } DPRINT("CreateItem %S Length %u Request %wZ %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer, CreateItemEntry->CreateItem->ObjectClass.Length, &RefString, RefString.Length); if (CreateItemEntry->CreateItem->ObjectClass.Length > RefString.Length) { /* create item doesnt match in length */ Entry = Entry->Flink; continue; } /* now check if the object class is the same */ if (!RtlCompareUnicodeString(&CreateItemEntry->CreateItem->ObjectClass, &RefString, TRUE)) { /* found matching create item */ *OutCreateItem = CreateItemEntry; return STATUS_SUCCESS; } /* iterate to next */ Entry = Entry->Flink; } return STATUS_NOT_FOUND; } NTSTATUS NTAPI KspCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PCREATE_ITEM_ENTRY CreateItemEntry; PIO_STACK_LOCATION IoStack; PDEVICE_EXTENSION DeviceExtension; PKSIDEVICE_HEADER DeviceHeader; PKSIOBJECT_HEADER ObjectHeader; NTSTATUS Status; DPRINT("KS / CREATE\n"); /* get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); /* get device extension */ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; /* get device header */ DeviceHeader = DeviceExtension->DeviceHeader; if (IoStack->FileObject->FileName.Buffer == NULL) { /* FIXME Pnp-Issue */ DPRINT("Using reference string hack\n"); Irp->IoStatus.Information = 0; /* set return status */ Irp->IoStatus.Status = STATUS_SUCCESS; CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } if (IoStack->FileObject->RelatedFileObject != NULL) { /* request is to instantiate a pin / node / clock / allocator */ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2; /* sanity check */ ASSERT(ObjectHeader); /* find a matching a create item */ Status = FindMatchingCreateItem(&ObjectHeader->ItemList, &IoStack->FileObject->FileName, &CreateItemEntry); } else { /* request to create a filter */ Status = FindMatchingCreateItem(&DeviceHeader->ItemList, &IoStack->FileObject->FileName, &CreateItemEntry); } if (NT_SUCCESS(Status)) { /* set object create item */ KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem; /* call create function */ Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp); if (NT_SUCCESS(Status)) { /* increment create item reference count */ InterlockedIncrement(&CreateItemEntry->ReferenceCount); } return Status; } Irp->IoStatus.Information = 0; /* set return status */ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } NTSTATUS NTAPI KspDispatchIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; //PDEVICE_EXTENSION DeviceExtension; PKSIOBJECT_HEADER ObjectHeader; //PKSIDEVICE_HEADER DeviceHeader; PDRIVER_DISPATCH Dispatch; NTSTATUS Status; /* get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); /* get device extension */ //DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; /* get device header */ //DeviceHeader = DeviceExtension->DeviceHeader; ASSERT(IoStack->FileObject); /* get object header */ ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext2; if (!ObjectHeader) { /* FIXME Pnp-Issue*/ Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; /* complete and forget */ CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } /* sanity check */ ASSERT(ObjectHeader); /* store create item */ //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem; /* retrieve matching dispatch function */ switch(IoStack->MajorFunction) { case IRP_MJ_CLOSE: Dispatch = ObjectHeader->DispatchTable.Close; break; case IRP_MJ_DEVICE_CONTROL: Dispatch = ObjectHeader->DispatchTable.DeviceIoControl; break; case IRP_MJ_READ: Dispatch = ObjectHeader->DispatchTable.Read; break; case IRP_MJ_WRITE: Dispatch = ObjectHeader->DispatchTable.Write; break; case IRP_MJ_FLUSH_BUFFERS : Dispatch = ObjectHeader->DispatchTable.Flush; break; case IRP_MJ_QUERY_SECURITY: Dispatch = ObjectHeader->DispatchTable.QuerySecurity; break; case IRP_MJ_SET_SECURITY: Dispatch = ObjectHeader->DispatchTable.SetSecurity; break; case IRP_MJ_PNP: Dispatch = KsDefaultDispatchPnp; break; default: Dispatch = NULL; } /* is the request supported */ if (Dispatch) { /* now call the dispatch function */ Status = Dispatch(DeviceObject, Irp); } else { /* not supported request */ Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } /* done */ return Status; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsSetMajorFunctionHandler( IN PDRIVER_OBJECT DriverObject, IN ULONG MajorFunction) { DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction); switch ( MajorFunction ) { case IRP_MJ_CREATE: DriverObject->MajorFunction[MajorFunction] = KspCreate; break; case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_CLOSE: case IRP_MJ_READ: case IRP_MJ_WRITE: case IRP_MJ_FLUSH_BUFFERS : case IRP_MJ_QUERY_SECURITY: case IRP_MJ_SET_SECURITY: DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp; break; default: DPRINT1("NotSupported %x\n", MajorFunction); return STATUS_INVALID_PARAMETER; }; return STATUS_SUCCESS; } /* @implemented */ KSDDKAPI NTSTATUS NTAPI KsDispatchIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; PKSIDEVICE_HEADER DeviceHeader; PDEVICE_EXTENSION DeviceExtension; DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp); /* get device extension */ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; /* get device header */ DeviceHeader = DeviceExtension->DeviceHeader; /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL) { if (IoStack->MajorFunction == IRP_MJ_CREATE) { /* check internal type */ if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */ { /* AVStream client */ return IKsDevice_Create(DeviceObject, Irp); } else { /* external client (portcls) */ return KspCreate(DeviceObject, Irp); } } switch (IoStack->MajorFunction) { case IRP_MJ_CLOSE: case IRP_MJ_READ: case IRP_MJ_WRITE: case IRP_MJ_FLUSH_BUFFERS: case IRP_MJ_QUERY_SECURITY: case IRP_MJ_SET_SECURITY: case IRP_MJ_PNP: case IRP_MJ_DEVICE_CONTROL: return KspDispatchIrp(DeviceObject, Irp); default: return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } } /* dispatch power */ if (IoStack->MajorFunction == IRP_MJ_POWER) { /* check internal type */ if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */ { /* AVStream client */ return IKsDevice_Power(DeviceObject, Irp); } else { /* external client (portcls) */ return KsDefaultDispatchPower(DeviceObject, Irp); } } else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */ { /* check internal type */ if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */ { /* AVStream client */ return IKsDevice_Pnp(DeviceObject, Irp); } else { /* external client (portcls) */ return KsDefaultDispatchPnp(DeviceObject, Irp); } } else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL) { /* forward irp */ return KsDefaultForwardIrp(DeviceObject, Irp); } else { /* not supported */ return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } } /* @unimplemented */ KSDDKAPI ULONG NTAPI KsGetNodeIdFromIrp( IN PIRP Irp) { UNIMPLEMENTED; return KSFILTER_NODE; }