dirwr.c

来自「一个类似windows」· C语言 代码 · 共 739 行 · 第 1/2 页

C
739
字号
  KeQuerySystemTime (&SystemTime);
#if 0
  {
    TIME_FIELDS tf;
    RtlTimeToTimeFields (&SystemTime, &tf);
    DPRINT1("%d.%d.%d %02d:%02d:%02d.%03d '%wZ'\n",
	    tf.Day, tf.Month, tf.Year, tf.Hour,
	    tf.Minute, tf.Second, tf.Milliseconds,
	    NameU);
  }
#endif
  FsdSystemTimeToDosDateTime (DeviceExt, &SystemTime, &DirContext.DirEntry.Fat.CreationDate,
                              &DirContext.DirEntry.Fat.CreationTime);
  DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;
  DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;
  DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;

  if (needLong)
    {
      /* calculate checksum for 8.3 name */
      for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++)
        {
          pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
                                   | ((pSlots[0].alias_checksum & 0xfe) >> 1))
                                   + DirContext.DirEntry.Fat.Filename[i]);
        }
      /* construct slots and entry */
      for (i = nbSlots - 2; i >= 0; i--)
        {
          DPRINT ("construct slot %d\n", i);
          pSlots[i].attr = 0xf;
          if (i)
            {
              pSlots[i].id = (unsigned char)(nbSlots - i - 1);
            }
          else
            {
              pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40);
            }
          pSlots[i].alias_checksum = pSlots[0].alias_checksum;
          RtlCopyMemory (pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
          RtlCopyMemory (pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
          RtlCopyMemory (pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
	}
    }
  /* try to find nbSlots contiguous entries frees in directory */
  if (!vfatFindDirSpace(DeviceExt, ParentFcb, nbSlots, &DirContext.StartIndex))
    {
      ExFreePool (Buffer);
      return STATUS_DISK_FULL;
    }
  DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
  if (RequestedOptions & FILE_DIRECTORY_FILE)
    {
      CurrentCluster = 0;
      Status = NextCluster (DeviceExt, 0, &CurrentCluster, TRUE);
      if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
        {
          ExFreePool (Buffer);
          if (!NT_SUCCESS(Status))
            {
              return Status;
            }
          return STATUS_DISK_FULL;
        }
      if (DeviceExt->FatInfo.FatType == FAT32)
        {
          DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
        }
      DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
    }

  i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);
  FileOffset.u.HighPart = 0;
  FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);
  if (DirContext.StartIndex / i == DirContext.DirIndex / i)
    {
      /* one cluster */
      CHECKPOINT;
      CcPinRead (ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY),
                 TRUE, &Context, (PVOID*)&pFatEntry);
      if (nbSlots > 1)
        {
          RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
        }
      RtlCopyMemory(pFatEntry + (nbSlots - 1), &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
    }
  else
    {
      /* two clusters */
      CHECKPOINT;
      size = DeviceExt->FatInfo.BytesPerCluster -
             (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;
      i = size / sizeof(FAT_DIR_ENTRY);
      CcPinRead (ParentFcb->FileObject, &FileOffset, size, TRUE,
                 &Context, (PVOID*)&pFatEntry);
      RtlCopyMemory(pFatEntry, Buffer, size);
      CcSetDirtyPinnedData(Context, NULL);
      CcUnpinData(Context);
      FileOffset.u.LowPart += size;
      CcPinRead (ParentFcb->FileObject, &FileOffset,
                 nbSlots * sizeof(FAT_DIR_ENTRY) - size,
                 TRUE, &Context, (PVOID*)&pFatEntry);
      if (nbSlots - 1 > i)
        {
          RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));
        }
      RtlCopyMemory(pFatEntry + nbSlots - 1 - i, &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
    }
  CcSetDirtyPinnedData(Context, NULL);
  CcUnpinData(Context);

  /* FIXME: check status */
  vfatMakeFCBFromDirEntry (DeviceExt, ParentFcb, &DirContext, Fcb);

  DPRINT ("new : entry=%11.11s\n", (*Fcb)->entry.Fat.Filename);
  DPRINT ("new : entry=%11.11s\n", DirContext.DirEntry.Fat.Filename);

  if (RequestedOptions & FILE_DIRECTORY_FILE)
    {
      FileOffset.QuadPart = 0;
      CcMapData ((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
                 &Context, (PVOID*)&pFatEntry);
      /* clear the new directory cluster */
      RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
      /* create '.' and '..' */
      RtlCopyMemory (&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
      RtlCopyMemory (pFatEntry[0].ShortName, ".          ", 11);
      RtlCopyMemory (&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
      RtlCopyMemory (pFatEntry[1].ShortName, "..         ", 11);
      pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;
      pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;
      if (vfatFCBIsRoot(ParentFcb))
        {
          pFatEntry[1].FirstCluster = 0;
          pFatEntry[1].FirstClusterHigh = 0;
        }
      CcSetDirtyPinnedData(Context, NULL);
      CcUnpinData(Context);
    }
  ExFreePool (Buffer);
  DPRINT ("addentry ok\n");
  return STATUS_SUCCESS;
}

static NTSTATUS
FATXAddEntry (PDEVICE_EXTENSION DeviceExt,
	      PUNICODE_STRING NameU,
	      PVFATFCB* Fcb,
	      PVFATFCB ParentFcb,
	      ULONG RequestedOptions,
	      UCHAR ReqAttr)
/*
  create a new FAT entry
*/
{
   PVOID Context = NULL;
   LARGE_INTEGER SystemTime, FileOffset;
   OEM_STRING NameA;
   VFAT_DIRENTRY_CONTEXT DirContext;
   PFATX_DIR_ENTRY pFatXDirEntry;
   ULONG Index;

   DPRINT ("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);

   DirContext.LongNameU = *NameU;

   if (DirContext.LongNameU.Length / sizeof(WCHAR) > 42)
   {
      /* name too long */
      CHECKPOINT;
      return STATUS_NAME_TOO_LONG;
   }

   /* try to find 1 entry free in directory */
   if (!vfatFindDirSpace(DeviceExt, ParentFcb, 1, &DirContext.StartIndex))
   {
      return STATUS_DISK_FULL;
   }
   Index = DirContext.DirIndex = DirContext.StartIndex;
   if (!vfatFCBIsRoot(ParentFcb))
   {
      DirContext.DirIndex += 2;
      DirContext.StartIndex += 2;
   }

   DirContext.ShortNameU.Buffer = 0;
   DirContext.ShortNameU.Length = 0;
   DirContext.ShortNameU.MaximumLength = 0;
   RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
   memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
   DirContext.DirEntry.FatX.FirstCluster = 0;
   DirContext.DirEntry.FatX.FileSize = 0;

   /* set file name */
   NameA.Buffer = (PCHAR)DirContext.DirEntry.FatX.Filename;
   NameA.Length = 0;
   NameA.MaximumLength = 42;
   RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE);
   DirContext.DirEntry.FatX.FilenameLength = (unsigned char)NameA.Length;

   /* set attributes */
   DirContext.DirEntry.FatX.Attrib = ReqAttr;
   if (RequestedOptions & FILE_DIRECTORY_FILE)
   {
      DirContext.DirEntry.FatX.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
   }

   /* set dates and times */
   KeQuerySystemTime (&SystemTime);
#if 0
  {
    TIME_FIELDS tf;
    RtlTimeToTimeFields (&SystemTime, &tf);
    DPRINT1("%d.%d.%d %02d:%02d:%02d.%03d '%wZ'\n",
	    tf.Day, tf.Month, tf.Year, tf.Hour,
	    tf.Minute, tf.Second, tf.Milliseconds,
	    NameU);
  }
#endif


   FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.FatX.CreationDate,
                              &DirContext.DirEntry.FatX.CreationTime);
   DirContext.DirEntry.FatX.UpdateDate = DirContext.DirEntry.FatX.CreationDate;
   DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
   DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
   DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;

   /* add entry into parent directory */
   FileOffset.u.HighPart = 0;
   FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY);
   CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY),
             TRUE, &Context, (PVOID*)&pFatXDirEntry);
   RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
   CcSetDirtyPinnedData(Context, NULL);
   CcUnpinData(Context);

   /* FIXME: check status */
   vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);

   DPRINT("addentry ok\n");
   return STATUS_SUCCESS;
}

NTSTATUS
VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
	      PUNICODE_STRING NameU,
	      PVFATFCB *Fcb,
	      PVFATFCB ParentFcb,
	      ULONG RequestedOptions,
	      UCHAR ReqAttr)
{
   if (DeviceExt->Flags & VCB_IS_FATX)
      return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
   else
      return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
}

static NTSTATUS
FATDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
/*
 * deleting an existing FAT entry
 */
{
  ULONG CurrentCluster = 0, NextCluster, i;
  PVOID Context = NULL;
  LARGE_INTEGER Offset;
  PFAT_DIR_ENTRY pDirEntry;

  ASSERT(pFcb);
  ASSERT(pFcb->parentFcb);

  DPRINT ("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
  DPRINT ("delete entry: %d to %d\n", pFcb->startIndex, pFcb->dirIndex);
  Offset.u.HighPart = 0;
  for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
    {
      if (Context == NULL || ((i * sizeof(FAT_DIR_ENTRY)) % PAGE_SIZE) == 0)
        {
          if (Context)
          {
            CcSetDirtyPinnedData(Context, NULL);
            CcUnpinData(Context);
          }
          Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
          CcPinRead (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
                     &Context, (PVOID*)&pDirEntry);
        }
      pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5;
      if (i == pFcb->dirIndex)
        {
          CurrentCluster =
          vfatDirEntryGetFirstCluster (DeviceExt,
            (PDIR_ENTRY)&pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))]);
        }
    }
  if (Context)
    {
      CcSetDirtyPinnedData(Context, NULL);
      CcUnpinData(Context);
    }

  while (CurrentCluster && CurrentCluster != 0xffffffff)
    {
      GetNextCluster (DeviceExt, CurrentCluster, &NextCluster);
      /* FIXME: check status */
      WriteCluster(DeviceExt, CurrentCluster, 0);
      CurrentCluster = NextCluster;
    }
  return STATUS_SUCCESS;
}

static NTSTATUS
FATXDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
/*
 * deleting an existing FAT entry
 */
{
  ULONG CurrentCluster = 0, NextCluster;
  PVOID Context = NULL;
  LARGE_INTEGER Offset;
  PFATX_DIR_ENTRY pDirEntry;
  ULONG StartIndex;

  ASSERT(pFcb);
  ASSERT(pFcb->parentFcb);
  ASSERT(pFcb->Flags & FCB_IS_FATX_ENTRY);

  StartIndex = pFcb->startIndex;

  DPRINT ("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
  DPRINT ("delete entry: %d\n", StartIndex);
  Offset.u.HighPart = 0;
  Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
  if (!CcPinRead (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
                     &Context, (PVOID*)&pDirEntry))
  {
    DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
    return STATUS_UNSUCCESSFUL;
  }
  pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
  pDirEntry->FilenameLength = 0xe5;
  CurrentCluster = vfatDirEntryGetFirstCluster (DeviceExt,
            (PDIR_ENTRY)pDirEntry);
  CcSetDirtyPinnedData(Context, NULL);
  CcUnpinData(Context);

  while (CurrentCluster && CurrentCluster != 0xffffffff)
    {
      GetNextCluster (DeviceExt, CurrentCluster, &NextCluster);
      /* FIXME: check status */
      WriteCluster(DeviceExt, CurrentCluster, 0);
      CurrentCluster = NextCluster;
    }
  return STATUS_SUCCESS;
}

NTSTATUS
VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
{
   if (DeviceExt->Flags & VCB_IS_FATX)
      return FATXDelEntry(DeviceExt, pFcb);
   else
      return FATDelEntry(DeviceExt, pFcb);
}

/* EOF */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?