* 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
#include <ddk/ntddk.h>
-//#define NDEBUG
+#define NDEBUG
#include <debug.h>
#include "cdfs.h"
/* 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,
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;
}
* 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
JolietLevel = 3;
}
+ /* Don't support Joliet yet! */
+//#if 0
Vcb->CdInfo.JolietLevel = JolietLevel;
if (JolietLevel != 0)
DPRINT1("RootStart: %lu\n", Svd->RootDirRecord.ExtentLocationL);
DPRINT1("RootSize: %lu\n", Svd->RootDirRecord.DataLengthL);
}
+//#endif
}
}
-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);
}
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;
}
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);
}
PIO_STACK_LOCATION Stack;
NTSTATUS Status;
- DPRINT1("CdfsFileSystemControl() called\n");
+ DPRINT("CdfsFileSystemControl() called\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
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: