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  *  ReactOS kernel
00003  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /*
00020  * PROJECT:          ReactOS kernel
00021  * FILE:             drivers/fs/vfat/create.c
00022  * PURPOSE:          VFAT Filesystem
00023  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
00024  */
00025 
00026 /* INCLUDES *****************************************************************/
00027 
00028 #define NDEBUG
00029 #include "vfat.h"
00030 
00031 /* FUNCTIONS *****************************************************************/
00032 
00033 void
00034 vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
00035 {
00036     OEM_STRING StringA;
00037     USHORT Length;
00038     CHAR  cString[12];
00039 
00040     RtlCopyMemory(cString, pEntry->ShortName, 11);
00041     cString[11] = 0;
00042     if (cString[0] == 0x05)
00043     {
00044         cString[0] = 0xe5;
00045     }
00046 
00047     StringA.Buffer = cString;
00048     for (StringA.Length = 0;
00049     StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
00050     StringA.Length++);
00051     StringA.MaximumLength = StringA.Length;
00052 
00053     RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
00054 
00055     if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
00056     {
00057         RtlDowncaseUnicodeString(NameU, NameU, FALSE);
00058     }
00059     if (cString[8] != ' ')
00060     {
00061         Length = NameU->Length;
00062         NameU->Buffer += Length / sizeof(WCHAR);
00063         if (!FAT_ENTRY_VOLUME(pEntry))
00064         {
00065             Length += sizeof(WCHAR);
00066             NameU->Buffer[0] = L'.';
00067             NameU->Buffer++;
00068         }
00069         NameU->Length = 0;
00070         NameU->MaximumLength -= Length;
00071 
00072         StringA.Buffer = &cString[8];
00073         for (StringA.Length = 0;
00074         StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
00075         StringA.Length++);
00076         StringA.MaximumLength = StringA.Length;
00077         RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
00078         if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
00079         {
00080             RtlDowncaseUnicodeString(NameU, NameU, FALSE);
00081         }
00082         NameU->Buffer -= Length / sizeof(WCHAR);
00083         NameU->Length += Length;
00084         NameU->MaximumLength += Length;
00085     }
00086     NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
00087     DPRINT("'%wZ'\n", NameU);
00088 }
00089 
00090 NTSTATUS
00091 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
00092 /*
00093  * FUNCTION: Read the volume label
00094  */
00095 {
00096     PVOID Context = NULL;
00097     ULONG DirIndex = 0;
00098     PDIR_ENTRY Entry;
00099     PVFATFCB pFcb;
00100     LARGE_INTEGER FileOffset;
00101     UNICODE_STRING NameU;
00102     ULONG SizeDirEntry;
00103     ULONG EntriesPerPage;
00104     OEM_STRING StringO;
00105 
00106     NameU.Buffer = Vpb->VolumeLabel;
00107     NameU.Length = 0;
00108     NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
00109     *(Vpb->VolumeLabel) = 0;
00110     Vpb->VolumeLabelLength = 0;
00111 
00112     if (DeviceExt->Flags & VCB_IS_FATX)
00113     {
00114         SizeDirEntry = sizeof(FATX_DIR_ENTRY);
00115         EntriesPerPage = FATX_ENTRIES_PER_PAGE;
00116     }
00117     else
00118     {
00119         SizeDirEntry = sizeof(FAT_DIR_ENTRY);
00120         EntriesPerPage = FAT_ENTRIES_PER_PAGE;
00121     }
00122 
00123     ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
00124     pFcb = vfatOpenRootFCB (DeviceExt);
00125     ExReleaseResourceLite (&DeviceExt->DirResource);
00126 
00127     FileOffset.QuadPart = 0;
00128     if (CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
00129     {
00130         while (TRUE)
00131         {
00132             if (ENTRY_VOLUME(DeviceExt, Entry))
00133             {
00134                 /* copy volume label */
00135                 if (DeviceExt->Flags & VCB_IS_FATX)
00136                 {
00137                     StringO.Buffer = (PCHAR)Entry->FatX.Filename;
00138                     StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
00139                     RtlOemStringToUnicodeString(&NameU, &StringO, FALSE);
00140                 }
00141                 else
00142                 {
00143                     vfat8Dot3ToString (&Entry->Fat, &NameU);
00144                 }
00145                 Vpb->VolumeLabelLength = NameU.Length;
00146                 break;
00147             }
00148             if (ENTRY_END(DeviceExt, Entry))
00149             {
00150                 break;
00151             }
00152             DirIndex++;
00153             Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
00154             if ((DirIndex % EntriesPerPage) == 0)
00155             {
00156                 CcUnpinData(Context);
00157                 FileOffset.u.LowPart += PAGE_SIZE;
00158                 if (!CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
00159                 {
00160                     Context = NULL;
00161                     break;
00162                 }
00163             }
00164         }
00165         if (Context)
00166         {
00167             CcUnpinData(Context);
00168         }
00169     }
00170     ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
00171     vfatReleaseFCB (DeviceExt, pFcb);
00172     ExReleaseResourceLite (&DeviceExt->DirResource);
00173 
00174     return STATUS_SUCCESS;
00175 }
00176 
00177 NTSTATUS
00178 FindFile (
00179     PDEVICE_EXTENSION DeviceExt,
00180     PVFATFCB Parent,
00181     PUNICODE_STRING FileToFindU,
00182     PVFAT_DIRENTRY_CONTEXT DirContext,
00183     BOOLEAN First)
00184 /*
00185  * FUNCTION: Find a file
00186  */
00187 {
00188     PWCHAR PathNameBuffer;
00189     USHORT PathNameBufferLength;
00190     NTSTATUS Status;
00191     PVOID Context = NULL;
00192     PVOID Page;
00193     PVFATFCB rcFcb;
00194     BOOLEAN Found;
00195     UNICODE_STRING PathNameU;
00196     UNICODE_STRING FileToFindUpcase;
00197     BOOLEAN WildCard;
00198 
00199     DPRINT ("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %d)\n",
00200         Parent, FileToFindU, DirContext->DirIndex);
00201     DPRINT ("FindFile: Path %wZ\n",&Parent->PathNameU);
00202 
00203     PathNameBufferLength = LONGNAME_MAX_LENGTH * sizeof(WCHAR);
00204     PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameBufferLength + sizeof(WCHAR), TAG_VFAT);
00205     if (!PathNameBuffer)
00206     {
00207         return STATUS_INSUFFICIENT_RESOURCES;
00208     }
00209 
00210     PathNameU.Buffer = PathNameBuffer;
00211     PathNameU.Length = 0;
00212     PathNameU.MaximumLength = PathNameBufferLength;
00213 
00214     DirContext->LongNameU.Length = 0;
00215     DirContext->ShortNameU.Length = 0;
00216 
00217     WildCard = FsRtlDoesNameContainWildCards(FileToFindU);
00218 
00219     if (WildCard == FALSE)
00220     {
00221         /* if there is no '*?' in the search name, than look first for an existing fcb */
00222         RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
00223         if (!vfatFCBIsRoot(Parent))
00224         {
00225             PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
00226             PathNameU.Length += sizeof(WCHAR);
00227         }
00228         RtlAppendUnicodeStringToString(&PathNameU, FileToFindU);
00229         PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
00230         rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
00231         if (rcFcb)
00232         {
00233             ULONG startIndex = rcFcb->startIndex;
00234             if ((rcFcb->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(Parent))
00235             {
00236                 startIndex += 2;
00237             }
00238             if(startIndex >= DirContext->DirIndex)
00239             {
00240                 RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
00241                 RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
00242                 RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
00243                 DirContext->StartIndex = rcFcb->startIndex;
00244                 DirContext->DirIndex = rcFcb->dirIndex;
00245                 DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
00246                     &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
00247                 Status = STATUS_SUCCESS;
00248             }
00249             else
00250             {
00251                 DPRINT("FCB not found for %wZ\n", &PathNameU);
00252                 Status = STATUS_UNSUCCESSFUL;
00253             }
00254             vfatReleaseFCB(DeviceExt, rcFcb);
00255             ExFreePool(PathNameBuffer);
00256             return Status;
00257         }
00258     }
00259 
00260     /* FsRtlIsNameInExpression need the searched string to be upcase,
00261     * even if IgnoreCase is specified */
00262     Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFindU, TRUE);
00263     if (!NT_SUCCESS(Status))
00264     {
00265         ExFreePool(PathNameBuffer);
00266         return Status;
00267     }
00268 
00269     while(TRUE)
00270     {
00271         Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First);
00272         First = FALSE;
00273         if (Status == STATUS_NO_MORE_ENTRIES)
00274         {
00275             break;
00276         }
00277         if (ENTRY_VOLUME(DeviceExt, &DirContext->DirEntry))
00278         {
00279             DirContext->DirIndex++;
00280             continue;
00281         }
00282         if (WildCard)
00283         {
00284             Found = FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->LongNameU, TRUE, NULL) ||
00285                 FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->ShortNameU, TRUE, NULL);
00286         }
00287         else
00288         {
00289             Found = FsRtlAreNamesEqual(&DirContext->LongNameU, FileToFindU, TRUE, NULL) ||
00290                 FsRtlAreNamesEqual(&DirContext->ShortNameU, FileToFindU, TRUE, NULL);
00291         }
00292 
00293         if (Found)
00294         {
00295             if (WildCard)
00296             {
00297                 RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
00298                 if (!vfatFCBIsRoot(Parent))
00299                 {
00300                     PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
00301                     PathNameU.Length += sizeof(WCHAR);
00302                 }
00303                 RtlAppendUnicodeStringToString(&PathNameU, &DirContext->LongNameU);
00304                 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
00305                 rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
00306                 if (rcFcb != NULL)
00307                 {
00308                     RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
00309                     vfatReleaseFCB(DeviceExt, rcFcb);
00310                 }
00311             }
00312             DPRINT("%d\n", DirContext->LongNameU.Length);
00313             DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
00314                 &DirContext->LongNameU, DirContext->DirIndex);
00315 
00316             if (Context)
00317             {
00318                 CcUnpinData(Context);
00319             }
00320             RtlFreeUnicodeString(&FileToFindUpcase);
00321             ExFreePool(PathNameBuffer);
00322             return STATUS_SUCCESS;
00323         }
00324         DirContext->DirIndex++;
00325     }
00326 
00327     if (Context)
00328     {
00329         CcUnpinData(Context);
00330     }
00331 
00332     RtlFreeUnicodeString(&FileToFindUpcase);
00333     ExFreePool(PathNameBuffer);
00334     return Status;
00335 }
00336 
00337 static
00338 NTSTATUS
00339 VfatOpenFile (
00340     PDEVICE_EXTENSION DeviceExt,
00341         PUNICODE_STRING PathNameU,
00342     PFILE_OBJECT FileObject,
00343     PVFATFCB* ParentFcb )
00344 /*
00345  * FUNCTION: Opens a file
00346  */
00347 {
00348     PVFATFCB Fcb;
00349     NTSTATUS Status;
00350 
00351     DPRINT ("VfatOpenFile(%p, '%wZ', %p, %p)\n", DeviceExt, PathNameU, FileObject, ParentFcb);
00352 
00353     if (FileObject->RelatedFileObject)
00354     {
00355         DPRINT ("'%wZ'\n", &FileObject->RelatedFileObject->FileName);
00356 
00357         *ParentFcb = FileObject->RelatedFileObject->FsContext;
00358         (*ParentFcb)->RefCount++;
00359     }
00360     else
00361     {
00362         *ParentFcb = NULL;
00363     }
00364 
00365     if (!DeviceExt->FatInfo.FixedMedia)
00366     {
00367         Status = VfatBlockDeviceIoControl (DeviceExt->StorageDevice,
00368             IOCTL_DISK_CHECK_VERIFY,
00369             NULL,
00370             0,
00371             NULL,
00372             0,
00373             FALSE);
00374 
00375         if (!NT_SUCCESS(Status))
00376         {
00377             DPRINT ("Status %lx\n", Status);
00378             *ParentFcb = NULL;
00379             return Status;
00380         }
00381     }
00382 
00383     if (*ParentFcb)
00384     {
00385         (*ParentFcb)->RefCount++;
00386     }
00387 
00388     /*  try first to find an existing FCB in memory  */
00389     DPRINT ("Checking for existing FCB in memory\n");
00390 
00391     Status = vfatGetFCBForFile (DeviceExt, ParentFcb, &Fcb, PathNameU);
00392     if (!NT_SUCCESS (Status))
00393     {
00394         DPRINT ("Could not make a new FCB, status: %x\n", Status);
00395         return  Status;
00396     }
00397     if (Fcb->Flags & FCB_DELETE_PENDING)
00398     {
00399         vfatReleaseFCB (DeviceExt, Fcb);
00400         return STATUS_DELETE_PENDING;
00401     }
00402     DPRINT ("Attaching FCB to fileObject\n");
00403     Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
00404     if (!NT_SUCCESS(Status))
00405     {
00406         vfatReleaseFCB (DeviceExt, Fcb);
00407     }
00408     return  Status;
00409 }
00410 
00411 static NTSTATUS
00412 VfatCreateFile ( PDEVICE_OBJECT DeviceObject, PIRP Irp )
00413 /*
00414  * FUNCTION: Create or open a file
00415  */
00416 {
00417     PIO_STACK_LOCATION Stack;
00418     PFILE_OBJECT FileObject;
00419     NTSTATUS Status = STATUS_SUCCESS;
00420     PDEVICE_EXTENSION DeviceExt;
00421     ULONG RequestedDisposition, RequestedOptions;
00422     PVFATFCB pFcb = NULL;
00423     PVFATFCB ParentFcb = NULL;
00424     PWCHAR c, last;
00425     BOOLEAN PagingFileCreate = FALSE;
00426     BOOLEAN Dots;
00427     UNICODE_STRING FileNameU;
00428         UNICODE_STRING PathNameU;
00429 
00430     /* Unpack the various parameters. */
00431     Stack = IoGetCurrentIrpStackLocation (Irp);
00432     RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
00433     RequestedOptions =
00434         Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
00435     PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
00436     FileObject = Stack->FileObject;
00437     DeviceExt = DeviceObject->DeviceExtension;
00438 
00439     /* Check their validity. */
00440     if (RequestedOptions & FILE_DIRECTORY_FILE &&
00441         RequestedDisposition == FILE_SUPERSEDE)
00442     {
00443         return(STATUS_INVALID_PARAMETER);
00444     }
00445 
00446         if (RequestedOptions & FILE_DIRECTORY_FILE &&
00447             RequestedOptions & FILE_NON_DIRECTORY_FILE)
00448         {
00449         return(STATUS_INVALID_PARAMETER);
00450         }
00451 
00452     /* This a open operation for the volume itself */
00453     if (FileObject->FileName.Length == 0 &&
00454         (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
00455     {
00456         if (RequestedDisposition != FILE_OPEN &&
00457             RequestedDisposition != FILE_OPEN_IF)
00458         {
00459             return(STATUS_ACCESS_DENIED);
00460         }
00461 #if 0
00462         /* In spite of what is shown in WDK, it seems that Windows FAT driver doesn't perform that test */
00463         if (RequestedOptions & FILE_DIRECTORY_FILE)
00464         {
00465             return(STATUS_NOT_A_DIRECTORY);
00466         }
00467 #endif
00468 
00469         pFcb = DeviceExt->VolumeFcb;
00470         vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
00471         pFcb->RefCount++;
00472 
00473         Irp->IoStatus.Information = FILE_OPENED;
00474         return(STATUS_SUCCESS);
00475     }
00476 
00477     /*
00478      * Check for illegal characters and illegale dot sequences in the file name
00479      */
00480         PathNameU = FileObject->FileName;
00481     c = PathNameU.Buffer + PathNameU.Length / sizeof(WCHAR);
00482     last = c - 1;
00483     Dots = TRUE;
00484     while (c-- > PathNameU.Buffer)
00485     {
00486         if (*c == L'\\' || c == PathNameU.Buffer)
00487         {
00488             if (Dots && last > c)
00489             {
00490                 return(STATUS_OBJECT_NAME_INVALID);
00491             }
00492             last = c - 1;
00493             Dots = TRUE;
00494         }
00495         else if (*c != L'.')
00496         {
00497             Dots = FALSE;
00498         }
00499 
00500         if (*c != '\\' && vfatIsLongIllegal(*c))
00501         {
00502             return(STATUS_OBJECT_NAME_INVALID);
00503         }
00504     }
00505         if (FileObject->RelatedFileObject && PathNameU.Length >= sizeof(WCHAR) && PathNameU.Buffer[0] == L'\\')
00506         {
00507             return(STATUS_OBJECT_NAME_INVALID);
00508         }
00509         if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\')
00510         {
00511             PathNameU.Length -= sizeof(WCHAR);
00512         }
00513 
00514     /* Try opening the file. */
00515     Status = VfatOpenFile (DeviceExt, &PathNameU, FileObject, &ParentFcb);
00516 
00517     /*
00518      * If the directory containing the file to open doesn't exist then
00519      * fail immediately
00520      */
00521     if (Status == STATUS_OBJECT_PATH_NOT_FOUND ||
00522             Status == STATUS_INVALID_PARAMETER ||
00523         Status == STATUS_DELETE_PENDING)
00524     {
00525         if (ParentFcb)
00526         {
00527             vfatReleaseFCB (DeviceExt, ParentFcb);
00528         }
00529         return(Status);
00530     }
00531         if (!NT_SUCCESS(Status) && ParentFcb == NULL)
00532         {
00533                 DPRINT1("VfatOpenFile faild for '%wZ', status %x\n", &PathNameU, Status);
00534                 return Status;
00535         }
00536 
00537     /*
00538      * If the file open failed then create the required file
00539      */
00540     if (!NT_SUCCESS (Status))
00541     {
00542         if (RequestedDisposition == FILE_CREATE ||
00543             RequestedDisposition == FILE_OPEN_IF ||
00544             RequestedDisposition == FILE_OVERWRITE_IF ||
00545             RequestedDisposition == FILE_SUPERSEDE)
00546         {
00547             ULONG Attributes;
00548             Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
00549 
00550             vfatSplitPathName(&PathNameU, NULL, &FileNameU);
00551             Status = VfatAddEntry (DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
00552                 (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
00553             vfatReleaseFCB (DeviceExt, ParentFcb);
00554             if (NT_SUCCESS (Status))
00555             {
00556                 Status = vfatAttachFCBToFileObject (DeviceExt, pFcb, FileObject);
00557                 if ( !NT_SUCCESS(Status) )
00558                 {
00559                     vfatReleaseFCB (DeviceExt, pFcb);
00560                     return Status;
00561                 }
00562 
00563                 Irp->IoStatus.Information = FILE_CREATED;
00564                 VfatSetAllocationSizeInformation(FileObject,
00565                     pFcb,
00566                     DeviceExt,
00567                     &Irp->Overlay.AllocationSize);
00568                 VfatSetExtendedAttributes(FileObject,
00569                     Irp->AssociatedIrp.SystemBuffer,
00570                     Stack->Parameters.Create.EaLength);
00571 
00572                 if (PagingFileCreate)
00573                 {
00574                     pFcb->Flags |= FCB_IS_PAGE_FILE;
00575                 }
00576             }
00577             else
00578             {
00579                 return(Status);
00580             }
00581         }
00582         else
00583         {
00584             if (ParentFcb)
00585             {
00586                 vfatReleaseFCB (DeviceExt, ParentFcb);
00587             }
00588             return(Status);
00589         }
00590     }
00591     else
00592     {
00593         if (ParentFcb)
00594         {
00595             vfatReleaseFCB (DeviceExt, ParentFcb);
00596         }
00597         /* Otherwise fail if the caller wanted to create a new file  */
00598         if (RequestedDisposition == FILE_CREATE)
00599         {
00600             Irp->IoStatus.Information = FILE_EXISTS;
00601             VfatCloseFile (DeviceExt, FileObject);
00602             return(STATUS_OBJECT_NAME_COLLISION);
00603         }
00604 
00605         pFcb = FileObject->FsContext;
00606 
00607         if (pFcb->OpenHandleCount != 0)
00608         {
00609             Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
00610                 Stack->Parameters.Create.ShareAccess,
00611                 FileObject,
00612                 &pFcb->FCBShareAccess,
00613                 FALSE);
00614             if (!NT_SUCCESS(Status))
00615             {
00616                 VfatCloseFile (DeviceExt, FileObject);
00617                 return(Status);
00618             }
00619         }
00620 
00621         /*
00622          * Check the file has the requested attributes
00623          */
00624         if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
00625             *pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
00626         {
00627             VfatCloseFile (DeviceExt, FileObject);
00628             return(STATUS_FILE_IS_A_DIRECTORY);
00629         }
00630         if (RequestedOptions & FILE_DIRECTORY_FILE &&
00631             !(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
00632         {
00633             VfatCloseFile (DeviceExt, FileObject);
00634             return(STATUS_NOT_A_DIRECTORY);
00635         }
00636 #ifndef USE_ROS_CC_AND_FS
00637         if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
00638         {
00639             if (Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA ||
00640                 RequestedDisposition == FILE_OVERWRITE ||
00641                 RequestedDisposition == FILE_OVERWRITE_IF)
00642             {
00643                 if (!MmFlushImageSection(&pFcb->SectionObjectPointers, MmFlushForWrite))
00644                 {
00645                     DPRINT1("%wZ\n", &pFcb->PathNameU);
00646                     DPRINT1("%d %d %d\n", Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA,
00647                             RequestedDisposition == FILE_OVERWRITE, RequestedDisposition == FILE_OVERWRITE_IF);
00648                     VfatCloseFile (DeviceExt, FileObject);
00649                     return STATUS_SHARING_VIOLATION;
00650                 }
00651             }
00652         }
00653 #endif
00654         if (PagingFileCreate)
00655         {
00656             /* FIXME:
00657              *   Do more checking for page files. It is possible,
00658              *   that the file was opened and closed previously
00659              *   as a normal cached file. In this case, the cache
00660              *   manager has referenced the fileobject and the fcb
00661              *   is held in memory. Try to remove the fileobject
00662              *   from cache manager and use the fcb.
00663              */
00664             if (pFcb->RefCount > 1)
00665             {
00666                 if(!(pFcb->Flags & FCB_IS_PAGE_FILE))
00667                 {
00668                     VfatCloseFile(DeviceExt, FileObject);
00669                     return(STATUS_INVALID_PARAMETER);
00670                 }
00671             }
00672             else
00673             {
00674                 pFcb->Flags |= FCB_IS_PAGE_FILE;
00675             }
00676         }
00677         else
00678         {
00679             if (pFcb->Flags & FCB_IS_PAGE_FILE)
00680             {
00681                 VfatCloseFile(DeviceExt, FileObject);
00682                 return(STATUS_INVALID_PARAMETER);
00683             }
00684         }
00685 
00686 
00687         if (RequestedDisposition == FILE_OVERWRITE ||
00688             RequestedDisposition == FILE_OVERWRITE_IF ||
00689             RequestedDisposition == FILE_SUPERSEDE)
00690         {
00691                         ExAcquireResourceExclusiveLite(&(pFcb->MainResource), TRUE);
00692             Status = VfatSetAllocationSizeInformation (FileObject,
00693                                                    pFcb,
00694                                                    DeviceExt,
00695                                                    &Irp->Overlay.AllocationSize);
00696                         ExReleaseResourceLite(&(pFcb->MainResource));
00697             if (!NT_SUCCESS (Status))
00698             {
00699                 VfatCloseFile (DeviceExt, FileObject);
00700                 return(Status);
00701             }
00702         }
00703 
00704         if (RequestedDisposition == FILE_SUPERSEDE)
00705         {
00706             Irp->IoStatus.Information = FILE_SUPERSEDED;
00707         }
00708         else if (RequestedDisposition == FILE_OVERWRITE ||
00709                  RequestedDisposition == FILE_OVERWRITE_IF)
00710         {
00711             Irp->IoStatus.Information = FILE_OVERWRITTEN;
00712         }
00713         else
00714         {
00715             Irp->IoStatus.Information = FILE_OPENED;
00716         }
00717     }
00718 
00719     if (pFcb->OpenHandleCount == 0)
00720     {
00721         IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
00722             Stack->Parameters.Create.ShareAccess,
00723             FileObject,
00724             &pFcb->FCBShareAccess);
00725     }
00726     else
00727     {
00728         IoUpdateShareAccess(
00729             FileObject,
00730             &pFcb->FCBShareAccess
00731             );
00732 
00733     }
00734 
00735     pFcb->OpenHandleCount++;
00736 
00737     /* FIXME : test write access if requested */
00738 
00739     return(Status);
00740 }
00741 
00742 
00743 NTSTATUS
00744 VfatCreate (PVFAT_IRP_CONTEXT IrpContext)
00745 /*
00746  * FUNCTION: Create or open a file
00747  */
00748 {
00749     NTSTATUS Status;
00750 
00751     ASSERT(IrpContext);
00752 
00753     if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
00754     {
00755         /* DeviceObject represents FileSystem instead of logical volume */
00756         DPRINT ("FsdCreate called with file system\n");
00757         IrpContext->Irp->IoStatus.Information = FILE_OPENED;
00758         IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
00759         IoCompleteRequest (IrpContext->Irp, IO_DISK_INCREMENT);
00760         VfatFreeIrpContext(IrpContext);
00761         return(STATUS_SUCCESS);
00762     }
00763 
00764     if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
00765     {
00766         return(VfatQueueRequest (IrpContext));
00767     }
00768 
00769     IrpContext->Irp->IoStatus.Information = 0;
00770     ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, TRUE);
00771     Status = VfatCreateFile (IrpContext->DeviceObject, IrpContext->Irp);
00772     ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource);
00773 
00774     IrpContext->Irp->IoStatus.Status = Status;
00775     IoCompleteRequest (IrpContext->Irp,
00776         (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
00777     VfatFreeIrpContext(IrpContext);
00778     return(Status);
00779 }
00780 
00781 /* EOF */

Generated on Mon May 28 2012 04:16:55 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.