ReactOS  0.4.13-dev-241-g63286c6
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  RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib,
810  sizeof(FAT_DIR_ENTRY) - FIELD_OFFSET(FAT_DIR_ENTRY, Attrib));
811  RtlCopyMemory(pFatEntry[0].ShortName, ". ", 11);
812  RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib,
813  sizeof(FAT_DIR_ENTRY) - FIELD_OFFSET(FAT_DIR_ENTRY, Attrib));
814  RtlCopyMemory(pFatEntry[1].ShortName, ".. ", 11);
815  }
816 
817  pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;
818  pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;
820  {
821  pFatEntry[1].FirstCluster = 0;
822  pFatEntry[1].FirstClusterHigh = 0;
823  }
826  }
828  DPRINT("addentry ok\n");
829  return STATUS_SUCCESS;
830 }
831 
832 /*
833  create a new FAT entry
834 */
835 static NTSTATUS
837  IN PDEVICE_EXTENSION DeviceExt,
838  IN PUNICODE_STRING NameU,
839  IN PVFATFCB* Fcb,
841  IN ULONG RequestedOptions,
842  IN UCHAR ReqAttr,
843  IN PVFAT_MOVE_CONTEXT MoveContext)
844 {
845  PVOID Context = NULL;
846  LARGE_INTEGER SystemTime, FileOffset;
847  OEM_STRING NameA;
849  PFATX_DIR_ENTRY pFatXDirEntry;
850  ULONG Index;
851 
852  DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);
853 
854  DirContext.LongNameU = *NameU;
855 
856  if (DirContext.LongNameU.Length / sizeof(WCHAR) > 42)
857  {
858  /* name too long */
859  return STATUS_NAME_TOO_LONG;
860  }
861 
862  /* try to find 1 entry free in directory */
863  if (!vfatFindDirSpace(DeviceExt, ParentFcb, 1, &DirContext.StartIndex))
864  {
865  return STATUS_DISK_FULL;
866  }
867  Index = DirContext.DirIndex = DirContext.StartIndex;
868  if (!vfatFCBIsRoot(ParentFcb))
869  {
870  DirContext.DirIndex += 2;
871  DirContext.StartIndex += 2;
872  }
873 
874  DirContext.ShortNameU.Buffer = 0;
875  DirContext.ShortNameU.Length = 0;
876  DirContext.ShortNameU.MaximumLength = 0;
877  DirContext.DeviceExt = DeviceExt;
878  RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
879  memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
880  /* Use cluster, if moving */
881  if (MoveContext != NULL)
882  {
883  DirContext.DirEntry.FatX.FirstCluster = MoveContext->FirstCluster;
884  }
885  else
886  {
887  DirContext.DirEntry.FatX.FirstCluster = 0;
888  }
889  DirContext.DirEntry.FatX.FileSize = 0;
890 
891  /* set file name */
892  NameA.Buffer = (PCHAR)DirContext.DirEntry.FatX.Filename;
893  NameA.Length = 0;
894  NameA.MaximumLength = 42;
895  RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE);
896  DirContext.DirEntry.FatX.FilenameLength = (unsigned char)NameA.Length;
897 
898  /* set attributes */
899  DirContext.DirEntry.FatX.Attrib = ReqAttr;
900  if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE))
901  {
902  DirContext.DirEntry.FatX.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
903  }
904 
905  /* set dates and times */
906  KeQuerySystemTime(&SystemTime);
907  FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.FatX.CreationDate,
908  &DirContext.DirEntry.FatX.CreationTime);
909  DirContext.DirEntry.FatX.UpdateDate = DirContext.DirEntry.FatX.CreationDate;
910  DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
911  DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
912  DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;
913  /* If it's moving, preserve creation time and file size */
914  if (MoveContext != NULL)
915  {
916  DirContext.DirEntry.FatX.CreationDate = MoveContext->CreationDate;
917  DirContext.DirEntry.FatX.CreationTime = MoveContext->CreationTime;
918  DirContext.DirEntry.FatX.FileSize = MoveContext->FileSize;
919  }
920 
921  /* No need to init cache here, vfatFindDirSpace() will have done it for us */
923 
924  /* add entry into parent directory */
925  FileOffset.u.HighPart = 0;
926  FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY);
927  _SEH2_TRY
928  {
929  CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), PIN_WAIT, &Context, (PVOID*)&pFatXDirEntry);
930  }
932  {
934  }
935  _SEH2_END;
936  RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
939 
940  if (MoveContext != NULL)
941  {
942  /* We're modifying an existing FCB - likely rename/move */
943  /* FIXME: check status */
944  vfatUpdateFCB(DeviceExt, *Fcb, &DirContext, ParentFcb);
945  }
946  else
947  {
948  /* FIXME: check status */
950  }
951 
952  DPRINT("addentry ok\n");
953  return STATUS_SUCCESS;
954 }
955 
956 /*
957  * deleting an existing FAT entry
958  */
959 static NTSTATUS
961  IN PDEVICE_EXTENSION DeviceExt,
962  IN PVFATFCB pFcb,
963  OUT PVFAT_MOVE_CONTEXT MoveContext)
964 {
965  ULONG CurrentCluster = 0, NextCluster, i;
966  PVOID Context = NULL;
968  PFAT_DIR_ENTRY pDirEntry = NULL;
970 
971  ASSERT(pFcb);
972  ASSERT(pFcb->parentFcb);
973 
974  Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
975  if (!NT_SUCCESS(Status))
976  {
977  return Status;
978  }
979 
980  DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
981  DPRINT("delete entry: %u to %u\n", pFcb->startIndex, pFcb->dirIndex);
982  Offset.u.HighPart = 0;
983  for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
984  {
985  if (Context == NULL || ((i * sizeof(FAT_DIR_ENTRY)) % PAGE_SIZE) == 0)
986  {
987  if (Context)
988  {
991  }
992  Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
993  _SEH2_TRY
994  {
995  CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
996  }
998  {
1000  }
1001  _SEH2_END;
1002  }
1003  pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5;
1004  if (i == pFcb->dirIndex)
1005  {
1006  CurrentCluster =
1007  vfatDirEntryGetFirstCluster(DeviceExt,
1008  (PDIR_ENTRY)&pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))]);
1009  }
1010  }
1011 
1012  /* In case of moving, save properties */
1013  if (MoveContext != NULL)
1014  {
1015  pDirEntry = &pDirEntry[pFcb->dirIndex % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))];
1016  MoveContext->FirstCluster = CurrentCluster;
1017  MoveContext->FileSize = pDirEntry->FileSize;
1018  MoveContext->CreationTime = pDirEntry->CreationTime;
1019  MoveContext->CreationDate = pDirEntry->CreationDate;
1020  }
1021 
1022  if (Context)
1023  {
1026  }
1027 
1028  /* In case of moving, don't delete data */
1029  if (MoveContext == NULL)
1030  {
1031  while (CurrentCluster && CurrentCluster != 0xffffffff)
1032  {
1033  GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
1034  /* FIXME: check status */
1035  WriteCluster(DeviceExt, CurrentCluster, 0);
1036  CurrentCluster = NextCluster;
1037  }
1038 
1039  if (DeviceExt->FatInfo.FatType == FAT32)
1040  {
1041  FAT32UpdateFreeClustersCount(DeviceExt);
1042  }
1043  }
1044 
1045  return STATUS_SUCCESS;
1046 }
1047 
1048 /*
1049  * deleting an existing FAT entry
1050  */
1051 static NTSTATUS
1053  IN PDEVICE_EXTENSION DeviceExt,
1054  IN PVFATFCB pFcb,
1055  OUT PVFAT_MOVE_CONTEXT MoveContext)
1056 {
1057  ULONG CurrentCluster = 0, NextCluster;
1058  PVOID Context = NULL;
1060  PFATX_DIR_ENTRY pDirEntry;
1061  ULONG StartIndex;
1062  NTSTATUS Status;
1063 
1064  ASSERT(pFcb);
1065  ASSERT(pFcb->parentFcb);
1066  ASSERT(vfatVolumeIsFatX(DeviceExt));
1067 
1068  StartIndex = pFcb->startIndex;
1069 
1070  Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
1071  if (!NT_SUCCESS(Status))
1072  {
1073  return Status;
1074  }
1075 
1076  DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
1077  DPRINT("delete entry: %u\n", StartIndex);
1078  Offset.u.HighPart = 0;
1079  Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
1080  _SEH2_TRY
1081  {
1082  CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
1083  }
1085  {
1086  DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
1088  }
1089  _SEH2_END;
1090  pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
1091  pDirEntry->FilenameLength = 0xe5;
1092  CurrentCluster = vfatDirEntryGetFirstCluster(DeviceExt,
1093  (PDIR_ENTRY)pDirEntry);
1094 
1095  /* In case of moving, save properties */
1096  if (MoveContext != NULL)
1097  {
1098  MoveContext->FirstCluster = CurrentCluster;
1099  MoveContext->FileSize = pDirEntry->FileSize;
1100  MoveContext->CreationTime = pDirEntry->CreationTime;
1101  MoveContext->CreationDate = pDirEntry->CreationDate;
1102  }
1103 
1106 
1107  /* In case of moving, don't delete data */
1108  if (MoveContext == NULL)
1109  {
1110  while (CurrentCluster && CurrentCluster != 0xffffffff)
1111  {
1112  GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
1113  /* FIXME: check status */
1114  WriteCluster(DeviceExt, CurrentCluster, 0);
1115  CurrentCluster = NextCluster;
1116  }
1117  }
1118 
1119  return STATUS_SUCCESS;
1120 }
1121 
1122 /*
1123  * move an existing FAT entry
1124  */
1125 NTSTATUS
1127  IN PDEVICE_EXTENSION DeviceExt,
1128  IN PVFATFCB pFcb,
1131 {
1132  NTSTATUS Status;
1133  PVFATFCB OldParent;
1134  VFAT_MOVE_CONTEXT MoveContext;
1135 
1136  DPRINT("VfatMoveEntry(%p, %p, %wZ, %p)\n", DeviceExt, pFcb, FileName, ParentFcb);
1137 
1138  /* Delete old entry while keeping data */
1139  Status = VfatDelEntry(DeviceExt, pFcb, &MoveContext);
1140  if (!NT_SUCCESS(Status))
1141  {
1142  return Status;
1143  }
1144 
1145  OldParent = pFcb->parentFcb;
1146  CcFlushCache(&OldParent->SectionObjectPointers, NULL, 0, NULL);
1147  MoveContext.InPlace = (OldParent == ParentFcb);
1148 
1149  /* Add our new entry with our cluster */
1150  Status = VfatAddEntry(DeviceExt,
1151  FileName,
1152  &pFcb,
1153  ParentFcb,
1155  *pFcb->Attributes,
1156  &MoveContext);
1157 
1158  CcFlushCache(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, NULL);
1159 
1160  return Status;
1161 }
1162 
1167 
1169  FATXIsDirectoryEmpty, // .IsDirectoryEmpty
1170  FATXAddEntry, // .AddEntry
1171  FATXDelEntry, // .DelEntry
1172  FATXGetNextDirEntry, // .GetNextDirEntry
1173 };
1174 
1176  FATIsDirectoryEmpty, // .IsDirectoryEmpty
1177  FATAddEntry, // .AddEntry
1178  FATDelEntry, // .DelEntry
1179  FATGetNextDirEntry, // .GetNextDirEntry
1180 };
1181 
1182 /* 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:504
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:1052
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:517
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:1168
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:1175
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
#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:836
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:501
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:1334
#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:960
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:1954
_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:520
#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:1126
_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)
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
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
struct _LARGE_INTEGER::@2192 u
#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:1012
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:2745
#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:1111
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