[NTOSKRNL]
authorPierre Schweitzer <pierre@reactos.org>
Sun, 5 Apr 2015 20:02:30 +0000 (20:02 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Sun, 5 Apr 2015 20:02:30 +0000 (20:02 +0000)
Implement the reparse points loop in IopParseDevice().

Reviewed by Thomas

svn path=/trunk/; revision=67067

reactos/ntoskrnl/include/internal/io.h
reactos/ntoskrnl/io/iomgr/file.c

index 52a15e5..b8cb589 100644 (file)
 //
 #define RD_SYMLINK_CREATE_FAILED 5
 
+//
+// Max traversal of reparse points for a single open in IoParseDevice
+//
+#define IOP_MAX_REPARSE_TRAVERSAL 0x20
+
 //
 // We can call the Ob Inlined API, it's the same thing
 //
index 44f5c34..bcb3fd1 100644 (file)
@@ -300,752 +300,761 @@ IopParseDevice(IN PVOID ParseObject,
     BOOLEAN AccessGranted, LockHeld = FALSE;
     PPRIVILEGE_SET Privileges = NULL;
     UNICODE_STRING FileString;
+    USHORT Attempt;
     IOTRACE(IO_FILE_DEBUG, "ParseObject: %p. RemainingName: %wZ\n",
             ParseObject, RemainingName);
 
-    /* Assume failure */
-    *Object = NULL;
-
-    /* Validate the open packet */
-    if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
-
-    /* Valide reparse point in case we traversed a mountpoint */
-    if (OpenPacket->TraversedMountPoint)
+    for (Attempt = 0; Attempt < IOP_MAX_REPARSE_TRAVERSAL; ++Attempt)
     {
-        /* This is a reparse point we understand */
-        ASSERT(OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT);
-
-        /* Make sure we're dealing with correct DO */
-        if (OriginalDeviceObject->DeviceType != FILE_DEVICE_DISK &&
-            OriginalDeviceObject->DeviceType != FILE_DEVICE_CD_ROM &&
-            OriginalDeviceObject->DeviceType != FILE_DEVICE_VIRTUAL_DISK &&
-            OriginalDeviceObject->DeviceType != FILE_DEVICE_TAPE)
-        {
-            OpenPacket->FinalStatus = STATUS_IO_REPARSE_DATA_INVALID;
-            return STATUS_IO_REPARSE_DATA_INVALID;
-        }
-    }
+        /* Assume failure */
+        *Object = NULL;
 
-    /* Check if we have a related file object */
-    if (OpenPacket->RelatedFileObject)
-    {
-        /* Use the related file object's device object */
-        OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject;
-    }
+        /* Validate the open packet */
+        if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
 
-    /* Validate device status */
-    Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject);
-    if (!NT_SUCCESS(Status))
-    {
-        /* We failed, return status */
-        OpenPacket->FinalStatus = Status;
-        return Status;
-    }
-
-    /* Map the generic mask and set the new mapping in the access state */
-    RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
-                      &IoFileObjectType->TypeInfo.GenericMapping);
-    RtlMapGenericMask(&AccessState->OriginalDesiredAccess,
-                      &IoFileObjectType->TypeInfo.GenericMapping);
-    SeSetAccessStateGenericMapping(AccessState,
-                                   &IoFileObjectType->TypeInfo.GenericMapping);
-    DesiredAccess = AccessState->RemainingDesiredAccess;
+        /* Valide reparse point in case we traversed a mountpoint */
+        if (OpenPacket->TraversedMountPoint)
+        {
+            /* This is a reparse point we understand */
+            ASSERT(OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT);
 
-    /* Check what kind of access checks to do */
-    if ((AccessMode != KernelMode) ||
-        (OpenPacket->Options & IO_FORCE_ACCESS_CHECK))
-    {
-        /* Call is from user-mode or kernel is forcing checks */
-        CheckMode = UserMode;
-    }
-    else
-    {
-        /* Call is from the kernel */
-        CheckMode = KernelMode;
-    }
+            /* Make sure we're dealing with correct DO */
+            if (OriginalDeviceObject->DeviceType != FILE_DEVICE_DISK &&
+                OriginalDeviceObject->DeviceType != FILE_DEVICE_CD_ROM &&
+                OriginalDeviceObject->DeviceType != FILE_DEVICE_VIRTUAL_DISK &&
+                OriginalDeviceObject->DeviceType != FILE_DEVICE_TAPE)
+            {
+                OpenPacket->FinalStatus = STATUS_IO_REPARSE_DATA_INVALID;
+                return STATUS_IO_REPARSE_DATA_INVALID;
+            }
+        }
 
-    /* Check privilege for backup or restore operation */
-    IopCheckBackupRestorePrivilege(AccessState,
-                                   &OpenPacket->CreateOptions,
-                                   CheckMode,
-                                   OpenPacket->Disposition);
+        /* Check if we have a related file object */
+        if (OpenPacket->RelatedFileObject)
+        {
+            /* Use the related file object's device object */
+            OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject;
+        }
 
-    /* Check if we are re-parsing */
-    if (((OpenPacket->Override) && !(RemainingName->Length)) ||
-        (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED))
-    {
-        /* Get granted access from the last call */
-        DesiredAccess |= AccessState->PreviouslyGrantedAccess;
-    }
+        /* Validate device status */
+        Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject);
+        if (!NT_SUCCESS(Status))
+        {
+            /* We failed, return status */
+            OpenPacket->FinalStatus = Status;
+            return Status;
+        }
 
-    /* Check if this is a volume open */
-    if ((OpenPacket->RelatedFileObject) &&
-        (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) &&
-        !(RemainingName->Length))
-    {
-        /* It is */
-        VolumeOpen = TRUE;
-    }
+        /* Map the generic mask and set the new mapping in the access state */
+        RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
+                          &IoFileObjectType->TypeInfo.GenericMapping);
+        RtlMapGenericMask(&AccessState->OriginalDesiredAccess,
+                          &IoFileObjectType->TypeInfo.GenericMapping);
+        SeSetAccessStateGenericMapping(AccessState,
+                                       &IoFileObjectType->TypeInfo.GenericMapping);
+        DesiredAccess = AccessState->RemainingDesiredAccess;
 
-    /* Now check if we need access checks */
-    if (((AccessMode != KernelMode) ||
-         (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) &&
-        (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) &&
-        !(OpenPacket->Override))
-    {
-        KeEnterCriticalRegion();
-        ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
+        /* Check what kind of access checks to do */
+        if ((AccessMode != KernelMode) ||
+            (OpenPacket->Options & IO_FORCE_ACCESS_CHECK))
+        {
+            /* Call is from user-mode or kernel is forcing checks */
+            CheckMode = UserMode;
+        }
+        else
+        {
+            /* Call is from the kernel */
+            CheckMode = KernelMode;
+        }
 
-        /* Check if a device object is being parsed  */
-        if (!RemainingName->Length)
-        {
-            /* Lock the subject context */
-            SeLockSubjectContext(&AccessState->SubjectSecurityContext);
-            LockHeld = TRUE;
-
-            /* Do access check */
-            AccessGranted = SeAccessCheck(OriginalDeviceObject->
-                                          SecurityDescriptor,
-                                          &AccessState->SubjectSecurityContext,
-                                          LockHeld,
-                                          DesiredAccess,
-                                          0,
-                                          &Privileges,
-                                          &IoFileObjectType->
-                                          TypeInfo.GenericMapping,
-                                          UserMode,
-                                          &GrantedAccess,
-                                          &Status);
-            if (Privileges)
-            {
-                /* Append and free the privileges */
-                SeAppendPrivileges(AccessState, Privileges);
-                SeFreePrivileges(Privileges);
-            }
+        /* Check privilege for backup or restore operation */
+        IopCheckBackupRestorePrivilege(AccessState,
+                                       &OpenPacket->CreateOptions,
+                                       CheckMode,
+                                       OpenPacket->Disposition);
 
-            /* Check if we got access */
-            if (AccessGranted)
-            {
-                /* Update access state */
-                AccessState->PreviouslyGrantedAccess |= GrantedAccess;
-                AccessState->RemainingDesiredAccess &= ~(GrantedAccess &
-                                                         MAXIMUM_ALLOWED);
-                OpenPacket->Override= TRUE;
-            }
+        /* Check if we are re-parsing */
+        if (((OpenPacket->Override) && !(RemainingName->Length)) ||
+            (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED))
+        {
+            /* Get granted access from the last call */
+            DesiredAccess |= AccessState->PreviouslyGrantedAccess;
+        }
 
-            FileString.Length = 8;
-            FileString.MaximumLength = 8;
-            FileString.Buffer = L"File";
-
-            /* Do Audit/Alarm for open operation */
-            SeOpenObjectAuditAlarm(&FileString,
-                                   OriginalDeviceObject,
-                                   CompleteName,
-                                   OriginalDeviceObject->SecurityDescriptor,
-                                   AccessState,
-                                   FALSE,
-                                   AccessGranted,
-                                   UserMode,
-                                   &AccessState->GenerateOnClose);
+        /* Check if this is a volume open */
+        if ((OpenPacket->RelatedFileObject) &&
+            (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) &&
+            !(RemainingName->Length))
+        {
+            /* It is */
+            VolumeOpen = TRUE;
         }
-        else
+
+        /* Now check if we need access checks */
+        if (((AccessMode != KernelMode) ||
+             (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) &&
+            (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) &&
+            !(OpenPacket->Override))
         {
-            /* Check if we need to do traverse validation */
-            if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) ||
-                ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) ||
-                 (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM)))
+            KeEnterCriticalRegion();
+            ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
+
+            /* Check if a device object is being parsed  */
+            if (!RemainingName->Length)
             {
-                /* Check if this is a restricted token */
-                if (!(AccessState->Flags & TOKEN_IS_RESTRICTED))
+                /* Lock the subject context */
+                SeLockSubjectContext(&AccessState->SubjectSecurityContext);
+                LockHeld = TRUE;
+
+                /* Do access check */
+                AccessGranted = SeAccessCheck(OriginalDeviceObject->
+                                              SecurityDescriptor,
+                                              &AccessState->SubjectSecurityContext,
+                                              LockHeld,
+                                              DesiredAccess,
+                                              0,
+                                              &Privileges,
+                                              &IoFileObjectType->
+                                              TypeInfo.GenericMapping,
+                                              UserMode,
+                                              &GrantedAccess,
+                                              &Status);
+                if (Privileges)
                 {
-                    /* Do the FAST traverse check */
-                    AccessGranted = SeFastTraverseCheck(OriginalDeviceObject->SecurityDescriptor,
-                                                        AccessState,
-                                                        FILE_TRAVERSE,
-                                                        UserMode);
+                    /* Append and free the privileges */
+                    SeAppendPrivileges(AccessState, Privileges);
+                    SeFreePrivileges(Privileges);
                 }
-                else
+
+                /* Check if we got access */
+                if (AccessGranted)
                 {
-                    /* Fail */
-                    AccessGranted = FALSE;
+                    /* Update access state */
+                    AccessState->PreviouslyGrantedAccess |= GrantedAccess;
+                    AccessState->RemainingDesiredAccess &= ~(GrantedAccess &
+                                                             MAXIMUM_ALLOWED);
+                    OpenPacket->Override= TRUE;
                 }
 
-                /* Check if we failed to get access */
-                if (!AccessGranted)
+                FileString.Length = 8;
+                FileString.MaximumLength = 8;
+                FileString.Buffer = L"File";
+
+                /* Do Audit/Alarm for open operation */
+                SeOpenObjectAuditAlarm(&FileString,
+                                       OriginalDeviceObject,
+                                       CompleteName,
+                                       OriginalDeviceObject->SecurityDescriptor,
+                                       AccessState,
+                                       FALSE,
+                                       AccessGranted,
+                                       UserMode,
+                                       &AccessState->GenerateOnClose);
+            }
+            else
+            {
+                /* Check if we need to do traverse validation */
+                if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) ||
+                    ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) ||
+                     (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM)))
                 {
-                    /* Lock the subject context */
-                    SeLockSubjectContext(&AccessState->SubjectSecurityContext);
-                    LockHeld = TRUE;
+                    /* Check if this is a restricted token */
+                    if (!(AccessState->Flags & TOKEN_IS_RESTRICTED))
+                    {
+                        /* Do the FAST traverse check */
+                        AccessGranted = SeFastTraverseCheck(OriginalDeviceObject->SecurityDescriptor,
+                                                            AccessState,
+                                                            FILE_TRAVERSE,
+                                                            UserMode);
+                    }
+                    else
+                    {
+                        /* Fail */
+                        AccessGranted = FALSE;
+                    }
 
-                    /* Do access check */
-                    AccessGranted = SeAccessCheck(OriginalDeviceObject->
-                                                  SecurityDescriptor,
-                                                  &AccessState->SubjectSecurityContext,
-                                                  LockHeld,
-                                                  FILE_TRAVERSE,
-                                                  0,
-                                                  &Privileges,
-                                                  &IoFileObjectType->
-                                                  TypeInfo.GenericMapping,
-                                                  UserMode,
-                                                  &GrantedAccess,
-                                                  &Status);
-                    if (Privileges)
+                    /* Check if we failed to get access */
+                    if (!AccessGranted)
                     {
-                        /* Append and free the privileges */
-                        SeAppendPrivileges(AccessState, Privileges);
-                        SeFreePrivileges(Privileges);
+                        /* Lock the subject context */
+                        SeLockSubjectContext(&AccessState->SubjectSecurityContext);
+                        LockHeld = TRUE;
+
+                        /* Do access check */
+                        AccessGranted = SeAccessCheck(OriginalDeviceObject->
+                                                      SecurityDescriptor,
+                                                      &AccessState->SubjectSecurityContext,
+                                                      LockHeld,
+                                                      FILE_TRAVERSE,
+                                                      0,
+                                                      &Privileges,
+                                                      &IoFileObjectType->
+                                                      TypeInfo.GenericMapping,
+                                                      UserMode,
+                                                      &GrantedAccess,
+                                                      &Status);
+                        if (Privileges)
+                        {
+                            /* Append and free the privileges */
+                            SeAppendPrivileges(AccessState, Privileges);
+                            SeFreePrivileges(Privileges);
+                        }
                     }
+
+                    /* FIXME: Do Audit/Alarm for traverse check */
+                }
+                else
+                {
+                    /* Access automatically granted */
+                    AccessGranted = TRUE;
                 }
+            }
 
-                /* FIXME: Do Audit/Alarm for traverse check */
+            ExReleaseResourceLite(&IopSecurityResource);
+            KeLeaveCriticalRegion();
+
+            /* Check if we hold the lock */
+            if (LockHeld)
+            {
+                /* Release it */
+                SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
             }
-            else
+
+            /* Check if access failed */
+            if (!AccessGranted)
             {
-                /* Access automatically granted */
-                AccessGranted = TRUE;
+                /* Dereference the device and fail */
+                DPRINT1("Traverse access failed!\n");
+                IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+                return STATUS_ACCESS_DENIED;
             }
         }
 
-        ExReleaseResourceLite(&IopSecurityResource);
-        KeLeaveCriticalRegion();
+        /* Check if we can simply use a dummy file */
+        UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly));
 
-        /* Check if we hold the lock */
-        if (LockHeld)
-        {
-            /* Release it */
-            SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
+#if 1
+        /* FIXME: Small hack still exists, have to check why...
+         * This is triggered multiple times by usetup and then once per boot.
+         */
+        if (ExpInTextModeSetup &&
+            !(DirectOpen) &&
+            !(RemainingName->Length) &&
+            !(OpenPacket->RelatedFileObject) &&
+            ((wcsstr(CompleteName->Buffer, L"Harddisk")) ||
+            (wcsstr(CompleteName->Buffer, L"Floppy"))) &&
+            !(UseDummyFile))
+        {
+            DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
+            DesiredAccess & ~(SYNCHRONIZE |
+                              FILE_READ_ATTRIBUTES |
+                              READ_CONTROL |
+                              ACCESS_SYSTEM_SECURITY |
+                              WRITE_OWNER |
+                              WRITE_DAC));
+            DirectOpen = TRUE;
         }
+#endif
 
-        /* Check if access failed */
-        if (!AccessGranted)
+        /* Check if this is a direct open */
+        if (!(RemainingName->Length) &&
+            !(OpenPacket->RelatedFileObject) &&
+            ((DesiredAccess & ~(SYNCHRONIZE |
+                                FILE_READ_ATTRIBUTES |
+                                READ_CONTROL |
+                                ACCESS_SYSTEM_SECURITY |
+                                WRITE_OWNER |
+                                WRITE_DAC)) == 0) &&
+            !(UseDummyFile))
         {
-            /* Dereference the device and fail */
-            DPRINT1("Traverse access failed!\n");
-            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
-            return STATUS_ACCESS_DENIED;
+            /* Remember this for later */
+            DirectOpen = TRUE;
         }
-    }
-
-    /* Check if we can simply use a dummy file */
-    UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly));
-
-#if 1
-    /* FIXME: Small hack still exists, have to check why...
-     * This is triggered multiple times by usetup and then once per boot.
-     */
-    if (ExpInTextModeSetup &&
-        !(DirectOpen) &&
-        !(RemainingName->Length) &&
-        !(OpenPacket->RelatedFileObject) &&
-        ((wcsstr(CompleteName->Buffer, L"Harddisk")) ||
-        (wcsstr(CompleteName->Buffer, L"Floppy"))) &&
-        !(UseDummyFile))
-    {
-        DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
-        DesiredAccess & ~(SYNCHRONIZE |
-                          FILE_READ_ATTRIBUTES |
-                          READ_CONTROL |
-                          ACCESS_SYSTEM_SECURITY |
-                          WRITE_OWNER |
-                          WRITE_DAC));
-        DirectOpen = TRUE;
-    }
-#endif
 
-    /* Check if this is a direct open */
-    if (!(RemainingName->Length) &&
-        !(OpenPacket->RelatedFileObject) &&
-        ((DesiredAccess & ~(SYNCHRONIZE |
-                            FILE_READ_ATTRIBUTES |
-                            READ_CONTROL |
-                            ACCESS_SYSTEM_SECURITY |
-                            WRITE_OWNER |
-                            WRITE_DAC)) == 0) &&
-        !(UseDummyFile))
-    {
-        /* Remember this for later */
-        DirectOpen = TRUE;
-    }
+        /* Check if we have a related FO that wasn't a direct open */
+        if ((OpenPacket->RelatedFileObject) &&
+            !(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN))
+        {
+            /* The device object is the one we were given */
+            DeviceObject = ParseObject;
 
-    /* Check if we have a related FO that wasn't a direct open */
-    if ((OpenPacket->RelatedFileObject) &&
-        !(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN))
-    {
-        /* The device object is the one we were given */
-        DeviceObject = ParseObject;
+            /* Check if the related FO had a VPB */
+            if (OpenPacket->RelatedFileObject->Vpb)
+            {
+                /* Yes, remember it */
+                Vpb = OpenPacket->RelatedFileObject->Vpb;
 
-        /* Check if the related FO had a VPB */
-        if (OpenPacket->RelatedFileObject->Vpb)
+                /* Reference it */
+                InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
+            }
+        }
+        else
         {
-            /* Yes, remember it */
-            Vpb = OpenPacket->RelatedFileObject->Vpb;
+            /* The device object is the one we were given */
+            DeviceObject = OriginalDeviceObject;
 
-            /* Reference it */
-            InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
+            /* Check if it has a VPB */
+            if ((OriginalDeviceObject->Vpb) && !(DirectOpen))
+            {
+                /* Check if the VPB is mounted, and mount it */
+                Vpb = IopCheckVpbMounted(OpenPacket,
+                                         OriginalDeviceObject,
+                                         RemainingName,
+                                         &Status);
+                if (!Vpb) return Status;
+
+                /* Get the VPB's device object */
+                DeviceObject = Vpb->DeviceObject;
+            }
+
+            /* Check if there's an attached device */
+            if (DeviceObject->AttachedDevice)
+            {
+                /* Get the attached device */
+                DeviceObject = IoGetAttachedDevice(DeviceObject);
+            }
         }
-    }
-    else
-    {
-        /* The device object is the one we were given */
-        DeviceObject = OriginalDeviceObject;
 
-        /* Check if it has a VPB */
-        if ((OriginalDeviceObject->Vpb) && !(DirectOpen))
+        /* If we traversed a mount point, reset the information */
+        if (OpenPacket->TraversedMountPoint)
         {
-            /* Check if the VPB is mounted, and mount it */
-            Vpb = IopCheckVpbMounted(OpenPacket,
-                                     OriginalDeviceObject,
-                                     RemainingName,
-                                     &Status);
-            if (!Vpb) return Status;
-
-            /* Get the VPB's device object */
-            DeviceObject = Vpb->DeviceObject;
+            OpenPacket->TraversedMountPoint = FALSE;
         }
 
-        /* Check if there's an attached device */
-        if (DeviceObject->AttachedDevice)
+        /* Check if this is a secure FSD */
+        if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) &&
+            ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
+            (!VolumeOpen))
         {
-            /* Get the attached device */
-            DeviceObject = IoGetAttachedDevice(DeviceObject);
+            DPRINT("Fix Secure FSD support!!!\n");
         }
-    }
-
-    /* If we traversed a mount point, reset the information */
-    if (OpenPacket->TraversedMountPoint)
-    {
-        OpenPacket->TraversedMountPoint = FALSE;
-    }
-
-    /* Check if this is a secure FSD */
-    if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) &&
-        ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
-        (!VolumeOpen))
-    {
-        DPRINT("Fix Secure FSD support!!!\n");
-    }
 
-    /* Allocate the IRP */
-    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-    if (!Irp)
-    {
-        /* Dereference the device and VPB, then fail */
-        IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
-        if (Vpb) IopDereferenceVpbAndFree(Vpb);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* Now set the IRP data */
-    Irp->RequestorMode = AccessMode;
-    Irp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API | IRP_DEFER_IO_COMPLETION;
-    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-    Irp->UserIosb = &IoStatusBlock;
-    Irp->MdlAddress = NULL;
-    Irp->PendingReturned = FALSE;
-    Irp->UserEvent = NULL;
-    Irp->Cancel = FALSE;
-    Irp->CancelRoutine = NULL;
-    Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
-
-    /* Setup the security context */
-    SecurityContext.SecurityQos = SecurityQos;
-    SecurityContext.AccessState = AccessState;
-    SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess;
-    SecurityContext.FullCreateOptions = OpenPacket->CreateOptions;
-
-    /* Get the I/O Stack location */
-    StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
-    StackLoc->Control = 0;
-
-    /* Check what kind of file this is */
-    switch (OpenPacket->CreateFileType)
-    {
-        /* Normal file */
-        case CreateFileTypeNone:
-
-            /* Set the major function and EA Length */
-            StackLoc->MajorFunction = IRP_MJ_CREATE;
-            StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength;
-
-            /* Set the flags */
-            StackLoc->Flags = (UCHAR)OpenPacket->Options;
-            StackLoc->Flags |= !(Attributes & OBJ_CASE_INSENSITIVE) ? SL_CASE_SENSITIVE: 0;
-            break;
+        /* Allocate the IRP */
+        Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
+        if (!Irp)
+        {
+            /* Dereference the device and VPB, then fail */
+            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+            if (Vpb) IopDereferenceVpbAndFree(Vpb);
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
 
-        /* Named pipe */
-        case CreateFileTypeNamedPipe:
+        /* Now set the IRP data */
+        Irp->RequestorMode = AccessMode;
+        Irp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API | IRP_DEFER_IO_COMPLETION;
+        Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+        Irp->UserIosb = &IoStatusBlock;
+        Irp->MdlAddress = NULL;
+        Irp->PendingReturned = FALSE;
+        Irp->UserEvent = NULL;
+        Irp->Cancel = FALSE;
+        Irp->CancelRoutine = NULL;
+        Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
+
+        /* Setup the security context */
+        SecurityContext.SecurityQos = SecurityQos;
+        SecurityContext.AccessState = AccessState;
+        SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess;
+        SecurityContext.FullCreateOptions = OpenPacket->CreateOptions;
+
+        /* Get the I/O Stack location */
+        StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
+        StackLoc->Control = 0;
+
+        /* Check what kind of file this is */
+        switch (OpenPacket->CreateFileType)
+        {
+            /* Normal file */
+            case CreateFileTypeNone:
+
+                /* Set the major function and EA Length */
+                StackLoc->MajorFunction = IRP_MJ_CREATE;
+                StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength;
+
+                /* Set the flags */
+                StackLoc->Flags = (UCHAR)OpenPacket->Options;
+                StackLoc->Flags |= !(Attributes & OBJ_CASE_INSENSITIVE) ? SL_CASE_SENSITIVE: 0;
+                break;
+
+            /* Named pipe */
+            case CreateFileTypeNamedPipe:
+
+                /* Set the named pipe MJ and set the parameters */
+                StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
+                StackLoc->Parameters.CreatePipe.Parameters = OpenPacket->ExtraCreateParameters;
+                break;
+
+            /* Mailslot */
+            case CreateFileTypeMailslot:
+
+                /* Set the mailslot MJ and set the parameters */
+                StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
+                StackLoc->Parameters.CreateMailslot.Parameters = OpenPacket->ExtraCreateParameters;
+                break;
+        }
+
+        /* Set the common data */
+        Irp->Overlay.AllocationSize = OpenPacket->AllocationSize;
+        Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer;
+        StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) |
+                                              (OpenPacket->CreateOptions &
+                                               0xFFFFFF);
+        StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes;
+        StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess;
+        StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
+
+        /* Check if we really need to create an object */
+        if (!UseDummyFile)
+        {
+            /* Create the actual file object */
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       NULL,
+                                       Attributes,
+                                       NULL,
+                                       NULL);
+            Status = ObCreateObject(KernelMode,
+                                    IoFileObjectType,
+                                    &ObjectAttributes,
+                                    AccessMode,
+                                    NULL,
+                                    sizeof(FILE_OBJECT),
+                                    0,
+                                    0,
+                                    (PVOID*)&FileObject);
+            if (!NT_SUCCESS(Status))
+            {
+                /* Create failed, free the IRP */
+                IoFreeIrp(Irp);
 
-            /* Set the named pipe MJ and set the parameters */
-            StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
-            StackLoc->Parameters.CreatePipe.Parameters = OpenPacket->ExtraCreateParameters;
-            break;
+                /* Dereference the device and VPB */
+                IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+                if (Vpb) IopDereferenceVpbAndFree(Vpb);
 
-        /* Mailslot */
-        case CreateFileTypeMailslot:
+                /* We failed, return status */
+                OpenPacket->FinalStatus = Status;
+                return Status;
+            }
 
-            /* Set the mailslot MJ and set the parameters */
-            StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
-            StackLoc->Parameters.CreateMailslot.Parameters = OpenPacket->ExtraCreateParameters;
-            break;
-    }
+            /* Clear the file object */
+            RtlZeroMemory(FileObject, sizeof(FILE_OBJECT));
 
-    /* Set the common data */
-    Irp->Overlay.AllocationSize = OpenPacket->AllocationSize;
-    Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer;
-    StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) |
-                                          (OpenPacket->CreateOptions &
-                                           0xFFFFFF);
-    StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes;
-    StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess;
-    StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
+            /* Check if this is Synch I/O */
+            if (OpenPacket->CreateOptions &
+                (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
+            {
+                /* Set the synch flag */
+                FileObject->Flags |= FO_SYNCHRONOUS_IO;
 
-    /* Check if we really need to create an object */
-    if (!UseDummyFile)
-    {
-        /* Create the actual file object */
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   NULL,
-                                   Attributes,
-                                   NULL,
-                                   NULL);
-        Status = ObCreateObject(KernelMode,
-                                IoFileObjectType,
-                                &ObjectAttributes,
-                                AccessMode,
-                                NULL,
-                                sizeof(FILE_OBJECT),
-                                0,
-                                0,
-                                (PVOID*)&FileObject);
-        if (!NT_SUCCESS(Status))
-        {
-            /* Create failed, free the IRP */
-            IoFreeIrp(Irp);
+                /* Check if it's also alertable */
+                if (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
+                {
+                    /* It is, set the alertable flag */
+                    FileObject->Flags |= FO_ALERTABLE_IO;
+                }
+            }
 
-            /* Dereference the device and VPB */
-            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
-            if (Vpb) IopDereferenceVpbAndFree(Vpb);
+            /* Check if this is synch I/O */
+            if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+            {
+                /* Initialize the event */
+                KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE);
+            }
 
-            /* We failed, return status */
-            OpenPacket->FinalStatus = Status;
-            return Status;
-        }
+            /* Check if the caller requested no intermediate buffering */
+            if (OpenPacket->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
+            {
+                /* Set the correct flag for the FSD to read */
+                FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+            }
 
-        /* Clear the file object */
-        RtlZeroMemory(FileObject, sizeof(FILE_OBJECT));
+            /* Check if the caller requested write through support */
+            if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH)
+            {
+                /* Set the correct flag for the FSD to read */
+                FileObject->Flags |= FO_WRITE_THROUGH;
+            }
 
-        /* Check if this is Synch I/O */
-        if (OpenPacket->CreateOptions &
-            (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
-        {
-            /* Set the synch flag */
-            FileObject->Flags |= FO_SYNCHRONOUS_IO;
+            /* Check if the caller says the file will be only read sequentially */
+            if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY)
+            {
+                /* Set the correct flag for the FSD to read */
+                FileObject->Flags |= FO_SEQUENTIAL_ONLY;
+            }
 
-            /* Check if it's also alertable */
-            if (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
+            /* Check if the caller believes the file will be only read randomly */
+            if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS)
             {
-                /* It is, set the alertable flag */
-                FileObject->Flags |= FO_ALERTABLE_IO;
+                /* Set the correct flag for the FSD to read */
+                FileObject->Flags |= FO_RANDOM_ACCESS;
             }
         }
-
-        /* Check if this is synch I/O */
-        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+        else
         {
-            /* Initialize the event */
-            KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE);
-        }
+            /* Use the dummy object instead */
+            LocalFileObject = OpenPacket->LocalFileObject;
+            RtlZeroMemory(LocalFileObject, sizeof(DUMMY_FILE_OBJECT));
 
-        /* Check if the caller requested no intermediate buffering */
-        if (OpenPacket->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
-        {
-            /* Set the correct flag for the FSD to read */
-            FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+            /* Set it up */
+            FileObject = (PFILE_OBJECT)&LocalFileObject->ObjectHeader.Body;
+            LocalFileObject->ObjectHeader.Type = IoFileObjectType;
+            LocalFileObject->ObjectHeader.PointerCount = 1;
         }
 
-        /* Check if the caller requested write through support */
-        if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH)
-        {
-            /* Set the correct flag for the FSD to read */
-            FileObject->Flags |= FO_WRITE_THROUGH;
-        }
+        /* Setup the file header */
+        FileObject->Type = IO_TYPE_FILE;
+        FileObject->Size = sizeof(FILE_OBJECT);
+        FileObject->RelatedFileObject = OpenPacket->RelatedFileObject;
+        FileObject->DeviceObject = OriginalDeviceObject;
 
-        /* Check if the caller says the file will be only read sequentially */
-        if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY)
-        {
-            /* Set the correct flag for the FSD to read */
-            FileObject->Flags |= FO_SEQUENTIAL_ONLY;
-        }
+        /* Check if this is a direct device open */
+        if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
 
-        /* Check if the caller believes the file will be only read randomly */
-        if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS)
+        /* Check if the caller wants case sensitivity */
+        if (!(Attributes & OBJ_CASE_INSENSITIVE))
         {
-            /* Set the correct flag for the FSD to read */
-            FileObject->Flags |= FO_RANDOM_ACCESS;
+            /* Tell the driver about it */
+            FileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
         }
-    }
-    else
-    {
-        /* Use the dummy object instead */
-        LocalFileObject = OpenPacket->LocalFileObject;
-        RtlZeroMemory(LocalFileObject, sizeof(DUMMY_FILE_OBJECT));
-
-        /* Set it up */
-        FileObject = (PFILE_OBJECT)&LocalFileObject->ObjectHeader.Body;
-        LocalFileObject->ObjectHeader.Type = IoFileObjectType;
-        LocalFileObject->ObjectHeader.PointerCount = 1;
-    }
-
-    /* Setup the file header */
-    FileObject->Type = IO_TYPE_FILE;
-    FileObject->Size = sizeof(FILE_OBJECT);
-    FileObject->RelatedFileObject = OpenPacket->RelatedFileObject;
-    FileObject->DeviceObject = OriginalDeviceObject;
-
-    /* Check if this is a direct device open */
-    if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
 
-    /* Check if the caller wants case sensitivity */
-    if (!(Attributes & OBJ_CASE_INSENSITIVE))
-    {
-        /* Tell the driver about it */
-        FileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
-    }
-
-    /* Now set the file object */
-    Irp->Tail.Overlay.OriginalFileObject = FileObject;
-    StackLoc->FileObject = FileObject;
-
-    /* Check if the file object has a name */
-    if (RemainingName->Length)
-    {
-        /* Setup the unicode string */
-        FileObject->FileName.MaximumLength = RemainingName->Length +
-                                             sizeof(WCHAR);
-        FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool,
-                                                            FileObject->
-                                                            FileName.
-                                                            MaximumLength,
-                                                            TAG_IO_NAME);
-        if (!FileObject->FileName.Buffer)
-        {
-            /* Failed to allocate the name, free the IRP */
-            IoFreeIrp(Irp);
+        /* Now set the file object */
+        Irp->Tail.Overlay.OriginalFileObject = FileObject;
+        StackLoc->FileObject = FileObject;
+
+        /* Check if the file object has a name */
+        if (RemainingName->Length)
+        {
+            /* Setup the unicode string */
+            FileObject->FileName.MaximumLength = RemainingName->Length +
+                                                 sizeof(WCHAR);
+            FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                                                FileObject->
+                                                                FileName.
+                                                                MaximumLength,
+                                                                TAG_IO_NAME);
+            if (!FileObject->FileName.Buffer)
+            {
+                /* Failed to allocate the name, free the IRP */
+                IoFreeIrp(Irp);
 
-            /* Dereference the device object and VPB */
-            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
-            if (Vpb) IopDereferenceVpbAndFree(Vpb);
+                /* Dereference the device object and VPB */
+                IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+                if (Vpb) IopDereferenceVpbAndFree(Vpb);
 
-            /* Clear the FO and dereference it */
-            FileObject->DeviceObject = NULL;
-            if (!UseDummyFile) ObDereferenceObject(FileObject);
+                /* Clear the FO and dereference it */
+                FileObject->DeviceObject = NULL;
+                if (!UseDummyFile) ObDereferenceObject(FileObject);
 
-            /* Fail */
-            return STATUS_INSUFFICIENT_RESOURCES;
+                /* Fail */
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
         }
-    }
 
-    /* Copy the name */
-    RtlCopyUnicodeString(&FileObject->FileName, RemainingName);
+        /* Copy the name */
+        RtlCopyUnicodeString(&FileObject->FileName, RemainingName);
 
-    /* Initialize the File Object event and set the FO */
-    KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
-    OpenPacket->FileObject = FileObject;
+        /* Initialize the File Object event and set the FO */
+        KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
+        OpenPacket->FileObject = FileObject;
 
-    /* Queue the IRP and call the driver */
-    IopQueueIrpToThread(Irp);
-    Status = IoCallDriver(DeviceObject, Irp);
-    if (Status == STATUS_PENDING)
-    {
-        /* Wait for the driver to complete the create */
-        KeWaitForSingleObject(&FileObject->Event,
-                              Executive,
-                              KernelMode,
-                              FALSE,
-                              NULL);
-
-        /* Get the new status */
-        Status = IoStatusBlock.Status;
-    }
-    else
-    {
-        /* We'll have to complete it ourselves */
-        ASSERT(!Irp->PendingReturned);
-        ASSERT(!Irp->MdlAddress);
+        /* Queue the IRP and call the driver */
+        IopQueueIrpToThread(Irp);
+        Status = IoCallDriver(DeviceObject, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            /* Wait for the driver to complete the create */
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive,
+                                  KernelMode,
+                                  FALSE,
+                                  NULL);
 
-        /* Handle name change if required */
-        if (Status == STATUS_REPARSE)
+            /* Get the new status */
+            Status = IoStatusBlock.Status;
+        }
+        else
         {
-            /* Check this is a mount point */
-            if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)
+            /* We'll have to complete it ourselves */
+            ASSERT(!Irp->PendingReturned);
+            ASSERT(!Irp->MdlAddress);
+
+            /* Handle name change if required */
+            if (Status == STATUS_REPARSE)
             {
-                PREPARSE_DATA_BUFFER ReparseData;
+                /* Check this is a mount point */
+                if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)
+                {
+                    PREPARSE_DATA_BUFFER ReparseData;
 
-                /* Reparse point attributes were passed by the driver in the auxiliary buffer */
-                ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
-                ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
+                    /* Reparse point attributes were passed by the driver in the auxiliary buffer */
+                    ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
+                    ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
 
-                ASSERT(ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
-                ASSERT(ReparseData->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
-                ASSERT(ReparseData->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+                    ASSERT(ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
+                    ASSERT(ReparseData->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+                    ASSERT(ReparseData->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
 
-                IopDoNameTransmogrify(Irp, FileObject, ReparseData);
+                    IopDoNameTransmogrify(Irp, FileObject, ReparseData);
+                }
             }
-        }
 
-        /* Completion happens at APC_LEVEL */
-        KeRaiseIrql(APC_LEVEL, &OldIrql);
+            /* Completion happens at APC_LEVEL */
+            KeRaiseIrql(APC_LEVEL, &OldIrql);
 
-        /* Get the new I/O Status block ourselves */
-        IoStatusBlock = Irp->IoStatus;
-        Status = IoStatusBlock.Status;
+            /* Get the new I/O Status block ourselves */
+            IoStatusBlock = Irp->IoStatus;
+            Status = IoStatusBlock.Status;
 
-        /* Manually signal the even, we can't have any waiters */
-        FileObject->Event.Header.SignalState = 1;
+            /* Manually signal the even, we can't have any waiters */
+            FileObject->Event.Header.SignalState = 1;
 
-        /* Now that we've signaled the events, de-associate the IRP */
-        IopUnQueueIrpFromThread(Irp);
+            /* Now that we've signaled the events, de-associate the IRP */
+            IopUnQueueIrpFromThread(Irp);
 
-        /* Check if the IRP had an input buffer */
-        if ((Irp->Flags & IRP_BUFFERED_IO) &&
-            (Irp->Flags & IRP_DEALLOCATE_BUFFER))
-        {
-            /* Free it. A driver might've tacked one on */
-            ExFreePool(Irp->AssociatedIrp.SystemBuffer);
-        }
+            /* Check if the IRP had an input buffer */
+            if ((Irp->Flags & IRP_BUFFERED_IO) &&
+                (Irp->Flags & IRP_DEALLOCATE_BUFFER))
+            {
+                /* Free it. A driver might've tacked one on */
+                ExFreePool(Irp->AssociatedIrp.SystemBuffer);
+            }
 
-        /* Free the IRP and bring the IRQL back down */
-        IoFreeIrp(Irp);
-        KeLowerIrql(OldIrql);
-    }
+            /* Free the IRP and bring the IRQL back down */
+            IoFreeIrp(Irp);
+            KeLowerIrql(OldIrql);
+        }
 
-    /* Copy the I/O Status */
-    OpenPacket->Information = IoStatusBlock.Information;
+        /* Copy the I/O Status */
+        OpenPacket->Information = IoStatusBlock.Information;
 
-    /* The driver failed to create the file */
-    if (!NT_SUCCESS(Status))
-    {
-        /* Check if we have a name */
-        if (FileObject->FileName.Length)
+        /* The driver failed to create the file */
+        if (!NT_SUCCESS(Status))
         {
-            /* Free it */
-            ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME);
-            FileObject->FileName.Length = 0;
-        }
+            /* Check if we have a name */
+            if (FileObject->FileName.Length)
+            {
+                /* Free it */
+                ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME);
+                FileObject->FileName.Length = 0;
+            }
 
-        /* Clear its device object */
-        FileObject->DeviceObject = NULL;
+            /* Clear its device object */
+            FileObject->DeviceObject = NULL;
 
-        /* Save this now because the FO might go away */
-        OpenCancelled = FileObject->Flags & FO_FILE_OPEN_CANCELLED ?
-                        TRUE : FALSE;
+            /* Save this now because the FO might go away */
+            OpenCancelled = FileObject->Flags & FO_FILE_OPEN_CANCELLED ?
+                            TRUE : FALSE;
 
-        /* Clear the file object in the open packet */
-        OpenPacket->FileObject = NULL;
+            /* Clear the file object in the open packet */
+            OpenPacket->FileObject = NULL;
 
-        /* Dereference the file object */
-        if (!UseDummyFile) ObDereferenceObject(FileObject);
+            /* Dereference the file object */
+            if (!UseDummyFile) ObDereferenceObject(FileObject);
 
-        /* Dereference the device object */
-        IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+            /* Dereference the device object */
+            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
 
-        /* Unless the driver cancelled the open, dereference the VPB */
-        if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb);
+            /* Unless the driver cancelled the open, dereference the VPB */
+            if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb);
 
-        /* Set the status and return */
-        OpenPacket->FinalStatus = Status;
-        return Status;
-    }
-    else if (Status == STATUS_REPARSE)
-    {
-        if (OpenPacket->Information == IO_REPARSE ||
-            OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
+            /* Set the status and return */
+            OpenPacket->FinalStatus = Status;
+            return Status;
+        }
+        else if (Status == STATUS_REPARSE)
         {
-            /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */
-            if (CompleteName->MaximumLength < FileObject->FileName.Length)
+            if (OpenPacket->Information == IO_REPARSE ||
+                OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
             {
-                PWSTR NewCompleteName;
-
-                /* Allocate a new buffer for the string */
-                NewCompleteName = ExAllocatePoolWithTag(PagedPool, FileObject->FileName.Length, TAG_IO_NAME);
-                if (NewCompleteName == NULL)
+                /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */
+                if (CompleteName->MaximumLength < FileObject->FileName.Length)
                 {
-                    OpenPacket->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
-                    return STATUS_INSUFFICIENT_RESOURCES;
+                    PWSTR NewCompleteName;
+
+                    /* Allocate a new buffer for the string */
+                    NewCompleteName = ExAllocatePoolWithTag(PagedPool, FileObject->FileName.Length, TAG_IO_NAME);
+                    if (NewCompleteName == NULL)
+                    {
+                        OpenPacket->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
+                        return STATUS_INSUFFICIENT_RESOURCES;
+                    }
+
+                    /* Release the old one */
+                    if (CompleteName->Buffer != NULL)
+                    {
+                        ExFreePoolWithTag(CompleteName->Buffer, TAG_IO_NAME);
+                    }
+
+                    /* And setup the new one */
+                    CompleteName->Buffer = NewCompleteName;
+                    CompleteName->MaximumLength = FileObject->FileName.Length;
                 }
 
-                /* Release the old one */
-                if (CompleteName->Buffer != NULL)
+                /* Copy our new complete name */
+                RtlCopyUnicodeString(CompleteName, &FileObject->FileName);
+
+                if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
                 {
-                    ExFreePoolWithTag(CompleteName->Buffer, TAG_IO_NAME);
+                    OpenPacket->RelatedFileObject = NULL;
                 }
-
-                /* And setup the new one */
-                CompleteName->Buffer = NewCompleteName;
-                CompleteName->MaximumLength = FileObject->FileName.Length;
             }
 
-            /* Copy our new complete name */
-            RtlCopyUnicodeString(CompleteName, &FileObject->FileName);
-
-            if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
+            /* Check if we have a name */
+            if (FileObject->FileName.Length)
             {
-                OpenPacket->RelatedFileObject = NULL;
+                /* Free it */
+                ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME);
+                FileObject->FileName.Length = 0;
             }
-        }
 
-        /* Check if we have a name */
-        if (FileObject->FileName.Length)
-        {
-            /* Free it */
-            ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME);
-            FileObject->FileName.Length = 0;
-        }
+            /* Clear its device object */
+            FileObject->DeviceObject = NULL;
 
-        /* Clear its device object */
-        FileObject->DeviceObject = NULL;
+            /* Clear the file object in the open packet */
+            OpenPacket->FileObject = NULL;
 
-        /* Clear the file object in the open packet */
-        OpenPacket->FileObject = NULL;
+            /* Dereference the file object */
+            if (!UseDummyFile) ObDereferenceObject(FileObject);
 
-        /* Dereference the file object */
-        if (!UseDummyFile) ObDereferenceObject(FileObject);
+            /* Dereference the device object */
+            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
 
-        /* Dereference the device object */
-        IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+            /* Unless the driver cancelled the open, dereference the VPB */
+            if (Vpb != NULL) IopDereferenceVpbAndFree(Vpb);
 
-        /* Unless the driver cancelled the open, dereference the VPB */
-        if (Vpb != NULL) IopDereferenceVpbAndFree(Vpb);
+            if (OpenPacket->Information != IO_REMOUNT)
+            {
+                OpenPacket->RelatedFileObject = NULL;
 
-        if (OpenPacket->Information != IO_REMOUNT)
-        {
-            OpenPacket->RelatedFileObject = NULL;
+                /* Inform we traversed a mount point for later attempt */
+                if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
+                {
+                    OpenPacket->TraversedMountPoint = 1;
+                }
 
-            /* Inform we traversed a mount point for later attempt */
-            if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
-            {
-                OpenPacket->TraversedMountPoint = 1;
-            }
+                /* In case we override checks, but got this on volume open, fail hard */
+                if (OpenPacket->Override)
+                {
+                    KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN,
+                                 (ULONG_PTR)OriginalDeviceObject,
+                                 (ULONG_PTR)DeviceObject,
+                                 (ULONG_PTR)CompleteName,
+                                 OpenPacket->Information);
+                }
 
-            /* In case we override checks, but got this on volume open, fail hard */
-            if (OpenPacket->Override)
-            {
-                KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN,
-                             (ULONG_PTR)OriginalDeviceObject,
-                             (ULONG_PTR)DeviceObject,
-                             (ULONG_PTR)CompleteName,
-                             OpenPacket->Information);
+                /* Return to IO/OB so that information can be upgraded */
+                return STATUS_REPARSE;
             }
 
-            /* Return to IO/OB so that information can be upgraded */
-            return STATUS_REPARSE;
+            /* Loop again and reattempt an opening */
+            continue;
         }
 
-        /* FIXME: At that point, we should loop again and reattempt an opening */
-        ASSERT(FALSE);
+        break;
     }
 
+    if (Attempt == IOP_MAX_REPARSE_TRAVERSAL)
+        return STATUS_UNSUCCESSFUL;
+
     /* Get the owner of the File Object */
     OwnerDevice = IoGetRelatedDeviceObject(FileObject);