From: Eric Kohl Date: Fri, 26 Apr 2002 23:21:28 +0000 (+0000) Subject: Added media change support (untested). X-Git-Tag: backups/mpw@12443~76 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=23f679e5714d51318f642d8d95dab86b25016ee1 Added media change support (untested). Added directory listing (works only on the root directory). svn path=/trunk/; revision=2872 --- diff --git a/reactos/drivers/fs/cdfs/common.c b/reactos/drivers/fs/cdfs/common.c index c3b5680e1ae..98a2b1ec09f 100644 --- a/reactos/drivers/fs/cdfs/common.c +++ b/reactos/drivers/fs/cdfs/common.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: common.c,v 1.2 2002/04/15 20:39:49 ekohl Exp $ +/* $Id: common.c,v 1.3 2002/04/26 23:21:28 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -93,6 +93,19 @@ CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, if (!NT_SUCCESS(Status)) { + if (Status == STATUS_VERIFY_REQUIRED) + { + PDEVICE_OBJECT DeviceToVerify; + NTSTATUS NewStatus; + + DPRINT1("STATUS_VERIFY_REQUIRED\n"); + DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); + IoSetDeviceToVerify(PsGetCurrentThread(), NULL); + + NewStatus = IoVerifyVolume(DeviceToVerify, FALSE); + DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus); + } + DPRINT("CdfsReadSectors() failed (Status %x)\n", Status); DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n", DeviceObject, DiskSector, Buffer, diff --git a/reactos/drivers/fs/cdfs/dirctl.c b/reactos/drivers/fs/cdfs/dirctl.c index a77729fe323..419087743bc 100644 --- a/reactos/drivers/fs/cdfs/dirctl.c +++ b/reactos/drivers/fs/cdfs/dirctl.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dirctl.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ +/* $Id: dirctl.c,v 1.2 2002/04/26 23:21:28 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -30,7 +30,7 @@ #include -//#define NDEBUG +#define NDEBUG #include #include "cdfs.h" @@ -38,42 +38,597 @@ /* FUNCTIONS ****************************************************************/ -/* HACK -- NEEDS FIXING */ -#if 0 -int -FsdExtractDirectoryEntry(PDEVICE_EXTENSION DeviceExt, - FsdFcbEntry *parent, - FsdFcbEntry *fill_in, - int entry_to_get) + +static BOOLEAN +wstrcmpjoki(PWSTR s1, PWSTR s2) +/* + * FUNCTION: Compare two wide character strings, s2 with jokers (* or ?) + * return TRUE if s1 like s2 + */ { - switch( entry_to_get ) + while ((*s2=='*')||(*s2=='?')||(towlower(*s1)==towlower(*s2))) { - case 0: - wcscpy( fill_in->name, L"." ); - fill_in->extent_start = parent->extent_start; - fill_in->byte_count = parent->byte_count; - break; + if ((*s1)==0 && (*s2)==0) + return(TRUE); - case 1: - wcscpy( fill_in->name, L".." ); - fill_in->extent_start = parent->extent_start; - fill_in->byte_count = parent->byte_count; - break; + if(*s2=='*') + { + s2++; + while (*s1) + if (wstrcmpjoki(s1,s2)) + return TRUE; + else + s1++; + } + else + { + s1++; + s2++; + } + } - case 2: - wcscpy( fill_in->name, L"readme.txt" ); - fill_in->extent_start = 0x190; - fill_in->byte_count = 0x800; - break; + if ((*s2)=='.') + { + for (;((*s2)=='.')||((*s2)=='*')||((*s2)=='?');s2++) + ; + } - default: - return 1; + if ((*s1)==0 && (*s2)==0) + return(TRUE); + + return(FALSE); +} + + +static void +CdfsSwapString(PWCHAR Out, + PUCHAR In, + ULONG Count) +{ + PUCHAR t = (PUCHAR)Out; + ULONG i; + + for (i = 0; i < Count; i += 2) + { + t[i] = In[i+1]; + t[i+1] = In[i]; } + t[i] = 0; + t[i+1] = 0; +} + + +static VOID +CdfsDateTimeToFileTime(PFCB Fcb, + TIME *FileTime) +{ + TIME_FIELDS TimeFields; - return 0; + TimeFields.Milliseconds = 0; + TimeFields.Second = Fcb->Entry.Second; + TimeFields.Minute = Fcb->Entry.Minute; + TimeFields.Hour = Fcb->Entry.Hour; + + TimeFields.Day = Fcb->Entry.Day; + TimeFields.Month = Fcb->Entry.Month; + TimeFields.Year = Fcb->Entry.Year + 1900; + + RtlTimeFieldsToTime(&TimeFields, + (PLARGE_INTEGER)FileTime); } + + +NTSTATUS +CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt, + PVOID Block, + ULONG BlockLength, + PVOID *Ptr, + PWSTR Name, + PULONG pIndex, + PULONG pIndex2) +/* + * FUNCTION: Retrieves the file name, be it in short or long file name format + */ +{ + PDIR_RECORD Record; + NTSTATUS Status; + ULONG Index = 0; + ULONG Offset = 0; + + Record = (PDIR_RECORD)Block; + while(Index < *pIndex) + { + Offset = Offset + Record->RecordLength; + + Record = (PDIR_RECORD)(Block + Offset); + if (Record->RecordLength == 0) + { + Offset = ROUND_UP(Offset, 2048); + Record = (PDIR_RECORD)(Block + Offset); + } + + if (Offset >= BlockLength) + return(STATUS_NO_MORE_ENTRIES); + + Index++; + } + + DPRINT("Index %lu RecordLength %lu Offset %lu\n", + Index, Record->RecordLength, Offset); + + if (Record->FileIdLength == 1 && Record->FileId[0] == 0) + { + wcscpy(Name, L"."); + } + else if (Record->FileIdLength == 1 && Record->FileId[0] == 1) + { + wcscpy(Name, L".."); + } + else + { + if (DeviceExt->CdInfo.JolietLevel == 0) + { + ULONG i; + + for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++) + Name[i] = (WCHAR)Record->FileId[i]; + Name[i] = 0; + } + else + { + CdfsSwapString(Name, Record->FileId, Record->FileIdLength); + } + } + + DPRINT("Name '%S'\n", Name); + + *Ptr = Record; + + *pIndex = Index; + + return(STATUS_SUCCESS); +} + + +NTSTATUS +CdfsFindFile(PDEVICE_EXTENSION DeviceExt, + PFCB Fcb, + PFCB Parent, + PWSTR FileToFind, + PULONG pDirIndex, + PULONG pDirIndex2) +/* + * FUNCTION: Find a file + */ +{ + WCHAR name[256]; + char * block; + WCHAR TempStr[2]; + NTSTATUS Status; + ULONG len; + ULONG DirIndex; + ULONG Offset; + ULONG FirstSector; + ULONG Read; + BOOLEAN IsRoot; + LARGE_INTEGER FileOffset; + PVOID Context = NULL; + + ULONG DirSize; + ULONG BufferSize; + ULONG SectorCount; + PUCHAR Ptr; + PDIR_RECORD Record; + + 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) + { + FirstSector = Parent->Entry.ExtentLocationL; + if (FirstSector == DeviceExt->CdInfo.RootStart) + { + IsRoot = TRUE; + } + } + else + { + IsRoot = TRUE; + } + + if (IsRoot == TRUE) + { + FirstSector = DeviceExt->CdInfo.RootStart; + DirSize = DeviceExt->CdInfo.RootSize; + + + if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0) + || (FileToFind[0] == '.' && FileToFind[1] == 0)) + { + /* it's root : complete essentials fields then return ok */ + RtlZeroMemory(Fcb, sizeof(FCB)); + + Fcb->PathName[0]='\\'; + Fcb->ObjectName = &Fcb->PathName[1]; + Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart; + Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize; + Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY; + + if (pDirIndex) + *pDirIndex = 0; + if (pDirIndex2) + *pDirIndex2 = 0; + DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName); + return (STATUS_SUCCESS); + } + } + else + { + FirstSector = Parent->Entry.ExtentLocationL; + DirSize = Parent->Entry.DataLengthL; + } + + DPRINT("FirstSector %lu DirSize %lu\n", FirstSector, DirSize); + + if (pDirIndex && (*pDirIndex)) + DirIndex = *pDirIndex; + + BufferSize = ROUND_UP(DirSize, BLOCKSIZE); + SectorCount = BufferSize / BLOCKSIZE; + + DPRINT("FirstSector %lu DirSize %lu BufferSize %lu SectorCount %lu\n", + FirstSector, DirSize, BufferSize, SectorCount); + + block = ExAllocatePool(NonPagedPool, BufferSize); + + Status = CdfsReadSectors(DeviceExt->StorageDevice, + FirstSector, + SectorCount, + block); + if (!NT_SUCCESS(Status)) + { + DPRINT("Reading directory extent failed (Status %lx)\n", Status); + ExFreePool(block); + return(Status); + } + + Ptr = (PUCHAR)block; + while(TRUE) + { + Record = (PDIR_RECORD)Ptr; + if (Record->RecordLength == 0) + { + DPRINT1("Stopped!\n"); + break; + } + + DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n", + Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength); + + Status = CdfsGetEntryName(DeviceExt, block, DirSize, (PVOID*)&Ptr, name, &DirIndex, pDirIndex2); + if (Status == STATUS_NO_MORE_ENTRIES) + { + break; + } + +// DPRINT("Name '%S'\n", name); + + if (wstrcmpjoki(name, FileToFind)) /* || wstrcmpjoki (name2, FileToFind)) */ + { + if (Parent && Parent->PathName) + { + len = wcslen(Parent->PathName); + 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]; + } + + DPRINT("PathName '%S' ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName); + + memcpy(&Fcb->Entry, Ptr, sizeof(DIR_RECORD)); + 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); + + ExFreePool(block); + + return(STATUS_SUCCESS); + } + + + Ptr = Ptr + Record->RecordLength; + DirIndex++; + + if (((ULONG)Ptr - (ULONG)block) >= DirSize) + { + DPRINT("Stopped!\n"); + break; + } + } + + ExFreePool(block); + + if (pDirIndex) + *pDirIndex = DirIndex; + + return(STATUS_UNSUCCESSFUL); +} + + +static NTSTATUS +CdfsGetBothInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_BOTH_DIRECTORY_INFORMATION Info, + ULONG BufferLength) +{ +// short i; +// ULONGLONG AllocSize; + ULONG Length; + + DPRINT("FileBothDirectoryInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + +// Info->FileIndex=; + + /* Convert file times */ + CdfsDateTimeToFileTime(Fcb, + &Info->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->ChangeTime); + + Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; + + /* Make AllocSize a rounded up multiple of the sector size */ +// AllocSize = ((Fcb->Entry.DataLengthL + BLOCKSIZE - 1) / +// BLOCKSIZE) * BLOCKSIZE; +// Info->AllocationSize.QuadPart = AllocSize; + Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); + + /* FIXME: Convert file flags to file attributes */ + Info->FileAttributes = (Fcb->Entry.FileFlags & 0x02) ? FILE_ATTRIBUTE_DIRECTORY : 0; + Info->EaSize = 0; + + /* FIXME: Copy or create a short file name */ +#if 0 + for (i = 0; i < 8 && (pFcb->entry.Filename[i] != ' '); i++) + pInfo->ShortName[i] = pFcb->entry.Filename[i]; + pInfo->ShortNameLength = i; + pInfo->ShortName[i] = '.'; + for (i = 0; i < 3 && (pFcb->entry.Ext[i] != ' '); i++) + pInfo->ShortName[i + 1 + pInfo->ShortNameLength] = pFcb->entry.Ext[i]; + if (i) + pInfo->ShortNameLength += (i + 1); + pInfo->ShortNameLength *= sizeof(WCHAR); #endif + Info->ShortName[0] = 0; + Info->ShortNameLength = 0; + + return STATUS_SUCCESS; +} + + + +static NTSTATUS +CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + LONG BufferLength = 0; + PUNICODE_STRING SearchPattern = NULL; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG FileIndex = 0; + PUCHAR Buffer = NULL; + PFILE_NAMES_INFORMATION Buffer0 = NULL; + PFCB Fcb; + PCCB Ccb; + FCB TempFcb; + BOOLEAN First = FALSE; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("CdfsQueryDirectory() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + + Ccb = (PCCB)FileObject->FsContext2; + Fcb = Ccb->Fcb; + + /* Obtain the callers parameters */ + BufferLength = Stack->Parameters.QueryDirectory.Length; + SearchPattern = Stack->Parameters.QueryDirectory.FileName; + FileInformationClass = + Stack->Parameters.QueryDirectory.FileInformationClass; + FileIndex = Stack->Parameters.QueryDirectory.FileIndex; + + + if (SearchPattern != NULL) + { + if (!Ccb->DirectorySearchPattern) + { + First = TRUE; + Ccb->DirectorySearchPattern = + ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR)); + if (!Ccb->DirectorySearchPattern) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + memcpy(Ccb->DirectorySearchPattern, + SearchPattern->Buffer, + SearchPattern->Length); + Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0; + } + } + else if (!Ccb->DirectorySearchPattern) + { + First = TRUE; + Ccb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR)); + if (!Ccb->DirectorySearchPattern) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + Ccb->DirectorySearchPattern[0] = L'*'; + Ccb->DirectorySearchPattern[1] = 0; + } + DPRINT("Search pattern '%S'\n", Ccb->DirectorySearchPattern); + + /* Determine directory index */ + if (Stack->Flags & SL_INDEX_SPECIFIED) + { + Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart; + } + else if (First || (Stack->Flags & SL_RESTART_SCAN)) + { + Ccb->Entry = 0; + } + + /* Determine Buffer for result */ + if (Irp->MdlAddress) + { + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + } + else + { + Buffer = Irp->UserBuffer; + } + DPRINT("Buffer=%x tofind=%S\n", Buffer, Ccb->DirectorySearchPattern); + + TempFcb.ObjectName = TempFcb.PathName; + while (Status == STATUS_SUCCESS && BufferLength > 0) + { + Status = CdfsFindFile(DeviceExtension, + &TempFcb, + Fcb, + Ccb->DirectorySearchPattern, + &Ccb->Entry, + NULL); + DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry); + + if (NT_SUCCESS(Status)) + { + switch (FileInformationClass) + { + case FileNameInformation: + DPRINT1("FileNameInformation\n"); +// Status = VfatGetFileNameInformation(&TempFcb, +// (PFILE_NAMES_INFORMATION) Buffer, BufferLength); +// break; + + case FileDirectoryInformation: + DPRINT1("FileDirectoryInformation\n"); +// Status = VfatGetFileDirectoryInformation(&TempFcb, DeviceExtension, +// (PFILE_DIRECTORY_INFORMATION) Buffer, BufferLength); + break; + + case FileFullDirectoryInformation: + DPRINT1("FileFullDirecrotyInformation\n"); +// Status = CdfsGetFullDirectoryInformation(&TempFcb, +// DeviceExtension, +// (PFILE_FULL_DIRECTORY_INFORMATION)Buffer, BufferLength); + break; + + case FileBothDirectoryInformation: + Status = CdfsGetBothInformation(&TempFcb, + DeviceExtension, + (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer, + BufferLength); + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + + if (Status == STATUS_BUFFER_OVERFLOW) + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + break; + } + } + else + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + + if (First) + { + Status = STATUS_NO_SUCH_FILE; + } + else + { + Status = STATUS_NO_MORE_FILES; + } + break; + } + + Buffer0 = (PFILE_NAMES_INFORMATION)Buffer; + Buffer0->FileIndex = FileIndex++; + Ccb->Entry++; + + if (Stack->Flags & SL_RETURN_SINGLE_ENTRY) + { + break; + } + BufferLength -= Buffer0->NextEntryOffset; + Buffer += Buffer0->NextEntryOffset; + } + + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + + if (FileIndex > 0) + { + Status = STATUS_SUCCESS; + } + + return(Status); +} + + NTSTATUS STDCALL CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject, @@ -88,9 +643,18 @@ CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject, switch (Stack->MinorFunction) { + case IRP_MN_QUERY_DIRECTORY: + Status = CdfsQueryDirectory(DeviceObject, + Irp); + break; + + case IRP_MN_NOTIFY_CHANGE_DIRECTORY: + DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; default: - DPRINT("CDFS: MinorFunction %d\n", Stack->MinorFunction); + DPRINT1("CDFS: MinorFunction %d\n", Stack->MinorFunction); Status = STATUS_INVALID_DEVICE_REQUEST; break; } diff --git a/reactos/drivers/fs/cdfs/fcb.c b/reactos/drivers/fs/cdfs/fcb.c index 3597ba76b33..e0958200ea1 100644 --- a/reactos/drivers/fs/cdfs/fcb.c +++ b/reactos/drivers/fs/cdfs/fcb.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: fcb.c,v 1.2 2002/04/15 20:39:49 ekohl Exp $ +/* $Id: fcb.c,v 1.3 2002/04/26 23:21:28 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -283,7 +283,7 @@ vfatMakeFCBFromDirEntry(PVCB vcb, PVFATFCB directoryFCB, PWSTR longName, PFAT_DIR_ENTRY dirEntry, - ULONG dirIndex, + ULONG dirIndex, PVFATFCB * fileFCB) { PVFATFCB rcFCB; diff --git a/reactos/drivers/fs/cdfs/fsctl.c b/reactos/drivers/fs/cdfs/fsctl.c index 9d411b591f1..2c2a053c3ce 100644 --- a/reactos/drivers/fs/cdfs/fsctl.c +++ b/reactos/drivers/fs/cdfs/fsctl.c @@ -16,7 +16,7 @@ * 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.1 2002/04/15 20:39:49 ekohl Exp $ +/* $Id: fsctl.c,v 1.2 2002/04/26 23:21:28 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -118,6 +118,8 @@ CdfsGetSVDData(PUCHAR Buffer, JolietLevel = 3; } + /* Don't support Joliet yet! */ +//#if 0 Vcb->CdInfo.JolietLevel = JolietLevel; if (JolietLevel != 0) @@ -128,6 +130,7 @@ CdfsGetSVDData(PUCHAR Buffer, DPRINT1("RootStart: %lu\n", Svd->RootDirRecord.ExtentLocationL); DPRINT1("RootSize: %lu\n", Svd->RootDirRecord.DataLengthL); } +//#endif } @@ -199,41 +202,47 @@ CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject, } -static BOOLEAN +static NTSTATUS CdfsHasFileSystem(PDEVICE_OBJECT DeviceToMount) /* * FUNCTION: Tests if the device contains a filesystem that can be mounted * by this fsd */ { - PUCHAR bytebuf; // [CDFS_BASIC_SECTOR]; + PUCHAR Buffer; NTSTATUS Status; - int ret; - bytebuf = ExAllocatePool( NonPagedPool, CDFS_BASIC_SECTOR ); - if( !bytebuf ) return FALSE; + Buffer = ExAllocatePool(NonPagedPool, + CDFS_BASIC_SECTOR); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } DPRINT1("CDFS: Checking on mount of device %08x\n", DeviceToMount); Status = CdfsReadSectors(DeviceToMount, CDFS_PRIMARY_DESCRIPTOR_LOCATION, 1, - bytebuf); - bytebuf[6] = 0; - DPRINT1( "CD-identifier: [%.5s]\n", bytebuf + 1 ); - - ret = - Status == STATUS_SUCCESS && - bytebuf[0] == 1 && - bytebuf[1] == 'C' && - bytebuf[2] == 'D' && - bytebuf[3] == '0' && - bytebuf[4] == '0' && - bytebuf[5] == '1'; - - ExFreePool( bytebuf ); - - return ret; + Buffer); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Buffer[6] = 0; + DPRINT1("CD-identifier: [%.5s]\n", Buffer + 1); + + Status = (Buffer[0] == 1 && + Buffer[1] == 'C' && + Buffer[2] == 'D' && + Buffer[3] == '0' && + Buffer[4] == '0' && + Buffer[5] == '1') ? STATUS_SUCCESS : STATUS_UNRECOGNIZED_VOLUME; + + ExFreePool(Buffer); + + return(Status); } @@ -260,9 +269,9 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject, Stack = IoGetCurrentIrpStackLocation(Irp); DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; - if (CdfsHasFileSystem(DeviceToMount) == FALSE) + Status = CdfsHasFileSystem(DeviceToMount); + if (!NT_SUCCESS(Status)) { - Status = STATUS_UNRECOGNIZED_VOLUME; goto ByeBye; } @@ -358,6 +367,106 @@ ByeBye: IoDeleteDevice(NewDeviceObject); } + DPRINT1("CdfsMountVolume() done (Status: %lx)\n", Status); + + return(Status); +} + + +static NTSTATUS +CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_OBJECT DeviceToVerify; + PIO_STACK_LOCATION Stack; + PUCHAR Buffer; + ULONG Sector; + ULONG i; + NTSTATUS Status; + + union + { + ULONG Value; + UCHAR Part[4]; + } Serial; + + DPRINT1("CdfsVerifyVolume() called\n"); + + if (DeviceObject != CdfsGlobalData->DeviceObject) + { + return(STATUS_INVALID_DEVICE_REQUEST); + } + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject; + + Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION; + + Buffer = ExAllocatePool(NonPagedPool, + CDFS_BASIC_SECTOR); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = STATUS_WRONG_VOLUME; + + do + { + /* Read the Primary Volume Descriptor (PVD) */ + Status = CdfsReadSectors(DeviceToVerify, + Sector, + 1, + Buffer); + if (!NT_SUCCESS(Status)) + { + goto ByeBye; + } + + if (Buffer[0] == 1 && + Buffer[1] == 'C' && + Buffer[2] == 'D' && + Buffer[3] == '0' && + Buffer[4] == '0' && + Buffer[5] == '1') + { + break; + } + + Sector++; + } + while (Buffer[0] != 255); + + if (Buffer[0] == 255) + goto ByeBye; + + + /* Calculate the volume serial number */ + Serial.Value = 0; + for (i = 0; i < 2048; i += 4) + { + /* DON'T optimize this to ULONG!!! (breaks overflow) */ + Serial.Part[0] += Buffer[i+3]; + Serial.Part[1] += Buffer[i+2]; + Serial.Part[2] += Buffer[i+1]; + Serial.Part[3] += Buffer[i+0]; + } + + DPRINT1("Current serial number %08lx Vpb serial number %08lx\n", + Serial.Value, DeviceToVerify->Vpb->SerialNumber); + + if (Serial.Value == DeviceToVerify->Vpb->SerialNumber) + Status = STATUS_SUCCESS; + +ByeBye: + + ExFreePool(Buffer); + + +// Status = STATUS_INVALID_DEVICE_REQUEST; + + DPRINT1("CdfsVerifyVolume() done (Status: %lx)\n", Status); + return(Status); } @@ -369,7 +478,7 @@ CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIO_STACK_LOCATION Stack; NTSTATUS Status; - DPRINT1("CdfsFileSystemControl() called\n"); + DPRINT("CdfsFileSystemControl() called\n"); Stack = IoGetCurrentIrpStackLocation(Irp); @@ -386,8 +495,8 @@ CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject, break; case IRP_MN_VERIFY_VOLUME: - DPRINT("CDFS: IRP_MN_VERIFY_VOLUME\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; + DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n"); + Status = CdfsVerifyVolume(DeviceObject, Irp); break; default: