[NTFS]
[reactos.git] / reactos / drivers / filesystems / ntfs / create.c
index 88cc138..e655406 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-/* GLOBALS *****************************************************************/
-
-
 /* FUNCTIONS ****************************************************************/
 
-static NTSTATUS
+static
+NTSTATUS
 NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
-                        PWSTR pRelativeFileName,
-                        PWSTR *pAbsoluteFilename)
+                         PWSTR pRelativeFileName,
+                         PWSTR *pAbsoluteFilename)
 {
-  PWSTR rcName;
-  PNTFS_FCB Fcb;
+    PWSTR rcName;
+    PNTFS_FCB Fcb;
 
-  DPRINT("try related for %S\n", pRelativeFileName);
-  Fcb = pFileObject->FsContext;
-  ASSERT(Fcb);
+    DPRINT("try related for %S\n", pRelativeFileName);
+    Fcb = pFileObject->FsContext;
+    ASSERT(Fcb);
 
-  /* verify related object is a directory and target name
-     don't start with \. */
-  if (NtfsFCBIsDirectory(Fcb) == FALSE ||
-      pRelativeFileName[0] == L'\\')
+    /* verify related object is a directory and target name
+       don't start with \. */
+    if (NtfsFCBIsDirectory(Fcb) == FALSE ||
+        pRelativeFileName[0] == L'\\')
     {
-      return(STATUS_INVALID_PARAMETER);
+        return STATUS_INVALID_PARAMETER;
     }
 
-  /* construct absolute path name */
-  ASSERT(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
-          <= MAX_PATH);
-  rcName = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH * sizeof(WCHAR), TAG_NTFS);
-  if (!rcName)
+    /* construct absolute path name */
+    ASSERT(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 <= MAX_PATH);
+    rcName = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH * sizeof(WCHAR), TAG_NTFS);
+    if (!rcName)
     {
-      return(STATUS_INSUFFICIENT_RESOURCES);
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-  wcscpy(rcName, Fcb->PathName);
-  if (!NtfsFCBIsRoot(Fcb))
-    wcscat (rcName, L"\\");
-  wcscat (rcName, pRelativeFileName);
-  *pAbsoluteFilename = rcName;
+    wcscpy(rcName, Fcb->PathName);
+    if (!NtfsFCBIsRoot(Fcb))
+        wcscat (rcName, L"\\");
+    wcscat (rcName, pRelativeFileName);
+    *pAbsoluteFilename = rcName;
 
-  return(STATUS_SUCCESS);
+    return STATUS_SUCCESS;
 }
 
 
-static NTSTATUS
-NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
-            PFILE_OBJECT FileObject,
-            PWSTR FileName)
 /*
  * FUNCTION: Opens a file
  */
+static
+NTSTATUS
+NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
+             PFILE_OBJECT FileObject,
+             PWSTR FileName,
+             PNTFS_FCB * FoundFCB)
 {
-  PNTFS_FCB ParentFcb;
-  PNTFS_FCB Fcb;
-  NTSTATUS Status;
-  PWSTR AbsFileName = NULL;
+    PNTFS_FCB ParentFcb;
+    PNTFS_FCB Fcb;
+    NTSTATUS Status;
+    PWSTR AbsFileName = NULL;
 
-  DPRINT("NtfsOpenFile(%p, %p, %S)\n", DeviceExt, FileObject, FileName);
+    DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB);
 
-  if (FileObject->RelatedFileObject)
+    *FoundFCB = NULL;
+
+    if (FileObject->RelatedFileObject)
     {
-      DPRINT("Converting relative filename to absolute filename\n");
-
-      Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
-                                       FileName,
-                                       &AbsFileName);
-      FileName = AbsFileName;
-      if (!NT_SUCCESS(Status))
-       {
-         return(Status);
-       }
-      return(STATUS_UNSUCCESSFUL);
+        DPRINT("Converting relative filename to absolute filename\n");
+
+        Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
+                                          FileName,
+                                          &AbsFileName);
+        FileName = AbsFileName;
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+
+        return STATUS_UNSUCCESSFUL;
     }
 
-  //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
+    //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
 
-  DPRINT("PathName to open: %S\n", FileName);
+    DPRINT("PathName to open: %S\n", FileName);
 
-  /*  try first to find an existing FCB in memory  */
-  DPRINT("Checking for existing FCB in memory\n");
-  Fcb = NtfsGrabFCBFromTable(DeviceExt,
-                            FileName);
-  if (Fcb == NULL)
+    /*  try first to find an existing FCB in memory  */
+    DPRINT("Checking for existing FCB in memory\n");
+    Fcb = NtfsGrabFCBFromTable(DeviceExt,
+                               FileName);
+    if (Fcb == NULL)
     {
-      DPRINT("No existing FCB found, making a new one if file exists.\n");
-      Status = NtfsGetFCBForFile(DeviceExt,
-                                &ParentFcb,
-                                &Fcb,
-                                FileName);
-      if (ParentFcb != NULL)
-       {
-         NtfsReleaseFCB(DeviceExt,
-                        ParentFcb);
-       }
-
-      if (!NT_SUCCESS (Status))
-       {
-         DPRINT("Could not make a new FCB, status: %x\n", Status);
-
-         if (AbsFileName)
-           ExFreePool(AbsFileName);
-
-         return(Status);
-       }
+        DPRINT("No existing FCB found, making a new one if file exists.\n");
+        Status = NtfsGetFCBForFile(DeviceExt,
+                                   &ParentFcb,
+                                   &Fcb,
+                                   FileName);
+        if (ParentFcb != NULL)
+        {
+            NtfsReleaseFCB(DeviceExt,
+                           ParentFcb);
+        }
+
+        if (!NT_SUCCESS (Status))
+        {
+            DPRINT("Could not make a new FCB, status: %x\n", Status);
+
+            if (AbsFileName)
+                ExFreePool(AbsFileName);
+
+            return Status;
+        }
     }
 
-  DPRINT("Attaching FCB to fileObject\n");
-  Status = NtfsAttachFCBToFileObject(DeviceExt,
-                                    Fcb,
-                                    FileObject);
+    DPRINT("Attaching FCB to fileObject\n");
+    Status = NtfsAttachFCBToFileObject(DeviceExt,
+                                       Fcb,
+                                       FileObject);
+
+    if (AbsFileName)
+        ExFreePool(AbsFileName);
 
-  if (AbsFileName)
-    ExFreePool (AbsFileName);
+    *FoundFCB = Fcb;
 
-  return(Status);
+    return Status;
 }
 
 
-static NTSTATUS
-NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
-              PIRP Irp)
 /*
  * FUNCTION: Opens a file
  */
+static
+NTSTATUS
+NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
+               PIRP Irp)
 {
-  PDEVICE_EXTENSION DeviceExt;
-  PIO_STACK_LOCATION Stack;
-  PFILE_OBJECT FileObject;
-  ULONG RequestedDisposition;
-//  ULONG RequestedOptions;
-//  PFCB Fcb;
-//  PWSTR FileName;
-  NTSTATUS Status;
-
-  DPRINT("NtfsCreateFile() called\n");
-
-  DeviceExt = DeviceObject->DeviceExtension;
-  ASSERT(DeviceExt);
-  Stack = IoGetCurrentIrpStackLocation (Irp);
-  ASSERT(Stack);
-
-  RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
-//  RequestedOptions =
-//    Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
+    PDEVICE_EXTENSION DeviceExt;
+    PIO_STACK_LOCATION Stack;
+    PFILE_OBJECT FileObject;
+    ULONG RequestedDisposition;
+    ULONG RequestedOptions;
+    PNTFS_FCB Fcb;
+//    PWSTR FileName;
+    NTSTATUS Status;
+
+    DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
+
+    DeviceExt = DeviceObject->DeviceExtension;
+    ASSERT(DeviceExt);
+    Stack = IoGetCurrentIrpStackLocation (Irp);
+    ASSERT(Stack);
+
+    RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
+    RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
 //  PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
-//  if ((RequestedOptions & FILE_DIRECTORY_FILE)
-//      && RequestedDisposition == FILE_SUPERSEDE)
-//    return STATUS_INVALID_PARAMETER;
+    if (RequestedOptions & FILE_DIRECTORY_FILE &&
+        RequestedDisposition == FILE_SUPERSEDE)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
 
-  FileObject = Stack->FileObject;
+    FileObject = Stack->FileObject;
+
+    if (RequestedDisposition == FILE_CREATE ||
+        RequestedDisposition == FILE_OVERWRITE_IF ||
+        RequestedDisposition == FILE_SUPERSEDE)
+    {
+        return STATUS_ACCESS_DENIED;
+    }
 
-  if (RequestedDisposition == FILE_CREATE ||
-      RequestedDisposition == FILE_OVERWRITE_IF ||
-      RequestedDisposition == FILE_SUPERSEDE)
+    /* This a open operation for the volume itself */
+    if (FileObject->FileName.Length == 0 &&
+        (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
     {
-      return(STATUS_ACCESS_DENIED);
+        if (RequestedDisposition != FILE_OPEN &&
+            RequestedDisposition != FILE_OPEN_IF)
+        {
+            return STATUS_ACCESS_DENIED;
+        }
+
+        if (RequestedOptions & FILE_DIRECTORY_FILE)
+        {
+            return STATUS_NOT_A_DIRECTORY;
+        }
+
+        NtfsAttachFCBToFileObject(DeviceExt, DeviceExt->VolumeFcb, FileObject);
+        DeviceExt->VolumeFcb->RefCount++;
+
+        Irp->IoStatus.Information = FILE_OPENED;
+        return STATUS_SUCCESS;
     }
 
-  Status = NtfsOpenFile(DeviceExt,
-                       FileObject,
-                       FileObject->FileName.Buffer);
+    Status = NtfsOpenFile(DeviceExt,
+                          FileObject,
+                          FileObject->FileName.Buffer,
+                          &Fcb);
 
-  /*
-   * If the directory containing the file to open doesn't exist then
-   * fail immediately
-   */
-  Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
-  Irp->IoStatus.Status = Status;
+    /*
+     * If the directory containing the file to open doesn't exist then
+     * fail immediately
+     */
+    Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
+    Irp->IoStatus.Status = Status;
 
-  return(Status);
+    return Status;
 }
 
 
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 NtfsFsdCreate(PDEVICE_OBJECT DeviceObject,
-          PIRP Irp)
+              PIRP Irp)
 {
-  PDEVICE_EXTENSION DeviceExt;
-  NTSTATUS Status;
+    PDEVICE_EXTENSION DeviceExt;
+    NTSTATUS Status;
 
-  if (DeviceObject == NtfsGlobalData->DeviceObject)
+    if (DeviceObject == NtfsGlobalData->DeviceObject)
     {
-      /* DeviceObject represents FileSystem instead of logical volume */
-      DPRINT("Opening file system\n");
-      Irp->IoStatus.Information = FILE_OPENED;
-      Status = STATUS_SUCCESS;
-      goto ByeBye;
+        /* DeviceObject represents FileSystem instead of logical volume */
+        DPRINT("Opening file system\n");
+        Irp->IoStatus.Information = FILE_OPENED;
+        Status = STATUS_SUCCESS;
+        goto ByeBye;
     }
 
-  DeviceExt = DeviceObject->DeviceExtension;
+    DeviceExt = DeviceObject->DeviceExtension;
 
-  FsRtlEnterFileSystem();
-  ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
-                                TRUE);
-  Status = NtfsCreateFile(DeviceObject,
-                         Irp);
-  ExReleaseResourceLite(&DeviceExt->DirResource);
-  FsRtlExitFileSystem();
+    FsRtlEnterFileSystem();
+    ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
+                                   TRUE);
+    Status = NtfsCreateFile(DeviceObject,
+                            Irp);
+    ExReleaseResourceLite(&DeviceExt->DirResource);
+    FsRtlExitFileSystem();
 
 ByeBye:
-  Irp->IoStatus.Status = Status;
-  IoCompleteRequest(Irp,
-                   NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp,
+                      NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
 
-  return(Status);
+    return Status;
 }
 
 /* EOF */