mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/blockdev.c
|
||||
* FILE: drivers/fs/vfat/blockdev.c
|
||||
* PURPOSE: Temporary sector reading support
|
||||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* Hartmut Birr
|
||||
* 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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/cleanup.c
|
||||
* FILE: drivers/fs/vfat/cleanup.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -25,11 +26,10 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext)
|
|||
*/
|
||||
{
|
||||
PVFATFCB pFcb;
|
||||
PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
|
||||
PFILE_OBJECT FileObject = IrpContext->FileObject;
|
||||
|
||||
DPRINT("VfatCleanupFile(DeviceExt %x, FileObject %x)\n",
|
||||
DeviceExt, FileObject);
|
||||
IrpContext->DeviceExt, FileObject);
|
||||
|
||||
/* FIXME: handle file/directory deletion here */
|
||||
pFcb = (PVFATFCB) FileObject->FsContext;
|
||||
|
@ -45,6 +45,11 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext)
|
|||
NULL);
|
||||
}
|
||||
|
||||
if (pFcb->Flags & FCB_IS_DIRTY)
|
||||
{
|
||||
VfatUpdateEntry (pFcb);
|
||||
}
|
||||
|
||||
/* Uninitialize file cache if initialized for this file object. */
|
||||
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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/close.c
|
||||
* FILE: drivers/fs/vfat/close.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -55,7 +56,7 @@ VfatCloseFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
|
|||
{
|
||||
if (pFcb->Flags & FCB_DELETE_PENDING)
|
||||
{
|
||||
delEntry (DeviceExt, FileObject);
|
||||
VfatDelEntry (DeviceExt, pFcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* 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
|
||||
* FILE: services/fs/vfat/create.c
|
||||
* FILE: drivers/fs/vfat/create.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
|
||||
* Hartmut Birr
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -42,73 +42,60 @@
|
|||
|
||||
/* 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;
|
||||
while (fromIndex < 8 && pEntry->Filename [fromIndex] != ' ')
|
||||
memcpy(cString, pEntry->Filename, 11);
|
||||
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)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
}
|
||||
if (pEntry->Ext [0] != ' ')
|
||||
{
|
||||
pName [toIndex++] = L'.';
|
||||
fromIndex = 0;
|
||||
while (fromIndex < 3 && pEntry->Ext [fromIndex] != ' ')
|
||||
{
|
||||
NameU->Length = 0;
|
||||
NameU->MaximumLength -= Length;
|
||||
|
||||
StringA.Buffer = &cString[8];
|
||||
for (StringA.Length = 0;
|
||||
StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
|
||||
StringA.Length++);
|
||||
StringA.MaximumLength = StringA.Length;
|
||||
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
|
||||
if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
|
||||
{
|
||||
pName [toIndex++] = tolower(pEntry->Ext [fromIndex++]);
|
||||
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pName [toIndex++] = pEntry->Ext [fromIndex++];
|
||||
NameU->Buffer -= Length / sizeof(WCHAR);
|
||||
NameU->Length += Length;
|
||||
NameU->MaximumLength += Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
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';
|
||||
NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
|
||||
DPRINT("'%wZ'\n", NameU);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -122,25 +109,31 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
|
|||
FATDirEntry* Entry;
|
||||
PVFATFCB pFcb;
|
||||
LARGE_INTEGER FileOffset;
|
||||
UNICODE_STRING NameU;
|
||||
|
||||
NameU.Buffer = Vpb->VolumeLabel;
|
||||
NameU.Length = 0;
|
||||
NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
|
||||
*(Vpb->VolumeLabel) = 0;
|
||||
Vpb->VolumeLabelLength = 0;
|
||||
|
||||
ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
|
||||
pFcb = vfatOpenRootFCB (DeviceExt);
|
||||
ExReleaseResourceLite (&DeviceExt->DirResource);
|
||||
|
||||
FileOffset.QuadPart = 0;
|
||||
if (CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
if (vfatIsDirEntryVolume(Entry))
|
||||
if (ENTRY_VOLUME(Entry))
|
||||
{
|
||||
/* copy volume label */
|
||||
vfat8Dot3ToVolumeLabel (Entry, Vpb->VolumeLabel);
|
||||
Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel) * sizeof(WCHAR);
|
||||
vfat8Dot3ToString (Entry, &NameU);
|
||||
Vpb->VolumeLabelLength = NameU.Length;
|
||||
break;
|
||||
}
|
||||
if (vfatIsDirEntryEndMarker(Entry))
|
||||
if (ENTRY_END(Entry))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -162,242 +155,183 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
|
|||
CcUnpinData(Context);
|
||||
}
|
||||
}
|
||||
ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
|
||||
vfatReleaseFCB (DeviceExt, pFcb);
|
||||
ExReleaseResourceLite (&DeviceExt->DirResource);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FindFile (PDEVICE_EXTENSION DeviceExt,
|
||||
PVFATFCB Fcb,
|
||||
PVFATFCB Parent,
|
||||
PWSTR FileToFind,
|
||||
ULONG *pDirIndex,
|
||||
ULONG *pDirIndex2)
|
||||
PUNICODE_STRING FileToFindU,
|
||||
PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
BOOLEAN First)
|
||||
/*
|
||||
* FUNCTION: Find a file
|
||||
*/
|
||||
{
|
||||
WCHAR name[256];
|
||||
WCHAR name2[14];
|
||||
WCHAR TempStr[2];
|
||||
WCHAR PathNameBuffer[MAX_PATH];
|
||||
NTSTATUS Status;
|
||||
ULONG len;
|
||||
ULONG DirIndex;
|
||||
ULONG FirstCluster;
|
||||
BOOL isRoot;
|
||||
PVOID Context = NULL;
|
||||
PVOID Page;
|
||||
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);
|
||||
DPRINT ("FindFile: old Pathname %x, old Objectname %x)\n",Fcb->PathName, Fcb->ObjectName);
|
||||
PathNameU.Buffer = PathNameBuffer;
|
||||
PathNameU.Length = 0;
|
||||
PathNameU.MaximumLength = sizeof(PathNameBuffer);
|
||||
|
||||
isRoot = FALSE;
|
||||
DirIndex = 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;
|
||||
DirContext->LongNameU.Length = 0;
|
||||
DirContext->ShortNameU.Length = 0;
|
||||
|
||||
if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0)
|
||||
|| (FileToFind[0] == '.' && FileToFind[1] == 0))
|
||||
/* FIXME: Use FsRtlDoesNameContainWildCards */
|
||||
WildCard = FALSE;
|
||||
curr = FileToFindU->Buffer;
|
||||
last = FileToFindU->Buffer + FileToFindU->Length / sizeof(WCHAR);
|
||||
while (curr < last)
|
||||
{
|
||||
/* it's root : complete essentials fields then return ok */
|
||||
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)
|
||||
if (*curr == L'?' || *curr == L'*')
|
||||
{
|
||||
Fcb->entry.FirstCluster = ((PUSHORT)&FirstCluster)[0];
|
||||
Fcb->entry.FirstClusterHigh = ((PUSHORT)&FirstCluster)[1];
|
||||
WildCard = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
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);
|
||||
curr++;
|
||||
}
|
||||
}
|
||||
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 */
|
||||
len = wcslen(Parent->PathName);
|
||||
memcpy(name, Parent->PathName, len * sizeof(WCHAR));
|
||||
RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
|
||||
if (!vfatFCBIsRoot(Parent))
|
||||
{
|
||||
name[len++] = L'\\';
|
||||
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
|
||||
PathNameU.Length += sizeof(WCHAR);
|
||||
}
|
||||
wcscpy(name + len, FileToFind);
|
||||
rcFcb = vfatGrabFCBFromTable(DeviceExt, name);
|
||||
RtlAppendUnicodeStringToString(&PathNameU, FileToFindU);
|
||||
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
|
||||
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
|
||||
if (rcFcb)
|
||||
{
|
||||
if(rcFcb->startIndex >= DirIndex)
|
||||
if(rcFcb->startIndex >= DirContext->DirIndex)
|
||||
{
|
||||
wcscpy(Fcb->PathName, name);
|
||||
Fcb->ObjectName = &Fcb->PathName[len];
|
||||
memcpy(&Fcb->entry, &rcFcb->entry, sizeof(FATDirEntry));
|
||||
if (pDirIndex)
|
||||
{
|
||||
*pDirIndex = rcFcb->dirIndex;
|
||||
}
|
||||
if (pDirIndex2)
|
||||
{
|
||||
*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;
|
||||
RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
|
||||
RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
|
||||
memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
|
||||
DirContext->StartIndex = rcFcb->startIndex;
|
||||
DirContext->DirIndex = rcFcb->dirIndex;
|
||||
DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
|
||||
&DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
vfatReleaseFCB(DeviceExt, rcFcb);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
CHECKPOINT1;
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
vfatReleaseFCB(DeviceExt, rcFcb);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (vfatIsDirEntryVolume(&fatDirEntry))
|
||||
if (ENTRY_VOLUME(&DirContext->FatDirEntry))
|
||||
{
|
||||
DirIndex++;
|
||||
DirContext->DirIndex++;
|
||||
continue;
|
||||
}
|
||||
vfat8Dot3ToString(&fatDirEntry, name2);
|
||||
if (wstrcmpjoki (name, FileToFind) || wstrcmpjoki (name2, FileToFind))
|
||||
DirContext->LongNameU.Buffer[DirContext->LongNameU.Length / sizeof(WCHAR)] = 0;
|
||||
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);
|
||||
CHECKPOINT;
|
||||
memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR));
|
||||
Fcb->ObjectName=&Fcb->PathName[len];
|
||||
if (len != 1 || Fcb->PathName[0] != '\\')
|
||||
FoundLong = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fcb->ObjectName[0] = '\\';
|
||||
Fcb->ObjectName = &Fcb->ObjectName[1];
|
||||
FoundLong = FALSE;
|
||||
}
|
||||
if (FoundLong == FALSE)
|
||||
{
|
||||
/* FIXME: Use FsRtlIsNameInExpression */
|
||||
FoundShort = wstrcmpjoki (DirContext->ShortNameU.Buffer, FileToFindU->Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
FoundShort = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Fcb->ObjectName=Fcb->PathName;
|
||||
Fcb->ObjectName[0]='\\';
|
||||
Fcb->ObjectName=&Fcb->ObjectName[1];
|
||||
FoundLong = RtlEqualUnicodeString(&DirContext->LongNameU, FileToFindU, TRUE);
|
||||
if (FoundLong == FALSE)
|
||||
{
|
||||
FoundShort = RtlEqualUnicodeString(&DirContext->ShortNameU, FileToFindU, TRUE);
|
||||
}
|
||||
memcpy(&Fcb->entry, &fatDirEntry, sizeof(FATDirEntry));
|
||||
wcsncpy(Fcb->ObjectName, *name == 0 ? name2 : name, MAX_PATH);
|
||||
if (pDirIndex)
|
||||
*pDirIndex = DirIndex;
|
||||
DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb->PathName, Fcb->ObjectName, DirIndex);
|
||||
}
|
||||
|
||||
if (FoundLong || FoundShort)
|
||||
{
|
||||
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)
|
||||
{
|
||||
CcUnpinData(Context);
|
||||
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
DirIndex++;
|
||||
DirContext->DirIndex++;
|
||||
}
|
||||
if (pDirIndex)
|
||||
*pDirIndex = DirIndex;
|
||||
|
||||
if (Context)
|
||||
{
|
||||
CcUnpinData(Context);
|
||||
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
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;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||
PWSTR FileName)
|
||||
PUNICODE_STRING FileNameU)
|
||||
/*
|
||||
* FUNCTION: Opens a file
|
||||
*/
|
||||
|
@ -405,34 +339,40 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
|||
PVFATFCB ParentFcb;
|
||||
PVFATFCB Fcb;
|
||||
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)
|
||||
{
|
||||
DPRINT ("Converting relative filename to absolute filename\n");
|
||||
Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
|
||||
FileName,
|
||||
&AbsFileName);
|
||||
FileName = AbsFileName;
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
||||
NameU.Buffer = Name;
|
||||
NameU.Length = 0;
|
||||
NameU.MaximumLength = sizeof(Name);
|
||||
|
||||
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: %S\n", FileName);
|
||||
DPRINT ("PathName to open: '%wZ'\n", FileNameU);
|
||||
|
||||
/* try first to find an existing FCB in memory */
|
||||
DPRINT ("Checking for existing FCB in memory\n");
|
||||
Fcb = vfatGrabFCBFromTable (DeviceExt, FileName);
|
||||
Fcb = vfatGrabFCBFromTable (DeviceExt, FileNameU);
|
||||
if (Fcb == NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
vfatReleaseFCB (DeviceExt, ParentFcb);
|
||||
|
@ -440,26 +380,17 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
|||
if (!NT_SUCCESS (Status))
|
||||
{
|
||||
DPRINT ("Could not make a new FCB, status: %x\n", Status);
|
||||
|
||||
if (AbsFileName)
|
||||
ExFreePool (AbsFileName);
|
||||
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
if (Fcb->Flags & FCB_DELETE_PENDING)
|
||||
{
|
||||
vfatReleaseFCB (DeviceExt, Fcb);
|
||||
if (AbsFileName)
|
||||
ExFreePool (AbsFileName);
|
||||
return STATUS_DELETE_PENDING;
|
||||
}
|
||||
DPRINT ("Attaching FCB to fileObject\n");
|
||||
Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
|
||||
|
||||
if (AbsFileName)
|
||||
ExFreePool (AbsFileName);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -481,7 +412,7 @@ VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
|||
}
|
||||
Fcb->entry.FirstCluster = 0;
|
||||
Fcb->entry.FirstClusterHigh = 0;
|
||||
VfatUpdateEntry (DeviceExt, FileObject);
|
||||
VfatUpdateEntry (Fcb);
|
||||
if (Fcb->RFCB.FileSize.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
|
||||
*/
|
||||
c = FileObject->FileName.Buffer;
|
||||
while (*c != 0)
|
||||
c = FileObject->FileName.Buffer + FileObject->FileName.Length / sizeof(WCHAR);
|
||||
while (c-- > FileObject->FileName.Buffer)
|
||||
{
|
||||
if (*c == L'*' || *c == L'?' || *c == L'<' || *c == L'>' ||
|
||||
*c == L'/' || *c == L'|' || *c == L':' || *c == L'"' ||
|
||||
(*c == L'\\' && c[1] == L'\\'))
|
||||
if (*c != '\\' && vfatIsLongIllegal(*c))
|
||||
{
|
||||
return(STATUS_OBJECT_NAME_INVALID);
|
||||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -607,7 +535,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
{
|
||||
ULONG Attributes;
|
||||
Attributes = Stack->Parameters.Create.FileAttributes;
|
||||
Status = VfatAddEntry (DeviceExt, FileObject, RequestedOptions,
|
||||
Status = VfatAddEntry (DeviceExt, &FileObject->FileName, FileObject, RequestedOptions,
|
||||
(UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
|
||||
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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/dir.c
|
||||
* FILE: drivers/fs/vfat/dir.c
|
||||
* PURPOSE: VFAT Filesystem : directory control
|
||||
* UPDATE HISTORY:
|
||||
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)))
|
||||
|
||||
NTSTATUS
|
||||
VfatGetFileNameInformation (PVFATFCB pFcb,
|
||||
VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
|
||||
{
|
||||
ULONG Length;
|
||||
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
|
||||
if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||
if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
pInfo->FileNameLength = Length;
|
||||
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
||||
pInfo->NextEntryOffset =
|
||||
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length);
|
||||
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
|
||||
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
|
||||
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
VfatGetFileDirectoryInformation (PVFATFCB pFcb,
|
||||
VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_DIRECTORY_INFORMATION pInfo,
|
||||
ULONG BufferLength)
|
||||
{
|
||||
ULONG Length;
|
||||
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
|
||||
if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||
if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
pInfo->FileNameLength = Length;
|
||||
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
||||
pInfo->NextEntryOffset =
|
||||
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length);
|
||||
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
|
||||
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
|
||||
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
||||
// pInfo->FileIndex=;
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
|
||||
pFcb->entry.CreationTime, &pInfo->CreationTime);
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
|
||||
DirContext->FatDirEntry.CreationTime, &pInfo->CreationTime);
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate, 0,
|
||||
&pInfo->LastAccessTime);
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
|
||||
&pInfo->LastWriteTime);
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
|
||||
DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
|
||||
pInfo->ChangeTime = pInfo->LastWriteTime;
|
||||
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 */
|
||||
pInfo->AllocationSize.u.HighPart = 0;
|
||||
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
|
||||
pInfo->FileAttributes = pFcb->entry.Attrib;
|
||||
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
|
||||
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
VfatGetFileFullDirectoryInformation (PVFATFCB pFcb,
|
||||
VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_FULL_DIRECTORY_INFORMATION pInfo,
|
||||
ULONG BufferLength)
|
||||
{
|
||||
ULONG Length;
|
||||
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
|
||||
if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||
if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
pInfo->FileNameLength = Length;
|
||||
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
||||
pInfo->NextEntryOffset =
|
||||
DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length);
|
||||
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
|
||||
DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
|
||||
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
||||
// pInfo->FileIndex=;
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
|
||||
pFcb->entry.CreationTime, &pInfo->CreationTime);
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
|
||||
&pInfo->LastAccessTime);
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
|
||||
&pInfo->LastWriteTime);
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
|
||||
DirContext->FatDirEntry.CreationTime, &pInfo->CreationTime);
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate,
|
||||
0, &pInfo->LastAccessTime);
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
|
||||
DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
|
||||
pInfo->ChangeTime = pInfo->LastWriteTime;
|
||||
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 */
|
||||
pInfo->AllocationSize.u.HighPart = 0;
|
||||
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
|
||||
pInfo->FileAttributes = pFcb->entry.Attrib;
|
||||
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
|
||||
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
|
||||
// pInfo->EaSize=;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
VfatGetFileBothInformation (PVFATFCB pFcb,
|
||||
VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_BOTH_DIRECTORY_INFORMATION pInfo,
|
||||
ULONG BufferLength)
|
||||
{
|
||||
ULONG Length;
|
||||
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
|
||||
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
pInfo->FileNameLength = Length;
|
||||
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
||||
pInfo->NextEntryOffset =
|
||||
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length);
|
||||
/*
|
||||
* vfatGetDirEntryName must be called befor the long name is copyed.
|
||||
* The terminating null will overwrite the first character from long name.
|
||||
*/
|
||||
vfatGetDirEntryName(&pFcb->entry, pInfo->ShortName);
|
||||
pInfo->ShortNameLength = wcslen(pInfo->ShortName) * sizeof(WCHAR);
|
||||
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
|
||||
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
|
||||
memcpy(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length);
|
||||
pInfo->ShortNameLength = DirContext->ShortNameU.Length;
|
||||
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
||||
// pInfo->FileIndex=;
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
|
||||
pFcb->entry.CreationTime, &pInfo->CreationTime);
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
|
||||
DirContext->FatDirEntry.CreationDate, &pInfo->CreationTime);
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate, 0,
|
||||
&pInfo->LastAccessTime);
|
||||
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
|
||||
&pInfo->LastWriteTime);
|
||||
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
|
||||
DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
|
||||
pInfo->ChangeTime = pInfo->LastWriteTime;
|
||||
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 */
|
||||
pInfo->AllocationSize.u.HighPart = 0;
|
||||
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
|
||||
pInfo->FileAttributes = pFcb->entry.Attrib;
|
||||
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
|
||||
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
|
||||
// pInfo->EaSize=;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -204,101 +192,131 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
|
|||
unsigned char *Buffer = NULL;
|
||||
PFILE_NAMES_INFORMATION Buffer0 = NULL;
|
||||
PVFATFCB pFcb;
|
||||
VFATFCB tmpFcb;
|
||||
PVFATCCB pCcb;
|
||||
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;
|
||||
|
||||
pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
|
||||
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,
|
||||
(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
|
||||
BufferLength = Stack->Parameters.QueryDirectory.Length;
|
||||
/* Obtain the callers parameters */
|
||||
pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
|
||||
FileInformationClass =
|
||||
Stack->Parameters.QueryDirectory.FileInformationClass;
|
||||
FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
|
||||
if (pSearchPattern)
|
||||
{
|
||||
if (!pCcb->DirectorySearchPattern)
|
||||
if (!pCcb->SearchPattern.Buffer)
|
||||
{
|
||||
First = TRUE;
|
||||
pCcb->DirectorySearchPattern =
|
||||
ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR));
|
||||
if (!pCcb->DirectorySearchPattern)
|
||||
pCcb->SearchPattern.MaximumLength = pSearchPattern->Length + sizeof(WCHAR);
|
||||
pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, pCcb->SearchPattern.MaximumLength);
|
||||
if (!pCcb->SearchPattern.Buffer)
|
||||
{
|
||||
ExReleaseResourceLite(&pFcb->MainResource);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer,
|
||||
pSearchPattern->Length);
|
||||
pCcb->DirectorySearchPattern[pSearchPattern->Length / sizeof(WCHAR)] = 0;
|
||||
RtlCopyUnicodeString(&pCcb->SearchPattern, pSearchPattern);
|
||||
pCcb->SearchPattern.Buffer[pCcb->SearchPattern.Length / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
}
|
||||
else if (!pCcb->DirectorySearchPattern)
|
||||
else if (!pCcb->SearchPattern.Buffer)
|
||||
{
|
||||
First = TRUE;
|
||||
pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
|
||||
if (!pCcb->DirectorySearchPattern)
|
||||
pCcb->SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
|
||||
pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
|
||||
if (!pCcb->SearchPattern.Buffer)
|
||||
{
|
||||
ExReleaseResourceLite(&pFcb->MainResource);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
pCcb->DirectorySearchPattern[0] = L'*';
|
||||
pCcb->DirectorySearchPattern[1] = 0;
|
||||
pCcb->SearchPattern.Buffer[0] = L'*';
|
||||
pCcb->SearchPattern.Buffer[1] = 0;
|
||||
pCcb->SearchPattern.Length = sizeof(WCHAR);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
pCcb->Entry = 0;
|
||||
}
|
||||
// determine Buffer for result :
|
||||
if (IrpContext->Irp->MdlAddress)
|
||||
{
|
||||
Buffer = MmGetSystemAddressForMdl (IrpContext->Irp->MdlAddress);
|
||||
DirContext.DirIndex = pCcb->Entry = 0;
|
||||
FirstCall = TRUE;
|
||||
}
|
||||
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)
|
||||
{
|
||||
RC = FindFile (IrpContext->DeviceExt, &tmpFcb, pFcb,
|
||||
pCcb->DirectorySearchPattern, &pCcb->Entry, NULL);
|
||||
DPRINT ("Found %S, RC=%x, entry %x\n", tmpFcb.ObjectName, RC, pCcb->Entry);
|
||||
RC = FindFile (IrpContext->DeviceExt, pFcb,
|
||||
&pCcb->SearchPattern, &DirContext, FirstCall);
|
||||
pCcb->Entry = DirContext.DirIndex;
|
||||
DPRINT ("Found %wZ, RC=%x, entry %x\n", &DirContext.LongNameU, RC, pCcb->Entry);
|
||||
FirstCall = FALSE;
|
||||
if (NT_SUCCESS (RC))
|
||||
{
|
||||
switch (FileInformationClass)
|
||||
{
|
||||
case FileNameInformation:
|
||||
RC = VfatGetFileNameInformation (&tmpFcb,
|
||||
(PFILE_NAMES_INFORMATION) Buffer, BufferLength);
|
||||
RC = VfatGetFileNameInformation (&DirContext,
|
||||
(PFILE_NAMES_INFORMATION) Buffer,
|
||||
BufferLength);
|
||||
break;
|
||||
case FileDirectoryInformation:
|
||||
RC = VfatGetFileDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
|
||||
(PFILE_DIRECTORY_INFORMATION) Buffer, BufferLength);
|
||||
RC = VfatGetFileDirectoryInformation (&DirContext,
|
||||
IrpContext->DeviceExt,
|
||||
(PFILE_DIRECTORY_INFORMATION) Buffer,
|
||||
BufferLength);
|
||||
break;
|
||||
case FileFullDirectoryInformation:
|
||||
RC = VfatGetFileFullDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
|
||||
(PFILE_FULL_DIRECTORY_INFORMATION) Buffer, BufferLength);
|
||||
RC = VfatGetFileFullDirectoryInformation (&DirContext,
|
||||
IrpContext->DeviceExt,
|
||||
(PFILE_FULL_DIRECTORY_INFORMATION) Buffer,
|
||||
BufferLength);
|
||||
break;
|
||||
case FileBothDirectoryInformation:
|
||||
RC = VfatGetFileBothInformation (&tmpFcb, IrpContext->DeviceExt,
|
||||
(PFILE_BOTH_DIRECTORY_INFORMATION) Buffer, BufferLength);
|
||||
RC = VfatGetFileBothInformation (&DirContext,
|
||||
IrpContext->DeviceExt,
|
||||
(PFILE_BOTH_DIRECTORY_INFORMATION) Buffer,
|
||||
BufferLength);
|
||||
break;
|
||||
default:
|
||||
RC = STATUS_INVALID_INFO_CLASS;
|
||||
|
@ -330,7 +348,7 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
|
|||
}
|
||||
Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
|
||||
Buffer0->FileIndex = FileIndex++;
|
||||
pCcb->Entry++;
|
||||
pCcb->Entry = ++DirContext.DirIndex;
|
||||
if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
|
||||
{
|
||||
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
|
||||
|
@ -7,6 +7,7 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Rex Jolliff (rex@lvcablemodem.com)
|
||||
* Hartmut Birr
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------- INCLUDES */
|
||||
|
@ -41,44 +42,64 @@ vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
|
|||
return cluster;
|
||||
}
|
||||
|
||||
BOOL
|
||||
vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry)
|
||||
BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
|
||||
{
|
||||
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
|
||||
vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry)
|
||||
{
|
||||
return pFatDirEntry->Filename [0] == 0;
|
||||
}
|
||||
FileOffset.QuadPart = 0LL;
|
||||
MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY);
|
||||
|
||||
BOOL
|
||||
vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry)
|
||||
while (Index < MaxIndex)
|
||||
{
|
||||
return pFatDirEntry->Attrib == 0x0f;
|
||||
}
|
||||
|
||||
BOOL
|
||||
vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry)
|
||||
if (Context == NULL || (Index % ENTRIES_PER_PAGE) == 0)
|
||||
{
|
||||
return 0x08 == (pFatDirEntry->Attrib & 0x1f);
|
||||
}
|
||||
|
||||
void
|
||||
vfatGetDirEntryName (PFAT_DIR_ENTRY dirEntry, PWSTR entryName)
|
||||
if (Context != NULL)
|
||||
{
|
||||
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,
|
||||
PVOID * pPage,
|
||||
IN PVFATFCB pDirFcb,
|
||||
IN OUT PULONG pDirIndex,
|
||||
OUT PWSTR pFileName,
|
||||
OUT PFAT_DIR_ENTRY pDirEntry,
|
||||
OUT PULONG pStartIndex)
|
||||
PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
BOOLEAN First)
|
||||
{
|
||||
ULONG dirMap;
|
||||
PWCHAR pName;
|
||||
|
@ -87,12 +108,17 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
|
|||
slot * longNameEntry;
|
||||
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.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)
|
||||
{
|
||||
|
@ -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;
|
||||
dirMap = 0;
|
||||
|
||||
if (pStartIndex)
|
||||
if (First)
|
||||
{
|
||||
*pStartIndex = *pDirIndex;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
/* 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 (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);
|
||||
FileOffset.u.LowPart -= PAGE_SIZE;
|
||||
if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
|
||||
{
|
||||
CHECKPOINT;
|
||||
*pContext = NULL;
|
||||
return STATUS_NO_MORE_ENTRIES;
|
||||
}
|
||||
|
||||
if (vfatIsDirEntryDeleted (fatDirEntry))
|
||||
{
|
||||
dirMap = 0;
|
||||
*pFileName = 0;
|
||||
if (pStartIndex)
|
||||
{
|
||||
*pStartIndex = *pDirIndex + 1;
|
||||
}
|
||||
fatDirEntry = (FATDirEntry*)(*pPage) + DirContext->DirIndex % ENTRIES_PER_PAGE;
|
||||
longNameEntry = (slot*) fatDirEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vfatIsDirEntryLongName (fatDirEntry))
|
||||
fatDirEntry--;
|
||||
longNameEntry--;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ENTRY_END(fatDirEntry) &&
|
||||
(ENTRY_DELETED(fatDirEntry) || !ENTRY_LONG(fatDirEntry)))
|
||||
{
|
||||
if (dirMap == 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)
|
||||
DirContext->DirIndex++;
|
||||
if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
|
||||
{
|
||||
CcUnpinData(*pContext);
|
||||
FileOffset.u.LowPart += PAGE_SIZE;
|
||||
|
@ -184,6 +192,109 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/dirwr.c
|
||||
* FILE: drivers/fs/vfat/dirwr.c
|
||||
* PURPOSE: VFAT Filesystem : write in directory
|
||||
*
|
||||
*/
|
||||
|
@ -19,56 +19,41 @@
|
|||
|
||||
#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
|
||||
VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||
VfatUpdateEntry (PVFATFCB pFcb)
|
||||
/*
|
||||
* update an existing FAT entry
|
||||
*/
|
||||
{
|
||||
PVOID Context;
|
||||
PVOID Buffer;
|
||||
PVFATFCB pDirFcb, pFcb;
|
||||
PFAT_DIR_ENTRY PinEntry;
|
||||
LARGE_INTEGER Offset;
|
||||
|
||||
/*
|
||||
DPRINT ("updEntry PathFileName \'%S\'\n",
|
||||
((PVFATCCB)(pFileObject->FsContext2))->pFcb->PathName);
|
||||
*/
|
||||
|
||||
pFcb = (PVFATFCB)pFileObject->FsContext;
|
||||
assert (pFcb);
|
||||
pDirFcb = pFcb->parentFcb;
|
||||
assert (pDirFcb);
|
||||
assert (pFcb->parentFcb);
|
||||
|
||||
DPRINT ("updEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
|
||||
|
||||
Offset.u.HighPart = 0;
|
||||
Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry);
|
||||
if (CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry),
|
||||
TRUE, &Context, (PVOID*)&Buffer))
|
||||
if (CcMapData (pFcb->parentFcb->FileObject, &Offset, sizeof(FATDirEntry),
|
||||
TRUE, &Context, (PVOID*)&PinEntry))
|
||||
{
|
||||
memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry));
|
||||
pFcb->Flags &= ~FCB_IS_DIRTY;
|
||||
*PinEntry = pFcb->entry;
|
||||
CcSetDirtyPinnedData(Context, NULL);
|
||||
CcUnpinData(Context);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
{
|
||||
DPRINT1 ("Failed write to \'%wZ\'.\n", &pFcb->parentFcb->PathNameU);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
findDirSpace(PDEVICE_EXTENSION DeviceExt,
|
||||
vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
|
||||
PVFATFCB pDirFcb,
|
||||
ULONG nbSlots,
|
||||
PULONG start)
|
||||
|
@ -98,11 +83,11 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
|
|||
TRUE, &Context, (PVOID*)&pFatEntry);
|
||||
FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
|
||||
}
|
||||
if (vfatIsDirEntryEndMarker(pFatEntry))
|
||||
if (ENTRY_END(pFatEntry))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (vfatIsDirEntryDeleted(pFatEntry))
|
||||
if (ENTRY_DELETED(pFatEntry))
|
||||
{
|
||||
nbFree++;
|
||||
}
|
||||
|
@ -172,6 +157,7 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
|
|||
|
||||
NTSTATUS
|
||||
VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
||||
PUNICODE_STRING PathNameU,
|
||||
PFILE_OBJECT pFileObject,
|
||||
ULONG RequestedOptions,
|
||||
UCHAR ReqAttr)
|
||||
|
@ -179,279 +165,190 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
create a new FAT entry
|
||||
*/
|
||||
{
|
||||
WCHAR DirName[MAX_PATH], *FileName, *PathFileName;
|
||||
VFATFCB FileFcb;
|
||||
PVOID Context = NULL;
|
||||
FATDirEntry *pFatEntry, *pEntry;
|
||||
FATDirEntry *pFatEntry;
|
||||
slot *pSlots;
|
||||
short nbSlots = 0, nbFree = 0, j, posCar, NameLen;
|
||||
short nbSlots = 0, j, posCar;
|
||||
PUCHAR Buffer;
|
||||
BOOLEAN needTilde = FALSE, needLong = FALSE;
|
||||
BOOLEAN lCaseBase, uCaseBase, lCaseExt, uCaseExt;
|
||||
BOOLEAN lCaseBase = FALSE, uCaseBase, lCaseExt = FALSE, uCaseExt;
|
||||
PVFATFCB newFCB;
|
||||
ULONG CurrentCluster;
|
||||
LARGE_INTEGER SystemTime, LocalTime, FileOffset;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PVFATFCB pDirFcb;
|
||||
ULONG start, size;
|
||||
ULONG size;
|
||||
long i;
|
||||
|
||||
PathFileName = pFileObject->FileName.Buffer;
|
||||
DPRINT ("addEntry: Pathname=%S\n", PathFileName);
|
||||
//find last \ in PathFileName
|
||||
posCar = -1;
|
||||
for (i = 0; PathFileName[i]; i++)
|
||||
ANSI_STRING NameA;
|
||||
CHAR aName[13];
|
||||
BOOLEAN IsNameLegal;
|
||||
BOOLEAN SpacesFound;
|
||||
|
||||
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'\\')
|
||||
{
|
||||
posCar = (short)i;
|
||||
DirNameU.Length -= sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
if (posCar == -1)
|
||||
{
|
||||
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);
|
||||
|
||||
pDirFcb = vfatGrabFCBFromTable(DeviceExt, &DirNameU);
|
||||
if (pDirFcb == NULL)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
nbSlots = (NameLen + 12) / 13 + 1; //nb of entry needed for long name+normal entry
|
||||
DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots);
|
||||
Buffer = ExAllocatePool (NonPagedPool, nbSlots * sizeof (FATDirEntry));
|
||||
RtlZeroMemory (Buffer, nbSlots * sizeof (FATDirEntry));
|
||||
pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry));
|
||||
nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1; //nb of entry needed for long name+normal entry
|
||||
DPRINT ("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
|
||||
Buffer = ExAllocatePool (NonPagedPool, (nbSlots - 1) * sizeof (FATDirEntry));
|
||||
RtlZeroMemory (Buffer, (nbSlots - 1) * sizeof (FATDirEntry));
|
||||
pSlots = (slot *) Buffer;
|
||||
// create 8.3 name
|
||||
needTilde = FALSE;
|
||||
// find last point in name
|
||||
posCar = j = 0;
|
||||
for (i = 0; FileName[i]; i++)
|
||||
|
||||
NameA.Buffer = aName;
|
||||
NameA.Length = 0;
|
||||
NameA.MaximumLength = sizeof(aName);
|
||||
|
||||
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] == '.')
|
||||
{
|
||||
posCar = (short)i;
|
||||
if (i == j)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!posCar)
|
||||
{
|
||||
posCar = (short)i;
|
||||
}
|
||||
if (posCar < j)
|
||||
{
|
||||
posCar = (short)i;
|
||||
GENERATE_NAME_CONTEXT NameContext;
|
||||
VFAT_DIRENTRY_CONTEXT SearchContext;
|
||||
WCHAR ShortSearchName[13];
|
||||
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;
|
||||
DPRINT ("searching a good value for tilde\n");
|
||||
for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++);
|
||||
if (posCar == 0) // ??????????????????????
|
||||
memset(&NameContext, 0, sizeof(GENERATE_NAME_CONTEXT));
|
||||
SearchContext.LongNameU.Buffer = LongNameBuffer;
|
||||
SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
|
||||
SearchContext.ShortNameU.Buffer = ShortSearchName;
|
||||
SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
pEntry->Filename[posCar++] = '_';
|
||||
}
|
||||
posCar += 2;
|
||||
if (posCar > 8)
|
||||
{
|
||||
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);
|
||||
RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU);
|
||||
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
|
||||
SearchContext.DirIndex = 0;
|
||||
Status = FindFile (DeviceExt, pDirFcb, &DirContext.ShortNameU, &SearchContext, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 10)
|
||||
{
|
||||
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 ?
|
||||
if (i == 100) /* FIXME : what to do after this ? */
|
||||
{
|
||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||
ExFreePool (Buffer);
|
||||
CHECKPOINT;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);
|
||||
aName[NameA.Length]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT ("check if long name entry needed, needlong=%d\n", needLong);
|
||||
lCaseBase = uCaseBase = lCaseExt = uCaseExt = FALSE;
|
||||
for (i = 0; i < posCar; i++)
|
||||
aName[NameA.Length] = 0;
|
||||
for (posCar = 0; posCar < DirContext.LongNameU.Length / sizeof(WCHAR); posCar++)
|
||||
{
|
||||
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]);
|
||||
lCaseBase = TRUE;
|
||||
break;
|
||||
}
|
||||
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]);
|
||||
uCaseBase = TRUE;
|
||||
i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
|
||||
uCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
|
||||
DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]);
|
||||
needLong = TRUE;
|
||||
uCaseExt = FALSE;
|
||||
}
|
||||
}
|
||||
if (FileName[i])
|
||||
/* check if the name and the extension contains lower case characters */
|
||||
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
|
||||
for (j = 0, i = posCar + 1; FileName[i] && i < posCar + 4; i++, j++)
|
||||
{
|
||||
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;
|
||||
i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
|
||||
lCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
|
||||
DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Ext[j], FileName[i]);
|
||||
needLong = TRUE;
|
||||
}
|
||||
}
|
||||
lCaseExt = FALSE;
|
||||
}
|
||||
if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt))
|
||||
{
|
||||
CHECKPOINT;
|
||||
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;
|
||||
memcpy (Buffer, pEntry, sizeof (FATDirEntry));
|
||||
memset (pEntry, 0, sizeof (FATDirEntry));
|
||||
pEntry = (FATDirEntry *) Buffer;
|
||||
if (lCaseBase)
|
||||
{
|
||||
pEntry->lCase |= VFAT_CASE_LOWER_BASE;
|
||||
DirContext.FatDirEntry.Filename[i] = aName[i];
|
||||
}
|
||||
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
|
||||
{
|
||||
memset (DirName, 0xff, sizeof (DirName));
|
||||
memcpy (DirName, FileName, NameLen * sizeof (WCHAR));
|
||||
DirName[NameLen] = 0;
|
||||
nbSlots = 1;
|
||||
if (lCaseBase)
|
||||
{
|
||||
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 */
|
||||
pEntry->Attrib = ReqAttr;
|
||||
DirContext.FatDirEntry.Attrib = ReqAttr;
|
||||
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
||||
{
|
||||
pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
DirContext.FatDirEntry.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
/* set dates and times */
|
||||
KeQuerySystemTime (&SystemTime);
|
||||
|
@ -466,22 +363,22 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
pFileObject->FileName.Buffer);
|
||||
}
|
||||
#endif
|
||||
FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &pEntry->CreationDate,
|
||||
&pEntry->CreationTime);
|
||||
pEntry->UpdateDate = pEntry->CreationDate;
|
||||
pEntry->UpdateTime = pEntry->CreationTime;
|
||||
pEntry->AccessDate = pEntry->CreationDate;
|
||||
FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &DirContext.FatDirEntry.CreationDate,
|
||||
&DirContext.FatDirEntry.CreationTime);
|
||||
DirContext.FatDirEntry.UpdateDate = DirContext.FatDirEntry.CreationDate;
|
||||
DirContext.FatDirEntry.UpdateTime = DirContext.FatDirEntry.CreationTime;
|
||||
DirContext.FatDirEntry.AccessDate = DirContext.FatDirEntry.CreationDate;
|
||||
|
||||
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++)
|
||||
{
|
||||
pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
|
||||
| ((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--)
|
||||
{
|
||||
DPRINT ("construct slot %d\n", i);
|
||||
|
@ -495,20 +392,19 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
pSlots[i].id = nbSlots - i - 1 + 0x40;
|
||||
}
|
||||
pSlots[i].alias_checksum = pSlots[0].alias_checksum;
|
||||
//FIXME pSlots[i].start=;
|
||||
memcpy (pSlots[i].name0_4, DirName + (nbSlots - i - 2) * 13, 10);
|
||||
memcpy (pSlots[i].name5_10, DirName + (nbSlots - i - 2) * 13 + 5, 12);
|
||||
memcpy (pSlots[i].name11_12, DirName + (nbSlots - i - 2) * 13 + 11, 4);
|
||||
memcpy (pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
|
||||
memcpy (pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
|
||||
memcpy (pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
|
||||
}
|
||||
}
|
||||
//try to find nbSlots contiguous entries frees in directory
|
||||
if (!findDirSpace(DeviceExt, pDirFcb, nbSlots, &start))
|
||||
/* try to find nbSlots contiguous entries frees in directory */
|
||||
if (!vfatFindDirSpace(DeviceExt, pDirFcb, nbSlots, &DirContext.StartIndex))
|
||||
{
|
||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||
ExFreePool (Buffer);
|
||||
return STATUS_DISK_FULL;
|
||||
}
|
||||
|
||||
DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
|
||||
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
||||
{
|
||||
CurrentCluster = 0xffffffff;
|
||||
|
@ -525,28 +421,33 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
}
|
||||
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.LowPart = start * sizeof(FATDirEntry);
|
||||
if (start / size == (start + nbSlots - 1) / size)
|
||||
FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FATDirEntry);
|
||||
if (DirContext.StartIndex / i == DirContext.DirIndex / i)
|
||||
{
|
||||
// one cluster
|
||||
/* one cluster */
|
||||
CHECKPOINT;
|
||||
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry),
|
||||
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
|
||||
{
|
||||
// two clusters
|
||||
/* two clusters */
|
||||
CHECKPOINT;
|
||||
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,
|
||||
&Context, (PVOID*)&pFatEntry);
|
||||
memcpy(pFatEntry, Buffer, size);
|
||||
|
@ -556,49 +457,41 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
CcMapData (pDirFcb->FileObject, &FileOffset,
|
||||
nbSlots * sizeof(FATDirEntry) - size,
|
||||
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);
|
||||
CcUnpinData(Context);
|
||||
|
||||
// FIXME: check status
|
||||
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, pEntry,
|
||||
start, start + nbSlots - 1, &newFCB);
|
||||
/* FIXME: check status */
|
||||
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, &DirContext, &newFCB);
|
||||
vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject);
|
||||
|
||||
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)
|
||||
{
|
||||
FileOffset.QuadPart = 0;
|
||||
CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
|
||||
&Context, (PVOID*)&pFatEntry);
|
||||
// clear the new directory cluster
|
||||
/* clear the new directory cluster */
|
||||
RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
|
||||
// create '.' and '..'
|
||||
memcpy (&pFatEntry[0].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11);
|
||||
/* create '.' and '..' */
|
||||
memcpy (&pFatEntry[0].Attrib, &DirContext.FatDirEntry.Attrib, sizeof(FATDirEntry) - 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);
|
||||
pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster;
|
||||
pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh;
|
||||
if (DeviceExt->FatInfo.FatType == FAT32)
|
||||
{
|
||||
if (pFatEntry[1].FirstCluster == (DeviceExt->FatInfo.RootCluster & 0xffff) &&
|
||||
pFatEntry[1].FirstClusterHigh == (DeviceExt->FatInfo.RootCluster >> 16))
|
||||
if (vfatFCBIsRoot(pDirFcb))
|
||||
{
|
||||
pFatEntry[1].FirstCluster = 0;
|
||||
pFatEntry[1].FirstClusterHigh = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pFatEntry[1].FirstCluster == 1)
|
||||
{
|
||||
pFatEntry[1].FirstCluster = 0;
|
||||
}
|
||||
}
|
||||
CcSetDirtyPinnedData(Context, NULL);
|
||||
CcUnpinData(Context);
|
||||
}
|
||||
|
@ -609,48 +502,23 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||
VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
|
||||
/*
|
||||
* deleting an existing FAT entry
|
||||
*/
|
||||
{
|
||||
VFATFCB Fcb;
|
||||
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))
|
||||
{
|
||||
ULONG CurrentCluster = 0, NextCluster, i;
|
||||
PVOID Context = NULL;
|
||||
LARGE_INTEGER Offset;
|
||||
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;
|
||||
for (i = startEntry; i <= Entry; i++)
|
||||
for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
|
||||
{
|
||||
if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGE_SIZE) == 0)
|
||||
{
|
||||
|
@ -660,11 +528,11 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
|||
CcUnpinData(Context);
|
||||
}
|
||||
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);
|
||||
}
|
||||
pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5;
|
||||
if (i == Entry)
|
||||
if (i == pFcb->dirIndex)
|
||||
{
|
||||
CurrentCluster =
|
||||
vfatDirEntryGetFirstCluster (DeviceExt,
|
||||
|
@ -680,13 +548,11 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
|||
while (CurrentCluster && CurrentCluster != 0xffffffff)
|
||||
{
|
||||
GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE);
|
||||
// FIXME: check status
|
||||
/* FIXME: check status */
|
||||
WriteCluster(DeviceExt, CurrentCluster, 0);
|
||||
CurrentCluster = NextCluster;
|
||||
}
|
||||
}
|
||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||
return status;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* 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
|
||||
* FILE: services/fs/vfat/ea.c
|
||||
* FILE: drivers/fs/vfat/ea.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* 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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/fat.c
|
||||
* FILE: drivers/fs/vfat/fat.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -143,7 +144,7 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
ULONG ChunkSize;
|
||||
PVOID Context = 0;
|
||||
LARGE_INTEGER Offset;
|
||||
PUSHORT Block;
|
||||
PUSHORT Block = NULL;
|
||||
|
||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2;
|
||||
|
@ -256,7 +257,7 @@ FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
|||
ULONG ChunkSize;
|
||||
PVOID Context = 0;
|
||||
LARGE_INTEGER Offset;
|
||||
PULONG Block;
|
||||
PULONG Block = NULL;
|
||||
|
||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4;
|
||||
|
@ -354,7 +355,7 @@ FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
|||
* FUNCTION: Counts free clusters in a FAT16 table
|
||||
*/
|
||||
{
|
||||
PUSHORT Block;
|
||||
PUSHORT Block = NULL;
|
||||
PVOID BaseAddress = NULL;
|
||||
ULONG ulCount = 0;
|
||||
ULONG i;
|
||||
|
@ -400,7 +401,7 @@ FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
|||
* FUNCTION: Counts free clusters in a FAT32 table
|
||||
*/
|
||||
{
|
||||
PULONG Block;
|
||||
PULONG Block = NULL;
|
||||
PVOID BaseAddress = NULL;
|
||||
ULONG ulCount = 0;
|
||||
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.
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Rex Jolliff (rex@lvcablemodem.com)
|
||||
* Hartmut Birr
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------- INCLUDES */
|
||||
|
@ -30,35 +31,79 @@
|
|||
|
||||
/* -------------------------------------------------------- PUBLICS */
|
||||
|
||||
ULONG vfatNameHash(ULONG hash, PWCHAR name)
|
||||
ULONG vfatNameHash(ULONG hash, PUNICODE_STRING NameU)
|
||||
{
|
||||
WCHAR c;
|
||||
while(c = *name++)
|
||||
PWCHAR last;
|
||||
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;
|
||||
}
|
||||
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
|
||||
vfatNewFCB(PWCHAR pFileName)
|
||||
vfatNewFCB(PUNICODE_STRING pFileNameU)
|
||||
{
|
||||
PVFATFCB rcFCB;
|
||||
|
||||
DPRINT("'%wZ'\n", pFileNameU);
|
||||
|
||||
rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList);
|
||||
if (rcFCB == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(rcFCB, 0, sizeof(VFATFCB));
|
||||
if (pFileName)
|
||||
{
|
||||
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);
|
||||
}
|
||||
vfatInitFcb(rcFCB, pFileNameU);
|
||||
rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
|
||||
rcFCB->Hash.self = rcFCB;
|
||||
rcFCB->ShortHash.self = rcFCB;
|
||||
ExInitializeResourceLite(&rcFCB->PagingIoResource);
|
||||
|
@ -70,9 +115,9 @@ vfatNewFCB(PWCHAR pFileName)
|
|||
VOID
|
||||
vfatDestroyCCB(PVFATCCB pCcb)
|
||||
{
|
||||
if (pCcb->DirectorySearchPattern)
|
||||
if (pCcb->SearchPattern.Buffer)
|
||||
{
|
||||
ExFreePool(pCcb->DirectorySearchPattern);
|
||||
ExFreePool(pCcb->SearchPattern.Buffer);
|
||||
}
|
||||
ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb);
|
||||
}
|
||||
|
@ -95,28 +140,26 @@ vfatFCBIsDirectory(PVFATFCB FCB)
|
|||
BOOL
|
||||
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
|
||||
vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
HASHENTRY* entry;
|
||||
ULONG Index;
|
||||
ULONG ShortIndex;
|
||||
PVFATFCB tmpFcb;
|
||||
|
||||
DPRINT ("releasing FCB at %x: %S, refCount:%d\n",
|
||||
DPRINT ("releasing FCB at %x: %wZ, refCount:%d\n",
|
||||
pFCB,
|
||||
pFCB->PathName,
|
||||
&pFCB->PathNameU,
|
||||
pFCB->RefCount);
|
||||
|
||||
while (pFCB)
|
||||
{
|
||||
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
|
||||
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
|
||||
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
||||
pFCB->RefCount--;
|
||||
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;
|
||||
}
|
||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||
if (vfatFCBIsDirectory(pFCB))
|
||||
{
|
||||
/* Uninitialize file cache if initialized for this file object. */
|
||||
|
@ -168,7 +210,6 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
|||
}
|
||||
else
|
||||
{
|
||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||
tmpFcb = NULL;
|
||||
}
|
||||
pFCB = tmpFcb;
|
||||
|
@ -178,13 +219,12 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
|||
VOID
|
||||
vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
ULONG Index;
|
||||
ULONG ShortIndex;
|
||||
|
||||
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
|
||||
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
|
||||
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
||||
|
||||
InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry);
|
||||
|
||||
pFCB->Hash.next = pVCB->FcbHashTable[Index];
|
||||
|
@ -198,69 +238,58 @@ vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
|||
{
|
||||
pFCB->parentFcb->RefCount++;
|
||||
}
|
||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||
}
|
||||
|
||||
PVFATFCB
|
||||
vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PWSTR pFileName)
|
||||
vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PUNICODE_STRING PathNameU)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PVFATFCB rcFCB;
|
||||
ULONG Hash;
|
||||
PWCHAR ObjectName = NULL;
|
||||
ULONG len;
|
||||
UNICODE_STRING DirNameU;
|
||||
UNICODE_STRING FileNameU;
|
||||
PUNICODE_STRING FcbNameU;
|
||||
|
||||
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];
|
||||
if (entry)
|
||||
{
|
||||
vfatSplitPathName(PathNameU, &DirNameU, &FileNameU);
|
||||
}
|
||||
|
||||
while (entry)
|
||||
{
|
||||
if (entry->Hash == Hash)
|
||||
{
|
||||
rcFCB = entry->self;
|
||||
DPRINT("'%wZ' '%wZ'\n", &DirNameU, &rcFCB->DirNameU);
|
||||
if (RtlEqualUnicodeString(&DirNameU, &rcFCB->DirNameU, TRUE))
|
||||
{
|
||||
if (rcFCB->Hash.Hash == Hash)
|
||||
{
|
||||
/* compare the long name */
|
||||
if (!_wcsicmp(pFileName, rcFCB->PathName))
|
||||
{
|
||||
rcFCB->RefCount++;
|
||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||
return rcFCB;
|
||||
}
|
||||
FcbNameU = &rcFCB->LongNameU;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = rcFCB->ObjectName - rcFCB->PathName + 1;
|
||||
if (ObjectName == NULL)
|
||||
{
|
||||
ObjectName = wcsrchr(pFileName, L'\\');
|
||||
if (ObjectName == NULL)
|
||||
{
|
||||
ObjectName = pFileName;
|
||||
FcbNameU = &rcFCB->ShortNameU;
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectName++;
|
||||
}
|
||||
}
|
||||
|
||||
/* compare the short name and the directory */
|
||||
if (!_wcsicmp(ObjectName, rcFCB->ShortName) && !_wcsnicmp(pFileName, rcFCB->PathName, len))
|
||||
/* compare the file name */
|
||||
DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU);
|
||||
if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE))
|
||||
{
|
||||
rcFCB->RefCount++;
|
||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||
CHECKPOINT;
|
||||
return rcFCB;
|
||||
}
|
||||
}
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||
|
||||
CHECKPOINT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -310,11 +339,12 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB)
|
|||
PVFATFCB FCB;
|
||||
ULONG FirstCluster, CurrentCluster, Size = 0;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
UNICODE_STRING NameU;
|
||||
|
||||
FCB = vfatNewFCB(L"\\");
|
||||
RtlInitUnicodeStringFromLiteral(&NameU, L"\\");
|
||||
|
||||
FCB = vfatNewFCB(&NameU);
|
||||
memset(FCB->entry.Filename, ' ', 11);
|
||||
FCB->ShortName[0] = L'\\';
|
||||
FCB->ShortName[1] = 0;
|
||||
FCB->ShortHash.Hash = FCB->Hash.Hash;
|
||||
FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
|
||||
FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||
|
@ -351,8 +381,11 @@ PVFATFCB
|
|||
vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
|
||||
{
|
||||
PVFATFCB FCB;
|
||||
UNICODE_STRING NameU;
|
||||
|
||||
FCB = vfatGrabFCBFromTable (pVCB, L"\\");
|
||||
RtlInitUnicodeStringFromLiteral(&NameU, L"\\");
|
||||
|
||||
FCB = vfatGrabFCBFromTable (pVCB, &NameU);
|
||||
if (FCB == NULL)
|
||||
{
|
||||
FCB = vfatMakeRootFCB (pVCB);
|
||||
|
@ -364,42 +397,44 @@ vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
|
|||
NTSTATUS
|
||||
vfatMakeFCBFromDirEntry(PVCB vcb,
|
||||
PVFATFCB directoryFCB,
|
||||
PWSTR longName,
|
||||
PFAT_DIR_ENTRY dirEntry,
|
||||
ULONG startIndex,
|
||||
ULONG dirIndex,
|
||||
PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
PVFATFCB* fileFCB)
|
||||
{
|
||||
PVFATFCB rcFCB;
|
||||
WCHAR pathName [MAX_PATH];
|
||||
WCHAR entryName [14];
|
||||
ULONG Size;
|
||||
ULONG hash;
|
||||
|
||||
if (longName [0] != 0 && wcslen (directoryFCB->PathName) +
|
||||
sizeof(WCHAR) + wcslen (longName) > MAX_PATH)
|
||||
UNICODE_STRING NameU;
|
||||
|
||||
if (directoryFCB->PathNameU.Length + 2 * sizeof(WCHAR) +
|
||||
+ DirContext->LongNameU.Length > MAX_PATH * sizeof(WCHAR))
|
||||
{
|
||||
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))
|
||||
{
|
||||
wcscat (pathName, L"\\");
|
||||
RtlAppendUnicodeToString(&NameU, L"\\");
|
||||
}
|
||||
hash = vfatNameHash(0, pathName);
|
||||
vfatGetDirEntryName (dirEntry, entryName);
|
||||
if (longName [0] != 0)
|
||||
hash = vfatNameHash(0, &NameU);
|
||||
if (DirContext->LongNameU.Length > 0)
|
||||
{
|
||||
wcscat (pathName, longName);
|
||||
RtlAppendUnicodeStringToString(&NameU, &DirContext->LongNameU);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat (pathName, entryName);
|
||||
RtlAppendUnicodeStringToString(&NameU, &DirContext->ShortNameU);
|
||||
}
|
||||
rcFCB = vfatNewFCB (pathName);
|
||||
memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY));
|
||||
wcscpy(rcFCB->ShortName, entryName);
|
||||
rcFCB->ShortHash.Hash = vfatNameHash(hash, entryName);
|
||||
NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
|
||||
rcFCB = vfatNewFCB (&NameU);
|
||||
memcpy (&rcFCB->entry, &DirContext->FatDirEntry, sizeof (FAT_DIR_ENTRY));
|
||||
RtlCopyUnicodeString(&rcFCB->ShortNameU, &DirContext->ShortNameU);
|
||||
rcFCB->ShortHash.Hash = vfatNameHash(hash, &rcFCB->ShortNameU);
|
||||
|
||||
if (vfatFCBIsDirectory(rcFCB))
|
||||
{
|
||||
|
@ -425,8 +460,8 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
|
|||
{
|
||||
Size = rcFCB->entry.FileSize;
|
||||
}
|
||||
rcFCB->dirIndex = dirIndex;
|
||||
rcFCB->startIndex = startIndex;
|
||||
rcFCB->dirIndex = DirContext->DirIndex;
|
||||
rcFCB->startIndex = DirContext->StartIndex;
|
||||
rcFCB->RFCB.FileSize.QuadPart = Size;
|
||||
rcFCB->RFCB.ValidDataLength.QuadPart = Size;
|
||||
rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster);
|
||||
|
@ -452,6 +487,7 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
|
|||
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
||||
if (newCCB == NULL)
|
||||
{
|
||||
CHECKPOINT;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
memset (newCCB, 0, sizeof (VFATCCB));
|
||||
|
@ -461,7 +497,7 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
|
|||
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
|
||||
fileObject->FsContext = fcb;
|
||||
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;
|
||||
}
|
||||
|
@ -469,92 +505,77 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
|
|||
NTSTATUS
|
||||
vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt,
|
||||
PVFATFCB pDirectoryFCB,
|
||||
PWSTR pFileToFind,
|
||||
PUNICODE_STRING FileToFindU,
|
||||
PVFATFCB * pFoundFCB)
|
||||
{
|
||||
ULONG directoryIndex;
|
||||
ULONG startIndex;
|
||||
NTSTATUS status;
|
||||
WCHAR defaultFileName [2];
|
||||
WCHAR currentLongName [256];
|
||||
FAT_DIR_ENTRY currentDirEntry;
|
||||
WCHAR currentEntryName [256];
|
||||
PVOID Context = NULL;
|
||||
PVOID Page;
|
||||
BOOLEAN First = TRUE;
|
||||
VFAT_DIRENTRY_CONTEXT DirContext;
|
||||
WCHAR LongNameBuffer[MAX_PATH];
|
||||
WCHAR ShortNameBuffer[13];
|
||||
BOOLEAN FoundLong;
|
||||
BOOLEAN FoundShort;
|
||||
|
||||
assert (pDeviceExt);
|
||||
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,
|
||||
pDirectoryFCB,
|
||||
pFileToFind);
|
||||
DPRINT ("Dir Path:%S\n", pDirectoryFCB->PathName);
|
||||
FileToFindU);
|
||||
DPRINT ("Dir Path:%wZ\n", &pDirectoryFCB->PathNameU);
|
||||
|
||||
// default to '.' if no filename specified
|
||||
if (wcslen (pFileToFind) == 0)
|
||||
{
|
||||
defaultFileName [0] = L'.';
|
||||
defaultFileName [1] = 0;
|
||||
pFileToFind = defaultFileName;
|
||||
}
|
||||
DirContext.DirIndex = 0;
|
||||
DirContext.LongNameU.Buffer = LongNameBuffer;
|
||||
DirContext.LongNameU.Length = 0;
|
||||
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
|
||||
DirContext.ShortNameU.Buffer = ShortNameBuffer;
|
||||
DirContext.ShortNameU.Length = 0;
|
||||
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
|
||||
|
||||
directoryIndex = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
status = vfatGetNextDirEntry(&Context,
|
||||
&Page,
|
||||
pDirectoryFCB,
|
||||
&directoryIndex,
|
||||
currentLongName,
|
||||
¤tDirEntry,
|
||||
&startIndex);
|
||||
&DirContext,
|
||||
First);
|
||||
First = FALSE;
|
||||
if (status == STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
DPRINT (" Index:%d longName:%S\n",
|
||||
directoryIndex,
|
||||
currentLongName);
|
||||
|
||||
if (!vfatIsDirEntryVolume(¤tDirEntry))
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
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;
|
||||
}
|
||||
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,
|
||||
pDirectoryFCB,
|
||||
currentLongName,
|
||||
¤tDirEntry,
|
||||
startIndex,
|
||||
directoryIndex,
|
||||
&DirContext,
|
||||
pFoundFCB);
|
||||
CcUnpinData(Context);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
directoryIndex++;
|
||||
DirContext.DirIndex++;
|
||||
}
|
||||
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
|
@ -564,23 +585,25 @@ NTSTATUS
|
|||
vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||
PVFATFCB *pParentFCB,
|
||||
PVFATFCB *pFCB,
|
||||
const PWSTR pFileName)
|
||||
PUNICODE_STRING pFileNameU)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WCHAR pathName [MAX_PATH];
|
||||
WCHAR elementName [MAX_PATH];
|
||||
PWCHAR currentElement;
|
||||
PVFATFCB FCB;
|
||||
PVFATFCB FCB = NULL;
|
||||
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,
|
||||
pParentFCB,
|
||||
pFCB,
|
||||
pFileName);
|
||||
pFileNameU);
|
||||
|
||||
RtlInitUnicodeStringFromLiteral(&RootNameU, L"\\");
|
||||
|
||||
// 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");
|
||||
|
||||
|
@ -591,34 +614,32 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
|||
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
currentElement = wcsrchr(pFileName, L'\\');
|
||||
wcsncpy(pathName, pFileName, currentElement - pFileName);
|
||||
pathName[currentElement - pFileName] = L'\0';
|
||||
currentElement++;
|
||||
last = curr = pFileNameU->Buffer + pFileNameU->Length / sizeof(WCHAR) - 1;
|
||||
while (*curr != L'\\' && curr > pFileNameU->Buffer)
|
||||
{
|
||||
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)
|
||||
{
|
||||
currentElement = pFileName + 1;
|
||||
wcscpy (pathName, L"\\");
|
||||
FCB = vfatOpenRootFCB(pVCB);
|
||||
curr = pFileNameU->Buffer;
|
||||
}
|
||||
curr++;
|
||||
parentFCB = NULL;
|
||||
|
||||
// Parse filename and check each path element for existance and access
|
||||
while (vfatGetNextPathElement (currentElement) != 0)
|
||||
while (curr <= last)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
vfatReleaseFCB (pVCB, parentFCB);
|
||||
|
@ -630,35 +651,31 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
|||
DPRINT ("Element in requested path is not a directory\n");
|
||||
|
||||
vfatReleaseFCB (pVCB, FCB);
|
||||
FCB = 0;
|
||||
FCB = NULL;
|
||||
*pParentFCB = NULL;
|
||||
*pFCB = NULL;
|
||||
|
||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
}
|
||||
parentFCB = FCB;
|
||||
|
||||
// Extract next directory level into dirName
|
||||
vfatWSubString (pathName,
|
||||
pFileName,
|
||||
vfatGetNextPathElement (currentElement) - pFileName);
|
||||
DPRINT (" pathName:%S\n", pathName);
|
||||
|
||||
FCB = vfatGrabFCBFromTable (pVCB, pathName);
|
||||
NameU.Buffer = pFileNameU->Buffer;
|
||||
prev = curr;
|
||||
while (*curr != L'\\' && curr <= last)
|
||||
{
|
||||
curr++;
|
||||
}
|
||||
NameU.MaximumLength = NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR);
|
||||
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
|
||||
if (FCB == NULL)
|
||||
{
|
||||
vfatWSubString (elementName,
|
||||
currentElement,
|
||||
vfatGetNextPathElement (currentElement) - currentElement);
|
||||
DPRINT (" elementName:%S\n", elementName);
|
||||
|
||||
status = vfatDirFindFile (pVCB, parentFCB, elementName, &FCB);
|
||||
NameU.Buffer = prev;
|
||||
NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR);
|
||||
status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB);
|
||||
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||
{
|
||||
*pParentFCB = parentFCB;
|
||||
*pFCB = NULL;
|
||||
currentElement = vfatGetNextPathElement(currentElement);
|
||||
if (*currentElement == L'\0' || vfatGetNextPathElement(currentElement + 1) == 0)
|
||||
if (curr > last)
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
@ -676,7 +693,7 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
|||
return status;
|
||||
}
|
||||
}
|
||||
currentElement = vfatGetNextPathElement (currentElement);
|
||||
curr++;
|
||||
}
|
||||
|
||||
*pParentFCB = parentFCB;
|
||||
|
@ -684,7 +701,3 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
|||
|
||||
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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/finfo.c
|
||||
* FILE: drivers/fs/vfat/finfo.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -119,7 +120,7 @@ VfatSetBasicInformation(PFILE_OBJECT FileObject,
|
|||
FILE_ATTRIBUTE_READONLY)));
|
||||
DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib);
|
||||
|
||||
VfatUpdateEntry(DeviceExt, FileObject);
|
||||
VfatUpdateEntry(FCB);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -170,10 +171,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
PDEVICE_OBJECT DeviceObject,
|
||||
PFILE_DISPOSITION_INFORMATION DispositionInfo)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
VFATFCB tmpFcb;
|
||||
WCHAR star[2];
|
||||
ULONG Index;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
int count;
|
||||
|
||||
|
@ -185,8 +182,9 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
assert (DeviceExt->FatInfo.BytesPerCluster != 0);
|
||||
assert (FCB != NULL);
|
||||
|
||||
if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..")
|
||||
|| !wcscmp(FCB->ObjectName, L"."))
|
||||
if (vfatFCBIsRoot(FCB) ||
|
||||
(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
|
||||
return STATUS_ACCESS_DENIED;
|
||||
|
@ -195,7 +193,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
{
|
||||
if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
|
||||
{
|
||||
KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql);
|
||||
count = FCB->RefCount;
|
||||
if (FCB->RefCount > 1)
|
||||
{
|
||||
|
@ -207,7 +204,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
FCB->Flags |= FCB_DELETE_PENDING;
|
||||
FileObject->DeletePending = TRUE;
|
||||
}
|
||||
KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -217,16 +213,8 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
DPRINT("RefCount:%d\n", count);
|
||||
if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
|
||||
{
|
||||
memset (&tmpFcb, 0, sizeof(VFATFCB));
|
||||
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))
|
||||
if (!VfatIsDirectoryEmpty(FCB))
|
||||
{
|
||||
DPRINT1("found: \'%S\'\n", tmpFcb.PathName);
|
||||
Status = STATUS_DIRECTORY_NOT_EMPTY;
|
||||
FCB->Flags &= ~FCB_DELETE_PENDING;
|
||||
FileObject->DeletePending = FALSE;
|
||||
|
@ -238,7 +226,9 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FileObject->DeletePending = FALSE;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -252,19 +242,18 @@ VfatGetNameInformation(PFILE_OBJECT FileObject,
|
|||
* FUNCTION: Retrieve the file name information
|
||||
*/
|
||||
{
|
||||
ULONG NameLength;
|
||||
|
||||
assert (NameInfo != NULL);
|
||||
assert (FCB != NULL);
|
||||
|
||||
NameLength = wcslen(FCB->PathName) * sizeof(WCHAR);
|
||||
if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR))
|
||||
if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
NameInfo->FileNameLength = NameLength;
|
||||
memcpy(NameInfo->FileName, FCB->PathName, NameLength + sizeof(WCHAR));
|
||||
NameInfo->FileNameLength = FCB->PathNameU.Length;
|
||||
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;
|
||||
}
|
||||
|
@ -328,13 +317,11 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
|
|||
* FUNCTION: Retrieve the all file information
|
||||
*/
|
||||
{
|
||||
ULONG NameLength;
|
||||
|
||||
assert (Info);
|
||||
assert (Fcb);
|
||||
|
||||
NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
|
||||
if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR))
|
||||
if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR))
|
||||
return(STATUS_BUFFER_OVERFLOW);
|
||||
|
||||
/* Basic Information */
|
||||
|
@ -377,10 +364,11 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
|
|||
/* The IO-Manager adds this information */
|
||||
|
||||
/* Name Information */
|
||||
Info->NameInformation.FileNameLength = NameLength;
|
||||
RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathName, NameLength + sizeof(WCHAR));
|
||||
Info->NameInformation.FileNameLength = Fcb->PathNameU.Length;
|
||||
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;
|
||||
}
|
||||
|
@ -421,6 +409,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
|
|||
ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
|
||||
ULONG NewSize = AllocationSize->u.LowPart;
|
||||
ULONG NCluster;
|
||||
BOOL AllocSizeChanged = FALSE;
|
||||
|
||||
DPRINT("VfatSetAllocationSizeInformation()\n");
|
||||
|
||||
|
@ -438,6 +427,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
|
|||
|
||||
if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
|
||||
{
|
||||
AllocSizeChanged = TRUE;
|
||||
if (FirstCluster == 0)
|
||||
{
|
||||
Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);
|
||||
|
@ -499,6 +489,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
|
|||
}
|
||||
else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
|
||||
{
|
||||
AllocSizeChanged = TRUE;
|
||||
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
|
||||
if (NewSize > 0)
|
||||
{
|
||||
|
@ -531,7 +522,11 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
|
|||
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
|
||||
}
|
||||
/* Update the on-disk directory entry */
|
||||
VfatUpdateEntry(DeviceExt, FileObject);
|
||||
Fcb->Flags |= FCB_IS_DIRTY;
|
||||
if (AllocSizeChanged)
|
||||
{
|
||||
VfatUpdateEntry(Fcb);
|
||||
}
|
||||
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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -20,8 +20,9 @@
|
|||
NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
|
||||
{
|
||||
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);
|
||||
if (IoStatus.Status == STATUS_INVALID_PARAMETER)
|
||||
|
@ -29,6 +30,14 @@ NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
|
|||
/* FIXME: Caching was possible not initialized */
|
||||
IoStatus.Status = STATUS_SUCCESS;
|
||||
}
|
||||
if (Fcb->Flags & FCB_IS_DIRTY)
|
||||
{
|
||||
Status = VfatUpdateEntry(Fcb);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
IoStatus.Status = Status;
|
||||
}
|
||||
}
|
||||
return IoStatus.Status;
|
||||
}
|
||||
|
||||
|
@ -45,6 +54,8 @@ NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
|
|||
{
|
||||
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
|
||||
ListEntry = ListEntry->Flink;
|
||||
if (!vfatFCBIsDirectory(Fcb))
|
||||
{
|
||||
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
||||
Status = VfatFlushFile(DeviceExt, Fcb);
|
||||
ExReleaseResourceLite (&Fcb->MainResource);
|
||||
|
@ -53,6 +64,25 @@ NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
|
|||
DPRINT1("VfatFlushFile failed, status = %x\n", 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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* 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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/fsctl.c
|
||||
* FILE: drivers/fs/vfat/fsctl.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
*/
|
||||
|
||||
|
@ -214,6 +214,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
|
|||
PVFATFCB VolumeFcb = NULL;
|
||||
PVFATCCB Ccb = NULL;
|
||||
PDEVICE_OBJECT DeviceToMount;
|
||||
UNICODE_STRING NameU;
|
||||
|
||||
DPRINT("VfatMount(IrpContext %x)\n", IrpContext);
|
||||
|
||||
|
@ -289,7 +290,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
|
|||
DPRINT("FsDeviceObject %lx\n", DeviceObject);
|
||||
|
||||
DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
|
||||
Fcb = vfatNewFCB(NULL);
|
||||
RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Fat$$");
|
||||
Fcb = vfatNewFCB(&NameU);
|
||||
if (Fcb == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -301,9 +303,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
|
|||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
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->FsContext = Fcb;
|
||||
DeviceExt->FATFileObject->FsContext2 = Ccb;
|
||||
|
@ -335,17 +336,15 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
|
|||
ExInitializeResourceLite(&DeviceExt->DirResource);
|
||||
ExInitializeResourceLite(&DeviceExt->FatResource);
|
||||
|
||||
KeInitializeSpinLock(&DeviceExt->FcbListLock);
|
||||
InitializeListHead(&DeviceExt->FcbListHead);
|
||||
RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Volume$$");
|
||||
|
||||
VolumeFcb = vfatNewFCB(NULL);
|
||||
VolumeFcb = vfatNewFCB(&NameU);
|
||||
if (VolumeFcb == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto ByeBye;
|
||||
}
|
||||
wcscpy(VolumeFcb->PathName, L"$$Volume$$");
|
||||
VolumeFcb->ObjectName = VolumeFcb->PathName;
|
||||
VolumeFcb->Flags = FCB_IS_VOLUME;
|
||||
VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
|
||||
VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
|
||||
|
|
|
@ -16,12 +16,13 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* 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
|
||||
* FILE: services/fs/vfat/iface.c
|
||||
* FILE: drivers/fs/vfat/iface.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*/
|
||||
|
||||
/* 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 = ../../..
|
||||
|
||||
|
@ -35,7 +35,13 @@ DEP_OBJECTS = $(TARGET_OBJECTS)
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/misc.c
|
||||
* FILE: drivers/fs/vfat/misc.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Hartmut Birr
|
||||
*
|
||||
|
@ -189,16 +189,16 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
|
||||
VOID STDCALL VfatDoRequest (PVOID IrpContext)
|
||||
{
|
||||
ULONG Count = InterlockedDecrement(&QueueCount);
|
||||
DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, Count);
|
||||
InterlockedDecrement(&QueueCount);
|
||||
DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
|
||||
VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
ULONG Count = InterlockedIncrement(&QueueCount);
|
||||
DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, Count);
|
||||
InterlockedIncrement(&QueueCount);
|
||||
DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, QueueCount);
|
||||
|
||||
assert (IrpContext != 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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/rw.c
|
||||
* FILE: drivers/fs/vfat/rw.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -303,7 +304,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
|
|||
ULONG BytesDone;
|
||||
ULONG StartCluster;
|
||||
ULONG ClusterCount;
|
||||
NTSTATUS Status;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOLEAN First = TRUE;
|
||||
ULONG BytesPerSector;
|
||||
ULONG BytesPerCluster;
|
||||
|
@ -323,9 +324,9 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
|
|||
BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
|
||||
|
||||
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,
|
||||
Fcb->PathName);
|
||||
&Fcb->PathNameU);
|
||||
|
||||
assert(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart);
|
||||
assert(WriteOffset.u.LowPart % BytesPerSector == 0);
|
||||
|
@ -482,7 +483,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
|
|||
Fcb = IrpContext->FileObject->FsContext;
|
||||
assert(Fcb);
|
||||
|
||||
DPRINT("<%S>\n", Fcb->PathName);
|
||||
DPRINT("<%wZ>\n", &Fcb->PathNameU);
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -720,7 +721,7 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
|
|||
Fcb = IrpContext->FileObject->FsContext;
|
||||
assert(Fcb);
|
||||
|
||||
DPRINT("<%S>\n", Fcb->PathName);
|
||||
DPRINT("<%wZ>\n", &Fcb->PathNameU);
|
||||
|
||||
if (Fcb->Flags & FCB_IS_PAGE_FILE)
|
||||
{
|
||||
|
@ -939,8 +940,8 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
|
|||
FsdFileTimeToDosDateTime ((TIME*)&LocalTime, &Fcb->entry.UpdateDate,
|
||||
&Fcb->entry.UpdateTime);
|
||||
Fcb->entry.AccessDate = Fcb->entry.UpdateDate;
|
||||
// update dates/times and length
|
||||
VfatUpdateEntry (IrpContext->DeviceExt, IrpContext->FileObject);
|
||||
/* set date and times to dirty */
|
||||
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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/shutdown.c
|
||||
* FILE: drivers/fs/vfat/shutdown.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* 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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/string.c
|
||||
* FILE: drivers/fs/vfat/string.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -20,13 +21,21 @@
|
|||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
const WCHAR *long_illegals = L"\"*\\<>/?:|";
|
||||
|
||||
BOOLEAN
|
||||
vfatIsLongIllegal(WCHAR c)
|
||||
{
|
||||
return wcschr(long_illegals, c) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
|
||||
/*
|
||||
* FUNCTION: Compare two wide character strings, s2 with jokers (* or ?)
|
||||
* 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)
|
||||
return(TRUE);
|
||||
|
@ -43,54 +52,16 @@ BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR 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)
|
||||
return(TRUE);
|
||||
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>
|
||||
|
||||
|
@ -68,6 +68,11 @@ typedef struct _BootSector BootSector;
|
|||
#define VFAT_CASE_LOWER_BASE 8 // base 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
|
||||
{
|
||||
unsigned char Filename[8], Ext[3];
|
||||
|
@ -145,6 +150,7 @@ typedef struct
|
|||
|
||||
KSPIN_LOCK FcbListLock;
|
||||
LIST_ENTRY FcbListHead;
|
||||
struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
|
||||
|
||||
PDEVICE_OBJECT StorageDevice;
|
||||
PFILE_OBJECT FATFileObject;
|
||||
|
@ -154,7 +160,6 @@ typedef struct
|
|||
BOOLEAN AvailableClustersValid;
|
||||
ULONG Flags;
|
||||
struct _VFATFCB * VolumeFcb;
|
||||
struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
|
||||
|
||||
LIST_ENTRY VolumeListEntry;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
|
||||
|
@ -178,6 +183,7 @@ extern PVFAT_GLOBAL_DATA VfatGlobalData;
|
|||
#define FCB_IS_FAT 0x0004
|
||||
#define FCB_IS_PAGE_FILE 0x0008
|
||||
#define FCB_IS_VOLUME 0x0010
|
||||
#define FCB_IS_DIRTY 0x0020
|
||||
|
||||
typedef struct _VFATFCB
|
||||
{
|
||||
|
@ -188,17 +194,26 @@ typedef struct _VFATFCB
|
|||
ERESOURCE PagingIoResource;
|
||||
/* end FCB header required by ROS/NT */
|
||||
|
||||
/* */
|
||||
/* directory entry for this file or directory */
|
||||
FATDirEntry entry;
|
||||
|
||||
/* point on filename (250 chars max) in PathName */
|
||||
WCHAR *ObjectName;
|
||||
|
||||
/* path+filename 260 max */
|
||||
WCHAR PathName[MAX_PATH];
|
||||
/* long file name, points into PathNameBuffer */
|
||||
UNICODE_STRING LongNameU;
|
||||
|
||||
/* 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;
|
||||
|
@ -241,7 +256,7 @@ typedef struct _VFATCCB
|
|||
/* for DirectoryControl */
|
||||
ULONG Entry;
|
||||
/* for DirectoryControl */
|
||||
PWCHAR DirectorySearchPattern;
|
||||
UNICODE_STRING SearchPattern;
|
||||
ULONG LastCluster;
|
||||
ULONG LastOffset;
|
||||
|
||||
|
@ -288,6 +303,16 @@ typedef struct
|
|||
PFILE_OBJECT FileObject;
|
||||
} 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 */
|
||||
|
||||
NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -336,27 +361,20 @@ NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext);
|
|||
|
||||
NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT FileObject,
|
||||
PWSTR FileName);
|
||||
PUNICODE_STRING FileNameU);
|
||||
|
||||
NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt,
|
||||
PVFATFCB Fcb,
|
||||
PVFATFCB Parent,
|
||||
PWSTR FileToFind,
|
||||
PULONG pDirIndex,
|
||||
PULONG pDirIndex2);
|
||||
PUNICODE_STRING FileToFindU,
|
||||
PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
BOOLEAN First);
|
||||
|
||||
VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry,
|
||||
PWSTR pName);
|
||||
PUNICODE_STRING NameU);
|
||||
|
||||
NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt,
|
||||
PVPB Vpb);
|
||||
|
||||
BOOLEAN IsDeletedEntry (PVOID Block,
|
||||
ULONG Offset);
|
||||
|
||||
BOOLEAN IsLastEntry (PVOID Block,
|
||||
ULONG Offset);
|
||||
|
||||
/* --------------------------------------------------------- close.c */
|
||||
|
||||
NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext);
|
||||
|
@ -392,28 +410,27 @@ NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject,
|
|||
/* --------------------------------------------------------- dirwr.c */
|
||||
|
||||
NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
||||
PUNICODE_STRING PathNameU,
|
||||
PFILE_OBJECT pFileObject,
|
||||
ULONG RequestedOptions,UCHAR ReqAttr);
|
||||
ULONG RequestedOptions,
|
||||
UCHAR ReqAttr);
|
||||
|
||||
NTSTATUS VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT pFileObject);
|
||||
NTSTATUS VfatUpdateEntry (PVFATFCB pFcb);
|
||||
|
||||
NTSTATUS delEntry(PDEVICE_EXTENSION,
|
||||
PFILE_OBJECT);
|
||||
NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB);
|
||||
|
||||
/* -------------------------------------------------------- string.c */
|
||||
|
||||
VOID
|
||||
vfatSplitPathName(PUNICODE_STRING PathNameU,
|
||||
PUNICODE_STRING DirNameU,
|
||||
PUNICODE_STRING FileNameU);
|
||||
|
||||
BOOLEAN vfatIsLongIllegal(WCHAR c);
|
||||
|
||||
BOOLEAN wstrcmpjoki (PWSTR s1,
|
||||
PWSTR s2);
|
||||
|
||||
PWCHAR vfatGetNextPathElement (PWCHAR pFileName);
|
||||
|
||||
VOID vfatWSubString (PWCHAR pTarget,
|
||||
const PWCHAR pSource,
|
||||
size_t pLength);
|
||||
|
||||
BOOL vfatIsFileNameValid (PWCHAR pFileName);
|
||||
|
||||
/* ----------------------------------------------------------- fat.c */
|
||||
|
||||
NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt,
|
||||
|
@ -443,26 +460,17 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
|
||||
PFAT_DIR_ENTRY pDirEntry);
|
||||
|
||||
BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry);
|
||||
|
||||
BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry);
|
||||
|
||||
BOOL vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry);
|
||||
|
||||
VOID vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry,
|
||||
PWSTR pEntryName);
|
||||
BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb);
|
||||
|
||||
NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
|
||||
PVOID * pPage,
|
||||
IN PVFATFCB pDirFcb,
|
||||
IN OUT PULONG pDirIndex,
|
||||
OUT PWSTR pFileName,
|
||||
OUT PFAT_DIR_ENTRY pDirEntry,
|
||||
OUT PULONG pStartIndex);
|
||||
IN PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
BOOLEAN First);
|
||||
|
||||
/* ----------------------------------------------------------- fcb.c */
|
||||
|
||||
PVFATFCB vfatNewFCB (PWCHAR pFileName);
|
||||
PVFATFCB vfatNewFCB (PUNICODE_STRING pFileNameU);
|
||||
|
||||
VOID vfatDestroyFCB (PVFATFCB pFCB);
|
||||
|
||||
|
@ -478,7 +486,7 @@ VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB,
|
|||
PVFATFCB pFCB);
|
||||
|
||||
PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt,
|
||||
PWSTR pFileName);
|
||||
PUNICODE_STRING pFileNameU);
|
||||
|
||||
PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB);
|
||||
|
||||
|
@ -494,20 +502,17 @@ NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
|
|||
|
||||
NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB,
|
||||
PVFATFCB parentFCB,
|
||||
PWSTR elementName,
|
||||
PUNICODE_STRING FileToFindU,
|
||||
PVFATFCB * fileFCB);
|
||||
|
||||
NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||
PVFATFCB *pParentFCB,
|
||||
PVFATFCB *pFCB,
|
||||
const PWSTR pFileName);
|
||||
PUNICODE_STRING pFileNameU);
|
||||
|
||||
NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb,
|
||||
PVFATFCB directoryFCB,
|
||||
PWSTR longName,
|
||||
PFAT_DIR_ENTRY dirEntry,
|
||||
ULONG startIndex,
|
||||
ULONG dirIndex,
|
||||
PVFAT_DIRENTRY_CONTEXT DirContext,
|
||||
PVFATFCB * fileFCB);
|
||||
|
||||
/* ------------------------------------------------------------ rw.c */
|
||||
|
@ -548,4 +553,5 @@ NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext);
|
|||
|
||||
NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb);
|
||||
|
||||
|
||||
/* 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
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/volume.c
|
||||
* FILE: drivers/fs/vfat/volume.c
|
||||
* PURPOSE: VFAT Filesystem
|
||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||
* Hartmut Birr
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
|
Loading…
Reference in a new issue