don't dereference the port in NtSetInformationFile with information class FileComplet...
authorThomas Bluemel <thomas@reactsoft.com>
Wed, 28 Sep 2005 17:15:57 +0000 (17:15 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Wed, 28 Sep 2005 17:15:57 +0000 (17:15 +0000)
svn path=/trunk/; revision=18137

reactos/ntoskrnl/io/file.c

index e91ef44..b2d17f2 100644 (file)
@@ -3059,34 +3059,57 @@ NtSetInformationFile(HANDLE FileHandle,
         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))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+            }
+            else
             {
-                /* 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);
+                /* 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'));
+
+                    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;
+                    }
+                }
             }
         }