* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
/* $Id: dirwr.c,v 1.32 2002/11/11 21:49:18 hbirr Exp $
|
2000-03-01 23:41:35 +00:00
|
|
|
*
|
1999-01-13 15:25:50 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: services/fs/vfat/dirwr.c
|
|
|
|
* PURPOSE: VFAT Filesystem : write in directory
|
2000-03-12 23:28:59 +00:00
|
|
|
*
|
|
|
|
*/
|
1999-01-13 15:25:50 +00:00
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2000-02-21 22:44:37 +00:00
|
|
|
#include <ddk/ntddk.h>
|
1999-03-19 05:55:55 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <wchar.h>
|
2000-06-29 23:35:53 +00:00
|
|
|
#include <string.h>
|
1999-01-13 15:25:50 +00:00
|
|
|
|
1999-01-20 13:00:35 +00:00
|
|
|
#define NDEBUG
|
2000-06-29 23:35:53 +00:00
|
|
|
#include <debug.h>
|
1999-01-13 15:25:50 +00:00
|
|
|
|
|
|
|
#include "vfat.h"
|
|
|
|
|
2001-08-03 19:01:17 +00:00
|
|
|
const char *short_illegals=" ;+=[]',\"*\\<>/?:|";
|
|
|
|
|
|
|
|
static BOOLEAN
|
|
|
|
vfatIsShortIllegal(char c)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; short_illegals[i]; i++)
|
|
|
|
if (c == short_illegals[i])
|
|
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2002-08-14 20:58:39 +00:00
|
|
|
NTSTATUS
|
|
|
|
VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
1999-01-13 15:25:50 +00:00
|
|
|
/*
|
2002-03-18 22:37:13 +00:00
|
|
|
* update an existing FAT entry
|
|
|
|
*/
|
1999-01-13 15:25:50 +00:00
|
|
|
{
|
2001-10-10 22:15:51 +00:00
|
|
|
PVOID Context;
|
|
|
|
PVOID Buffer;
|
2000-12-29 23:17:12 +00:00
|
|
|
NTSTATUS status;
|
2001-08-14 20:47:30 +00:00
|
|
|
PVFATFCB pDirFcb = NULL, pFcb = NULL;
|
2001-10-10 22:15:51 +00:00
|
|
|
LARGE_INTEGER Offset;
|
2000-03-13 17:58:06 +00:00
|
|
|
|
2001-10-10 22:15:51 +00:00
|
|
|
DPRINT ("updEntry PathFileName \'%S\'\n",
|
|
|
|
((PVFATCCB)(pFileObject->FsContext2))->pFcb->PathName);
|
|
|
|
status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb,
|
|
|
|
((PVFATCCB)(pFileObject->FsContext2))->pFcb->PathName);
|
2001-08-14 20:47:30 +00:00
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
if (pDirFcb != NULL)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2001-08-14 20:47:30 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2001-08-14 20:47:30 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
Offset.u.HighPart = 0;
|
|
|
|
Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry);
|
|
|
|
if (CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry),
|
|
|
|
TRUE, &Context, (PVOID*)&Buffer))
|
2001-08-14 20:47:30 +00:00
|
|
|
{
|
2001-10-10 22:15:51 +00:00
|
|
|
memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry));
|
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
2001-08-14 20:47:30 +00:00
|
|
|
}
|
2001-10-10 22:15:51 +00:00
|
|
|
else
|
|
|
|
DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName);
|
2002-03-18 22:37:13 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
2002-06-10 21:19:18 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, pFcb);
|
2001-10-10 22:15:51 +00:00
|
|
|
return STATUS_SUCCESS;
|
1999-01-13 15:25:50 +00:00
|
|
|
}
|
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
BOOLEAN
|
|
|
|
findDirSpace(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PVFATFCB pDirFcb,
|
|
|
|
ULONG nbSlots,
|
|
|
|
PULONG start)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* try to find contiguous entries frees in directory,
|
|
|
|
* extend a directory if is neccesary
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER FileOffset;
|
|
|
|
ULONG i, count, size, nbFree = 0;
|
|
|
|
FATDirEntry* pFatEntry;
|
|
|
|
PVOID Context = NULL;
|
|
|
|
NTSTATUS Status;
|
|
|
|
FileOffset.QuadPart = 0;
|
|
|
|
count = pDirFcb->RFCB.FileSize.u.LowPart / sizeof(FATDirEntry);
|
|
|
|
size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
|
|
|
|
for (i = 0; i < count; i++, pFatEntry++)
|
|
|
|
{
|
|
|
|
if (Context == NULL || (i % size) == 0)
|
|
|
|
{
|
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
|
|
|
// FIXME: check return value
|
|
|
|
CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
|
|
|
|
TRUE, &Context, (PVOID*)&pFatEntry);
|
|
|
|
FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
|
|
|
|
}
|
|
|
|
if (vfatIsDirEntryEndMarker(pFatEntry))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (vfatIsDirEntryDeleted(pFatEntry))
|
|
|
|
{
|
|
|
|
nbFree++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nbFree = 0;
|
|
|
|
}
|
|
|
|
if (nbFree == nbSlots)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
2002-04-27 19:25:57 +00:00
|
|
|
Context = NULL;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
|
|
|
if (nbFree == nbSlots)
|
|
|
|
{
|
|
|
|
// found enough contiguous free slots
|
|
|
|
*start = i - nbSlots + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*start = i - nbFree;
|
|
|
|
if (*start + nbSlots > count)
|
|
|
|
{
|
2002-08-17 15:15:50 +00:00
|
|
|
LARGE_INTEGER AllocationSize;
|
2002-03-18 22:37:13 +00:00
|
|
|
CHECKPOINT;
|
|
|
|
// extend the directory
|
|
|
|
if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32)
|
|
|
|
{
|
|
|
|
// We can't extend a root directory on a FAT12/FAT16 partition
|
|
|
|
return FALSE;
|
|
|
|
}
|
2002-08-17 15:15:50 +00:00
|
|
|
AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster;
|
|
|
|
Status = VfatSetAllocationSizeInformation(pDirFcb->FileObject, pDirFcb,
|
|
|
|
DeviceExt, &AllocationSize);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
// clear the new dir cluster
|
|
|
|
FileOffset.u.LowPart = pDirFcb->RFCB.FileSize.QuadPart -
|
|
|
|
DeviceExt->FatInfo.BytesPerCluster;
|
|
|
|
CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
|
|
|
|
TRUE, &Context, (PVOID*)&pFatEntry);
|
|
|
|
RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
|
|
|
|
}
|
|
|
|
else if (*start + nbSlots < count)
|
|
|
|
{
|
|
|
|
// clear the entry after the last new entry
|
|
|
|
FileOffset.u.LowPart = (*start + nbSlots) * sizeof(FATDirEntry);
|
|
|
|
CcMapData (pDirFcb->FileObject, &FileOffset, sizeof(FATDirEntry),
|
|
|
|
TRUE, &Context, (PVOID*)&pFatEntry);
|
|
|
|
RtlZeroMemory(pFatEntry, sizeof(FATDirEntry));
|
|
|
|
}
|
2002-04-27 19:25:57 +00:00
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
|
|
|
DPRINT ("nbSlots %d nbFree %d, entry number %d\n", nbSlots, nbFree, *start);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
NTSTATUS
|
2002-08-14 20:58:39 +00:00
|
|
|
VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PFILE_OBJECT pFileObject,
|
|
|
|
ULONG RequestedOptions,
|
|
|
|
UCHAR ReqAttr)
|
1999-01-13 15:25:50 +00:00
|
|
|
/*
|
|
|
|
create a new FAT entry
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
WCHAR DirName[MAX_PATH], *FileName, *PathFileName;
|
2001-08-03 19:01:17 +00:00
|
|
|
VFATFCB FileFcb;
|
2002-03-18 22:37:13 +00:00
|
|
|
PVOID Context = NULL;
|
|
|
|
FATDirEntry *pFatEntry, *pEntry;
|
2000-12-29 23:17:12 +00:00
|
|
|
slot *pSlots;
|
2002-03-18 22:37:13 +00:00
|
|
|
short nbSlots = 0, nbFree = 0, j, posCar, NameLen;
|
|
|
|
PUCHAR Buffer;
|
2000-12-29 23:17:12 +00:00
|
|
|
BOOLEAN needTilde = FALSE, needLong = FALSE;
|
|
|
|
PVFATFCB newFCB;
|
|
|
|
ULONG CurrentCluster;
|
2002-03-18 22:37:13 +00:00
|
|
|
LARGE_INTEGER SystemTime, LocalTime, FileOffset;
|
2001-08-14 20:47:30 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2001-10-10 22:15:51 +00:00
|
|
|
PVFATFCB pDirFcb;
|
2002-03-18 22:37:13 +00:00
|
|
|
ULONG start, size;
|
|
|
|
long i;
|
2000-03-12 23:28:59 +00:00
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
PathFileName = pFileObject->FileName.Buffer;
|
|
|
|
DPRINT ("addEntry: Pathname=%S\n", PathFileName);
|
|
|
|
//find last \ in PathFileName
|
|
|
|
posCar = -1;
|
|
|
|
for (i = 0; PathFileName[i]; i++)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
if (PathFileName[i] == L'\\')
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
posCar = i;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
if (posCar == -1)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
FileName = &PathFileName[posCar + 1];
|
|
|
|
for (NameLen = 0; FileName[NameLen]; NameLen++);
|
|
|
|
// extract directory name from pathname
|
2001-08-14 20:47:30 +00:00
|
|
|
if (posCar == 0)
|
|
|
|
{
|
|
|
|
// root dir
|
|
|
|
DirName[0] = L'\\';
|
|
|
|
DirName[1] = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy (DirName, PathFileName, posCar * sizeof (WCHAR));
|
|
|
|
DirName[posCar] = 0;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
// open parent directory
|
2001-10-10 22:15:51 +00:00
|
|
|
pDirFcb = vfatGrabFCBFromTable(DeviceExt, DirName);
|
|
|
|
if (pDirFcb == NULL)
|
2001-08-03 19:01:17 +00:00
|
|
|
{
|
2001-10-10 22:15:51 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
nbSlots = (NameLen + 12) / 13 + 1; //nb of entry needed for long name+normal entry
|
|
|
|
DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots);
|
2002-03-18 22:37:13 +00:00
|
|
|
Buffer = ExAllocatePool (NonPagedPool, nbSlots * sizeof (FATDirEntry));
|
|
|
|
RtlZeroMemory (Buffer, nbSlots * sizeof (FATDirEntry));
|
2000-12-29 23:17:12 +00:00
|
|
|
pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry));
|
|
|
|
pSlots = (slot *) Buffer;
|
|
|
|
// create 8.3 name
|
|
|
|
needTilde = FALSE;
|
|
|
|
// find last point in name
|
2001-08-03 19:01:17 +00:00
|
|
|
posCar = j = 0;
|
2000-12-29 23:17:12 +00:00
|
|
|
for (i = 0; FileName[i]; i++)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
if (FileName[i] == '.')
|
2001-08-03 19:01:17 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
posCar = i;
|
2001-08-03 19:01:17 +00:00
|
|
|
if (i == j)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
j++;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
if (!posCar)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
posCar = i;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
if (posCar < j)
|
|
|
|
{
|
|
|
|
posCar = i;
|
|
|
|
needTilde = TRUE;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
if (posCar > 8)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
needTilde = TRUE;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
//copy 8 characters max
|
|
|
|
memset (pEntry, ' ', 11);
|
|
|
|
for (i = 0, j = 0; j < 8 && i < posCar; i++)
|
2001-08-03 19:01:17 +00:00
|
|
|
{
|
|
|
|
if (vfatIsShortIllegal (FileName[i]))
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
needTilde = TRUE;
|
|
|
|
pEntry->Filename[j++] = '_';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (FileName[i] == '.')
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
needTilde = TRUE;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
else
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
pEntry->Filename[j++] = toupper ((char) FileName[i]);
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
//copy extension
|
|
|
|
if (FileName[posCar])
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
for (j = 0, i = posCar + 1; FileName[i] && j < 3; i++)
|
|
|
|
{
|
|
|
|
if (vfatIsShortIllegal(FileName[i]))
|
|
|
|
{
|
|
|
|
needTilde = TRUE;
|
|
|
|
pEntry->Ext[j++] = '_';
|
|
|
|
}
|
|
|
|
else
|
1999-01-13 15:25:50 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
if (FileName[i] == '.')
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
needTilde = TRUE;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
else
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F));
|
|
|
|
}
|
1999-01-13 15:25:50 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
if (FileName[i])
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
needTilde = TRUE;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
//find good value for tilde
|
|
|
|
if (needTilde)
|
2001-08-03 19:01:17 +00:00
|
|
|
{
|
|
|
|
needLong = TRUE;
|
|
|
|
DPRINT ("searching a good value for tilde\n");
|
|
|
|
for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++);
|
|
|
|
if (posCar == 0) // ??????????????????????
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
pEntry->Filename[posCar++] = '_';
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
posCar += 2;
|
|
|
|
if (posCar > 8)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
posCar = 8;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
pEntry->Filename[posCar - 2] = '~';
|
|
|
|
pEntry->Filename[posCar - 1] = '1';
|
|
|
|
vfat8Dot3ToString (pEntry->Filename, pEntry->Ext, DirName);
|
|
|
|
//try first with xxxxxx~y.zzz
|
|
|
|
for (i = 1; i < 10; i++)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
DirName[posCar-1] = '0' + i;
|
|
|
|
pEntry->Filename[posCar - 1] = '0' + i;
|
2002-03-18 22:37:13 +00:00
|
|
|
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
|
|
|
if (i == 10)
|
|
|
|
{
|
|
|
|
posCar++;
|
|
|
|
if (posCar > 8)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-03 19:01:17 +00:00
|
|
|
posCar = 8;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
pEntry->Filename[posCar - 3] = '~';
|
|
|
|
pEntry->Filename[posCar - 2] = '1';
|
|
|
|
pEntry->Filename[posCar - 1] = '0';
|
|
|
|
vfat8Dot3ToString (pEntry->Filename, pEntry->Ext, DirName);
|
1999-01-13 15:25:50 +00:00
|
|
|
//try second with xxxxx~yy.zzz
|
2001-08-03 19:01:17 +00:00
|
|
|
for (i = 10; i < 100; i++)
|
|
|
|
{
|
|
|
|
DirName[posCar - 1] = '0' + i % 10;
|
|
|
|
DirName[posCar - 2] = '0' + i / 10;
|
|
|
|
pEntry->Filename[posCar - 1] = '0' + i % 10;
|
|
|
|
pEntry->Filename[posCar - 2] = '0' + i / 10;
|
2002-03-18 22:37:13 +00:00
|
|
|
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
|
|
|
if (i == 100) //FIXME : what to do after 99 tilde ?
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
|
|
|
ExFreePool (Buffer);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
else
|
2001-08-03 19:01:17 +00:00
|
|
|
{
|
|
|
|
DPRINT ("check if long name entry needed, needlong=%d\n", needLong);
|
|
|
|
for (i = 0; i < posCar; i++)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
if ((USHORT) pEntry->Filename[i] != FileName[i])
|
|
|
|
{
|
|
|
|
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]);
|
2001-08-03 19:01:17 +00:00
|
|
|
needLong = TRUE;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
if (FileName[i])
|
|
|
|
{
|
|
|
|
i++; //jump on point char
|
|
|
|
for (j = 0, i = posCar + 1; FileName[i] && i < posCar + 4; i++)
|
|
|
|
{
|
|
|
|
if ((USHORT) pEntry->Ext[j++] != FileName[i])
|
|
|
|
{
|
|
|
|
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Filename[i],
|
|
|
|
FileName[i]);
|
|
|
|
needLong = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-08-03 19:01:17 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
if (needLong == FALSE)
|
2001-08-03 19:01:17 +00:00
|
|
|
{
|
|
|
|
nbSlots = 1;
|
|
|
|
memcpy (Buffer, pEntry, sizeof (FATDirEntry));
|
|
|
|
memset (pEntry, 0, sizeof (FATDirEntry));
|
|
|
|
pEntry = (FATDirEntry *) Buffer;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
else
|
2001-08-03 19:01:17 +00:00
|
|
|
{
|
|
|
|
memset (DirName, 0xff, sizeof (DirName));
|
|
|
|
memcpy (DirName, FileName, NameLen * sizeof (WCHAR));
|
|
|
|
DirName[NameLen] = 0;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
DPRINT ("dos name=%11.11s\n", pEntry->Filename);
|
1999-01-20 13:00:35 +00:00
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
/* set attributes */
|
|
|
|
pEntry->Attrib = ReqAttr;
|
|
|
|
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY;
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
/* set dates and times */
|
|
|
|
KeQuerySystemTime (&SystemTime);
|
|
|
|
ExSystemTimeToLocalTime (&SystemTime, &LocalTime);
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
#if 0
|
|
|
|
{
|
|
|
|
TIME_FIELDS tf;
|
|
|
|
RtlTimeToTimeFields (&LocalTime, &tf);
|
|
|
|
DPRINT1("%d.%d.%d %02d:%02d:%02d.%03d '%S'\n",
|
|
|
|
tf.Day, tf.Month, tf.Year, tf.Hour,
|
|
|
|
tf.Minute, tf.Second, tf.Milliseconds,
|
|
|
|
pFileObject->FileName.Buffer);
|
|
|
|
}
|
|
|
|
#endif
|
2002-09-08 10:23:54 +00:00
|
|
|
FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &pEntry->CreationDate,
|
2002-03-18 22:37:13 +00:00
|
|
|
&pEntry->CreationTime);
|
2000-12-29 23:17:12 +00:00
|
|
|
pEntry->UpdateDate = pEntry->CreationDate;
|
|
|
|
pEntry->UpdateTime = pEntry->CreationTime;
|
|
|
|
pEntry->AccessDate = pEntry->CreationDate;
|
2000-03-12 23:28:59 +00:00
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
// calculate checksum for 8.3 name
|
|
|
|
for (pSlots[0].alias_checksum = i = 0; i < 11; i++)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
|
|
|
|
| ((pSlots[0].alias_checksum & 0xfe) >> 1))
|
|
|
|
+ pEntry->Filename[i]);
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
//construct slots and entry
|
|
|
|
for (i = nbSlots - 2; i >= 0; i--)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
DPRINT ("construct slot %d\n", i);
|
|
|
|
pSlots[i].attr = 0xf;
|
|
|
|
if (i)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2002-03-18 22:37:13 +00:00
|
|
|
pSlots[i].id = nbSlots - i - 1;
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
else
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2002-03-18 22:37:13 +00:00
|
|
|
pSlots[i].id = nbSlots - i - 1 + 0x40;
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
pSlots[i].alias_checksum = pSlots[0].alias_checksum;
|
|
|
|
//FIXME pSlots[i].start=;
|
|
|
|
memcpy (pSlots[i].name0_4, DirName + (nbSlots - i - 2) * 13, 10);
|
|
|
|
memcpy (pSlots[i].name5_10, DirName + (nbSlots - i - 2) * 13 + 5, 12);
|
|
|
|
memcpy (pSlots[i].name11_12, DirName + (nbSlots - i - 2) * 13 + 11, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
//try to find nbSlots contiguous entries frees in directory
|
|
|
|
if (!findDirSpace(DeviceExt, pDirFcb, nbSlots, &start))
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
|
|
|
ExFreePool (Buffer);
|
|
|
|
return STATUS_DISK_FULL;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
|
|
|
|
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
2001-08-14 20:47:30 +00:00
|
|
|
CurrentCluster = 0xffffffff;
|
2002-03-18 22:37:13 +00:00
|
|
|
Status = NextCluster (DeviceExt, NULL, 0, &CurrentCluster, TRUE);
|
|
|
|
if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
|
2001-08-14 20:47:30 +00:00
|
|
|
{
|
2001-10-10 22:15:51 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
2001-08-14 20:47:30 +00:00
|
|
|
ExFreePool (Buffer);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2001-08-14 20:47:30 +00:00
|
|
|
{
|
2002-03-18 22:37:13 +00:00
|
|
|
return Status;
|
2001-08-14 20:47:30 +00:00
|
|
|
}
|
|
|
|
return STATUS_DISK_FULL;
|
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
|
|
|
{
|
|
|
|
pEntry->FirstClusterHigh = CurrentCluster >> 16;
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
pEntry->FirstCluster = CurrentCluster;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
|
2002-08-17 15:15:50 +00:00
|
|
|
FileOffset.u.HighPart = 0;
|
|
|
|
FileOffset.u.LowPart = start * sizeof(FATDirEntry);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (start / size == (start + nbSlots - 1) / size)
|
|
|
|
{
|
|
|
|
// one cluster
|
|
|
|
CHECKPOINT;
|
|
|
|
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry),
|
|
|
|
TRUE, &Context, (PVOID*)&pFatEntry);
|
|
|
|
memcpy(pFatEntry, Buffer, nbSlots * sizeof(FATDirEntry));
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
else
|
2001-08-14 20:47:30 +00:00
|
|
|
{
|
2002-03-18 22:37:13 +00:00
|
|
|
// two clusters
|
|
|
|
CHECKPOINT;
|
|
|
|
size = DeviceExt->FatInfo.BytesPerCluster -
|
|
|
|
(start * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster;
|
|
|
|
CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE,
|
|
|
|
&Context, (PVOID*)&pFatEntry);
|
|
|
|
memcpy(pFatEntry, Buffer, size);
|
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
|
|
|
FileOffset.u.LowPart += size;
|
|
|
|
CcMapData (pDirFcb->FileObject, &FileOffset,
|
|
|
|
nbSlots * sizeof(FATDirEntry) - size,
|
|
|
|
TRUE, &Context, (PVOID*)&pFatEntry);
|
|
|
|
memcpy(pFatEntry, (PVOID)Buffer + size, nbSlots * sizeof(FATDirEntry) - size);
|
2001-08-14 20:47:30 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2001-08-14 20:47:30 +00:00
|
|
|
// FEXME: check status
|
2002-03-18 22:37:13 +00:00
|
|
|
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, pEntry,
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
start, start + nbSlots - 1, &newFCB);
|
2001-08-14 20:47:30 +00:00
|
|
|
vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject);
|
2000-03-12 23:28:59 +00:00
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename);
|
|
|
|
DPRINT ("new : entry=%11.11s\n", pEntry->Filename);
|
2001-08-14 20:47:30 +00:00
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
FileOffset.QuadPart = 0;
|
|
|
|
CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
|
|
|
|
&Context, (PVOID*)&pFatEntry);
|
|
|
|
// clear the new directory cluster
|
|
|
|
RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
|
|
|
|
// create '.' and '..'
|
|
|
|
memcpy (&pFatEntry[0].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11);
|
|
|
|
memcpy (pFatEntry[0].Filename, ". ", 11);
|
|
|
|
memcpy (&pFatEntry[1].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11);
|
|
|
|
memcpy (pFatEntry[1].Filename, ".. ", 11);
|
|
|
|
pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster;
|
|
|
|
pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh;
|
|
|
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
|
|
|
{
|
|
|
|
if (pFatEntry[1].FirstCluster == (DeviceExt->FatInfo.RootCluster & 0xffff) &&
|
|
|
|
pFatEntry[1].FirstClusterHigh == (DeviceExt->FatInfo.RootCluster >> 16))
|
|
|
|
{
|
|
|
|
pFatEntry[1].FirstCluster = 0;
|
|
|
|
pFatEntry[1].FirstClusterHigh = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2002-03-18 22:37:13 +00:00
|
|
|
if (pFatEntry[1].FirstCluster == 1)
|
|
|
|
{
|
|
|
|
pFatEntry[1].FirstCluster = 0;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
2001-10-10 22:15:51 +00:00
|
|
|
vfatReleaseFCB (DeviceExt, pDirFcb);
|
2000-12-29 23:17:12 +00:00
|
|
|
ExFreePool (Buffer);
|
|
|
|
DPRINT ("addentry ok\n");
|
|
|
|
return STATUS_SUCCESS;
|
1999-01-13 15:25:50 +00:00
|
|
|
}
|
|
|
|
|
2001-08-14 20:47:30 +00:00
|
|
|
NTSTATUS
|
|
|
|
delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
|
|
|
/*
|
2002-03-18 22:37:13 +00:00
|
|
|
* deleting an existing FAT entry
|
|
|
|
*/
|
2001-08-14 20:47:30 +00:00
|
|
|
{
|
|
|
|
VFATFCB Fcb;
|
|
|
|
PVFATFCB pFcb = NULL, pDirFcb = NULL;
|
|
|
|
NTSTATUS status;
|
|
|
|
PWSTR pName;
|
|
|
|
ULONG Entry = 0, startEntry, Read, CurrentCluster, NextCluster, i;
|
|
|
|
FATDirEntry DirEntry;
|
|
|
|
|
|
|
|
DPRINT ("delEntry PathFileName \'%S\'\n", pFileObject->FileName.Buffer);
|
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb,
|
|
|
|
pFileObject->FileName.Buffer);
|
2001-08-14 20:47:30 +00:00
|
|
|
if (pFcb != NULL)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, pFcb);
|
|
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
if (pDirFcb != NULL)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
pName = ((PVFATCCB)(pFileObject->FsContext2))->pFcb->ObjectName;
|
|
|
|
if (*pName == L'\\')
|
|
|
|
{
|
|
|
|
pName ++;
|
|
|
|
}
|
|
|
|
status = FindFile (DeviceExt, &Fcb, pDirFcb, pName, &Entry, &startEntry);
|
|
|
|
|
|
|
|
if (NT_SUCCESS(status))
|
|
|
|
{
|
2002-03-18 22:37:13 +00:00
|
|
|
PVOID Context = NULL;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
FATDirEntry* pDirEntry;
|
2001-08-14 20:47:30 +00:00
|
|
|
DPRINT ("delete entry: %d to %d\n", startEntry, Entry);
|
2002-03-18 22:37:13 +00:00
|
|
|
Offset.u.HighPart = 0;
|
2001-08-14 20:47:30 +00:00
|
|
|
for (i = startEntry; i <= Entry; i++)
|
|
|
|
{
|
2002-10-01 19:27:25 +00:00
|
|
|
if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGE_SIZE) == 0)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
2002-10-01 19:27:25 +00:00
|
|
|
Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGE_SIZE) * PAGE_SIZE;
|
|
|
|
CcMapData (pDirFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
|
2002-03-18 22:37:13 +00:00
|
|
|
&Context, (PVOID*)&pDirEntry);
|
|
|
|
}
|
2002-10-01 19:27:25 +00:00
|
|
|
pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5;
|
2002-03-18 22:37:13 +00:00
|
|
|
if (i == Entry)
|
|
|
|
{
|
|
|
|
CurrentCluster =
|
|
|
|
vfatDirEntryGetFirstCluster (DeviceExt,
|
2002-10-01 19:27:25 +00:00
|
|
|
&pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))]);
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2001-08-14 20:47:30 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
|
|
|
|
2001-08-14 20:47:30 +00:00
|
|
|
while (CurrentCluster && CurrentCluster != 0xffffffff)
|
|
|
|
{
|
|
|
|
GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE);
|
|
|
|
// FIXME: check status
|
|
|
|
WriteCluster(DeviceExt, CurrentCluster, 0);
|
|
|
|
CurrentCluster = NextCluster;
|
|
|
|
}
|
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
2001-08-14 20:47:30 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2000-03-12 23:28:59 +00:00
|
|
|
/* EOF */
|