don't dereference the port in NtSetInformationFile with information class FileCompletionInformation. The Also make setting the completion port thread-safe. This might fix bug 816 Modified: trunk/reactos/ntoskrnl/io/file.c _____
Modified: trunk/reactos/ntoskrnl/io/file.c --- trunk/reactos/ntoskrnl/io/file.c 2005-09-28 15:40:52 UTC (rev 18136) +++ trunk/reactos/ntoskrnl/io/file.c 2005-09-28 17:15:57 UTC (rev 18137) @@ -3059,34 +3059,57 @@
PVOID Queue; PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation; PIO_COMPLETION_CONTEXT Context; - - if (Length < sizeof(FILE_COMPLETION_INFORMATION)) + + if (FileObject->Flags & FO_SYNCHRONOUS_IO || FileObject->CompletionContext != NULL) { - Status = STATUS_INFO_LENGTH_MISMATCH; + Status = STATUS_INVALID_PARAMETER; } else { - /* Reference the Port */ - Status = ObReferenceObjectByHandle(CompletionInfo->Port, - IO_COMPLETION_MODIFY_STATE, - IoCompletionType, - PreviousMode, - (PVOID*)&Queue, - NULL); - if (NT_SUCCESS(Status)) + if (Length < sizeof(FILE_COMPLETION_INFORMATION)) { - /* Allocate the Context */ - Context = ExAllocatePoolWithTag(PagedPool, - sizeof(IO_COMPLETION_CONTEXT), - TAG('I', 'o', 'C', 'p')); + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + /* Reference the Port */ + Status = ObReferenceObjectByHandle(CompletionInfo->Port, /* FIXME - protect with SEH! */ + IO_COMPLETION_MODIFY_STATE, + IoCompletionType, + PreviousMode, + (PVOID*)&Queue, + NULL); + if (NT_SUCCESS(Status)) + { + /* Allocate the Context */ + Context = ExAllocatePoolWithTag(PagedPool, + sizeof(IO_COMPLETION_CONTEXT), + TAG('I', 'o', 'C', 'p'));
- /* Set the Data */ - Context->Key = CompletionInfo->Key; - Context->Port = Queue; - FileObject->CompletionContext = Context; - - /* Dereference the Port now */ - ObDereferenceObject(Queue); + if (Context != NULL) + { + /* Set the Data */ + Context->Key = CompletionInfo->Key; /* FIXME - protect with SEH! */ + Context->Port = Queue; + + if (InterlockedCompareExchangePointer(&FileObject->CompletionContext, + Context, + NULL) != NULL) + { + /* someone else set the completion port in the + meanwhile, fail */ + ExFreePool(Context); + ObDereferenceObject(Queue); + Status = STATUS_INVALID_PARAMETER; + } + } + else + { + /* Dereference the Port now */ + ObDereferenceObject(Queue); + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } } }