ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

create.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS FAT file system driver
00003  * LICENSE:         GNU GPLv3 as published by the Free Software Foundation
00004  * FILE:            drivers/filesystems/fastfat/create.c
00005  * PURPOSE:         Create routines
00006  * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)
00007  */
00008 
00009 /* INCLUDES *****************************************************************/
00010 
00011 #define NDEBUG
00012 #include "fastfat.h"
00013 
00014 /* FUNCTIONS *****************************************************************/
00015 
00016 IO_STATUS_BLOCK
00017 NTAPI
00018 FatiOpenRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
00019                 IN PFILE_OBJECT FileObject,
00020                 IN PVCB Vcb,
00021                 IN PACCESS_MASK DesiredAccess,
00022                 IN USHORT ShareAccess,
00023                 IN ULONG CreateDisposition)
00024 {
00025     IO_STATUS_BLOCK Iosb;
00026     PFCB Dcb;
00027     NTSTATUS Status;
00028     PCCB Ccb;
00029 
00030     /* Reference our DCB */
00031     Dcb = Vcb->RootDcb;
00032 
00033     DPRINT("Opening root directory\n");
00034 
00035     /* Exclusively lock this DCB */
00036     (VOID)FatAcquireExclusiveFcb(IrpContext, Dcb);
00037 
00038     do
00039     {
00040         /* Validate parameters */
00041         if (CreateDisposition != FILE_OPEN &&
00042             CreateDisposition != FILE_OPEN_IF)
00043         {
00044             Iosb.Status = STATUS_ACCESS_DENIED;
00045             break;
00046         }
00047 
00048         // TODO: Check file access
00049 
00050         /* Is it a first time open? */
00051         if (Dcb->OpenCount == 0)
00052         {
00053             /* Set share access */
00054             IoSetShareAccess(*DesiredAccess,
00055                              ShareAccess,
00056                              FileObject,
00057                              &Dcb->ShareAccess);
00058         }
00059         else
00060         {
00061             /* Check share access */
00062             Status = IoCheckShareAccess(*DesiredAccess,
00063                                         ShareAccess,
00064                                         FileObject,
00065                                         &Dcb->ShareAccess,
00066                                         TRUE);
00067         }
00068 
00069         /* Set file object pointers */
00070         Ccb = FatCreateCcb();
00071         FatSetFileObject(FileObject, UserDirectoryOpen, Dcb, Ccb);
00072 
00073         /* Increment counters */
00074         Dcb->OpenCount++;
00075         Dcb->UncleanCount++;
00076         Vcb->OpenFileCount++;
00077         if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
00078 
00079         /* Set success statuses */
00080         Iosb.Status = STATUS_SUCCESS;
00081         Iosb.Information = FILE_OPENED;
00082     } while (FALSE);
00083 
00084     /* Release the DCB lock */
00085     FatReleaseFcb(IrpContext, Dcb);
00086 
00087     return Iosb;
00088 }
00089 
00090 FF_ERROR
00091 NTAPI
00092 FatiTryToOpen(IN PFILE_OBJECT FileObject,
00093               IN PVCB Vcb)
00094 {
00095     OEM_STRING AnsiName;
00096     CHAR AnsiNameBuf[512];
00097     FF_ERROR Error;
00098     NTSTATUS Status;
00099     FF_FILE *FileHandle;
00100 
00101     /* Convert the name to ANSI */
00102     AnsiName.Buffer = AnsiNameBuf;
00103     AnsiName.Length = 0;
00104     AnsiName.MaximumLength = sizeof(AnsiNameBuf);
00105     RtlZeroMemory(AnsiNameBuf, sizeof(AnsiNameBuf));
00106     Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiName, &FileObject->FileName, FALSE);
00107     if (!NT_SUCCESS(Status))
00108     {
00109         ASSERT(FALSE);
00110     }
00111 
00112     /* Open the file with FullFAT */
00113     FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, &Error);
00114 
00115     /* Close the handle */
00116     if (FileHandle) FF_Close(FileHandle);
00117 
00118     /* Return status */
00119     return Error;
00120 }
00121 
00122 IO_STATUS_BLOCK
00123 NTAPI
00124 FatiOverwriteFile(PFAT_IRP_CONTEXT IrpContext,
00125                   PFILE_OBJECT FileObject,
00126                   PFCB Fcb,
00127                   ULONG AllocationSize,
00128                   PFILE_FULL_EA_INFORMATION EaBuffer,
00129                   ULONG EaLength,
00130                   UCHAR FileAttributes,
00131                   ULONG CreateDisposition,
00132                   BOOLEAN NoEaKnowledge)
00133 {
00134     IO_STATUS_BLOCK Iosb = {{0}};
00135     PCCB Ccb;
00136     LARGE_INTEGER Zero;
00137     ULONG NotifyFilter;
00138 
00139     Zero.QuadPart = 0;
00140 
00141     /* Check Ea mismatch first */
00142     if (NoEaKnowledge && EaLength > 0)
00143     {
00144         Iosb.Status = STATUS_ACCESS_DENIED;
00145         return Iosb;
00146     }
00147 
00148     do
00149     {
00150         /* Check if it's not still mapped */
00151         if (!MmCanFileBeTruncated(&Fcb->SectionObjectPointers,
00152                                   &Zero))
00153         {
00154             /* Fail */
00155             Iosb.Status = STATUS_USER_MAPPED_FILE;
00156             break;
00157         }
00158 
00159         /* Set file object pointers */
00160         Ccb = FatCreateCcb();
00161         FatSetFileObject(FileObject,
00162                          UserFileOpen,
00163                          Fcb,
00164                          Ccb);
00165 
00166         FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
00167 
00168         /* Indicate that create is in progress */
00169         Fcb->Vcb->State |= VCB_STATE_CREATE_IN_PROGRESS;
00170 
00171         /* Purge the cache section */
00172         CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE);
00173 
00174         /* Add Eas */
00175         if (EaLength > 0)
00176         {
00177             ASSERT(FALSE);
00178         }
00179 
00180         /* Acquire the paging resource */
00181         (VOID)ExAcquireResourceExclusiveLite(Fcb->Header.PagingIoResource, TRUE);
00182 
00183         /* Initialize FCB header */
00184         Fcb->Header.FileSize.QuadPart = 0;
00185         Fcb->Header.ValidDataLength.QuadPart = 0;
00186 
00187         /* Let CC know about changed file size */
00188         CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
00189 
00190         // TODO: Actually truncate the file
00191         DPRINT1("TODO: Actually truncate file '%wZ' with a fullfat handle %x\n", &Fcb->FullFileName, Fcb->FatHandle);
00192 
00193         /* Release the paging resource */
00194         ExReleaseResourceLite(Fcb->Header.PagingIoResource);
00195 
00196         /* Specify truncate on close */
00197         Fcb->State |= FCB_STATE_TRUNCATE_ON_CLOSE;
00198 
00199         // TODO: Delete previous EA if needed
00200 
00201         /* Send notification about changes */
00202         NotifyFilter = FILE_NOTIFY_CHANGE_LAST_WRITE |
00203                        FILE_NOTIFY_CHANGE_ATTRIBUTES |
00204                        FILE_NOTIFY_CHANGE_SIZE;
00205 
00206         FsRtlNotifyFullReportChange(Fcb->Vcb->NotifySync,
00207                                     &Fcb->Vcb->NotifyList,
00208                                     (PSTRING)&Fcb->FullFileName,
00209                                     Fcb->FullFileName.Length - Fcb->FileNameLength,
00210                                     NULL,
00211                                     NULL,
00212                                     NotifyFilter,
00213                                     FILE_ACTION_MODIFIED,
00214                                     NULL);
00215 
00216         /* Set success status */
00217         Iosb.Status = STATUS_SUCCESS;
00218 
00219         /* Set correct information code */
00220         Iosb.Information = (CreateDisposition == FILE_SUPERSEDE) ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
00221     } while (0);
00222 
00223     /* Remove the create in progress flag */
00224     ClearFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);
00225 
00226     return Iosb;
00227 }
00228 
00229 IO_STATUS_BLOCK
00230 NTAPI
00231 FatiOpenExistingDir(IN PFAT_IRP_CONTEXT IrpContext,
00232                      IN PFILE_OBJECT FileObject,
00233                      IN PVCB Vcb,
00234                      IN PFCB ParentDcb,
00235                      IN PACCESS_MASK DesiredAccess,
00236                      IN USHORT ShareAccess,
00237                      IN ULONG AllocationSize,
00238                      IN PFILE_FULL_EA_INFORMATION EaBuffer,
00239                      IN ULONG EaLength,
00240                      IN UCHAR FileAttributes,
00241                      IN ULONG CreateDisposition,
00242                      IN BOOLEAN DeleteOnClose)
00243 {
00244     IO_STATUS_BLOCK Iosb = {{0}};
00245     OEM_STRING AnsiName;
00246     CHAR AnsiNameBuf[512];
00247     PFCB Fcb;
00248     NTSTATUS Status;
00249     FF_FILE *FileHandle;
00250 
00251     /* Only open is permitted */
00252     if (CreateDisposition != FILE_OPEN &&
00253         CreateDisposition != FILE_OPEN_IF)
00254     {
00255         Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
00256         return Iosb;
00257     }
00258 
00259     // TODO: Check dir access
00260 
00261     /* Convert the name to ANSI */
00262     AnsiName.Buffer = AnsiNameBuf;
00263     AnsiName.Length = 0;
00264     AnsiName.MaximumLength = sizeof(AnsiNameBuf);
00265     RtlZeroMemory(AnsiNameBuf, sizeof(AnsiNameBuf));
00266     Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiName, &FileObject->FileName, FALSE);
00267     if (!NT_SUCCESS(Status))
00268     {
00269         ASSERT(FALSE);
00270     }
00271 
00272     /* Open the dir with FullFAT */
00273     FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_DIR, NULL);
00274 
00275     if (!FileHandle)
00276     {
00277         Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for now
00278         return Iosb;
00279     }
00280 
00281     /* Create a new DCB for this directory */
00282     Fcb = FatCreateDcb(IrpContext, Vcb, ParentDcb, FileHandle);
00283 
00284     /* Set share access */
00285     IoSetShareAccess(*DesiredAccess, ShareAccess, FileObject, &Fcb->ShareAccess);
00286 
00287     /* Set context and section object pointers */
00288     FatSetFileObject(FileObject,
00289                      UserDirectoryOpen,
00290                      Fcb,
00291                      FatCreateCcb());
00292 
00293     /* Increase counters */
00294     Fcb->UncleanCount++;
00295     Fcb->OpenCount++;
00296     Vcb->OpenFileCount++;
00297     if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
00298 
00299     Iosb.Status = STATUS_SUCCESS;
00300     Iosb.Information = FILE_OPENED;
00301 
00302     DPRINT1("Successfully opened dir %s\n", AnsiNameBuf);
00303 
00304     return Iosb;
00305 }
00306 
00307 IO_STATUS_BLOCK
00308 NTAPI
00309 FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
00310                      IN PFILE_OBJECT FileObject,
00311                      IN PVCB Vcb,
00312                      IN PFCB ParentDcb,
00313                      IN PACCESS_MASK DesiredAccess,
00314                      IN USHORT ShareAccess,
00315                      IN ULONG AllocationSize,
00316                      IN PFILE_FULL_EA_INFORMATION EaBuffer,
00317                      IN ULONG EaLength,
00318                      IN UCHAR FileAttributes,
00319                      IN ULONG CreateDisposition,
00320                      IN BOOLEAN IsPagingFile,
00321                      IN BOOLEAN DeleteOnClose,
00322                      IN BOOLEAN IsDosName)
00323 {
00324     IO_STATUS_BLOCK Iosb = {{0}};
00325     OEM_STRING AnsiName;
00326     CHAR AnsiNameBuf[512];
00327     PFCB Fcb;
00328     NTSTATUS Status;
00329     FF_FILE *FileHandle;
00330     FF_ERROR FfError;
00331 
00332     /* Check for create file option and fail */
00333     if (CreateDisposition == FILE_CREATE)
00334     {
00335         Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
00336         return Iosb;
00337     }
00338 
00339     // TODO: Check more params
00340 
00341     /* Convert the name to ANSI */
00342     AnsiName.Buffer = AnsiNameBuf;
00343     AnsiName.Length = 0;
00344     AnsiName.MaximumLength = sizeof(AnsiNameBuf);
00345     RtlZeroMemory(AnsiNameBuf, sizeof(AnsiNameBuf));
00346     Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiName, &FileObject->FileName, FALSE);
00347     if (!NT_SUCCESS(Status))
00348     {
00349         ASSERT(FALSE);
00350     }
00351 
00352     /* Open the file with FullFAT */
00353     FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, &FfError);
00354 
00355     if (!FileHandle)
00356     {
00357         DPRINT1("Failed to open file '%s', error %ld\n", AnsiName.Buffer, FfError);
00358         Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for now
00359         return Iosb;
00360     }
00361     DPRINT1("Succeeded opening file '%s'\n", AnsiName.Buffer);
00362 
00363     /* Create a new FCB for this file */
00364     Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb, FileHandle);
00365 
00366     // TODO: Check if overwrite is needed
00367 
00368     // TODO: This is usual file open branch, without overwriting!
00369     /* Set context and section object pointers */
00370     FatSetFileObject(FileObject,
00371                      UserFileOpen,
00372                      Fcb,
00373                      FatCreateCcb());
00374     FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
00375 
00376     Iosb.Status = STATUS_SUCCESS;
00377     Iosb.Information = FILE_OPENED;
00378 
00379 
00380     /* Increase counters */
00381     Fcb->UncleanCount++;
00382     Fcb->OpenCount++;
00383     if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) Fcb->NonCachedUncleanCount++;
00384     if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
00385 
00386     return Iosb;
00387 }
00388 
00389 IO_STATUS_BLOCK
00390 NTAPI
00391 FatiOpenVolume(IN PFAT_IRP_CONTEXT IrpContext,
00392                IN PFILE_OBJECT FileObject,
00393                IN PVCB Vcb,
00394                IN PACCESS_MASK DesiredAccess,
00395                IN USHORT ShareAccess,
00396                IN ULONG CreateDisposition)
00397 {
00398     PCCB Ccb;
00399     IO_STATUS_BLOCK Iosb = {{0}};
00400     BOOLEAN VolumeFlushed = FALSE;
00401 
00402     /* Check parameters */
00403     if (CreateDisposition != FILE_OPEN &&
00404         CreateDisposition != FILE_OPEN_IF)
00405     {
00406         /* Deny access */
00407         Iosb.Status = STATUS_ACCESS_DENIED;
00408     }
00409 
00410     /* Check if it's exclusive open */
00411     if (!FlagOn(ShareAccess, FILE_SHARE_WRITE) &&
00412         !FlagOn(ShareAccess, FILE_SHARE_DELETE))
00413     {
00414         // TODO: Check if exclusive read access requested
00415         // and opened handles count is not 0
00416         //if (!FlagOn(ShareAccess, FILE_SHARE_READ)
00417 
00418         DPRINT1("Exclusive volume open\n");
00419 
00420         // TODO: Flush the volume
00421         VolumeFlushed = TRUE;
00422     }
00423     else if (FlagOn(*DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))
00424     {
00425         DPRINT1("Shared open\n");
00426 
00427         // TODO: Flush the volume
00428         VolumeFlushed = TRUE;
00429     }
00430 
00431     if (VolumeFlushed &&
00432         !FlagOn(Vcb->State, VCB_STATE_MOUNTED_DIRTY) &&
00433         FlagOn(Vcb->State, VCB_STATE_FLAG_DIRTY) &&
00434         CcIsThereDirtyData(Vcb->Vpb))
00435     {
00436         UNIMPLEMENTED;
00437     }
00438 
00439     /* Set share access */
00440     if (Vcb->DirectOpenCount > 0)
00441     {
00442         /* This volume has already been opened */
00443         Iosb.Status = IoCheckShareAccess(*DesiredAccess,
00444                                          ShareAccess,
00445                                          FileObject,
00446                                          &Vcb->ShareAccess,
00447                                          TRUE);
00448 
00449         if (!NT_SUCCESS(Iosb.Status))
00450         {
00451             ASSERT(FALSE);
00452         }
00453     }
00454     else
00455     {
00456         /* This is the first time open */
00457         IoSetShareAccess(*DesiredAccess,
00458                          ShareAccess,
00459                          FileObject,
00460                          &Vcb->ShareAccess);
00461     }
00462 
00463     /* Set file object pointers */
00464     Ccb = FatCreateCcb();
00465     FatSetFileObject(FileObject, UserVolumeOpen, Vcb, Ccb);
00466     FileObject->SectionObjectPointer = &Vcb->SectionObjectPointers;
00467 
00468     /* Increase direct open count */
00469     Vcb->DirectOpenCount++;
00470     Vcb->OpenFileCount++;
00471     if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
00472 
00473     /* Set no buffering flag */
00474     FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
00475 
00476     // TODO: User's access check
00477 
00478     Iosb.Status = STATUS_SUCCESS;
00479     Iosb.Information = FILE_OPENED;
00480 
00481     return Iosb;
00482 }
00483 
00484 NTSTATUS
00485 NTAPI
00486 FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
00487            IN PIRP Irp)
00488 {
00489     /* Boolean options */
00490     BOOLEAN CreateDirectory;
00491     BOOLEAN SequentialOnly;
00492     BOOLEAN NoIntermediateBuffering;
00493     BOOLEAN OpenDirectory;
00494     BOOLEAN IsPagingFile;
00495     BOOLEAN OpenTargetDirectory;
00496     BOOLEAN IsDirectoryFile;
00497     BOOLEAN NonDirectoryFile;
00498     BOOLEAN NoEaKnowledge;
00499     BOOLEAN DeleteOnClose;
00500     BOOLEAN TemporaryFile;
00501     ULONG CreateDisposition;
00502 
00503     /* Control blocks */
00504     PVCB Vcb, DecodedVcb, RelatedVcb;
00505     PFCB Fcb, NextFcb, RelatedDcb;
00506     PCCB Ccb, RelatedCcb;
00507     PFCB ParentDcb;
00508 
00509     /* IRP data */
00510     PFILE_OBJECT FileObject;
00511     PFILE_OBJECT RelatedFO;
00512     UNICODE_STRING FileName;
00513     ULONG AllocationSize;
00514     PFILE_FULL_EA_INFORMATION EaBuffer;
00515     PACCESS_MASK DesiredAccess;
00516     ULONG Options;
00517     UCHAR FileAttributes;
00518     USHORT ShareAccess;
00519     ULONG EaLength;
00520 
00521     /* Misc */
00522     NTSTATUS Status;
00523     IO_STATUS_BLOCK Iosb;
00524     PIO_STACK_LOCATION IrpSp;
00525     BOOLEAN EndBackslash = FALSE, OpenedAsDos, FirstRun = TRUE;
00526     UNICODE_STRING RemainingPart, FirstName, NextName, FileNameUpcased;
00527     OEM_STRING AnsiFirstName;
00528     FF_ERROR FfError;
00529     TYPE_OF_OPEN TypeOfOpen;
00530     BOOLEAN OplockPostIrp = FALSE;
00531 
00532     Iosb.Status = STATUS_SUCCESS;
00533 
00534     /* Get current IRP stack location */
00535     IrpSp = IoGetCurrentIrpStackLocation(Irp);
00536 
00537     DPRINT("FatCommonCreate\n", 0 );
00538     DPRINT("Irp                       = %08lx\n",   Irp );
00539     DPRINT("\t->Flags                   = %08lx\n", Irp->Flags );
00540     DPRINT("\t->FileObject              = %08lx\n", IrpSp->FileObject );
00541     DPRINT("\t->RelatedFileObject       = %08lx\n", IrpSp->FileObject->RelatedFileObject );
00542     DPRINT("\t->FileName                = %wZ\n",   &IrpSp->FileObject->FileName );
00543     DPRINT("\t->AllocationSize.LowPart  = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
00544     DPRINT("\t->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
00545     DPRINT("\t->SystemBuffer            = %08lx\n", Irp->AssociatedIrp.SystemBuffer );
00546     DPRINT("\t->DesiredAccess           = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
00547     DPRINT("\t->Options                 = %08lx\n", IrpSp->Parameters.Create.Options );
00548     DPRINT("\t->FileAttributes          = %04x\n",  IrpSp->Parameters.Create.FileAttributes );
00549     DPRINT("\t->ShareAccess             = %04x\n",  IrpSp->Parameters.Create.ShareAccess );
00550     DPRINT("\t->EaLength                = %08lx\n", IrpSp->Parameters.Create.EaLength );
00551 
00552     /* Apply a special hack for Win32, idea taken from FASTFAT reference driver from WDK */
00553     if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
00554         (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
00555         (IrpSp->FileObject->FileName.Buffer[0] == L'\\'))
00556     {
00557         /* Remove a leading slash */
00558         IrpSp->FileObject->FileName.Length -= sizeof(WCHAR);
00559         RtlMoveMemory(&IrpSp->FileObject->FileName.Buffer[0],
00560                       &IrpSp->FileObject->FileName.Buffer[1],
00561                       IrpSp->FileObject->FileName.Length );
00562 
00563         /* Check again: if there are still two leading slashes,
00564            exit with an error */
00565         if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
00566             (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
00567             (IrpSp->FileObject->FileName.Buffer[0] == L'\\'))
00568         {
00569             FatCompleteRequest( IrpContext, Irp, STATUS_OBJECT_NAME_INVALID );
00570 
00571             DPRINT1("FatiCreate: STATUS_OBJECT_NAME_INVALID\n");
00572             return STATUS_OBJECT_NAME_INVALID;
00573         }
00574     }
00575 
00576     /* Make sure we have SecurityContext */
00577     ASSERT(IrpSp->Parameters.Create.SecurityContext != NULL);
00578 
00579     /* Get necessary data out of IRP */
00580     FileObject     = IrpSp->FileObject;
00581     FileName       = FileObject->FileName;
00582     RelatedFO      = FileObject->RelatedFileObject;
00583     AllocationSize = Irp->Overlay.AllocationSize.LowPart;
00584     EaBuffer       = Irp->AssociatedIrp.SystemBuffer;
00585     DesiredAccess  = &IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
00586     Options        = IrpSp->Parameters.Create.Options;
00587     FileAttributes = (UCHAR)(IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL);
00588     ShareAccess    = IrpSp->Parameters.Create.ShareAccess;
00589     EaLength       = IrpSp->Parameters.Create.EaLength;
00590 
00591     /* Set VPB to related object's VPB if it exists */
00592     if (RelatedFO)
00593         FileObject->Vpb = RelatedFO->Vpb;
00594 
00595     /* Reject open by id */
00596     if (Options & FILE_OPEN_BY_FILE_ID)
00597     {
00598         FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
00599         return STATUS_INVALID_PARAMETER;
00600     }
00601 
00602     /* Prepare file attributes mask */
00603     FileAttributes &= (FILE_ATTRIBUTE_READONLY |
00604                        FILE_ATTRIBUTE_HIDDEN   |
00605                        FILE_ATTRIBUTE_SYSTEM   |
00606                        FILE_ATTRIBUTE_ARCHIVE);
00607 
00608     /* Get the volume control object */
00609     Vcb = &((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Vcb;
00610 
00611     /* Get options */
00612     IsDirectoryFile         = BooleanFlagOn(Options, FILE_DIRECTORY_FILE);
00613     NonDirectoryFile        = BooleanFlagOn(Options, FILE_NON_DIRECTORY_FILE);
00614     SequentialOnly          = BooleanFlagOn(Options, FILE_SEQUENTIAL_ONLY);
00615     NoIntermediateBuffering = BooleanFlagOn(Options, FILE_NO_INTERMEDIATE_BUFFERING);
00616     NoEaKnowledge           = BooleanFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
00617     DeleteOnClose           = BooleanFlagOn(Options, FILE_DELETE_ON_CLOSE);
00618     TemporaryFile           = BooleanFlagOn(IrpSp->Parameters.Create.FileAttributes,
00619                                             FILE_ATTRIBUTE_TEMPORARY );
00620     IsPagingFile            = BooleanFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
00621     OpenTargetDirectory     = BooleanFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
00622 
00623     /* Calculate create disposition */
00624     CreateDisposition = (Options >> 24) & 0x000000ff;
00625 
00626     /* Get Create/Open directory flags based on it */
00627     CreateDirectory = (BOOLEAN)(IsDirectoryFile &&
00628                                 ((CreateDisposition == FILE_CREATE) ||
00629                                  (CreateDisposition == FILE_OPEN_IF)));
00630 
00631     OpenDirectory   = (BOOLEAN)(IsDirectoryFile &&
00632                                 ((CreateDisposition == FILE_OPEN) ||
00633                                  (CreateDisposition == FILE_OPEN_IF)));
00634 
00635     /* Validate parameters: directory/nondirectory mismatch and
00636        AllocationSize being more than 4GB */
00637     if ((IsDirectoryFile && NonDirectoryFile) ||
00638         Irp->Overlay.AllocationSize.HighPart != 0)
00639     {
00640         FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
00641 
00642         DPRINT1("FatiCreate: STATUS_INVALID_PARAMETER\n", 0);
00643         return STATUS_INVALID_PARAMETER;
00644     }
00645 
00646     /* Acquire the VCB lock exclusively */
00647     if (!FatAcquireExclusiveVcb(IrpContext, Vcb))
00648     {
00649         // TODO: Postpone the IRP for later processing
00650         ASSERT(FALSE);
00651         return STATUS_NOT_IMPLEMENTED;
00652     }
00653 
00654     // TODO: Verify the VCB
00655 
00656     /* If VCB is locked, then no file openings are possible */
00657     if (Vcb->State & VCB_STATE_FLAG_LOCKED)
00658     {
00659         DPRINT1("This volume is locked\n");
00660         Status = STATUS_ACCESS_DENIED;
00661 
00662         /* Set volume dismount status */
00663         if (Vcb->Condition != VcbGood)
00664             Status = STATUS_VOLUME_DISMOUNTED;
00665 
00666         /* Cleanup and return */
00667         FatReleaseVcb(IrpContext, Vcb);
00668         FatCompleteRequest(IrpContext, Irp, Status);
00669         return Status;
00670     }
00671 
00672     /* Check if the volume is write protected and disallow DELETE_ON_CLOSE */
00673     if (DeleteOnClose & FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
00674     {
00675         ASSERT(FALSE);
00676         return STATUS_NOT_IMPLEMENTED;
00677     }
00678 
00679     // TODO: Make sure EAs aren't supported on FAT32
00680 
00681     /* Check if it's a volume open request */
00682     if (FileName.Length == 0)
00683     {
00684         /* Test related FO to be sure */
00685         if (!RelatedFO ||
00686             FatDecodeFileObject(RelatedFO, &DecodedVcb, &Fcb, &Ccb) == UserVolumeOpen)
00687         {
00688             /* Check parameters */
00689             if (IsDirectoryFile || OpenTargetDirectory)
00690             {
00691                 Status = IsDirectoryFile ? STATUS_NOT_A_DIRECTORY : STATUS_INVALID_PARAMETER;
00692 
00693                 /* Unlock VCB */
00694                 FatReleaseVcb(IrpContext, Vcb);
00695 
00696                 /* Complete the request and return */
00697                 FatCompleteRequest(IrpContext, Irp, Status);
00698                 return Status;
00699             }
00700 
00701             /* It is indeed a volume open request */
00702             Iosb = FatiOpenVolume(IrpContext,
00703                                   FileObject,
00704                                   Vcb,
00705                                   DesiredAccess,
00706                                   ShareAccess,
00707                                   CreateDisposition);
00708 
00709             /* Set resulting information */
00710             Irp->IoStatus.Information = Iosb.Information;
00711 
00712             /* Unlock VCB */
00713             FatReleaseVcb(IrpContext, Vcb);
00714 
00715             /* Complete the request and return */
00716             FatCompleteRequest(IrpContext, Irp, Iosb.Status);
00717             return Iosb.Status;
00718         }
00719     }
00720 
00721     /* Check if this is a relative open */
00722     if (RelatedFO)
00723     {
00724         /* Decode the file object */
00725         TypeOfOpen = FatDecodeFileObject(RelatedFO,
00726                                          &RelatedVcb,
00727                                          &RelatedDcb,
00728                                          &RelatedCcb);
00729 
00730         /* Check open type */
00731         if (TypeOfOpen != UserFileOpen &&
00732             TypeOfOpen != UserDirectoryOpen)
00733         {
00734             DPRINT1("Invalid file object!\n");
00735 
00736             Status = STATUS_OBJECT_PATH_NOT_FOUND;
00737 
00738             /* Cleanup and return */
00739             FatReleaseVcb(IrpContext, Vcb);
00740             FatCompleteRequest(IrpContext, Irp, Status);
00741             return Status;
00742         }
00743 
00744         /* File path must be relative */
00745         if (FileName.Length != 0 &&
00746             FileName.Buffer[0] == L'\\')
00747         {
00748             Status = STATUS_OBJECT_NAME_INVALID;
00749 
00750             /* The name is absolute, fail */
00751             FatReleaseVcb(IrpContext, Vcb);
00752             FatCompleteRequest(IrpContext, Irp, Status);
00753             return Status;
00754         }
00755 
00756         /* Make sure volume is the same */
00757         ASSERT(RelatedVcb == Vcb);
00758 
00759         /* Save VPB */
00760         FileObject->Vpb = RelatedFO->Vpb;
00761 
00762         /* Set parent DCB */
00763         ParentDcb = RelatedDcb;
00764 
00765         DPRINT("Opening file '%wZ' relatively to '%wZ'\n", &FileName, &ParentDcb->FullFileName);
00766     }
00767     else
00768     {
00769         /* Absolute open */
00770         if ((FileName.Length == sizeof(WCHAR)) &&
00771             (FileName.Buffer[0] == L'\\'))
00772         {
00773             /* Check if it's ok to open it */
00774             if (NonDirectoryFile)
00775             {
00776                 DPRINT1("Trying to open root dir as a file\n");
00777                 Status = STATUS_FILE_IS_A_DIRECTORY;
00778 
00779                 /* Cleanup and return */
00780                 FatReleaseVcb(IrpContext, Vcb);
00781                 FatCompleteRequest(IrpContext, Irp, Status);
00782                 return Status;
00783             }
00784 
00785             /* Check for target directory on a root dir */
00786             if (OpenTargetDirectory)
00787             {
00788                 Status = STATUS_INVALID_PARAMETER;
00789 
00790                 /* Cleanup and return */
00791                 FatReleaseVcb(IrpContext, Vcb);
00792                 FatCompleteRequest(IrpContext, Irp, Status);
00793                 return Status;
00794             }
00795 
00796             /* Check delete on close on a root dir */
00797             if (DeleteOnClose)
00798             {
00799                 Status = STATUS_CANNOT_DELETE;
00800 
00801                 /* Cleanup and return */
00802                 FatReleaseVcb(IrpContext, Vcb);
00803                 FatCompleteRequest(IrpContext, Irp, Status);
00804                 return Status;
00805             }
00806 
00807             /* Call root directory open routine */
00808             Iosb = FatiOpenRootDcb(IrpContext,
00809                                    FileObject,
00810                                    Vcb,
00811                                    DesiredAccess,
00812                                    ShareAccess,
00813                                    CreateDisposition);
00814 
00815             Irp->IoStatus.Information = Iosb.Information;
00816 
00817             /* Cleanup and return */
00818             FatReleaseVcb(IrpContext, Vcb);
00819             FatCompleteRequest(IrpContext, Irp, Iosb.Status);
00820             return Iosb.Status;
00821         }
00822         else
00823         {
00824             /* Not a root dir */
00825             ParentDcb = Vcb->RootDcb;
00826             DPRINT("ParentDcb %p\n", ParentDcb);
00827         }
00828     }
00829 
00830     /* Check for backslash at the end */
00831     if (FileName.Length &&
00832         FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1] == L'\\')
00833     {
00834         /* Cut it out */
00835         FileName.Length -= sizeof(WCHAR);
00836 
00837         /* Remember we cut it */
00838         EndBackslash = TRUE;
00839     }
00840 
00841     /* Ensure the name is set */
00842     if (!ParentDcb->FullFileName.Buffer)
00843     {
00844         /* Set it if it's missing */
00845         FatSetFullFileNameInFcb(IrpContext, ParentDcb);
00846     }
00847 
00848     /* Check max path length */
00849     if (ParentDcb->FullFileName.Length + FileName.Length + sizeof(WCHAR) <= FileName.Length)
00850     {
00851         DPRINT1("Max length is way off\n");
00852         Iosb.Status = STATUS_OBJECT_NAME_INVALID;
00853         ASSERT(FALSE);
00854     }
00855 
00856     /* Loop through FCBs to find a good one */
00857     while (TRUE)
00858     {
00859         Fcb = ParentDcb;
00860 
00861         /* Dissect the name */
00862         RemainingPart = FileName;
00863         while (RemainingPart.Length)
00864         {
00865             FsRtlDissectName(RemainingPart, &FirstName, &NextName);
00866 
00867             /* Check for validity */
00868             if ((NextName.Length && NextName.Buffer[0] == L'\\') ||
00869                 (NextName.Length > 255 * sizeof(WCHAR)))
00870             {
00871                 /* The name is invalid */
00872                 DPRINT1("Invalid name found\n");
00873                 Iosb.Status = STATUS_OBJECT_NAME_INVALID;
00874                 ASSERT(FALSE);
00875             }
00876 
00877             /* Convert the name to ANSI */
00878             AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length);
00879             AnsiFirstName.Length = 0;
00880             AnsiFirstName.MaximumLength = FirstName.Length;
00881             Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE);
00882 
00883             if (!NT_SUCCESS(Status))
00884             {
00885                 DPRINT1("RtlUpcaseUnicodeStringToCountedOemString() failed with 0x%08x\n", Status);
00886                 ASSERT(FALSE);
00887                 NextFcb = NULL;
00888                 AnsiFirstName.Length = 0;
00889             }
00890             else
00891             {
00892                 /* Find the coresponding FCB */
00893                 NextFcb = FatFindFcb(IrpContext,
00894                                      &Fcb->Dcb.SplayLinksAnsi,
00895                                      (PSTRING)&AnsiFirstName,
00896                                      &OpenedAsDos);
00897             }
00898 
00899             /* If nothing found - try with unicode */
00900             if (!NextFcb && Fcb->Dcb.SplayLinksUnicode)
00901             {
00902                 FileNameUpcased.Buffer = FsRtlAllocatePool(PagedPool, FirstName.Length);
00903                 FileNameUpcased.Length = 0;
00904                 FileNameUpcased.MaximumLength = FirstName.Length;
00905 
00906                 /* Downcase and then upcase to normalize it */
00907                 Status = RtlDowncaseUnicodeString(&FileNameUpcased, &FirstName, FALSE);
00908                 Status = RtlUpcaseUnicodeString(&FileNameUpcased, &FileNameUpcased, FALSE);
00909 
00910                 /* Try to find FCB again using unicode name */
00911                 NextFcb = FatFindFcb(IrpContext,
00912                                      &Fcb->Dcb.SplayLinksUnicode,
00913                                      (PSTRING)&FileNameUpcased,
00914                                      &OpenedAsDos);
00915             }
00916 
00917             /* Move to the next FCB */
00918             if (NextFcb)
00919             {
00920                 Fcb = NextFcb;
00921                 RemainingPart = NextName;
00922             }
00923 
00924             /* Break out of this loop if nothing can be found */
00925             if (!NextFcb ||
00926                 NextName.Length == 0 ||
00927                 FatNodeType(NextFcb) == FAT_NTC_FCB)
00928             {
00929                 break;
00930             }
00931         }
00932 
00933         /* Ensure remaining name doesn't start from a backslash */
00934         if (RemainingPart.Length &&
00935             RemainingPart.Buffer[0] == L'\\')
00936         {
00937             /* Cut it */
00938             RemainingPart.Buffer++;
00939             RemainingPart.Length -= sizeof(WCHAR);
00940         }
00941 
00942         if (Fcb->Condition == FcbGood)
00943         {
00944             /* Good FCB, break out of the loop */
00945             break;
00946         }
00947         else
00948         {
00949             ASSERT(FALSE);
00950         }
00951     }
00952 
00953     /* Treat page file in a special way */
00954     if (IsPagingFile)
00955     {
00956         UNIMPLEMENTED;
00957         // FIXME: System file too
00958     }
00959 
00960     /* Make sure there is no pending delete on a higher-level FCB */
00961     if (Fcb->State & FCB_STATE_DELETE_ON_CLOSE)
00962     {
00963         Iosb.Status = STATUS_DELETE_PENDING;
00964 
00965         /* Cleanup and return */
00966         FatReleaseVcb(IrpContext, Vcb);
00967 
00968         /* Complete the request */
00969         FatCompleteRequest(IrpContext, Irp, Iosb.Status);
00970 
00971         return Iosb.Status;
00972     }
00973 
00974     /* We have a valid FCB now */
00975     if (!RemainingPart.Length)
00976     {
00977         /* Check for target dir open */
00978         if (OpenTargetDirectory)
00979         {
00980             DPRINT1("Opening target dir is missing\n");
00981             ASSERT(FALSE);
00982         }
00983 
00984         /* Check this FCB's type */
00985         if (FatNodeType(Fcb) == FAT_NTC_ROOT_DCB ||
00986             FatNodeType(Fcb) == FAT_NTC_DCB)
00987         {
00988             /* Open a directory */
00989             if (NonDirectoryFile)
00990             {
00991                 /* Forbidden */
00992                 Iosb.Status = STATUS_FILE_IS_A_DIRECTORY;
00993                 ASSERT(FALSE);
00994                 return Iosb.Status;
00995             }
00996 
00997             /* Open existing DCB */
00998             Iosb = FatiOpenExistingDcb(IrpContext,
00999                                        FileObject,
01000                                        Vcb,
01001                                        Fcb,
01002                                        DesiredAccess,
01003                                        ShareAccess,
01004                                        CreateDisposition,
01005                                        NoEaKnowledge,
01006                                        DeleteOnClose);
01007 
01008             /* Save information */
01009             Irp->IoStatus.Information = Iosb.Information;
01010 
01011             /* Unlock VCB */
01012             FatReleaseVcb(IrpContext, Vcb);
01013 
01014             /* Complete the request */
01015             FatCompleteRequest(IrpContext, Irp, Iosb.Status);
01016 
01017             return Iosb.Status;
01018         }
01019         else if (FatNodeType(Fcb) == FAT_NTC_FCB)
01020         {
01021             /* Open a file */
01022             if (OpenDirectory)
01023             {
01024                 /* Forbidden */
01025                 Iosb.Status = STATUS_NOT_A_DIRECTORY;
01026                 ASSERT(FALSE);
01027                 return Iosb.Status;
01028             }
01029 
01030             /* Check for trailing backslash */
01031             if (EndBackslash)
01032             {
01033                 /* Forbidden */
01034                 Iosb.Status = STATUS_OBJECT_NAME_INVALID;
01035                 ASSERT(FALSE);
01036                 return Iosb.Status;
01037             }
01038 
01039             Iosb = FatiOpenExistingFcb(IrpContext,
01040                                        FileObject,
01041                                        Vcb,
01042                                        Fcb,
01043                                        DesiredAccess,
01044                                        ShareAccess,
01045                                        AllocationSize,
01046                                        EaBuffer,
01047                                        EaLength,
01048                                        FileAttributes,
01049                                        CreateDisposition,
01050                                        NoEaKnowledge,
01051                                        DeleteOnClose,
01052                                        OpenedAsDos,
01053                                        &OplockPostIrp);
01054 
01055             /* Check if it's pending */
01056             if (Iosb.Status != STATUS_PENDING)
01057             {
01058                 /* In case of success set cache supported flag */
01059                 if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering)
01060                 {
01061                     SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
01062                 }
01063 
01064                 /* Save information */
01065                 Irp->IoStatus.Information = Iosb.Information;
01066 
01067                 /* Unlock VCB */
01068                 FatReleaseVcb(IrpContext, Vcb);
01069 
01070                 /* Complete the request */
01071                 FatCompleteRequest(IrpContext, Irp, Iosb.Status);
01072 
01073                 return Iosb.Status;
01074             }
01075             else
01076             {
01077                 /* Queue this IRP */
01078                 UNIMPLEMENTED;
01079                 ASSERT(FALSE);
01080             }
01081         }
01082         else
01083         {
01084             /* Unexpected FCB type */
01085             KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)Fcb, 0, 0);
01086         }
01087     }
01088 
01089     /* During parsing we encountered a part which has no attached FCB/DCB.
01090     Check that the parent is really DCB and not FCB */
01091     if (FatNodeType(Fcb) != FAT_NTC_ROOT_DCB &&
01092         FatNodeType(Fcb) != FAT_NTC_DCB)
01093     {
01094         DPRINT1("Weird FCB node type %x, expected DCB or root DCB\n", FatNodeType(Fcb));
01095         ASSERT(FALSE);
01096     }
01097 
01098     /* Create additional DCBs for all path items */
01099     ParentDcb = Fcb;
01100     while (TRUE)
01101     {
01102         if (FirstRun)
01103         {
01104             RemainingPart = NextName;
01105             if (AnsiFirstName.Length)
01106                 Status = STATUS_SUCCESS;
01107             else
01108                 Status = STATUS_UNMAPPABLE_CHARACTER;
01109 
01110             /* First run init is done */
01111             FirstRun = FALSE;
01112         }
01113         else
01114         {
01115             FsRtlDissectName(RemainingPart, &FirstName, &RemainingPart);
01116 
01117             /* Check for validity */
01118             if ((RemainingPart.Length && RemainingPart.Buffer[0] == L'\\') ||
01119                 (NextName.Length > 255 * sizeof(WCHAR)))
01120             {
01121                 /* The name is invalid */
01122                 DPRINT1("Invalid name found\n");
01123                 Iosb.Status = STATUS_OBJECT_NAME_INVALID;
01124                 ASSERT(FALSE);
01125             }
01126 
01127             /* Convert the name to ANSI */
01128             AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length);
01129             AnsiFirstName.Length = 0;
01130             AnsiFirstName.MaximumLength = FirstName.Length;
01131             Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE);
01132         }
01133 
01134         if (!NT_SUCCESS(Status))
01135         {
01136             ASSERT(FALSE);
01137         }
01138 
01139         DPRINT("FirstName %wZ, RemainingPart %wZ\n", &FirstName, &RemainingPart);
01140 
01141         /* Break if came to the end */
01142         if (!RemainingPart.Length) break;
01143 
01144         /* Create a DCB for this entry */
01145         ParentDcb = FatCreateDcb(IrpContext,
01146                                  Vcb,
01147                                  ParentDcb,
01148                                  NULL);
01149 
01150         /* Set its name */
01151         FatSetFullNameInFcb(ParentDcb, &FirstName);
01152     }
01153 
01154     /* Try to open it and get a result, saying if this is a dir or a file */
01155     FfError = FatiTryToOpen(FileObject, Vcb);
01156 
01157     /* Check if we need to open target directory */
01158     if (OpenTargetDirectory)
01159     {
01160         // TODO: Open target directory
01161         UNIMPLEMENTED;
01162     }
01163 
01164     /* Check, if path is a existing directory or file */
01165     if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR ||
01166         FfError == FF_ERR_FILE_ALREADY_OPEN ||
01167         FfError == FF_ERR_NONE)
01168     {
01169         if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR)
01170         {
01171             if (NonDirectoryFile)
01172             {
01173                 DPRINT1("Can't open dir as a file\n");
01174 
01175                 /* Unlock VCB */
01176                 FatReleaseVcb(IrpContext, Vcb);
01177 
01178                 /* Complete the request */
01179                 Iosb.Status = STATUS_FILE_IS_A_DIRECTORY;
01180                 FatCompleteRequest(IrpContext, Irp, Iosb.Status);
01181                 return Iosb.Status;
01182             }
01183 
01184             /* Open this directory */
01185             Iosb = FatiOpenExistingDir(IrpContext,
01186                 FileObject,
01187                 Vcb,
01188                 ParentDcb,
01189                 DesiredAccess,
01190                 ShareAccess,
01191                 AllocationSize,
01192                 EaBuffer,
01193                 EaLength,
01194                 FileAttributes,
01195                 CreateDisposition,
01196                 DeleteOnClose);
01197 
01198             Irp->IoStatus.Information = Iosb.Information;
01199 
01200             /* Unlock VCB */
01201             FatReleaseVcb(IrpContext, Vcb);
01202 
01203             /* Complete the request */
01204             FatCompleteRequest(IrpContext, Irp, Iosb.Status);
01205 
01206             return Iosb.Status;
01207         }
01208         else
01209         {
01210             /* This is opening an existing file */
01211             if (OpenDirectory)
01212             {
01213                 /* But caller wanted a dir */
01214                 Status = STATUS_NOT_A_DIRECTORY;
01215 
01216                 /* Unlock VCB */
01217                 FatReleaseVcb(IrpContext, Vcb);
01218 
01219                 /* Complete the request */
01220                 FatCompleteRequest(IrpContext, Irp, Status);
01221 
01222                 return Status;
01223             }
01224 
01225             /* If end backslash here, then it's definately not permitted,
01226             since we're opening files here */
01227             if (EndBackslash)
01228             {
01229                 /* Unlock VCB */
01230                 FatReleaseVcb(IrpContext, Vcb);
01231 
01232                 /* Complete the request */
01233                 Iosb.Status = STATUS_OBJECT_NAME_INVALID;
01234                 FatCompleteRequest(IrpContext, Irp, Iosb.Status);
01235                 return Iosb.Status;
01236             }
01237 
01238             /* Try to open the file */
01239             Iosb = FatiOpenExistingFile(IrpContext,
01240                                         FileObject,
01241                                         Vcb,
01242                                         ParentDcb,
01243                                         DesiredAccess,
01244                                         ShareAccess,
01245                                         AllocationSize,
01246                                         EaBuffer,
01247                                         EaLength,
01248                                         FileAttributes,
01249                                         CreateDisposition,
01250                                         FALSE,
01251                                         DeleteOnClose,
01252                                         OpenedAsDos);
01253 
01254             /* In case of success set cache supported flag */
01255             if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering)
01256             {
01257                 SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
01258             }
01259 
01260             Irp->IoStatus.Information = Iosb.Information;
01261 
01262             /* Unlock VCB */
01263             FatReleaseVcb(IrpContext, Vcb);
01264 
01265             /* Complete the request */
01266             FatCompleteRequest(IrpContext, Irp, Iosb.Status);
01267 
01268             return Iosb.Status;
01269         }
01270     }
01271 
01272     /* We come here only in the case when a new file is created */
01273     //ASSERT(FALSE);
01274     DPRINT1("TODO: Create a new file/directory, called '%wZ'\n", &IrpSp->FileObject->FileName);
01275 
01276     Status = STATUS_NOT_IMPLEMENTED;
01277 
01278     /* Unlock VCB */
01279     FatReleaseVcb(IrpContext, Vcb);
01280 
01281     /* Complete the request */
01282     FatCompleteRequest(IrpContext, Irp, Status);
01283 
01284     return Status;
01285 }
01286 
01287 NTSTATUS
01288 NTAPI
01289 FatCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
01290 {
01291     PFAT_IRP_CONTEXT IrpContext;
01292     NTSTATUS Status;
01293 
01294     /* If it's called with our Disk FS device object - it's always open */
01295     // TODO: Add check for CDROM FS device object
01296     if (DeviceObject == FatGlobalData.DiskDeviceObject)
01297     {
01298         /* Complete the request and return success */
01299         Irp->IoStatus.Status = STATUS_SUCCESS;
01300         Irp->IoStatus.Information = FILE_OPENED;
01301 
01302         IoCompleteRequest(Irp, IO_DISK_INCREMENT);
01303 
01304         return STATUS_SUCCESS;
01305     }
01306 
01307     /* Enter FsRtl critical region */
01308     FsRtlEnterFileSystem();
01309 
01310     /* Build an irp context */
01311     IrpContext = FatBuildIrpContext(Irp, TRUE);
01312 
01313     /* Call internal function */
01314     Status = FatiCreate(IrpContext, Irp);
01315 
01316     /* Leave FsRtl critical region */
01317     FsRtlExitFileSystem();
01318 
01319     return Status;
01320 }
01321 
01322 /* EOF */

Generated on Fri May 25 2012 04:15:16 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.