mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 02:25:17 +00:00
- 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:
parent
a751ffce23
commit
096a69471d
21 changed files with 1510 additions and 1556 deletions
|
@ -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:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
¤tDirEntry,
|
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(¤tDirEntry))
|
|
||||||
{
|
{
|
||||||
if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind))
|
|
||||||
{
|
|
||||||
DPRINT ("Match found, %S\n", currentLongName);
|
|
||||||
status = vfatMakeFCBFromDirEntry (pDeviceExt,
|
|
||||||
pDirectoryFCB,
|
|
||||||
currentLongName,
|
|
||||||
¤tDirEntry,
|
|
||||||
startIndex,
|
|
||||||
directoryIndex,
|
|
||||||
pFoundFCB);
|
|
||||||
CcUnpinData(Context);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
vfatGetDirEntryName (¤tDirEntry, 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,
|
||||||
¤tDirEntry,
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 *****************************************************************/
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 *****************************************************************/
|
||||||
|
|
Loading…
Reference in a new issue