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

dirwr.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:        See COPYING in the top level directory
00003  * PROJECT:          ReactOS kernel
00004  * FILE:             drivers/fs/vfat/dirwr.c
00005  * PURPOSE:          VFAT Filesystem : write in directory
00006  *
00007  */
00008 
00009 /* INCLUDES *****************************************************************/
00010 
00011 #define NDEBUG
00012 #include "vfat.h"
00013 
00014 /*
00015  * update an existing FAT entry
00016  */
00017 NTSTATUS
00018 VfatUpdateEntry(
00019     IN PVFATFCB pFcb)
00020 {
00021     PVOID Context;
00022     PDIR_ENTRY PinEntry;
00023     LARGE_INTEGER Offset;
00024     ULONG SizeDirEntry;
00025     ULONG dirIndex;
00026 
00027     ASSERT(pFcb);
00028 
00029     if (pFcb->Flags & FCB_IS_FATX_ENTRY)
00030     {
00031         SizeDirEntry = sizeof(FATX_DIR_ENTRY);
00032         dirIndex = pFcb->startIndex;
00033     }
00034     else
00035     {
00036         SizeDirEntry = sizeof(FAT_DIR_ENTRY);
00037         dirIndex = pFcb->dirIndex;
00038     }
00039 
00040     DPRINT("updEntry dirIndex %d, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU);
00041 
00042     if (vfatFCBIsRoot(pFcb) || (pFcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)))
00043     {
00044         return STATUS_SUCCESS;
00045     }
00046 
00047     ASSERT(pFcb->parentFcb);
00048 
00049     Offset.u.HighPart = 0;
00050     Offset.u.LowPart = dirIndex * SizeDirEntry;
00051     if (CcPinRead(pFcb->parentFcb->FileObject, &Offset, SizeDirEntry,
00052         TRUE, &Context, (PVOID*)&PinEntry))
00053     {
00054         pFcb->Flags &= ~FCB_IS_DIRTY;
00055         RtlCopyMemory(PinEntry, &pFcb->entry, SizeDirEntry);
00056         CcSetDirtyPinnedData(Context, NULL);
00057         CcUnpinData(Context);
00058         return STATUS_SUCCESS;
00059     }
00060     else
00061     {
00062         DPRINT1("Failed write to \'%wZ\'.\n", &pFcb->parentFcb->PathNameU);
00063         return STATUS_UNSUCCESSFUL;
00064     }
00065 }
00066 
00067 /*
00068  * try to find contiguous entries frees in directory,
00069  * extend a directory if is neccesary
00070  */
00071 BOOLEAN
00072 vfatFindDirSpace(
00073     IN PDEVICE_EXTENSION DeviceExt,
00074     IN PVFATFCB pDirFcb,
00075     IN ULONG nbSlots,
00076     OUT PULONG start)
00077 {
00078     LARGE_INTEGER FileOffset;
00079     ULONG i, count, size, nbFree = 0;
00080     PDIR_ENTRY pFatEntry = NULL;
00081     PVOID Context = NULL;
00082     NTSTATUS Status;
00083     ULONG SizeDirEntry;
00084     FileOffset.QuadPart = 0;
00085 
00086     if (DeviceExt->Flags & VCB_IS_FATX)
00087         SizeDirEntry = sizeof(FATX_DIR_ENTRY);
00088     else
00089         SizeDirEntry = sizeof(FAT_DIR_ENTRY);
00090 
00091     count = pDirFcb->RFCB.FileSize.u.LowPart / SizeDirEntry;
00092     size = DeviceExt->FatInfo.BytesPerCluster / SizeDirEntry;
00093     for (i = 0; i < count; i++, pFatEntry = (PDIR_ENTRY)((ULONG_PTR)pFatEntry + SizeDirEntry))
00094     {
00095         if (Context == NULL || (i % size) == 0)
00096         {
00097             if (Context)
00098             {
00099                 CcUnpinData(Context);
00100             }
00101             if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
00102                       TRUE, &Context, (PVOID*)&pFatEntry))
00103             {
00104                 return FALSE;
00105             }
00106             FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
00107         }
00108         if (ENTRY_END(DeviceExt, pFatEntry))
00109         {
00110             break;
00111         }
00112         if (ENTRY_DELETED(DeviceExt, pFatEntry))
00113         {
00114             nbFree++;
00115         }
00116         else
00117         {
00118             nbFree = 0;
00119         }
00120         if (nbFree == nbSlots)
00121         {
00122             break;
00123         }
00124     }
00125     if (Context)
00126     {
00127         CcUnpinData(Context);
00128         Context = NULL;
00129     }
00130     if (nbFree == nbSlots)
00131     {
00132         /* found enough contiguous free slots */
00133         *start = i - nbSlots + 1;
00134     }
00135     else
00136     {
00137         *start = i - nbFree;
00138         if (*start + nbSlots > count)
00139         {
00140             LARGE_INTEGER AllocationSize;
00141             /* extend the directory */
00142             if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32)
00143             {
00144                 /* We can't extend a root directory on a FAT12/FAT16/FATX partition */
00145                 return FALSE;
00146             }
00147             AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster;
00148             Status = VfatSetAllocationSizeInformation(pDirFcb->FileObject, pDirFcb,
00149                                                       DeviceExt, &AllocationSize);
00150             if (!NT_SUCCESS(Status))
00151             {
00152                 return FALSE;
00153             }
00154             /* clear the new dir cluster */
00155             FileOffset.u.LowPart = (ULONG)(pDirFcb->RFCB.FileSize.QuadPart -
00156                                            DeviceExt->FatInfo.BytesPerCluster);
00157             if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
00158                       TRUE, &Context, (PVOID*)&pFatEntry))
00159             {
00160                 return FALSE;
00161             }
00162             if (DeviceExt->Flags & VCB_IS_FATX)
00163                 memset(pFatEntry, 0xff, DeviceExt->FatInfo.BytesPerCluster);
00164             else
00165                 RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
00166         }
00167         else if (*start + nbSlots < count)
00168         {
00169             /* clear the entry after the last new entry */
00170             FileOffset.u.LowPart = (*start + nbSlots) * SizeDirEntry;
00171             if (!CcPinRead(pDirFcb->FileObject, &FileOffset, SizeDirEntry,
00172                 TRUE, &Context, (PVOID*)&pFatEntry))
00173             {
00174                 return FALSE;
00175             }
00176             if (DeviceExt->Flags & VCB_IS_FATX)
00177                 memset(pFatEntry, 0xff, SizeDirEntry);
00178             else
00179                 RtlZeroMemory(pFatEntry, SizeDirEntry);
00180         }
00181         if (Context)
00182         {
00183             CcSetDirtyPinnedData(Context, NULL);
00184             CcUnpinData(Context);
00185         }
00186     }
00187     DPRINT("nbSlots %d nbFree %d, entry number %d\n", nbSlots, nbFree, *start);
00188     return TRUE;
00189 }
00190 
00191 /*
00192   create a new FAT entry
00193 */
00194 static NTSTATUS
00195 FATAddEntry(
00196     IN PDEVICE_EXTENSION DeviceExt,
00197     IN PUNICODE_STRING NameU,
00198     IN PVFATFCB* Fcb,
00199     IN PVFATFCB ParentFcb,
00200     IN ULONG RequestedOptions,
00201     IN UCHAR ReqAttr)
00202 {
00203     PVOID Context = NULL;
00204     PFAT_DIR_ENTRY pFatEntry;
00205     slot *pSlots;
00206     USHORT nbSlots = 0, j, posCar;
00207     PUCHAR Buffer;
00208     BOOLEAN needTilde = FALSE, needLong = FALSE;
00209     BOOLEAN lCaseBase = FALSE, uCaseBase, lCaseExt = FALSE, uCaseExt;
00210     ULONG CurrentCluster;
00211     LARGE_INTEGER SystemTime, FileOffset;
00212     NTSTATUS Status = STATUS_SUCCESS;
00213     ULONG size;
00214     long i;
00215 
00216     OEM_STRING NameA;
00217     CHAR aName[13];
00218     BOOLEAN IsNameLegal;
00219     BOOLEAN SpacesFound;
00220 
00221     VFAT_DIRENTRY_CONTEXT DirContext;
00222     WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];
00223     WCHAR ShortNameBuffer[13];
00224 
00225     DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);
00226 
00227     DirContext.LongNameU = *NameU;
00228 
00229     /* nb of entry needed for long name+normal entry */
00230     nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1;
00231     DPRINT("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
00232     Buffer = ExAllocatePoolWithTag(NonPagedPool, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY), TAG_VFAT);
00233     if (Buffer == NULL)
00234     {
00235         return STATUS_INSUFFICIENT_RESOURCES;
00236     }
00237     RtlZeroMemory(Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
00238     pSlots = (slot *) Buffer;
00239 
00240     NameA.Buffer = aName;
00241     NameA.Length = 0;
00242     NameA.MaximumLength = sizeof(aName);
00243 
00244     DirContext.ShortNameU.Buffer = ShortNameBuffer;
00245     DirContext.ShortNameU.Length = 0;
00246     DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
00247 
00248     RtlZeroMemory(&DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
00249 
00250     IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound);
00251 
00252     if (!IsNameLegal || SpacesFound)
00253     {
00254         GENERATE_NAME_CONTEXT NameContext;
00255         VFAT_DIRENTRY_CONTEXT SearchContext;
00256         WCHAR ShortSearchName[13];
00257         needTilde = TRUE;
00258         needLong = TRUE;
00259         RtlZeroMemory(&NameContext, sizeof(GENERATE_NAME_CONTEXT));
00260         SearchContext.LongNameU.Buffer = LongNameBuffer;
00261         SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
00262         SearchContext.ShortNameU.Buffer = ShortSearchName;
00263         SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);
00264 
00265         for (i = 0; i < 100; i++)
00266         {
00267             RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU);
00268             DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
00269                                          SearchContext.DirIndex = 0;
00270             Status = FindFile(DeviceExt, ParentFcb, &DirContext.ShortNameU, &SearchContext, TRUE);
00271             if (!NT_SUCCESS(Status))
00272             {
00273                 break;
00274             }
00275         }
00276         if (i == 100) /* FIXME : what to do after this ? */
00277         {
00278             ExFreePoolWithTag(Buffer, TAG_VFAT);
00279             return STATUS_UNSUCCESSFUL;
00280         }
00281         IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);
00282         aName[NameA.Length]=0;
00283     }
00284     else
00285     {
00286         aName[NameA.Length] = 0;
00287         for (posCar = 0; posCar < DirContext.LongNameU.Length / sizeof(WCHAR); posCar++)
00288         {
00289             if (DirContext.LongNameU.Buffer[posCar] == L'.')
00290             {
00291                 break;
00292             }
00293         }
00294         /* check if the name and the extension contains upper case characters */
00295         RtlDowncaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
00296         DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
00297         uCaseBase = wcsncmp(DirContext.LongNameU.Buffer,
00298                             DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;
00299         if (posCar < DirContext.LongNameU.Length/sizeof(WCHAR))
00300         {
00301             i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
00302             uCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
00303                                DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
00304         }
00305         else
00306         {
00307             uCaseExt = FALSE;
00308         }
00309         /* check if the name and the extension contains lower case characters */
00310         RtlUpcaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
00311         DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
00312         lCaseBase = wcsncmp(DirContext.LongNameU.Buffer,
00313                             DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;
00314         if (posCar < DirContext.LongNameU.Length / sizeof(WCHAR))
00315         {
00316             i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
00317             lCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
00318                                DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
00319         }
00320         else
00321         {
00322             lCaseExt = FALSE;
00323         }
00324         if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt))
00325         {
00326             needLong = TRUE;
00327         }
00328     }
00329     DPRINT("'%s', '%wZ', needTilde=%d, needLong=%d\n",
00330            aName, &DirContext.LongNameU, needTilde, needLong);
00331     memset(DirContext.DirEntry.Fat.ShortName, ' ', 11);
00332     for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)
00333     {
00334         DirContext.DirEntry.Fat.Filename[i] = aName[i];
00335     }
00336     if (aName[i] == '.')
00337     {
00338         i++;
00339         for (j = 0; j < 3 && aName[i]; j++, i++)
00340         {
00341             DirContext.DirEntry.Fat.Ext[j] = aName[i];
00342         }
00343     }
00344     if (DirContext.DirEntry.Fat.Filename[0] == 0xe5)
00345     {
00346         DirContext.DirEntry.Fat.Filename[0] = 0x05;
00347     }
00348 
00349     if (needLong)
00350     {
00351         RtlCopyMemory(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);
00352         DirContext.LongNameU.Buffer = LongNameBuffer;
00353         DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
00354         DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
00355         memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1, 0xff,
00356                DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR));
00357     }
00358     else
00359     {
00360         nbSlots = 1;
00361         if (lCaseBase)
00362         {
00363             DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_BASE;
00364         }
00365         if (lCaseExt)
00366         {
00367             DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_EXT;
00368         }
00369     }
00370 
00371     DPRINT ("dos name=%11.11s\n", DirContext.DirEntry.Fat.Filename);
00372 
00373     /* set attributes */
00374     DirContext.DirEntry.Fat.Attrib = ReqAttr;
00375     if (RequestedOptions & FILE_DIRECTORY_FILE)
00376     {
00377         DirContext.DirEntry.Fat.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
00378     }
00379     /* set dates and times */
00380     KeQuerySystemTime(&SystemTime);
00381     FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.Fat.CreationDate,
00382                                &DirContext.DirEntry.Fat.CreationTime);
00383     DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;
00384     DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;
00385     DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;
00386 
00387     if (needLong)
00388     {
00389         /* calculate checksum for 8.3 name */
00390         for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++)
00391         {
00392             pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
00393                                      | ((pSlots[0].alias_checksum & 0xfe) >> 1))
00394                                      + DirContext.DirEntry.Fat.ShortName[i]);
00395         }
00396         /* construct slots and entry */
00397         for (i = nbSlots - 2; i >= 0; i--)
00398         {
00399             DPRINT("construct slot %d\n", i);
00400             pSlots[i].attr = 0xf;
00401             if (i)
00402             {
00403                 pSlots[i].id = (unsigned char)(nbSlots - i - 1);
00404             }
00405             else
00406             {
00407                 pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40);
00408             }
00409             pSlots[i].alias_checksum = pSlots[0].alias_checksum;
00410             RtlCopyMemory(pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
00411             RtlCopyMemory(pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
00412             RtlCopyMemory(pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
00413         }
00414     }
00415     /* try to find nbSlots contiguous entries frees in directory */
00416     if (!vfatFindDirSpace(DeviceExt, ParentFcb, nbSlots, &DirContext.StartIndex))
00417     {
00418         ExFreePoolWithTag(Buffer, TAG_VFAT);
00419         return STATUS_DISK_FULL;
00420     }
00421     DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
00422     if (RequestedOptions & FILE_DIRECTORY_FILE)
00423     {
00424         CurrentCluster = 0;
00425         Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);
00426         if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
00427         {
00428             ExFreePoolWithTag(Buffer, TAG_VFAT);
00429             if (!NT_SUCCESS(Status))
00430             {
00431                 return Status;
00432             }
00433             return STATUS_DISK_FULL;
00434         }
00435         if (DeviceExt->FatInfo.FatType == FAT32)
00436         {
00437             DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
00438         }
00439         DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
00440     }
00441 
00442     i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);
00443     FileOffset.u.HighPart = 0;
00444     FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);
00445     if (DirContext.StartIndex / i == DirContext.DirIndex / i)
00446     {
00447         /* one cluster */
00448         if (!CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY),
00449                   TRUE, &Context, (PVOID*)&pFatEntry))
00450         {
00451             ExFreePoolWithTag(Buffer, TAG_VFAT);
00452             return STATUS_UNSUCCESSFUL;
00453         }
00454         if (nbSlots > 1)
00455         {
00456             RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
00457         }
00458         RtlCopyMemory(pFatEntry + (nbSlots - 1), &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
00459     }
00460     else
00461     {
00462         /* two clusters */
00463         size = DeviceExt->FatInfo.BytesPerCluster -
00464                (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;
00465         i = size / sizeof(FAT_DIR_ENTRY);
00466         if (!CcPinRead(ParentFcb->FileObject, &FileOffset, size, TRUE,
00467                   &Context, (PVOID*)&pFatEntry))
00468         {
00469             ExFreePoolWithTag(Buffer, TAG_VFAT);
00470             return STATUS_UNSUCCESSFUL;
00471         }
00472         RtlCopyMemory(pFatEntry, Buffer, size);
00473         CcSetDirtyPinnedData(Context, NULL);
00474         CcUnpinData(Context);
00475         FileOffset.u.LowPart += size;
00476         if (!CcPinRead(ParentFcb->FileObject, &FileOffset,
00477                   nbSlots * sizeof(FAT_DIR_ENTRY) - size,
00478                   TRUE, &Context, (PVOID*)&pFatEntry))
00479         {
00480             ExFreePoolWithTag(Buffer, TAG_VFAT);
00481             return STATUS_UNSUCCESSFUL;
00482         }
00483         if (nbSlots - 1 > i)
00484         {
00485             RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));
00486         }
00487         RtlCopyMemory(pFatEntry + nbSlots - 1 - i, &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
00488     }
00489     CcSetDirtyPinnedData(Context, NULL);
00490     CcUnpinData(Context);
00491 
00492     Status = vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
00493     if (!NT_SUCCESS(Status))
00494     {
00495         ExFreePoolWithTag(Buffer, TAG_VFAT);
00496         return Status;
00497     }
00498 
00499     DPRINT("new : entry=%11.11s\n", (*Fcb)->entry.Fat.Filename);
00500     DPRINT("new : entry=%11.11s\n", DirContext.DirEntry.Fat.Filename);
00501 
00502     if (RequestedOptions & FILE_DIRECTORY_FILE)
00503     {
00504         FileOffset.QuadPart = 0;
00505         if (!CcPinRead((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
00506                   &Context, (PVOID*)&pFatEntry))
00507         {
00508             ExFreePoolWithTag(Buffer, TAG_VFAT);
00509             return STATUS_UNSUCCESSFUL;
00510         }
00511         /* clear the new directory cluster */
00512         RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
00513         /* create '.' and '..' */
00514         RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
00515         RtlCopyMemory(pFatEntry[0].ShortName, ".          ", 11);
00516         RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
00517         RtlCopyMemory(pFatEntry[1].ShortName, "..         ", 11);
00518         pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;
00519         pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;
00520         if (vfatFCBIsRoot(ParentFcb))
00521         {
00522             pFatEntry[1].FirstCluster = 0;
00523             pFatEntry[1].FirstClusterHigh = 0;
00524         }
00525         CcSetDirtyPinnedData(Context, NULL);
00526         CcUnpinData(Context);
00527     }
00528     ExFreePoolWithTag(Buffer, TAG_VFAT);
00529     DPRINT("addentry ok\n");
00530     return STATUS_SUCCESS;
00531 }
00532 
00533 /*
00534   create a new FAT entry
00535 */
00536 static NTSTATUS
00537 FATXAddEntry(
00538     IN PDEVICE_EXTENSION DeviceExt,
00539     IN PUNICODE_STRING NameU,
00540     IN PVFATFCB* Fcb,
00541     IN PVFATFCB ParentFcb,
00542     IN ULONG RequestedOptions,
00543     IN UCHAR ReqAttr)
00544 {
00545     PVOID Context = NULL;
00546     LARGE_INTEGER SystemTime, FileOffset;
00547     OEM_STRING NameA;
00548     VFAT_DIRENTRY_CONTEXT DirContext;
00549     PFATX_DIR_ENTRY pFatXDirEntry;
00550     ULONG Index;
00551 
00552     DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);
00553 
00554     DirContext.LongNameU = *NameU;
00555 
00556     if (DirContext.LongNameU.Length / sizeof(WCHAR) > 42)
00557     {
00558         /* name too long */
00559         return STATUS_NAME_TOO_LONG;
00560     }
00561 
00562     /* try to find 1 entry free in directory */
00563     if (!vfatFindDirSpace(DeviceExt, ParentFcb, 1, &DirContext.StartIndex))
00564     {
00565         return STATUS_DISK_FULL;
00566     }
00567     Index = DirContext.DirIndex = DirContext.StartIndex;
00568     if (!vfatFCBIsRoot(ParentFcb))
00569     {
00570         DirContext.DirIndex += 2;
00571         DirContext.StartIndex += 2;
00572     }
00573 
00574     DirContext.ShortNameU.Buffer = 0;
00575     DirContext.ShortNameU.Length = 0;
00576     DirContext.ShortNameU.MaximumLength = 0;
00577     RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
00578     memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
00579     DirContext.DirEntry.FatX.FirstCluster = 0;
00580     DirContext.DirEntry.FatX.FileSize = 0;
00581 
00582     /* set file name */
00583     NameA.Buffer = (PCHAR)DirContext.DirEntry.FatX.Filename;
00584     NameA.Length = 0;
00585     NameA.MaximumLength = 42;
00586     RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE);
00587     DirContext.DirEntry.FatX.FilenameLength = (unsigned char)NameA.Length;
00588 
00589     /* set attributes */
00590     DirContext.DirEntry.FatX.Attrib = ReqAttr;
00591     if (RequestedOptions & FILE_DIRECTORY_FILE)
00592     {
00593         DirContext.DirEntry.FatX.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
00594     }
00595 
00596     /* set dates and times */
00597     KeQuerySystemTime(&SystemTime);
00598     FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.FatX.CreationDate,
00599                                &DirContext.DirEntry.FatX.CreationTime);
00600     DirContext.DirEntry.FatX.UpdateDate = DirContext.DirEntry.FatX.CreationDate;
00601     DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
00602     DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
00603     DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;
00604 
00605     /* add entry into parent directory */
00606     FileOffset.u.HighPart = 0;
00607     FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY);
00608     if (!CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY),
00609               TRUE, &Context, (PVOID*)&pFatXDirEntry))
00610     {
00611         return STATUS_UNSUCCESSFUL;
00612     }
00613     RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
00614     CcSetDirtyPinnedData(Context, NULL);
00615     CcUnpinData(Context);
00616 
00617     /* FIXME: check status */
00618     vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
00619 
00620     DPRINT("addentry ok\n");
00621     return STATUS_SUCCESS;
00622 }
00623 
00624 NTSTATUS
00625 VfatAddEntry(
00626     IN PDEVICE_EXTENSION DeviceExt,
00627     IN PUNICODE_STRING NameU,
00628     IN PVFATFCB *Fcb,
00629     IN PVFATFCB ParentFcb,
00630     IN ULONG RequestedOptions,
00631     IN UCHAR ReqAttr)
00632 {
00633     if (DeviceExt->Flags & VCB_IS_FATX)
00634         return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
00635     else
00636         return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
00637 }
00638 
00639 /*
00640  * deleting an existing FAT entry
00641  */
00642 static NTSTATUS
00643 FATDelEntry(
00644     IN PDEVICE_EXTENSION DeviceExt,
00645     IN PVFATFCB pFcb)
00646 {
00647     ULONG CurrentCluster = 0, NextCluster, i;
00648     PVOID Context = NULL;
00649     LARGE_INTEGER Offset;
00650     PFAT_DIR_ENTRY pDirEntry = NULL;
00651 
00652     ASSERT(pFcb);
00653     ASSERT(pFcb->parentFcb);
00654 
00655     DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
00656     DPRINT("delete entry: %d to %d\n", pFcb->startIndex, pFcb->dirIndex);
00657     Offset.u.HighPart = 0;
00658     for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
00659     {
00660         if (Context == NULL || ((i * sizeof(FAT_DIR_ENTRY)) % PAGE_SIZE) == 0)
00661         {
00662             if (Context)
00663             {
00664                 CcSetDirtyPinnedData(Context, NULL);
00665                 CcUnpinData(Context);
00666             }
00667             Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
00668             if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FAT_DIR_ENTRY), TRUE,
00669                       &Context, (PVOID*)&pDirEntry))
00670             {
00671                 return STATUS_UNSUCCESSFUL;
00672             }
00673         }
00674         pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5;
00675         if (i == pFcb->dirIndex)
00676         {
00677             CurrentCluster =
00678             vfatDirEntryGetFirstCluster(DeviceExt,
00679                                         (PDIR_ENTRY)&pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))]);
00680         }
00681     }
00682     if (Context)
00683     {
00684         CcSetDirtyPinnedData(Context, NULL);
00685         CcUnpinData(Context);
00686     }
00687 
00688     while (CurrentCluster && CurrentCluster != 0xffffffff)
00689     {
00690         GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
00691         /* FIXME: check status */
00692         WriteCluster(DeviceExt, CurrentCluster, 0);
00693         CurrentCluster = NextCluster;
00694     }
00695     return STATUS_SUCCESS;
00696 }
00697 
00698 /*
00699  * deleting an existing FAT entry
00700  */
00701 static NTSTATUS
00702 FATXDelEntry(
00703     IN PDEVICE_EXTENSION DeviceExt,
00704     IN PVFATFCB pFcb)
00705 {
00706     ULONG CurrentCluster = 0, NextCluster;
00707     PVOID Context = NULL;
00708     LARGE_INTEGER Offset;
00709     PFATX_DIR_ENTRY pDirEntry;
00710     ULONG StartIndex;
00711 
00712     ASSERT(pFcb);
00713     ASSERT(pFcb->parentFcb);
00714     ASSERT(pFcb->Flags & FCB_IS_FATX_ENTRY);
00715 
00716     StartIndex = pFcb->startIndex;
00717 
00718     DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
00719     DPRINT("delete entry: %d\n", StartIndex);
00720     Offset.u.HighPart = 0;
00721     Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
00722     if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FATX_DIR_ENTRY), TRUE,
00723                    &Context, (PVOID*)&pDirEntry))
00724     {
00725         DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
00726         return STATUS_UNSUCCESSFUL;
00727     }
00728     pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
00729     pDirEntry->FilenameLength = 0xe5;
00730     CurrentCluster = vfatDirEntryGetFirstCluster(DeviceExt,
00731                                                  (PDIR_ENTRY)pDirEntry);
00732     CcSetDirtyPinnedData(Context, NULL);
00733     CcUnpinData(Context);
00734 
00735     while (CurrentCluster && CurrentCluster != 0xffffffff)
00736     {
00737         GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
00738         /* FIXME: check status */
00739         WriteCluster(DeviceExt, CurrentCluster, 0);
00740         CurrentCluster = NextCluster;
00741     }
00742     return STATUS_SUCCESS;
00743 }
00744 
00745 NTSTATUS
00746 VfatDelEntry(
00747     IN PDEVICE_EXTENSION DeviceExt,
00748     IN PVFATFCB pFcb)
00749 {
00750     if (DeviceExt->Flags & VCB_IS_FATX)
00751         return FATXDelEntry(DeviceExt, pFcb);
00752     else
00753         return FATDelEntry(DeviceExt, pFcb);
00754 }
00755 
00756 /* EOF */

Generated on Fri May 25 2012 04:25:59 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.