ReactOS  0.4.14-dev-50-g13bb5e2
dirwr.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS kernel
4  * FILE: drivers/filesystems/fastfat/dirwr.c
5  * PURPOSE: VFAT Filesystem : write in directory
6  * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com)
7  * Herve Poussineau (reactos@poussine.freesurf.fr)
8  * Pierre Schweitzer (pierre@reactos.org)
9  *
10  */
11 
12 /* INCLUDES *****************************************************************/
13 
14 #include "vfat.h"
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 #ifdef KDBG
20 extern UNICODE_STRING DebugFile;
21 #endif
22 
25  PVCB vcb,
26  PVFATFCB fcb)
27 {
28  PFILE_OBJECT fileObject;
29  PVFATCCB newCCB;
31  BOOLEAN Acquired;
32 
33  /* Don't re-initialize if already done */
35  {
36  return STATUS_SUCCESS;
37  }
38 
40  ASSERT(fcb->FileObject == NULL);
41 
42  Acquired = FALSE;
43  if (!ExIsResourceAcquiredExclusive(&vcb->DirResource))
44  {
45  ExAcquireResourceExclusiveLite(&vcb->DirResource, TRUE);
46  Acquired = TRUE;
47  }
48 
49  fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
50  if (fileObject == NULL)
51  {
53  goto Quit;
54  }
55 
56 #ifdef KDBG
57  if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL))
58  {
59  DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount);
60  }
61 #endif
62 
63  newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
64  if (newCCB == NULL)
65  {
67  ObDereferenceObject(fileObject);
68  goto Quit;
69  }
70  RtlZeroMemory(newCCB, sizeof (VFATCCB));
71 
72  fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
73  fileObject->FsContext = fcb;
74  fileObject->FsContext2 = newCCB;
75  fileObject->Vpb = vcb->IoVPB;
76  fcb->FileObject = fileObject;
77 
78  _SEH2_TRY
79  {
80  CcInitializeCacheMap(fileObject,
81  (PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize),
82  TRUE,
84  fcb);
85  }
87  {
89  fcb->FileObject = NULL;
90  ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, newCCB);
91  ObDereferenceObject(fileObject);
92  if (Acquired)
93  {
94  ExReleaseResourceLite(&vcb->DirResource);
95  }
96  return status;
97  }
98  _SEH2_END;
99 
100  vfatGrabFCB(vcb, fcb);
103 
104 Quit:
105  if (Acquired)
106  {
107  ExReleaseResourceLite(&vcb->DirResource);
108  }
109 
110  return status;
111 }
112 
113 /*
114  * update an existing FAT entry
115  */
116 NTSTATUS
118  IN PDEVICE_EXTENSION DeviceExt,
119  IN PVFATFCB pFcb)
120 {
121  PVOID Context;
122  PDIR_ENTRY PinEntry;
124  ULONG SizeDirEntry;
125  ULONG dirIndex;
127 
128  ASSERT(pFcb);
129 
130  if (vfatVolumeIsFatX(DeviceExt))
131  {
132  SizeDirEntry = sizeof(FATX_DIR_ENTRY);
133  dirIndex = pFcb->startIndex;
134  }
135  else
136  {
137  SizeDirEntry = sizeof(FAT_DIR_ENTRY);
138  dirIndex = pFcb->dirIndex;
139  }
140 
141  DPRINT("updEntry dirIndex %u, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU);
142 
143  if (vfatFCBIsRoot(pFcb) || BooleanFlagOn(pFcb->Flags, FCB_IS_FAT | FCB_IS_VOLUME))
144  {
145  return STATUS_SUCCESS;
146  }
147 
148  ASSERT(pFcb->parentFcb);
149 
150  Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
151  if (!NT_SUCCESS(Status))
152  {
153  return Status;
154  }
155 
156  Offset.u.HighPart = 0;
157  Offset.u.LowPart = dirIndex * SizeDirEntry;
158  _SEH2_TRY
159  {
160  CcPinRead(pFcb->parentFcb->FileObject, &Offset, SizeDirEntry, PIN_WAIT, &Context, (PVOID*)&PinEntry);
161  }
163  {
164  DPRINT1("Failed write to \'%wZ\'.\n", &pFcb->parentFcb->PathNameU);
166  }
167  _SEH2_END;
168 
169  pFcb->Flags &= ~FCB_IS_DIRTY;
170  RtlCopyMemory(PinEntry, &pFcb->entry, SizeDirEntry);
173  return STATUS_SUCCESS;
174 }
175 
176 /*
177  * rename an existing FAT entry
178  */
179 NTSTATUS
181  IN PDEVICE_EXTENSION DeviceExt,
182  IN PVFATFCB pFcb,
184  IN BOOLEAN CaseChangeOnly)
185 {
186  OEM_STRING NameA;
187  ULONG StartIndex;
188  PVOID Context = NULL;
190  PFATX_DIR_ENTRY pDirEntry;
192 
193  DPRINT("vfatRenameEntry(%p, %p, %wZ, %d)\n", DeviceExt, pFcb, FileName, CaseChangeOnly);
194 
195  Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
196  if (!NT_SUCCESS(Status))
197  {
198  return Status;
199  }
200 
201  if (vfatVolumeIsFatX(DeviceExt))
202  {
204 
205  /* Open associated dir entry */
206  StartIndex = pFcb->startIndex;
207  Offset.u.HighPart = 0;
208  Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
209  _SEH2_TRY
210  {
211  CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
212  }
214  {
215  DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
217  }
218  _SEH2_END;
219 
220  pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
221 
222  /* Set file name */
223  NameA.Buffer = (PCHAR)pDirEntry->Filename;
224  NameA.Length = 0;
225  NameA.MaximumLength = 42;
227  pDirEntry->FilenameLength = (unsigned char)NameA.Length;
228 
229  /* Update FCB */
230  DirContext.DeviceExt = DeviceExt;
231  DirContext.ShortNameU.Length = 0;
232  DirContext.ShortNameU.MaximumLength = 0;
233  DirContext.ShortNameU.Buffer = NULL;
234  DirContext.LongNameU = *FileName;
235  DirContext.DirEntry.FatX = *pDirEntry;
236 
239 
240  Status = vfatUpdateFCB(DeviceExt, pFcb, &DirContext, pFcb->parentFcb);
241  if (NT_SUCCESS(Status))
242  {
243  CcFlushCache(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, NULL);
244  }
245 
246  return Status;
247  }
248  else
249  {
250  /* This we cannot handle properly, move file - would likely need love */
251  return VfatMoveEntry(DeviceExt, pFcb, FileName, pFcb->parentFcb);
252  }
253 }
254 
255 /*
256  * try to find contiguous entries frees in directory,
257  * extend a directory if is necessary
258  */
259 BOOLEAN
261  IN PDEVICE_EXTENSION DeviceExt,
262  IN PVFATFCB pDirFcb,
263  IN ULONG nbSlots,
264  OUT PULONG start)
265 {
267  ULONG i, count, size, nbFree = 0;
268  PDIR_ENTRY pFatEntry = NULL;
269  PVOID Context = NULL;
271  ULONG SizeDirEntry;
272  BOOLEAN IsFatX = vfatVolumeIsFatX(DeviceExt);
273  FileOffset.QuadPart = 0;
274 
275  if (IsFatX)
276  SizeDirEntry = sizeof(FATX_DIR_ENTRY);
277  else
278  SizeDirEntry = sizeof(FAT_DIR_ENTRY);
279 
280  Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pDirFcb);
281  if (!NT_SUCCESS(Status))
282  {
283  return FALSE;
284  }
285 
286  count = pDirFcb->RFCB.FileSize.u.LowPart / SizeDirEntry;
287  size = DeviceExt->FatInfo.BytesPerCluster / SizeDirEntry;
288  for (i = 0; i < count; i++, pFatEntry = (PDIR_ENTRY)((ULONG_PTR)pFatEntry + SizeDirEntry))
289  {
290  if (Context == NULL || (i % size) == 0)
291  {
292  if (Context)
293  {
295  }
296  _SEH2_TRY
297  {
298  CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
299  }
301  {
302  _SEH2_YIELD(return FALSE);
303  }
304  _SEH2_END;
305 
306  FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
307  }
308  if (ENTRY_END(IsFatX, pFatEntry))
309  {
310  break;
311  }
312  if (ENTRY_DELETED(IsFatX, pFatEntry))
313  {
314  nbFree++;
315  }
316  else
317  {
318  nbFree = 0;
319  }
320  if (nbFree == nbSlots)
321  {
322  break;
323  }
324  }
325  if (Context)
326  {
328  Context = NULL;
329  }
330  if (nbFree == nbSlots)
331  {
332  /* found enough contiguous free slots */
333  *start = i - nbSlots + 1;
334  }
335  else
336  {
337  *start = i - nbFree;
338  if (*start + nbSlots > count)
339  {
341  /* extend the directory */
342  if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32)
343  {
344  /* We can't extend a root directory on a FAT12/FAT16/FATX partition */
345  return FALSE;
346  }
347  AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster;
348  Status = VfatSetAllocationSizeInformation(pDirFcb->FileObject, pDirFcb,
349  DeviceExt, &AllocationSize);
350  if (!NT_SUCCESS(Status))
351  {
352  return FALSE;
353  }
354  /* clear the new dir cluster */
355  FileOffset.u.LowPart = (ULONG)(pDirFcb->RFCB.FileSize.QuadPart -
356  DeviceExt->FatInfo.BytesPerCluster);
357  _SEH2_TRY
358  {
359  CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
360  }
362  {
363  _SEH2_YIELD(return FALSE);
364  }
365  _SEH2_END;
366 
367  if (IsFatX)
368  memset(pFatEntry, 0xff, DeviceExt->FatInfo.BytesPerCluster);
369  else
370  RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
371  }
372  else if (*start + nbSlots < count)
373  {
374  /* clear the entry after the last new entry */
375  FileOffset.u.LowPart = (*start + nbSlots) * SizeDirEntry;
376  _SEH2_TRY
377  {
378  CcPinRead(pDirFcb->FileObject, &FileOffset, SizeDirEntry, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
379  }
381  {
382  _SEH2_YIELD(return FALSE);
383  }
384  _SEH2_END;
385 
386  if (IsFatX)
387  memset(pFatEntry, 0xff, SizeDirEntry);
388  else
389  RtlZeroMemory(pFatEntry, SizeDirEntry);
390  }
391  if (Context)
392  {
395  }
396  }
397  DPRINT("nbSlots %u nbFree %u, entry number %u\n", nbSlots, nbFree, *start);
398  return TRUE;
399 }
400 
401 /*
402  create a new FAT entry
403 */
404 static NTSTATUS
406  IN PDEVICE_EXTENSION DeviceExt,
407  IN PUNICODE_STRING NameU,
408  IN PVFATFCB* Fcb,
410  IN ULONG RequestedOptions,
411  IN UCHAR ReqAttr,
412  IN PVFAT_MOVE_CONTEXT MoveContext)
413 {
414  PVOID Context = NULL;
415  PFAT_DIR_ENTRY pFatEntry;
416  slot *pSlots;
417  USHORT nbSlots = 0, j;
418  PUCHAR Buffer;
419  BOOLEAN needTilde = FALSE, needLong = FALSE;
420  BOOLEAN BaseAllLower, BaseAllUpper;
421  BOOLEAN ExtensionAllLower, ExtensionAllUpper;
422  BOOLEAN InExtension;
424  WCHAR c;
425  ULONG CurrentCluster;
426  LARGE_INTEGER SystemTime, FileOffset;
428  ULONG size;
429  long i;
430 
431  OEM_STRING NameA;
432  CHAR aName[13];
433  BOOLEAN IsNameLegal;
434  BOOLEAN SpacesFound;
435 
437  WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];
438  WCHAR ShortNameBuffer[13];
439 
440  DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);
441 
442  DirContext.LongNameU = *NameU;
443  IsDirectory = BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE);
444 
445  /* nb of entry needed for long name+normal entry */
446  nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1;
447  DPRINT("NameLen= %u, nbSlots =%u\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
449  if (Buffer == NULL)
450  {
452  }
453  RtlZeroMemory(Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
454  pSlots = (slot *) Buffer;
455 
456  NameA.Buffer = aName;
457  NameA.Length = 0;
458  NameA.MaximumLength = sizeof(aName);
459 
460  DirContext.DeviceExt = DeviceExt;
461  DirContext.ShortNameU.Buffer = ShortNameBuffer;
462  DirContext.ShortNameU.Length = 0;
463  DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
464 
465  RtlZeroMemory(&DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
466 
467  IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound);
468 
469  if (!IsNameLegal || SpacesFound)
470  {
471  GENERATE_NAME_CONTEXT NameContext;
472  VFAT_DIRENTRY_CONTEXT SearchContext;
473  WCHAR ShortSearchName[13];
474  needTilde = TRUE;
475  needLong = TRUE;
476  RtlZeroMemory(&NameContext, sizeof(GENERATE_NAME_CONTEXT));
477  SearchContext.DeviceExt = DeviceExt;
478  SearchContext.LongNameU.Buffer = LongNameBuffer;
479  SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
480  SearchContext.ShortNameU.Buffer = ShortSearchName;
481  SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);
482 
483  for (i = 0; i < 100; i++)
484  {
485  RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU);
486  DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
487  SearchContext.DirIndex = 0;
488  Status = FindFile(DeviceExt, ParentFcb, &DirContext.ShortNameU, &SearchContext, TRUE);
489  if (!NT_SUCCESS(Status))
490  {
491  break;
492  }
493  else if (MoveContext)
494  {
495  ASSERT(*Fcb);
496  if (strncmp((char *)SearchContext.DirEntry.Fat.ShortName, (char *)(*Fcb)->entry.Fat.ShortName, 11) == 0)
497  {
498  if (MoveContext->InPlace)
499  {
500  ASSERT(SearchContext.DirEntry.Fat.FileSize == MoveContext->FileSize);
501  break;
502  }
503  }
504  }
505  }
506  if (i == 100) /* FIXME : what to do after this ? */
507  {
509  return STATUS_UNSUCCESSFUL;
510  }
511  IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);
512  }
513  else
514  {
515  BaseAllLower = BaseAllUpper = TRUE;
516  ExtensionAllLower = ExtensionAllUpper = TRUE;
517  InExtension = FALSE;
518  for (i = 0; i < DirContext.LongNameU.Length / sizeof(WCHAR); i++)
519  {
520  c = DirContext.LongNameU.Buffer[i];
521  if (c >= L'A' && c <= L'Z')
522  {
523  if (InExtension)
524  ExtensionAllLower = FALSE;
525  else
526  BaseAllLower = FALSE;
527  }
528  else if (c >= L'a' && c <= L'z')
529  {
530  if (InExtension)
531  ExtensionAllUpper = FALSE;
532  else
533  BaseAllUpper = FALSE;
534  }
535  else if (c > 0x7f)
536  {
537  needLong = TRUE;
538  break;
539  }
540 
541  if (c == L'.')
542  {
543  InExtension = TRUE;
544  }
545  }
546 
547  if ((!BaseAllLower && !BaseAllUpper) ||
548  (!ExtensionAllLower && !ExtensionAllUpper))
549  {
550  needLong = TRUE;
551  }
552 
553  RtlUpcaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
554  DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
555  }
556  aName[NameA.Length] = 0;
557  DPRINT("'%s', '%wZ', needTilde=%u, needLong=%u\n",
558  aName, &DirContext.LongNameU, needTilde, needLong);
559  memset(DirContext.DirEntry.Fat.ShortName, ' ', 11);
560  for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)
561  {
562  DirContext.DirEntry.Fat.Filename[i] = aName[i];
563  }
564  if (aName[i] == '.')
565  {
566  i++;
567  for (j = 0; j < 3 && aName[i]; j++, i++)
568  {
569  DirContext.DirEntry.Fat.Ext[j] = aName[i];
570  }
571  }
572  if (DirContext.DirEntry.Fat.Filename[0] == 0xe5)
573  {
574  DirContext.DirEntry.Fat.Filename[0] = 0x05;
575  }
576 
577  if (needLong)
578  {
579  RtlCopyMemory(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);
580  DirContext.LongNameU.Buffer = LongNameBuffer;
581  DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
582  DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
583  memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1, 0xff,
584  DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR));
585  }
586  else
587  {
588  nbSlots = 1;
589  if (BaseAllLower && !BaseAllUpper)
590  {
591  DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_BASE;
592  }
593  if (ExtensionAllLower && !ExtensionAllUpper)
594  {
595  DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_EXT;
596  }
597  }
598 
599  DPRINT ("dos name=%11.11s\n", DirContext.DirEntry.Fat.Filename);
600 
601  /* set attributes */
602  DirContext.DirEntry.Fat.Attrib = ReqAttr;
603  if (IsDirectory)
604  {
605  DirContext.DirEntry.Fat.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
606  }
607  /* set dates and times */
608  KeQuerySystemTime(&SystemTime);
609  FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.Fat.CreationDate,
610  &DirContext.DirEntry.Fat.CreationTime);
611  DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;
612  DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;
613  DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;
614  /* If it's moving, preserve creation time and file size */
615  if (MoveContext != NULL)
616  {
617  DirContext.DirEntry.Fat.CreationDate = MoveContext->CreationDate;
618  DirContext.DirEntry.Fat.CreationTime = MoveContext->CreationTime;
619  DirContext.DirEntry.Fat.FileSize = MoveContext->FileSize;
620  }
621 
622  if (needLong)
623  {
624  /* calculate checksum for 8.3 name */
625  for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++)
626  {
627  pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
628  | ((pSlots[0].alias_checksum & 0xfe) >> 1))
629  + DirContext.DirEntry.Fat.ShortName[i]);
630  }
631  /* construct slots and entry */
632  for (i = nbSlots - 2; i >= 0; i--)
633  {
634  DPRINT("construct slot %d\n", i);
635  pSlots[i].attr = 0xf;
636  if (i)
637  {
638  pSlots[i].id = (unsigned char)(nbSlots - i - 1);
639  }
640  else
641  {
642  pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40);
643  }
644  pSlots[i].alias_checksum = pSlots[0].alias_checksum;
645  RtlCopyMemory(pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
646  RtlCopyMemory(pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
647  RtlCopyMemory(pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
648  }
649  }
650  /* try to find nbSlots contiguous entries frees in directory */
651  if (!vfatFindDirSpace(DeviceExt, ParentFcb, nbSlots, &DirContext.StartIndex))
652  {
654  return STATUS_DISK_FULL;
655  }
656  DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
657  if (IsDirectory)
658  {
659  /* If we aren't moving, use next */
660  if (MoveContext == NULL)
661  {
662  CurrentCluster = 0;
663  Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);
664  if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
665  {
667  if (!NT_SUCCESS(Status))
668  {
669  return Status;
670  }
671  return STATUS_DISK_FULL;
672  }
673 
674  if (DeviceExt->FatInfo.FatType == FAT32)
675  {
676  FAT32UpdateFreeClustersCount(DeviceExt);
677  }
678  }
679  else
680  {
681  CurrentCluster = MoveContext->FirstCluster;
682  }
683 
684  if (DeviceExt->FatInfo.FatType == FAT32)
685  {
686  DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
687  }
688  DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
689  }
690  else if (MoveContext != NULL)
691  {
692  CurrentCluster = MoveContext->FirstCluster;
693 
694  if (DeviceExt->FatInfo.FatType == FAT32)
695  {
696  DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
697  }
698  DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
699  }
700 
701  /* No need to init cache here, vfatFindDirSpace() will have done it for us */
703 
704  i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);
705  FileOffset.u.HighPart = 0;
706  FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);
707  if (DirContext.StartIndex / i == DirContext.DirIndex / i)
708  {
709  /* one cluster */
710  _SEH2_TRY
711  {
712  CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY), PIN_WAIT, &Context, (PVOID*)&pFatEntry);
713  }
715  {
718  }
719  _SEH2_END;
720 
721  if (nbSlots > 1)
722  {
723  RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
724  }
725  RtlCopyMemory(pFatEntry + (nbSlots - 1), &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
726  }
727  else
728  {
729  /* two clusters */
730  size = DeviceExt->FatInfo.BytesPerCluster -
731  (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;
732  i = size / sizeof(FAT_DIR_ENTRY);
733  _SEH2_TRY
734  {
736  }
738  {
741  }
742  _SEH2_END;
743  RtlCopyMemory(pFatEntry, Buffer, size);
746  FileOffset.u.LowPart += size;
747  _SEH2_TRY
748  {
749  CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY) - size, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
750  }
752  {
755  }
756  _SEH2_END;
757  if (nbSlots - 1 > i)
758  {
759  RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));
760  }
761  RtlCopyMemory(pFatEntry + nbSlots - 1 - i, &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
762  }
765 
766  if (MoveContext != NULL)
767  {
768  /* We're modifying an existing FCB - likely rename/move */
769  Status = vfatUpdateFCB(DeviceExt, *Fcb, &DirContext, ParentFcb);
770  }
771  else
772  {
774  }
775  if (!NT_SUCCESS(Status))
776  {
778  return Status;
779  }
780 
781  DPRINT("new : entry=%11.11s\n", (*Fcb)->entry.Fat.Filename);
782  DPRINT("new : entry=%11.11s\n", DirContext.DirEntry.Fat.Filename);
783 
784  if (IsDirectory)
785  {
787  if (!NT_SUCCESS(Status))
788  {
790  return Status;
791  }
792 
793  FileOffset.QuadPart = 0;
794  _SEH2_TRY
795  {
796  CcPinRead((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
797  }
799  {
802  }
803  _SEH2_END;
804  /* clear the new directory cluster if not moving */
805  if (MoveContext == NULL)
806  {
807  RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
808  /* create '.' and '..' */
809  pFatEntry[0] = DirContext.DirEntry.Fat;
810  RtlCopyMemory(pFatEntry[0].ShortName, ". ", 11);
811  pFatEntry[1] = DirContext.DirEntry.Fat;
812  RtlCopyMemory(pFatEntry[1].ShortName, ".. ", 11);
813  }
814 
815  pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;
816  pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;
818  {
819  pFatEntry[1].FirstCluster = 0;
820  pFatEntry[1].FirstClusterHigh = 0;
821  }
824  }
826  DPRINT("addentry ok\n");
827  return STATUS_SUCCESS;
828 }
829 
830 /*
831  create a new FAT entry
832 */
833 static NTSTATUS
835  IN PDEVICE_EXTENSION DeviceExt,
836  IN PUNICODE_STRING NameU,
837  IN PVFATFCB* Fcb,
839  IN ULONG RequestedOptions,
840  IN UCHAR ReqAttr,
841  IN PVFAT_MOVE_CONTEXT MoveContext)
842 {
843  PVOID Context = NULL;
844  LARGE_INTEGER SystemTime, FileOffset;
845  OEM_STRING NameA;
847  PFATX_DIR_ENTRY pFatXDirEntry;
848  ULONG Index;
849 
850  DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);
851 
852  DirContext.LongNameU = *NameU;
853 
854  if (DirContext.LongNameU.Length / sizeof(WCHAR) > 42)
855  {
856  /* name too long */
857  return STATUS_NAME_TOO_LONG;
858  }
859 
860  /* try to find 1 entry free in directory */
861  if (!vfatFindDirSpace(DeviceExt, ParentFcb, 1, &DirContext.StartIndex))
862  {
863  return STATUS_DISK_FULL;
864  }
865  Index = DirContext.DirIndex = DirContext.StartIndex;
866  if (!vfatFCBIsRoot(ParentFcb))
867  {
868  DirContext.DirIndex += 2;
869  DirContext.StartIndex += 2;
870  }
871 
872  DirContext.ShortNameU.Buffer = 0;
873  DirContext.ShortNameU.Length = 0;
874  DirContext.ShortNameU.MaximumLength = 0;
875  DirContext.DeviceExt = DeviceExt;
876  RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
877  memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
878  /* Use cluster, if moving */
879  if (MoveContext != NULL)
880  {
881  DirContext.DirEntry.FatX.FirstCluster = MoveContext->FirstCluster;
882  }
883  else
884  {
885  DirContext.DirEntry.FatX.FirstCluster = 0;
886  }
887  DirContext.DirEntry.FatX.FileSize = 0;
888 
889  /* set file name */
890  NameA.Buffer = (PCHAR)DirContext.DirEntry.FatX.Filename;
891  NameA.Length = 0;
892  NameA.MaximumLength = 42;
893  RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE);
894  DirContext.DirEntry.FatX.FilenameLength = (unsigned char)NameA.Length;
895 
896  /* set attributes */
897  DirContext.DirEntry.FatX.Attrib = ReqAttr;
898  if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE))
899  {
900  DirContext.DirEntry.FatX.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
901  }
902 
903  /* set dates and times */
904  KeQuerySystemTime(&SystemTime);
905  FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.FatX.CreationDate,
906  &DirContext.DirEntry.FatX.CreationTime);
907  DirContext.DirEntry.FatX.UpdateDate = DirContext.DirEntry.FatX.CreationDate;
908  DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
909  DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
910  DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;
911  /* If it's moving, preserve creation time and file size */
912  if (MoveContext != NULL)
913  {
914  DirContext.DirEntry.FatX.CreationDate = MoveContext->CreationDate;
915  DirContext.DirEntry.FatX.CreationTime = MoveContext->CreationTime;
916  DirContext.DirEntry.FatX.FileSize = MoveContext->FileSize;
917  }
918 
919  /* No need to init cache here, vfatFindDirSpace() will have done it for us */
921 
922  /* add entry into parent directory */
923  FileOffset.u.HighPart = 0;
924  FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY);
925  _SEH2_TRY
926  {
927  CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), PIN_WAIT, &Context, (PVOID*)&pFatXDirEntry);
928  }
930  {
932  }
933  _SEH2_END;
934  RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
937 
938  if (MoveContext != NULL)
939  {
940  /* We're modifying an existing FCB - likely rename/move */
941  /* FIXME: check status */
942  vfatUpdateFCB(DeviceExt, *Fcb, &DirContext, ParentFcb);
943  }
944  else
945  {
946  /* FIXME: check status */
948  }
949 
950  DPRINT("addentry ok\n");
951  return STATUS_SUCCESS;
952 }
953 
954 /*
955  * deleting an existing FAT entry
956  */
957 static NTSTATUS
959  IN PDEVICE_EXTENSION DeviceExt,
960  IN PVFATFCB pFcb,
961  OUT PVFAT_MOVE_CONTEXT MoveContext)
962 {
963  ULONG CurrentCluster = 0, NextCluster, i;
964  PVOID Context = NULL;
966  PFAT_DIR_ENTRY pDirEntry = NULL;
968 
969  ASSERT(pFcb);
970  ASSERT(pFcb->parentFcb);
971 
972  Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
973  if (!NT_SUCCESS(Status))
974  {
975  return Status;
976  }
977 
978  DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
979  DPRINT("delete entry: %u to %u\n", pFcb->startIndex, pFcb->dirIndex);
980  Offset.u.HighPart = 0;
981  for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
982  {
983  if (Context == NULL || ((i * sizeof(FAT_DIR_ENTRY)) % PAGE_SIZE) == 0)
984  {
985  if (Context)
986  {
989  }
990  Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
991  _SEH2_TRY
992  {
993  CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
994  }
996  {
998  }
999  _SEH2_END;
1000  }
1001  pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5;
1002  if (i == pFcb->dirIndex)
1003  {
1004  CurrentCluster =
1005  vfatDirEntryGetFirstCluster(DeviceExt,
1006  (PDIR_ENTRY)&pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))]);
1007  }
1008  }
1009 
1010  /* In case of moving, save properties */
1011  if (MoveContext != NULL)
1012  {
1013  pDirEntry = &pDirEntry[pFcb->dirIndex % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))];
1014  MoveContext->FirstCluster = CurrentCluster;
1015  MoveContext->FileSize = pDirEntry->FileSize;
1016  MoveContext->CreationTime = pDirEntry->CreationTime;
1017  MoveContext->CreationDate = pDirEntry->CreationDate;
1018  }
1019 
1020  if (Context)
1021  {
1024  }
1025 
1026  /* In case of moving, don't delete data */
1027  if (MoveContext == NULL)
1028  {
1029  while (CurrentCluster && CurrentCluster != 0xffffffff)
1030  {
1031  GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
1032  /* FIXME: check status */
1033  WriteCluster(DeviceExt, CurrentCluster, 0);
1034  CurrentCluster = NextCluster;
1035  }
1036 
1037  if (DeviceExt->FatInfo.FatType == FAT32)
1038  {
1039  FAT32UpdateFreeClustersCount(DeviceExt);
1040  }
1041  }
1042 
1043  return STATUS_SUCCESS;
1044 }
1045 
1046 /*
1047  * deleting an existing FAT entry
1048  */
1049 static NTSTATUS
1051  IN PDEVICE_EXTENSION DeviceExt,
1052  IN PVFATFCB pFcb,
1053  OUT PVFAT_MOVE_CONTEXT MoveContext)
1054 {
1055  ULONG CurrentCluster = 0, NextCluster;
1056  PVOID Context = NULL;
1058  PFATX_DIR_ENTRY pDirEntry;
1059  ULONG StartIndex;
1060  NTSTATUS Status;
1061 
1062  ASSERT(pFcb);
1063  ASSERT(pFcb->parentFcb);
1064  ASSERT(vfatVolumeIsFatX(DeviceExt));
1065 
1066  StartIndex = pFcb->startIndex;
1067 
1068  Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
1069  if (!NT_SUCCESS(Status))
1070  {
1071  return Status;
1072  }
1073 
1074  DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
1075  DPRINT("delete entry: %u\n", StartIndex);
1076  Offset.u.HighPart = 0;
1077  Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
1078  _SEH2_TRY
1079  {
1080  CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
1081  }
1083  {
1084  DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
1086  }
1087  _SEH2_END;
1088  pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
1089  pDirEntry->FilenameLength = 0xe5;
1090  CurrentCluster = vfatDirEntryGetFirstCluster(DeviceExt,
1091  (PDIR_ENTRY)pDirEntry);
1092 
1093  /* In case of moving, save properties */
1094  if (MoveContext != NULL)
1095  {
1096  MoveContext->FirstCluster = CurrentCluster;
1097  MoveContext->FileSize = pDirEntry->FileSize;
1098  MoveContext->CreationTime = pDirEntry->CreationTime;
1099  MoveContext->CreationDate = pDirEntry->CreationDate;
1100  }
1101 
1104 
1105  /* In case of moving, don't delete data */
1106  if (MoveContext == NULL)
1107  {
1108  while (CurrentCluster && CurrentCluster != 0xffffffff)
1109  {
1110  GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
1111  /* FIXME: check status */
1112  WriteCluster(DeviceExt, CurrentCluster, 0);
1113  CurrentCluster = NextCluster;
1114  }
1115  }
1116 
1117  return STATUS_SUCCESS;
1118 }
1119 
1120 /*
1121  * move an existing FAT entry
1122  */
1123 NTSTATUS
1125  IN PDEVICE_EXTENSION DeviceExt,
1126  IN PVFATFCB pFcb,
1129 {
1130  NTSTATUS Status;
1131  PVFATFCB OldParent;
1132  VFAT_MOVE_CONTEXT MoveContext;
1133 
1134  DPRINT("VfatMoveEntry(%p, %p, %wZ, %p)\n", DeviceExt, pFcb, FileName, ParentFcb);
1135 
1136  /* Delete old entry while keeping data */
1137  Status = VfatDelEntry(DeviceExt, pFcb, &MoveContext);
1138  if (!NT_SUCCESS(Status))
1139  {
1140  return Status;
1141  }
1142 
1143  OldParent = pFcb->parentFcb;
1144  CcFlushCache(&OldParent->SectionObjectPointers, NULL, 0, NULL);
1145  MoveContext.InPlace = (OldParent == ParentFcb);
1146 
1147  /* Add our new entry with our cluster */
1148  Status = VfatAddEntry(DeviceExt,
1149  FileName,
1150  &pFcb,
1151  ParentFcb,
1153  *pFcb->Attributes,
1154  &MoveContext);
1155 
1156  CcFlushCache(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, NULL);
1157 
1158  return Status;
1159 }
1160 
1165 
1167  FATXIsDirectoryEmpty, // .IsDirectoryEmpty
1168  FATXAddEntry, // .AddEntry
1169  FATXDelEntry, // .DelEntry
1170  FATXGetNextDirEntry, // .GetNextDirEntry
1171 };
1172 
1174  FATIsDirectoryEmpty, // .IsDirectoryEmpty
1175  FATAddEntry, // .AddEntry
1176  FATDelEntry, // .DelEntry
1177  FATGetNextDirEntry, // .GetNextDirEntry
1178 };
1179 
1180 /* EOF */
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1294
NTSTATUS VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER AllocationSize)
Definition: finfo.c:1207
static NTSTATUS FATAddEntry(IN PDEVICE_EXTENSION DeviceExt, IN PUNICODE_STRING NameU, IN PVFATFCB *Fcb, IN PVFATFCB ParentFcb, IN ULONG RequestedOptions, IN UCHAR ReqAttr, IN PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:405
LONGLONG CreationTime
Definition: cdstruc.h:1036
#define IN
Definition: typedefs.h:38
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
NTSTATUS vfatUpdateFCB(PDEVICE_EXTENSION pVCB, PVFATFCB Fcb, PVFAT_DIRENTRY_CONTEXT DirContext, PVFATFCB ParentFcb)
Definition: fcb.c:538
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: vfat.h:445
unsigned short CreationTime
Definition: vfat.h:120
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:40
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
unsigned char FilenameLength
Definition: vfat.h:171
#define ENTRY_END(IsFatX, DirEntry)
Definition: vfat.h:207
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
NTSTATUS FATGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
unsigned char attr
Definition: vfat.h:188
#define FCB_IS_DIRTY
Definition: vfat.h:432
unsigned char alias_checksum
Definition: vfat.h:190
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
Definition: vfat.h:441
USHORT MaximumLength
Definition: env_spec_w32.h:370
PFILE_OBJECT FileObject
Definition: ntfs.h:516
Definition: vfat.h:530
unsigned long FileSize
Definition: vfat.h:129
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:19
BOOLEAN FATIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
Definition: direntry.c:43
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
GLuint GLuint GLsizei count
Definition: gl.h:1545
NTSTATUS FAT32UpdateFreeClustersCount(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:1213
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
static NTSTATUS FATXDelEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:1050
UNICODE_STRING LongNameU
Definition: vfat.h:596
LONG NTSTATUS
Definition: precomp.h:26
unsigned char Filename[8]
Definition: vfat.h:114
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
ULONG DirIndex
Definition: ntfs.h:529
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:631
Definition: cdstruc.h:504
#define PIN_WAIT
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:294
#define ENTRY_DELETED(IsFatX, DirEntry)
Definition: vfat.h:205
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
NTSTATUS FATXGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
STRING OEM_STRING
Definition: umtypes.h:203
NTSTATUS vfatMakeFCBFromDirEntry(PVCB vcb, PVFATFCB directoryFCB, PVFAT_DIRENTRY_CONTEXT DirContext, PVFATFCB *fileFCB)
Definition: fcb.c:725
FAT_DIR_ENTRY Fat
Definition: vfat.h:226
VFAT_DISPATCH FatXDispatch
Definition: dirwr.c:1166
BOOLEAN NTAPI FsRtlIsNameInExpression(IN PUNICODE_STRING Expression, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL)
Definition: name.c:514
_SEH2_TRY
Definition: create.c:4250
VFAT_DISPATCH FatDispatch
Definition: dirwr.c:1173
uint32_t ULONG_PTR
Definition: typedefs.h:63
unsigned char ShortName[11]
Definition: vfat.h:115
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
WCHAR First[]
Definition: FormatMessage.c:11
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:93
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:53
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
struct _LARGE_INTEGER::@2201 u
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
static NTSTATUS FATXAddEntry(IN PDEVICE_EXTENSION DeviceExt, IN PUNICODE_STRING NameU, IN PVFATFCB *Fcb, IN PVFATFCB ParentFcb, IN ULONG RequestedOptions, IN UCHAR ReqAttr, IN PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:834
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
unsigned char
Definition: typeof.h:29
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
NTSTATUS WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue)
Definition: fat.c:703
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:484
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3186
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:513
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
NPAGED_LOOKASIDE_LIST CcbLookasideList
Definition: vfat.h:412
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define PCHAR
Definition: match.c:90
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:645
unsigned short CreationDate
Definition: vfat.h:120
GLsizeiptr size
Definition: glext.h:5919
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:24
struct _fcb fcb
Definition: btrfs_drv.h:1301
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
struct _VFATFCB * parentFcb
Definition: vfat.h:484
if(!(yy_init))
Definition: macro.lex.yy.c:714
union _DIR_ENTRY * PDIR_ENTRY
Definition: vfat.h:230
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:193
UNICODE_STRING ShortNameU
Definition: vfat.h:597
FORCEINLINE NTSTATUS VfatAddEntry(PDEVICE_EXTENSION DeviceExt, PUNICODE_STRING NameU, struct _VFATFCB **Fcb, struct _VFATFCB *ParentFcb, ULONG RequestedOptions, UCHAR ReqAttr, struct _VFAT_MOVE_CONTEXT *MoveContext)
Definition: vfat.h:369
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:429
static NTSTATUS FATDelEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:958
const GLubyte * c
Definition: glext.h:8905
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static const UCHAR Index[8]
Definition: usbohci.c:18
DIR_ENTRY DirEntry
Definition: vfat.h:595
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
_In_ PFCB ParentFcb
Definition: cdprocs.h:741
BOOLEAN NTAPI CcPinRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
Definition: pinsup.c:802
#define VFAT_CASE_LOWER_BASE
Definition: vfat.h:200
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
ULONG Flags
Definition: ntfs.h:532
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define FCB_IS_FAT
Definition: vfat.h:429
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
_Must_inspect_result_ _In_ PFLT_INSTANCE _Out_ PBOOLEAN IsDirectory
Definition: fltkernel.h:1139
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
BOOLEAN InPlace
Definition: vfat.h:607
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define VFAT_CASE_LOWER_EXT
Definition: vfat.h:201
unsigned short FirstClusterHigh
Definition: vfat.h:123
Definition: vfat.h:184
Status
Definition: gdiplustypes.h:24
#define FCB_CACHE_INITIALIZED
Definition: vfat.h:427
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:310
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:40
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:416
#define FCB_IS_VOLUME
Definition: vfat.h:431
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:742
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_SEH2_END
Definition: create.c:4424
NTSTATUS vfatRenameEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN BOOLEAN CaseChangeOnly)
Definition: dirwr.c:180
unsigned char Filename[42]
Definition: vfat.h:173
unsigned short USHORT
Definition: pedump.c:61
FORCEINLINE NTSTATUS VfatDelEntry(PDEVICE_EXTENSION DeviceExt, struct _VFATFCB *Fcb, struct _VFAT_MOVE_CONTEXT *MoveContext)
Definition: vfat.h:382
GLuint start
Definition: gl.h:1545
unsigned char id
Definition: vfat.h:186
NTSTATUS VfatMoveEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN PVFATFCB ParentFcb)
Definition: dirwr.c:1124
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:151
NTSYSAPI VOID NTAPI RtlGenerate8dot3Name(_In_ PCUNICODE_STRING Name, _In_ BOOLEAN AllowExtendedCharacters, _Inout_ PGENERATE_NAME_CONTEXT Context, _Inout_ PUNICODE_STRING Name8dot3)
unsigned int * PULONG
Definition: retypes.h:1
Definition: vfat.h:224
#define FAT32
Definition: fat.h:169
unsigned short FirstCluster
Definition: vfat.h:128
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:39
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define LONGNAME_MAX_LENGTH
Definition: vfat.h:203
NTSTATUS VfatUpdateEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb)
Definition: dirwr.c:117
BOOLEAN FATXIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
Definition: direntry.c:119
#define c
Definition: ke_i.h:80
struct tagContext Context
Definition: acpixf.h:1024
unsigned int ULONG
Definition: retypes.h:1
VOID vfatGrabFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
Definition: fcb.c:302
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:598
_In_ PFCB Fcb
Definition: cdprocs.h:151
#define ExIsResourceAcquiredExclusive
Definition: exfuncs.h:347
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define memset(x, y, z)
Definition: compat.h:39
BOOLEAN vfatFindDirSpace(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pDirFcb, IN ULONG nbSlots, OUT PULONG start)
Definition: dirwr.c:260
static SERVICE_STATUS status
Definition: service.c:31
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1114
BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3(_In_ PUNICODE_STRING Name, _Inout_opt_ POEM_STRING OemName, _Inout_opt_ PBOOLEAN NameContainsSpaces)
#define TAG_DIRENT
Definition: vfat.h:549
Definition: find.c:28
Definition: ps.c:97