-/* $Id: create.c,v 1.6 2000/07/07 02:14:14 ekohl Exp $
+/* $Id: create.c,v 1.36 2002/01/15 21:54:51 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
-#include <ddk/cctypes.h>
#include <wchar.h>
#include <limits.h>
#include "vfat.h"
-/* FUNCTIONS ****************************************************************/
+/* GLOBALS *******************************************************************/
-BOOLEAN IsLastEntry(PVOID Block, ULONG Offset)
+#define ENTRIES_PER_PAGE (PAGESIZE / sizeof (FATDirEntry))
+
+/* FUNCTIONS *****************************************************************/
+
+BOOLEAN
+IsLastEntry (PVOID Block, ULONG Offset)
/*
* FUNCTION: Determine if the given directory entry is the last
*/
{
- return(((FATDirEntry *)Block)[Offset].Filename[0] == 0);
+ return (((FATDirEntry *) Block)[Offset].Filename[0] == 0);
}
-BOOLEAN IsVolEntry(PVOID Block, ULONG Offset)
+BOOLEAN
+IsVolEntry (PVOID Block, ULONG Offset)
/*
* FUNCTION: Determine if the given directory entry is a vol entry
*/
{
- if( (((FATDirEntry *)Block)[Offset].Attrib)==0x28 ) return TRUE;
- else return FALSE;
+ if ((((FATDirEntry *) Block)[Offset].Attrib) == 0x28)
+ return TRUE;
+ else
+ return FALSE;
}
-BOOLEAN IsDeletedEntry(PVOID Block, ULONG Offset)
+BOOLEAN
+IsDeletedEntry (PVOID Block, ULONG Offset)
/*
* FUNCTION: Determines if the given entry is a deleted one
*/
{
- /* Checks special character */
+ /* Checks special character */
+
+ return ((((FATDirEntry *) Block)[Offset].Filename[0] == 0xe5) ||
+ (((FATDirEntry *) Block)[Offset].Filename[0] == 0));
+}
+
+void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
+{
+ int fromIndex, toIndex;
+
+ fromIndex = toIndex = 0;
+ while (fromIndex < 8 && pBasename [fromIndex] != ' ')
+ {
+ pName [toIndex++] = pBasename [fromIndex++];
+ }
+ if (pExtension [0] != ' ')
+ {
+ pName [toIndex++] = L'.';
+ fromIndex = 0;
+ while (fromIndex < 3 && pExtension [fromIndex] != ' ')
+ {
+ pName [toIndex++] = pExtension [fromIndex++];
+ }
+ }
+ pName [toIndex] = L'\0';
+}
- return ((((FATDirEntry *)Block)[Offset].Filename[0] == 0xe5) || (((FATDirEntry *)Block)[Offset].Filename[0] == 0));
+static void vfat8Dot3ToVolumeLabel (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
+{
+ int fromIndex, toIndex;
+
+ fromIndex = toIndex = 0;
+ while (fromIndex < 8 && pBasename [fromIndex] != ' ')
+ {
+ pName [toIndex++] = pBasename [fromIndex++];
+ }
+ if (pExtension [0] != ' ')
+ {
+ fromIndex = 0;
+ while (fromIndex < 3 && pBasename [fromIndex] != ' ')
+ {
+ pName [toIndex++] = pExtension [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;
- ULONG cpos;
-
- test = (FATDirEntry *)Block;
- test2 = (slot *)Block;
-
- *Name = 0;
-
- if (IsDeletedEntry(Block,Offset))
- {
- return(FALSE);
- }
-
- if(test2[Offset].attr == 0x0f)
- {
- vfat_initstr(Name, 256);
- 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);
-
- cpos=0;
- while((test2[Offset].id!=0x41) && (test2[Offset].id!=0x01) &&
- (test2[Offset].attr>0))
+ NTSTATUS Status;
+ FATDirEntry * test;
+ slot * test2;
+ ULONG cpos;
+ ULONG Offset = *pIndex % ENTRIES_PER_PAGE;
+ ULONG Read;
+ LARGE_INTEGER FileOffset;
+
+ *Name = 0;
+ while (TRUE)
+ {
+ test = (FATDirEntry *) *Block;
+ test2 = (slot *) *Block;
+ if (vfatIsDirEntryEndMarker(&test[Offset]))
+ {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ if (test2[Offset].attr == 0x0f && !vfatIsDirEntryDeleted(&test[Offset]))
+ {
+ *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;
- StartingSector++;//FIXME : nor always the next sector
- jloop++;
- 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);
-
+ (*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;
}
-
- if (IsDeletedEntry(Block,Offset+1))
- {
- Offset++;
- *_Offset = Offset;
- *_jloop = jloop;
- *_StartingSector = StartingSector;
- return(FALSE);
+ 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);
}
-
- *_Offset = Offset;
- *_jloop = jloop;
- *_StartingSector = StartingSector;
-
- return(TRUE);
- }
-
- RtlAnsiToUnicode(Name,test[Offset].Filename,8);
- if (test[Offset].Ext[0]!=' ')
- {
- RtlCatAnsiToUnicode(Name,".",1);
- }
- RtlCatAnsiToUnicode(Name,test[Offset].Ext,3);
-
- *_Offset = Offset;
-
- return(TRUE);
+ (*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;
+ }
+ }
+ 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 ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
+NTSTATUS
+ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
/*
* FUNCTION: Read the volume label
*/
{
- ULONG i = 0;
- ULONG j;
- ULONG Size;
- char* block;
- ULONG StartingSector;
- ULONG NextCluster;
-
- Size = DeviceExt->rootDirectorySectors;//FIXME : in fat32, no limit
- StartingSector = DeviceExt->rootStart;
- NextCluster=0;
-
- block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
- DPRINT("FindFile : start at sector %lx, entry %ld\n",StartingSector,i);
- for (j=0; j<Size; j++)
- {
- VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
-
- for (i=0; i<ENTRIES_PER_SECTOR; i++)
- {
- if (IsVolEntry((PVOID)block,i))
- {
- FATDirEntry *test = (FATDirEntry *)block;
+ ULONG i = 0;
+ ULONG j;
+ ULONG Size;
+ char *block;
+ ULONG StartingSector;
+ ULONG NextCluster;
+ NTSTATUS Status;
+
+ Size = DeviceExt->rootDirectorySectors; /* FIXME : in fat32, no limit */
+ StartingSector = DeviceExt->rootStart;
+ NextCluster = 0;
+
+ block = ExAllocatePool (NonPagedPool, BLOCKSIZE);
+ DPRINT ("ReadVolumeLabel : start at sector %lx, entry %ld\n", StartingSector, i);
+ for (j = 0; j < Size; j++)
+ {
+ /* FIXME: Check status */
+ Status = VfatReadSectors (DeviceExt->StorageDevice, StartingSector, 1, block);
+ if (!NT_SUCCESS(Status))
+ {
+ *(Vpb->VolumeLabel) = 0;
+ Vpb->VolumeLabelLength = 0;
+ ExFreePool(block);
+ return(Status);
+ }
- /* copy volume label */
- RtlAnsiToUnicode(Vpb->VolumeLabel,test[i].Filename,8);
- RtlCatAnsiToUnicode(Vpb->VolumeLabel,test[i].Ext,3);
- Vpb->VolumeLabelLength = wcslen(Vpb->VolumeLabel);
+ for (i = 0; i < ENTRIES_PER_SECTOR; i++)
+ {
+ if (IsVolEntry ((PVOID) block, i))
+ {
+ FATDirEntry *test = (FATDirEntry *) block;
+
+ /* copy volume label */
+ vfat8Dot3ToVolumeLabel (test[i].Filename, test[i].Ext, Vpb->VolumeLabel);
+ Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel);
+
+ ExFreePool (block);
+ return (STATUS_SUCCESS);
+ }
+ if (IsLastEntry ((PVOID) block, i))
+ {
+ *(Vpb->VolumeLabel) = 0;
+ Vpb->VolumeLabelLength = 0;
+ ExFreePool (block);
+ return (STATUS_UNSUCCESSFUL);
+ }
+ }
+ /* not found in this sector, try next : */
- ExFreePool(block);
- return(STATUS_SUCCESS);
- }
- if (IsLastEntry((PVOID)block,i))
- {
- *(Vpb->VolumeLabel) = 0;
- Vpb->VolumeLabelLength = 0;
- ExFreePool(block);
- return(STATUS_UNSUCCESSFUL);
- }
- }
- // not found in this sector, try next :
-
- /* directory can be fragmented although it is best to keep them
- unfragmented */
- StartingSector++;
- if (DeviceExt->FatType ==FAT32)
- {
- if(StartingSector==ClusterToSector(DeviceExt,NextCluster+1))
- {
- NextCluster = GetNextCluster(DeviceExt,NextCluster);
- if (NextCluster == 0||NextCluster==0xffffffff)
- {
- *(Vpb->VolumeLabel) = 0;
- Vpb->VolumeLabelLength = 0;
- ExFreePool(block);
- return(STATUS_UNSUCCESSFUL);
- }
- StartingSector = ClusterToSector(DeviceExt,NextCluster);
- }
- }
- }
- *(Vpb->VolumeLabel) = 0;
- Vpb->VolumeLabelLength = 0;
- ExFreePool(block);
- return(STATUS_UNSUCCESSFUL);
-}
+ /* directory can be fragmented although it is best to keep them
+ unfragmented.*/
+ StartingSector++;
+ if (DeviceExt->FatType == FAT32)
+ {
+ if (StartingSector == ClusterToSector (DeviceExt, NextCluster + 1))
+ {
+ Status = GetNextCluster (DeviceExt, NextCluster, &NextCluster,
+ FALSE);
+ if (NextCluster == 0 || NextCluster == 0xffffffff)
+ {
+ *(Vpb->VolumeLabel) = 0;
+ Vpb->VolumeLabelLength = 0;
+ ExFreePool (block);
+ return (STATUS_UNSUCCESSFUL);
+ }
+ StartingSector = ClusterToSector (DeviceExt, NextCluster);
+ }
+ }
+ }
+ *(Vpb->VolumeLabel) = 0;
+ Vpb->VolumeLabelLength = 0;
+ ExFreePool (block);
+ return (STATUS_UNSUCCESSFUL);
+}
-NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb,
- PVFATFCB Parent, PWSTR FileToFind,ULONG *StartSector,ULONG *Entry)
+NTSTATUS
+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 TempStr[2];
-
- DPRINT("FindFile(Parent %x, FileToFind '%S')\n",Parent,FileToFind);
-
- if (wcslen(FileToFind)==0)
- {
- CHECKPOINT;
- TempStr[0] = (WCHAR)'.';
- TempStr[1] = 0;
- FileToFind=(PWSTR)&TempStr;
- }
- if (Parent != NULL)
- {
- DPRINT("Parent->entry.FirstCluster %d\n",Parent->entry.FirstCluster);
- }
-
- DPRINT("FindFile '%S'\n", FileToFind);
- if (Parent == NULL||Parent->entry.FirstCluster==1)
- {
- CHECKPOINT;
- 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))
- {
- /* it's root : complete essentials fields then return ok */
- CHECKPOINT;
- memset(Fcb,0,sizeof(VFATFCB));
- 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? */
- if(StartSector)
- *StartSector=StartingSector;
- if(Entry)
- *Entry=0;
- return(STATUS_SUCCESS);
- }
- }
- else
- {
- DPRINT("Parent->entry.FileSize %x\n",Parent->entry.FileSize);
-
- 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;
- }
- }
- CHECKPOINT;
- block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
- CHECKPOINT;
- if (StartSector && (*StartSector)) StartingSector=*StartSector;
- i=(Entry)?(*Entry):0;
- DPRINT("FindFile : start at sector %lx, entry %ld\n",StartingSector,i);
- for (j=0; j<Size; j++)
- {
- VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
-
- for (i=(Entry)?(*Entry):0; i<ENTRIES_PER_SECTOR; i++)
- {
- 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))
- {
- DPRINT("Comparing '%S' '%S'\n",name,FileToFind);
- if (wstrcmpjoki(name,FileToFind))
- {
- /* 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))
- {
- /* entry is in next sector */
- StartingSector++;
- /* FIXME : treat case of next sector fragmented */
- VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
- i=0;
- }
- 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);
- return(STATUS_SUCCESS);
- }
- }
- }
- /* not found in this sector, try next : */
-
- /* directory can be fragmented although it is best to keep them
- unfragmented */
- if(Entry) *Entry=0;
- StartingSector++;
- if ((Parent != NULL && Parent->entry.FirstCluster!=1)
- || DeviceExt->FatType ==FAT32)
+ WCHAR name[256];
+ WCHAR name2[14];
+ char * block;
+ WCHAR TempStr[2];
+ NTSTATUS Status;
+ ULONG len;
+ 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)
+ {
+ if (FirstCluster == ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster)
+ isRoot = TRUE;
+ }
+ else
+ {
+ 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;
+ memset (Fcb, 0, sizeof (VFATFCB));
+ memset (Fcb->entry.Filename, ' ', 11);
+ CHECKPOINT;
+ Fcb->PathName[0]='\\';
+ Fcb->ObjectName = &Fcb->PathName[1];
+ Fcb->entry.FileSize = DeviceExt->rootDirectorySectors * BLOCKSIZE;
+ Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
+ if (DeviceExt->FatType == FAT32)
+ {
+ Fcb->entry.FirstCluster = ((PUSHORT)FirstCluster)[0];
+ Fcb->entry.FirstClusterHigh = ((PUSHORT)FirstCluster)[1];
+ }
+ 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);
+ }
+ }
+ else
+ {
+ DPRINT ("Parent->entry.FileSize %x\n", Parent->entry.FileSize);
+ FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Parent->entry);
+ }
+ if (pDirIndex && (*pDirIndex))
+ DirIndex = *pDirIndex;
+
+ 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;
+ }
+ }
+ if (vfatIsDirEntryVolume(&((FATDirEntry*)block)[Offset]))
+ {
+ 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))
+ {
+ vfat8Dot3ToString(((FATDirEntry *) block)[Offset].Filename,((FATDirEntry *) block)[Offset].Ext, name2);
+ if (wstrcmpjoki (name, FileToFind) || wstrcmpjoki (name2, FileToFind))
{
- if(StartingSector==ClusterToSector(DeviceExt,NextCluster+1))
- {
- NextCluster = GetNextCluster(DeviceExt,NextCluster);
- if (NextCluster == 0||NextCluster==0xffffffff)
- {
- if(StartSector) *StartSector=StartingSector;
- if(Entry) *Entry=i;
- ExFreePool(block);
- return(STATUS_UNSUCCESSFUL);
- }
- StartingSector = ClusterToSector(DeviceExt,NextCluster);
- }
+ 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] != '\\')
+ {
+ Fcb->ObjectName[0] = '\\';
+ Fcb->ObjectName = &Fcb->ObjectName[1];
+ }
+ }
+ else
+ {
+ Fcb->ObjectName=Fcb->PathName;
+ Fcb->ObjectName[0]='\\';
+ Fcb->ObjectName=&Fcb->ObjectName[1];
+ }
+
+ 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);
- return(STATUS_UNSUCCESSFUL);
+ }
+ Offset++;
+ 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;
+ PVFATCCB ccb;
+
+ DbgPrint ("try related for %S\n", pRelativeFileName);
+ ccb = pFileObject->FsContext2;
+ assert (ccb);
+ fcb = ccb->pFcb;
+ assert (fcb);
+
+ /* verify related object is a directory and target name
+ don't start with \. */
+ 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
+ <= MAX_PATH);
+ rcName = ExAllocatePool (NonPagedPool, MAX_PATH);
+ wcscpy (rcName, fcb->PathName);
+ wcscat (rcName, L"\\");
+ wcscat (rcName, pRelativeFileName);
+ *pAbsoluteFilename = rcName;
+
+ return STATUS_SUCCESS;
+}
-
-NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
- PWSTR FileName)
+NTSTATUS
+VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
+ PWSTR FileName)
/*
* FUNCTION: Opens a file
*/
{
- PWSTR current = NULL;
- PWSTR next;
- PWSTR string;
- PVFATFCB ParentFcb;
- PVFATFCB Fcb,pRelFcb;
- PVFATFCB Temp;
- PVFATCCB newCCB,pRelCcb;
- NTSTATUS Status;
- PFILE_OBJECT pRelFileObject;
- PWSTR AbsFileName=NULL;
- short i,j;
- PLIST_ENTRY current_entry;
- KIRQL oldIrql;
-
- DPRINT("FsdOpenFile(%08lx, %08lx, %S)\n",
- DeviceExt,
- FileObject,
- FileName);
-
- /* FIXME : treat relative name */
- if(FileObject->RelatedFileObject)
- {
- DbgPrint("try related for %S\n",FileName);
- pRelFileObject=FileObject->RelatedFileObject;
- pRelCcb=pRelFileObject->FsContext2;
- assert(pRelCcb);
- pRelFcb=pRelCcb->pFcb;
- assert(pRelFcb);
- /*
- * verify related object is a directory and target name don't start with \.
- */
- if( !(pRelFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
- || (FileName[0]!= '\\') )
- {
- Status=STATUS_INVALID_PARAMETER;
- return Status;
- }
- /* construct absolute path name */
- AbsFileName=ExAllocatePool(NonPagedPool,MAX_PATH);
- for (i=0;pRelFcb->PathName[i];i++)
- AbsFileName[i]=pRelFcb->PathName[i];
- AbsFileName[i++]='\\';
- for (j=0;FileName[j]&&i<MAX_PATH;j++)
- AbsFileName[i++]=FileName[j];
- assert(i<MAX_PATH);
- AbsFileName[i]=0;
- FileName=AbsFileName;
- }
-
- /*
- * try first to find an existing FCB in memory
- */
- CHECKPOINT;
-
- KeAcquireSpinLock(&DeviceExt->FcbListLock, &oldIrql);
- current_entry = DeviceExt->FcbListHead.Flink;
- while (current_entry != &DeviceExt->FcbListHead)
- {
- Fcb = CONTAINING_RECORD(current_entry, VFATFCB, FcbListEntry);
-
- DPRINT("Scanning %x\n", Fcb);
- DPRINT("Scanning %S\n", Fcb->PathName);
-
- if (DeviceExt==Fcb->pDevExt
- && wstrcmpi(FileName,Fcb->PathName))
- {
- Fcb->RefCount++;
- KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
- FileObject->FsContext =(PVOID) &Fcb->NTRequiredFCB;
- newCCB = ExAllocatePool(NonPagedPool,sizeof(VFATCCB));
- memset(newCCB,0,sizeof(VFATCCB));
- FileObject->FsContext2 = newCCB;
- newCCB->pFcb=Fcb;
- newCCB->PtrFileObject=FileObject;
- if(AbsFileName)ExFreePool(AbsFileName);
- return(STATUS_SUCCESS);
- }
-
- current_entry = current_entry->Flink;
- }
- KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
-
-CHECKPOINT;
-DPRINT("FileName %S\n", FileName);
-
- string = FileName;
- ParentFcb = NULL;
- Fcb = ExAllocatePool(NonPagedPool, sizeof(VFATFCB));
- memset(Fcb,0,sizeof(VFATFCB));
- Fcb->ObjectName=Fcb->PathName;
- next = &string[0];
-
- CHECKPOINT;
- while (TRUE)
- {
- CHECKPOINT;
- *next = '\\';
- current = next+1;
- next = wcschr(next+1,'\\');
- if (next!=NULL)
+ PVFATFCB ParentFcb;
+ PVFATFCB Fcb;
+ NTSTATUS Status;
+ PWSTR AbsFileName = NULL;
+
+ DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
+
+ if (FileObject->RelatedFileObject)
+ {
+ DPRINT ("Converting relative filename to absolute filename\n");
+ Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
+ FileName,
+ &AbsFileName);
+ FileName = AbsFileName;
+ }
+
+ //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)
+ {
+ DPRINT ("No existing FCB found, making a new one if file exists.\n");
+ Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName);
+ if (ParentFcb != NULL)
+ {
+ vfatReleaseFCB (DeviceExt, ParentFcb);
+ }
+ 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;
+}
+
+NTSTATUS
+VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/*
+ * FUNCTION: Create or open a file
+ */
+{
+ PIO_STACK_LOCATION Stack;
+ PFILE_OBJECT FileObject;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PDEVICE_EXTENSION DeviceExt;
+ ULONG RequestedDisposition, RequestedOptions;
+ PVFATCCB pCcb;
+ PVFATFCB pFcb;
+ PWCHAR c;
+ BOOLEAN PagingFileCreate = FALSE;
+
+ Stack = IoGetCurrentIrpStackLocation (Irp);
+ assert (Stack);
+ RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
+ RequestedOptions =
+ Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
+ PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
+ if ((RequestedOptions & FILE_DIRECTORY_FILE)
+ && RequestedDisposition == FILE_SUPERSEDE)
+ return STATUS_INVALID_PARAMETER;
+ 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'?' || (*c == L'\\' && c[1] == L'\\'))
{
- *next=0;
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ return(STATUS_OBJECT_NAME_INVALID);
}
- else
+ c++;
+ }
+
+ Status = VfatOpenFile (DeviceExt, FileObject, FileObject->FileName.Buffer);
+
+ /*
+ * If the directory containing the file to open doesn't exist then
+ * fail immediately
+ */
+ Irp->IoStatus.Information = 0;
+ if (Status == STATUS_OBJECT_PATH_NOT_FOUND)
+ {
+ Irp->IoStatus.Status = Status;
+ 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 ||
+ RequestedDisposition == FILE_SUPERSEDE)
{
- /* reached the last path component */
- DPRINT("exiting: current '%S'\n",current);
- break;
+ CHECKPOINT;
+ Status =
+ addEntry (DeviceExt, FileObject, RequestedOptions,
+ (Stack->Parameters.
+ Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS));
+ if (NT_SUCCESS (Status))
+ {
+ if (PagingFileCreate)
+ {
+ DPRINT("Creating a new paging file.\n");
+ pCcb = FileObject->FsContext2;
+ pFcb = pCcb->pFcb;
+ pFcb->Flags |= FCB_IS_PAGE_FILE;
+ pFcb->FatChainSize = 0;
+ pFcb->FatChain = NULL;
+ }
+
+ Irp->IoStatus.Information = FILE_CREATED;
+ }
+ /* FIXME set size if AllocationSize requested */
+ /* FIXME set extended attributes? */
+ /* FIXME set share access */
+ /* IoSetShareAccess(DesiredAccess,ShareAccess,FileObject,
+ * ((PVfatCCB)(FileObject->FsContext2))->pFcb->FCBShareAccess);
+ */
}
-
- DPRINT("current '%S'\n",current);
- Status = FindFile(DeviceExt,Fcb,ParentFcb,current,NULL,NULL);
- if (Status != STATUS_SUCCESS)
+ }
+ else
+ {
+ /*
+ * Otherwise fail if the caller wanted to create a new file
+ */
+ if (RequestedDisposition == FILE_CREATE)
{
- 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;
+ Irp->IoStatus.Information = FILE_EXISTS;
+ Status = STATUS_OBJECT_NAME_COLLISION;
}
- Temp = Fcb;
-CHECKPOINT;
- if (ParentFcb == NULL)
+ 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);
+ 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;
+ }
+ }
+
+ /*
+ * If this create was for a paging file then make sure all the
+ * information needed to manipulate it is locked in memory.
+ */
+ if (PagingFileCreate)
+ {
+ ULONG CurrentCluster, NextCluster, i;
+ DPRINT("Open an existing paging file\n");
+ pFcb->Flags |= FCB_IS_PAGE_FILE;
+ pFcb->FatChainSize =
+ ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) / DeviceExt->BytesPerCluster);
+ if (pFcb->FatChainSize)
{
- CHECKPOINT;
- Fcb = ExAllocatePool(NonPagedPool,sizeof(VFATFCB));
- memset(Fcb,0,sizeof(VFATFCB));
- Fcb->ObjectName=Fcb->PathName;
+ pFcb->FatChain = ExAllocatePool(NonPagedPool,
+ pFcb->FatChainSize * sizeof(ULONG));
}
- else
- Fcb = ParentFcb;
-CHECKPOINT;
- ParentFcb = Temp;
- }
-
- /* searching for last path component */
- DPRINT("current '%S'\n",current);
- 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;
-CHECKPOINT;
- if (ParentFcb == NULL)
- {
- CHECKPOINT;
- Fcb = ExAllocatePool(NonPagedPool,sizeof(VFATFCB));
- memset(Fcb,0,sizeof(VFATFCB));
- Fcb->ObjectName=Fcb->PathName;
- }
- else
- Fcb = ParentFcb;
-CHECKPOINT;
- ParentFcb = Temp;
-
-
-CHECKPOINT;
- FileObject->FsContext =(PVOID) &ParentFcb->NTRequiredFCB;
- newCCB = ExAllocatePool(NonPagedPool,sizeof(VFATCCB));
- memset(newCCB,0,sizeof(VFATCCB));
- FileObject->FsContext2 = newCCB;
- newCCB->pFcb=ParentFcb;
- newCCB->PtrFileObject=FileObject;
- ParentFcb->RefCount++;
- //FIXME : initialize all fields in FCB and CCB
-
- KeAcquireSpinLock(&DeviceExt->FcbListLock, &oldIrql);
- InsertTailList(&DeviceExt->FcbListHead, &ParentFcb->FcbListEntry);
- KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
-
- vfat_wcsncpy(ParentFcb->PathName,FileName,MAX_PATH);
- ParentFcb->ObjectName=ParentFcb->PathName+(current-FileName);
- ParentFcb->pDevExt=DeviceExt;
- 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);
-}
+ if (DeviceExt->FatType == FAT32)
+ {
+ CurrentCluster = pFcb->entry.FirstCluster +
+ pFcb->entry.FirstClusterHigh * 65536;
+ }
+ else
+ {
+ CurrentCluster = pFcb->entry.FirstCluster;
+ }
-NTSTATUS FsdCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Create or open a file
- */
-{
- PIO_STACK_LOCATION Stack;
- PFILE_OBJECT FileObject;
- NTSTATUS Status=STATUS_SUCCESS;
- PDEVICE_EXTENSION DeviceExt;
- ULONG RequestedDisposition,RequestedOptions;
- PVFATCCB pCcb;
- PVFATFCB pFcb;
-
- Stack = IoGetCurrentIrpStackLocation(Irp);
- assert(Stack);
- RequestedDisposition = ((Stack->Parameters.Create.Options>>24)&0xff);
- RequestedOptions=Stack->Parameters.Create.Options&FILE_VALID_OPTION_FLAGS;
- FileObject = Stack->FileObject;
- DeviceExt = DeviceObject->DeviceExtension;
- assert(DeviceExt);
-
- Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
-
- CHECKPOINT;
- Irp->IoStatus.Information = 0;
- if (Status == STATUS_OBJECT_PATH_NOT_FOUND)
- {
- Irp->IoStatus.Status = Status;
- return Status;
- }
-
- CHECKPOINT;
- if(!NT_SUCCESS(Status))
- {
- if(RequestedDisposition==FILE_CREATE
- ||RequestedDisposition==FILE_OPEN_IF
- ||RequestedDisposition==FILE_OVERWRITE_IF)
- {
-CHECKPOINT;
- Status=addEntry(DeviceExt,FileObject,RequestedOptions
- ,(Stack->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS));
- if(NT_SUCCESS(Status))
- Irp->IoStatus.Information = FILE_CREATED;
- // FIXME set size if AllocationSize requested
- // FIXME set extended attributes ?
- // FIXME set share access
- // IoSetShareAccess(DesiredAccess,ShareAccess,FileObject
- // ,((PVfatCCB)(FileObject->FsContext2))->pFcb->FCBShareAccess);
+ i = 0;
+ if (pFcb->FatChainSize)
+ {
+ while (CurrentCluster != 0xffffffff)
+ {
+ pFcb->FatChain[i] = CurrentCluster;
+ Status = GetNextCluster (DeviceExt, CurrentCluster, &NextCluster,
+ FALSE);
+ i++;
+ CurrentCluster = NextCluster;
+ }
}
- }
- else
- {
- if(RequestedDisposition==FILE_CREATE)
- {
- Irp->IoStatus.Information = FILE_EXISTS;
- Status=STATUS_OBJECT_NAME_COLLISION;
- }
- pCcb=FileObject->FsContext2;
- pFcb=pCcb->pFcb;
- if( (RequestedOptions&FILE_NON_DIRECTORY_FILE)
- && (pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
- {
- Status=STATUS_FILE_IS_A_DIRECTORY;
- }
- if( (RequestedOptions&FILE_DIRECTORY_FILE)
- && !(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
- {
- Status=STATUS_NOT_A_DIRECTORY;
- }
- // FIXME : test share access
- // FIXME : test write access if requested
- if(!NT_SUCCESS(Status))
- FsdCloseFile(DeviceExt,FileObject);
- else Irp->IoStatus.Information = FILE_OPENED;
- // FIXME : make supersed or overwrite if requested
- }
-
-CHECKPOINT;
- Irp->IoStatus.Status = Status;
-
- return Status;
+ }
+
+ /*
+ * 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)
+ && !(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ Status = STATUS_NOT_A_DIRECTORY;
+ }
+ /* FIXME : test share access */
+ /* FIXME : test write access if requested */
+ if (!NT_SUCCESS (Status))
+ VfatCloseFile (DeviceExt, FileObject);
+ else
+ Irp->IoStatus.Information = FILE_OPENED;
+ /* FIXME : make supersed or overwrite if requested */
+ }
+
+ Irp->IoStatus.Status = Status;
+
+ return Status;
}
-NTSTATUS FsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext)
/*
* FUNCTION: Create or open a file
*/
{
- NTSTATUS Status=STATUS_SUCCESS;
- PDEVICE_EXTENSION DeviceExt;
-
- assert(DeviceObject);
- assert(Irp);
-
- if (DeviceObject->Size==sizeof(DEVICE_OBJECT))
- {
- /* DeviceObject represent 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);
- }
-
- DeviceExt = DeviceObject->DeviceExtension;
- assert(DeviceExt);
- ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
-
- Status = FsdCreateFile (DeviceObject, Irp);
-
- ExReleaseResourceLite(&DeviceExt->DirResource);
-
- Irp->IoStatus.Status = Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return Status;
+ NTSTATUS Status;
+
+ assert (IrpContext);
+
+ 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;
+ }
+
+ 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;
}
/* EOF */