/* FUNCTIONS *****************************************************************/
-BOOLEAN
-IsLastEntry (PVOID Block, ULONG Offset)
-/*
- * FUNCTION: Determine if the given directory entry is the last
- */
-{
- return (((FATDirEntry *) Block)[Offset].Filename[0] == 0);
-}
-
-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;
-}
-
-BOOLEAN
-IsDeletedEntry (PVOID Block, ULONG Offset)
-/*
- * FUNCTION: Determines if the given entry is a deleted one
- */
-{
- /* Checks special character */
-
- return ((((FATDirEntry *) Block)[Offset].Filename[0] == 0xe5) ||
- (((FATDirEntry *) Block)[Offset].Filename[0] == 0));
-}
-
-void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
+void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PWSTR pName)
{
int fromIndex, toIndex;
fromIndex = toIndex = 0;
- while (fromIndex < 8 && pBasename [fromIndex] != ' ')
+ while (fromIndex < 8 && pEntry->Filename [fromIndex] != ' ')
{
- pName [toIndex++] = pBasename [fromIndex++];
+ if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
+ {
+ pName [toIndex++] = tolower(pEntry->Filename [fromIndex++]);
+ }
+ else
+ {
+ pName [toIndex++] = pEntry->Filename [fromIndex++];
+ }
}
- if (pExtension [0] != ' ')
+ if (pEntry->Ext [0] != ' ')
{
pName [toIndex++] = L'.';
fromIndex = 0;
- while (fromIndex < 3 && pExtension [fromIndex] != ' ')
+ while (fromIndex < 3 && pEntry->Ext [fromIndex] != ' ')
{
- pName [toIndex++] = pExtension [fromIndex++];
+ if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
+ {
+ pName [toIndex++] = tolower(pEntry->Ext [fromIndex++]);
+ }
+ else
+ {
+ pName [toIndex++] = pEntry->Ext [fromIndex++];
+ }
}
}
pName [toIndex] = L'\0';
}
-static void vfat8Dot3ToVolumeLabel (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
+static void vfat8Dot3ToVolumeLabel (PFAT_DIR_ENTRY pEntry, PWSTR pName)
{
int fromIndex, toIndex;
fromIndex = toIndex = 0;
- while (fromIndex < 8 && pBasename [fromIndex] != ' ')
+ while (fromIndex < 8 && pEntry->Filename [fromIndex] != ' ')
{
- pName [toIndex++] = pBasename [fromIndex++];
+ if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
+ {
+ pName [toIndex++] = tolower(pEntry->Filename [fromIndex++]);
+ }
+ else
+ {
+ pName [toIndex++] = pEntry->Filename [fromIndex++];
+ }
}
- if (pExtension [0] != ' ')
+ if (pEntry->Ext [0] != ' ')
{
fromIndex = 0;
- while (fromIndex < 3 && pBasename [fromIndex] != ' ')
+ while (fromIndex < 3 && pEntry->Ext [fromIndex] != ' ')
{
- pName [toIndex++] = pExtension [fromIndex++];
+ if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
+ {
+ pName [toIndex++] = tolower(pEntry->Ext [fromIndex++]);
+ }
+ else
+ {
+ pName [toIndex++] = pEntry->Ext [fromIndex++];
+ }
}
}
pName [toIndex] = L'\0';
}
NTSTATUS
-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
- */
-{
- 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))
- {
- (*pIndex)++;
- Offset++;
-
- if (Offset == ENTRIES_PER_PAGE)
- {
- Offset = 0;
- CcUnpinData(*pContext);
- FileOffset.QuadPart = *pIndex * sizeof(FATDirEntry);
- if(!CcMapData(FileObject, &FileOffset, PAGE_SIZE, 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, PAGE_SIZE, 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)
/*
* FUNCTION: Read the volume label
*/
{
PVOID Context = NULL;
- ULONG Offset = 0;
ULONG DirIndex = 0;
FATDirEntry* Entry;
PVFATFCB pFcb;
pFcb = vfatOpenRootFCB (DeviceExt);
- while (TRUE)
- {
- if (Context == NULL || Offset == ENTRIES_PER_PAGE)
- {
- if (Offset == ENTRIES_PER_PAGE)
- {
- Offset = 0;
- }
- if (Context)
- {
- CcUnpinData(Context);
- }
- FileOffset.u.HighPart = 0;
- FileOffset.u.LowPart = (DirIndex - Offset) * sizeof(FATDirEntry);
- if (!CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
- {
- Context = NULL;
- break;
- }
- }
- if (IsVolEntry(Entry, Offset))
- {
- /* copy volume label */
- vfat8Dot3ToVolumeLabel (Entry[Offset].Filename, Entry[Offset].Ext, Vpb->VolumeLabel);
- Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel) * sizeof(WCHAR);
- break;
- }
- if (IsLastEntry(Entry, Offset))
- {
- break;
- }
- Offset++;
- DirIndex++;
- }
-
- if (Context)
+ FileOffset.QuadPart = 0;
+ if (CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
{
- CcUnpinData(Context);
+ while (TRUE)
+ {
+ if (vfatIsDirEntryVolume(Entry))
+ {
+ /* copy volume label */
+ vfat8Dot3ToVolumeLabel (Entry, Vpb->VolumeLabel);
+ Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel) * sizeof(WCHAR);
+ break;
+ }
+ if (vfatIsDirEntryEndMarker(Entry))
+ {
+ break;
+ }
+ DirIndex++;
+ Entry++;
+ if ((DirIndex % ENTRIES_PER_PAGE) == 0)
+ {
+ CcUnpinData(Context);
+ FileOffset.u.LowPart += PAGE_SIZE;
+ if (!CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
+ {
+ Context = NULL;
+ break;
+ }
+ }
+ }
+ if (Context)
+ {
+ CcUnpinData(Context);
+ }
}
vfatReleaseFCB (DeviceExt, pFcb);
{
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;
+ PVOID Page;
+ PVFATFCB rcFcb;
+
+ FATDirEntry fatDirEntry;
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);
if (wcslen (FileToFind) == 0)
{
CHECKPOINT;
- TempStr[0] = (WCHAR) '.';
+ TempStr[0] = (WCHAR) '*';
TempStr[1] = 0;
FileToFind = (PWSTR)&TempStr;
}
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->FatInfo.rootDirectorySectors * DeviceExt->FatInfo.BytesPerSector;
- Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
- if (DeviceExt->FatInfo.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);
- }
+ {
+ /* 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->FatInfo.rootDirectorySectors * DeviceExt->FatInfo.BytesPerSector;
+ Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
+ if (DeviceExt->FatInfo.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
{
if (pDirIndex && (*pDirIndex))
DirIndex = *pDirIndex;
- Offset = DirIndex % ENTRIES_PER_PAGE;
+ if (NULL == wcschr(FileToFind, L'?') && NULL == wcschr(FileToFind, L'*'))
+ {
+ /* 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));
+ if (!vfatFCBIsRoot(Parent))
+ {
+ name[len++] = L'\\';
+ }
+ wcscpy(name + len, FileToFind);
+ rcFcb = vfatGrabFCBFromTable(DeviceExt, name);
+ if (rcFcb)
+ {
+ if(rcFcb->startIndex >= 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;
+ }
+ else
+ {
+ vfatReleaseFCB(DeviceExt, rcFcb);
+ return STATUS_UNSUCCESSFUL;
+ }
+ vfatReleaseFCB(DeviceExt, rcFcb);
+ }
+ }
+
while(TRUE)
{
- if (Context == NULL || Offset == ENTRIES_PER_PAGE)
+ Status = vfatGetNextDirEntry(&Context, &Page, Parent, &DirIndex, name, &fatDirEntry, pDirIndex2);
+ if (Status == STATUS_NO_MORE_ENTRIES)
{
- if (Offset == ENTRIES_PER_PAGE)
- Offset = 0;
- if (Context)
- {
- CcUnpinData(Context);
- }
- FileOffset.QuadPart = (DirIndex - Offset) * sizeof(FATDirEntry);
- if (!CcMapData(Parent->FileObject, &FileOffset, PAGE_SIZE, TRUE,
- &Context, (PVOID*)&block))
- {
- Context = NULL;
- break;
- }
+ break;
}
- if (vfatIsDirEntryVolume(&((FATDirEntry*)block)[Offset]))
+ if (vfatIsDirEntryVolume(&fatDirEntry))
{
- Offset++;
DirIndex++;
- continue;
+ 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))
+ vfat8Dot3ToString(&fatDirEntry, name2);
+ if (wstrcmpjoki (name, FileToFind) || wstrcmpjoki (name2, FileToFind))
+ {
+ 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] != '\\')
{
- 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;
+ 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, 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 (Context)
+ CcUnpinData(Context);
+
+ return STATUS_SUCCESS;
}
- Offset++;
DirIndex++;
}
if (pDirIndex)
- *pDirIndex = DirIndex;
+ *pDirIndex = DirIndex;
+
if (Context)
- CcUnpinData(Context);
+ CcUnpinData(Context);
+
return (STATUS_UNSUCCESSFUL);
}
Fcb->RFCB.AllocationSize.QuadPart = 0;
Fcb->RFCB.FileSize.QuadPart = 0;
Fcb->RFCB.ValidDataLength.QuadPart = 0;
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
+ /* Notify cache manager about the change in file size if caching is
+ initialized on the file stream */
+ if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
+ {
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
+ }
}
while (Cluster != 0xffffffff && Cluster > 1)
{
PVFATCCB pCcb;
PVFATFCB pFcb;
PWCHAR c;
- BOOLEAN PagingFileCreate = FALSE;
+ BOOLEAN PagingFileCreate = FALSE;
+ LARGE_INTEGER AllocationSize;
/* Unpack the various parameters. */
Stack = IoGetCurrentIrpStackLocation (Irp);
return(STATUS_NOT_A_DIRECTORY);
}
pFcb = DeviceExt->VolumeFcb;
- pCcb = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
+ pCcb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
if (pCcb == NULL)
{
return (STATUS_INSUFFICIENT_RESOURCES);
if (RequestedDisposition == FILE_CREATE)
{
Irp->IoStatus.Information = FILE_EXISTS;
+ VfatCloseFile (DeviceExt, FileObject);
return(STATUS_OBJECT_NAME_COLLISION);
}
VfatCloseFile (DeviceExt, FileObject);
return(STATUS_NOT_A_DIRECTORY);
}
+
+ if (RequestedDisposition == FILE_OVERWRITE ||
+ RequestedDisposition == FILE_OVERWRITE_IF)
+ {
+ AllocationSize.QuadPart = 0;
+ Status = VfatSetAllocationSizeInformation (FileObject,
+ pFcb,
+ DeviceExt,
+ &AllocationSize);
+ if (!NT_SUCCESS (Status))
+ {
+ VfatCloseFile (DeviceExt, FileObject);
+ return(Status);
+ }
+ }
+
/* Supersede the file */
if (RequestedDisposition == FILE_SUPERSEDE)