[EXT2]
[reactos.git] / reactos / drivers / filesystems / ext2 / src / create.c
index 13aeafd..43703ea 100644 (file)
-/*************************************************************************
-*
-* File: create.c
-*
-* Module: Ext2 File System Driver (Kernel mode execution only)
-*
-* Description:
-*      Contains code to handle the "Create"/"Open" dispatch entry point.
-*
-* Author: Manoj Paul Joseph
-*
-*
-*************************************************************************/
-
-#include                       "ext2fsd.h"
-
-// define the file specific bug-check id
-#define                        EXT2_BUG_CHECK_ID                               EXT2_FILE_CREATE
-
-#define                        DEBUG_LEVEL                                             (DEBUG_TRACE_CREATE)
-
-/*************************************************************************
-*
-* Function: Ext2Create()
-*
-* Description: 
-*      The I/O Manager will invoke this routine to handle a create/open
-*      request
-*
-* Expected Interrupt Level (for execution) :
-*
-*  IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
-*      to be deferred to a worker thread context)
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2Create(
-PDEVICE_OBJECT         DeviceObject,           // the logical volume device object
-PIRP                                   Irp)                                    // I/O Request Packet
-{
-       NTSTATUS                                RC = STATUS_SUCCESS;
-    PtrExt2IrpContext  PtrIrpContext;
-       BOOLEAN                         AreWeTopLevel = FALSE;
+/*
+ * COPYRIGHT:        See COPYRIGHT.TXT
+ * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
+ * FILE:             create.c
+ * PROGRAMMER:       Matt Wu <mattwu@163.com>
+ * HOMEPAGE:         http://www.ext2fsd.com
+ * UPDATE HISTORY:
+ */
 
-       DebugTrace( DEBUG_TRACE_IRP_ENTRY, "Create Control IRP received...", 0);
+/* INCLUDES *****************************************************************/
 
-       FsRtlEnterFileSystem();
-       
-       //      Ext2BreakPoint();
+#include "ext2fs.h"
 
-       ASSERT(DeviceObject);
-       ASSERT(Irp);
+/* GLOBALS *****************************************************************/
 
-       // sometimes, we may be called here with the device object representing
-       //      the file system (instead of the device object created for a logical
-       //      volume. In this case, there is not much we wish to do (this create
-       //      typically will happen 'cause some process has to open the FSD device
-       //      object so as to be able to send an IOCTL to the FSD)
+extern PEXT2_GLOBAL Ext2Global;
 
-       //      All of the logical volume device objects we create have a device
-       //      extension whereas the device object representing the FSD has no
-       //      device extension. This seems like a good enough method to identify
-       //      between the two device objects ...
-       if (DeviceObject->Size == (unsigned short)(sizeof(DEVICE_OBJECT))) 
-       {
-               // this is an open of the FSD itself
-               DebugTrace( DEBUG_TRACE_MISC, " === Open for the FSD itself", 0);
-               Irp->IoStatus.Status = RC;
-               Irp->IoStatus.Information = FILE_OPENED;
+/* DEFINITIONS *************************************************************/
 
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               return(RC);
-       }
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, Ext2IsNameValid)
+#pragma alloc_text(PAGE, Ext2FollowLink)
+#pragma alloc_text(PAGE, Ext2IsSpecialSystemFile)
+#pragma alloc_text(PAGE, Ext2LookupFile)
+#pragma alloc_text(PAGE, Ext2ScanDir)
+#pragma alloc_text(PAGE, Ext2CreateFile)
+#pragma alloc_text(PAGE, Ext2CreateVolume)
+#pragma alloc_text(PAGE, Ext2Create)
+#pragma alloc_text(PAGE, Ext2CreateInode)
+#pragma alloc_text(PAGE, Ext2SupersedeOrOverWriteFile)
+#endif
 
-       // set the top level context
-       AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
 
-       try 
-       {
+BOOLEAN
+Ext2IsNameValid(PUNICODE_STRING FileName)
+{
+    USHORT  i = 0;
+    PUSHORT pName = (PUSHORT) FileName->Buffer;
 
-               // get an IRP context structure and issue the request
-               PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
-               ASSERT(PtrIrpContext);
+    if (FileName == NULL) {
+        return FALSE;
+    }
 
-               RC = Ext2CommonCreate(PtrIrpContext, Irp, TRUE );
+    while (i < (FileName->Length / sizeof(WCHAR))) {
 
-       } 
-       except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) 
-       {
+        if (pName[i] == 0) {
+            break;
+        }
 
-               RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
+        if (pName[i] == L'|'  || pName[i] == L':'  ||
+                pName[i] == L'/'  || pName[i] == L'*'  ||
+                pName[i] == L'?'  || pName[i] == L'\"' ||
+                pName[i] == L'<'  || pName[i] == L'>'   ) {
 
-               Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
-       }
+            return FALSE;
+        }
 
-       if (AreWeTopLevel) 
-       {
-               IoSetTopLevelIrp(NULL);
-       }
-       
-       FsRtlExitFileSystem();
+        i++;
+    }
 
-       return(RC);
+    return TRUE;
 }
 
 
+NTSTATUS
+Ext2FollowLink (
+    IN PEXT2_IRP_CONTEXT    IrpContext,
+    IN PEXT2_VCB            Vcb,
+    IN PEXT2_MCB            Parent,
+    IN PEXT2_MCB            Mcb,
+    IN USHORT               Linkdep
+)
+{
+    NTSTATUS        Status = STATUS_LINK_FAILED;
+
+    UNICODE_STRING  UniName;
+    OEM_STRING      OemName;
+    BOOLEAN         bOemBuffer = FALSE;
+
+    PEXT2_MCB       Target = NULL;
+
+    USHORT          i;
+
+    _SEH2_TRY {
+
+        RtlZeroMemory(&UniName, sizeof(UNICODE_STRING));
+        RtlZeroMemory(&OemName, sizeof(OEM_STRING));
+
+        /* exit if we jump into a possible symlink forever loop */
+        if ((Linkdep + 1) > EXT2_MAX_NESTED_LINKS ||
+                IoGetRemainingStackSize() < 1024) {
+            _SEH2_LEAVE;
+        }
+
+        /* read the symlink target path */
+        if (Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {
+
+            OemName.Buffer = (PUCHAR) (&Mcb->Inode.i_block[0]);
+            OemName.Length = (USHORT)Mcb->Inode.i_size;
+            OemName.MaximumLength = OemName.Length + 1;
+
+        } else {
+
+            OemName.Length = (USHORT)Mcb->Inode.i_size;
+            OemName.MaximumLength = OemName.Length + 1;
+            OemName.Buffer = Ext2AllocatePool(PagedPool,
+                                              OemName.MaximumLength,
+                                              'NL2E');
+            if (OemName.Buffer == NULL) {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                _SEH2_LEAVE;
+            }
+            bOemBuffer = TRUE;
+            RtlZeroMemory(OemName.Buffer, OemName.MaximumLength);
+
+            Status = Ext2ReadInode(
+                         IrpContext,
+                         Vcb,
+                         Mcb,
+                         (ULONGLONG)0,
+                         OemName.Buffer,
+                         (ULONG)(Mcb->Inode.i_size),
+                         FALSE,
+                         NULL);
+            if (!NT_SUCCESS(Status)) {
+                _SEH2_LEAVE;
+            }
+        }
+
+        /* convert Linux slash to Windows backslash */
+        for (i=0; i < OemName.Length; i++) {
+            if (OemName.Buffer[i] == '/') {
+                OemName.Buffer[i] = '\\';
+            }
+        }
+
+        /* convert oem string to unicode string */
+        UniName.MaximumLength = (USHORT)Ext2OEMToUnicodeSize(Vcb, &OemName);
+        if (UniName.MaximumLength <= 0) {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            _SEH2_LEAVE;
+        }
+
+        UniName.MaximumLength += 2;
+        UniName.Buffer = Ext2AllocatePool(PagedPool,
+                                          UniName.MaximumLength,
+                                          'NL2E');
+        if (UniName.Buffer == NULL) {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            _SEH2_LEAVE;
+        }
+        RtlZeroMemory(UniName.Buffer, UniName.MaximumLength);
+        Status = Ext2OEMToUnicode(Vcb, &UniName, &OemName);
+        if (!NT_SUCCESS(Status)) {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            _SEH2_LEAVE;
+        }
+
+        /* search the real target */
+        Status = Ext2LookupFile(
+                     IrpContext,
+                     Vcb,
+                     &UniName,
+                     Parent,
+                     &Target,
+                     Linkdep
+                 );
+        if (Target == NULL) {
+            Status = STATUS_LINK_FAILED;
+        }
+
+        if (Target == NULL /* link target doesn't exist */      ||
+                Target == Mcb  /* symlink points to itself */       ||
+                IsMcbSpecialFile(Target) /* target not resolved*/   ||
+                IsFileDeleted(Target)  /* target deleted */         ) {
+
+            if (Target) {
+                ASSERT(Target->Refercount > 0);
+                Ext2DerefMcb(Target);
+            }
+            ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+            SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+            Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
+            Mcb->Target = NULL;
+
+        } else if (IsMcbSymLink(Target)) {
+
+            ASSERT(Target->Refercount > 0);
+            ASSERT(Target->Target != NULL);
+            Ext2ReferMcb(Target->Target);
+            Mcb->Target = Target->Target;
+            Ext2DerefMcb(Target);
+            ASSERT(!IsMcbSymLink(Target->Target));
+            SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+            ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+            ASSERT(Mcb->Target->Refercount > 0);
+            Mcb->FileAttr = Target->FileAttr;
+
+        } else {
+
+            Mcb->Target = Target;
+            SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+            ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+            ASSERT(Mcb->Target->Refercount > 0);
+            Mcb->FileAttr = Target->FileAttr;
+        }
+
+    } _SEH2_FINALLY {
+
+        if (bOemBuffer) {
+            Ext2FreePool(OemName.Buffer, 'NL2E');
+        }
+
+        if (UniName.Buffer) {
+            Ext2FreePool(UniName.Buffer, 'NL2E');
+        }
+    } _SEH2_END;
+
+    return Status;
+}
+
+BOOLEAN
+Ext2IsSpecialSystemFile(
+    IN PUNICODE_STRING FileName,
+    IN BOOLEAN         bDirectory
+)
+{
+    PWSTR SpecialFileList[] = {
+        L"pagefile.sys",
+        L"swapfile.sys",
+        L"hiberfil.sys",
+        NULL
+    };
+
+    PWSTR SpecialDirList[] = {
+        L"Recycled",
+        L"RECYCLER",
+        L"$RECYCLE.BIN",
+        NULL
+    };
+
+    PWSTR   entryName;
+    ULONG   length;
+    int     i;
+
+    for (i = 0; TRUE; i++) {
+
+        if (bDirectory) {
+            entryName = SpecialDirList[i];
+        } else {
+            entryName = SpecialFileList[i];
+        }
+
+        if (NULL == entryName) {
+            break;
+        }
+
+        length = wcslen(entryName) * sizeof(WCHAR);
+        if (FileName->Length == length) {
+            if ( 0 == _wcsnicmp( entryName,
+                                 FileName->Buffer,
+                                 length / sizeof(WCHAR) )) {
+                return TRUE;
+            }
+        }
+    }
+
+    return FALSE;
+}
 
-/*************************************************************************
-*
-* Function: Ext2CommonCreate()
-*
-* Description:
-*      The actual work is performed here. This routine may be invoked in one'
-*      of the two possible contexts:
-*      (a) in the context of a system worker thread
-*      (b) in the context of the original caller
-*
-* Expected Interrupt Level (for execution) :
-*
-*  IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2CommonCreate(
-PtrExt2IrpContext                      PtrIrpContext,
-PIRP                                           PtrIrp,
-BOOLEAN                                                FirstAttempt)
+NTSTATUS
+Ext2LookupFile (
+    IN PEXT2_IRP_CONTEXT    IrpContext,
+    IN PEXT2_VCB            Vcb,
+    IN PUNICODE_STRING      FullName,
+    IN PEXT2_MCB            Parent,
+    OUT PEXT2_MCB *         Ext2Mcb,
+    IN USHORT               Linkdep
+)
 {
-       NTSTATUS                                RC = STATUS_SUCCESS;
-       PIO_STACK_LOCATION              PtrIoStackLocation = NULL;
-       PIO_SECURITY_CONTEXT    PtrSecurityContext = NULL;
-       PFILE_OBJECT                    PtrNewFileObject = NULL;
-       PFILE_OBJECT                    PtrRelatedFileObject = NULL;
-       uint32                                  AllocationSize = 0;     // if we create a new file
-       PFILE_FULL_EA_INFORMATION       PtrExtAttrBuffer = NULL;
-       unsigned long                   RequestedOptions = 0;
-       unsigned long                   RequestedDisposition = 0;
-       uint8                                   FileAttributes = 0;
-       unsigned short                  ShareAccess = 0;
-       unsigned long                   ExtAttrLength = 0;
-       ACCESS_MASK                             DesiredAccess;
-
-       BOOLEAN                                 DeferredProcessing = FALSE;
-
-       PtrExt2VCB                              PtrVCB = NULL;
-       BOOLEAN                                 AcquiredVCB = FALSE;
-
-       BOOLEAN                                 DirectoryOnlyRequested = FALSE;
-       BOOLEAN                                 FileOnlyRequested = FALSE;
-       BOOLEAN                                 NoBufferingSpecified = FALSE;
-       BOOLEAN                                 WriteThroughRequested = FALSE;
-       BOOLEAN                                 DeleteOnCloseSpecified = FALSE;
-       BOOLEAN                                 NoExtAttrKnowledge = FALSE;
-       BOOLEAN                                 CreateTreeConnection = FALSE;
-       BOOLEAN                                 OpenByFileId    = FALSE;
-
-       BOOLEAN                                 SequentialOnly  = FALSE;
-       BOOLEAN                                 RandomAccess    = FALSE;
-       
-       // Are we dealing with a page file?
-       BOOLEAN                                 PageFileManipulation = FALSE;
-
-       // Is this open for a target directory (used in rename operations)?
-       BOOLEAN                                 OpenTargetDirectory = FALSE;
-
-       // Should we ignore case when attempting to locate the object?
-       BOOLEAN                                 IgnoreCaseWhenChecking = FALSE;
-
-       PtrExt2CCB                              PtrRelatedCCB = NULL, PtrNewCCB = NULL;
-       PtrExt2FCB                              PtrRelatedFCB = NULL, PtrNewFCB = NULL;
-
-       unsigned long                   ReturnedInformation = -1;
-
-       UNICODE_STRING                  TargetObjectName;
-       UNICODE_STRING                  RelatedObjectName;
-
-       UNICODE_STRING                  AbsolutePathName;
-       UNICODE_STRING                  RenameLinkTargetFileName;
-
-    /* Silence GCC warnings */
-    RtlZeroMemory(&RelatedObjectName, sizeof(UNICODE_STRING));
-
-
-       ASSERT(PtrIrpContext);
-       ASSERT(PtrIrp);
-
-       try 
-       {
-
-               AbsolutePathName.Buffer = NULL;
-               AbsolutePathName.Length = AbsolutePathName.MaximumLength = 0;
-
-               // Getting a pointer to the current I/O stack location
-               PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
-               ASSERT(PtrIoStackLocation);
-
-               // Can we block?
-               if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK)) 
-               {
-                       //      Asynchronous processing required...
-                       RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
-                       DeferredProcessing = TRUE;
-                       try_return();
-               }
-
-               // Obtaining the parameters specified by the user.
-               PtrNewFileObject        = PtrIoStackLocation->FileObject;
-               TargetObjectName        = PtrNewFileObject->FileName;
-               PtrRelatedFileObject = PtrNewFileObject->RelatedFileObject;
-
-               if( PtrNewFileObject->FileName.Length && PtrNewFileObject->FileName.Buffer )
-               {
-                       if( PtrNewFileObject->FileName.Buffer[ PtrNewFileObject->FileName.Length/2 ] != 0 )
-                       {
-                               DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&&  PtrFileObject->FileName not NULL terminated! [Create]", 0 );
-                       }
-                       DebugTrace( DEBUG_TRACE_FILE_NAME, " === Create/Open File Name : -%S- [Create]", PtrNewFileObject->FileName.Buffer );
-               }
-               else
-               {
-                       DebugTrace( DEBUG_TRACE_FILE_NAME, " === Create/Open File Name : -null- [Create]", 0);
-               }
-
-               // Is this a Relative Create/Open?
-               if (PtrRelatedFileObject) 
-               {
-                       PtrRelatedCCB = (PtrExt2CCB)(PtrRelatedFileObject->FsContext2);
-                       ASSERT(PtrRelatedCCB);
-                       ASSERT(PtrRelatedCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB);
-                       // each CCB in turn points to a FCB
-                       PtrRelatedFCB = PtrRelatedCCB->PtrFCB;
-                       ASSERT(PtrRelatedFCB);
-                       if( PtrRelatedFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB &&
-                               PtrRelatedFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_VCB    )
-                       {
-                               //      How the hell can this happen!!!
-                               Ext2BreakPoint();
-                       }
-
-                       AssertFCBorVCB( PtrRelatedFCB );
-
-                       RelatedObjectName = PtrRelatedFileObject->FileName;
-
-                       if( PtrRelatedFileObject->FileName.Length && PtrRelatedFileObject->FileName.Buffer )
-                       {
-                               DebugTrace( DEBUG_TRACE_FILE_NAME, " === Relative to : -%S-", PtrRelatedFileObject->FileName.Buffer );
-                       }
-                       else
-                       {
-                               DebugTrace( DEBUG_TRACE_FILE_NAME, " === Relative to : -null-",0);
-                       }
-
-               }
-
-
-               AllocationSize    = PtrIrp->Overlay.AllocationSize.LowPart;
-               //      Only 32 bit file sizes supported...
-
-               if (PtrIrp->Overlay.AllocationSize.HighPart) 
-               {
-                       RC = STATUS_INVALID_PARAMETER;
-                       try_return();
-               }
-
-               // Getting a pointer to the supplied security context
-               PtrSecurityContext = PtrIoStackLocation->Parameters.Create.SecurityContext;
-
-               // Obtaining the desired access 
-               DesiredAccess = PtrSecurityContext->DesiredAccess;
-
-               //      Getting the options supplied by the user...
-               RequestedOptions = (PtrIoStackLocation->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS);
-               RequestedDisposition = ((PtrIoStackLocation->Parameters.Create.Options >> 24) & 0xFF);
-
-               FileAttributes  = (uint8)(PtrIoStackLocation->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS);
-               ShareAccess     = PtrIoStackLocation->Parameters.Create.ShareAccess;
-               PtrExtAttrBuffer        = PtrIrp->AssociatedIrp.SystemBuffer;
-
-               ExtAttrLength           = PtrIoStackLocation->Parameters.Create.EaLength;
-
-               SequentialOnly      = ((RequestedOptions & FILE_SEQUENTIAL_ONLY ) ? TRUE : FALSE);
-               RandomAccess            = ((RequestedOptions & FILE_RANDOM_ACCESS ) ? TRUE : FALSE);
-               
-
-               DirectoryOnlyRequested = ((RequestedOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
-               FileOnlyRequested = ((RequestedOptions & FILE_NON_DIRECTORY_FILE) ? TRUE : FALSE);
-               NoBufferingSpecified = ((RequestedOptions & FILE_NO_INTERMEDIATE_BUFFERING) ? TRUE : FALSE);
-               WriteThroughRequested = ((RequestedOptions & FILE_WRITE_THROUGH) ? TRUE : FALSE);
-               DeleteOnCloseSpecified = ((RequestedOptions & FILE_DELETE_ON_CLOSE) ? TRUE : FALSE);
-               NoExtAttrKnowledge = ((RequestedOptions & FILE_NO_EA_KNOWLEDGE) ? TRUE : FALSE);
-               CreateTreeConnection = ((RequestedOptions & FILE_CREATE_TREE_CONNECTION) ? TRUE : FALSE);
-               OpenByFileId = ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? TRUE : FALSE);
-               PageFileManipulation = ((PtrIoStackLocation->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE);
-               OpenTargetDirectory = ((PtrIoStackLocation->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE);
-               IgnoreCaseWhenChecking = ((PtrIoStackLocation->Flags & SL_CASE_SENSITIVE) ? TRUE : FALSE);
-
-               // Ensure that the operation has been directed to a valid VCB ...
-               PtrVCB =        (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
-               ASSERT(PtrVCB);
-               ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
-
-               
-               if( !PtrNewFileObject->Vpb )
-               {
-                       PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
-               }
-
-               //      Acquiring the VCBResource Exclusively...
-               //      This is done to synchronise with the close and cleanup routines...
-               
-               DebugTrace(DEBUG_TRACE_MISC,  "*** Going into a block to acquire VCB Exclusively [Create]", 0);
-               
-               DebugTraceState( "VCB       AC:0x%LX   SW:0x%LX   EX:0x%LX   [Create]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
-               ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE);
-                               
-               AcquiredVCB = TRUE;
-
-               DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Acquired in Create", 0);
-               if( PtrNewFileObject )
-               {
-                       DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Create]", PtrNewFileObject);
-               }
-
-               //      Verify Volume...
-               //      if (!NT_SUCCESS(RC = Ext2VerifyVolume(PtrVCB))) 
-               //      {
-               //              try_return();
-               //      }
-
-               // If the volume has been locked, fail the request
-
-               if (PtrVCB->VCBFlags & EXT2_VCB_FLAGS_VOLUME_LOCKED) 
-               {
-                       DebugTrace(DEBUG_TRACE_MISC,   "Volume locked. Failing Create", 0 );
-                       RC = STATUS_ACCESS_DENIED;
-                       try_return();
-               }
-
-
-               if ((PtrNewFileObject->FileName.Length == 0) && ((PtrRelatedFileObject == NULL) ||
-                         (PtrRelatedFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB))) 
-               {
-                       //
-                       //      >>>>>>>>>>>>>   Volume Open requested. <<<<<<<<<<<<<
-                       //
-
-                       //      Performing validity checks...
-                       if ((OpenTargetDirectory) || (PtrExtAttrBuffer)) 
-                       {
-                               RC = STATUS_INVALID_PARAMETER;
-                               try_return();
-                       }
-
-                       if (DirectoryOnlyRequested) 
-                       {
-                               // a volume is not a directory
-                               RC = STATUS_NOT_A_DIRECTORY;
-                               try_return();
-                       }
-
-                       if ((RequestedDisposition != FILE_OPEN) && (RequestedDisposition != FILE_OPEN_IF)) 
-                       {
-                               // cannot create a new volume, I'm afraid ...
-                               RC = STATUS_ACCESS_DENIED;
-                               try_return();
-                       }
-                       DebugTrace(DEBUG_TRACE_MISC,   "Volume open requested", 0 );
-                       RC = Ext2OpenVolume(PtrVCB, PtrIrpContext, PtrIrp, ShareAccess, PtrSecurityContext, PtrNewFileObject);
-                       ReturnedInformation = PtrIrp->IoStatus.Information;
-
-                       try_return();
-               }
-
-               if (OpenByFileId) 
-               {
-                       DebugTrace(DEBUG_TRACE_MISC, "Open by File Id requested", 0 );
-                       RC = STATUS_ACCESS_DENIED;
-                       try_return();
-               }
-
-               // Relative path name specified...
-               if (PtrRelatedFileObject)
-               {
-
-                       if (!(PtrRelatedFCB->FCBFlags & EXT2_FCB_DIRECTORY)) 
-                       {
-                               // we must have a directory as the "related" object
-                               RC = STATUS_INVALID_PARAMETER;
-                               try_return();
-                       }
-
-                       //      Performing validity checks...
-                       if ((RelatedObjectName.Length == 0) || (RelatedObjectName.Buffer[0] != L'\\')) 
-                       {
-                               RC = STATUS_INVALID_PARAMETER;
-                               try_return();
-                       }
-
-                       if ((TargetObjectName.Length != 0) && (TargetObjectName.Buffer[0] == L'\\')) 
-                       {
-                               RC = STATUS_INVALID_PARAMETER;
-                               try_return();
-                       }
-
-                       // Creating an absolute path-name.
-                       {
-                               AbsolutePathName.MaximumLength = TargetObjectName.Length + RelatedObjectName.Length + sizeof(WCHAR);
-                               if (!(AbsolutePathName.Buffer = Ext2AllocatePool(PagedPool, AbsolutePathName.MaximumLength ))) 
-                               {
-                                       RC = STATUS_INSUFFICIENT_RESOURCES;
-                                       try_return();
-                               }
-
-                               RtlZeroMemory(AbsolutePathName.Buffer, AbsolutePathName.MaximumLength);
-
-                               RtlCopyMemory((void *)(AbsolutePathName.Buffer), (void *)(RelatedObjectName.Buffer), RelatedObjectName.Length);
-                               AbsolutePathName.Length = RelatedObjectName.Length;
-                               RtlAppendUnicodeToString(&AbsolutePathName, L"\\");
-                               RtlAppendUnicodeToString(&AbsolutePathName, TargetObjectName.Buffer);
-                       }
-
-               }
-               //      Absolute Path name specified...
-               else 
-               {
-                       
-
-                       // Validity Checks...
-                       if (TargetObjectName.Buffer[0] != L'\\') 
-                       {
-                               RC = STATUS_INVALID_PARAMETER;
-                               try_return();
-                       }
-
-                       {
-                               AbsolutePathName.MaximumLength = TargetObjectName.Length;
-                               if (!(AbsolutePathName.Buffer = Ext2AllocatePool(PagedPool, AbsolutePathName.MaximumLength ))) {
-                                       RC = STATUS_INSUFFICIENT_RESOURCES;
-                                       try_return();
-                               }
-
-                               RtlZeroMemory(AbsolutePathName.Buffer, AbsolutePathName.MaximumLength);
-
-                               RtlCopyMemory((void *)(AbsolutePathName.Buffer), (void *)(TargetObjectName.Buffer), TargetObjectName.Length);
-                               AbsolutePathName.Length = TargetObjectName.Length;
-                       }
-               }
-
-
-               //      Parsing the path...
-               if (AbsolutePathName.Length == 2) 
-               {
-                       
-                       // this is an open of the root directory, ensure that   the caller has not requested a file only
-                       if (FileOnlyRequested || (RequestedDisposition == FILE_SUPERSEDE) || (RequestedDisposition == FILE_OVERWRITE) ||
-                                (RequestedDisposition == FILE_OVERWRITE_IF)) 
-                       {
-                               RC = STATUS_FILE_IS_A_DIRECTORY;
-                               try_return();
-                       }
-
-                       RC = Ext2OpenRootDirectory(PtrVCB, PtrIrpContext, PtrIrp, ShareAccess, PtrSecurityContext, PtrNewFileObject);
-                       DebugTrace(DEBUG_TRACE_MISC,   " === Root directory opened", 0 );
-                       try_return();
-               }
-
-
-               {
-                       //      Used during parsing the file path...
-                       UNICODE_STRING                  RemainingName;
-                       UNICODE_STRING                  CurrentName;
-                       UNICODE_STRING                  NextRemainingName;
-                       ULONG                                   CurrInodeNo = 0;
-                       PtrExt2FCB                              PtrCurrFCB = NULL;
-                       PtrExt2FCB                              PtrNextFCB = NULL;
-                       PFILE_OBJECT                    PtrCurrFileObject = NULL;
-                       ULONG                                   Type = 0;
-                       LARGE_INTEGER ZeroSize;
-                       BOOLEAN Found           = FALSE;
-                       
-                       ZeroSize.QuadPart = 0;
-                       if ( PtrRelatedFileObject ) 
-                       {
-                               CurrInodeNo = PtrRelatedFCB->INodeNo;
-                               PtrCurrFCB = PtrRelatedFCB;
-                       }
-                       else 
-                       {
-                               CurrInodeNo = PtrVCB->PtrRootDirectoryFCB->INodeNo;
-                               PtrCurrFCB = PtrVCB->PtrRootDirectoryFCB;
-
-                       }
-
-                       //      Ext2ZerooutUnicodeString( &RemainingName );
-                       Ext2ZerooutUnicodeString( &CurrentName );
-                       Ext2ZerooutUnicodeString( &NextRemainingName );
-
-                       RemainingName = TargetObjectName;
-               
-                       while ( !Found && CurrInodeNo ) 
-                       {
-                               FsRtlDissectName ( RemainingName, &CurrentName, &NextRemainingName );
-
-                               RemainingName = NextRemainingName;
-                               //      CurrInodeNo is the parent inode for the entry I am searching for
-                               //      PtrCurrFCB      is the parent's FCB
-                               //      Current Name is its name...
-
-
-                               PtrNextFCB = Ext2LocateChildFCBInCore ( PtrVCB, &CurrentName, CurrInodeNo );
-                               
-                               if( PtrNextFCB )
-                               {
-                                       CurrInodeNo = PtrNextFCB->INodeNo;
-       
-                                       if( NextRemainingName.Length == 0 )
-                                       {
-                                               //
-                                               //      Done Parsing...
-                                               //      Found the file...
-                                               //
-                                               Found = TRUE;
-                                               
-                                               if( OpenTargetDirectory )
-                                               {
-                                                       //
-                                                       //      This is for a rename/move operation...
-                                                       //
-                                                       ReturnedInformation = FILE_EXISTS;
-
-                                                       //      Now replace the file name field with that of the 
-                                                       //      Target file name...
-                                                       Ext2CopyUnicodeString( 
-                                                               &RenameLinkTargetFileName,
-                                                               &CurrentName );
-                                                       /*
-                                                       
-                                                       for( i = 0; i < (CurrentName.Length/2); i++ )
-                                                       {
-                                                               PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
-                                                       }
-                                                       PtrNewFileObject->FileName.Length = CurrentName.Length;
-                                                       */
-                                                       //      Now open the Parent Directory...
-                                                       PtrNextFCB = PtrCurrFCB;
-                                                       CurrInodeNo = PtrNextFCB->INodeNo;
-                                               }
-
-                                               //      
-                                               //      Relating the FCB to the New File Object
-                                               //
-                                               PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
-                                               PtrNewFileObject->PrivateCacheMap = NULL;
-                                               PtrNewFileObject->FsContext = (void *)( &(PtrNextFCB->NTRequiredFCB.CommonFCBHeader) );
-                                               PtrNewFileObject->SectionObjectPointer = &(PtrNextFCB->NTRequiredFCB.SectionObject) ;
-                                               break;
-                                       }
-
-                                       else if( !Ext2IsFlagOn( PtrNextFCB->FCBFlags, EXT2_FCB_DIRECTORY ) )
-                                       {
-                                               //      Invalid path...
-                                               //      Can have only a directory in the middle of the path...
-                                               //
-                                               RC = STATUS_OBJECT_PATH_NOT_FOUND;
-                                               try_return();
-                                       }
-                               }
-                               else    //      searching on the disk...
-                               {
-                                       CurrInodeNo = Ext2LocateFileInDisk( PtrVCB, &CurrentName, PtrCurrFCB, &Type );
-                                       if( !CurrInodeNo )
-                                       {
-                                               //
-                                               //      Not found...
-                                               //      Quit searching...
-                                               //      
-                                       
-                                               if( ( NextRemainingName.Length == 0 ) && (
-                                                       ( RequestedDisposition == FILE_CREATE ) ||
-                                                       ( RequestedDisposition == FILE_OPEN_IF) ||
-                                                       ( RequestedDisposition == FILE_OVERWRITE_IF) ) )
-
-                                               {
-                                                       //
-                                                       //      Just the last component was not found...
-                                                       //      A create was requested...
-                                                       //
-                                                       if( DirectoryOnlyRequested )
-                                                       {
-                                                               Type = EXT2_FT_DIR;
-                                                       }
-                                                       else
-                                                       {
-                                                               Type = EXT2_FT_REG_FILE;
-                                                       }
-
-                                                       CurrInodeNo = Ext2CreateFile( PtrIrpContext, PtrVCB, 
-                                                               &CurrentName, PtrCurrFCB, Type );
-                                                       
-                                                       if(     !CurrInodeNo )
-                                                       {
-                                                               RC = STATUS_OBJECT_PATH_NOT_FOUND;
-                                                               try_return();
-                                                       }
-                                                       // Set the allocation size for the object is specified
-                                                       //IoSetShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject, &(PtrNewFCB->FCBShareAccess));
-                                                       //      RC = STATUS_SUCCESS;
-                                                       ReturnedInformation = FILE_CREATED;
-                                                       
-                                                       //      Should also create a CCB structure...
-                                                       //      Doing that a little fathre down... ;)
-
-                                               }
-                                               else if( NextRemainingName.Length == 0 && OpenTargetDirectory )
-                                               { 
-                                                       //
-                                                       //      This is for a rename/move operation...
-                                                       //      Just the last component was not found...
-                                                       //
-                                                       ReturnedInformation = FILE_DOES_NOT_EXIST;
-
-                                                       //      Now replace the file name field with that of the 
-                                                       //      Target file name...
-                                                       Ext2CopyUnicodeString( 
-                                                               &RenameLinkTargetFileName,
-                                                               &CurrentName );
-                                                       /*
-                                                       for( i = 0; i < (CurrentName.Length/2); i++ )
-                                                       {
-                                                               PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
-                                                       }
-                                                       PtrNewFileObject->FileName.Length = CurrentName.Length;
-                                                       */
-
-                                                       //      Now open the Parent Directory...
-                                                       PtrNextFCB = PtrCurrFCB;
-                                                       CurrInodeNo = PtrNextFCB->INodeNo;
-                                                       //      Initialize the FsContext
-                                                       PtrNewFileObject->FsContext = &PtrNextFCB->NTRequiredFCB.CommonFCBHeader;
-                                                       //      Initialize the section object pointer...
-                                                       PtrNewFileObject->SectionObjectPointer = &(PtrNextFCB->NTRequiredFCB.SectionObject);
-                                                       PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
-                                                       PtrNewFileObject->PrivateCacheMap = NULL;                                                       
-
-                                                       break;
-                                               }
-                                               else
-                                               {
-                                                       RC = STATUS_OBJECT_PATH_NOT_FOUND;
-                                                       try_return();
-                                               }
-                                       }
-
-                                       if( NextRemainingName.Length )
-                                       {
-                                               //      Should be a directory...
-                                               if( Type != EXT2_FT_DIR )
-                                               {
-                                                       //      Invalid path...
-                                                       //      Can have only a directory in the middle of the path...
-                                                       //
-                                                       RC = STATUS_OBJECT_PATH_NOT_FOUND;
-                                                       try_return();
-                                               }
-
-                                               PtrCurrFileObject = NULL;
-                                       }
-                                       else
-                                       {
-                                               //
-                                               //      Done Parsing...
-                                               //      Found the file...
-                                               //
-                                               Found = TRUE;
-                                               
-                                               //
-                                               //      Was I supposed to create a new file?
-                                               //
-                                               if (RequestedDisposition == FILE_CREATE &&
-                                                       ReturnedInformation != FILE_CREATED ) 
-                                               {
-                                                       ReturnedInformation = FILE_EXISTS;
-                                                       RC = STATUS_OBJECT_NAME_COLLISION;
-                                                       try_return();
-                                               }
-                                               
-                                               //      Is this the type of file I was looking for?
-                                               //      Do some checking here...
-
-                                               if( Type != EXT2_FT_DIR && Type != EXT2_FT_REG_FILE )
-                                               {
-                                                       //      Deny access!
-                                                       //      Cannot open a special file...
-                                                       RC = STATUS_ACCESS_DENIED;
-                                                       try_return();
-
-                                               }
-                                               if( DirectoryOnlyRequested && Type != EXT2_FT_DIR )
-                                               {
-                                                       RC = STATUS_NOT_A_DIRECTORY;
-                                                       try_return();
-                                               }
-                                               if( FileOnlyRequested && Type == EXT2_FT_DIR )
-                                               {
-                                                       RC = STATUS_FILE_IS_A_DIRECTORY;
-                                                       try_return();
-                                               }
-
-                                               PtrCurrFileObject = PtrNewFileObject;
-                                               //      Things seem to be ok enough!
-                                               //      Proceeing with the Open/Create...
-                                               
-                                       }
-
-                               
-                                       //
-                                       //      Create an FCB and initialise it...
-                                       //
-                                       {
-                                               PtrExt2ObjectName               PtrObjectName;
-                                               
-                                               //      Initialising the object name...
-                                               PtrObjectName = Ext2AllocateObjectName();
-                                               Ext2CopyUnicodeString( &PtrObjectName->ObjectName, &CurrentName ); 
-                                               //      RtlInitUnicodeString( &PtrObjectName->ObjectName, CurrentName.Buffer );
-
-                                               if( !NT_SUCCESS( Ext2CreateNewFCB( 
-                                                       &PtrNextFCB,                            //      the new FCB
-                                                       ZeroSize,                                       //      AllocationSize,
-                                                       ZeroSize,                                       //      EndOfFile,
-                                       PtrCurrFileObject,                      //      The File Object
-                                                       PtrVCB,
-                                                       PtrObjectName  )  )  )
-                                               {
-                                                       RC = STATUS_INSUFFICIENT_RESOURCES;
-                                                       try_return();
-                                               }
-
-                                               if( Type == EXT2_FT_DIR )
-                                                       PtrNextFCB->FCBFlags |= EXT2_FCB_DIRECTORY;
-                                               else if( Type != EXT2_FT_REG_FILE )
-                                                       PtrNextFCB->FCBFlags |= EXT2_FCB_SPECIAL_FILE;
-
-                                               PtrNextFCB->INodeNo = CurrInodeNo ;
-                                               PtrNextFCB->ParentINodeNo = PtrCurrFCB->INodeNo;
-
-                                               if( PtrCurrFileObject == NULL && CurrInodeNo != EXT2_ROOT_INO )
-                                               {
-                                                       //      This is an FCB created to cache the reads done while parsing
-                                                       //      Put this FCB on the ClosableFCBList 
-                                                       if( !PtrNextFCB->ClosableFCBs.OnClosableFCBList )
-                                                       {
-                                                                       InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
-                                                                               &PtrNextFCB->ClosableFCBs.ClosableFCBList );
-                                                                       PtrVCB->ClosableFCBs.Count++;
-                                                                       PtrNextFCB->ClosableFCBs.OnClosableFCBList = TRUE;
-                                                       }
-                                               }
-                                       }
-                               }
-       
-                               //
-                               //      Still not done parsing...
-                               //      miles to go before I open... ;)
-                               //
-                               PtrCurrFCB = PtrNextFCB;
-                       }
-
-                       PtrNewFCB = PtrNextFCB;
-               }
-               
-
-               //      If I get this far...
-               //      it means, I have located the file...
-               //      I even have an FCB to represent it!!!
-
-               if ( NT_SUCCESS (RC) ) 
-               {
-
-                       if ((PtrNewFCB->FCBFlags & EXT2_FCB_DIRECTORY) && ((RequestedDisposition == FILE_SUPERSEDE) ||
-                                 (RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF ))) 
-                       {
-                               RC = STATUS_FILE_IS_A_DIRECTORY;
-                               try_return();
-                       }
-               
-                       
-                       // Check share access and fail if the share conflicts with an existing
-                       // open.
-                       
-                       if (PtrNewFCB->OpenHandleCount > 0) 
-                       {
-                               // The FCB is currently in use by some thread.
-                               // We must check whether the requested access/share access
-                               // conflicts with the existing open operations.
-
-                               if (!NT_SUCCESS(RC = IoCheckShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject,
-                                                                                               &(PtrNewFCB->FCBShareAccess), TRUE))) 
-                               {
-                                       // Ext2CloseCCB(PtrNewCCB);
-                                       try_return();
-                               }
-                       } 
-                       else 
-                       {
-                               IoSetShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject, &(PtrNewFCB->FCBShareAccess));
-                       }
-
-                       //
-                       //      Allocating a new CCB Structure...
-                       //      
-                       Ext2CreateNewCCB( &PtrNewCCB, PtrNewFCB, PtrNewFileObject);
-                       PtrNewFileObject->FsContext2 = (void *) PtrNewCCB;
-                       Ext2CopyUnicodeString( &(PtrNewCCB->AbsolutePathName), &AbsolutePathName );
-
-                       if( ReturnedInformation == -1 )
-                       {
-                               //      
-                               //      ReturnedInformation has not been set so far...
-                               //
-                               ReturnedInformation = FILE_OPENED;
-                       }
-
-                       // If a supersede or overwrite was requested, do so now ...
-                       if (RequestedDisposition == FILE_SUPERSEDE) 
-                       {
-                               // Attempt the operation here ...
-                               if( Ext2SupersedeFile( PtrNewFCB, PtrIrpContext) )
-                               {
-                                       ReturnedInformation = FILE_SUPERSEDED;
-                               }
-                       }
-                       
-                       else if ((RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF))
-                       {
-                               // Attempt the overwrite operation...
-                               if( Ext2OverwriteFile( PtrNewFCB, PtrIrpContext) )
-                               {
-                                       ReturnedInformation = FILE_OVERWRITTEN;
-                               }
-                       }
-                       if( AllocationSize )
-                       {
-                               if( ReturnedInformation == FILE_CREATED ||
-                                       ReturnedInformation == FILE_SUPERSEDED )
-                               {
-                                       ULONG CurrentSize;
-                                       ULONG LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
-                                       
-                                       for( CurrentSize = 0; CurrentSize < AllocationSize; CurrentSize += LogicalBlockSize )
-                                       {
-                                               Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrNewFCB, PtrNewFileObject, FALSE );
-                                       }
-                               }
-                       }
-
-                       if( ReturnedInformation == FILE_CREATED )
-                       {
-                               //      Allocate some data blocks if 
-                               //              1. initial file size has been specified...
-                               //              2. if the file is a Directory...
-                               //                      In case of (2) make entries for '.' and '..'
-                               //      Zero out the Blocks...
-
-                               UNICODE_STRING          Name;
-
-                               if( DirectoryOnlyRequested )
-                               {
-
-                                       Ext2CopyCharToUnicodeString( &Name, ".", 1 );
-                                       Ext2MakeNewDirectoryEntry( PtrIrpContext, PtrNewFCB, PtrNewFileObject, &Name, EXT2_FT_DIR, PtrNewFCB->INodeNo);
-
-                                       Name.Buffer[1] = '.';
-                                       Name.Buffer[2] = '\0';
-                                       Name.Length += 2;
-                                       Ext2MakeNewDirectoryEntry( PtrIrpContext, PtrNewFCB, PtrNewFileObject, &Name, EXT2_FT_DIR, PtrNewFCB->ParentINodeNo );
-                                       Ext2DeallocateUnicodeString( &Name );
-                               }
-                       }
-                       if( OpenTargetDirectory )
-                       {
-                               //
-                               //      Save the taget file name in the CCB...
-                               //
-                               Ext2CopyUnicodeString( 
-                                       &PtrNewCCB->RenameLinkTargetFileName,
-                                       &RenameLinkTargetFileName );
-                               Ext2DeallocateUnicodeString( &RenameLinkTargetFileName );
-                       }
-               }
-
-               try_exit:       NOTHING;
-
-       }
-       finally 
-       {
-               if (AcquiredVCB) 
-               {
-                       ASSERT(PtrVCB);
-                       Ext2ReleaseResource(&(PtrVCB->VCBResource));
-
-                       AcquiredVCB = FALSE;
-                       DebugTrace(DEBUG_TRACE_MISC,   "*** VCB released [Create]", 0);
-
-                       if( PtrNewFileObject )
-                       {
-                               DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Create]", PtrNewFileObject);
-                       }
-               }
-
-               if (AbsolutePathName.Buffer != NULL) 
-               {
-                       DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Create]", AbsolutePathName.Buffer );
-                       ExFreePool(AbsolutePathName.Buffer);
-               }
-
-               // Complete the request unless we are here as part of unwinding
-               //      when an exception condition was encountered, OR
-               //      if the request has been deferred (i.e. posted for later handling)
-               if (RC != STATUS_PENDING) 
-               {
-                       // If we acquired any FCB resources, release them now ...
-
-                       // If any intermediate (directory) open operations were performed,
-                       //      implement the corresponding close (do *not* however close
-                       //      the target you have opened on behalf of the caller ...).
-
-                       if (NT_SUCCESS(RC)) 
-                       {
-                               // Update the file object such that:
-                               //      (a) the FsContext field points to the NTRequiredFCB field
-                               //               in the FCB
-                               //      (b) the FsContext2 field points to the CCB created as a
-                               //               result of the open operation
-
-                               // If write-through was requested, then mark the file object
-                               //      appropriately
-                               if (WriteThroughRequested) 
-                               {
-                                       PtrNewFileObject->Flags |= FO_WRITE_THROUGH;
-                               }
-                               DebugTrace( DEBUG_TRACE_SPECIAL,   " === Create/Open successful", 0 );
-                       } 
-                       else 
-                       {
-                               DebugTrace( DEBUG_TRACE_SPECIAL,   " === Create/Open failed", 0 );
-                               // Perform failure related post-processing now
-                       }
-
-                       // As long as this unwinding is not being performed as a result of
-                       //      an exception condition, complete the IRP ...
-                       if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION)) 
-                       {
-                               PtrIrp->IoStatus.Status = RC;
-                               PtrIrp->IoStatus.Information = ReturnedInformation;
-                       
-                               // Free up the Irp Context
-                               Ext2ReleaseIrpContext(PtrIrpContext);
-                               
-                               // complete the IRP
-                               IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
-                       }
-               }
-       }
-       return(RC);
+    NTSTATUS        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+    UNICODE_STRING  FileName;
+    PEXT2_MCB       Mcb = NULL;
+    struct dentry  *de = NULL;
+
+    USHORT          i = 0, End;
+    ULONG           Inode;
+
+    BOOLEAN         bParent = FALSE;
+    BOOLEAN         bDirectory = FALSE;
+    BOOLEAN         LockAcquired = FALSE;
+
+    _SEH2_TRY {
+
+        ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE);
+        LockAcquired = TRUE;
+
+        *Ext2Mcb = NULL;
+
+        DEBUG(DL_RES, ("Ext2LookupFile: %wZ\n", FullName));
+
+        /* check names and parameters */
+        if (FullName->Buffer[0] == L'\\') {
+            Parent = Vcb->McbTree;
+        } else if (Parent) {
+            bParent = TRUE;
+        } else {
+            Parent = Vcb->McbTree;
+        }
+
+        /* make sure the parent is NULL */
+        if (!IsMcbDirectory(Parent)) {
+            Status =  STATUS_NOT_A_DIRECTORY;
+            _SEH2_LEAVE;
+        }
+
+        /* use symlink's target as parent directory */
+        if (IsMcbSymLink(Parent)) {
+            Parent = Parent->Target;
+            ASSERT(!IsMcbSymLink(Parent));
+            if (IsFileDeleted(Parent)) {
+                Status =  STATUS_NOT_A_DIRECTORY;
+                _SEH2_LEAVE;
+            }
+        }
+
+        if (NULL == Parent) {
+            Status =  STATUS_NOT_A_DIRECTORY;
+            _SEH2_LEAVE;
+        }
+
+        /* default is the parent Mcb*/
+        Ext2ReferMcb(Parent);
+        Mcb = Parent;
+
+        /* is empty file name or root node */
+        End = FullName->Length/sizeof(WCHAR);
+        if ( (End == 0) || (End == 1 &&
+                            FullName->Buffer[0] == L'\\')) {
+            Status = STATUS_SUCCESS;
+            _SEH2_LEAVE;
+        }
+
+        /* is a directory expected ? */
+        if (FullName->Buffer[End - 1] == L'\\') {
+            bDirectory = TRUE;
+        }
+
+        /* loop with every sub name */
+        while (i < End) {
+
+            USHORT Start = 0;
+
+            /* zero the prefix '\' */
+            while (i < End && FullName->Buffer[i] == L'\\') i++;
+            Start = i;
+
+            /* zero the suffix '\' */
+            while (i < End && (FullName->Buffer[i] != L'\\')) i++;
+
+            if (i > Start) {
+
+                FileName = *FullName;
+                FileName.Buffer += Start;
+                FileName.Length = (USHORT)((i - Start) * 2);
+
+                /* make sure the parent is NULL */
+                if (!IsMcbDirectory(Parent)) {
+                    Status =  STATUS_NOT_A_DIRECTORY;
+                    Ext2DerefMcb(Parent);
+                    break;
+                }
+
+                if (IsMcbSymLink(Parent)) {
+                    if (IsFileDeleted(Parent->Target)) {
+                        Status =  STATUS_NOT_A_DIRECTORY;
+                        Ext2DerefMcb(Parent);
+                        break;
+                    } else {
+                        Ext2ReferMcb(Parent->Target);
+                        Ext2DerefMcb(Parent);
+                        Parent = Parent->Target;
+                    }
+                }
+
+                /* search cached Mcb nodes */
+                Mcb = Ext2SearchMcbWithoutLock(Parent, &FileName);
+
+                if (Mcb) {
+
+                    /* derefer the parent Mcb */
+                    Ext2DerefMcb(Parent);
+                    Status = STATUS_SUCCESS;
+                    Parent = Mcb;
+
+                    if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target) &&
+                            (Mcb->Refercount == 1)) {
+
+                        ASSERT(Mcb->Target);
+                        ASSERT(Mcb->Target->Refercount > 0);
+                        Ext2DerefMcb(Mcb->Target);
+                        Mcb->Target = NULL;
+                        ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+                        SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+                        Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
+                    }
+
+                } else {
+
+                    /* need create new Mcb node */
+
+                    /* is a valid ext2 name */
+                    if (!Ext2IsNameValid(&FileName)) {
+                        Status = STATUS_OBJECT_NAME_INVALID;
+                        Ext2DerefMcb(Parent);
+                        break;
+                    }
+
+                    /* seach the disk */
+                    de = NULL;
+                    Status = Ext2ScanDir (
+                                 IrpContext,
+                                 Vcb,
+                                 Parent,
+                                 &FileName,
+                                 &Inode,
+                                 &de);
+
+                    if (NT_SUCCESS(Status)) {
+
+                        /* check it's real parent */
+                        ASSERT (!IsMcbSymLink(Parent));
+
+                        /* allocate Mcb ... */
+                        Mcb = Ext2AllocateMcb(Vcb, &FileName, &Parent->FullName, 0);
+                        if (!Mcb) {
+                            Status = STATUS_INSUFFICIENT_RESOURCES;
+                            Ext2DerefMcb(Parent);
+                            break;
+                        }
+                        Mcb->de = de;
+                        Mcb->de->d_inode = &Mcb->Inode;
+                        Mcb->Inode.i_ino = Inode;
+                        Mcb->Inode.i_sb = &Vcb->sb;
+                        de = NULL;
+
+                        /* load inode information */
+                        if (!Ext2LoadInode(Vcb, &Mcb->Inode)) {
+                            Status = STATUS_CANT_WAIT;
+                            Ext2DerefMcb(Parent);
+                            Ext2FreeMcb(Vcb, Mcb);
+                            break;
+                        }
+
+                        /* set inode attribute */
+                        if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) {
+                            SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+                        }
+
+                        if (S_ISDIR(Mcb->Inode.i_mode)) {
+                            SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+                        } else {
+                            SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
+                            if (!S_ISREG(Mcb->Inode.i_mode) &&
+                                    !S_ISLNK(Mcb->Inode.i_mode)) {
+                                SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+                            }
+                        }
+
+                        /* process special files under root directory */
+                        if (IsMcbRoot(Parent)) {
+                            /* set hidden and system attributes for
+                               Recycled / RECYCLER / pagefile.sys */
+                            BOOLEAN IsDirectory = IsMcbDirectory(Mcb);
+                            if (Ext2IsSpecialSystemFile(&Mcb->ShortName, IsDirectory)) {
+                                SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_HIDDEN);
+                                SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_SYSTEM);
+                            }
+                        }
+
+                        Mcb->CreationTime = Ext2NtTime(Mcb->Inode.i_ctime);
+                        Mcb->LastAccessTime = Ext2NtTime(Mcb->Inode.i_atime);
+                        Mcb->LastWriteTime = Ext2NtTime(Mcb->Inode.i_mtime);
+                        Mcb->ChangeTime = Ext2NtTime(Mcb->Inode.i_mtime);
+
+                        /* process symlink */
+                        if (S_ISLNK(Mcb->Inode.i_mode)) {
+                            Ext2FollowLink( IrpContext,
+                                            Vcb,
+                                            Parent,
+                                            Mcb,
+                                            Linkdep+1
+                                          );
+                        }
+
+                        /* add reference ... */
+                        Ext2ReferMcb(Mcb);
+
+                        /* add Mcb to it's parent tree*/
+                        Ext2InsertMcb(Vcb, Parent, Mcb);
+
+                        /* it's safe to deref Parent Mcb */
+                        Ext2DerefMcb(Parent);
+
+                        /* linking this Mcb*/
+                        Ext2LinkTailMcb(Vcb, Mcb);
+
+                        /* set parent to preare re-scan */
+                        Parent = Mcb;
+
+                    } else {
+
+                        /* derefernce it's parent */
+                        Ext2DerefMcb(Parent);
+                        break;
+                    }
+                }
+
+            } else {
+
+                /* there seems too many \ or / */
+                /* Mcb should be already set to Parent */
+                ASSERT(Mcb == Parent);
+                Status = STATUS_SUCCESS;
+                break;
+            }
+        }
+
+    } _SEH2_FINALLY {
+
+        if (de) {
+            Ext2FreeEntry(de);
+        }
+
+        if (NT_SUCCESS(Status)) {
+            if (bDirectory) {
+                if (IsMcbDirectory(Mcb)) {
+                    *Ext2Mcb = Mcb;
+                } else {
+                    Ext2DerefMcb(Mcb);
+                    Status = STATUS_NOT_A_DIRECTORY;
+                }
+            } else {
+                *Ext2Mcb = Mcb;
+            }
+        }
+
+        if (LockAcquired) {
+            ExReleaseResourceLite(&Vcb->McbLock);
+        }
+    } _SEH2_END;
+
+    return Status;
 }
 
 
-/*************************************************************************
-*
-* Function: Ext2OpenVolume()
-*
-* Description:
-*      Open a logical volume for the caller.
-*
-* Expected Interrupt Level (for execution) :
-*
-*  IRQL_PASSIVE_LEVEL
-*
-* Return Value: STATUS_SUCCESS/Error
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2OpenVolume(
-PtrExt2VCB                             PtrVCB,                                 // volume to be opened
-PtrExt2IrpContext              PtrIrpContext,                  // IRP context
-PIRP                                           PtrIrp,                                 // original/user IRP
-unsigned short                 ShareAccess,                    // share access
-PIO_SECURITY_CONTEXT   PtrSecurityContext,     // caller's context (incl access)
-PFILE_OBJECT                   PtrNewFileObject)               // I/O Mgr. created file object
+NTSTATUS
+Ext2ScanDir (
+    IN PEXT2_IRP_CONTEXT    IrpContext,
+    IN PEXT2_VCB            Vcb,
+    IN PEXT2_MCB            Parent,
+    IN PUNICODE_STRING      FileName,
+    OUT PULONG              Inode,
+    OUT struct dentry     **dentry
+)
+{
+    struct ext3_dir_entry_2 *dir_entry = NULL;
+    struct buffer_head     *bh = NULL;
+    struct dentry          *de = NULL;
+
+    NTSTATUS                Status = STATUS_NO_SUCH_FILE;
+
+    DEBUG(DL_RES, ("Ext2ScanDir: %wZ\\%wZ\n", &Parent->FullName, FileName));
+
+    _SEH2_TRY {
+
+        /* grab parent's reference first */
+        Ext2ReferMcb(Parent);
+
+        /* bad request ! Can a man be pregnant ? Maybe:) */
+        if (!IsMcbDirectory(Parent)) {
+            Status = STATUS_NOT_A_DIRECTORY;
+            _SEH2_LEAVE;
+        }
+
+        /* parent is a symlink ? */
+        if IsMcbSymLink(Parent) {
+            if (Parent->Target) {
+                Ext2ReferMcb(Parent->Target);
+                Ext2DerefMcb(Parent);
+                Parent = Parent->Target;
+                ASSERT(!IsMcbSymLink(Parent));
+            } else {
+                DbgBreak();
+                Status = STATUS_NOT_A_DIRECTORY;
+                _SEH2_LEAVE;
+            }
+        }
+
+        de = Ext2BuildEntry(Vcb, Parent, FileName);
+        if (!de) {
+            DEBUG(DL_ERR, ( "Ex2ScanDir: failed to allocate dentry.\n"));
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            _SEH2_LEAVE;
+        }
+
+        bh = ext3_find_entry(IrpContext, de, &dir_entry);
+        if (dir_entry) {
+            Status = STATUS_SUCCESS;
+            *Inode = dir_entry->inode;
+            *dentry = de;
+        }
+
+    } _SEH2_FINALLY {
+
+        Ext2DerefMcb(Parent);
+
+        if (bh)
+            brelse(bh);
+
+        if (!NT_SUCCESS(Status)) {
+            if (de)
+                Ext2FreeEntry(de);
+        }
+    } _SEH2_END;
+
+    return Status;
+}
+
+NTSTATUS Ext2AddDotEntries(struct ext2_icb *icb, struct inode *dir,
+                           struct inode *inode)
 {
-       NTSTATUS                                RC = STATUS_SUCCESS;
-       PtrExt2CCB                      PtrCCB = NULL;
-
-       try {
-               // check for exclusive open requests (using share modes supplied)
-               //      and determine whether it is even possible to open the volume
-               //      with the specified share modes (e.g. if caller does not
-               //      wish to share read or share write ...)
-       
-               //      Use IoCheckShareAccess() and IoSetShareAccess() here ...        
-               //      They are defined in the DDK.
-
-               //      You might also wish to check the caller's security context
-               //      to see whether you wish to allow the volume open or not.
-               //      Use the SeAccessCheck() routine described in the DDK for        this purpose.
-       
-               // create a new CCB structure
-               if (!(PtrCCB = Ext2AllocateCCB())) 
-               {
-                       RC = STATUS_INSUFFICIENT_RESOURCES;
-                       try_return();
-               }
-
-               // initialize the CCB
-               PtrCCB->PtrFCB = (PtrExt2FCB)(PtrVCB);
-               InsertTailList(&(PtrVCB->VolumeOpenListHead), &(PtrCCB->NextCCB));
-
-               // initialize the CCB to point to the file object
-               PtrCCB->PtrFileObject = PtrNewFileObject;
-
-               Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_VOLUME_OPEN);
-
-               // initialize the file object appropriately
-               PtrNewFileObject->FsContext = (void *)( &(PtrVCB->CommonVCBHeader) );
-               PtrNewFileObject->FsContext2 = (void *)(PtrCCB);
-
-               // increment the number of outstanding open operations on this
-               //      logical volume (i.e. volume cannot be dismounted)
-
-               //      You might be concerned about 32 bit wrap-around though I would
-               //      argue that it is unlikely ... :-)
-               (PtrVCB->VCBOpenCount)++;
-       
-               // now set the IoStatus Information value correctly in the IRP
-               //      (caller will set the status field)
-               PtrIrp->IoStatus.Information = FILE_OPENED;
-       
-               try_exit:       NOTHING;
-       } 
-       finally 
-       {
-               NOTHING;
-       }
-
-       return(RC);
+    struct ext3_dir_entry_2 * de;
+    struct buffer_head * bh;
+    ext3_lblk_t block = 0;
+    int rc = 0;
+
+    bh = ext3_append(icb, inode, &block, &rc);
+    if (!bh) {
+        goto errorout;
+    }
+
+    de = (struct ext3_dir_entry_2 *) bh->b_data;
+    de->inode = cpu_to_le32(inode->i_ino);
+    de->name_len = 1;
+    de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
+    strcpy (de->name, ".");
+    ext3_set_de_type(inode->i_sb, de, S_IFDIR);
+    de = (struct ext3_dir_entry_2 *)
+         ((char *) de + le16_to_cpu(de->rec_len));
+    de->inode = cpu_to_le32(dir->i_ino);
+    de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+    de->name_len = 2;
+    strcpy (de->name, "..");
+    ext3_set_de_type(inode->i_sb, de, S_IFDIR);
+    inode->i_nlink = 2;
+    set_buffer_dirty(bh);
+    ext3_mark_inode_dirty(icb, inode);
+
+errorout:
+    if (bh)
+        brelse (bh);
+
+    return Ext2WinntError(rc);
 }
 
-/*************************************************************************
-*
-* Function: Ext2InitializeFCB()
-*
-* Description:
-*      Initialize a new FCB structure and also the sent-in file object
-*      (if supplied)
-*
-* Expected Interrupt Level (for execution) :
-*
-*  IRQL_PASSIVE_LEVEL
-*
-* Return Value: None
-*
-*************************************************************************
-void Ext2InitializeFCB(
-PtrExt2FCB                             PtrNewFCB,              // FCB structure to be initialized
-PtrExt2VCB                             PtrVCB,                 // logical volume (VCB) pointer
-PtrExt2ObjectName              PtrObjectName,  // name of the object
-uint32                                 Flags,                  // is this a file/directory, etc.
-PFILE_OBJECT                   PtrFileObject)  // optional file object to be initialized
+NTSTATUS
+Ext2CreateFile(
+    PEXT2_IRP_CONTEXT IrpContext,
+    PEXT2_VCB         Vcb,
+    PBOOLEAN          OpPostIrp
+)
 {
-       // Initialize the disk dependent portion as you see fit
+    NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+    PIO_STACK_LOCATION  IrpSp;
+    PEXT2_FCB           Fcb = NULL;
+    PEXT2_MCB           Mcb = NULL;
+    PEXT2_MCB           SymLink = NULL;
+    PEXT2_CCB           Ccb = NULL;
 
-       // Initialize the two ERESOURCE objects
-       ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.MainResource));
-       ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.PagingIoResource));
+    PEXT2_FCB           ParentFcb = NULL;
+    PEXT2_MCB           ParentMcb = NULL;
 
-       PtrNewFCB->FCBFlags |= EXT2_INITIALIZED_MAIN_RESOURCE | EXT2_INITIALIZED_PAGING_IO_RESOURCE | Flags;
+    UNICODE_STRING      FileName;
+    PIRP                Irp;
+
+    ULONG               Options;
+    ULONG               CreateDisposition;
+
+    BOOLEAN             bParentFcbCreated = FALSE;
+
+#ifndef __REACTOS__
+    BOOLEAN             bDir = FALSE;
+#endif
+    BOOLEAN             bFcbAllocated = FALSE;
+    BOOLEAN             bCreated = FALSE;
+    BOOLEAN             bMainResourceAcquired = FALSE;
 
-       PtrNewFCB->PtrVCB = PtrVCB;
+    BOOLEAN             OpenDirectory;
+    BOOLEAN             OpenTargetDirectory;
+    BOOLEAN             CreateDirectory;
+    BOOLEAN             SequentialOnly;
+    BOOLEAN             NoIntermediateBuffering;
+    BOOLEAN             IsPagingFile;
+    BOOLEAN             DirectoryFile;
+    BOOLEAN             NonDirectoryFile;
+    BOOLEAN             NoEaKnowledge;
+    BOOLEAN             DeleteOnClose;
+    BOOLEAN             TemporaryFile;
+    BOOLEAN             CaseSensitive;
 
-       // caller MUST ensure that VCB has been acquired exclusively
-       InsertTailList(&(PtrVCB->FCBListHead), &(PtrNewFCB->NextFCB));
+    ACCESS_MASK         DesiredAccess;
+    ULONG               ShareAccess;
 
-       // initialize the various list heads
-       InitializeListHead(&(PtrNewFCB->CCBListHead));
+    RtlZeroMemory(&FileName, sizeof(UNICODE_STRING));
 
-//     PtrNewFCB->ReferenceCount = 1;
-//     PtrNewFCB->OpenHandleCount = 1;
+    Irp = IrpContext->Irp;
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
-       if( PtrObjectName )
-       {
-               PtrNewFCB->FCBName = PtrObjectName;
-       }
+    Options  = IrpSp->Parameters.Create.Options;
 
-       if ( PtrFileObject )
-       {
-               PtrFileObject->FsContext = (void *)(&(PtrNewFCB->NTRequiredFCB));
-       }
+    DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
+    OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
 
-       return;
+    NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
+    SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
+    NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
+    NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
+    DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
+
+    CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
+
+    TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
+                             FILE_ATTRIBUTE_TEMPORARY );
+
+    CreateDisposition = (Options >> 24) & 0x000000ff;
+
+    IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
+
+    CreateDirectory = (BOOLEAN)(DirectoryFile &&
+                                ((CreateDisposition == FILE_CREATE) ||
+                                 (CreateDisposition == FILE_OPEN_IF)));
+
+    OpenDirectory   = (BOOLEAN)(DirectoryFile &&
+                                ((CreateDisposition == FILE_OPEN) ||
+                                 (CreateDisposition == FILE_OPEN_IF)));
+
+    DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+    ShareAccess   = IrpSp->Parameters.Create.ShareAccess;
+
+    *OpPostIrp = FALSE;
+
+    _SEH2_TRY {
+
+        FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength;
+        FileName.Length = IrpSp->FileObject->FileName.Length;
+
+        if (IrpSp->FileObject->RelatedFileObject) {
+            ParentFcb = (PEXT2_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext);
+        }
+
+        if (ParentFcb) {
+            ParentMcb = ParentFcb->Mcb;
+            SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+            Ext2ReferMcb(ParentMcb);
+        }
+
+        if (FileName.Length == 0) {
+
+            if (ParentFcb) {
+                Mcb = ParentFcb->Mcb;
+                Ext2ReferMcb(Mcb);
+                Status = STATUS_SUCCESS;
+                goto McbExisting;
+            } else {
+                DbgBreak();
+                Status = STATUS_INVALID_PARAMETER;
+                _SEH2_LEAVE;
+            }
+        }
+
+        FileName.Buffer = Ext2AllocatePool(
+                              PagedPool,
+                              FileName.MaximumLength,
+                              EXT2_FNAME_MAGIC
+                          );
+
+        if (!FileName.Buffer) {
+            DEBUG(DL_ERR, ( "Ex2CreateFile: failed to allocate FileName.\n"));
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            _SEH2_LEAVE;
+        }
+
+        INC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
+
+        RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
+        RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
+
+        if (ParentFcb && FileName.Buffer[0] == L'\\') {
+            Status = STATUS_INVALID_PARAMETER;
+            _SEH2_LEAVE;
+        }
+
+        if ((FileName.Length > sizeof(WCHAR)) &&
+                (FileName.Buffer[1] == L'\\') &&
+                (FileName.Buffer[0] == L'\\')) {
+
+            FileName.Length -= sizeof(WCHAR);
+
+            RtlMoveMemory( &FileName.Buffer[0],
+                           &FileName.Buffer[1],
+                           FileName.Length );
+
+            //
+            //  Bad Name if there are still beginning backslashes.
+            //
+
+            if ((FileName.Length > sizeof(WCHAR)) &&
+                    (FileName.Buffer[1] == L'\\') &&
+                    (FileName.Buffer[0] == L'\\')) {
+
+                Status = STATUS_OBJECT_NAME_INVALID;
+                _SEH2_LEAVE;
+            }
+        }
+
+        if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID)) {
+            Status = STATUS_NOT_IMPLEMENTED;
+            _SEH2_LEAVE;
+        }
+
+        DEBUG(DL_INF, ( "Ext2CreateFile: %wZ Paging=%d Option: %xh:"
+                        "Dir=%d NonDir=%d OpenTarget=%d NC=%d DeleteOnClose=%d\n",
+                        &FileName, IsPagingFile, IrpSp->Parameters.Create.Options,
+                        DirectoryFile, NonDirectoryFile, OpenTargetDirectory,
+                        NoIntermediateBuffering, DeleteOnClose ));
+
+        DEBUG(DL_RES, ("Ext2CreateFile: Lookup 1st: %wZ at %S\n",
+                       &FileName, ParentMcb ? ParentMcb->FullName.Buffer : L" "));
+        Status = Ext2LookupFile(
+                     IrpContext,
+                     Vcb,
+                     &FileName,
+                     ParentMcb,
+                     &Mcb,
+                     0 );
+McbExisting:
+
+        if (!NT_SUCCESS(Status)) {
+
+            UNICODE_STRING  PathName;
+            UNICODE_STRING  RealName;
+            UNICODE_STRING  RemainName;
+
+#ifndef __REACTOS__
+            LONG            i = 0;
+#endif
+            PathName = FileName;
+            Mcb = NULL;
+
+            if (PathName.Buffer[PathName.Length/2 - 1] == L'\\') {
+                if (DirectoryFile) {
+                    PathName.Length -=2;
+                    PathName.Buffer[PathName.Length/2] = 0;
+                } else {
+                    DirectoryFile = TRUE;
+                }
+            }
+
+            if (!ParentMcb) {
+                if (PathName.Buffer[0] != L'\\') {
+                    Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                    _SEH2_LEAVE;
+                } else {
+                    ParentMcb = Vcb->McbTree;
+                    Ext2ReferMcb(ParentMcb);
+                }
+            }
+
+Dissecting:
+
+            FsRtlDissectName(PathName, &RealName, &RemainName);
+
+            if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) ||
+                    (RealName.Length >= 256 * sizeof(WCHAR))) {
+                Status = STATUS_OBJECT_NAME_INVALID;
+                _SEH2_LEAVE;
+            }
+
+            if (RemainName.Length != 0) {
+
+                PEXT2_MCB   RetMcb = NULL;
+
+                DEBUG(DL_RES, ("Ext2CreateFile: Lookup 2nd: %wZ\\%wZ\n",
+                               &ParentMcb->FullName, &RealName));
+
+                Status = Ext2LookupFile (
+                             IrpContext,
+                             Vcb,
+                             &RealName,
+                             ParentMcb,
+                             &RetMcb,
+                             0);
+
+                /* quit name resolving loop */
+                if (!NT_SUCCESS(Status)) {
+                    if (Status == STATUS_NO_SUCH_FILE && RemainName.Length != 0) {
+                        Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                    }
+                    _SEH2_LEAVE;
+                }
+
+                /* deref ParentMcb */
+                Ext2DerefMcb(ParentMcb);
+
+                /* RetMcb is already refered */
+                ParentMcb = RetMcb;
+                PathName  = RemainName;
+
+                /* symlink must use it's target */
+                if (IsMcbSymLink(ParentMcb)) {
+                    Ext2ReferMcb(ParentMcb->Target);
+                    Ext2DerefMcb(ParentMcb);
+                    ParentMcb = ParentMcb->Target;
+                    ASSERT(!IsMcbSymLink(ParentMcb));
+                }
+
+                goto Dissecting;
+            }
+
+            /* is name valid */
+            if ( FsRtlDoesNameContainWildCards(&RealName) ||
+                    !Ext2IsNameValid(&RealName)) {
+                Status = STATUS_OBJECT_NAME_INVALID;
+                _SEH2_LEAVE;
+            }
+
+            /* clear BUSY bit from original ParentFcb */
+            if (ParentFcb) {
+                ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+            }
+
+            /* get the ParentFcb, allocate it if needed ... */
+            ParentFcb = ParentMcb->Fcb;
+            if (!ParentFcb) {
+                ParentFcb = Ext2AllocateFcb(Vcb, ParentMcb);
+                if (!ParentFcb) {
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    _SEH2_LEAVE;
+                }
+                bParentFcbCreated = TRUE;
+                Ext2ReferXcb(&ParentFcb->ReferenceCount);
+            }
+            SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+
+            // We need to create a new one ?
+            if ((CreateDisposition == FILE_CREATE ) ||
+                    (CreateDisposition == FILE_SUPERSEDE) ||
+                    (CreateDisposition == FILE_OPEN_IF) ||
+                    (CreateDisposition == FILE_OVERWRITE_IF)) {
+
+                if (IsVcbReadOnly(Vcb)) {
+                    Status = STATUS_MEDIA_WRITE_PROTECTED;
+                    _SEH2_LEAVE;
+                }
+
+                if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(ParentFcb->Mcb->Inode.i_mode)) {
+                    Status = STATUS_ACCESS_DENIED;
+                    _SEH2_LEAVE;
+                }
+
+                if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
+                    IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
+                                                  Vcb->Vpb->RealDevice );
+                    SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+                    Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+                }
+
+                if (DirectoryFile) {
+                    if (TemporaryFile) {
+                        DbgBreak();
+                        Status = STATUS_INVALID_PARAMETER;
+                        _SEH2_LEAVE;
+                    }
+                }
+
+                if (!ParentFcb) {
+                    Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                    _SEH2_LEAVE;
+                }
+
+                /* allocate inode and construct entry for this file */
+                Status = Ext2CreateInode(
+                             IrpContext,
+                             Vcb,
+                             ParentFcb,
+                             DirectoryFile ? EXT2_FT_DIR : EXT2_FT_REG_FILE,
+                             IrpSp->Parameters.Create.FileAttributes,
+                             &RealName
+                         );
+
+                if (!NT_SUCCESS(Status)) {
+                    DbgBreak();
+                    _SEH2_LEAVE;
+                }
+
+                bCreated = TRUE;
+                DEBUG(DL_RES, ("Ext2CreateFile: Confirm creation: %wZ\\%wZ\n",
+                               &ParentMcb->FullName, &RealName));
+
+                Irp->IoStatus.Information = FILE_CREATED;
+                Status = Ext2LookupFile (
+                             IrpContext,
+                             Vcb,
+                             &RealName,
+                             ParentMcb,
+                             &Mcb,
+                             0);
+                if (!NT_SUCCESS(Status)) {
+                    DbgBreak();
+                }
+
+            } else if (OpenTargetDirectory) {
+
+                if (IsVcbReadOnly(Vcb)) {
+                    Status = STATUS_MEDIA_WRITE_PROTECTED;
+                    _SEH2_LEAVE;
+                }
+
+                if (!ParentFcb) {
+                    Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                    _SEH2_LEAVE;
+                }
+
+                RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
+                               IrpSp->FileObject->FileName.MaximumLength);
+                IrpSp->FileObject->FileName.Length = RealName.Length;
+
+                RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
+                               RealName.Buffer,
+                               RealName.Length );
+
+                Fcb = ParentFcb;
+                Mcb = Fcb->Mcb;
+                Ext2ReferMcb(Mcb);
+
+                Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
+                Status = STATUS_SUCCESS;
+
+            } else {
+
+                Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                _SEH2_LEAVE;
+            }
+
+        } else { // File / Dir already exists.
+
+            /* here already get Mcb referred */
+            if (OpenTargetDirectory) {
+
+                UNICODE_STRING  RealName = FileName;
+                USHORT          i = 0;
+
+                while (RealName.Buffer[RealName.Length/2 - 1] == L'\\') {
+                    RealName.Length -= sizeof(WCHAR);
+                    RealName.Buffer[RealName.Length/2] = 0;
+                }
+                i = RealName.Length/2;
+                while (i > 0 && RealName.Buffer[i - 1] != L'\\')
+                    i--;
+
+                if (IsVcbReadOnly(Vcb)) {
+                    Status = STATUS_MEDIA_WRITE_PROTECTED;
+                    Ext2DerefMcb(Mcb);
+                    _SEH2_LEAVE;
+                }
+
+                Irp->IoStatus.Information = FILE_EXISTS;
+                Status = STATUS_SUCCESS;
+
+                RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
+                               IrpSp->FileObject->FileName.MaximumLength);
+                IrpSp->FileObject->FileName.Length = RealName.Length - i * sizeof(WCHAR);
+                RtlCopyMemory( IrpSp->FileObject->FileName.Buffer, &RealName.Buffer[i],
+                               IrpSp->FileObject->FileName.Length );
+
+                // use's it's parent since it's open-target operation
+                Ext2ReferMcb(Mcb->Parent);
+                Ext2DerefMcb(Mcb);
+                Mcb = Mcb->Parent;
+
+                goto Openit;
+            }
+
+            // We can not create if one exists
+            if (CreateDisposition == FILE_CREATE) {
+                Irp->IoStatus.Information = FILE_EXISTS;
+                Status = STATUS_OBJECT_NAME_COLLISION;
+                Ext2DerefMcb(Mcb);
+                _SEH2_LEAVE;
+            }
+
+            /* directory forbits us to do the followings ... */
+            if (IsMcbDirectory(Mcb)) {
+
+                if ((CreateDisposition != FILE_OPEN) &&
+                        (CreateDisposition != FILE_OPEN_IF)) {
+
+                    Status = STATUS_OBJECT_NAME_COLLISION;
+                    Ext2DerefMcb(Mcb);
+                    _SEH2_LEAVE;
+                }
+
+                if (NonDirectoryFile) {
+                    Status = STATUS_FILE_IS_A_DIRECTORY;
+                    Ext2DerefMcb(Mcb);
+                    _SEH2_LEAVE;
+                }
+
+                if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
+
+                    if (OpenTargetDirectory) {
+                        DbgBreak();
+                        Status = STATUS_INVALID_PARAMETER;
+                        Ext2DerefMcb(Mcb);
+                        _SEH2_LEAVE;
+                    }
+                }
+
+            } else {
+
+                if (DirectoryFile) {
+                    Status = STATUS_NOT_A_DIRECTORY;;
+                    Ext2DerefMcb(Mcb);
+                    _SEH2_LEAVE;
+                }
+            }
+
+            Irp->IoStatus.Information = FILE_OPENED;
+        }
+
+Openit:
+        /* Mcb should already be referred and symlink is too */
+        if (Mcb) {
+
+            ASSERT(Mcb->Refercount > 0);
+
+            /* refer it's target if it's a symlink, so both refered */
+            if (IsMcbSymLink(Mcb)) {
+                if (IsFileDeleted(Mcb->Target)) {
+                    DbgBreak();
+                    SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
+                    ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
+                    Ext2DerefMcb(Mcb->Target);
+                    Mcb->Target = NULL;
+                } else {
+                    SymLink = Mcb;
+                    Mcb = Mcb->Target;
+                    Ext2ReferMcb(Mcb);
+                    ASSERT (!IsMcbSymLink(Mcb));
+                }
+            }
+
+            // Check readonly flag
+            if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) {
+                if (BooleanFlagOn(DesiredAccess,  FILE_WRITE_DATA | FILE_APPEND_DATA |
+                                  FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)) {
+                    Status = STATUS_ACCESS_DENIED;
+                    _SEH2_LEAVE;
+                } else if (IsFlagOn(Options, FILE_DELETE_ON_CLOSE )) {
+                    Status = STATUS_CANNOT_DELETE;
+                    _SEH2_LEAVE;
+                }
+            }
+
+            Fcb = Mcb->Fcb;
+            if (Fcb == NULL) {
+
+                /* allocate Fcb for this file */
+                Fcb = Ext2AllocateFcb (Vcb, Mcb);
+                if (Fcb) {
+                    bFcbAllocated = TRUE;
+                } else {
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                }
+            } else {
+                if (IsPagingFile) {
+                    Status = STATUS_SHARING_VIOLATION;
+                    Fcb = NULL;
+                }
+            }
+
+            /* Now it's safe to defer Mcb */
+            Ext2DerefMcb(Mcb);
+        }
+
+        if (Fcb) {
+
+            /* grab Fcb's reference first to avoid the race between
+               Ext2Close  (it could free the Fcb we are accessing) */
+            Ext2ReferXcb(&Fcb->ReferenceCount);
+
+            ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+            bMainResourceAcquired = TRUE;
+
+            /* Open target directory ? */
+            if (NULL == Mcb) {
+                DbgBreak();
+                Mcb = Fcb->Mcb;
+            }
+
+            /* check Mcb reference */
+            ASSERT(Fcb->Mcb->Refercount > 0);
+
+            /* file delted ? */
+            if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) {
+                Status = STATUS_FILE_DELETED;
+                _SEH2_LEAVE;
+            }
+
+            if (DeleteOnClose && NULL == SymLink) {
+                Status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
+                if (!NT_SUCCESS(Status)) {
+                    _SEH2_LEAVE;
+                }
+            }
+
+            /* check access and oplock access for opened files */
+            if (!bFcbAllocated  && !IsDirectory(Fcb)) {
+
+                /* whether there's batch oplock grabed on the file */
+                if (FsRtlCurrentBatchOplock(&Fcb->Oplock)) {
+
+                    Irp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
+
+                    /* break the batch lock if the sharing check fails */
+                    Status = FsRtlCheckOplock( &Fcb->Oplock,
+                                               IrpContext->Irp,
+                                               IrpContext,
+                                               Ext2OplockComplete,
+                                               Ext2LockIrp );
+
+                    if ( Status != STATUS_SUCCESS &&
+                            Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
+                        *OpPostIrp = TRUE;
+                        _SEH2_LEAVE;
+                    }
+                }
+            }
+
+            if (bCreated) {
+
+                //
+                //  This file is just created.
+                //
+
+                if (DirectoryFile) {
+
+                    Status = Ext2AddDotEntries(IrpContext, &ParentMcb->Inode, &Mcb->Inode);
+                    if (!NT_SUCCESS(Status)) {
+                        Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
+                        _SEH2_LEAVE;
+                    }
+
+                } else {
+
+                    if ((LONGLONG)ext3_free_blocks_count(SUPER_BLOCK) <=
+                            Ext2TotalBlocks(Vcb, &Irp->Overlay.AllocationSize, NULL)) {
+                        DbgBreak();
+                        Status = STATUS_DISK_FULL;
+                        _SEH2_LEAVE;
+                    }
+
+                    /* disable data blocks allocation */
+#if 0
+                    Fcb->Header.AllocationSize.QuadPart =
+                        Irp->Overlay.AllocationSize.QuadPart;
+
+                    if (Fcb->Header.AllocationSize.QuadPart > 0) {
+                        Status = Ext2ExpandFile(IrpContext,
+                                                Vcb,
+                                                Fcb->Mcb,
+                                                &(Fcb->Header.AllocationSize)
+                                               );
+                        SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
+                        if (!NT_SUCCESS(Status)) {
+                            Fcb->Header.AllocationSize.QuadPart = 0;
+                            Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb,
+                                             &Fcb->Header.AllocationSize);
+                            _SEH2_LEAVE;
+                        }
+                    }
+#endif
+                }
+
+            } else {
+
+                //
+                //  This file alreayd exists.
+                //
+
+                if (DeleteOnClose) {
+
+                    if (IsVcbReadOnly(Vcb)) {
+                        Status = STATUS_MEDIA_WRITE_PROTECTED;
+                        _SEH2_LEAVE;
+                    }
+
+                    if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
+                        Status = STATUS_MEDIA_WRITE_PROTECTED;
+
+                        IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
+                                                      Vcb->Vpb->RealDevice );
+
+                        SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+
+                        Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+                    }
+
+                } else {
+
+                    //
+                    // Just to Open file (Open/OverWrite ...)
+                    //
+
+                    if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
+                                                         FO_NO_INTERMEDIATE_BUFFERING))) {
+                        Fcb->Header.IsFastIoPossible = FastIoIsPossible;
+
+                        if (Fcb->SectionObject.DataSectionObject != NULL) {
+
+                            if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) {
+
+                                if (!IsVcbReadOnly(Vcb)) {
+                                    CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
+                                    ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+                                }
+
+                                CcPurgeCacheSection(&Fcb->SectionObject,
+                                                    NULL,
+                                                    0,
+                                                    FALSE );
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (!IsDirectory(Fcb)) {
+
+                if (!IsVcbReadOnly(Vcb)) {
+                    if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile) {
+                        DesiredAccess |= DELETE;
+                    } else if (((CreateDisposition == FILE_OVERWRITE) ||
+                                (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
+                        DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
+                                          FILE_WRITE_ATTRIBUTES );
+                    }
+                }
+
+                if (!bFcbAllocated) {
+
+                    //
+                    //  check the oplock state of the file
+                    //
+                    Status = FsRtlCheckOplock(  &Fcb->Oplock,
+                                                IrpContext->Irp,
+                                                IrpContext,
+                                                Ext2OplockComplete,
+                                                Ext2LockIrp );
+
+                    if ( Status != STATUS_SUCCESS &&
+                            Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
+                        *OpPostIrp = TRUE;
+                        _SEH2_LEAVE;
+                    }
+                }
+            }
+
+            if (Fcb->OpenHandleCount > 0) {
+
+                /* check the shrae access conflicts */
+                Status = IoCheckShareAccess( DesiredAccess,
+                                             ShareAccess,
+                                             IrpSp->FileObject,
+                                             &(Fcb->ShareAccess),
+                                             TRUE );
+                if (!NT_SUCCESS(Status)) {
+                    _SEH2_LEAVE;
+                }
+
+            } else {
+
+                /* set share access rights */
+                IoSetShareAccess( DesiredAccess,
+                                  ShareAccess,
+                                  IrpSp->FileObject,
+                                  &(Fcb->ShareAccess) );
+            }
+
+            Ccb = Ext2AllocateCcb(SymLink);
+            if (!Ccb) {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                DbgBreak();
+                _SEH2_LEAVE;
+            }
+
+            if (DeleteOnClose)
+                SetLongFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
+
+            if (SymLink)
+                Ccb->filp.f_dentry = SymLink->de;
+            else
+                Ccb->filp.f_dentry = Fcb->Mcb->de;
+
+            Ccb->filp.f_version = Fcb->Mcb->Inode.i_version;
+            Ext2ReferXcb(&Fcb->OpenHandleCount);
+            Ext2ReferXcb(&Fcb->ReferenceCount);
+
+            if (!IsDirectory(Fcb)) {
+                if (NoIntermediateBuffering) {
+                    Fcb->NonCachedOpenCount++;
+                    SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
+                } else {
+                    SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
+                }
+            }
+
+            Ext2ReferXcb(&Vcb->OpenHandleCount);
+            Ext2ReferXcb(&Vcb->ReferenceCount);
+
+            IrpSp->FileObject->FsContext = (void*) Fcb;
+            IrpSp->FileObject->FsContext2 = (void*) Ccb;
+            IrpSp->FileObject->PrivateCacheMap = NULL;
+            IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
+
+            DEBUG(DL_INF, ( "Ext2CreateFile: %wZ OpenCount=%u ReferCount=%u NonCachedCount=%u\n",
+                            &Fcb->Mcb->FullName, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount));
+
+            Status = STATUS_SUCCESS;
+
+            if (bCreated) {
+
+                if (IsDirectory(Fcb)) {
+                    Ext2NotifyReportChange(
+                        IrpContext,
+                        Vcb,
+                        Fcb->Mcb,
+                        FILE_NOTIFY_CHANGE_DIR_NAME,
+                        FILE_ACTION_ADDED );
+                } else {
+                    Ext2NotifyReportChange(
+                        IrpContext,
+                        Vcb,
+                        Fcb->Mcb,
+                        FILE_NOTIFY_CHANGE_FILE_NAME,
+                        FILE_ACTION_ADDED );
+                }
+
+            } else if (!IsDirectory(Fcb)) {
+
+                if ( DeleteOnClose ||
+                        IsFlagOn(DesiredAccess, FILE_WRITE_DATA) ||
+                        (CreateDisposition == FILE_OVERWRITE) ||
+                        (CreateDisposition == FILE_OVERWRITE_IF)) {
+                    if (!MmFlushImageSection( &Fcb->SectionObject,
+                                              MmFlushForWrite )) {
+
+                        Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
+                                 STATUS_SHARING_VIOLATION;
+                        _SEH2_LEAVE;
+                    }
+                }
+
+                if ((CreateDisposition == FILE_SUPERSEDE) ||
+                        (CreateDisposition == FILE_OVERWRITE) ||
+                        (CreateDisposition == FILE_OVERWRITE_IF)) {
+
+                    if (IsDirectory(Fcb)) {
+                        Status = STATUS_FILE_IS_A_DIRECTORY;
+                        _SEH2_LEAVE;
+                    }
+
+                    if (SymLink != NULL) {
+                        DbgBreak();
+                        Status = STATUS_INVALID_PARAMETER;
+                        _SEH2_LEAVE;
+                    }
+
+                    if (IsVcbReadOnly(Vcb)) {
+                        Status = STATUS_MEDIA_WRITE_PROTECTED;
+                        _SEH2_LEAVE;
+                    }
+
+                    if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
+
+                        IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
+                                                      Vcb->Vpb->RealDevice );
+                        SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+                        Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+                    }
+
+                    Status = Ext2SupersedeOrOverWriteFile(
+                                 IrpContext,
+                                 IrpSp->FileObject,
+                                 Vcb,
+                                 Fcb,
+                                 &Irp->Overlay.AllocationSize,
+                                 CreateDisposition );
+
+                    if (!NT_SUCCESS(Status)) {
+                        DbgBreak();
+                        _SEH2_LEAVE;
+                    }
+
+                    Ext2NotifyReportChange(
+                        IrpContext,
+                        Vcb,
+                        Fcb->Mcb,
+                        FILE_NOTIFY_CHANGE_LAST_WRITE |
+                        FILE_NOTIFY_CHANGE_ATTRIBUTES |
+                        FILE_NOTIFY_CHANGE_SIZE,
+                        FILE_ACTION_MODIFIED );
+
+
+                    if (CreateDisposition == FILE_SUPERSEDE) {
+                        Irp->IoStatus.Information = FILE_SUPERSEDED;
+                    } else {
+                        Irp->IoStatus.Information = FILE_OVERWRITTEN;
+                    }
+                }
+            }
+
+        } else {
+            DbgBreak();
+            _SEH2_LEAVE;
+        }
+
+    } _SEH2_FINALLY {
+
+
+        if (ParentMcb) {
+            Ext2DerefMcb(ParentMcb);
+        }
+
+        /* cleanup Fcb and Ccb, Mcb if necessary */
+        if (!NT_SUCCESS(Status)) {
+
+            if (Ccb != NULL) {
+
+                DbgBreak();
+
+                ASSERT(Fcb != NULL);
+                ASSERT(Fcb->Mcb != NULL);
+
+                DEBUG(DL_ERR, ("Ext2CreateFile: failed to create %wZ status = %xh\n",
+                               &Fcb->Mcb->FullName, Status));
+
+                Ext2DerefXcb(&Fcb->OpenHandleCount);
+                Ext2DerefXcb(&Fcb->ReferenceCount);
+
+                if (!IsDirectory(Fcb)) {
+                    if (NoIntermediateBuffering) {
+                        Fcb->NonCachedOpenCount--;
+                    } else {
+                        ClearFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
+                    }
+                }
+
+                Ext2DerefXcb(&Vcb->OpenHandleCount);
+                Ext2DerefXcb(&Vcb->ReferenceCount);
+
+                IoRemoveShareAccess(IrpSp->FileObject, &Fcb->ShareAccess);
+
+                IrpSp->FileObject->FsContext = NULL;
+                IrpSp->FileObject->FsContext2 = NULL;
+                IrpSp->FileObject->PrivateCacheMap = NULL;
+                IrpSp->FileObject->SectionObjectPointer = NULL;
+
+                Ext2FreeCcb(Vcb, Ccb);
+            }
+        }
+
+        if (Fcb && Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
+
+            if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
+
+                LARGE_INTEGER Size;
+                ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
+                _SEH2_TRY {
+                    Size.QuadPart = 0;
+                    Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+                } _SEH2_FINALLY {
+                    ExReleaseResourceLite(&Fcb->PagingIoResource);
+                } _SEH2_END;
+            }
+
+            if (bCreated) {
+                Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
+            }
+
+            Ext2FreeFcb(Fcb);
+            Fcb = NULL;
+            bMainResourceAcquired = FALSE;
+        }
+
+        if (bMainResourceAcquired) {
+            ExReleaseResourceLite(&Fcb->MainResource);
+        }
+
+        /* free file name buffer */
+        if (FileName.Buffer) {
+            DEC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
+            Ext2FreePool(FileName.Buffer, EXT2_FNAME_MAGIC);
+        }
+
+        /* dereference parent Fcb, free it if it goes to zero */
+        if (ParentFcb) {
+            ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
+            if (bParentFcbCreated) {
+                if (Ext2DerefXcb(&ParentFcb->ReferenceCount) == 0) {
+                    Ext2FreeFcb(ParentFcb);
+                }
+            }
+        }
+
+        /* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer
+           it already. It fails, we need release the refer to let it freed */
+        if (SymLink) {
+            Ext2DerefMcb(SymLink);
+        }
+    } _SEH2_END;
+
+    return Status;
 }
-*/
-
-/*************************************************************************
-*
-* Function: Ext2OpenRootDirectory()
-*
-* Description:
-*      Open the root directory for a volume
-*      
-*
-* Expected Interrupt Level (for execution) :
-*
-*  ???
-*
-* Return Value: None
-*
-*************************************************************************/
-NTSTATUS NTAPI Ext2OpenRootDirectory(
-       PtrExt2VCB                              PtrVCB,                                 // volume 
-       PtrExt2IrpContext               PtrIrpContext,                  // IRP context
-       PIRP                                    PtrIrp,                                 // original/user IRP
-       unsigned short                  ShareAccess,                    // share access
-       PIO_SECURITY_CONTEXT    PtrSecurityContext,             // caller's context (incl access)
-       PFILE_OBJECT                    PtrNewFileObject                // I/O Mgr. created file object
-       )
+
+NTSTATUS
+Ext2CreateVolume(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
 {
-       //      Declerations...
-       PtrExt2CCB PtrCCB;
-       
-       ASSERT( PtrVCB );
-       ASSERT( PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
-       ASSERT( PtrVCB->PtrRootDirectoryFCB );
-       AssertFCB( PtrVCB->PtrRootDirectoryFCB );
-               
-       PtrVCB->PtrRootDirectoryFCB->INodeNo = EXT2_ROOT_INO;
-       
-       //      Create a new CCB...
-       Ext2CreateNewCCB( &PtrCCB, PtrVCB->PtrRootDirectoryFCB, PtrNewFileObject);
-       PtrNewFileObject->FsContext = (void *) &(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.CommonFCBHeader);
-       PtrVCB->PtrRootDirectoryFCB->FCBFlags |= EXT2_FCB_DIRECTORY;
-       PtrNewFileObject->FsContext2 = (void *) PtrCCB;
-       PtrNewFileObject->SectionObjectPointer = &PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.SectionObject;
-       PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
-
-       Ext2CopyUnicodeString( &(PtrCCB->AbsolutePathName), &PtrVCB->PtrRootDirectoryFCB->FCBName->ObjectName );
-
-
-       return STATUS_SUCCESS;
-}
+    PIO_STACK_LOCATION  IrpSp;
+    PIRP                Irp;
+    PEXT2_CCB           Ccb;
 
+    NTSTATUS            Status;
 
+    ACCESS_MASK         DesiredAccess;
+    ULONG               ShareAccess;
 
-PtrExt2FCB NTAPI Ext2LocateChildFCBInCore(
-       PtrExt2VCB                              PtrVCB, 
-       PUNICODE_STRING                 PtrName, 
-       ULONG                                   ParentInodeNo )
-{
+    ULONG               Options;
+    BOOLEAN             DirectoryFile;
+    BOOLEAN             OpenTargetDirectory;
 
-       PtrExt2FCB PtrFCB = NULL;
-       PLIST_ENTRY     PtrEntry;
-
-       if( IsListEmpty( &(PtrVCB->FCBListHead) ) )
-       {
-               return NULL;    //      Failure;
-       }
-
-       for( PtrEntry = PtrVCB->FCBListHead.Flink; 
-                       PtrEntry != &PtrVCB->FCBListHead; 
-                       PtrEntry = PtrEntry->Flink )
-       {
-               PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, NextFCB );
-               ASSERT( PtrFCB );
-               if( PtrFCB->ParentINodeNo == ParentInodeNo )
-               {
-                       if( RtlCompareUnicodeString( &PtrFCB->FCBName->ObjectName, PtrName, TRUE ) == 0 )
-                               return PtrFCB;
-               }
-       }
-
-       return NULL;
-}
+    ULONG               CreateDisposition;
 
-PtrExt2FCB NTAPI Ext2LocateFCBInCore(
-       PtrExt2VCB                              PtrVCB, 
-       ULONG                                   InodeNo )
-{
-       PtrExt2FCB PtrFCB = NULL;
-       PLIST_ENTRY     PtrEntry;
-
-       if( IsListEmpty( &(PtrVCB->FCBListHead) ) )
-       {
-               return NULL;    //      Failure;
-       }
-
-       for( PtrEntry = PtrVCB->FCBListHead.Flink; 
-                       PtrEntry != &PtrVCB->FCBListHead; 
-                       PtrEntry = PtrEntry->Flink )
-       {
-               PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, NextFCB );
-               ASSERT( PtrFCB );
-               if( PtrFCB->INodeNo == InodeNo )
-               {
-                       return PtrFCB;
-               }
-       }
-
-       return NULL;
-}
+    Irp = IrpContext->Irp;
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
+    Options  = IrpSp->Parameters.Create.Options;
 
-ULONG NTAPI Ext2LocateFileInDisk (
-       PtrExt2VCB                              PtrVCB,
-       PUNICODE_STRING                 PtrCurrentName, 
-       PtrExt2FCB                              PtrParentFCB,
-       ULONG                                   *Type )
-{
+    DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
+    OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
 
-       PFILE_OBJECT            PtrFileObject = NULL;
-       ULONG                           InodeNo = 0;
-       
-       *Type = EXT2_FT_UNKNOWN;
-
-       //      1. 
-       //      Initialize the Blocks in the FCB...
-       //
-       Ext2InitializeFCBInodeInfo( PtrParentFCB );
-
-       
-       //      2.
-       //      Is there a file object I can use for caching??
-       //      If not create one...
-       //
-       if( !PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject )
-       {
-               //
-               //      No Directory File Object?
-               //      No problem, will create one...
-               //
-
-               //      Acquire the MainResource first though...
-                       
-                       PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject = IoCreateStreamFileObject(NULL, PtrVCB->TargetDeviceObject );
-                       PtrFileObject = PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject;
-                       
-                       if( !PtrFileObject )
-                       {
-                               Ext2BreakPoint();
-                               return 0;
-                       }
-                       PtrFileObject->ReadAccess = TRUE;
-                       PtrFileObject->WriteAccess = TRUE;
-
-                       //      Associate the file stream with the Volume parameter block...
-                       PtrFileObject->Vpb = PtrVCB->PtrVPB;
-
-                       //      No caching as yet...
-                       PtrFileObject->PrivateCacheMap = NULL;
-
-                       //      this establishes the FCB - File Object connection...
-                       PtrFileObject->FsContext = (void *)( & (PtrParentFCB->NTRequiredFCB.CommonFCBHeader) );
-
-                       //      Initialize the section object pointer...
-                       PtrFileObject->SectionObjectPointer = &(PtrParentFCB->NTRequiredFCB.SectionObject);
-       }
-       else
-       {
-               //      
-               //      I do have a file object... 
-               //      I am using it now!
-               //
-               PtrFileObject = PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject;
-       }
-
-       //      3.
-       //      Got hold of a file object? Good ;)
-       //      Now initiating Caching, pinned access to be precise ...
-       //
-       if (PtrFileObject->PrivateCacheMap == NULL) 
-       {
-                       CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrParentFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)),
-                               TRUE,           // We utilize pin access for directories
-                               &(Ext2GlobalData.CacheMgrCallBacks), // callbacks
-                               PtrParentFCB );         // The context used in callbacks
-       }
-
-       //      4.
-       //      Getting down to the real business now... ;)
-       //      Read in the directory contents and do a search 
-       //      a sequential search to be precise...
-       //      Wish Mm'm Renuga were reading this
-       //      Would feel proud...     ;)
-       //
-       {
-               LARGE_INTEGER   StartBufferOffset;
-               ULONG                   PinBufferLength;
-               ULONG                   BufferIndex;
-               PBCB                    PtrBCB = NULL;
-               BYTE *                  PtrPinnedBlockBuffer = NULL;
-               PEXT2_DIR_ENTRY PtrDirEntry = NULL;
-               BOOLEAN                 Found;
-               int                             i;
-
-
-               StartBufferOffset.QuadPart = 0;
-
-               //
-               //      Read in the whole damn directory
-               //      **Bad programming**
-               //      Will do for now.
-               //
-               PinBufferLength = PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.LowPart;
-               if (!CcMapData( PtrFileObject,
-                  &StartBufferOffset,
-                  PinBufferLength,
-                  TRUE,
-                  &PtrBCB,
-                  (PVOID*)&PtrPinnedBlockBuffer ) )
-               {
-
-                       
-               }
-               //
-               //      Walking through now...
-               //
-               
-               for( BufferIndex = 0, Found = FALSE; !Found && BufferIndex < ( PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; BufferIndex += PtrDirEntry->rec_len )
-               {
-                       PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ BufferIndex ];
-                       if( PtrDirEntry->name_len == 0 || PtrDirEntry->rec_len == 0 || PtrDirEntry->inode == 0)
-                       {
-                               //      Invalid entry...
-                               //  Ignore...
-                               continue;
-                       }
-                       //
-                       //      Comparing ( case sensitive )
-                       //      Directory entry is not NULL terminated...
-                       //      nor is the CurrentName...
-                       //
-                       if( PtrDirEntry->name_len != (PtrCurrentName->Length / 2) )
-                               continue;
-                       
-                       for( i = 0, Found = TRUE ; i < PtrDirEntry->name_len ; i++ )
-                       {
-                               if( PtrDirEntry->name[ i ] != PtrCurrentName->Buffer[ i ] )
-                               {
-                                       Found = FALSE;
-                                       break;
-
-                               }
-                       }
-                       
-               }
-               if( Found )
-               {
-                       InodeNo = PtrDirEntry->inode;
-
-                       if( PtrDirEntry->file_type == EXT2_FT_UNKNOWN )
-                       {
-
-                               //      Old Fashioned Directory entries...
-                               //      Will have to read in the Inode to determine the File Type...
-                               EXT2_INODE      Inode;
-                               //      PtrInode = Ext2AllocatePool( NonPagedPool, sizeof( EXT2_INODE )  );
-                               Ext2ReadInode( PtrVCB, InodeNo, &Inode );       
-
-                               if( Ext2IsModeRegularFile( Inode.i_mode ) )
-                               {
-                                       *Type = EXT2_FT_REG_FILE;
-                               }
-                               else if ( Ext2IsModeDirectory( Inode.i_mode) )
-                               {
-                                       //      Directory...
-                                       *Type = EXT2_FT_DIR;
-                               }
-                               else if( Ext2IsModeSymbolicLink(Inode.i_mode) )
-                               {
-                                       *Type = EXT2_FT_SYMLINK;
-                               }
-                               else if( Ext2IsModePipe(Inode.i_mode) )
-                               {
-                                       *Type = EXT2_FT_FIFO;
-                               }
-                               else if( Ext2IsModeCharacterDevice(Inode.i_mode) )
-                               {
-                                       *Type = EXT2_FT_CHRDEV;
-                               }
-                               else if( Ext2IsModeBlockDevice(Inode.i_mode) )
-                               {
-                                       *Type = EXT2_FT_BLKDEV;
-                               }
-                               else if( Ext2IsModeSocket(Inode.i_mode) )
-                               {
-                                       *Type = EXT2_FT_SOCK;
-                               }
-                               else
-                               {
-                                       *Type = EXT2_FT_UNKNOWN;
-                               }
-                               
-                               //DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Create]", PtrInode );
-                               //ExFreePool( PtrInode );
-                       }
-                       else
-                       {
-                               *Type = PtrDirEntry->file_type;
-                       }
-               }
-
-               CcUnpinData( PtrBCB );
-               PtrBCB = NULL;
-
-               return InodeNo;
-       }
+    CreateDisposition = (Options >> 24) & 0x000000ff;
+
+    DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+    ShareAccess   = IrpSp->Parameters.Create.ShareAccess;
+
+    if (DirectoryFile) {
+        return STATUS_NOT_A_DIRECTORY;
+    }
+
+    if (OpenTargetDirectory) {
+        DbgBreak();
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if ( (CreateDisposition != FILE_OPEN) &&
+            (CreateDisposition != FILE_OPEN_IF) ) {
+        return STATUS_ACCESS_DENIED;
+    }
+
+    if ( !FlagOn(ShareAccess, FILE_SHARE_READ) &&
+            Vcb->OpenVolumeCount  != 0 ) {
+        return STATUS_SHARING_VIOLATION;
+    }
+
+    Ccb = Ext2AllocateCcb(NULL);
+    if (Ccb == NULL) {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
+    }
+
+    Status = STATUS_SUCCESS;
+
+    if (Vcb->OpenVolumeCount > 0) {
+        Status = IoCheckShareAccess( DesiredAccess, ShareAccess,
+                                     IrpSp->FileObject,
+                                     &(Vcb->ShareAccess), TRUE);
+
+        if (!NT_SUCCESS(Status)) {
+            goto errorout;
+        }
+    } else {
+        IoSetShareAccess( DesiredAccess, ShareAccess,
+                          IrpSp->FileObject,
+                          &(Vcb->ShareAccess)   );
+    }
+
+
+    if (Vcb->OpenVolumeCount == 0 &&
+        !IsFlagOn(ShareAccess, FILE_SHARE_READ)  &&
+        !IsFlagOn(ShareAccess, FILE_SHARE_WRITE) ){
+
+        if (!IsVcbReadOnly(Vcb)) {
+            Ext2FlushFiles(IrpContext, Vcb, FALSE);
+            Ext2FlushVolume(IrpContext, Vcb, FALSE);
+        }
+
+        SetLongFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
+        Vcb->LockFile = IrpSp->FileObject;
+    } else {
+        if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA) ) {
+            if (!IsVcbReadOnly(Vcb)) {
+                Ext2FlushFiles(IrpContext, Vcb, FALSE);
+                Ext2FlushVolume(IrpContext, Vcb, FALSE);
+            }
+        }
+    }
+
+    IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+    IrpSp->FileObject->FsContext  = Vcb;
+    IrpSp->FileObject->FsContext2 = Ccb;
+    IrpSp->FileObject->Vpb = Vcb->Vpb;
+
+    Ext2ReferXcb(&Vcb->ReferenceCount);
+    Ext2ReferXcb(&Vcb->OpenHandleCount);
+    Ext2ReferXcb(&Vcb->OpenVolumeCount);
+
+    Irp->IoStatus.Information = FILE_OPENED;
+
+errorout:
+
+    return Status;
 }
 
 
-/*************************************************************************
-*
-* Function: Ext2CreateFile()
-*
-* Description:
-*      Creates a new file on the disk
-*      
-* Expected Interrupt Level (for execution) :
-*      IRQL_PASSIVE_LEVEL
-*
-* Restrictions:
-*      Expects the VCB to be acquired Exclusively before being invoked
-*
-* Return Value: None
-*
-*************************************************************************/
-ULONG NTAPI Ext2CreateFile( 
-       PtrExt2IrpContext               PtrIrpContext,
-       PtrExt2VCB                              PtrVCB,
-       PUNICODE_STRING                 PtrName, 
-       PtrExt2FCB                              PtrParentFCB,
-       ULONG                                   Type)
+NTSTATUS
+Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext)
 {
-       EXT2_INODE      Inode, ParentInode;
-
-       ULONG           NewInodeNo = 0;
-       BOOLEAN         FCBAcquired = FALSE;
-
-       ULONG           LogicalBlockSize = 0;
-
-       try
-       {
-               
-
-               //      0. Verify if the creation is possible,,,
-               if( Type != EXT2_FT_DIR && Type != EXT2_FT_REG_FILE )
-               {
-                       //
-                       //      Can create only a directory or a regular file...
-                       //
-                       return 0;
-               }
-               
-               //      1. Allocate an i-node...
-               
-               NewInodeNo = Ext2AllocInode( PtrIrpContext, PtrVCB, PtrParentFCB->INodeNo );
-               
-               //      NewInodeNo = 12;
-
-               if( !NewInodeNo )
-               {
-                       return 0;
-               }
-               
-               //      2. Acquire the Parent FCB Exclusively...
-               if( !ExAcquireResourceExclusiveLite(&( PtrParentFCB->NTRequiredFCB.MainResource ), TRUE) )
-               {
-                       Ext2DeallocInode( PtrIrpContext, PtrVCB, NewInodeNo );
-                       try_return( NewInodeNo = 0);
-               }
-               FCBAcquired = TRUE;
-
-               //      3. Make an entry in the parent Directory...             
-               ASSERT( PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject );
-               
-               Ext2MakeNewDirectoryEntry(
-                       PtrIrpContext,
-                       PtrParentFCB, 
-                       PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject, 
-                       PtrName, Type, NewInodeNo );
-       
-               
-               //      4. Initialize an inode entry and  write it to disk...
-               LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
-
-               {
-                       //      To be deleted
-                       Ext2ReadInode( PtrVCB, NewInodeNo, &Inode );
-               }
-
-               RtlZeroMemory( &Inode, sizeof( EXT2_INODE ) );
-               if( Type == EXT2_FT_DIR )
-               {
-                       Inode.i_mode = 0x41ff;
-
-                       //      In addition to the usual link, 
-                       //      there will be an additional link in the directory itself - the '.' entry
-                       Inode.i_links_count = 2;
-
-                       //      Incrementing the link count for the parent as well...
-                       Ext2ReadInode( PtrVCB, PtrParentFCB->INodeNo, &ParentInode );
-                       ParentInode.i_links_count++;
-                       Ext2WriteInode( PtrIrpContext, PtrVCB, PtrParentFCB->INodeNo, &ParentInode );
-
-               }
-               else
-               {
-                       Inode.i_mode = 0x81ff;
-                       Inode.i_links_count = 1;
-               }
-
-
-               {
-                       //
-                       //      Setting the time fields in the inode...
-                       //
-                       ULONG Time;
-                       Time = Ext2GetCurrentTime();
-                       Inode.i_ctime = Time;
-                       Inode.i_atime = Time;
-                       Inode.i_mtime = Time;
-                       Inode.i_dtime = 0;                      //      Deleted time;
-               }
-
-               Ext2WriteInode( PtrIrpContext, PtrVCB, NewInodeNo, &Inode );
-
-               try_exit:       NOTHING;
-       }
-       finally 
-       {
-               if( FCBAcquired )
-               {
-                       Ext2ReleaseResource( &(PtrParentFCB->NTRequiredFCB.MainResource) );
-               }
-       }
-
-       return NewInodeNo ;
+    PDEVICE_OBJECT      DeviceObject;
+    PIRP                Irp;
+    PIO_STACK_LOCATION  IrpSp;
+    PEXT2_VCB           Vcb = 0;
+    NTSTATUS            Status = STATUS_OBJECT_NAME_NOT_FOUND;
+    PEXT2_FCBVCB        Xcb = NULL;
+    BOOLEAN             PostIrp = FALSE;
+    BOOLEAN             VcbResourceAcquired = FALSE;
+
+    DeviceObject = IrpContext->DeviceObject;
+    Irp = IrpContext->Irp;
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    Xcb = (PEXT2_FCBVCB) (IrpSp->FileObject->FsContext);
+
+    if (IsExt2FsDevice(DeviceObject)) {
+
+        DEBUG(DL_INF, ( "Ext2Create: Create on main device object.\n"));
+
+        Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = FILE_OPENED;
+
+        Ext2CompleteIrpContext(IrpContext, Status);
+
+        return Status;
+    }
+
+    _SEH2_TRY {
+
+        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
+        ASSERT(Vcb->Identifier.Type == EXT2VCB);
+        IrpSp->FileObject->Vpb = Vcb->Vpb;
+
+        if (!IsMounted(Vcb)) {
+            DbgBreak();
+            if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
+                Status = STATUS_NO_SUCH_DEVICE;
+            } else {
+                Status = STATUS_VOLUME_DISMOUNTED;
+            }
+            _SEH2_LEAVE;
+        }
+
+        if (!ExAcquireResourceExclusiveLite(
+                    &Vcb->MainResource, TRUE)) {
+            Status = STATUS_PENDING;
+            _SEH2_LEAVE;
+        }
+        VcbResourceAcquired = TRUE;
+
+        Ext2VerifyVcb(IrpContext, Vcb);
+
+        if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
+            Status = STATUS_ACCESS_DENIED;
+            if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
+                Status = STATUS_VOLUME_DISMOUNTED;
+            }
+            _SEH2_LEAVE;
+        }
+
+        if ( ((IrpSp->FileObject->FileName.Length == 0) &&
+                (IrpSp->FileObject->RelatedFileObject == NULL)) ||
+                (Xcb && Xcb->Identifier.Type == EXT2VCB)  ) {
+            Status = Ext2CreateVolume(IrpContext, Vcb);
+        } else {
+
+            Status = Ext2CreateFile(IrpContext, Vcb, &PostIrp);
+        }
+
+    } _SEH2_FINALLY {
+
+        if (VcbResourceAcquired) {
+            ExReleaseResourceLite(&Vcb->MainResource);
+        }
+
+        if (!IrpContext->ExceptionInProgress && !PostIrp)  {
+            if ( Status == STATUS_PENDING ||
+                    Status == STATUS_CANT_WAIT) {
+                Status = Ext2QueueRequest(IrpContext);
+            } else {
+                Ext2CompleteIrpContext(IrpContext, Status);
+            }
+        }
+    } _SEH2_END;
+
+    return Status;
 }
 
-/*************************************************************************
-*
-* Function: Ext2CreateFile()
-*
-* Description:
-*      Overwrites an existing file on the disk
-*      
-* Expected Interrupt Level (for execution) :
-*      IRQL_PASSIVE_LEVEL
-*
-* Restrictions:
-*      Expects the VCB to be acquired Exclusively before being invoked
-*
-* Return Value: None
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2OverwriteFile(
-       PtrExt2FCB                      PtrFCB,
-       PtrExt2IrpContext       PtrIrpContext)
+NTSTATUS
+Ext2CreateInode(
+    PEXT2_IRP_CONTEXT   IrpContext,
+    PEXT2_VCB           Vcb,
+    PEXT2_FCB           Parent,
+    ULONG               Type,
+    ULONG               FileAttr,
+    PUNICODE_STRING     FileName)
 {
-       EXT2_INODE                      Inode;
-       PtrExt2VCB                      PtrVCB = PtrFCB->PtrVCB;
-       ULONG                           i;
-       ULONG   Time;
-       Time = Ext2GetCurrentTime();
-
-       Ext2InitializeFCBInodeInfo( PtrFCB );
-       //      1.
-       //      Update the inode...
-       if( !NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
-       {
-               return FALSE;
-       }
-
-       Inode.i_size = 0;
-       Inode.i_blocks = 0;
-       Inode.i_atime = Time;
-       Inode.i_mtime = Time;
-       Inode.i_dtime = 0;
-
-       for( i = 0; i < EXT2_N_BLOCKS; i++ )
-       {
-               Inode.i_block[ i ] = 0;
-       }
-
-       if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
-       {
-               return FALSE;
-       }
-
-       //      2.
-       //      Release all the data blocks...
-       if( !Ext2ReleaseDataBlocks( PtrFCB, PtrIrpContext) )
-       {
-               return FALSE;
-       }
-       
-       Ext2ClearFlag( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED );
-       Ext2InitializeFCBInodeInfo( PtrFCB );
-       
-       return TRUE;
+    NTSTATUS    Status;
+    ULONG       iGrp;
+    ULONG       iNo;
+    struct inode Inode = { 0 };
+    struct dentry *Dentry = NULL;
+
+    LARGE_INTEGER   SysTime;
+
+    iGrp = (Parent->Inode->i_ino - 1) / BLOCKS_PER_GROUP;
+
+    DEBUG(DL_INF, ("Ext2CreateInode: %S in %S(Inode=%xh)\n",
+                   FileName->Buffer,
+                   Parent->Mcb->ShortName.Buffer,
+                   Parent->Inode->i_ino));
+
+    Status = Ext2NewInode(IrpContext, Vcb, iGrp, Type, &iNo);
+    if (!NT_SUCCESS(Status)) {
+        goto errorout;
+    }
+
+    KeQuerySystemTime(&SysTime);
+    Ext2ClearInode(IrpContext, Vcb, iNo);
+    Inode.i_sb = &Vcb->sb;
+    Inode.i_ino = iNo;
+    Inode.i_ctime = Inode.i_mtime =
+                        Inode.i_atime = Ext2LinuxTime(SysTime);
+    Inode.i_uid = Parent->Inode->i_uid;
+    Inode.i_gid = Parent->Inode->i_gid;
+    Inode.i_generation = Parent->Inode->i_generation;
+    Inode.i_mode = S_IPERMISSION_MASK &
+                   Parent->Inode->i_mode;
+    if (Type == EXT2_FT_DIR)  {
+        Inode.i_mode |= S_IFDIR;
+    } else if (Type == EXT2_FT_REG_FILE) {
+        Inode.i_mode &= S_IFATTR;
+        Inode.i_mode |= S_IFREG;
+    } else {
+        DbgBreak();
+    }
+
+    /* Force using extent */
+    if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+        Inode.i_flags |= EXT2_EXTENTS_FL;
+    }
+
+    /* add new entry to its parent */
+    Status = Ext2AddEntry(
+                 IrpContext,
+                 Vcb,
+                 Parent,
+                 &Inode,
+                 FileName,
+                 &Dentry
+             );
+
+    if (!NT_SUCCESS(Status)) {
+        DbgBreak();
+        Ext2FreeInode(IrpContext, Vcb, iNo, Type);
+        goto errorout;
+    }
+
+    DEBUG(DL_INF, ("Ext2CreateInode: New Inode = %xh (Type=%xh)\n",
+                   Inode.i_ino, Type));
+
+errorout:
+
+    if (Dentry)
+        Ext2FreeEntry(Dentry);
+
+    return Status;
 }
 
-/*************************************************************************
-*
-* Function: Ext2SupersedeFile()
-*
-* Description:
-*      Supersedes an existing file on the disk
-*      
-* Expected Interrupt Level (for execution) :
-*      IRQL_PASSIVE_LEVEL
-*
-* Restrictions:
-*      Expects the VCB to be acquired Exclusively before being invoked
-*
-* Return Value: None
-*
-*************************************************************************/
-BOOLEAN NTAPI Ext2SupersedeFile(
-       PtrExt2FCB                      PtrFCB,
-       PtrExt2IrpContext       PtrIrpContext)
+
+NTSTATUS
+Ext2SupersedeOrOverWriteFile(
+    IN PEXT2_IRP_CONTEXT IrpContext,
+    IN PFILE_OBJECT      FileObject,
+    IN PEXT2_VCB         Vcb,
+    IN PEXT2_FCB         Fcb,
+    IN PLARGE_INTEGER    AllocationSize,
+    IN ULONG             Disposition
+)
 {
-       EXT2_INODE                      Inode;
-       PtrExt2VCB                      PtrVCB = PtrFCB->PtrVCB;
-
-       Ext2InitializeFCBInodeInfo( PtrFCB );
-
-       //      1.
-       //      Initialize the inode...
-       RtlZeroMemory( &Inode, sizeof( EXT2_INODE ) );
-
-       //      Setting the file mode...
-       //      This operation is allowed only for a regular file...
-       Inode.i_mode = 0x81ff;
-
-       //      Maintaining the old link count...
-       Inode.i_links_count = PtrFCB->LinkCount;
-
-       //      Setting the time fields in the inode...
-       {
-               ULONG Time;
-               Time = Ext2GetCurrentTime();
-               Inode.i_ctime = Time;
-               Inode.i_atime = Time;
-               Inode.i_mtime = Time;
-               Inode.i_dtime = 0;                      //      Deleted time;
-       }
-
-       if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
-       {
-               return FALSE;
-       }
-
-       //      2.
-       //      Release all the data blocks...
-       if( !Ext2ReleaseDataBlocks( PtrFCB, PtrIrpContext) )
-       {
-               return FALSE;
-       }
-       
-       Ext2ClearFlag( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED );
-       Ext2InitializeFCBInodeInfo( PtrFCB );
-       
-       return TRUE;
+    LARGE_INTEGER   CurrentTime;
+    LARGE_INTEGER   Size;
+
+    KeQuerySystemTime(&CurrentTime);
+
+    Size.QuadPart = 0;
+    if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(Size))) {
+        return STATUS_USER_MAPPED_FILE;
+    }
+
+    /* purge all file cache and shrink cache windows size */
+    CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
+    Fcb->Header.AllocationSize.QuadPart =
+        Fcb->Header.FileSize.QuadPart =
+            Fcb->Header.ValidDataLength.QuadPart = 0;
+    CcSetFileSizes(FileObject,
+                   (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
+
+    Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
+                                    (ULONGLONG)AllocationSize->QuadPart,
+                                    (ULONGLONG)BLOCK_SIZE);
+
+    if ((loff_t)Size.QuadPart > Fcb->Inode->i_size) {
+        Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+    } else {
+        Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+    }
+
+    Fcb->Header.AllocationSize = Size;
+    if (Fcb->Header.AllocationSize.QuadPart > 0) {
+        SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
+        CcSetFileSizes(FileObject,
+                       (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
+    }
+
+    /* remove all extent mappings */
+    DEBUG(DL_EXT, ("Ext2SuperSede ...: %wZ\n", &Fcb->Mcb->FullName));
+    Fcb->Inode->i_size = 0;
+
+    if (Disposition == FILE_SUPERSEDE) {
+        Fcb->Inode->i_ctime = Ext2LinuxTime(CurrentTime);
+    }
+    Fcb->Inode->i_atime =
+        Fcb->Inode->i_mtime = Ext2LinuxTime(CurrentTime);
+    Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
+
+    return STATUS_SUCCESS;
 }