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 + -
显示快捷键?