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