/*++ Copyright (c) 1993 Microsoft Corporation Module Name: spdblspc.c Abstract: Code that detects compressed drives on a system that contains dblspace.ini in the root of c:. Author: Jaime Sasson (jaimes) 01-October-1993 Revision History: --*/ #include "spprecmp.h" #pragma hdrstop // // This variable is needed since it contains a buffer that can // be used in kernel mode. The buffer is used by NtFsControlFile, // since the Zw API is not exported // extern PSETUP_COMMUNICATION CommunicationParams; #define KWD_ACT L"ActivateDrive" #define KWD_FIRST L"FirstDrive" #define KWD_LAST L"LastDrive" #define KWD_MAXREM L"MaxRemovableDrives" #define KWD_MAXFILE L"MaxFileFragments" #define KWD_AUTOMOUNT L"Automount" #define KWD_DOUBLEGUARD L"Doubleguard" #define KWD_ROMSERVER L"Romserver" #define KWD_SWITCHES L"Switches" #define CVF_SEQ_MAX 255 #define MINFILEFRAGMENTS 50 #define MAXFILEFRAGMENTS 10000 #define DBLSPACE_INI_FILE L"\\dblspace.ini" #define CVF_NAME_PATTERN L"DBLSPACE.%03d" typedef struct _ACTIVATE_DRIVE { struct _ACTIVATE_DRIVE* Next; struct _ACTIVATE_DRIVE* Previous; WCHAR MountDrive; WCHAR HostDrive; USHORT SeqNumber; } ACTIVATE_DRIVE, *PACTIVATE_DRIVE; typedef struct _DBLSPACE_INI_INFO { USHORT MaxRemovableDrives; WCHAR FirstDrive; WCHAR LastDrive; USHORT MaxFileFragments; WCHAR DoubleGuard[2]; WCHAR RomServer[2]; PACTIVATE_DRIVE CompressedDriveList; WCHAR AutoMount[30]; WCHAR Switches[4]; } DBLSPACE_INI_INFO, *PDBLSPACE_INI_INFO; BOOLEAN DblspaceModified = FALSE; DBLSPACE_INI_INFO DblspaceInfo = { 0, // MaxRemovableDrives 0, // FirstDrive 0, // LastDrive 0, // MaxFileFragments { (WCHAR)'\0' }, // DoubleGuard { (WCHAR)'\0' }, // RomServer NULL, // CompressedDriveList { (WCHAR)'\0' }, // AutoMount[0] { (WCHAR)'\0' } // Switches[0] }; LONG CompareDrive( IN PACTIVATE_DRIVE Drive1, IN PACTIVATE_DRIVE Drive2 ) /*++ Routine Description: Compares two structures of type ACTIVATE_DRIVE. This routine is used to sort the list of compressed drives in the global variable DblspaceInfo. Drive1 < Drive2 if Drive1->HostDrive < Drive2->HostDrive or Drive1->HostDrive == Drive2->HostDrive and Drive1->SeqNumber < Drive2->SeqNumber Drive1 == Drive2 if Drive1->HostDrive == Drive2->HostDrive and Drive1->SeqNumber == Drive2->SeqNumber Drive1 > Drive2 if Drive1->HostDrive > Drive2->HostDrive or Drive1->HostDrive == Drive2->HostDrive and Drive1->SeqNumber > Drive2->SeqNumber Arguments: Drive1, Drive2 - Pointer to ACTIVATE_STRUCTUREs to be compared. Return Value: LONG - Returns: -1 if Drive1 < Drive2 0 if Drive1 == Drive2 1 if Drive1 > Drive2 --*/ { if( ( Drive1->HostDrive < Drive2->HostDrive ) || ( ( Drive1->HostDrive == Drive2->HostDrive ) && ( Drive1->SeqNumber < Drive2->SeqNumber ) ) ) { return( -1 ); } else if ( ( Drive1->HostDrive > Drive2->HostDrive ) || ( ( Drive1->HostDrive == Drive2->HostDrive ) && ( Drive1->SeqNumber > Drive2->SeqNumber ) ) ) { return( 1 ); } return( 0 ); } BOOLEAN AddCompressedDrive( IN WCHAR MountDrive, IN WCHAR HostDrive, IN USHORT SeqNumber ) /*++ Routine Description: Add an ACTIVATE_DRIVE structure to the list of compressed drives kept in DblspaceInfo. Arguments: MountDrive - Indicates the drive letter of the compressed drive. HostDrive - Indicates the drive letter of the host drive (drive that contains the file dblspace.nnn) for the compressed drive. SeqNumber - Sequence number for the CVF file associated to the compressed drive. Return Value: BOOLEAN - Returns TRUE if the information was successfully added to the list of compressed drives. --*/ { PACTIVATE_DRIVE NewElement; PACTIVATE_DRIVE Pointer; NewElement = SpMemAlloc( sizeof( ACTIVATE_DRIVE ) ); if( NewElement == NULL ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to allocate memory!\n" ) ); return( FALSE ); } NewElement->MountDrive = MountDrive; NewElement->HostDrive = HostDrive; NewElement->SeqNumber = SeqNumber; NewElement->Next = NULL; NewElement->Previous = NULL; if( ( Pointer = DblspaceInfo.CompressedDriveList ) == NULL ) { DblspaceInfo.CompressedDriveList = NewElement; } else { for( ; Pointer; Pointer = Pointer->Next ) { if( CompareDrive( NewElement, Pointer ) <= 0 ) { // // Insert element // NewElement->Previous = Pointer->Previous; if( NewElement->Previous != NULL ) { NewElement->Previous->Next = NewElement; } else { DblspaceInfo.CompressedDriveList = NewElement; } NewElement->Next = Pointer; Pointer->Previous = NewElement; break; } else { if( Pointer->Next == NULL ) { // // Insert element if element is greater than the last // element in the list // Pointer->Next = NewElement; NewElement->Previous = Pointer; break; } } } } DblspaceModified = TRUE; return( TRUE ); } BOOLEAN RemoveCompressedDrive( IN WCHAR Drive ) /*++ Routine Description: Remove a the entry from the list of compressed drives that describes a particular compressed drive. Arguments: Drive - Drive letter that describes a compressed drive. Return Value: BOOLEAN - Returns TRUE if the compressed drive was successfuly removed from the list of compressed drives. Returns FALSE if the drive was not found in the data base. --*/ { PACTIVATE_DRIVE Pointer; BOOLEAN Status; Status = FALSE; Pointer = DblspaceInfo.CompressedDriveList; for( ; Pointer; Pointer = Pointer->Next ) { if( Pointer->MountDrive == Drive ) { if( Pointer->Previous != NULL ) { Pointer->Previous->Next = Pointer->Next; } if( Pointer->Next != NULL ) { Pointer->Next->Previous = Pointer->Previous; } if( Pointer == DblspaceInfo.CompressedDriveList ) { DblspaceInfo.CompressedDriveList = Pointer->Next; } SpMemFree( Pointer ); Status = TRUE; DblspaceModified = TRUE; break; } } return( Status ); } VOID DumpDblspaceInfo() /*++ Routine Description: Dump the information stored in the global variable DblspaceInfo into the debugger. Arguments: None. Return Value: None. --*/ { PACTIVATE_DRIVE Pointer; KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "MaxRemovableDrives=%d\n", DblspaceInfo.MaxRemovableDrives )); KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "FirstDrive=%c\n", ( CHAR )DblspaceInfo.FirstDrive )); KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "LastDrive=%c\n", ( CHAR )DblspaceInfo.LastDrive )); KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "MaxFileFragments=%d\n", DblspaceInfo.MaxFileFragments )); for( Pointer = DblspaceInfo.CompressedDriveList; Pointer; Pointer = Pointer->Next ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "ActivateDrive=%c,%c%d\n", ( CHAR )Pointer->MountDrive, ( CHAR )Pointer->HostDrive, Pointer->SeqNumber )); } } VOID DumpCompressedDrives( IN PDISK_REGION HostRegion ) /*++ Routine Description: Dump the compressed drive list associated to a particular host drive, into the debugger Arguments: None. Return Value: None. --*/ { PDISK_REGION CurrentDrive; if( ( HostRegion->Filesystem == FilesystemFat ) && ( HostRegion->NextCompressed != NULL ) ) { for( CurrentDrive = HostRegion; CurrentDrive; CurrentDrive = CurrentDrive->NextCompressed ) { if( CurrentDrive->Filesystem == FilesystemFat ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "HostDrive = %wc\n", CurrentDrive->HostDrive) ); } else { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "CompressedDrive = %wc, HostDrive = %wc, CVF = %wc:DBLSPACE.%03d\n", CurrentDrive->MountDrive, CurrentDrive->HostRegion->HostDrive, CurrentDrive->HostDrive, CurrentDrive->SeqNumber ) ); } } } } VOID DumpAllCompressedDrives() /*++ Routine Description: Traverse all the structures that represent partitions and dump all compressed drives into the debugger. Arguments: None. Return Value: None. --*/ { ULONG DiskNumber; PPARTITIONED_DISK pDisk; PDISK_REGION pRegion; unsigned pass; for( DiskNumber = 0; DiskNumber < HardDiskCount; DiskNumber++ ) { pDisk = &PartitionedDisks[DiskNumber]; for(pass=0; pass<2; pass++) { pRegion = pass ? pDisk->ExtendedDiskRegions : pDisk->PrimaryDiskRegions; for( ; pRegion; pRegion=pRegion->Next) { DumpCompressedDrives( pRegion ); } } } } BOOLEAN SpLoadDblspaceIni() /*++ Routine Description: Read and parse dblspace.ini, if one is found. Arguments: None. Return Value: BOOLEAN - Returns TRUE if dblspace.ini was read successfully. Returns FALSE otherwise. --*/ { PDISK_REGION CColonRegion; WCHAR NtPath[ 512 ]; NTSTATUS Status; PVOID Handle; ULONG ErrorLine; ULONG LineNumber; PWCHAR Key; PWCHAR Value1; PWCHAR Value2; PWCHAR Value3; UINT ValueSize; ULONG CvfNumber; ULONG MaxNumber; PWCHAR AuxPointer; // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Entering SpLoadDblspaceIni\n")); // // See if there is a valid C: already. If not, then silently fail. // #ifndef _X86_ return( FALSE ); #else CColonRegion = SpPtValidSystemPartition(); if(!CColonRegion) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: no C:, no dblspace.ini!\n")); return(FALSE); } // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpPtValidSystemPartition\n")); #endif // // Check the filesystem. If not FAT, then silently fail. // if(CColonRegion->Filesystem != FilesystemFat) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: C: is not FAT, dblspace.ini!\n")); return(FALSE); } SpNtNameFromRegion( CColonRegion, NtPath, sizeof(NtPath), PartitionOrdinalCurrent ); wcscat( NtPath, DBLSPACE_INI_FILE ); // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpNtNameFromRegion\n")); Status = SpLoadSetupTextFile( NtPath, NULL, 0, &Handle, &ErrorLine, TRUE, FALSE ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read dblspace.ini!\n")); return( FALSE ); } // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpLoadSetupTextFile\n")); // // Read and interpret each line in dblspace.ini // // DblspaceInfo.ActivateDriveCount = 0; LineNumber = 0; while( ( Key = SpGetKeyName( Handle, DBLSPACE_SECTION, LineNumber ) ) != NULL ) { // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpGetKeyName\n")); if( _wcsicmp( Key, KWD_ACT ) == 0 ) { // // Found an ActivateDrive= key // // // Read mount drive letter // Value1 = SpGetSectionLineIndex( Handle, DBLSPACE_SECTION, LineNumber, 0 ); if( Value1 == NULL ) { // // Unable to read mount drive letter // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read Mount Drive letter from dblspace.ini!\n")); continue; } // // Validate Mount Drive letter // if( ( wcslen( Value1 ) != 1 ) || ( !SpIsAlpha( *Value1 ) ) ) { // // Mount Drive letter is not valid // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Mount Drive letter in dblspace.ini is not legal!\n")); continue; } // // Read host drive letter // Value2 = SpGetSectionLineIndex( Handle, DBLSPACE_SECTION, LineNumber, 1 ); if( Value2 == NULL ) { // // Unable to read host drive letter // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read Host Drive letter from dblspace.ini!\n")); continue; } // // Validate Host Drive letter // ValueSize = wcslen( Value2 ); if( ( ( ValueSize < 2 ) || ( ValueSize > 4 ) ) || ( !SpIsAlpha( *Value2 ) ) ) { // // Mount Drive letter is not valid // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Mount Drive letter in dblspace.ini is not legal!\n")); continue; } // // Validate CVF string // Value3 = Value2 + 1; ValueSize--; while( ValueSize != 0 ) { if( !SpIsDigit( *Value3 ) ) { // // CVF number is not valid // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read CVF number from dblspace.ini!\n")); continue; } ValueSize--; Value3++; } // // Validate CVF number // CvfNumber = (ULONG)SpStringToLong( Value2 + 1, &AuxPointer, 10 ); if( CvfNumber > CVF_SEQ_MAX ) { // // CVF number is out of range // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: found an invalid CVF number in dblspace.ini!\n")); continue; } // // Save the values read in DblspaceInfo // if( !AddCompressedDrive( SpToUpper( *Value1 ), SpToUpper( *Value2 ), ( USHORT )CvfNumber ) ) { // // CVF number is out of range // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to initialize DblspaceInfo: out of memory!\n")); continue; } } else if( ( _wcsicmp( Key, KWD_FIRST ) == 0 ) || ( _wcsicmp( Key, KWD_LAST ) == 0 ) ) { // // Read first drive // Value1 = SpGetSectionLineIndex( Handle, DBLSPACE_SECTION, LineNumber, 0 ); if( Value1 == NULL ) { // // Unable to read drive letter // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read FirstDrive or LastDrive from dblspace.ini!\n")); continue; } // // Validate the drive letter // if( ( wcslen( Value1 ) != 1 ) || ( !SpIsAlpha( *Value1 ) ) ) { // // Drive letter is not valid // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: FirstDrive or LastDrive in dblspace.ini is not legal!\n")); continue; } if( _wcsicmp( Key, KWD_FIRST ) == 0 ) { DblspaceInfo.FirstDrive = SpToUpper( *Value1 ); } else { DblspaceInfo.LastDrive = SpToUpper( *Value1 ); } } else if( ( _wcsicmp( Key, KWD_MAXFILE ) == 0 ) || ( _wcsicmp( Key, KWD_MAXREM ) == 0 ) ) { // // Read MaxFileFragment or MaxRemovableDrives // Value1 = SpGetSectionLineIndex( Handle, DBLSPACE_SECTION, LineNumber, 0 ); if( Value1 == NULL ) { // // Unable to read MaxFileFragments or MaxRemovableDrives // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read MaxFileFragments or MaxRemovableDrives from dblspace.ini!\n")); continue; } // // Validate MaxFileFragments or MaxRemovableDrives // Value2 = Value1; ValueSize = wcslen( Value2 ); while( ValueSize != 0 ) { ValueSize--; if( !SpIsDigit( *Value2 ) ) { // // Number is not valid // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: value of MaxFileFragments or MaxRemovableDrives in dblspace.ini is not valid!\n")); ValueSize = 0; } Value2++; } // // Validate number // MaxNumber = (ULONG)SpStringToLong( Value1, &AuxPointer, 10 ); // // Validate and initialize MaxFileFragments or MaxRemovableDrives // if( _wcsicmp( Key, KWD_MAXFILE ) == 0 ) { if( MaxNumber < MINFILEFRAGMENTS ) { MaxNumber = MINFILEFRAGMENTS; } else if( MaxNumber > MAXFILEFRAGMENTS ) { MaxNumber = MAXFILEFRAGMENTS; } DblspaceInfo.MaxFileFragments = ( USHORT )MaxNumber; } else { DblspaceInfo.MaxRemovableDrives = ( MaxNumber == 0 )? 1 : ( USHORT )MaxNumber; } } else if( ( _wcsicmp( Key, KWD_DOUBLEGUARD ) == 0 ) || ( _wcsicmp( Key, KWD_ROMSERVER ) == 0 ) || ( _wcsicmp( Key, KWD_SWITCHES ) == 0 ) || ( _wcsicmp( Key, KWD_AUTOMOUNT ) == 0 ) ) { // // Read Doubleguard, Romerver, Switches, or Automount // Value1 = SpGetSectionLineIndex( Handle, DBLSPACE_SECTION, LineNumber, 0 ); if( Value1 == NULL ) { // // Unable to read Doubleguard, Romerver, Switches, or Automount // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read Doubleguard, Romerver, Switches, or Automount from dblspace.ini!\n")); continue; } if( _wcsicmp( Key, KWD_DOUBLEGUARD ) == 0 ) { wcsncpy( DblspaceInfo.DoubleGuard, Value1, sizeof( DblspaceInfo.DoubleGuard ) / sizeof( WCHAR ) ); } else if( _wcsicmp( Key, KWD_ROMSERVER ) == 0 ) { wcsncpy( DblspaceInfo.RomServer, Value1, sizeof( DblspaceInfo.RomServer ) / sizeof( WCHAR ) ); } else if( _wcsicmp( Key, KWD_SWITCHES ) == 0 ) { wcsncpy( DblspaceInfo.Switches, Value1, sizeof( DblspaceInfo.Switches ) / sizeof( WCHAR ) ); } else { wcsncpy( DblspaceInfo.AutoMount, Value1, sizeof( DblspaceInfo.AutoMount ) / sizeof( WCHAR ) ); } } else { // // Invalid key in dblspace.ini // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: dblspace.ini contains invalid key!\n")); continue; } LineNumber++; } SpFreeTextFile( Handle ); // // Clear DblspaceModified flag, so that dblspace.ini won't get updated when // SpUpdateDoubleSpaceIni() is called, and no compressed drive was added or // deleted. // DblspaceModified = FALSE; // DumpDblspaceInfo(); // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Exiting SpLoadDblspaceIni\n")); return( TRUE ); } BOOLEAN IsHostDrive( IN WCHAR Drive, OUT PACTIVATE_DRIVE* Pointer ) /*++ Routine Description: Find out whether a particular drive is the host for a compressed drive. Arguments: Drive - Pointer - Variable that will contain the pointer for an entry in the list of compressed drives, that describes the compressed drive with the lowest sequence number, whose host drive is the drive received as parameter. Return Value: BOOLEAN - Returns TRUE if the drive passed as argument is a host drive. Returns FALSE otherwise. --*/ { PACTIVATE_DRIVE p; BOOLEAN Status; Status = FALSE; for( p = DblspaceInfo.CompressedDriveList; ( p && ( p->HostDrive != Drive ) ); p = p->Next ); if( p ) { *Pointer = p; Status = TRUE; } return( Status ); } NTSTATUS MountDoubleSpaceDrive( IN PDISK_REGION HostRegion, IN PACTIVATE_DRIVE CompressedDriveInfo ) /*++ Routine Description: Mount a double space drive. Arguments: HostRegion - Pointer to the structure that describes a FAT partition, that will be the host for the compressed drive. CompressedDriveInfo - Pointer to a structure that contains the information about the compressed drive to be mounted. Return Value: NTSTATUS - Returns an NT status code indicating whether or not the drive was mounted. --*/ { #ifdef FULL_DOUBLE_SPACE_SUPPORT NTSTATUS Status; WCHAR HostName[512]; UNICODE_STRING UnicodeDasdName; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; PIO_STATUS_BLOCK KernelModeIoStatusBlock; HANDLE Handle; PFILE_MOUNT_DBLS_BUFFER KernelModeMountFsctlBuffer; SpNtNameFromRegion( HostRegion, HostName, sizeof(HostName), PartitionOrdinalCurrent ); RtlInitUnicodeString( &UnicodeDasdName, HostName ); InitializeObjectAttributes( &ObjectAttributes, &UnicodeDasdName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ZwCreateFile( &Handle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if( !NT_SUCCESS( Status ) ) { KdPrintEx( DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, ("SETUP: NtCreateFile failed, Status = %x\n", Status ) ); return( Status ); } // // Note that since we use the NtFsControlFile API instead of the // Zw API (this one is not exported), we need a buffer for IoStatusBlock // and for MountBuffer, that can be used in kernel mode. // We use the the region of memory pointed by CommunicationParams for this // purpose. // KernelModeIoStatusBlock = ( PIO_STATUS_BLOCK )( &(CommunicationParams->Buffer[0]) ); *KernelModeIoStatusBlock = IoStatusBlock; KernelModeMountFsctlBuffer = ( PFILE_MOUNT_DBLS_BUFFER )( &(CommunicationParams->Buffer[128]) ); KernelModeMountFsctlBuffer->CvfNameLength = sizeof(WCHAR) * swprintf( KernelModeMountFsctlBuffer->CvfName, CVF_NAME_PATTERN, CompressedDriveInfo->SeqNumber ); Status = NtFsControlFile( Handle, NULL, NULL, NULL, KernelModeIoStatusBlock, FSCTL_MOUNT_DBLS_VOLUME, KernelModeMountFsctlBuffer, sizeof( FILE_MOUNT_DBLS_BUFFER ) + 12*sizeof( WCHAR ), NULL, 0 ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to mount %ls. NtFsControlFile returned Status = %x\n", KernelModeMountFsctlBuffer->CvfName, Status ) ); } ZwClose( Handle ); return( Status ); #else //FULL_DOUBLE_SPACE_SUPPORT return( STATUS_SUCCESS ); #endif } VOID MountCompressedDrives( IN PDISK_REGION HostRegion ) /*++ Routine Description: Mount all compressed drives detected on a partition. Arguments: HostRegion - Pointer to the structure that describes a FAT partition. Return Value: None. --*/ { PDISK_REGION CompressedList; PDISK_REGION CurrentDrive; PDISK_REGION TmpPointer; WCHAR HostDrive; PACTIVATE_DRIVE Pointer; CompressedList = NULL; CurrentDrive = NULL; if( ( HostRegion != NULL ) && ( HostRegion->Filesystem == FilesystemFat ) && IsHostDrive( HostRegion->DriveLetter, &Pointer ) ) { HostDrive = HostRegion->DriveLetter; for( ; ( Pointer && ( HostDrive == Pointer->HostDrive )); Pointer = Pointer->Next ) { // // Mount the drive // if( NT_SUCCESS( MountDoubleSpaceDrive( HostRegion, Pointer) ) ) { // // Drive was mounted successfully // TmpPointer = SpPtAllocateDiskRegionStructure( HostRegion->DiskNumber, HostRegion->StartSector, HostRegion->SectorCount, HostRegion->PartitionedSpace, HostRegion->MbrInfo, HostRegion->TablePosition ); ASSERT( TmpPointer ); if( TmpPointer == NULL ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to allocate memory\n" ) ); // // Unmount drive // continue; } TmpPointer->NextCompressed = NULL; TmpPointer->HostRegion = HostRegion; TmpPointer->Filesystem = FilesystemDoubleSpace; TmpPointer->SeqNumber = Pointer->SeqNumber; if( TmpPointer->SeqNumber == 0 ) { TmpPointer->MountDrive = Pointer->HostDrive; TmpPointer->HostDrive = Pointer->MountDrive; HostRegion->HostDrive = TmpPointer->HostDrive; } else { TmpPointer->MountDrive = Pointer->MountDrive; if( HostRegion->HostDrive == 0 ) { HostRegion->HostDrive = Pointer->HostDrive; } TmpPointer->HostDrive = HostRegion->HostDrive; } swprintf( TmpPointer->TypeName, CVF_NAME_PATTERN, TmpPointer->SeqNumber ); if( CompressedList == NULL ) { TmpPointer->PreviousCompressed = NULL; CompressedList = TmpPointer; } else { TmpPointer->PreviousCompressed = CurrentDrive; CurrentDrive->NextCompressed = TmpPointer; } CurrentDrive = TmpPointer; } } } HostRegion->NextCompressed = CompressedList; } VOID SpInitializeCompressedDrives() /*++ Routine Description: Traverse the structure that describes all the disks in the system, and mount all compressed drives previously identified. Arguments: None. Return Value: None. --*/ { ULONG DiskNumber; PPARTITIONED_DISK pDisk; PDISK_REGION pRegion; unsigned pass; for( DiskNumber = 0; DiskNumber < HardDiskCount; DiskNumber++ ) { pDisk = &PartitionedDisks[DiskNumber]; for(pass=0; pass<2; pass++) { pRegion = pass ? pDisk->ExtendedDiskRegions : pDisk->PrimaryDiskRegions; for( ; pRegion; pRegion=pRegion->Next) { MountCompressedDrives( pRegion ); } } } // DumpAllCompressedDrives(); } VOID SpDisposeCompressedDrives( PDISK_REGION CompressedDrive ) /*++ Routine Description: Delete the list of compressed drives found in a structure associated with a partition in the disk. This function is called when the user deletes a host partition that contains compressed drives. The list of compressed drives kept in the global variable DblspaceInfo is updated so that it reflects the changes made by the user. Arguments: CompressedDrive - Pointer to the first element of a compressed drive list. Return Value: None. --*/ { ASSERT( CompressedDrive->Filesystem == FilesystemDoubleSpace ); if( CompressedDrive->NextCompressed != NULL ) { SpDisposeCompressedDrives( CompressedDrive->NextCompressed ); } if( CompressedDrive->SeqNumber != 0 ) { RemoveCompressedDrive( CompressedDrive->MountDrive ); } else { RemoveCompressedDrive( CompressedDrive->HostDrive ); } SpMemFree( CompressedDrive ); } BOOLEAN SpUpdateDoubleSpaceIni() /*++ Routine Description: Update dblspace.ini to reflect all changes made by the user, with respect to compressed drives deleted or created. Arguments: None. Return Value: BOOLEAN - Returns TRUE if dblspace.ini was successfully updated. Returns FALSE otherwise. --*/ { PDISK_REGION CColonRegion; WCHAR NtPath[ 512 ]; UNICODE_STRING FileName; NTSTATUS Status; HANDLE Handle; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; CHAR Buffer[ 512 ]; PACTIVATE_DRIVE Pointer; // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Entering SpUpdateDblspaceIni\n")); // // If no compressed drive was created or deleted, then do not // touch dblspace.ini // if( !DblspaceModified ) { return( TRUE ); } // // See if there is a valid C: already. If not, then silently fail. // #ifndef _X86_ return( FALSE ); #else CColonRegion = SpPtValidSystemPartition(); if(!CColonRegion) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: no C:, no dblspace.ini!\n")); return(FALSE); } // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpPtValidSystemPartition\n")); #endif // // Check the filesystem. If not FAT, then silently fail. // if(CColonRegion->Filesystem != FilesystemFat) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: C: is not FAT, no dblspace.ini!\n")); return(FALSE); } SpNtNameFromRegion( CColonRegion, NtPath, sizeof(NtPath), PartitionOrdinalCurrent ); wcscat( NtPath, DBLSPACE_INI_FILE ); Status = SpDeleteFile( NtPath, NULL, NULL ); if( !NT_SUCCESS( Status ) && ( Status != STATUS_OBJECT_NAME_NOT_FOUND ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Unable to delete dblspace.ini, Status = %x\n",Status ) ); return( FALSE ); } // // If the user deleted all compressed drives, then don't create a new // dblspace.ini // // if( DblspaceInfo.CompressedDriveList == NULL ) { // return( TRUE ); // } // // Create and write a new dblspace.ini // RtlInitUnicodeString( &FileName, NtPath ); InitializeObjectAttributes( &ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ZwCreateFile( &Handle, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to create dblspace.ini, Status = %x\n", Status ) ); return( FALSE ); } sprintf( Buffer, "%ls=%d\r\n", KWD_MAXREM, DblspaceInfo.MaxRemovableDrives ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write MaxRemovableDrives to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } if( DblspaceInfo.FirstDrive != ( WCHAR )'\0' ) { sprintf( Buffer, "%ls=%c\r\n", KWD_FIRST, DblspaceInfo.FirstDrive ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write FirstDrive to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } } if( DblspaceInfo.LastDrive != ( WCHAR )'\0' ) { sprintf( Buffer, "%ls=%c\r\n", KWD_LAST, DblspaceInfo.LastDrive ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write LastDrive to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } } sprintf( Buffer, "%ls=%d\r\n", KWD_MAXFILE, DblspaceInfo.MaxFileFragments ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write LastDrive to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } if( wcslen( DblspaceInfo.DoubleGuard ) != 0 ) { sprintf( Buffer, "%ls=%ls\r\n", KWD_AUTOMOUNT, DblspaceInfo.AutoMount ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Automount to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } } if( wcslen( DblspaceInfo.RomServer ) != 0 ) { sprintf( Buffer, "%ls=%ls\r\n", KWD_ROMSERVER, DblspaceInfo.RomServer ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Romserver to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } } if( wcslen( DblspaceInfo.Switches ) != 0 ) { sprintf( Buffer, "%ls=%ls\r\n", KWD_SWITCHES, DblspaceInfo.Switches ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Switches to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } } if( wcslen( DblspaceInfo.DoubleGuard ) != 0 ) { sprintf( Buffer, "%ls=%ls\r\n", KWD_DOUBLEGUARD, DblspaceInfo.DoubleGuard ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Doubleguard to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } } for( Pointer = DblspaceInfo.CompressedDriveList; Pointer; Pointer = Pointer->Next ) { sprintf( Buffer, "%ls=%c,%c%d\r\n", KWD_ACT, Pointer->MountDrive, Pointer->HostDrive, Pointer->SeqNumber ); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, Buffer, strlen( Buffer ), NULL, NULL ); if( !NT_SUCCESS( Status ) ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write to dblspace.ini, Status = %x\n", Status )); ZwClose( Handle ); return( FALSE ); } } ZwClose( Handle ); // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Exiting SpUpdateDblspaceIni\n")); return( TRUE ); } ULONG SpGetNumberOfCompressedDrives( IN PDISK_REGION Partition ) /*++ Routine Description: Determine the number of compressed volumes on a particular partition. Arguments: Partition - Pointer to the structure that describes a partition. Return Value: ULONG - Returns the number of compressed drives found on the partition. --*/ { ULONG Count; PDISK_REGION Pointer; Count = 0; if( ( Partition != NULL ) && ( Partition->Filesystem == FilesystemFat ) ) { for( Pointer = Partition->NextCompressed; Pointer; Pointer = Pointer->NextCompressed ) { Count++; } } return( Count ); }