- Changed the file names to unicode strings.

- Replaced most of the string functions with the unicode functions.
- Removed some overhead.
- Fixed some minor bugs.

svn path=/trunk/; revision=6279
This commit is contained in:
Hartmut Birr 2003-10-11 17:51:56 +00:00
parent a751ffce23
commit 096a69471d
21 changed files with 1510 additions and 1556 deletions

View file

@ -1,9 +1,10 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/blockdev.c * FILE: drivers/fs/vfat/blockdev.c
* PURPOSE: Temporary sector reading support * PURPOSE: Temporary sector reading support
* PROGRAMMER: David Welch (welch@cwcom.net) * PROGRAMMER: David Welch (welch@cwcom.net)
* Hartmut Birr
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */

View file

@ -1,10 +1,11 @@
/* $Id: cleanup.c,v 1.13 2003/07/24 20:52:58 chorns Exp $ /* $Id: cleanup.c,v 1.14 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/cleanup.c * FILE: drivers/fs/vfat/cleanup.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -25,11 +26,10 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext)
*/ */
{ {
PVFATFCB pFcb; PVFATFCB pFcb;
PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
PFILE_OBJECT FileObject = IrpContext->FileObject; PFILE_OBJECT FileObject = IrpContext->FileObject;
DPRINT("VfatCleanupFile(DeviceExt %x, FileObject %x)\n", DPRINT("VfatCleanupFile(DeviceExt %x, FileObject %x)\n",
DeviceExt, FileObject); IrpContext->DeviceExt, FileObject);
/* FIXME: handle file/directory deletion here */ /* FIXME: handle file/directory deletion here */
pFcb = (PVFATFCB) FileObject->FsContext; pFcb = (PVFATFCB) FileObject->FsContext;
@ -45,6 +45,11 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext)
NULL); NULL);
} }
if (pFcb->Flags & FCB_IS_DIRTY)
{
VfatUpdateEntry (pFcb);
}
/* Uninitialize file cache if initialized for this file object. */ /* Uninitialize file cache if initialized for this file object. */
if (FileObject->PrivateCacheMap) if (FileObject->PrivateCacheMap)
{ {

View file

@ -1,10 +1,11 @@
/* $Id: close.c,v 1.20 2003/07/24 20:52:58 chorns Exp $ /* $Id: close.c,v 1.21 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/close.c * FILE: drivers/fs/vfat/close.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -55,7 +56,7 @@ VfatCloseFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
{ {
if (pFcb->Flags & FCB_DELETE_PENDING) if (pFcb->Flags & FCB_DELETE_PENDING)
{ {
delEntry (DeviceExt, FileObject); VfatDelEntry (DeviceExt, pFcb);
} }
else else
{ {

View file

@ -16,13 +16,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: create.c,v 1.63 2003/07/24 20:52:58 chorns Exp $ /* $Id: create.c,v 1.64 2003/10/11 17:51:56 hbirr Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/create.c * FILE: drivers/fs/vfat/create.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -42,73 +42,60 @@
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PWSTR pName) void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
{ {
int fromIndex, toIndex; OEM_STRING StringA;
ULONG Length;
CHAR cString[12];
fromIndex = toIndex = 0; memcpy(cString, pEntry->Filename, 11);
while (fromIndex < 8 && pEntry->Filename [fromIndex] != ' ') cString[11] = 0;
if (cString[0] == 0x05)
{ {
cString[0] = 0xe5;
}
StringA.Buffer = cString;
for (StringA.Length = 0;
StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
StringA.Length++);
StringA.MaximumLength = StringA.Length;
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
if (pEntry->lCase & VFAT_CASE_LOWER_BASE) if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
{ {
pName [toIndex++] = tolower(pEntry->Filename [fromIndex++]); RtlDowncaseUnicodeString(NameU, NameU, FALSE);
} }
else if (cString[8] != ' ')
{ {
pName [toIndex++] = pEntry->Filename [fromIndex++]; Length = NameU->Length;
NameU->Buffer += Length / sizeof(WCHAR);
if (!ENTRY_VOLUME(pEntry))
{
Length += sizeof(WCHAR);
NameU->Buffer[0] = L'.';
NameU->Buffer++;
} }
} NameU->Length = 0;
if (pEntry->Ext [0] != ' ') NameU->MaximumLength -= Length;
{
pName [toIndex++] = L'.'; StringA.Buffer = &cString[8];
fromIndex = 0; for (StringA.Length = 0;
while (fromIndex < 3 && pEntry->Ext [fromIndex] != ' ') StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
{ StringA.Length++);
StringA.MaximumLength = StringA.Length;
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
if (pEntry->lCase & VFAT_CASE_LOWER_EXT) if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
{ {
pName [toIndex++] = tolower(pEntry->Ext [fromIndex++]); RtlDowncaseUnicodeString(NameU, NameU, FALSE);
} }
else NameU->Buffer -= Length / sizeof(WCHAR);
{ NameU->Length += Length;
pName [toIndex++] = pEntry->Ext [fromIndex++]; NameU->MaximumLength += Length;
} }
} NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
} DPRINT("'%wZ'\n", NameU);
pName [toIndex] = L'\0';
}
static void vfat8Dot3ToVolumeLabel (PFAT_DIR_ENTRY pEntry, PWSTR pName)
{
int fromIndex, toIndex;
fromIndex = toIndex = 0;
while (fromIndex < 8 && pEntry->Filename [fromIndex] != ' ')
{
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
{
pName [toIndex++] = tolower(pEntry->Filename [fromIndex++]);
}
else
{
pName [toIndex++] = pEntry->Filename [fromIndex++];
}
}
if (pEntry->Ext [0] != ' ')
{
fromIndex = 0;
while (fromIndex < 3 && pEntry->Ext [fromIndex] != ' ')
{
if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
{
pName [toIndex++] = tolower(pEntry->Ext [fromIndex++]);
}
else
{
pName [toIndex++] = pEntry->Ext [fromIndex++];
}
}
}
pName [toIndex] = L'\0';
} }
NTSTATUS NTSTATUS
@ -122,25 +109,31 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
FATDirEntry* Entry; FATDirEntry* Entry;
PVFATFCB pFcb; PVFATFCB pFcb;
LARGE_INTEGER FileOffset; LARGE_INTEGER FileOffset;
UNICODE_STRING NameU;
NameU.Buffer = Vpb->VolumeLabel;
NameU.Length = 0;
NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
*(Vpb->VolumeLabel) = 0; *(Vpb->VolumeLabel) = 0;
Vpb->VolumeLabelLength = 0; Vpb->VolumeLabelLength = 0;
ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
pFcb = vfatOpenRootFCB (DeviceExt); pFcb = vfatOpenRootFCB (DeviceExt);
ExReleaseResourceLite (&DeviceExt->DirResource);
FileOffset.QuadPart = 0; FileOffset.QuadPart = 0;
if (CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry)) if (CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
{ {
while (TRUE) while (TRUE)
{ {
if (vfatIsDirEntryVolume(Entry)) if (ENTRY_VOLUME(Entry))
{ {
/* copy volume label */ /* copy volume label */
vfat8Dot3ToVolumeLabel (Entry, Vpb->VolumeLabel); vfat8Dot3ToString (Entry, &NameU);
Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel) * sizeof(WCHAR); Vpb->VolumeLabelLength = NameU.Length;
break; break;
} }
if (vfatIsDirEntryEndMarker(Entry)) if (ENTRY_END(Entry))
{ {
break; break;
} }
@ -162,242 +155,183 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
CcUnpinData(Context); CcUnpinData(Context);
} }
} }
ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
vfatReleaseFCB (DeviceExt, pFcb); vfatReleaseFCB (DeviceExt, pFcb);
ExReleaseResourceLite (&DeviceExt->DirResource);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
FindFile (PDEVICE_EXTENSION DeviceExt, FindFile (PDEVICE_EXTENSION DeviceExt,
PVFATFCB Fcb,
PVFATFCB Parent, PVFATFCB Parent,
PWSTR FileToFind, PUNICODE_STRING FileToFindU,
ULONG *pDirIndex, PVFAT_DIRENTRY_CONTEXT DirContext,
ULONG *pDirIndex2) BOOLEAN First)
/* /*
* FUNCTION: Find a file * FUNCTION: Find a file
*/ */
{ {
WCHAR name[256]; WCHAR PathNameBuffer[MAX_PATH];
WCHAR name2[14];
WCHAR TempStr[2];
NTSTATUS Status; NTSTATUS Status;
ULONG len;
ULONG DirIndex;
ULONG FirstCluster;
BOOL isRoot;
PVOID Context = NULL; PVOID Context = NULL;
PVOID Page; PVOID Page;
PVFATFCB rcFcb; PVFATFCB rcFcb;
BOOLEAN FoundLong;
BOOLEAN FoundShort;
UNICODE_STRING PathNameU;
BOOLEAN WildCard;
PWCHAR curr, last;
FATDirEntry fatDirEntry; DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
Parent, FileToFindU, DirContext->DirIndex);
DPRINT ("FindFile: Path %wZ)\n",&Parent->PathNameU);
DPRINT ("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", Parent, FileToFind, pDirIndex ? *pDirIndex : 0); PathNameU.Buffer = PathNameBuffer;
DPRINT ("FindFile: old Pathname %x, old Objectname %x)\n",Fcb->PathName, Fcb->ObjectName); PathNameU.Length = 0;
PathNameU.MaximumLength = sizeof(PathNameBuffer);
isRoot = FALSE; DirContext->LongNameU.Length = 0;
DirIndex = 0; DirContext->ShortNameU.Length = 0;
if (wcslen (FileToFind) == 0)
{
CHECKPOINT;
TempStr[0] = (WCHAR) '*';
TempStr[1] = 0;
FileToFind = (PWSTR)&TempStr;
}
if (Parent)
{
FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Parent->entry);
if (DeviceExt->FatInfo.FatType == FAT32)
{
if (FirstCluster == DeviceExt->FatInfo.RootCluster)
isRoot = TRUE;
}
else
{
if (FirstCluster == 1)
isRoot = TRUE;
}
}
else
isRoot = TRUE;
if (isRoot)
{
if (DeviceExt->FatInfo.FatType == FAT32)
FirstCluster = DeviceExt->FatInfo.RootCluster;
else
FirstCluster = 1;
if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0) /* FIXME: Use FsRtlDoesNameContainWildCards */
|| (FileToFind[0] == '.' && FileToFind[1] == 0)) WildCard = FALSE;
curr = FileToFindU->Buffer;
last = FileToFindU->Buffer + FileToFindU->Length / sizeof(WCHAR);
while (curr < last)
{ {
/* it's root : complete essentials fields then return ok */ if (*curr == L'?' || *curr == L'*')
CHECKPOINT;
memset (Fcb, 0, sizeof (VFATFCB));
memset (Fcb->entry.Filename, ' ', 11);
CHECKPOINT;
Fcb->PathName[0]='\\';
Fcb->ObjectName = &Fcb->PathName[1];
Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
Fcb->entry.CreationDate = 0x0021; /* 1.1.1980 */
Fcb->entry.AccessDate = 0x0021;
Fcb->entry.UpdateDate = 0x0021;
if (DeviceExt->FatInfo.FatType == FAT32)
{ {
Fcb->entry.FirstCluster = ((PUSHORT)&FirstCluster)[0]; WildCard = TRUE;
Fcb->entry.FirstClusterHigh = ((PUSHORT)&FirstCluster)[1]; break;
} }
else curr++;
Fcb->entry.FirstCluster = 1;
if (pDirIndex)
*pDirIndex = 0;
if (pDirIndex2)
*pDirIndex2 = 0;
DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
return (STATUS_SUCCESS);
} }
}
else
{
DPRINT ("Parent->entry.FileSize %x\n", Parent->entry.FileSize);
FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Parent->entry);
}
if (pDirIndex && (*pDirIndex))
DirIndex = *pDirIndex;
if (NULL == wcschr(FileToFind, L'?') && NULL == wcschr(FileToFind, L'*')) if (WildCard == FALSE)
{ {
/* if there is no '*?' in the search name, than look first for an existing fcb */ /* if there is no '*?' in the search name, than look first for an existing fcb */
len = wcslen(Parent->PathName); RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
memcpy(name, Parent->PathName, len * sizeof(WCHAR));
if (!vfatFCBIsRoot(Parent)) if (!vfatFCBIsRoot(Parent))
{ {
name[len++] = L'\\'; PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
PathNameU.Length += sizeof(WCHAR);
} }
wcscpy(name + len, FileToFind); RtlAppendUnicodeStringToString(&PathNameU, FileToFindU);
rcFcb = vfatGrabFCBFromTable(DeviceExt, name); PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
if (rcFcb) if (rcFcb)
{ {
if(rcFcb->startIndex >= DirIndex) if(rcFcb->startIndex >= DirContext->DirIndex)
{ {
wcscpy(Fcb->PathName, name); RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
Fcb->ObjectName = &Fcb->PathName[len]; RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
memcpy(&Fcb->entry, &rcFcb->entry, sizeof(FATDirEntry)); memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
if (pDirIndex) DirContext->StartIndex = rcFcb->startIndex;
{ DirContext->DirIndex = rcFcb->dirIndex;
*pDirIndex = rcFcb->dirIndex; DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
} &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
if (pDirIndex2) Status = STATUS_SUCCESS;
{
*pDirIndex2 = rcFcb->startIndex;
}
DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d (%d)\n",Fcb->PathName, Fcb->ObjectName, rcFcb->dirIndex, rcFcb->startIndex);
vfatReleaseFCB(DeviceExt, rcFcb);
return STATUS_SUCCESS;
} }
else else
{ {
vfatReleaseFCB(DeviceExt, rcFcb); CHECKPOINT1;
return STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
} }
vfatReleaseFCB(DeviceExt, rcFcb); vfatReleaseFCB(DeviceExt, rcFcb);
return Status;
} }
} }
while(TRUE) while(TRUE)
{ {
Status = vfatGetNextDirEntry(&Context, &Page, Parent, &DirIndex, name, &fatDirEntry, pDirIndex2); Status = vfatGetNextDirEntry(&Context, &Page, Parent, DirContext, First);
First = FALSE;
if (Status == STATUS_NO_MORE_ENTRIES) if (Status == STATUS_NO_MORE_ENTRIES)
{ {
break; break;
} }
if (vfatIsDirEntryVolume(&fatDirEntry)) if (ENTRY_VOLUME(&DirContext->FatDirEntry))
{ {
DirIndex++; DirContext->DirIndex++;
continue; continue;
} }
vfat8Dot3ToString(&fatDirEntry, name2); DirContext->LongNameU.Buffer[DirContext->LongNameU.Length / sizeof(WCHAR)] = 0;
if (wstrcmpjoki (name, FileToFind) || wstrcmpjoki (name2, FileToFind)) DirContext->ShortNameU.Buffer[DirContext->ShortNameU.Length / sizeof(WCHAR)] = 0;
if (WildCard)
{ {
if (Parent && Parent->PathName) /* FIXME: Use FsRtlIsNameInExpression */
if (DirContext->LongNameU.Length > 0 &&
wstrcmpjoki (DirContext->LongNameU.Buffer, FileToFindU->Buffer))
{ {
len = wcslen(Parent->PathName); FoundLong = TRUE;
CHECKPOINT; }
memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR)); else
Fcb->ObjectName=&Fcb->PathName[len];
if (len != 1 || Fcb->PathName[0] != '\\')
{ {
Fcb->ObjectName[0] = '\\'; FoundLong = FALSE;
Fcb->ObjectName = &Fcb->ObjectName[1]; }
if (FoundLong == FALSE)
{
/* FIXME: Use FsRtlIsNameInExpression */
FoundShort = wstrcmpjoki (DirContext->ShortNameU.Buffer, FileToFindU->Buffer);
}
else
{
FoundShort = FALSE;
} }
} }
else else
{ {
Fcb->ObjectName=Fcb->PathName; FoundLong = RtlEqualUnicodeString(&DirContext->LongNameU, FileToFindU, TRUE);
Fcb->ObjectName[0]='\\'; if (FoundLong == FALSE)
Fcb->ObjectName=&Fcb->ObjectName[1]; {
FoundShort = RtlEqualUnicodeString(&DirContext->ShortNameU, FileToFindU, TRUE);
} }
memcpy(&Fcb->entry, &fatDirEntry, sizeof(FATDirEntry)); }
wcsncpy(Fcb->ObjectName, *name == 0 ? name2 : name, MAX_PATH);
if (pDirIndex) if (FoundLong || FoundShort)
*pDirIndex = DirIndex; {
DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb->PathName, Fcb->ObjectName, DirIndex); if (WildCard)
{
RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
if (!vfatFCBIsRoot(Parent))
{
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
PathNameU.Length += sizeof(WCHAR);
}
RtlAppendUnicodeStringToString(&PathNameU, &DirContext->LongNameU);
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
if (rcFcb != NULL)
{
memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
vfatReleaseFCB(DeviceExt, rcFcb);
}
}
DPRINT("%d\n", DirContext->LongNameU.Length);
DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
&DirContext->LongNameU, DirContext->DirIndex);
if (Context) if (Context)
{
CcUnpinData(Context); CcUnpinData(Context);
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
DirIndex++; DirContext->DirIndex++;
} }
if (pDirIndex)
*pDirIndex = DirIndex;
if (Context) if (Context)
{
CcUnpinData(Context); CcUnpinData(Context);
return (STATUS_UNSUCCESSFUL);
} }
NTSTATUS return Status;
vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject,
PWSTR pRelativeFileName,
PWSTR *pAbsoluteFilename)
{
PWSTR rcName;
PVFATFCB fcb;
DPRINT ("try related for %S\n", pRelativeFileName);
fcb = pFileObject->FsContext;
assert (fcb);
/* verify related object is a directory and target name
don't start with \. */
if (!(fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|| (pRelativeFileName[0] == L'\\'))
{
return STATUS_INVALID_PARAMETER;
}
/* construct absolute path name */
assert (wcslen (fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
<= MAX_PATH);
rcName = ExAllocatePool (NonPagedPool, MAX_PATH * sizeof(WCHAR));
if (!rcName)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
wcscpy (rcName, fcb->PathName);
if (!vfatFCBIsRoot(fcb))
wcscat (rcName, L"\\");
wcscat (rcName, pRelativeFileName);
*pAbsoluteFilename = rcName;
return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
PWSTR FileName) PUNICODE_STRING FileNameU)
/* /*
* FUNCTION: Opens a file * FUNCTION: Opens a file
*/ */
@ -405,34 +339,40 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
PVFATFCB ParentFcb; PVFATFCB ParentFcb;
PVFATFCB Fcb; PVFATFCB Fcb;
NTSTATUS Status; NTSTATUS Status;
PWSTR AbsFileName = NULL; UNICODE_STRING NameU;
WCHAR Name[MAX_PATH];
DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName); DPRINT ("VfatOpenFile(%08lx, %08lx, '%wZ')\n", DeviceExt, FileObject, FileNameU);
if (FileObject->RelatedFileObject) if (FileObject->RelatedFileObject)
{ {
DPRINT ("Converting relative filename to absolute filename\n"); DPRINT ("Converting relative filename to absolute filename\n");
Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
FileName, NameU.Buffer = Name;
&AbsFileName); NameU.Length = 0;
FileName = AbsFileName; NameU.MaximumLength = sizeof(Name);
if (!NT_SUCCESS(Status))
Fcb = FileObject->RelatedFileObject->FsContext;
RtlCopyUnicodeString(&NameU, &Fcb->PathNameU);
if (!vfatFCBIsRoot(Fcb))
{ {
return Status; NameU.Buffer[NameU.Length / sizeof(WCHAR)] = L'\\';
NameU.Length += sizeof(WCHAR);
} }
RtlAppendUnicodeStringToString(&NameU, FileNameU);
NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
FileNameU = &NameU;
} }
//FIXME: Get cannonical path name (remove .'s, ..'s and extra separators) DPRINT ("PathName to open: '%wZ'\n", FileNameU);
DPRINT ("PathName to open: %S\n", FileName);
/* try first to find an existing FCB in memory */ /* try first to find an existing FCB in memory */
DPRINT ("Checking for existing FCB in memory\n"); DPRINT ("Checking for existing FCB in memory\n");
Fcb = vfatGrabFCBFromTable (DeviceExt, FileName); Fcb = vfatGrabFCBFromTable (DeviceExt, FileNameU);
if (Fcb == NULL) if (Fcb == NULL)
{ {
DPRINT ("No existing FCB found, making a new one if file exists.\n"); DPRINT ("No existing FCB found, making a new one if file exists.\n");
Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName); Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileNameU);
if (ParentFcb != NULL) if (ParentFcb != NULL)
{ {
vfatReleaseFCB (DeviceExt, ParentFcb); vfatReleaseFCB (DeviceExt, ParentFcb);
@ -440,26 +380,17 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
if (!NT_SUCCESS (Status)) if (!NT_SUCCESS (Status))
{ {
DPRINT ("Could not make a new FCB, status: %x\n", Status); DPRINT ("Could not make a new FCB, status: %x\n", Status);
if (AbsFileName)
ExFreePool (AbsFileName);
return Status; return Status;
} }
} }
if (Fcb->Flags & FCB_DELETE_PENDING) if (Fcb->Flags & FCB_DELETE_PENDING)
{ {
vfatReleaseFCB (DeviceExt, Fcb); vfatReleaseFCB (DeviceExt, Fcb);
if (AbsFileName)
ExFreePool (AbsFileName);
return STATUS_DELETE_PENDING; return STATUS_DELETE_PENDING;
} }
DPRINT ("Attaching FCB to fileObject\n"); DPRINT ("Attaching FCB to fileObject\n");
Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject); Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
if (AbsFileName)
ExFreePool (AbsFileName);
return Status; return Status;
} }
@ -481,7 +412,7 @@ VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
} }
Fcb->entry.FirstCluster = 0; Fcb->entry.FirstCluster = 0;
Fcb->entry.FirstClusterHigh = 0; Fcb->entry.FirstClusterHigh = 0;
VfatUpdateEntry (DeviceExt, FileObject); VfatUpdateEntry (Fcb);
if (Fcb->RFCB.FileSize.QuadPart > 0) if (Fcb->RFCB.FileSize.QuadPart > 0)
{ {
Fcb->RFCB.AllocationSize.QuadPart = 0; Fcb->RFCB.AllocationSize.QuadPart = 0;
@ -569,20 +500,17 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/* /*
* Check for illegal characters in the file name * Check for illegal characters in the file name
*/ */
c = FileObject->FileName.Buffer; c = FileObject->FileName.Buffer + FileObject->FileName.Length / sizeof(WCHAR);
while (*c != 0) while (c-- > FileObject->FileName.Buffer)
{ {
if (*c == L'*' || *c == L'?' || *c == L'<' || *c == L'>' || if (*c != '\\' && vfatIsLongIllegal(*c))
*c == L'/' || *c == L'|' || *c == L':' || *c == L'"' ||
(*c == L'\\' && c[1] == L'\\'))
{ {
return(STATUS_OBJECT_NAME_INVALID); return(STATUS_OBJECT_NAME_INVALID);
} }
c++;
} }
/* Try opening the file. */ /* Try opening the file. */
Status = VfatOpenFile (DeviceExt, FileObject, FileObject->FileName.Buffer); Status = VfatOpenFile (DeviceExt, FileObject, &FileObject->FileName);
/* /*
* If the directory containing the file to open doesn't exist then * If the directory containing the file to open doesn't exist then
@ -607,7 +535,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{ {
ULONG Attributes; ULONG Attributes;
Attributes = Stack->Parameters.Create.FileAttributes; Attributes = Stack->Parameters.Create.FileAttributes;
Status = VfatAddEntry (DeviceExt, FileObject, RequestedOptions, Status = VfatAddEntry (DeviceExt, &FileObject->FileName, FileObject, RequestedOptions,
(UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS)); (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
if (NT_SUCCESS (Status)) if (NT_SUCCESS (Status))
{ {

View file

@ -1,9 +1,9 @@
/* /*
* $Id: dir.c,v 1.31 2003/08/07 11:47:32 silverblade Exp $ * $Id: dir.c,v 1.32 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/dir.c * FILE: drivers/fs/vfat/dir.c
* PURPOSE: VFAT Filesystem : directory control * PURPOSE: VFAT Filesystem : directory control
* UPDATE HISTORY: * UPDATE HISTORY:
19-12-1998 : created 19-12-1998 : created
@ -78,118 +78,106 @@ FsdFileTimeToDosDateTime (TIME * FileTime, WORD * pwDosDate, WORD * pwDosTime)
#define DWORD_ROUND_UP(x) ROUND_UP((x), (sizeof(DWORD))) #define DWORD_ROUND_UP(x) ROUND_UP((x), (sizeof(DWORD)))
NTSTATUS NTSTATUS
VfatGetFileNameInformation (PVFATFCB pFcb, VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength) PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
{ {
ULONG Length; if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length; pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset = pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length); DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, pFcb->ObjectName, Length); memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
VfatGetFileDirectoryInformation (PVFATFCB pFcb, VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
PFILE_DIRECTORY_INFORMATION pInfo, PFILE_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength) ULONG BufferLength)
{ {
ULONG Length; if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length; pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset = pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length); DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, pFcb->ObjectName, Length); memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=; // pInfo->FileIndex=;
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
pFcb->entry.CreationTime, &pInfo->CreationTime); DirContext->FatDirEntry.CreationTime, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate, 0,
&pInfo->LastAccessTime); &pInfo->LastAccessTime);
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
&pInfo->LastWriteTime); DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime; pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0; pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize; pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */ /* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0; pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster); pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = pFcb->entry.Attrib; pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
VfatGetFileFullDirectoryInformation (PVFATFCB pFcb, VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
PFILE_FULL_DIRECTORY_INFORMATION pInfo, PFILE_FULL_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength) ULONG BufferLength)
{ {
ULONG Length; if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length; pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset = pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length); DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, pFcb->ObjectName, Length); memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=; // pInfo->FileIndex=;
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
pFcb->entry.CreationTime, &pInfo->CreationTime); DirContext->FatDirEntry.CreationTime, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate,
&pInfo->LastAccessTime); 0, &pInfo->LastAccessTime);
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
&pInfo->LastWriteTime); DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime; pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0; pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize; pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */ /* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0; pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster); pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = pFcb->entry.Attrib; pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
// pInfo->EaSize=; // pInfo->EaSize=;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
VfatGetFileBothInformation (PVFATFCB pFcb, VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
PFILE_BOTH_DIRECTORY_INFORMATION pInfo, PFILE_BOTH_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength) ULONG BufferLength)
{ {
ULONG Length; if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length; pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset = pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length); DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
/* memcpy(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length);
* vfatGetDirEntryName must be called befor the long name is copyed. pInfo->ShortNameLength = DirContext->ShortNameU.Length;
* The terminating null will overwrite the first character from long name. memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
*/
vfatGetDirEntryName(&pFcb->entry, pInfo->ShortName);
pInfo->ShortNameLength = wcslen(pInfo->ShortName) * sizeof(WCHAR);
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
// pInfo->FileIndex=; // pInfo->FileIndex=;
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
pFcb->entry.CreationTime, &pInfo->CreationTime); DirContext->FatDirEntry.CreationDate, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate, 0,
&pInfo->LastAccessTime); &pInfo->LastAccessTime);
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
&pInfo->LastWriteTime); DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime; pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0; pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize; pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */ /* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0; pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster); pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = pFcb->entry.Attrib; pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
// pInfo->EaSize=; // pInfo->EaSize=;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -204,101 +192,131 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
unsigned char *Buffer = NULL; unsigned char *Buffer = NULL;
PFILE_NAMES_INFORMATION Buffer0 = NULL; PFILE_NAMES_INFORMATION Buffer0 = NULL;
PVFATFCB pFcb; PVFATFCB pFcb;
VFATFCB tmpFcb;
PVFATCCB pCcb; PVFATCCB pCcb;
BOOLEAN First = FALSE; BOOLEAN First = FALSE;
BOOLEAN FirstCall;
VFAT_DIRENTRY_CONTEXT DirContext;
WCHAR LongNameBuffer[MAX_PATH];
WCHAR ShortNameBuffer[13];
PEXTENDED_IO_STACK_LOCATION Stack = (PEXTENDED_IO_STACK_LOCATION) IrpContext->Stack; PEXTENDED_IO_STACK_LOCATION Stack = (PEXTENDED_IO_STACK_LOCATION) IrpContext->Stack;
pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2; pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
pFcb = (PVFATFCB) IrpContext->FileObject->FsContext; pFcb = (PVFATFCB) IrpContext->FileObject->FsContext;
// determine Buffer for result :
BufferLength = Stack->Parameters.QueryDirectory.Length;
if (IrpContext->Irp->RequestorMode != KernelMode &&
IrpContext->Irp->MdlAddress == NULL &&
IrpContext->Irp->UserBuffer != NULL)
{
ProbeForWrite(IrpContext->Irp->UserBuffer, BufferLength, 1);
}
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!ExAcquireResourceSharedLite(&pFcb->MainResource, if (!ExAcquireResourceSharedLite(&pFcb->MainResource,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT))) (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
{ {
return STATUS_PENDING; RC = VfatLockUserBuffer(IrpContext->Irp, BufferLength, IoWriteAccess);
if (NT_SUCCESS(RC))
{
RC = STATUS_PENDING;
}
return RC;
} }
// Obtain the callers parameters /* Obtain the callers parameters */
BufferLength = Stack->Parameters.QueryDirectory.Length;
pSearchPattern = Stack->Parameters.QueryDirectory.FileName; pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
FileInformationClass = FileInformationClass =
Stack->Parameters.QueryDirectory.FileInformationClass; Stack->Parameters.QueryDirectory.FileInformationClass;
FileIndex = Stack->Parameters.QueryDirectory.FileIndex; FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
if (pSearchPattern) if (pSearchPattern)
{ {
if (!pCcb->DirectorySearchPattern) if (!pCcb->SearchPattern.Buffer)
{ {
First = TRUE; First = TRUE;
pCcb->DirectorySearchPattern = pCcb->SearchPattern.MaximumLength = pSearchPattern->Length + sizeof(WCHAR);
ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR)); pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, pCcb->SearchPattern.MaximumLength);
if (!pCcb->DirectorySearchPattern) if (!pCcb->SearchPattern.Buffer)
{ {
ExReleaseResourceLite(&pFcb->MainResource); ExReleaseResourceLite(&pFcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer, RtlCopyUnicodeString(&pCcb->SearchPattern, pSearchPattern);
pSearchPattern->Length); pCcb->SearchPattern.Buffer[pCcb->SearchPattern.Length / sizeof(WCHAR)] = 0;
pCcb->DirectorySearchPattern[pSearchPattern->Length / sizeof(WCHAR)] = 0;
} }
} }
else if (!pCcb->DirectorySearchPattern) else if (!pCcb->SearchPattern.Buffer)
{ {
First = TRUE; First = TRUE;
pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR)); pCcb->SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
if (!pCcb->DirectorySearchPattern) pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
if (!pCcb->SearchPattern.Buffer)
{ {
ExReleaseResourceLite(&pFcb->MainResource); ExReleaseResourceLite(&pFcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
pCcb->DirectorySearchPattern[0] = L'*'; pCcb->SearchPattern.Buffer[0] = L'*';
pCcb->DirectorySearchPattern[1] = 0; pCcb->SearchPattern.Buffer[1] = 0;
pCcb->SearchPattern.Length = sizeof(WCHAR);
} }
if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED) if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED)
{ {
pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart; DirContext.DirIndex = pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart;
FirstCall = TRUE;
} }
else if (First || (IrpContext->Stack->Flags & SL_RESTART_SCAN)) else if (First || (IrpContext->Stack->Flags & SL_RESTART_SCAN))
{ {
pCcb->Entry = 0; DirContext.DirIndex = pCcb->Entry = 0;
} FirstCall = TRUE;
// determine Buffer for result :
if (IrpContext->Irp->MdlAddress)
{
Buffer = MmGetSystemAddressForMdl (IrpContext->Irp->MdlAddress);
} }
else else
{ {
Buffer = IrpContext->Irp->UserBuffer; DirContext.DirIndex = pCcb->Entry;
FirstCall = FALSE;
} }
DPRINT ("Buffer=%x tofind=%S\n", Buffer, pCcb->DirectorySearchPattern);
tmpFcb.ObjectName = tmpFcb.PathName; DPRINT ("Buffer=%x tofind=%wZ\n", Buffer, &pCcb->SearchPattern);
DirContext.LongNameU.Buffer = LongNameBuffer;
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
while (RC == STATUS_SUCCESS && BufferLength > 0) while (RC == STATUS_SUCCESS && BufferLength > 0)
{ {
RC = FindFile (IrpContext->DeviceExt, &tmpFcb, pFcb, RC = FindFile (IrpContext->DeviceExt, pFcb,
pCcb->DirectorySearchPattern, &pCcb->Entry, NULL); &pCcb->SearchPattern, &DirContext, FirstCall);
DPRINT ("Found %S, RC=%x, entry %x\n", tmpFcb.ObjectName, RC, pCcb->Entry); pCcb->Entry = DirContext.DirIndex;
DPRINT ("Found %wZ, RC=%x, entry %x\n", &DirContext.LongNameU, RC, pCcb->Entry);
FirstCall = FALSE;
if (NT_SUCCESS (RC)) if (NT_SUCCESS (RC))
{ {
switch (FileInformationClass) switch (FileInformationClass)
{ {
case FileNameInformation: case FileNameInformation:
RC = VfatGetFileNameInformation (&tmpFcb, RC = VfatGetFileNameInformation (&DirContext,
(PFILE_NAMES_INFORMATION) Buffer, BufferLength); (PFILE_NAMES_INFORMATION) Buffer,
BufferLength);
break; break;
case FileDirectoryInformation: case FileDirectoryInformation:
RC = VfatGetFileDirectoryInformation (&tmpFcb, IrpContext->DeviceExt, RC = VfatGetFileDirectoryInformation (&DirContext,
(PFILE_DIRECTORY_INFORMATION) Buffer, BufferLength); IrpContext->DeviceExt,
(PFILE_DIRECTORY_INFORMATION) Buffer,
BufferLength);
break; break;
case FileFullDirectoryInformation: case FileFullDirectoryInformation:
RC = VfatGetFileFullDirectoryInformation (&tmpFcb, IrpContext->DeviceExt, RC = VfatGetFileFullDirectoryInformation (&DirContext,
(PFILE_FULL_DIRECTORY_INFORMATION) Buffer, BufferLength); IrpContext->DeviceExt,
(PFILE_FULL_DIRECTORY_INFORMATION) Buffer,
BufferLength);
break; break;
case FileBothDirectoryInformation: case FileBothDirectoryInformation:
RC = VfatGetFileBothInformation (&tmpFcb, IrpContext->DeviceExt, RC = VfatGetFileBothInformation (&DirContext,
(PFILE_BOTH_DIRECTORY_INFORMATION) Buffer, BufferLength); IrpContext->DeviceExt,
(PFILE_BOTH_DIRECTORY_INFORMATION) Buffer,
BufferLength);
break; break;
default: default:
RC = STATUS_INVALID_INFO_CLASS; RC = STATUS_INVALID_INFO_CLASS;
@ -330,7 +348,7 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
} }
Buffer0 = (PFILE_NAMES_INFORMATION) Buffer; Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
Buffer0->FileIndex = FileIndex++; Buffer0->FileIndex = FileIndex++;
pCcb->Entry++; pCcb->Entry = ++DirContext.DirIndex;
if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY) if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
{ {
break; break;

View file

@ -1,4 +1,4 @@
/* $Id: direntry.c,v 1.14 2003/07/24 20:52:58 chorns Exp $ /* $Id: direntry.c,v 1.15 2003/10/11 17:51:56 hbirr Exp $
* *
* *
* FILE: DirEntry.c * FILE: DirEntry.c
@ -7,6 +7,7 @@
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Rex Jolliff (rex@lvcablemodem.com) * Rex Jolliff (rex@lvcablemodem.com)
* Hartmut Birr
*/ */
/* ------------------------------------------------------- INCLUDES */ /* ------------------------------------------------------- INCLUDES */
@ -41,44 +42,64 @@ vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
return cluster; return cluster;
} }
BOOL BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry)
{ {
return pFatDirEntry->Filename [0] == 0xe5; LARGE_INTEGER FileOffset;
PVOID Context = NULL;
PFAT_DIR_ENTRY FatDirEntry;
ULONG Index, MaxIndex;
if (vfatFCBIsRoot(Fcb))
{
Index = 0;
}
else
{
Index = 2;
} }
BOOL FileOffset.QuadPart = 0LL;
vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry) MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY);
{
return pFatDirEntry->Filename [0] == 0;
}
BOOL while (Index < MaxIndex)
vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry)
{ {
return pFatDirEntry->Attrib == 0x0f; if (Context == NULL || (Index % ENTRIES_PER_PAGE) == 0)
}
BOOL
vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry)
{ {
return 0x08 == (pFatDirEntry->Attrib & 0x1f); if (Context != NULL)
}
void
vfatGetDirEntryName (PFAT_DIR_ENTRY dirEntry, PWSTR entryName)
{ {
vfat8Dot3ToString (dirEntry, entryName); CcUnpinData(Context);
}
if (!CcMapData(Fcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&FatDirEntry))
{
return TRUE;
}
FatDirEntry += Index % ENTRIES_PER_PAGE;
}
if (ENTRY_END(FatDirEntry))
{
CcUnpinData(Context);
return TRUE;
}
if (!ENTRY_DELETED(FatDirEntry))
{
CcUnpinData(Context);
return FALSE;
}
Index++;
FatDirEntry++;
}
if (Context)
{
CcUnpinData(Context);
}
return TRUE;
} }
NTSTATUS vfatGetNextDirEntry(PVOID * pContext, NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
PVOID * pPage, PVOID * pPage,
IN PVFATFCB pDirFcb, IN PVFATFCB pDirFcb,
IN OUT PULONG pDirIndex, PVFAT_DIRENTRY_CONTEXT DirContext,
OUT PWSTR pFileName, BOOLEAN First)
OUT PFAT_DIR_ENTRY pDirEntry,
OUT PULONG pStartIndex)
{ {
ULONG dirMap; ULONG dirMap;
PWCHAR pName; PWCHAR pName;
@ -87,12 +108,17 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
slot * longNameEntry; slot * longNameEntry;
ULONG index; ULONG index;
*pFileName = 0; UCHAR CheckSum, shortCheckSum;
USHORT i;
BOOLEAN Valid = TRUE;
BOOLEAN Back = FALSE;
DirContext->LongNameU.Buffer[0] = 0;
FileOffset.u.HighPart = 0; FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = ROUND_DOWN(*pDirIndex * sizeof(FATDirEntry), PAGE_SIZE); FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FATDirEntry), PAGE_SIZE);
if (*pContext == NULL || (*pDirIndex % ENTRIES_PER_PAGE) == 0) if (*pContext == NULL || (DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
{ {
if (*pContext != NULL) if (*pContext != NULL)
{ {
@ -106,66 +132,48 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
} }
fatDirEntry = (FATDirEntry*)(*pPage) + *pDirIndex % ENTRIES_PER_PAGE; fatDirEntry = (FATDirEntry*)(*pPage) + DirContext->DirIndex % ENTRIES_PER_PAGE;
longNameEntry = (slot*) fatDirEntry; longNameEntry = (slot*) fatDirEntry;
dirMap = 0; dirMap = 0;
if (pStartIndex) if (First)
{ {
*pStartIndex = *pDirIndex; /* This is the first call to vfatGetNextDirEntry. Possible the start index points
} * into a long name or points to a short name with an assigned long name.
* We must go back to the real start of the entry */
while (TRUE) while (DirContext->DirIndex > 0 &&
!ENTRY_END(fatDirEntry) &&
!ENTRY_DELETED(fatDirEntry) &&
((!ENTRY_LONG(fatDirEntry) && !Back) ||
(ENTRY_LONG(fatDirEntry) && !(longNameEntry->id & 0x40))))
{ {
if (vfatIsDirEntryEndMarker(fatDirEntry)) DirContext->DirIndex--;
Back = TRUE;
if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == ENTRIES_PER_PAGE - 1)
{ {
CcUnpinData(*pContext); CcUnpinData(*pContext);
FileOffset.u.LowPart -= PAGE_SIZE;
if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
{
CHECKPOINT;
*pContext = NULL; *pContext = NULL;
return STATUS_NO_MORE_ENTRIES; return STATUS_NO_MORE_ENTRIES;
} }
fatDirEntry = (FATDirEntry*)(*pPage) + DirContext->DirIndex % ENTRIES_PER_PAGE;
if (vfatIsDirEntryDeleted (fatDirEntry)) longNameEntry = (slot*) fatDirEntry;
{
dirMap = 0;
*pFileName = 0;
if (pStartIndex)
{
*pStartIndex = *pDirIndex + 1;
}
} }
else else
{ {
if (vfatIsDirEntryLongName (fatDirEntry)) fatDirEntry--;
longNameEntry--;
}
}
if (!ENTRY_END(fatDirEntry) &&
(ENTRY_DELETED(fatDirEntry) || !ENTRY_LONG(fatDirEntry)))
{ {
if (dirMap == 0) DirContext->DirIndex++;
{ if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
DPRINT (" long name entry found at %d\n", *pDirIndex);
memset(pFileName, 0, 256 * sizeof(WCHAR));
}
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
5, longNameEntry->name0_4,
6, longNameEntry->name5_10,
2, longNameEntry->name11_12);
index = (longNameEntry->id & 0x1f) - 1;
dirMap |= 1 << index;
pName = pFileName + 13 * index;
memcpy(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR));
memcpy(pName + 5, longNameEntry->name5_10, 6 * sizeof(WCHAR));
memcpy(pName + 11, longNameEntry->name11_12, 2 * sizeof(WCHAR));
DPRINT (" longName: [%S]\n", pFileName);
}
else
{
memcpy (pDirEntry, fatDirEntry, sizeof (FAT_DIR_ENTRY));
break;
}
}
(*pDirIndex)++;
if ((*pDirIndex % ENTRIES_PER_PAGE) == 0)
{ {
CcUnpinData(*pContext); CcUnpinData(*pContext);
FileOffset.u.LowPart += PAGE_SIZE; FileOffset.u.LowPart += PAGE_SIZE;
@ -184,6 +192,109 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
longNameEntry++; longNameEntry++;
} }
} }
}
DirContext->StartIndex = DirContext->DirIndex;
CheckSum = 0;
while (TRUE)
{
if (ENTRY_END(fatDirEntry))
{
CcUnpinData(*pContext);
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
if (ENTRY_DELETED(fatDirEntry))
{
dirMap = 0;
DirContext->LongNameU.Buffer[0] = 0;
DirContext->StartIndex = DirContext->DirIndex + 1;
}
else
{
if (ENTRY_LONG(fatDirEntry))
{
if (dirMap == 0)
{
DPRINT (" long name entry found at %d\n", DirContext->DirIndex);
memset(DirContext->LongNameU.Buffer, 0, DirContext->LongNameU.MaximumLength);
CheckSum = longNameEntry->alias_checksum;
Valid = TRUE;
}
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
5, longNameEntry->name0_4,
6, longNameEntry->name5_10,
2, longNameEntry->name11_12);
index = (longNameEntry->id & 0x1f) - 1;
dirMap |= 1 << index;
pName = DirContext->LongNameU.Buffer + 13 * index;
memcpy(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR));
memcpy(pName + 5, longNameEntry->name5_10, 6 * sizeof(WCHAR));
memcpy(pName + 11, longNameEntry->name11_12, 2 * sizeof(WCHAR));
DPRINT (" longName: [%S]\n", DirContext->LongNameU.Buffer);
if (CheckSum != longNameEntry->alias_checksum)
{
DPRINT1("Found wrong alias checksum in long name entry (first %x, current %x, %S)\n",
CheckSum, longNameEntry->alias_checksum, DirContext->LongNameU.Buffer);
Valid = FALSE;
}
}
else
{
shortCheckSum = 0;
for (i = 0; i < 11; i++)
{
shortCheckSum = (((shortCheckSum & 1) << 7)
| ((shortCheckSum & 0xfe) >> 1))
+ fatDirEntry->Filename[i];
}
if (shortCheckSum != CheckSum && DirContext->LongNameU.Buffer[0])
{
DPRINT1("Checksum from long and short name is not equal (short: %x, long: %x, %S)\n",
shortCheckSum, CheckSum, DirContext->LongNameU.Buffer);
DirContext->LongNameU.Buffer[0] = 0;
}
if (Valid == FALSE)
{
DirContext->LongNameU.Buffer[0] = 0;
}
memcpy (&DirContext->FatDirEntry, fatDirEntry, sizeof (FAT_DIR_ENTRY));
break;
}
}
DirContext->DirIndex++;
if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
{
CcUnpinData(*pContext);
FileOffset.u.LowPart += PAGE_SIZE;
if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
{
CHECKPOINT;
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
fatDirEntry = (FATDirEntry*)*pPage;
longNameEntry = (slot*) *pPage;
}
else
{
fatDirEntry++;
longNameEntry++;
}
}
DirContext->LongNameU.Length = wcslen(DirContext->LongNameU.Buffer) * sizeof(WCHAR);
vfat8Dot3ToString(&DirContext->FatDirEntry, &DirContext->ShortNameU);
if (DirContext->LongNameU.Length == 0)
{
RtlCopyUnicodeString(&DirContext->LongNameU, &DirContext->ShortNameU);
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -1,8 +1,8 @@
/* $Id: dirwr.c,v 1.38 2003/07/24 20:52:58 chorns Exp $ /* $Id: dirwr.c,v 1.39 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/dirwr.c * FILE: drivers/fs/vfat/dirwr.c
* PURPOSE: VFAT Filesystem : write in directory * PURPOSE: VFAT Filesystem : write in directory
* *
*/ */
@ -19,56 +19,41 @@
#include "vfat.h" #include "vfat.h"
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;
}
NTSTATUS NTSTATUS
VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) VfatUpdateEntry (PVFATFCB pFcb)
/* /*
* update an existing FAT entry * update an existing FAT entry
*/ */
{ {
PVOID Context; PVOID Context;
PVOID Buffer; PFAT_DIR_ENTRY PinEntry;
PVFATFCB pDirFcb, pFcb;
LARGE_INTEGER Offset; LARGE_INTEGER Offset;
/*
DPRINT ("updEntry PathFileName \'%S\'\n",
((PVFATCCB)(pFileObject->FsContext2))->pFcb->PathName);
*/
pFcb = (PVFATFCB)pFileObject->FsContext;
assert (pFcb); assert (pFcb);
pDirFcb = pFcb->parentFcb; assert (pFcb->parentFcb);
assert (pDirFcb);
DPRINT ("updEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
Offset.u.HighPart = 0; Offset.u.HighPart = 0;
Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry); Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry);
if (CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry), if (CcMapData (pFcb->parentFcb->FileObject, &Offset, sizeof(FATDirEntry),
TRUE, &Context, (PVOID*)&Buffer)) TRUE, &Context, (PVOID*)&PinEntry))
{ {
memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry)); pFcb->Flags &= ~FCB_IS_DIRTY;
*PinEntry = pFcb->entry;
CcSetDirtyPinnedData(Context, NULL); CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context); CcUnpinData(Context);
return STATUS_SUCCESS;
} }
else else
DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName); {
DPRINT1 ("Failed write to \'%wZ\'.\n", &pFcb->parentFcb->PathNameU);
return STATUS_SUCCESS; return STATUS_UNSUCCESSFUL;
}
} }
BOOLEAN BOOLEAN
findDirSpace(PDEVICE_EXTENSION DeviceExt, vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
PVFATFCB pDirFcb, PVFATFCB pDirFcb,
ULONG nbSlots, ULONG nbSlots,
PULONG start) PULONG start)
@ -98,11 +83,11 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
TRUE, &Context, (PVOID*)&pFatEntry); TRUE, &Context, (PVOID*)&pFatEntry);
FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster; FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
} }
if (vfatIsDirEntryEndMarker(pFatEntry)) if (ENTRY_END(pFatEntry))
{ {
break; break;
} }
if (vfatIsDirEntryDeleted(pFatEntry)) if (ENTRY_DELETED(pFatEntry))
{ {
nbFree++; nbFree++;
} }
@ -172,6 +157,7 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
NTSTATUS NTSTATUS
VfatAddEntry (PDEVICE_EXTENSION DeviceExt, VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PFILE_OBJECT pFileObject, PFILE_OBJECT pFileObject,
ULONG RequestedOptions, ULONG RequestedOptions,
UCHAR ReqAttr) UCHAR ReqAttr)
@ -179,279 +165,190 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
create a new FAT entry create a new FAT entry
*/ */
{ {
WCHAR DirName[MAX_PATH], *FileName, *PathFileName;
VFATFCB FileFcb;
PVOID Context = NULL; PVOID Context = NULL;
FATDirEntry *pFatEntry, *pEntry; FATDirEntry *pFatEntry;
slot *pSlots; slot *pSlots;
short nbSlots = 0, nbFree = 0, j, posCar, NameLen; short nbSlots = 0, j, posCar;
PUCHAR Buffer; PUCHAR Buffer;
BOOLEAN needTilde = FALSE, needLong = FALSE; BOOLEAN needTilde = FALSE, needLong = FALSE;
BOOLEAN lCaseBase, uCaseBase, lCaseExt, uCaseExt; BOOLEAN lCaseBase = FALSE, uCaseBase, lCaseExt = FALSE, uCaseExt;
PVFATFCB newFCB; PVFATFCB newFCB;
ULONG CurrentCluster; ULONG CurrentCluster;
LARGE_INTEGER SystemTime, LocalTime, FileOffset; LARGE_INTEGER SystemTime, LocalTime, FileOffset;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PVFATFCB pDirFcb; PVFATFCB pDirFcb;
ULONG start, size; ULONG size;
long i; long i;
PathFileName = pFileObject->FileName.Buffer; ANSI_STRING NameA;
DPRINT ("addEntry: Pathname=%S\n", PathFileName); CHAR aName[13];
//find last \ in PathFileName BOOLEAN IsNameLegal;
posCar = -1; BOOLEAN SpacesFound;
for (i = 0; PathFileName[i]; i++)
VFAT_DIRENTRY_CONTEXT DirContext;
UNICODE_STRING DirNameU;
WCHAR LongNameBuffer[MAX_PATH];
WCHAR ShortNameBuffer[13];
DPRINT ("addEntry: Pathname='%wZ'\n", PathNameU);
vfatSplitPathName(PathNameU, &DirNameU, &DirContext.LongNameU);
if (DirNameU.Length > sizeof(WCHAR))
{ {
if (PathFileName[i] == L'\\') DirNameU.Length -= sizeof(WCHAR);
{
posCar = (short)i;
} }
}
if (posCar == -1) pDirFcb = vfatGrabFCBFromTable(DeviceExt, &DirNameU);
{
return STATUS_UNSUCCESSFUL;
}
FileName = &PathFileName[posCar + 1];
for (NameLen = 0; FileName[NameLen]; NameLen++);
// extract directory name from pathname
if (posCar == 0)
{
// root dir
DirName[0] = L'\\';
DirName[1] = 0;
}
else
{
memcpy (DirName, PathFileName, posCar * sizeof (WCHAR));
DirName[posCar] = 0;
}
// open parent directory
pDirFcb = vfatGrabFCBFromTable(DeviceExt, DirName);
if (pDirFcb == NULL) if (pDirFcb == NULL)
{ {
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
nbSlots = (NameLen + 12) / 13 + 1; //nb of entry needed for long name+normal entry nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1; //nb of entry needed for long name+normal entry
DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots); DPRINT ("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
Buffer = ExAllocatePool (NonPagedPool, nbSlots * sizeof (FATDirEntry)); Buffer = ExAllocatePool (NonPagedPool, (nbSlots - 1) * sizeof (FATDirEntry));
RtlZeroMemory (Buffer, nbSlots * sizeof (FATDirEntry)); RtlZeroMemory (Buffer, (nbSlots - 1) * sizeof (FATDirEntry));
pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry));
pSlots = (slot *) Buffer; pSlots = (slot *) Buffer;
// create 8.3 name
needTilde = FALSE; NameA.Buffer = aName;
// find last point in name NameA.Length = 0;
posCar = j = 0; NameA.MaximumLength = sizeof(aName);
for (i = 0; FileName[i]; i++)
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
memset(&DirContext.FatDirEntry, 0, sizeof(FATDirEntry));
IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound);
if (IsNameLegal == FALSE || SpacesFound != FALSE)
{ {
if (FileName[i] == '.') GENERATE_NAME_CONTEXT NameContext;
{ VFAT_DIRENTRY_CONTEXT SearchContext;
posCar = (short)i; WCHAR ShortSearchName[13];
if (i == j)
{
j++;
}
}
}
if (!posCar)
{
posCar = (short)i;
}
if (posCar < j)
{
posCar = (short)i;
needTilde = TRUE; needTilde = TRUE;
}
if (posCar > 8)
{
needTilde = TRUE;
}
//copy 8 characters max
memset (pEntry, ' ', 11);
for (i = 0, j = 0; j < 8 && i < posCar; i++)
{
if (vfatIsShortIllegal (FileName[i]))
{
needTilde = TRUE;
pEntry->Filename[j++] = '_';
}
else
{
if (FileName[i] == '.')
{
needTilde = TRUE;
}
else
{
pEntry->Filename[j++] = toupper ((char) FileName[i]);
}
}
}
//copy extension
if (FileName[posCar])
{
for (j = 0, i = posCar + 1; FileName[i] && j < 3; i++)
{
if (vfatIsShortIllegal(FileName[i]))
{
needTilde = TRUE;
pEntry->Ext[j++] = '_';
}
else
{
if (FileName[i] == '.')
{
needTilde = TRUE;
}
else
{
pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F));
}
}
}
}
if (FileName[i])
{
needTilde = TRUE;
}
//find good value for tilde
if (needTilde)
{
needLong = TRUE; needLong = TRUE;
DPRINT ("searching a good value for tilde\n"); memset(&NameContext, 0, sizeof(GENERATE_NAME_CONTEXT));
for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++); SearchContext.LongNameU.Buffer = LongNameBuffer;
if (posCar == 0) // ?????????????????????? SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
SearchContext.ShortNameU.Buffer = ShortSearchName;
SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);
for (i = 0; i < 100; i++)
{ {
pEntry->Filename[posCar++] = '_'; RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU);
} DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
posCar += 2; SearchContext.DirIndex = 0;
if (posCar > 8) Status = FindFile (DeviceExt, pDirFcb, &DirContext.ShortNameU, &SearchContext, TRUE);
{
posCar = 8;
}
pEntry->Filename[posCar - 2] = '~';
pEntry->Filename[posCar - 1] = '1';
vfat8Dot3ToString (pEntry, DirName);
//try first with xxxxxx~y.zzz
for (i = 1; i < 10; i++)
{
DirName[posCar-1] = (WCHAR)('0' + i);
pEntry->Filename[posCar - 1] = (unsigned char)('0' + i);
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
break; break;
} }
} }
if (i == 10) if (i == 100) /* FIXME : what to do after this ? */
{
posCar++;
if (posCar > 8)
{
posCar = 8;
}
pEntry->Filename[posCar - 3] = '~';
pEntry->Filename[posCar - 2] = '1';
pEntry->Filename[posCar - 1] = '0';
vfat8Dot3ToString (pEntry, DirName);
//try second with xxxxx~yy.zzz
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;
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
if (!NT_SUCCESS(Status))
{
break;
}
}
if (i == 100) //FIXME : what to do after 99 tilde ?
{ {
vfatReleaseFCB(DeviceExt, pDirFcb); vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer); ExFreePool (Buffer);
CHECKPOINT;
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
} IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);
aName[NameA.Length]=0;
} }
else else
{ {
DPRINT ("check if long name entry needed, needlong=%d\n", needLong); aName[NameA.Length] = 0;
lCaseBase = uCaseBase = lCaseExt = uCaseExt = FALSE; for (posCar = 0; posCar < DirContext.LongNameU.Length / sizeof(WCHAR); posCar++)
for (i = 0; i < posCar; i++)
{ {
if ((USHORT) tolower(pEntry->Filename[i]) == FileName[i]) if (DirContext.LongNameU.Buffer[posCar] == L'.')
{ {
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]); break;
lCaseBase = TRUE;
} }
else if ((USHORT) pEntry->Filename[i] == FileName[i]) }
/* check if the name and the extension contains upper case characters */
RtlDowncaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
uCaseBase = wcsncmp(DirContext.LongNameU.Buffer,
DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;
if (posCar < DirContext.LongNameU.Length/sizeof(WCHAR))
{ {
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]); i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
uCaseBase = TRUE; uCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
} }
else else
{ {
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]); uCaseExt = FALSE;
needLong = TRUE;
} }
} /* check if the name and the extension contains lower case characters */
if (FileName[i]) RtlUpcaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
lCaseBase = wcsncmp(DirContext.LongNameU.Buffer,
DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;
if (posCar < DirContext.LongNameU.Length / sizeof(WCHAR))
{ {
i++; //jump on point char i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
for (j = 0, i = posCar + 1; FileName[i] && i < posCar + 4; i++, j++) lCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
{ DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
if ((USHORT) tolower(pEntry->Ext[j]) == FileName[i])
{
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Ext[j], FileName[i]);
lCaseExt = TRUE;
}
else if ((USHORT) pEntry->Ext[j] == FileName[i])
{
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Ext[j], FileName[i]);
uCaseExt = TRUE;
} }
else else
{ {
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Ext[j], FileName[i]); lCaseExt = FALSE;
needLong = TRUE;
}
}
} }
if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt)) if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt))
{ {
CHECKPOINT;
needLong = TRUE; needLong = TRUE;
} }
} }
if (needLong == FALSE) DPRINT ("'%s', '%wZ', needTilde=%d, needLong=%d\n",
aName, &DirContext.LongNameU, needTilde, needLong);
memset(DirContext.FatDirEntry.Filename, ' ', 11);
for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)
{ {
nbSlots = 1; DirContext.FatDirEntry.Filename[i] = aName[i];
memcpy (Buffer, pEntry, sizeof (FATDirEntry));
memset (pEntry, 0, sizeof (FATDirEntry));
pEntry = (FATDirEntry *) Buffer;
if (lCaseBase)
{
pEntry->lCase |= VFAT_CASE_LOWER_BASE;
} }
if (lCaseExt) if (aName[i] == '.')
{ {
pEntry->lCase |= VFAT_CASE_LOWER_EXT; i++;
for (j = 8; j < 11 && aName[i]; j++, i++)
{
DirContext.FatDirEntry.Filename[j] = aName[i];
} }
} }
if (DirContext.FatDirEntry.Filename[0] == 0xe5)
{
DirContext.FatDirEntry.Filename[0] = 0x05;
}
if (needLong)
{
memcpy(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);
DirContext.LongNameU.Buffer = LongNameBuffer;
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1, 0xff,
DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR));
}
else else
{ {
memset (DirName, 0xff, sizeof (DirName)); nbSlots = 1;
memcpy (DirName, FileName, NameLen * sizeof (WCHAR)); if (lCaseBase)
DirName[NameLen] = 0; {
DirContext.FatDirEntry.lCase |= VFAT_CASE_LOWER_BASE;
} }
DPRINT ("dos name=%11.11s\n", pEntry->Filename); if (lCaseExt)
{
DirContext.FatDirEntry.lCase |= VFAT_CASE_LOWER_EXT;
}
}
DPRINT ("dos name=%11.11s\n", DirContext.FatDirEntry.Filename);
/* set attributes */ /* set attributes */
pEntry->Attrib = ReqAttr; DirContext.FatDirEntry.Attrib = ReqAttr;
if (RequestedOptions & FILE_DIRECTORY_FILE) if (RequestedOptions & FILE_DIRECTORY_FILE)
{ {
pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY; DirContext.FatDirEntry.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
} }
/* set dates and times */ /* set dates and times */
KeQuerySystemTime (&SystemTime); KeQuerySystemTime (&SystemTime);
@ -466,22 +363,22 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
pFileObject->FileName.Buffer); pFileObject->FileName.Buffer);
} }
#endif #endif
FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &pEntry->CreationDate, FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &DirContext.FatDirEntry.CreationDate,
&pEntry->CreationTime); &DirContext.FatDirEntry.CreationTime);
pEntry->UpdateDate = pEntry->CreationDate; DirContext.FatDirEntry.UpdateDate = DirContext.FatDirEntry.CreationDate;
pEntry->UpdateTime = pEntry->CreationTime; DirContext.FatDirEntry.UpdateTime = DirContext.FatDirEntry.CreationTime;
pEntry->AccessDate = pEntry->CreationDate; DirContext.FatDirEntry.AccessDate = DirContext.FatDirEntry.CreationDate;
if (needLong) if (needLong)
{ {
// calculate checksum for 8.3 name /* calculate checksum for 8.3 name */
for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++) 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 = (((pSlots[0].alias_checksum & 1) << 7
| ((pSlots[0].alias_checksum & 0xfe) >> 1)) | ((pSlots[0].alias_checksum & 0xfe) >> 1))
+ pEntry->Filename[i]); + DirContext.FatDirEntry.Filename[i]);
} }
//construct slots and entry /* construct slots and entry */
for (i = nbSlots - 2; i >= 0; i--) for (i = nbSlots - 2; i >= 0; i--)
{ {
DPRINT ("construct slot %d\n", i); DPRINT ("construct slot %d\n", i);
@ -495,20 +392,19 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
pSlots[i].id = nbSlots - i - 1 + 0x40; pSlots[i].id = nbSlots - i - 1 + 0x40;
} }
pSlots[i].alias_checksum = pSlots[0].alias_checksum; pSlots[i].alias_checksum = pSlots[0].alias_checksum;
//FIXME pSlots[i].start=; memcpy (pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
memcpy (pSlots[i].name0_4, DirName + (nbSlots - i - 2) * 13, 10); memcpy (pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
memcpy (pSlots[i].name5_10, DirName + (nbSlots - i - 2) * 13 + 5, 12); memcpy (pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
memcpy (pSlots[i].name11_12, DirName + (nbSlots - i - 2) * 13 + 11, 4);
} }
} }
//try to find nbSlots contiguous entries frees in directory /* try to find nbSlots contiguous entries frees in directory */
if (!findDirSpace(DeviceExt, pDirFcb, nbSlots, &start)) if (!vfatFindDirSpace(DeviceExt, pDirFcb, nbSlots, &DirContext.StartIndex))
{ {
vfatReleaseFCB(DeviceExt, pDirFcb); vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer); ExFreePool (Buffer);
return STATUS_DISK_FULL; return STATUS_DISK_FULL;
} }
DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
if (RequestedOptions & FILE_DIRECTORY_FILE) if (RequestedOptions & FILE_DIRECTORY_FILE)
{ {
CurrentCluster = 0xffffffff; CurrentCluster = 0xffffffff;
@ -525,28 +421,33 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
} }
if (DeviceExt->FatInfo.FatType == FAT32) if (DeviceExt->FatInfo.FatType == FAT32)
{ {
pEntry->FirstClusterHigh = (unsigned short)(CurrentCluster >> 16); DirContext.FatDirEntry.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
} }
pEntry->FirstCluster = (unsigned short)CurrentCluster; DirContext.FatDirEntry.FirstCluster = (unsigned short)CurrentCluster;
} }
size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry); i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
FileOffset.u.HighPart = 0; FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = start * sizeof(FATDirEntry); FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FATDirEntry);
if (start / size == (start + nbSlots - 1) / size) if (DirContext.StartIndex / i == DirContext.DirIndex / i)
{ {
// one cluster /* one cluster */
CHECKPOINT; CHECKPOINT;
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry), CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry),
TRUE, &Context, (PVOID*)&pFatEntry); TRUE, &Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, Buffer, nbSlots * sizeof(FATDirEntry)); if (nbSlots > 1)
{
memcpy(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FATDirEntry));
}
memcpy(pFatEntry + (nbSlots - 1), &DirContext.FatDirEntry, sizeof(FATDirEntry));
} }
else else
{ {
// two clusters /* two clusters */
CHECKPOINT; CHECKPOINT;
size = DeviceExt->FatInfo.BytesPerCluster - size = DeviceExt->FatInfo.BytesPerCluster -
(start * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster; (DirContext.StartIndex * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster;
i = size / sizeof(FATDirEntry);
CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE, CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE,
&Context, (PVOID*)&pFatEntry); &Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, Buffer, size); memcpy(pFatEntry, Buffer, size);
@ -556,49 +457,41 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
CcMapData (pDirFcb->FileObject, &FileOffset, CcMapData (pDirFcb->FileObject, &FileOffset,
nbSlots * sizeof(FATDirEntry) - size, nbSlots * sizeof(FATDirEntry) - size,
TRUE, &Context, (PVOID*)&pFatEntry); TRUE, &Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, (PVOID)(Buffer + size), nbSlots * sizeof(FATDirEntry) - size); if (nbSlots - 1 > i)
{
memcpy(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FATDirEntry));
}
memcpy(pFatEntry + nbSlots - 1 - i, &DirContext.FatDirEntry, sizeof(FATDirEntry));
} }
CcSetDirtyPinnedData(Context, NULL); CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context); CcUnpinData(Context);
// FIXME: check status /* FIXME: check status */
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, pEntry, vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, &DirContext, &newFCB);
start, start + nbSlots - 1, &newFCB);
vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject); vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject);
DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename); DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename);
DPRINT ("new : entry=%11.11s\n", pEntry->Filename); DPRINT ("new : entry=%11.11s\n", DirContext.FatDirEntry.Filename);
if (RequestedOptions & FILE_DIRECTORY_FILE) if (RequestedOptions & FILE_DIRECTORY_FILE)
{ {
FileOffset.QuadPart = 0; FileOffset.QuadPart = 0;
CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE, CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
&Context, (PVOID*)&pFatEntry); &Context, (PVOID*)&pFatEntry);
// clear the new directory cluster /* clear the new directory cluster */
RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster); RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
// create '.' and '..' /* create '.' and '..' */
memcpy (&pFatEntry[0].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11); memcpy (&pFatEntry[0].Attrib, &DirContext.FatDirEntry.Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[0].Filename, ". ", 11); memcpy (pFatEntry[0].Filename, ". ", 11);
memcpy (&pFatEntry[1].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11); memcpy (&pFatEntry[1].Attrib, &DirContext.FatDirEntry.Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[1].Filename, ".. ", 11); memcpy (pFatEntry[1].Filename, ".. ", 11);
pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster; pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster;
pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh; pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh;
if (DeviceExt->FatInfo.FatType == FAT32) if (vfatFCBIsRoot(pDirFcb))
{
if (pFatEntry[1].FirstCluster == (DeviceExt->FatInfo.RootCluster & 0xffff) &&
pFatEntry[1].FirstClusterHigh == (DeviceExt->FatInfo.RootCluster >> 16))
{ {
pFatEntry[1].FirstCluster = 0; pFatEntry[1].FirstCluster = 0;
pFatEntry[1].FirstClusterHigh = 0; pFatEntry[1].FirstClusterHigh = 0;
} }
}
else
{
if (pFatEntry[1].FirstCluster == 1)
{
pFatEntry[1].FirstCluster = 0;
}
}
CcSetDirtyPinnedData(Context, NULL); CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context); CcUnpinData(Context);
} }
@ -609,48 +502,23 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
} }
NTSTATUS NTSTATUS
delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
/* /*
* deleting an existing FAT entry * deleting an existing FAT entry
*/ */
{ {
VFATFCB Fcb; ULONG CurrentCluster = 0, NextCluster, i;
PVFATFCB pFcb = NULL, pDirFcb = NULL;
NTSTATUS status;
PWSTR pName;
ULONG Entry = 0, startEntry, CurrentCluster, NextCluster, i;
DPRINT ("delEntry PathFileName \'%S\'\n", pFileObject->FileName.Buffer);
status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb,
pFileObject->FileName.Buffer);
if (pFcb != NULL)
{
vfatReleaseFCB(DeviceExt, pFcb);
}
if (!NT_SUCCESS(status))
{
if (pDirFcb != NULL)
{
vfatReleaseFCB(DeviceExt, pDirFcb);
}
return status;
}
pName = ((PVFATFCB)pFileObject->FsContext)->ObjectName;
if (*pName == L'\\')
{
pName ++;
}
status = FindFile (DeviceExt, &Fcb, pDirFcb, pName, &Entry, &startEntry);
if (NT_SUCCESS(status))
{
PVOID Context = NULL; PVOID Context = NULL;
LARGE_INTEGER Offset; LARGE_INTEGER Offset;
FATDirEntry* pDirEntry; FATDirEntry* pDirEntry;
DPRINT ("delete entry: %d to %d\n", startEntry, Entry);
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; Offset.u.HighPart = 0;
for (i = startEntry; i <= Entry; i++) for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
{ {
if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGE_SIZE) == 0) if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGE_SIZE) == 0)
{ {
@ -660,11 +528,11 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
CcUnpinData(Context); CcUnpinData(Context);
} }
Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGE_SIZE) * PAGE_SIZE; Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGE_SIZE) * PAGE_SIZE;
CcMapData (pDirFcb->FileObject, &Offset, PAGE_SIZE, TRUE, CcMapData (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
&Context, (PVOID*)&pDirEntry); &Context, (PVOID*)&pDirEntry);
} }
pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5; pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5;
if (i == Entry) if (i == pFcb->dirIndex)
{ {
CurrentCluster = CurrentCluster =
vfatDirEntryGetFirstCluster (DeviceExt, vfatDirEntryGetFirstCluster (DeviceExt,
@ -680,13 +548,11 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
while (CurrentCluster && CurrentCluster != 0xffffffff) while (CurrentCluster && CurrentCluster != 0xffffffff)
{ {
GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE); GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE);
// FIXME: check status /* FIXME: check status */
WriteCluster(DeviceExt, CurrentCluster, 0); WriteCluster(DeviceExt, CurrentCluster, 0);
CurrentCluster = NextCluster; CurrentCluster = NextCluster;
} }
} return STATUS_SUCCESS;
vfatReleaseFCB(DeviceExt, pDirFcb);
return status;
} }
/* EOF */ /* EOF */

View file

@ -16,10 +16,10 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: ea.c,v 1.3 2003/07/24 20:52:58 chorns Exp $ /* $Id: ea.c,v 1.4 2003/10/11 17:51:56 hbirr Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/ea.c * FILE: drivers/fs/vfat/ea.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)

View file

@ -1,11 +1,12 @@
/* /*
* $Id: fat.c,v 1.43 2003/07/24 20:52:58 chorns Exp $ * $Id: fat.c,v 1.44 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/fat.c * FILE: drivers/fs/vfat/fat.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
* *
*/ */
@ -143,7 +144,7 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
ULONG ChunkSize; ULONG ChunkSize;
PVOID Context = 0; PVOID Context = 0;
LARGE_INTEGER Offset; LARGE_INTEGER Offset;
PUSHORT Block; PUSHORT Block = NULL;
ChunkSize = CACHEPAGESIZE(DeviceExt); ChunkSize = CACHEPAGESIZE(DeviceExt);
FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2; FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2;
@ -256,7 +257,7 @@ FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
ULONG ChunkSize; ULONG ChunkSize;
PVOID Context = 0; PVOID Context = 0;
LARGE_INTEGER Offset; LARGE_INTEGER Offset;
PULONG Block; PULONG Block = NULL;
ChunkSize = CACHEPAGESIZE(DeviceExt); ChunkSize = CACHEPAGESIZE(DeviceExt);
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4; FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4;
@ -354,7 +355,7 @@ FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
* FUNCTION: Counts free clusters in a FAT16 table * FUNCTION: Counts free clusters in a FAT16 table
*/ */
{ {
PUSHORT Block; PUSHORT Block = NULL;
PVOID BaseAddress = NULL; PVOID BaseAddress = NULL;
ULONG ulCount = 0; ULONG ulCount = 0;
ULONG i; ULONG i;
@ -400,7 +401,7 @@ FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
* FUNCTION: Counts free clusters in a FAT32 table * FUNCTION: Counts free clusters in a FAT32 table
*/ */
{ {
PULONG Block; PULONG Block = NULL;
PVOID BaseAddress = NULL; PVOID BaseAddress = NULL;
ULONG ulCount = 0; ULONG ulCount = 0;
ULONG i; ULONG i;

View file

@ -1,12 +1,13 @@
/* $Id: fcb.c,v 1.33 2003/08/07 11:47:32 silverblade Exp $ /* $Id: fcb.c,v 1.34 2003/10/11 17:51:56 hbirr Exp $
* *
* *
* FILE: fcb.c * FILE: drivers/fs/vfat/fcb.c
* PURPOSE: Routines to manipulate FCBs. * PURPOSE: Routines to manipulate FCBs.
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Rex Jolliff (rex@lvcablemodem.com) * Rex Jolliff (rex@lvcablemodem.com)
* Hartmut Birr
*/ */
/* ------------------------------------------------------- INCLUDES */ /* ------------------------------------------------------- INCLUDES */
@ -30,35 +31,79 @@
/* -------------------------------------------------------- PUBLICS */ /* -------------------------------------------------------- PUBLICS */
ULONG vfatNameHash(ULONG hash, PWCHAR name) ULONG vfatNameHash(ULONG hash, PUNICODE_STRING NameU)
{ {
WCHAR c; PWCHAR last;
while(c = *name++) PWCHAR curr;
register WCHAR c;
curr = NameU->Buffer;
last = NameU->Buffer + NameU->Length / sizeof(WCHAR);
while(curr < last)
{ {
c = towlower(c); c = towlower(*curr++);
hash = (hash + (c << 4) + (c >> 4)) * 11; hash = (hash + (c << 4) + (c >> 4)) * 11;
} }
return hash; return hash;
} }
VOID
vfatSplitPathName(PUNICODE_STRING PathNameU, PUNICODE_STRING DirNameU, PUNICODE_STRING FileNameU)
{
PWCHAR pName;
DirNameU->Buffer = PathNameU->Buffer;
pName = PathNameU->Buffer + PathNameU->Length / sizeof(WCHAR) - 1;
while (*pName != L'\\' && pName > PathNameU->Buffer)
{
pName--;
}
assert(*pName == L'\\');
FileNameU->Buffer = pName + 1;
DirNameU->Length = (FileNameU->Buffer - PathNameU->Buffer) * sizeof(WCHAR);
DirNameU->MaximumLength = DirNameU->Length;
FileNameU->Length = PathNameU->Length - DirNameU->Length;
FileNameU->MaximumLength = FileNameU->Length;
}
VOID
vfatInitFcb(PVFATFCB Fcb, PUNICODE_STRING NameU)
{
Fcb->PathNameU.Length = 0;
Fcb->PathNameU.Buffer = Fcb->PathNameBuffer;
Fcb->PathNameU.MaximumLength = sizeof(Fcb->PathNameBuffer);
Fcb->ShortNameU.Length = 0;
Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
Fcb->ShortNameU.MaximumLength = sizeof(Fcb->ShortNameBuffer);
Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
if (NameU && NameU->Length)
{
RtlCopyUnicodeString(&Fcb->PathNameU, NameU);
vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
}
else
{
Fcb->DirNameU.Buffer = Fcb->LongNameU.Buffer = NULL;
Fcb->DirNameU.MaximumLength = Fcb->DirNameU.Length = 0;
Fcb->LongNameU.MaximumLength = Fcb->LongNameU.Length = 0;
}
}
PVFATFCB PVFATFCB
vfatNewFCB(PWCHAR pFileName) vfatNewFCB(PUNICODE_STRING pFileNameU)
{ {
PVFATFCB rcFCB; PVFATFCB rcFCB;
DPRINT("'%wZ'\n", pFileNameU);
rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList); rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList);
if (rcFCB == NULL)
{
return NULL;
}
memset(rcFCB, 0, sizeof(VFATFCB)); memset(rcFCB, 0, sizeof(VFATFCB));
if (pFileName) vfatInitFcb(rcFCB, pFileNameU);
{ rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
wcscpy (rcFCB->PathName, pFileName);
rcFCB->ObjectName = wcsrchr(rcFCB->PathName, L'\\');
if (rcFCB->ObjectName == NULL)
{
rcFCB->ObjectName = rcFCB->PathName;
}
rcFCB->Hash.Hash = vfatNameHash(0, rcFCB->PathName);
DPRINT("%08x (%03x) '%S'\n", rcFCB->Hash.Hash, rcFCB->Hash.Hash % FCB_HASH_TABLE_SIZE, pFileName);
}
rcFCB->Hash.self = rcFCB; rcFCB->Hash.self = rcFCB;
rcFCB->ShortHash.self = rcFCB; rcFCB->ShortHash.self = rcFCB;
ExInitializeResourceLite(&rcFCB->PagingIoResource); ExInitializeResourceLite(&rcFCB->PagingIoResource);
@ -70,9 +115,9 @@ vfatNewFCB(PWCHAR pFileName)
VOID VOID
vfatDestroyCCB(PVFATCCB pCcb) vfatDestroyCCB(PVFATCCB pCcb)
{ {
if (pCcb->DirectorySearchPattern) if (pCcb->SearchPattern.Buffer)
{ {
ExFreePool(pCcb->DirectorySearchPattern); ExFreePool(pCcb->SearchPattern.Buffer);
} }
ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb); ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb);
} }
@ -95,28 +140,26 @@ vfatFCBIsDirectory(PVFATFCB FCB)
BOOL BOOL
vfatFCBIsRoot(PVFATFCB FCB) vfatFCBIsRoot(PVFATFCB FCB)
{ {
return FCB->PathName[0] == L'\\' && FCB->PathName[1] == 0 ? TRUE : FALSE; return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE;
} }
VOID VOID
vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{ {
KIRQL oldIrql;
HASHENTRY* entry; HASHENTRY* entry;
ULONG Index; ULONG Index;
ULONG ShortIndex; ULONG ShortIndex;
PVFATFCB tmpFcb; PVFATFCB tmpFcb;
DPRINT ("releasing FCB at %x: %S, refCount:%d\n", DPRINT ("releasing FCB at %x: %wZ, refCount:%d\n",
pFCB, pFCB,
pFCB->PathName, &pFCB->PathNameU,
pFCB->RefCount); pFCB->RefCount);
while (pFCB) while (pFCB)
{ {
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE; Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE; ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
pFCB->RefCount--; pFCB->RefCount--;
if (pFCB->RefCount <= 0 && (!vfatFCBIsDirectory (pFCB) || pFCB->Flags & FCB_DELETE_PENDING)) if (pFCB->RefCount <= 0 && (!vfatFCBIsDirectory (pFCB) || pFCB->Flags & FCB_DELETE_PENDING))
{ {
@ -151,7 +194,6 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
} }
entry->next = pFCB->Hash.next; entry->next = pFCB->Hash.next;
} }
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
if (vfatFCBIsDirectory(pFCB)) if (vfatFCBIsDirectory(pFCB))
{ {
/* Uninitialize file cache if initialized for this file object. */ /* Uninitialize file cache if initialized for this file object. */
@ -168,7 +210,6 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
} }
else else
{ {
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
tmpFcb = NULL; tmpFcb = NULL;
} }
pFCB = tmpFcb; pFCB = tmpFcb;
@ -178,13 +219,12 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
VOID VOID
vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{ {
KIRQL oldIrql;
ULONG Index; ULONG Index;
ULONG ShortIndex; ULONG ShortIndex;
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE; Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE; ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry); InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry);
pFCB->Hash.next = pVCB->FcbHashTable[Index]; pFCB->Hash.next = pVCB->FcbHashTable[Index];
@ -198,69 +238,58 @@ vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{ {
pFCB->parentFcb->RefCount++; pFCB->parentFcb->RefCount++;
} }
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
} }
PVFATFCB PVFATFCB
vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PWSTR pFileName) vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PUNICODE_STRING PathNameU)
{ {
KIRQL oldIrql;
PVFATFCB rcFCB; PVFATFCB rcFCB;
ULONG Hash; ULONG Hash;
PWCHAR ObjectName = NULL; UNICODE_STRING DirNameU;
ULONG len; UNICODE_STRING FileNameU;
PUNICODE_STRING FcbNameU;
HASHENTRY* entry; HASHENTRY* entry;
Hash = vfatNameHash(0, pFileName); DPRINT("'%wZ'\n", PathNameU);
Hash = vfatNameHash(0, PathNameU);
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
entry = pVCB->FcbHashTable[Hash % FCB_HASH_TABLE_SIZE]; entry = pVCB->FcbHashTable[Hash % FCB_HASH_TABLE_SIZE];
if (entry)
{
vfatSplitPathName(PathNameU, &DirNameU, &FileNameU);
}
while (entry) while (entry)
{ {
if (entry->Hash == Hash) if (entry->Hash == Hash)
{ {
rcFCB = entry->self; rcFCB = entry->self;
DPRINT("'%wZ' '%wZ'\n", &DirNameU, &rcFCB->DirNameU);
if (RtlEqualUnicodeString(&DirNameU, &rcFCB->DirNameU, TRUE))
{
if (rcFCB->Hash.Hash == Hash) if (rcFCB->Hash.Hash == Hash)
{ {
/* compare the long name */ FcbNameU = &rcFCB->LongNameU;
if (!_wcsicmp(pFileName, rcFCB->PathName))
{
rcFCB->RefCount++;
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
return rcFCB;
}
} }
else else
{ {
len = rcFCB->ObjectName - rcFCB->PathName + 1; FcbNameU = &rcFCB->ShortNameU;
if (ObjectName == NULL)
{
ObjectName = wcsrchr(pFileName, L'\\');
if (ObjectName == NULL)
{
ObjectName = pFileName;
} }
else /* compare the file name */
{ DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU);
ObjectName++; if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE))
}
}
/* compare the short name and the directory */
if (!_wcsicmp(ObjectName, rcFCB->ShortName) && !_wcsnicmp(pFileName, rcFCB->PathName, len))
{ {
rcFCB->RefCount++; rcFCB->RefCount++;
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); CHECKPOINT;
return rcFCB; return rcFCB;
} }
} }
} }
entry = entry->next; entry = entry->next;
} }
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); CHECKPOINT;
return NULL; return NULL;
} }
@ -310,11 +339,12 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB)
PVFATFCB FCB; PVFATFCB FCB;
ULONG FirstCluster, CurrentCluster, Size = 0; ULONG FirstCluster, CurrentCluster, Size = 0;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING NameU;
FCB = vfatNewFCB(L"\\"); RtlInitUnicodeStringFromLiteral(&NameU, L"\\");
FCB = vfatNewFCB(&NameU);
memset(FCB->entry.Filename, ' ', 11); memset(FCB->entry.Filename, ' ', 11);
FCB->ShortName[0] = L'\\';
FCB->ShortName[1] = 0;
FCB->ShortHash.Hash = FCB->Hash.Hash; FCB->ShortHash.Hash = FCB->Hash.Hash;
FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector; FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY; FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
@ -351,8 +381,11 @@ PVFATFCB
vfatOpenRootFCB(PDEVICE_EXTENSION pVCB) vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
{ {
PVFATFCB FCB; PVFATFCB FCB;
UNICODE_STRING NameU;
FCB = vfatGrabFCBFromTable (pVCB, L"\\"); RtlInitUnicodeStringFromLiteral(&NameU, L"\\");
FCB = vfatGrabFCBFromTable (pVCB, &NameU);
if (FCB == NULL) if (FCB == NULL)
{ {
FCB = vfatMakeRootFCB (pVCB); FCB = vfatMakeRootFCB (pVCB);
@ -364,42 +397,44 @@ vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
NTSTATUS NTSTATUS
vfatMakeFCBFromDirEntry(PVCB vcb, vfatMakeFCBFromDirEntry(PVCB vcb,
PVFATFCB directoryFCB, PVFATFCB directoryFCB,
PWSTR longName, PVFAT_DIRENTRY_CONTEXT DirContext,
PFAT_DIR_ENTRY dirEntry,
ULONG startIndex,
ULONG dirIndex,
PVFATFCB* fileFCB) PVFATFCB* fileFCB)
{ {
PVFATFCB rcFCB; PVFATFCB rcFCB;
WCHAR pathName [MAX_PATH]; WCHAR pathName [MAX_PATH];
WCHAR entryName [14];
ULONG Size; ULONG Size;
ULONG hash; ULONG hash;
if (longName [0] != 0 && wcslen (directoryFCB->PathName) + UNICODE_STRING NameU;
sizeof(WCHAR) + wcslen (longName) > MAX_PATH)
if (directoryFCB->PathNameU.Length + 2 * sizeof(WCHAR) +
+ DirContext->LongNameU.Length > MAX_PATH * sizeof(WCHAR))
{ {
return STATUS_OBJECT_NAME_INVALID; return STATUS_OBJECT_NAME_INVALID;
} }
wcscpy (pathName, directoryFCB->PathName); NameU.Buffer = pathName;
NameU.Length = 0;
NameU.MaximumLength = sizeof(pathName);
RtlCopyUnicodeString(&NameU, &directoryFCB->PathNameU);
if (!vfatFCBIsRoot (directoryFCB)) if (!vfatFCBIsRoot (directoryFCB))
{ {
wcscat (pathName, L"\\"); RtlAppendUnicodeToString(&NameU, L"\\");
} }
hash = vfatNameHash(0, pathName); hash = vfatNameHash(0, &NameU);
vfatGetDirEntryName (dirEntry, entryName); if (DirContext->LongNameU.Length > 0)
if (longName [0] != 0)
{ {
wcscat (pathName, longName); RtlAppendUnicodeStringToString(&NameU, &DirContext->LongNameU);
} }
else else
{ {
wcscat (pathName, entryName); RtlAppendUnicodeStringToString(&NameU, &DirContext->ShortNameU);
} }
rcFCB = vfatNewFCB (pathName); NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY)); rcFCB = vfatNewFCB (&NameU);
wcscpy(rcFCB->ShortName, entryName); memcpy (&rcFCB->entry, &DirContext->FatDirEntry, sizeof (FAT_DIR_ENTRY));
rcFCB->ShortHash.Hash = vfatNameHash(hash, entryName); RtlCopyUnicodeString(&rcFCB->ShortNameU, &DirContext->ShortNameU);
rcFCB->ShortHash.Hash = vfatNameHash(hash, &rcFCB->ShortNameU);
if (vfatFCBIsDirectory(rcFCB)) if (vfatFCBIsDirectory(rcFCB))
{ {
@ -425,8 +460,8 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
{ {
Size = rcFCB->entry.FileSize; Size = rcFCB->entry.FileSize;
} }
rcFCB->dirIndex = dirIndex; rcFCB->dirIndex = DirContext->DirIndex;
rcFCB->startIndex = startIndex; rcFCB->startIndex = DirContext->StartIndex;
rcFCB->RFCB.FileSize.QuadPart = Size; rcFCB->RFCB.FileSize.QuadPart = Size;
rcFCB->RFCB.ValidDataLength.QuadPart = Size; rcFCB->RFCB.ValidDataLength.QuadPart = Size;
rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster); rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster);
@ -452,6 +487,7 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList); newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
if (newCCB == NULL) if (newCCB == NULL)
{ {
CHECKPOINT;
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
memset (newCCB, 0, sizeof (VFATCCB)); memset (newCCB, 0, sizeof (VFATCCB));
@ -461,7 +497,7 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers; fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
fileObject->FsContext = fcb; fileObject->FsContext = fcb;
fileObject->FsContext2 = newCCB; fileObject->FsContext2 = newCCB;
DPRINT ("file open: fcb:%x file size: %d\n", fcb, fcb->entry.FileSize); DPRINT ("file open: fcb:%x PathName:%wZ file size: %d\n", fcb, &fcb->PathNameU, fcb->entry.FileSize);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -469,92 +505,77 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
NTSTATUS NTSTATUS
vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt, vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pDirectoryFCB, PVFATFCB pDirectoryFCB,
PWSTR pFileToFind, PUNICODE_STRING FileToFindU,
PVFATFCB * pFoundFCB) PVFATFCB * pFoundFCB)
{ {
ULONG directoryIndex;
ULONG startIndex;
NTSTATUS status; NTSTATUS status;
WCHAR defaultFileName [2];
WCHAR currentLongName [256];
FAT_DIR_ENTRY currentDirEntry;
WCHAR currentEntryName [256];
PVOID Context = NULL; PVOID Context = NULL;
PVOID Page; PVOID Page;
BOOLEAN First = TRUE;
VFAT_DIRENTRY_CONTEXT DirContext;
WCHAR LongNameBuffer[MAX_PATH];
WCHAR ShortNameBuffer[13];
BOOLEAN FoundLong;
BOOLEAN FoundShort;
assert (pDeviceExt); assert (pDeviceExt);
assert (pDirectoryFCB); assert (pDirectoryFCB);
assert (pFileToFind); assert (FileToFindU);
DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n", DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%wZ)\n",
pDeviceExt, pDeviceExt,
pDirectoryFCB, pDirectoryFCB,
pFileToFind); FileToFindU);
DPRINT ("Dir Path:%S\n", pDirectoryFCB->PathName); DPRINT ("Dir Path:%wZ\n", &pDirectoryFCB->PathNameU);
// default to '.' if no filename specified DirContext.DirIndex = 0;
if (wcslen (pFileToFind) == 0) DirContext.LongNameU.Buffer = LongNameBuffer;
{ DirContext.LongNameU.Length = 0;
defaultFileName [0] = L'.'; DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
defaultFileName [1] = 0; DirContext.ShortNameU.Buffer = ShortNameBuffer;
pFileToFind = defaultFileName; DirContext.ShortNameU.Length = 0;
} DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
directoryIndex = 0;
while (TRUE) while (TRUE)
{ {
status = vfatGetNextDirEntry(&Context, status = vfatGetNextDirEntry(&Context,
&Page, &Page,
pDirectoryFCB, pDirectoryFCB,
&directoryIndex, &DirContext,
currentLongName, First);
&currentDirEntry, First = FALSE;
&startIndex);
if (status == STATUS_NO_MORE_ENTRIES) if (status == STATUS_NO_MORE_ENTRIES)
{ {
return STATUS_OBJECT_NAME_NOT_FOUND; return STATUS_OBJECT_NAME_NOT_FOUND;
} }
if (!NT_SUCCESS(status))
DPRINT (" Index:%d longName:%S\n",
directoryIndex,
currentLongName);
if (!vfatIsDirEntryVolume(&currentDirEntry))
{ {
if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind))
{
DPRINT ("Match found, %S\n", currentLongName);
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
currentLongName,
&currentDirEntry,
startIndex,
directoryIndex,
pFoundFCB);
CcUnpinData(Context);
return status; return status;
} }
else
{
vfatGetDirEntryName (&currentDirEntry, currentEntryName);
DPRINT (" entryName:%S\n", currentEntryName);
if (wstrcmpjoki (currentEntryName, pFileToFind)) DPRINT (" Index:%d longName:%wZ\n",
DirContext.DirIndex,
&DirContext.LongNameU);
DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
if (!ENTRY_VOLUME(&DirContext.FatDirEntry))
{
FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE);
if (FoundLong == FALSE)
{
FoundShort = RtlEqualUnicodeString(FileToFindU, &DirContext.ShortNameU, TRUE);
}
if (FoundLong || FoundShort)
{ {
DPRINT ("Match found, %S\n", currentEntryName);
status = vfatMakeFCBFromDirEntry (pDeviceExt, status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB, pDirectoryFCB,
currentLongName, &DirContext,
&currentDirEntry,
startIndex,
directoryIndex,
pFoundFCB); pFoundFCB);
CcUnpinData(Context); CcUnpinData(Context);
return status; return status;
} }
} }
} DirContext.DirIndex++;
directoryIndex++;
} }
return STATUS_OBJECT_NAME_NOT_FOUND; return STATUS_OBJECT_NAME_NOT_FOUND;
@ -564,23 +585,25 @@ NTSTATUS
vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
PVFATFCB *pParentFCB, PVFATFCB *pParentFCB,
PVFATFCB *pFCB, PVFATFCB *pFCB,
const PWSTR pFileName) PUNICODE_STRING pFileNameU)
{ {
NTSTATUS status; NTSTATUS status;
WCHAR pathName [MAX_PATH]; PVFATFCB FCB = NULL;
WCHAR elementName [MAX_PATH];
PWCHAR currentElement;
PVFATFCB FCB;
PVFATFCB parentFCB; PVFATFCB parentFCB;
UNICODE_STRING NameU;
UNICODE_STRING RootNameU;
PWCHAR curr, prev, last;
DPRINT ("vfatGetFCBForFile (%x,%x,%x,%S)\n", DPRINT ("vfatGetFCBForFile (%x,%x,%x,%wZ)\n",
pVCB, pVCB,
pParentFCB, pParentFCB,
pFCB, pFCB,
pFileName); pFileNameU);
RtlInitUnicodeStringFromLiteral(&RootNameU, L"\\");
// Trivial case, open of the root directory on volume // Trivial case, open of the root directory on volume
if (pFileName [0] == L'\0' || wcscmp (pFileName, L"\\") == 0) if (RtlEqualUnicodeString(pFileNameU, &RootNameU, FALSE))
{ {
DPRINT ("returning root FCB\n"); DPRINT ("returning root FCB\n");
@ -591,34 +614,32 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND; return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
} }
currentElement = wcsrchr(pFileName, L'\\'); last = curr = pFileNameU->Buffer + pFileNameU->Length / sizeof(WCHAR) - 1;
wcsncpy(pathName, pFileName, currentElement - pFileName); while (*curr != L'\\' && curr > pFileNameU->Buffer)
pathName[currentElement - pFileName] = L'\0'; {
currentElement++; curr--;
}
if (curr > pFileNameU->Buffer)
{
NameU.Buffer = pFileNameU->Buffer;
NameU.MaximumLength = NameU.Length = (curr - pFileNameU->Buffer - 1) * sizeof(WCHAR);
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
}
else
{
FCB = NULL;
}
FCB = vfatGrabFCBFromTable(pVCB, pathName);
if (FCB == NULL) if (FCB == NULL)
{ {
currentElement = pFileName + 1;
wcscpy (pathName, L"\\");
FCB = vfatOpenRootFCB(pVCB); FCB = vfatOpenRootFCB(pVCB);
curr = pFileNameU->Buffer;
} }
curr++;
parentFCB = NULL; parentFCB = NULL;
while (curr <= last)
// Parse filename and check each path element for existance and access
while (vfatGetNextPathElement (currentElement) != 0)
{ {
// Skip blank directory levels
if ((vfatGetNextPathElement (currentElement) - currentElement) == 0)
{
currentElement++;
continue;
}
DPRINT ("Parsing, currentElement:%S\n", currentElement);
DPRINT (" parentFCB:%x FCB:%x\n", parentFCB, FCB);
// descend to next directory level
if (parentFCB) if (parentFCB)
{ {
vfatReleaseFCB (pVCB, parentFCB); vfatReleaseFCB (pVCB, parentFCB);
@ -630,35 +651,31 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
DPRINT ("Element in requested path is not a directory\n"); DPRINT ("Element in requested path is not a directory\n");
vfatReleaseFCB (pVCB, FCB); vfatReleaseFCB (pVCB, FCB);
FCB = 0; FCB = NULL;
*pParentFCB = NULL; *pParentFCB = NULL;
*pFCB = NULL; *pFCB = NULL;
return STATUS_OBJECT_PATH_NOT_FOUND; return STATUS_OBJECT_PATH_NOT_FOUND;
} }
parentFCB = FCB; parentFCB = FCB;
NameU.Buffer = pFileNameU->Buffer;
// Extract next directory level into dirName prev = curr;
vfatWSubString (pathName, while (*curr != L'\\' && curr <= last)
pFileName, {
vfatGetNextPathElement (currentElement) - pFileName); curr++;
DPRINT (" pathName:%S\n", pathName); }
NameU.MaximumLength = NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR);
FCB = vfatGrabFCBFromTable (pVCB, pathName); FCB = vfatGrabFCBFromTable(pVCB, &NameU);
if (FCB == NULL) if (FCB == NULL)
{ {
vfatWSubString (elementName, NameU.Buffer = prev;
currentElement, NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR);
vfatGetNextPathElement (currentElement) - currentElement); status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB);
DPRINT (" elementName:%S\n", elementName);
status = vfatDirFindFile (pVCB, parentFCB, elementName, &FCB);
if (status == STATUS_OBJECT_NAME_NOT_FOUND) if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{ {
*pParentFCB = parentFCB; *pParentFCB = parentFCB;
*pFCB = NULL; *pFCB = NULL;
currentElement = vfatGetNextPathElement(currentElement); if (curr > last)
if (*currentElement == L'\0' || vfatGetNextPathElement(currentElement + 1) == 0)
{ {
return STATUS_OBJECT_NAME_NOT_FOUND; return STATUS_OBJECT_NAME_NOT_FOUND;
} }
@ -676,7 +693,7 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
return status; return status;
} }
} }
currentElement = vfatGetNextPathElement (currentElement); curr++;
} }
*pParentFCB = parentFCB; *pParentFCB = parentFCB;
@ -684,7 +701,3 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -1,10 +1,11 @@
/* $Id: finfo.c,v 1.33 2003/09/20 20:31:57 weiden Exp $ /* $Id: finfo.c,v 1.34 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/finfo.c * FILE: drivers/fs/vfat/finfo.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
* *
*/ */
@ -119,7 +120,7 @@ VfatSetBasicInformation(PFILE_OBJECT FileObject,
FILE_ATTRIBUTE_READONLY))); FILE_ATTRIBUTE_READONLY)));
DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib); DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib);
VfatUpdateEntry(DeviceExt, FileObject); VfatUpdateEntry(FCB);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -170,10 +171,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,
PFILE_DISPOSITION_INFORMATION DispositionInfo) PFILE_DISPOSITION_INFORMATION DispositionInfo)
{ {
KIRQL oldIrql;
VFATFCB tmpFcb;
WCHAR star[2];
ULONG Index;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
int count; int count;
@ -185,8 +182,9 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
assert (DeviceExt->FatInfo.BytesPerCluster != 0); assert (DeviceExt->FatInfo.BytesPerCluster != 0);
assert (FCB != NULL); assert (FCB != NULL);
if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..") if (vfatFCBIsRoot(FCB) ||
|| !wcscmp(FCB->ObjectName, L".")) (FCB->LongNameU.Length == sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.') ||
(FCB->LongNameU.Length == 2 * sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.' && FCB->LongNameU.Buffer[1] == L'.'))
{ {
// we cannot delete a '.', '..' or the root directory // we cannot delete a '.', '..' or the root directory
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
@ -195,7 +193,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
{ {
if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete)) if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
{ {
KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql);
count = FCB->RefCount; count = FCB->RefCount;
if (FCB->RefCount > 1) if (FCB->RefCount > 1)
{ {
@ -207,7 +204,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
FCB->Flags |= FCB_DELETE_PENDING; FCB->Flags |= FCB_DELETE_PENDING;
FileObject->DeletePending = TRUE; FileObject->DeletePending = TRUE;
} }
KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
} }
else else
{ {
@ -217,16 +213,8 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
DPRINT("RefCount:%d\n", count); DPRINT("RefCount:%d\n", count);
if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB)) if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
{ {
memset (&tmpFcb, 0, sizeof(VFATFCB)); if (!VfatIsDirectoryEmpty(FCB))
tmpFcb.ObjectName = tmpFcb.PathName;
star[0] = L'*';
star[1] = 0;
// skip '.' and '..', start by 2
Index = 2;
Status = FindFile (DeviceExt, &tmpFcb, FCB, star, &Index, NULL);
if (NT_SUCCESS(Status))
{ {
DPRINT1("found: \'%S\'\n", tmpFcb.PathName);
Status = STATUS_DIRECTORY_NOT_EMPTY; Status = STATUS_DIRECTORY_NOT_EMPTY;
FCB->Flags &= ~FCB_DELETE_PENDING; FCB->Flags &= ~FCB_DELETE_PENDING;
FileObject->DeletePending = FALSE; FileObject->DeletePending = FALSE;
@ -238,7 +226,9 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
} }
} }
else else
{
FileObject->DeletePending = FALSE; FileObject->DeletePending = FALSE;
}
return Status; return Status;
} }
@ -252,19 +242,18 @@ VfatGetNameInformation(PFILE_OBJECT FileObject,
* FUNCTION: Retrieve the file name information * FUNCTION: Retrieve the file name information
*/ */
{ {
ULONG NameLength;
assert (NameInfo != NULL); assert (NameInfo != NULL);
assert (FCB != NULL); assert (FCB != NULL);
NameLength = wcslen(FCB->PathName) * sizeof(WCHAR); if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR))
if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR))
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
NameInfo->FileNameLength = NameLength; NameInfo->FileNameLength = FCB->PathNameU.Length;
memcpy(NameInfo->FileName, FCB->PathName, NameLength + sizeof(WCHAR)); memcpy(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
NameInfo->FileName[FCB->PathNameU.Length / sizeof(WCHAR)] = 0;
*BufferLength -= (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR)); *BufferLength -= (sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR));
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -328,13 +317,11 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
* FUNCTION: Retrieve the all file information * FUNCTION: Retrieve the all file information
*/ */
{ {
ULONG NameLength;
assert (Info); assert (Info);
assert (Fcb); assert (Fcb);
NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR); if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR))
if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR))
return(STATUS_BUFFER_OVERFLOW); return(STATUS_BUFFER_OVERFLOW);
/* Basic Information */ /* Basic Information */
@ -377,10 +364,11 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
/* The IO-Manager adds this information */ /* The IO-Manager adds this information */
/* Name Information */ /* Name Information */
Info->NameInformation.FileNameLength = NameLength; Info->NameInformation.FileNameLength = Fcb->PathNameU.Length;
RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathName, NameLength + sizeof(WCHAR)); RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathNameU.Buffer, Fcb->PathNameU.Length);
Info->NameInformation.FileName[Fcb->PathNameU.Length / sizeof(WCHAR)] = 0;
*BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR)); *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -421,6 +409,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster; ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
ULONG NewSize = AllocationSize->u.LowPart; ULONG NewSize = AllocationSize->u.LowPart;
ULONG NCluster; ULONG NCluster;
BOOL AllocSizeChanged = FALSE;
DPRINT("VfatSetAllocationSizeInformation()\n"); DPRINT("VfatSetAllocationSizeInformation()\n");
@ -438,6 +427,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart) if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
{ {
AllocSizeChanged = TRUE;
if (FirstCluster == 0) if (FirstCluster == 0)
{ {
Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE); Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);
@ -499,6 +489,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
} }
else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart) else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
{ {
AllocSizeChanged = TRUE;
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize); UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
if (NewSize > 0) if (NewSize > 0)
{ {
@ -531,7 +522,11 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize); UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
} }
/* Update the on-disk directory entry */ /* Update the on-disk directory entry */
VfatUpdateEntry(DeviceExt, FileObject); Fcb->Flags |= FCB_IS_DIRTY;
if (AllocSizeChanged)
{
VfatUpdateEntry(Fcb);
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -1,4 +1,4 @@
/* $Id: flush.c,v 1.4 2003/07/24 20:52:58 chorns Exp $ /* $Id: flush.c,v 1.5 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -20,8 +20,9 @@
NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb) NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
{ {
IO_STATUS_BLOCK IoStatus; IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
DPRINT("VfatFlushFile(DeviceExt %x, Fcb %x) for '%S'\n", DeviceExt, Fcb, Fcb->PathName); DPRINT("VfatFlushFile(DeviceExt %x, Fcb %x) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus); CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
if (IoStatus.Status == STATUS_INVALID_PARAMETER) if (IoStatus.Status == STATUS_INVALID_PARAMETER)
@ -29,6 +30,14 @@ NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
/* FIXME: Caching was possible not initialized */ /* FIXME: Caching was possible not initialized */
IoStatus.Status = STATUS_SUCCESS; IoStatus.Status = STATUS_SUCCESS;
} }
if (Fcb->Flags & FCB_IS_DIRTY)
{
Status = VfatUpdateEntry(Fcb);
if (!NT_SUCCESS(Status))
{
IoStatus.Status = Status;
}
}
return IoStatus.Status; return IoStatus.Status;
} }
@ -45,6 +54,8 @@ NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
{ {
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry); Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
ListEntry = ListEntry->Flink; ListEntry = ListEntry->Flink;
if (!vfatFCBIsDirectory(Fcb))
{
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
Status = VfatFlushFile(DeviceExt, Fcb); Status = VfatFlushFile(DeviceExt, Fcb);
ExReleaseResourceLite (&Fcb->MainResource); ExReleaseResourceLite (&Fcb->MainResource);
@ -53,6 +64,25 @@ NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
DPRINT1("VfatFlushFile failed, status = %x\n", Status); DPRINT1("VfatFlushFile failed, status = %x\n", Status);
ReturnStatus = Status; ReturnStatus = Status;
} }
}
/* FIXME: Stop flushing if this is a removable media and the media was removed */
}
ListEntry = DeviceExt->FcbListHead.Flink;
while (ListEntry != &DeviceExt->FcbListHead)
{
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
ListEntry = ListEntry->Flink;
if (vfatFCBIsDirectory(Fcb))
{
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
Status = VfatFlushFile(DeviceExt, Fcb);
ExReleaseResourceLite (&Fcb->MainResource);
if (!NT_SUCCESS(Status))
{
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
ReturnStatus = Status;
}
}
/* FIXME: Stop flushing if this is a removable media and the media was removed */ /* FIXME: Stop flushing if this is a removable media and the media was removed */
} }

View file

@ -16,11 +16,11 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: fsctl.c,v 1.23 2003/08/27 21:28:07 dwelch Exp $ /* $Id: fsctl.c,v 1.24 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/fsctl.c * FILE: drivers/fs/vfat/fsctl.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
*/ */
@ -214,6 +214,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
PVFATFCB VolumeFcb = NULL; PVFATFCB VolumeFcb = NULL;
PVFATCCB Ccb = NULL; PVFATCCB Ccb = NULL;
PDEVICE_OBJECT DeviceToMount; PDEVICE_OBJECT DeviceToMount;
UNICODE_STRING NameU;
DPRINT("VfatMount(IrpContext %x)\n", IrpContext); DPRINT("VfatMount(IrpContext %x)\n", IrpContext);
@ -289,7 +290,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
DPRINT("FsDeviceObject %lx\n", DeviceObject); DPRINT("FsDeviceObject %lx\n", DeviceObject);
DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
Fcb = vfatNewFCB(NULL); RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Fat$$");
Fcb = vfatNewFCB(&NameU);
if (Fcb == NULL) if (Fcb == NULL)
{ {
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
@ -301,9 +303,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye; goto ByeBye;
} }
memset(Ccb, 0, sizeof (VFATCCB)); memset(Ccb, 0, sizeof (VFATCCB));
wcscpy(Fcb->PathName, L"$$Fat$$");
Fcb->ObjectName = Fcb->PathName;
DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
DeviceExt->FATFileObject->FsContext = Fcb; DeviceExt->FATFileObject->FsContext = Fcb;
DeviceExt->FATFileObject->FsContext2 = Ccb; DeviceExt->FATFileObject->FsContext2 = Ccb;
@ -335,17 +336,15 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
ExInitializeResourceLite(&DeviceExt->DirResource); ExInitializeResourceLite(&DeviceExt->DirResource);
ExInitializeResourceLite(&DeviceExt->FatResource); ExInitializeResourceLite(&DeviceExt->FatResource);
KeInitializeSpinLock(&DeviceExt->FcbListLock);
InitializeListHead(&DeviceExt->FcbListHead); InitializeListHead(&DeviceExt->FcbListHead);
RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Volume$$");
VolumeFcb = vfatNewFCB(NULL); VolumeFcb = vfatNewFCB(&NameU);
if (VolumeFcb == NULL) if (VolumeFcb == NULL)
{ {
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye; goto ByeBye;
} }
wcscpy(VolumeFcb->PathName, L"$$Volume$$");
VolumeFcb->ObjectName = VolumeFcb->PathName;
VolumeFcb->Flags = FCB_IS_VOLUME; VolumeFcb->Flags = FCB_IS_VOLUME;
VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector; VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize; VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;

View file

@ -16,12 +16,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: iface.c,v 1.71 2003/09/20 20:31:57 weiden Exp $ /* $Id: iface.c,v 1.72 2003/10/11 17:51:56 hbirr Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/iface.c * FILE: drivers/fs/vfat/iface.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.42 2003/04/05 09:37:42 chorns Exp $ # $Id: makefile,v 1.43 2003/10/11 17:51:56 hbirr Exp $
PATH_TO_TOP = ../../.. PATH_TO_TOP = ../../..
@ -35,7 +35,13 @@ DEP_OBJECTS = $(TARGET_OBJECTS)
TARGET_CLEAN = $(DEP_FILES) *.o *.sys *.sym TARGET_CLEAN = $(DEP_FILES) *.o *.sys *.sym
TARGET_CFLAGS = -g include $(PATH_TO_TOP)/config
ifeq ($(DBG), 1)
TARGET_CFLAGS = -Wall -Werror -g
else
TARGET_CFLAGS = -Wall -Werror -fno-strict-aliasing -O6
endif
include $(PATH_TO_TOP)/rules.mak include $(PATH_TO_TOP)/rules.mak

View file

@ -1,8 +1,8 @@
/* $Id: misc.c,v 1.10 2003/07/24 20:52:58 chorns Exp $ /* $Id: misc.c,v 1.11 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/misc.c * FILE: drivers/fs/vfat/misc.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Hartmut Birr * PROGRAMMER: Hartmut Birr
* *
@ -189,16 +189,16 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
VOID STDCALL VfatDoRequest (PVOID IrpContext) VOID STDCALL VfatDoRequest (PVOID IrpContext)
{ {
ULONG Count = InterlockedDecrement(&QueueCount); InterlockedDecrement(&QueueCount);
DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, Count); DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext); VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
} }
NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext) NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
{ {
ULONG Count = InterlockedIncrement(&QueueCount); InterlockedIncrement(&QueueCount);
DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, Count); DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, QueueCount);
assert (IrpContext != NULL); assert (IrpContext != NULL);
assert (IrpContext->Irp != NULL); assert (IrpContext->Irp != NULL);

View file

@ -1,11 +1,12 @@
/* $Id: rw.c,v 1.60 2003/08/07 11:47:32 silverblade Exp $ /* $Id: rw.c,v 1.61 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/rw.c * FILE: drivers/fs/vfat/rw.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
* *
*/ */
@ -303,7 +304,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
ULONG BytesDone; ULONG BytesDone;
ULONG StartCluster; ULONG StartCluster;
ULONG ClusterCount; ULONG ClusterCount;
NTSTATUS Status; NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN First = TRUE; BOOLEAN First = TRUE;
ULONG BytesPerSector; ULONG BytesPerSector;
ULONG BytesPerCluster; ULONG BytesPerCluster;
@ -323,9 +324,9 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
BytesPerSector = DeviceExt->FatInfo.BytesPerSector; BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
DPRINT("VfatWriteFileData(DeviceExt %x, FileObject %x, Buffer %x, " DPRINT("VfatWriteFileData(DeviceExt %x, FileObject %x, Buffer %x, "
"Length %d, WriteOffset 0x%I64x), '%S'\n", DeviceExt, "Length %d, WriteOffset 0x%I64x), '%wZ'\n", DeviceExt,
IrpContext->FileObject, Buffer, Length, WriteOffset, IrpContext->FileObject, Buffer, Length, WriteOffset,
Fcb->PathName); &Fcb->PathNameU);
assert(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart); assert(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart);
assert(WriteOffset.u.LowPart % BytesPerSector == 0); assert(WriteOffset.u.LowPart % BytesPerSector == 0);
@ -482,7 +483,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
Fcb = IrpContext->FileObject->FsContext; Fcb = IrpContext->FileObject->FsContext;
assert(Fcb); assert(Fcb);
DPRINT("<%S>\n", Fcb->PathName); DPRINT("<%wZ>\n", &Fcb->PathNameU);
if (Fcb->Flags & FCB_IS_PAGE_FILE) if (Fcb->Flags & FCB_IS_PAGE_FILE)
{ {
@ -509,7 +510,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
} }
DPRINT("'%S', Offset: %d, Length %d\n", Fcb->PathName, ByteOffset.u.LowPart, Length); DPRINT("'%wZ', Offset: %d, Length %d\n", &Fcb->PathNameU, ByteOffset.u.LowPart, Length);
if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME)) if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME))
{ {
@ -720,7 +721,7 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
Fcb = IrpContext->FileObject->FsContext; Fcb = IrpContext->FileObject->FsContext;
assert(Fcb); assert(Fcb);
DPRINT("<%S>\n", Fcb->PathName); DPRINT("<%wZ>\n", &Fcb->PathNameU);
if (Fcb->Flags & FCB_IS_PAGE_FILE) if (Fcb->Flags & FCB_IS_PAGE_FILE)
{ {
@ -939,8 +940,8 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
FsdFileTimeToDosDateTime ((TIME*)&LocalTime, &Fcb->entry.UpdateDate, FsdFileTimeToDosDateTime ((TIME*)&LocalTime, &Fcb->entry.UpdateDate,
&Fcb->entry.UpdateTime); &Fcb->entry.UpdateTime);
Fcb->entry.AccessDate = Fcb->entry.UpdateDate; Fcb->entry.AccessDate = Fcb->entry.UpdateDate;
// update dates/times and length /* set date and times to dirty */
VfatUpdateEntry (IrpContext->DeviceExt, IrpContext->FileObject); Fcb->Flags |= FCB_IS_DIRTY;
} }
} }

View file

@ -1,8 +1,8 @@
/* $Id: shutdown.c,v 1.7 2003/07/24 20:52:58 chorns Exp $ /* $Id: shutdown.c,v 1.8 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/shutdown.c * FILE: drivers/fs/vfat/shutdown.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de) * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
*/ */

View file

@ -1,10 +1,11 @@
/* $Id: string.c,v 1.11 2003/07/24 20:52:58 chorns Exp $ /* $Id: string.c,v 1.12 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/string.c * FILE: drivers/fs/vfat/string.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
* *
*/ */
@ -20,13 +21,21 @@
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
const WCHAR *long_illegals = L"\"*\\<>/?:|";
BOOLEAN
vfatIsLongIllegal(WCHAR c)
{
return wcschr(long_illegals, c) ? TRUE : FALSE;
}
BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2) BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
/* /*
* FUNCTION: Compare two wide character strings, s2 with jokers (* or ?) * FUNCTION: Compare two wide character strings, s2 with jokers (* or ?)
* return TRUE if s1 like s2 * return TRUE if s1 like s2
*/ */
{ {
while ((*s2=='*')||(*s2=='?')||(towlower(*s1)==towlower(*s2))) while ((*s2==L'*')||(*s2==L'?')||(RtlUpcaseUnicodeChar(*s1)==RtlUpcaseUnicodeChar(*s2)))
{ {
if ((*s1)==0 && (*s2)==0) if ((*s1)==0 && (*s2)==0)
return(TRUE); return(TRUE);
@ -43,54 +52,16 @@ BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
s2++; s2++;
} }
} }
if ((*s2)=='.') if ((*s2)==L'.')
{ {
for (;((*s2)=='.')||((*s2)=='*')||((*s2)=='?');s2++) {} for (;((*s2)==L'.')||((*s2)==L'*')||((*s2)==L'?');s2++) {}
} }
if ((*s1)==0 && (*s2)==0) if ((*s1)==0 && (*s2)==0)
return(TRUE); return(TRUE);
return(FALSE); return(FALSE);
} }
PWCHAR
vfatGetNextPathElement (PWCHAR pFileName)
{
if (*pFileName == L'\0')
{
return 0;
}
while (*pFileName != L'\0' && *pFileName != L'\\')
{
pFileName++;
}
return pFileName;
}
void
vfatWSubString (PWCHAR pTarget, const PWCHAR pSource, size_t pLength)
{
wcsncpy (pTarget, pSource, pLength);
pTarget [pLength] = L'\0';
}
BOOL
vfatIsFileNameValid (PWCHAR pFileName)
{
PWCHAR c;
c = pFileName;
while (*c != 0)
{
if (*c == L'*' || *c == L'?')
{
return FALSE;
}
c++;
}
return TRUE;
}

View file

@ -1,4 +1,4 @@
/* $Id: vfat.h,v 1.59 2003/07/24 19:00:42 chorns Exp $ */ /* $Id: vfat.h,v 1.60 2003/10/11 17:51:56 hbirr Exp $ */
#include <ddk/ntifs.h> #include <ddk/ntifs.h>
@ -68,6 +68,11 @@ typedef struct _BootSector BootSector;
#define VFAT_CASE_LOWER_BASE 8 // base is lower case #define VFAT_CASE_LOWER_BASE 8 // base is lower case
#define VFAT_CASE_LOWER_EXT 16 // extension is lower case #define VFAT_CASE_LOWER_EXT 16 // extension is lower case
#define ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
#define ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
#define ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
#define ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
struct _FATDirEntry struct _FATDirEntry
{ {
unsigned char Filename[8], Ext[3]; unsigned char Filename[8], Ext[3];
@ -145,6 +150,7 @@ typedef struct
KSPIN_LOCK FcbListLock; KSPIN_LOCK FcbListLock;
LIST_ENTRY FcbListHead; LIST_ENTRY FcbListHead;
struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
PDEVICE_OBJECT StorageDevice; PDEVICE_OBJECT StorageDevice;
PFILE_OBJECT FATFileObject; PFILE_OBJECT FATFileObject;
@ -154,7 +160,6 @@ typedef struct
BOOLEAN AvailableClustersValid; BOOLEAN AvailableClustersValid;
ULONG Flags; ULONG Flags;
struct _VFATFCB * VolumeFcb; struct _VFATFCB * VolumeFcb;
struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
LIST_ENTRY VolumeListEntry; LIST_ENTRY VolumeListEntry;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; } DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
@ -178,6 +183,7 @@ extern PVFAT_GLOBAL_DATA VfatGlobalData;
#define FCB_IS_FAT 0x0004 #define FCB_IS_FAT 0x0004
#define FCB_IS_PAGE_FILE 0x0008 #define FCB_IS_PAGE_FILE 0x0008
#define FCB_IS_VOLUME 0x0010 #define FCB_IS_VOLUME 0x0010
#define FCB_IS_DIRTY 0x0020
typedef struct _VFATFCB typedef struct _VFATFCB
{ {
@ -188,17 +194,26 @@ typedef struct _VFATFCB
ERESOURCE PagingIoResource; ERESOURCE PagingIoResource;
/* end FCB header required by ROS/NT */ /* end FCB header required by ROS/NT */
/* */ /* directory entry for this file or directory */
FATDirEntry entry; FATDirEntry entry;
/* point on filename (250 chars max) in PathName */ /* long file name, points into PathNameBuffer */
WCHAR *ObjectName; UNICODE_STRING LongNameU;
/* path+filename 260 max */
WCHAR PathName[MAX_PATH];
/* short file name */ /* short file name */
WCHAR ShortName[14]; UNICODE_STRING ShortNameU;
/* directory name, points into PathNameBuffer */
UNICODE_STRING DirNameU;
/* path + long file name 260 max*/
UNICODE_STRING PathNameU;
/* buffer for PathNameU */
WCHAR PathNameBuffer[MAX_PATH];
/* buffer for ShortNameU */
WCHAR ShortNameBuffer[13];
/* */ /* */
LONG RefCount; LONG RefCount;
@ -241,7 +256,7 @@ typedef struct _VFATCCB
/* for DirectoryControl */ /* for DirectoryControl */
ULONG Entry; ULONG Entry;
/* for DirectoryControl */ /* for DirectoryControl */
PWCHAR DirectorySearchPattern; UNICODE_STRING SearchPattern;
ULONG LastCluster; ULONG LastCluster;
ULONG LastOffset; ULONG LastOffset;
@ -288,6 +303,16 @@ typedef struct
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; } VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
typedef struct _VFAT_DIRENTRY_CONTEXT
{
ULONG StartIndex;
ULONG DirIndex;
FAT_DIR_ENTRY FatDirEntry;
UNICODE_STRING LongNameU;
UNICODE_STRING ShortNameU;
} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
/* ------------------------------------------------------ shutdown.c */ /* ------------------------------------------------------ shutdown.c */
NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject, NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject,
@ -336,27 +361,20 @@ NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt, NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject, PFILE_OBJECT FileObject,
PWSTR FileName); PUNICODE_STRING FileNameU);
NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt, NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt,
PVFATFCB Fcb,
PVFATFCB Parent, PVFATFCB Parent,
PWSTR FileToFind, PUNICODE_STRING FileToFindU,
PULONG pDirIndex, PVFAT_DIRENTRY_CONTEXT DirContext,
PULONG pDirIndex2); BOOLEAN First);
VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry,
PWSTR pName); PUNICODE_STRING NameU);
NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt,
PVPB Vpb); PVPB Vpb);
BOOLEAN IsDeletedEntry (PVOID Block,
ULONG Offset);
BOOLEAN IsLastEntry (PVOID Block,
ULONG Offset);
/* --------------------------------------------------------- close.c */ /* --------------------------------------------------------- close.c */
NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext); NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext);
@ -392,28 +410,27 @@ NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject,
/* --------------------------------------------------------- dirwr.c */ /* --------------------------------------------------------- dirwr.c */
NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt, NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PFILE_OBJECT pFileObject, PFILE_OBJECT pFileObject,
ULONG RequestedOptions,UCHAR ReqAttr); ULONG RequestedOptions,
UCHAR ReqAttr);
NTSTATUS VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt, NTSTATUS VfatUpdateEntry (PVFATFCB pFcb);
PFILE_OBJECT pFileObject);
NTSTATUS delEntry(PDEVICE_EXTENSION, NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB);
PFILE_OBJECT);
/* -------------------------------------------------------- string.c */ /* -------------------------------------------------------- string.c */
VOID
vfatSplitPathName(PUNICODE_STRING PathNameU,
PUNICODE_STRING DirNameU,
PUNICODE_STRING FileNameU);
BOOLEAN vfatIsLongIllegal(WCHAR c);
BOOLEAN wstrcmpjoki (PWSTR s1, BOOLEAN wstrcmpjoki (PWSTR s1,
PWSTR s2); PWSTR s2);
PWCHAR vfatGetNextPathElement (PWCHAR pFileName);
VOID vfatWSubString (PWCHAR pTarget,
const PWCHAR pSource,
size_t pLength);
BOOL vfatIsFileNameValid (PWCHAR pFileName);
/* ----------------------------------------------------------- fat.c */ /* ----------------------------------------------------------- fat.c */
NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt,
@ -443,26 +460,17 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PFAT_DIR_ENTRY pDirEntry); PFAT_DIR_ENTRY pDirEntry);
BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry); BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb);
BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry);
BOOL vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry);
VOID vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry,
PWSTR pEntryName);
NTSTATUS vfatGetNextDirEntry(PVOID * pContext, NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
PVOID * pPage, PVOID * pPage,
IN PVFATFCB pDirFcb, IN PVFATFCB pDirFcb,
IN OUT PULONG pDirIndex, IN PVFAT_DIRENTRY_CONTEXT DirContext,
OUT PWSTR pFileName, BOOLEAN First);
OUT PFAT_DIR_ENTRY pDirEntry,
OUT PULONG pStartIndex);
/* ----------------------------------------------------------- fcb.c */ /* ----------------------------------------------------------- fcb.c */
PVFATFCB vfatNewFCB (PWCHAR pFileName); PVFATFCB vfatNewFCB (PUNICODE_STRING pFileNameU);
VOID vfatDestroyFCB (PVFATFCB pFCB); VOID vfatDestroyFCB (PVFATFCB pFCB);
@ -478,7 +486,7 @@ VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB); PVFATFCB pFCB);
PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt,
PWSTR pFileName); PUNICODE_STRING pFileNameU);
PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB);
@ -494,20 +502,17 @@ NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB,
PVFATFCB parentFCB, PVFATFCB parentFCB,
PWSTR elementName, PUNICODE_STRING FileToFindU,
PVFATFCB * fileFCB); PVFATFCB * fileFCB);
NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
PVFATFCB *pParentFCB, PVFATFCB *pParentFCB,
PVFATFCB *pFCB, PVFATFCB *pFCB,
const PWSTR pFileName); PUNICODE_STRING pFileNameU);
NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb, NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb,
PVFATFCB directoryFCB, PVFATFCB directoryFCB,
PWSTR longName, PVFAT_DIRENTRY_CONTEXT DirContext,
PFAT_DIR_ENTRY dirEntry,
ULONG startIndex,
ULONG dirIndex,
PVFATFCB * fileFCB); PVFATFCB * fileFCB);
/* ------------------------------------------------------------ rw.c */ /* ------------------------------------------------------------ rw.c */
@ -548,4 +553,5 @@ NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb); NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb);
/* EOF */ /* EOF */

View file

@ -1,10 +1,11 @@
/* $Id: volume.c,v 1.23 2003/08/07 11:47:32 silverblade Exp $ /* $Id: volume.c,v 1.24 2003/10/11 17:51:56 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: services/fs/vfat/volume.c * FILE: drivers/fs/vfat/volume.c
* PURPOSE: VFAT Filesystem * PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/