X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fio%2Fiocomp.c;fp=ntoskrnl%2Fio%2Fiocomp.c;h=0bb9b964eb2216190d7962fa257cf043a28c4d55;hp=21b672dbad7948c8b1a547aca558d8a17f8ec03c;hb=7c0db166f81fbe8c8b913d7f26048e337d383605;hpb=e3ed2d773259cc445c7ff8181ebd934931365328 diff --git a/ntoskrnl/io/iocomp.c b/ntoskrnl/io/iocomp.c index 21b672d..0bb9b96 100644 --- a/ntoskrnl/io/iocomp.c +++ b/ntoskrnl/io/iocomp.c @@ -11,73 +11,303 @@ /* INCLUDES *****************************************************************/ +#include #include +#include +#define NDEBUG #include +#define IOC_TAG TAG('I', 'O', 'C', 'T') + +POBJECT_TYPE ExIoCompletionType; + +NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside; + +static GENERIC_MAPPING ExIoCompletionMapping = +{ + STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE, + STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE, + IO_COMPLETION_ALL_ACCESS +}; + /* FUNCTIONS *****************************************************************/ +NTSTATUS +STDCALL +NtpCreateIoCompletion( + PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes + ) +{ + DPRINT("NtpCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; +} + +VOID STDCALL +NtpDeleteIoCompletion(PVOID ObjectBody) +{ + PKQUEUE Queue = ObjectBody; + + DPRINT("NtpDeleteIoCompletion()\n"); + + KeRundownQueue(Queue); +} + + +VOID +NtInitializeIoCompletionImplementation(VOID) +{ + ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + RtlCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion"); + + ExIoCompletionType->Tag = IOC_TAG; + ExIoCompletionType->MaxObjects = ULONG_MAX; + ExIoCompletionType->MaxHandles = ULONG_MAX; + ExIoCompletionType->TotalObjects = 0; + ExIoCompletionType->TotalHandles = 0; + ExIoCompletionType->PagedPoolCharge = 0; + ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE); + ExIoCompletionType->Mapping = &ExIoCompletionMapping; + ExIoCompletionType->Dump = NULL; + ExIoCompletionType->Open = NULL; + ExIoCompletionType->Close = NULL; + ExIoCompletionType->Delete = NtpDeleteIoCompletion; + ExIoCompletionType->Parse = NULL; + ExIoCompletionType->Security = NULL; + ExIoCompletionType->QueryName = NULL; + ExIoCompletionType->OkayToClose = NULL; + ExIoCompletionType->Create = NtpCreateIoCompletion; + ExIoCompletionType->DuplicationNotify = NULL; + + ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside, + NULL, + NULL, + 0, + sizeof(IO_COMPLETION_PACKET), + IOC_TAG, + 0); +} + + NTSTATUS STDCALL -NtCreateIoCompletion ( - OUT PHANDLE CompletionPort, - IN ACCESS_MASK DesiredAccess, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG NumberOfConcurrentThreads - ) +NtCreateIoCompletion( + OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG NumberOfConcurrentThreads + ) { - UNIMPLEMENTED; + PKQUEUE Queue; + NTSTATUS Status; + + Status = ObCreateObject(IoCompletionHandle, + DesiredAccess, + ObjectAttributes, + ExIoCompletionType, + (PVOID*)&Queue); + + if (NT_SUCCESS(Status)) + { + (void) KeInitializeQueue(Queue, NumberOfConcurrentThreads); + ObDereferenceObject(Queue); + } + + return Status; + /* + + CompletionPort = NULL OR ExistingCompletionPort + + */ + + } +/* +DesiredAccess: +ZERO +IO_COMPLETION_QUERY_STATE Query access +IO_COMPLETION_MODIFY_STATE Modify access +IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL + +ObjectAttributes +OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes +Return Value +STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or +STATUS_OBJECT_NAME_NOT_FOUND. +*/ NTSTATUS STDCALL -NtOpenIoCompletion ( - OUT PHANDLE CompletionPort, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes - ) +NtOpenIoCompletion( + OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ) { - return(STATUS_SUCCESS); + NTSTATUS Status; + + Status = ObOpenObjectByName(ObjectAttributes, + ExIoCompletionType, + NULL, + UserMode, + DesiredAccess, + NULL, + IoCompletionHandle); //<- ??? + + return Status; } NTSTATUS STDCALL -NtQueryIoCompletion ( - IN HANDLE CompletionPort, - IN ULONG CompletionKey, - OUT PIO_STATUS_BLOCK IoStatusBlock, - OUT PULONG NumberOfBytesTransferred - ) +NtQueryIoCompletion( + IN HANDLE IoCompletionHandle, + IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, + OUT PVOID IoCompletionInformation, + IN ULONG IoCompletionInformationLength, + OUT PULONG ResultLength OPTIONAL + ) { - UNIMPLEMENTED; + PKQUEUE Queue; + NTSTATUS Status; + + if (IoCompletionInformationClass != IoCompletionBasicInformation) + { + return STATUS_INVALID_INFO_CLASS; + } + if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION)) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + + Status = ObReferenceObjectByHandle( IoCompletionHandle, + IO_COMPLETION_QUERY_STATE, + ExIoCompletionType, + UserMode, + (PVOID*)&Queue, + NULL); + if (NT_SUCCESS(Status)) + { + ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->SignalState = + Queue->Header.SignalState; + + ObDereferenceObject(Queue); + + if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION); + } + + return Status; } +/* + * Dequeues an I/O completion message from an I/O completion object + */ NTSTATUS STDCALL -NtRemoveIoCompletion ( - IN HANDLE CompletionPort, - OUT PULONG CompletionKey, - OUT PIO_STATUS_BLOCK IoStatusBlock, - OUT PULONG CompletionStatus, - PLARGE_INTEGER WaitTime - ) +NtRemoveIoCompletion( + IN HANDLE IoCompletionHandle, + OUT PULONG CompletionKey, + OUT PULONG CompletionValue, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER Timeout OPTIONAL + ) { - UNIMPLEMENTED; + PKQUEUE Queue; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle( IoCompletionHandle, + IO_COMPLETION_MODIFY_STATE, + ExIoCompletionType, + UserMode, + (PVOID*)&Queue, + NULL); + if (NT_SUCCESS(Status)) + { + PIO_COMPLETION_PACKET Packet; + PLIST_ENTRY ListEntry; + + /* + Try 2 remove packet from queue. Wait (optionaly) if + no packet in queue or max num of threads allready running. + */ + ListEntry = KeRemoveQueue(Queue, UserMode, Timeout ); + + ObDereferenceObject(Queue); + + Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry); + + if (CompletionKey) *CompletionKey = Packet->Key; + if (CompletionValue) *CompletionValue = Packet->Overlapped; + if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus; + + ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet); + } + + return Status; } +/* +ASSOSIERT MED FOB's IoCompletionContext + +typedef struct _IO_COMPLETION_CONTEXT { + PVOID Port; + ULONG Key; +} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT; + +*/ + + +/* + * Queues an I/O completion message to an I/O completion object + */ NTSTATUS STDCALL -NtSetIoCompletion ( - IN HANDLE CompletionPort, - IN ULONG CompletionKey, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG NumberOfBytesToTransfer, - OUT PULONG NumberOfBytesTransferred - ) +NtSetIoCompletion( + IN HANDLE IoCompletionPortHandle, + IN ULONG CompletionKey, + IN ULONG CompletionValue, + IN NTSTATUS CompletionStatus, + IN ULONG CompletionInformation + ) { - UNIMPLEMENTED; + NTSTATUS Status; + PKQUEUE Queue; + + Status = ObReferenceObjectByHandle( IoCompletionPortHandle, + IO_COMPLETION_MODIFY_STATE, + ExIoCompletionType, + UserMode, + (PVOID*)&Queue, + NULL); + if (NT_SUCCESS(Status)) + { + PIO_COMPLETION_PACKET Packet; + + Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside); + + Packet->Key = CompletionKey; + Packet->Overlapped = CompletionValue; + Packet->IoStatus.Status = CompletionStatus; + Packet->IoStatus.Information = CompletionInformation; + + KeInsertQueue(Queue, &Packet->ListEntry); + ObDereferenceObject(Queue); + } + + return Status; }