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

svn path=/trunk/; revision=18137
This commit is contained in:
Thomas Bluemel 2005-09-28 17:15:57 +00:00
parent 294680db96
commit 56b2e53628

View file

@ -3060,33 +3060,56 @@ NtSetInformationFile(HANDLE FileHandle,
PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation; PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
PIO_COMPLETION_CONTEXT Context; 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 else
{ {
/* Reference the Port */ if (Length < sizeof(FILE_COMPLETION_INFORMATION))
Status = ObReferenceObjectByHandle(CompletionInfo->Port,
IO_COMPLETION_MODIFY_STATE,
IoCompletionType,
PreviousMode,
(PVOID*)&Queue,
NULL);
if (NT_SUCCESS(Status))
{ {
/* Allocate the Context */ Status = STATUS_INFO_LENGTH_MISMATCH;
Context = ExAllocatePoolWithTag(PagedPool, }
sizeof(IO_COMPLETION_CONTEXT), else
TAG('I', 'o', 'C', 'p')); {
/* 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 */ if (Context != NULL)
Context->Key = CompletionInfo->Key; {
Context->Port = Queue; /* Set the Data */
FileObject->CompletionContext = Context; Context->Key = CompletionInfo->Key; /* FIXME - protect with SEH! */
Context->Port = Queue;
/* Dereference the Port now */ if (InterlockedCompareExchangePointer(&FileObject->CompletionContext,
ObDereferenceObject(Queue); 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;
}
}
} }
} }