-/* $Id: create.c,v 1.24 2001/05/02 03:18:03 rex Exp $
+/* $Id: create.c,v 1.34 2001/11/02 22:44:34 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* GLOBALS *******************************************************************/
-#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
-
-#define TAG_CCB TAG('V', 'C', 'C', 'B')
+#define ENTRIES_PER_PAGE (PAGESIZE / sizeof (FATDirEntry))
/* FUNCTIONS *****************************************************************/
(((FATDirEntry *) Block)[Offset].Filename[0] == 0));
}
-static void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
+void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
{
int fromIndex, toIndex;
{
pName [toIndex++] = L'.';
fromIndex = 0;
- while (fromIndex < 3 && pBasename [fromIndex] != ' ')
+ while (fromIndex < 3 && pExtension [fromIndex] != ' ')
{
pName [toIndex++] = pExtension [fromIndex++];
}
{
int fromIndex, toIndex;
- fromIndex = toIndex = 0;
+ fromIndex = toIndex = 0;
while (fromIndex < 8 && pBasename [fromIndex] != ' ')
{
pName [toIndex++] = pBasename [fromIndex++];
pName [toIndex] = L'\0';
}
-BOOLEAN
-GetEntryName (PVOID Block, PULONG _Offset, PWSTR Name, PULONG _jloop,
- PDEVICE_EXTENSION DeviceExt, ULONG * _StartingSector)
+NTSTATUS
+GetEntryName(PVOID *pContext,
+ PVOID *Block,
+ PFILE_OBJECT FileObject,
+ PWSTR Name,
+ PULONG pIndex,
+ PULONG pIndex2)
/*
* FUNCTION: Retrieves the file name, be it in short or long file name format
*/
{
- FATDirEntry *test;
- slot *test2;
- ULONG Offset = *_Offset;
- ULONG StartingSector = *_StartingSector;
- ULONG jloop = *_jloop;
+ NTSTATUS Status;
+ FATDirEntry * test;
+ slot * test2;
ULONG cpos;
-
- test = (FATDirEntry *) Block;
- test2 = (slot *) Block;
+ ULONG Offset = *pIndex % ENTRIES_PER_PAGE;
+ ULONG Read;
+ LARGE_INTEGER FileOffset;
*Name = 0;
-
- if (IsDeletedEntry (Block, Offset))
+ while (TRUE)
+ {
+ test = (FATDirEntry *) *Block;
+ test2 = (slot *) *Block;
+ if (vfatIsDirEntryEndMarker(&test[Offset]))
{
- return (FALSE);
+ return STATUS_NO_MORE_ENTRIES;
}
-
- if (test2[Offset].attr == 0x0f)
+ if (test2[Offset].attr == 0x0f && !vfatIsDirEntryDeleted(&test[Offset]))
{
- vfat_initstr (Name, 256);
+ *Name = 0;
+ if (pIndex2)
+ *pIndex2 = *pIndex; // start of dir entry
+
+ DPRINT (" long name entry found at %d\n", *pIndex);
+
+ DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
+ 5, test2 [Offset].name0_4,
+ 6, test2 [Offset].name5_10,
+ 2, test2 [Offset].name11_12);
+
+ vfat_initstr (Name, 255);
vfat_wcsncpy (Name, test2[Offset].name0_4, 5);
vfat_wcsncat (Name, test2[Offset].name5_10, 5, 6);
vfat_wcsncat (Name, test2[Offset].name11_12, 11, 2);
+ DPRINT (" longName: [%S]\n", Name);
cpos = 0;
while ((test2[Offset].id != 0x41) && (test2[Offset].id != 0x01) &&
- (test2[Offset].attr > 0))
- {
- Offset++;
- if (Offset == ENTRIES_PER_SECTOR)
- {
- Offset = 0;
- /* FIXME: Check status */
- GetNextSector (DeviceExt, StartingSector, &StartingSector, FALSE);
- jloop++;
- /* FIXME: Check status */
- VfatReadSectors (DeviceExt->StorageDevice,
- StartingSector, 1, Block);
- test2 = (slot *) Block;
- }
- cpos++;
- vfat_movstr (Name, 13, 0, cpos * 13);
- vfat_wcsncpy (Name, test2[Offset].name0_4, 5);
- vfat_wcsncat (Name, test2[Offset].name5_10, 5, 6);
- vfat_wcsncat (Name, test2[Offset].name11_12, 11, 2);
-
- }
-
- if (IsDeletedEntry (Block, Offset + 1))
- {
- Offset++;
- *_Offset = Offset;
- *_jloop = jloop;
- *_StartingSector = StartingSector;
- return (FALSE);
- }
-
- *_Offset = Offset;
- *_jloop = jloop;
- *_StartingSector = StartingSector;
+ (test2[Offset].attr > 0))
+ {
+ (*pIndex)++;
+ Offset++;
- return (TRUE);
+ if (Offset == ENTRIES_PER_PAGE)
+ {
+ Offset = 0;
+ CcUnpinData(*pContext);
+ FileOffset.QuadPart = *pIndex * sizeof(FATDirEntry);
+ if(!CcMapData(FileObject, &FileOffset, PAGESIZE, TRUE, pContext, Block))
+ {
+ *pContext = NULL;
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ test2 = (slot *) *Block;
+ }
+ DPRINT (" long name entry found at %d\n", *pIndex);
+
+ DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
+ 5, test2 [Offset].name0_4,
+ 6, test2 [Offset].name5_10,
+ 2, test2 [Offset].name11_12);
+
+ cpos++;
+ vfat_movstr (Name, 13, 0, cpos * 13);
+ vfat_wcsncpy (Name, test2[Offset].name0_4, 5);
+ vfat_wcsncat (Name, test2[Offset].name5_10, 5, 6);
+ vfat_wcsncat (Name, test2[Offset].name11_12, 11, 2);
+
+ DPRINT (" longName: [%S]\n", Name);
+ }
+ (*pIndex)++;
+ Offset++;
+ if (Offset == ENTRIES_PER_PAGE)
+ {
+ Offset = 0;
+ CcUnpinData(*pContext);
+ FileOffset.QuadPart = *pIndex * sizeof(FATDirEntry);
+ if(!CcMapData(FileObject, &FileOffset, PAGESIZE, TRUE, pContext, Block))
+ {
+ *pContext = NULL;
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ test2 = (slot *) *Block;
+ test = (FATDirEntry*) *Block;
+ }
}
-
- vfat8Dot3ToString (test[Offset].Filename, test[Offset].Ext, Name);
-
- *_Offset = Offset;
-
- return (TRUE);
+ else
+ {
+ if (vfatIsDirEntryEndMarker(&test[Offset]))
+ return STATUS_NO_MORE_ENTRIES;
+ if (vfatIsDirEntryDeleted(&test[Offset]))
+ return STATUS_UNSUCCESSFUL;
+ if (*Name == 0)
+ {
+ vfat8Dot3ToString (test[Offset].Filename, test[Offset].Ext, Name);
+ if (pIndex2)
+ *pIndex2 = *pIndex;
+ }
+ break;
+ }
+ }
+ return STATUS_SUCCESS;
}
NTSTATUS
NextCluster = 0;
block = ExAllocatePool (NonPagedPool, BLOCKSIZE);
- DPRINT ("FindFile : start at sector %lx, entry %ld\n", StartingSector, i);
+ DPRINT ("ReadVolumeLabel : start at sector %lx, entry %ld\n", StartingSector, i);
for (j = 0; j < Size; j++)
{
/* FIXME: Check status */
- VfatReadSectors (DeviceExt->StorageDevice, StartingSector, 1, block);
+ Status = VfatReadSectors (DeviceExt->StorageDevice, StartingSector, 1, block);
+ if (!NT_SUCCESS(Status))
+ {
+ *(Vpb->VolumeLabel) = 0;
+ Vpb->VolumeLabelLength = 0;
+ ExFreePool(block);
+ return(Status);
+ }
for (i = 0; i < ENTRIES_PER_SECTOR; i++)
{
FATDirEntry *test = (FATDirEntry *) block;
/* copy volume label */
- vfat8Dot3ToVolumeLabel (test[i].Filename, test[i].Ext, Vpb->VolumeLabel);
+ vfat8Dot3ToVolumeLabel (test[i].Filename, test[i].Ext, Vpb->VolumeLabel);
Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel);
ExFreePool (block);
return (STATUS_UNSUCCESSFUL);
}
-
NTSTATUS
-FindFile (PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb,
- PVFATFCB Parent, PWSTR FileToFind, ULONG * StartSector,
- ULONG * Entry)
+FindFile (PDEVICE_EXTENSION DeviceExt,
+ PVFATFCB Fcb,
+ PVFATFCB Parent,
+ PWSTR FileToFind,
+ ULONG *pDirIndex,
+ ULONG *pDirIndex2)
/*
* FUNCTION: Find a file
*/
{
- ULONG i, j;
- ULONG Size;
- char *block;
WCHAR name[256];
- ULONG StartingSector;
- ULONG NextCluster;
+ WCHAR name2[14];
+ char * block;
WCHAR TempStr[2];
NTSTATUS Status;
ULONG len;
-
-// DPRINT ("FindFile(Parent %x, FileToFind '%S')\n", Parent, FileToFind);
- DPRINT("FindFile: old Pathname %x, old Objectname %x)\n",Fcb->PathName, Fcb->ObjectName);
-
+ ULONG DirIndex;
+ ULONG Offset;
+ ULONG FirstCluster;
+ ULONG Read;
+ BOOL isRoot;
+ LARGE_INTEGER FileOffset;
+ PVOID Context = NULL;
+
+ 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);
+
+ 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->FatType == FAT32)
{
- CHECKPOINT;
- TempStr[0] = (WCHAR) '.';
- TempStr[1] = 0;
- FileToFind = (PWSTR)&TempStr;
+ if (FirstCluster == ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster)
+ isRoot = TRUE;
}
-
- if (Parent == NULL || Parent->entry.FirstCluster == 1)
+ else
{
- Size = DeviceExt->rootDirectorySectors; /* FIXME : in fat32, no limit */
- StartingSector = DeviceExt->rootStart;
- NextCluster = 0;
- if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0)
- || (FileToFind[0] == '.' && FileToFind[1] == 0))
+ if (FirstCluster == 1)
+ isRoot = TRUE;
+ }
+ }
+ else
+ isRoot = TRUE;
+ if (isRoot)
+ {
+ if (DeviceExt->FatType == FAT32)
+ FirstCluster = ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster;
+ else
+ FirstCluster = 1;
+
+ if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0)
+ || (FileToFind[0] == '.' && FileToFind[1] == 0))
{
/* it's root : complete essentials fields then return ok */
CHECKPOINT;
Fcb->entry.FileSize = DeviceExt->rootDirectorySectors * BLOCKSIZE;
Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
if (DeviceExt->FatType == FAT32)
- Fcb->entry.FirstCluster = 2;
+ {
+ Fcb->entry.FirstCluster = ((PUSHORT)FirstCluster)[0];
+ Fcb->entry.FirstClusterHigh = ((PUSHORT)FirstCluster)[1];
+ }
else
- Fcb->entry.FirstCluster = 1;
- if (StartSector)
- *StartSector = StartingSector;
- if (Entry)
- *Entry = 0;
- DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
+ Fcb->entry.FirstCluster = 1;
+ if (pDirIndex)
+ *pDirIndex = 0;
+ if (pDirIndex2)
+ *pDirIndex2 = 0;
+ DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
return (STATUS_SUCCESS);
}
- }
+ }
else
- {
- DPRINT ("Parent->entry.FileSize %x\n", Parent->entry.FileSize);
+ {
+ DPRINT ("Parent->entry.FileSize %x\n", Parent->entry.FileSize);
+ FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Parent->entry);
+ }
+ if (pDirIndex && (*pDirIndex))
+ DirIndex = *pDirIndex;
- Size = ULONG_MAX;
- if (DeviceExt->FatType == FAT32)
- NextCluster = Parent->entry.FirstCluster
- + Parent->entry.FirstClusterHigh * 65536;
- else
- NextCluster = Parent->entry.FirstCluster;
- StartingSector = ClusterToSector (DeviceExt, NextCluster);
- if (Parent->entry.FirstCluster == 1 && DeviceExt->FatType != FAT32)
- {
- /* read of root directory in FAT16 or FAT12 */
- StartingSector = DeviceExt->rootStart;
- }
+ Offset = DirIndex % ENTRIES_PER_PAGE;
+ while(TRUE)
+ {
+ if (Context == NULL || Offset == ENTRIES_PER_PAGE)
+ {
+ if (Offset == ENTRIES_PER_PAGE)
+ Offset = 0;
+ if (Context)
+ {
+ CcUnpinData(Context);
+ }
+ FileOffset.QuadPart = (DirIndex - Offset) * sizeof(FATDirEntry);
+ if (!CcMapData(Parent->FileObject, &FileOffset, PAGESIZE, TRUE,
+ &Context, (PVOID*)&block))
+ {
+ Context = NULL;
+ break;
+ }
}
- block = ExAllocatePool (NonPagedPool, BLOCKSIZE);
- if (StartSector && (*StartSector))
- StartingSector = *StartSector;
- i = (Entry) ? (*Entry) : 0;
- for (j = 0; j < Size; j++)
+ if (vfatIsDirEntryVolume(&((FATDirEntry*)block)[Offset]))
{
- /* FIXME: Check status */
- VfatReadSectors (DeviceExt->StorageDevice, StartingSector, 1, block);
-
- for (i = (Entry) ? (*Entry) : 0; i < ENTRIES_PER_SECTOR; i++)
+ Offset++;
+ DirIndex++;
+ continue;
+ }
+ Status = GetEntryName (&Context, (PVOID*)&block, Parent->FileObject, name,
+ &DirIndex, pDirIndex2);
+ if (Status == STATUS_NO_MORE_ENTRIES)
+ break;
+ Offset = DirIndex % ENTRIES_PER_PAGE;
+ if (NT_SUCCESS(Status))
{
- if (IsVolEntry ((PVOID) block, i))
- continue;
- if (IsLastEntry ((PVOID) block, i))
- {
- if (StartSector)
- *StartSector = StartingSector;
- if (Entry)
- *Entry = i;
- ExFreePool (block);
- return (STATUS_UNSUCCESSFUL);
- }
- if (GetEntryName
- ((PVOID) block, &i, name, &j, DeviceExt, &StartingSector))
- {
- if (wstrcmpjoki (name, FileToFind))
+ vfat8Dot3ToString(((FATDirEntry *) block)[Offset].Filename,((FATDirEntry *) block)[Offset].Ext, name2);
+ if (wstrcmpjoki (name, FileToFind) || wstrcmpjoki (name2, FileToFind))
+ {
+ if (Parent && Parent->PathName)
{
- /* In the case of a long filename, the firstcluster is
- stored in the next record -- where it's short name is */
- if (((FATDirEntry *) block)[i].Attrib == 0x0f)
- i++;
- if (i == (ENTRIES_PER_SECTOR))
- {
- /* FIXME: Check status */
- GetNextSector (DeviceExt, StartingSector, &StartingSector, FALSE);
-
- /* FIXME: Check status */
- VfatReadSectors (DeviceExt->StorageDevice,
- StartingSector, 1, block);
- i = 0;
- }
- if (Parent && Parent->PathName)
+ len = wcslen(Parent->PathName);
+ CHECKPOINT;
+ memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR));
+ Fcb->ObjectName=&Fcb->PathName[len];
+ if (len != 1 || Fcb->PathName[0] != '\\')
{
- len = wcslen(Parent->PathName);
- CHECKPOINT;
- memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR));
- Fcb->ObjectName=&Fcb->PathName[len];
+ Fcb->ObjectName[0] = '\\';
+ Fcb->ObjectName = &Fcb->ObjectName[1];
}
- else
- Fcb->ObjectName=Fcb->PathName;
-
+ }
+ else
+ {
+ Fcb->ObjectName=Fcb->PathName;
Fcb->ObjectName[0]='\\';
Fcb->ObjectName=&Fcb->ObjectName[1];
-
- memcpy (&Fcb->entry, &((FATDirEntry *) block)[i],
- sizeof (FATDirEntry));
- vfat_wcsncpy (Fcb->ObjectName, name, MAX_PATH);
- if (StartSector)
- *StartSector = StartingSector;
- if (Entry)
- *Entry = i;
- ExFreePool (block);
- DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
- return (STATUS_SUCCESS);
}
- }
- }
- /* not found in this sector, try next : */
- /* directory can be fragmented although it is best to keep them
- unfragmented. Should we change this to also use GetNextSector?
- GetNextSector was originally implemented to handle the case above */
- if (Entry)
- *Entry = 0;
- StartingSector++;
- if ((Parent != NULL && Parent->entry.FirstCluster != 1)
- || DeviceExt->FatType == FAT32)
- {
- if (StartingSector == ClusterToSector (DeviceExt, NextCluster + 1))
- {
- Status = GetNextCluster (DeviceExt, NextCluster, &NextCluster,
- FALSE);
- if (NextCluster == 0 || NextCluster == 0xffffffff)
- {
- if (StartSector)
- *StartSector = StartingSector;
- if (Entry)
- *Entry = i;
- ExFreePool (block);
- return (STATUS_UNSUCCESSFUL);
- }
- StartingSector = ClusterToSector (DeviceExt, NextCluster);
- }
- }
+ memcpy (&Fcb->entry, &((FATDirEntry *) block)[Offset],
+ sizeof (FATDirEntry));
+ vfat_wcsncpy (Fcb->ObjectName, name, MAX_PATH);
+ if (pDirIndex)
+ *pDirIndex = DirIndex;
+ DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb->PathName, Fcb->ObjectName, DirIndex);
+ if (Context)
+ CcUnpinData(Context);
+ return STATUS_SUCCESS;
+ }
}
- if (StartSector)
- *StartSector = StartingSector;
- if (Entry)
- *Entry = i;
- ExFreePool (block);
+ Offset++;
+ DirIndex++;
+ }
+ if (pDirIndex)
+ *pDirIndex = DirIndex;
+ if (Context)
+ CcUnpinData(Context);
return (STATUS_UNSUCCESSFUL);
}
-NTSTATUS
-vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject,
+NTSTATUS
+vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject,
PWSTR pRelativeFileName,
PWSTR *pAbsoluteFilename)
{
fcb = ccb->pFcb;
assert (fcb);
- /* verify related object is a directory and target name
+ /* verify related object is a directory and target name
don't start with \. */
- if (!(fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
+ if (!(fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|| (pRelativeFileName[0] != '\\'))
{
return STATUS_INVALID_PARAMETER;
}
/* construct absolute path name */
- assert (wcslen (fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
+ assert (wcslen (fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
<= MAX_PATH);
rcName = ExAllocatePool (NonPagedPool, MAX_PATH);
wcscpy (rcName, fcb->PathName);
* FUNCTION: Opens a file
*/
{
- PWSTR current = NULL;
- PWSTR next;
- PWSTR string;
-// PWSTR buffer; // used to store a pointer while checking MAX_PATH conformance
PVFATFCB ParentFcb;
PVFATFCB Fcb;
- PVFATFCB Temp;
- PVFATCCB newCCB;
NTSTATUS Status;
PWSTR AbsFileName = NULL;
- ULONG BytesPerCluster;
DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
- /* FIXME : treat relative name */
if (FileObject->RelatedFileObject)
{
+ DPRINT ("Converting relative filename to absolute filename\n");
Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
FileName,
&AbsFileName);
FileName = AbsFileName;
}
- /*
- * try first to find an existing FCB in memory
- */
- CHECKPOINT;
+ //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
+ DPRINT ("PathName to open: %S\n", FileName);
+
+ /* try first to find an existing FCB in memory */
+ DPRINT ("Checking for existing FCB in memory\n");
Fcb = vfatGrabFCBFromTable (DeviceExt, FileName);
- if (Fcb != NULL)
+ if (Fcb == NULL)
{
- FileObject->FsContext = (PVOID)&Fcb->RFCB;
- newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
- memset (newCCB, 0, sizeof (VFATCCB));
- FileObject->Flags = FileObject->Flags |
- FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
- FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
- FileObject->FsContext2 = newCCB;
- newCCB->pFcb = Fcb;
- newCCB->PtrFileObject = FileObject;
- if (AbsFileName)
- ExFreePool (AbsFileName);
- return STATUS_SUCCESS;
- }
-
- DPRINT ("FileName %S\n", FileName);
-
- string = FileName;
- ParentFcb = NULL;
- Fcb = vfatNewFCB (L"\\");
- next = &string[0];
-
- CHECKPOINT;
- if (*next == 0 || *(next+1) == 0) // root
+ DPRINT ("No existing FCB found, making a new one if file exists.\n");
+ Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName);
+ if (ParentFcb != NULL)
{
- memset (Fcb->entry.Filename, ' ', 11);
- Fcb->entry.FileSize = DeviceExt->rootDirectorySectors * BLOCKSIZE;
- Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
- if (DeviceExt->FatType == FAT32)
- Fcb->entry.FirstCluster = 2;
- else
- Fcb->entry.FirstCluster = 1;
- /* FIXME : is 1 the good value for mark root? */
- ParentFcb = Fcb;
- DPRINT("%S filename, PathName: %S\n",FileName, ParentFcb->PathName);
- Fcb = NULL;
+ vfatReleaseFCB (DeviceExt, ParentFcb);
}
- else
+ if (!NT_SUCCESS (Status))
{
- while (TRUE)
- {
- CHECKPOINT;
- *next = '\\';
- current = next + 1;
- next = wcschr (next + 1, '\\');
- if (next != NULL)
- {
- *next = 0;
- }
- else
- {
- /* reached the last path component */
- DPRINT ("exiting: current '%S'\n", current);
- break;
- }
-
- DPRINT ("search for (%S) in (%S)\n", current, ParentFcb ? ParentFcb->PathName : L"");
- Status = FindFile (DeviceExt, Fcb, ParentFcb, current, NULL, NULL);
- if (Status != STATUS_SUCCESS)
- {
- CHECKPOINT;
- if (Fcb != NULL)
- ExFreePool (Fcb);
- if (ParentFcb != NULL)
- ExFreePool (ParentFcb);
- if (AbsFileName)
- ExFreePool (AbsFileName);
-
- DPRINT ("error STATUS_OBJECT_PATH_NOT_FOUND\n");
- return STATUS_OBJECT_PATH_NOT_FOUND;
- }
- Temp = Fcb;
- CHECKPOINT;
- if (ParentFcb == NULL)
- {
- CHECKPOINT;
- Fcb = vfatNewFCB (L"\\");
- }
- else
- Fcb = ParentFcb;
+ DPRINT ("Could not make a new FCB, status: %x\n", Status);
- if (*(Temp->ObjectName))
- {
- vfat_wcsncpy(Fcb->PathName+(Fcb->ObjectName-Fcb->PathName),Temp->PathName+(Fcb->ObjectName-Fcb->PathName), MAX_PATH);
+ if (AbsFileName)
+ ExFreePool (AbsFileName);
- Fcb->ObjectName = &Fcb->PathName[wcslen(Fcb->PathName)];
- Fcb->ObjectName[0]='\\';
- Fcb->ObjectName=&Fcb->ObjectName[1];
- Fcb->ObjectName[0]=0;
- }
- CHECKPOINT;
- ParentFcb = Temp;
- }
-
- /* searching for last path component */
- DPRINT ("search for (%S) in (%S)\n", current, Fcb ? Fcb->PathName : L"");
- Status = FindFile (DeviceExt, Fcb, ParentFcb, current, NULL, NULL);
- if (Status != STATUS_SUCCESS)
- {
- /* file does not exist */
- CHECKPOINT;
- if (Fcb != NULL)
- ExFreePool (Fcb);
- if (ParentFcb != NULL)
- ExFreePool (ParentFcb);
- if (AbsFileName)
- ExFreePool (AbsFileName);
-
- return STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- Temp = Fcb;
-
- Fcb = ParentFcb;
- ParentFcb = Temp;
- ParentFcb->ObjectName = &(wcschr (ParentFcb->ObjectName, '\\'))[1];
+ 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);
- FileObject->Flags = FileObject->Flags |
- FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
- FileObject->SectionObjectPointers = &ParentFcb->SectionObjectPointers;
- memset(FileObject->SectionObjectPointers, 0,
- sizeof(SECTION_OBJECT_POINTERS));
- FileObject->FsContext = (PVOID)&ParentFcb->RFCB;
- newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
- memset (newCCB, 0, sizeof (VFATCCB));
- FileObject->FsContext2 = newCCB;
- newCCB->pFcb = ParentFcb;
- newCCB->PtrFileObject = FileObject;
- ParentFcb->RefCount++;
- /* FIXME : initialize all fields in FCB and CCB */
-
- vfatAddFCBToTable (DeviceExt, ParentFcb);
-
-/* vfat_wcsncpy (ParentFcb->PathName, FileName, MAX_PATH);
- ParentFcb->ObjectName = ParentFcb->PathName + (current - FileName); */
- ParentFcb->pDevExt = DeviceExt;
- BytesPerCluster = DeviceExt->Boot->SectorsPerCluster * BLOCKSIZE;
- if (BytesPerCluster >= PAGESIZE)
- {
- Status = CcInitializeFileCache(FileObject, &ParentFcb->RFCB.Bcb,
- BytesPerCluster);
- }
- else
- {
- Status = CcInitializeFileCache(FileObject, &ParentFcb->RFCB.Bcb,
- PAGESIZE);
- }
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("CcInitializeFileCache failed\n");
- KeBugCheck(0);
- }
- DPRINT ("file open, fcb=%x\n", ParentFcb);
- DPRINT ("FileSize %d\n", ParentFcb->entry.FileSize);
- if (Fcb)
- ExFreePool (Fcb);
if (AbsFileName)
ExFreePool (AbsFileName);
- CHECKPOINT;
- return (STATUS_SUCCESS);
+ return Status;
}
-
NTSTATUS
VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
FileObject = Stack->FileObject;
DeviceExt = DeviceObject->DeviceExtension;
assert (DeviceExt);
-
+
/*
* Check for illegal characters in the file name
*/
c = FileObject->FileName.Buffer;
while (*c != 0)
{
- if (*c == L'*' || *c == L'?')
+ if (*c == L'*' || *c == L'?' || (*c == L'\\' && c[1] == L'\\'))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
return Status;
}
+ if (Status == STATUS_DELETE_PENDING)
+ {
+ Irp->IoStatus.Status = Status;
+ return Status;
+ }
if (!NT_SUCCESS (Status))
{
/*
* If the file open failed then create the required file
*/
- if (RequestedDisposition == FILE_CREATE ||
- RequestedDisposition == FILE_OPEN_IF ||
- RequestedDisposition == FILE_OVERWRITE_IF ||
+ if (RequestedDisposition == FILE_CREATE ||
+ RequestedDisposition == FILE_OPEN_IF ||
+ RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
{
CHECKPOINT;
- Status =
+ Status =
addEntry (DeviceExt, FileObject, RequestedOptions,
(Stack->Parameters.
Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS));
}
}
else
- {
- /*
- * Otherwise fail if the caller wanted to create a new file
- */
- if (RequestedDisposition == FILE_CREATE)
+ {
+ /*
+ * Otherwise fail if the caller wanted to create a new file
+ */
+ if (RequestedDisposition == FILE_CREATE)
{
Irp->IoStatus.Information = FILE_EXISTS;
Status = STATUS_OBJECT_NAME_COLLISION;
- }
- pCcb = FileObject->FsContext2;
- pFcb = pCcb->pFcb;
- /*
- * If requested then delete the file and create a new one with the
- * same name
- */
- if (RequestedDisposition == FILE_SUPERSEDE)
- {
- ULONG Cluster, NextCluster;
- /* FIXME set size to 0 and free clusters */
- pFcb->entry.FileSize = 0;
- if (DeviceExt->FatType == FAT32)
+ }
+ pCcb = FileObject->FsContext2;
+ pFcb = pCcb->pFcb;
+ /*
+ * If requested then delete the file and create a new one with the
+ * same name
+ */
+ if (RequestedDisposition == FILE_SUPERSEDE)
+ {
+ ULONG Cluster, NextCluster;
+ /* FIXME set size to 0 and free clusters */
+ pFcb->entry.FileSize = 0;
+ if (DeviceExt->FatType == FAT32)
Cluster = pFcb->entry.FirstCluster
+ pFcb->entry.FirstClusterHigh * 65536;
- else
- Cluster = pFcb->entry.FirstCluster;
- pFcb->entry.FirstCluster = 0;
- pFcb->entry.FirstClusterHigh = 0;
- updEntry (DeviceExt, FileObject);
- while (Cluster != 0xffffffff && Cluster > 1)
- {
- Status = GetNextCluster (DeviceExt, Cluster, &NextCluster, TRUE);
- WriteCluster (DeviceExt, Cluster, 0);
- Cluster = NextCluster;
- }
- }
+ else
+ Cluster = pFcb->entry.FirstCluster;
+ pFcb->entry.FirstCluster = 0;
+ pFcb->entry.FirstClusterHigh = 0;
+ updEntry (DeviceExt, FileObject);
+ if ((ULONG)pFcb->RFCB.FileSize.QuadPart > 0)
+ {
+ pFcb->RFCB.AllocationSize.QuadPart = 0;
+ pFcb->RFCB.FileSize.QuadPart = 0;
+ pFcb->RFCB.ValidDataLength.QuadPart = 0;
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&pFcb->RFCB.AllocationSize);
+ }
+ while (Cluster != 0xffffffff && Cluster > 1)
+ {
+ Status = GetNextCluster (DeviceExt, Cluster, &NextCluster, FALSE);
+ WriteCluster (DeviceExt, Cluster, 0);
+ Cluster = NextCluster;
+ }
+ }
- /*
- * Check the file has the requested attributes
- */
- if ((RequestedOptions & FILE_NON_DIRECTORY_FILE)
+ /*
+ * Check the file has the requested attributes
+ */
+ if ((RequestedOptions & FILE_NON_DIRECTORY_FILE)
&& (pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
{
Status = STATUS_FILE_IS_A_DIRECTORY;
}
- if ((RequestedOptions & FILE_DIRECTORY_FILE)
+ if ((RequestedOptions & FILE_DIRECTORY_FILE)
&& !(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
{
Status = STATUS_NOT_A_DIRECTORY;
}
- /* FIXME : test share access */
+ /* FIXME : test share access */
/* FIXME : test write access if requested */
- if (!NT_SUCCESS (Status))
- VfatCloseFile (DeviceExt, FileObject);
- else
- Irp->IoStatus.Information = FILE_OPENED;
+ if (!NT_SUCCESS (Status))
+ VfatCloseFile (DeviceExt, FileObject);
+ else
+ Irp->IoStatus.Information = FILE_OPENED;
/* FIXME : make supersed or overwrite if requested */
- }
+ }
Irp->IoStatus.Status = Status;
}
-NTSTATUS STDCALL
-VfatCreate (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext)
/*
* FUNCTION: Create or open a file
*/
{
- NTSTATUS Status = STATUS_SUCCESS;
- PDEVICE_EXTENSION DeviceExt;
+ NTSTATUS Status;
- assert (DeviceObject);
- assert (Irp);
-
- if (DeviceObject->Size == sizeof (DEVICE_OBJECT))
- {
- /* DeviceObject represents FileSystem instead of logical volume */
- DbgPrint ("FsdCreate called with file system\n");
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = FILE_OPENED;
- IoCompleteRequest (Irp, IO_NO_INCREMENT);
- return (Status);
- }
+ assert (IrpContext);
- DeviceExt = DeviceObject->DeviceExtension;
- assert (DeviceExt);
- ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
+ if (IrpContext->DeviceObject->Size == sizeof (DEVICE_OBJECT))
+ {
+ /* DeviceObject represents FileSystem instead of logical volume */
+ DbgPrint ("FsdCreate called with file system\n");
+ IrpContext->Irp->IoStatus.Information = FILE_OPENED;
+ Status = STATUS_SUCCESS;
+ goto ByeBye;
+ }
- Status = VfatCreateFile (DeviceObject, Irp);
-
- ExReleaseResourceLite (&DeviceExt->DirResource);
-
- Irp->IoStatus.Status = Status;
- IoCompleteRequest (Irp, IO_NO_INCREMENT);
+ if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
+ {
+ return VfatQueueRequest (IrpContext);
+ }
+
+ ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, TRUE);
+ Status = VfatCreateFile (IrpContext->DeviceObject, IrpContext->Irp);
+ ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource);
+ByeBye:
+ IrpContext->Irp->IoStatus.Status = Status;
+ IoCompleteRequest (IrpContext->Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
+ VfatFreeIrpContext(IrpContext);
return Status;
}