ReactOS  0.4.15-dev-5452-g3c95c95
dirwr.c File Reference
#include "vfat.h"
#include <debug.h>
Include dependency graph for dirwr.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

NTSTATUS vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb)
 
NTSTATUS VfatUpdateEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb)
 
NTSTATUS vfatRenameEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN BOOLEAN CaseChangeOnly)
 
BOOLEAN vfatFindDirSpace (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pDirFcb, IN ULONG nbSlots, OUT PULONG start)
 
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)
 
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)
 
static NTSTATUS FATDelEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
 
static NTSTATUS FATXDelEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
 
NTSTATUS VfatMoveEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN PVFATFCB ParentFcb)
 
BOOLEAN FATXIsDirectoryEmpty (PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
 
BOOLEAN FATIsDirectoryEmpty (PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
 
NTSTATUS FATGetNextDirEntry (PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
 
NTSTATUS FATXGetNextDirEntry (PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
 

Variables

VFAT_DISPATCH FatXDispatch
 
VFAT_DISPATCH FatDispatch
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file dirwr.c.

Function Documentation

◆ FATAddEntry()

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 
)
static

Definition at line 403 of file dirwr.c.

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 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
_SEH2_TRY
Definition: create.c:4226
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1303
LONGLONG CreationTime
Definition: cdstruc.h:1030
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
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:52
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
unsigned char attr
Definition: vfat.h:188
NTSTATUS FAT32UpdateFreeClustersCount(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:1215
unsigned char alias_checksum
Definition: vfat.h:190
USHORT MaximumLength
Definition: env_spec_w32.h:370
PFILE_OBJECT FileObject
Definition: ntfs.h:520
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
unsigned long FileSize
Definition: vfat.h:129
#define TRUE
Definition: types.h:120
#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
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
UNICODE_STRING LongNameU
Definition: vfat.h:602
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
ULONG DirIndex
Definition: ntfs.h:533
#define PIN_WAIT
_SEH2_END
Definition: create.c:4400
STRING OEM_STRING
Definition: umtypes.h:203
FAT_DIR_ENTRY Fat
Definition: vfat.h:226
unsigned char ShortName[11]
Definition: vfat.h:115
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
unsigned char BOOLEAN
unsigned char
Definition: typeof.h:29
#define TAG_DIRENT
Definition: nodetype.h:158
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:293
Definition: bufpool.h:45
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
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
Status
Definition: gdiplustypes.h:24
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
GLsizeiptr size
Definition: glext.h:5919
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
UNICODE_STRING ShortNameU
Definition: vfat.h:603
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:424
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
_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
#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
_Must_inspect_result_ _In_ PFLT_INSTANCE _Out_ PBOOLEAN IsDirectory
Definition: fltkernel.h:1139
#define VFAT_CASE_LOWER_EXT
Definition: vfat.h:201
unsigned short FirstClusterHigh
Definition: vfat.h:123
Definition: vfat.h:184
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 short USHORT
Definition: pedump.c:61
unsigned char id
Definition: vfat.h:186
_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)
#define NULL
Definition: types.h:112
#define FAT32
Definition: fat.h:169
unsigned short FirstCluster
Definition: vfat.h:128
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define LONGNAME_MAX_LENGTH
Definition: vfat.h:203
#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 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
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
Definition: find.c:28

◆ FATDelEntry()

static NTSTATUS FATDelEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
OUT PVFAT_MOVE_CONTEXT  MoveContext 
)
static

Definition at line 956 of file dirwr.c.

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 }
_SEH2_TRY
Definition: create.c:4226
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
unsigned short CreationTime
Definition: vfat.h:120
NTSTATUS WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue)
Definition: fat.c:705
NTSTATUS FAT32UpdateFreeClustersCount(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:1215
unsigned long FileSize
Definition: vfat.h:129
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:18
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
LONG NTSTATUS
Definition: precomp.h:26
unsigned char Filename[8]
Definition: vfat.h:114
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define PIN_WAIT
_SEH2_END
Definition: create.c:4400
Status
Definition: gdiplustypes.h:24
unsigned short CreationDate
Definition: vfat.h:120
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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 PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
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
Definition: vfat.h:224
#define NULL
Definition: types.h:112
#define FAT32
Definition: fat.h:169
unsigned short FirstCluster
Definition: vfat.h:128
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
unsigned int ULONG
Definition: retypes.h:1
#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 GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:744

◆ FATGetNextDirEntry()

NTSTATUS FATGetNextDirEntry ( PVOID pContext,
PVOID pPage,
PVFATFCB  pDirFcb,
PVFAT_DIRENTRY_CONTEXT  DirContext,
BOOLEAN  First 
)

◆ FATIsDirectoryEmpty()

BOOLEAN FATIsDirectoryEmpty ( PDEVICE_EXTENSION  DeviceExt,
PVFATFCB  Fcb 
)

Definition at line 42 of file direntry.c.

45 {
47  PVOID Context = NULL;
48  PFAT_DIR_ENTRY FatDirEntry;
49  ULONG Index, MaxIndex;
51 
52  if (vfatFCBIsRoot(Fcb))
53  {
54  Index = 0;
55  }
56  else
57  {
58  Index = 2;
59  }
60 
61  FileOffset.QuadPart = 0;
62  MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY);
63 
65  if (!NT_SUCCESS(Status))
66  {
67  return FALSE;
68  }
69 
70  while (Index < MaxIndex)
71  {
72  if (Context == NULL || (Index % FAT_ENTRIES_PER_PAGE) == 0)
73  {
74  if (Context != NULL)
75  {
77  }
78 
79  _SEH2_TRY
80  {
81  CcMapData(Fcb->FileObject, &FileOffset, sizeof(FAT_DIR_ENTRY), MAP_WAIT, &Context, (PVOID*)&FatDirEntry);
82  }
84  {
85  _SEH2_YIELD(return TRUE);
86  }
87  _SEH2_END;
88 
89  FatDirEntry += Index % FAT_ENTRIES_PER_PAGE;
90  FileOffset.QuadPart += PAGE_SIZE;
91  }
92 
93  if (FAT_ENTRY_END(FatDirEntry))
94  {
96  return TRUE;
97  }
98 
99  if (!FAT_ENTRY_DELETED(FatDirEntry))
100  {
102  return FALSE;
103  }
104 
105  Index++;
106  FatDirEntry++;
107  }
108 
109  if (Context)
110  {
112  }
113 
114  return TRUE;
115 }
struct _LARGE_INTEGER::@2253 u
_SEH2_TRY
Definition: create.c:4226
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
#define FAT_ENTRY_END(DirEntry)
Definition: vfat.h:210
PFILE_OBJECT FileObject
Definition: ntfs.h:520
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define MAP_WAIT
#define FAT_ENTRIES_PER_PAGE
Definition: vfat.h:219
_SEH2_END
Definition: create.c:4400
#define FALSE
Definition: types.h:117
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:293
#define FAT_ENTRY_DELETED(DirEntry)
Definition: vfat.h:209
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
Status
Definition: gdiplustypes.h:24
BOOLEAN NTAPI CcMapData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *BcbResult, OUT PVOID *Buffer)
Definition: pinsup.c:694
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ WDFCOLLECTION _In_ ULONG Index
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_In_ PFCB Fcb
Definition: cdprocs.h:159

◆ FATXAddEntry()

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 
)
static

Definition at line 832 of file dirwr.c.

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 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
_SEH2_TRY
Definition: create.c:4226
LONGLONG CreationTime
Definition: cdstruc.h:1030
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:52
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
PFILE_OBJECT FileObject
Definition: ntfs.h:520
#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
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
ULONG DirIndex
Definition: ntfs.h:533
#define PIN_WAIT
_SEH2_END
Definition: create.c:4400
STRING OEM_STRING
Definition: umtypes.h:203
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define FALSE
Definition: types.h:117
NTSTATUS vfatMakeFCBFromDirEntry(PVCB vcb, PVFATFCB directoryFCB, PVFAT_DIRENTRY_CONTEXT DirContext, PVFATFCB *fileFCB)
Definition: fcb.c:725
unsigned char
Definition: typeof.h:29
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:293
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define PCHAR
Definition: match.c:90
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ WDFCOLLECTION _In_ ULONG Index
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:424
_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
#define FCB_CACHE_INITIALIZED
Definition: ntfs.h:508
ULONG Flags
Definition: ntfs.h:536
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define NULL
Definition: types.h:112
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
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
_In_ PFCB Fcb
Definition: cdprocs.h:159
#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

◆ FATXDelEntry()

static NTSTATUS FATXDelEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
OUT PVFAT_MOVE_CONTEXT  MoveContext 
)
static

Definition at line 1048 of file dirwr.c.

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 }
_SEH2_TRY
Definition: create.c:4226
unsigned char FilenameLength
Definition: vfat.h:171
NTSTATUS WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue)
Definition: fat.c:705
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:18
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define PIN_WAIT
_SEH2_END
Definition: create.c:4400
unsigned long FileSize
Definition: vfat.h:175
unsigned short CreationDate
Definition: vfat.h:179
Status
Definition: gdiplustypes.h:24
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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 PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
Definition: vfat.h:224
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
unsigned short CreationTime
Definition: vfat.h:178
unsigned int ULONG
Definition: retypes.h:1
#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 GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:744

◆ FATXGetNextDirEntry()

NTSTATUS FATXGetNextDirEntry ( PVOID pContext,
PVOID pPage,
PVFATFCB  pDirFcb,
PVFAT_DIRENTRY_CONTEXT  DirContext,
BOOLEAN  First 
)

◆ FATXIsDirectoryEmpty()

BOOLEAN FATXIsDirectoryEmpty ( PDEVICE_EXTENSION  DeviceExt,
PVFATFCB  Fcb 
)

Definition at line 118 of file direntry.c.

121 {
123  PVOID Context = NULL;
124  PFATX_DIR_ENTRY FatXDirEntry;
125  ULONG Index = 0, MaxIndex;
127 
128  FileOffset.QuadPart = 0;
129  MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FATX_DIR_ENTRY);
130 
132  if (!NT_SUCCESS(Status))
133  {
134  return FALSE;
135  }
136 
137  while (Index < MaxIndex)
138  {
139  if (Context == NULL || (Index % FATX_ENTRIES_PER_PAGE) == 0)
140  {
141  if (Context != NULL)
142  {
144  }
145 
146  _SEH2_TRY
147  {
148  CcMapData(Fcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), MAP_WAIT, &Context, (PVOID*)&FatXDirEntry);
149  }
151  {
152  _SEH2_YIELD(return TRUE);
153  }
154  _SEH2_END;
155 
156  FatXDirEntry += Index % FATX_ENTRIES_PER_PAGE;
157  FileOffset.QuadPart += PAGE_SIZE;
158  }
159 
160  if (FATX_ENTRY_END(FatXDirEntry))
161  {
163  return TRUE;
164  }
165 
166  if (!FATX_ENTRY_DELETED(FatXDirEntry))
167  {
169  return FALSE;
170  }
171 
172  Index++;
173  FatXDirEntry++;
174  }
175 
176  if (Context)
177  {
179  }
180 
181  return TRUE;
182 }
struct _LARGE_INTEGER::@2253 u
_SEH2_TRY
Definition: create.c:4226
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
PFILE_OBJECT FileObject
Definition: ntfs.h:520
#define TRUE
Definition: types.h:120
#define FATX_ENTRY_END(DirEntry)
Definition: vfat.h:215
#define FATX_ENTRY_DELETED(DirEntry)
Definition: vfat.h:214
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define MAP_WAIT
_SEH2_END
Definition: create.c:4400
#define FALSE
Definition: types.h:117
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
Status
Definition: gdiplustypes.h:24
BOOLEAN NTAPI CcMapData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *BcbResult, OUT PVOID *Buffer)
Definition: pinsup.c:694
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
#define FATX_ENTRIES_PER_PAGE
Definition: vfat.h:220
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ WDFCOLLECTION _In_ ULONG Index
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_In_ PFCB Fcb
Definition: cdprocs.h:159

◆ vfatFCBInitializeCacheFromVolume()

NTSTATUS vfatFCBInitializeCacheFromVolume ( PVCB  vcb,
PVFATFCB  fcb 
)

Definition at line 22 of file dirwr.c.

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 }
_SEH2_TRY
Definition: create.c:4226
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: vfat.h:536
#define TRUE
Definition: types.h:120
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
VOID vfatGrabFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
Definition: fcb.c:301
_SEH2_END
Definition: create.c:4400
BOOLEAN NTAPI FsRtlIsNameInExpression(IN PUNICODE_STRING Expression, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL)
Definition: name.c:514
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3186
NPAGED_LOOKASIDE_LIST CcbLookasideList
Definition: vfat.h:418
struct _fcb fcb
Definition: btrfs_drv.h:1364
#define ASSERT(a)
Definition: mode.c:44
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FCB_CACHE_INITIALIZED
Definition: ntfs.h:508
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:18
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define ExIsResourceAcquiredExclusive
Definition: exfuncs.h:347
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

Referenced by FATAddEntry(), FATDelEntry(), FATGetNextDirEntry(), FATIsDirectoryEmpty(), FATXDelEntry(), FATXGetNextDirEntry(), FATXIsDirectoryEmpty(), FsdSetFsLabelInformation(), vfatFindDirSpace(), vfatMakeRootFCB(), vfatRenameEntry(), and VfatUpdateEntry().

◆ vfatFindDirSpace()

BOOLEAN vfatFindDirSpace ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pDirFcb,
IN ULONG  nbSlots,
OUT PULONG  start 
)

Definition at line 258 of file dirwr.c.

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 }
struct _LARGE_INTEGER::@2253 u
_SEH2_TRY
Definition: create.c:4226
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
#define ENTRY_END(IsFatX, DirEntry)
Definition: vfat.h:207
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
#define TRUE
Definition: types.h:120
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
GLuint GLuint GLsizei count
Definition: gl.h:1545
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define PIN_WAIT
#define ENTRY_DELETED(IsFatX, DirEntry)
Definition: vfat.h:205
_SEH2_END
Definition: create.c:4400
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:293
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
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
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
GLsizeiptr size
Definition: glext.h:5919
union _DIR_ENTRY * PDIR_ENTRY
Definition: vfat.h:230
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
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
GLuint start
Definition: gl.h:1545
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
Definition: vfat.h:224
#define NULL
Definition: types.h:112
#define FAT32
Definition: fat.h:169
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define DPRINT
Definition: sndvol32.h:71
#define memset(x, y, z)
Definition: compat.h:39

Referenced by FATAddEntry(), FATXAddEntry(), and FsdSetFsLabelInformation().

◆ VfatMoveEntry()

NTSTATUS VfatMoveEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
IN PUNICODE_STRING  FileName,
IN PVFATFCB  ParentFcb 
)

Definition at line 1122 of file dirwr.c.

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 }
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: vfat.h:451
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
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
Status
Definition: gdiplustypes.h:24
struct _VFATFCB * parentFcb
Definition: vfat.h:490
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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 ParentFcb
Definition: cdprocs.h:736
BOOLEAN InPlace
Definition: vfat.h:613
FORCEINLINE NTSTATUS VfatDelEntry(PDEVICE_EXTENSION DeviceExt, struct _VFATFCB *Fcb, struct _VFAT_MOVE_CONTEXT *MoveContext)
Definition: vfat.h:388
#define NULL
Definition: types.h:112
#define DPRINT
Definition: sndvol32.h:71

Referenced by vfatRenameEntry(), and VfatSetRenameInformation().

◆ vfatRenameEntry()

NTSTATUS vfatRenameEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
IN PUNICODE_STRING  FileName,
IN BOOLEAN  CaseChangeOnly 
)

Definition at line 178 of file dirwr.c.

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 }
_SEH2_TRY
Definition: create.c:4226
unsigned char FilenameLength
Definition: vfat.h:171
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
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
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define PIN_WAIT
_SEH2_END
Definition: create.c:4400
STRING OEM_STRING
Definition: umtypes.h:203
#define FALSE
Definition: types.h:117
unsigned char
Definition: typeof.h:29
#define PCHAR
Definition: match.c:90
Status
Definition: gdiplustypes.h:24
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:424
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
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
unsigned char Filename[42]
Definition: vfat.h:173
NTSTATUS VfatMoveEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN PVFATFCB ParentFcb)
Definition: dirwr.c:1122
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#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

Referenced by VfatSetRenameInformation().

◆ VfatUpdateEntry()

NTSTATUS VfatUpdateEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb 
)

Definition at line 115 of file dirwr.c.

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 }
_SEH2_TRY
Definition: create.c:4226
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
#define FCB_IS_DIRTY
Definition: vfat.h:438
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define PIN_WAIT
_SEH2_END
Definition: create.c:4400
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:293
Status
Definition: gdiplustypes.h:24
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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 FCB_IS_FAT
Definition: vfat.h:435
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
Definition: vfat.h:224
#define NULL
Definition: types.h:112
#define FCB_IS_VOLUME
Definition: ntfs.h:510
#define DPRINT1
Definition: precomp.h:8
struct tagContext Context
Definition: acpixf.h:1038
unsigned int ULONG
Definition: retypes.h:1
#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

Referenced by VfatCleanupFile(), VfatCreateFile(), VfatFlushFile(), VfatSetAllocationSizeInformation(), and VfatSetBasicInformation().

Variable Documentation

◆ FatDispatch

VFAT_DISPATCH FatDispatch
Initial value:
= {
}
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
NTSTATUS FATGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
BOOLEAN FATIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
Definition: direntry.c:42
static NTSTATUS FATDelEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:956

Definition at line 1171 of file dirwr.c.

Referenced by VfatMount().

◆ FatXDispatch

VFAT_DISPATCH FatXDispatch
Initial value:
= {
}
static NTSTATUS FATXDelEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:1048
NTSTATUS FATXGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
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
BOOLEAN FATXIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
Definition: direntry.c:118

Definition at line 1164 of file dirwr.c.

Referenced by VfatMount().