1 /************************************************************************* 2 * 3 * File: volinfo.c 4 * 5 * Module: Ext2 File System Driver (Kernel mode execution only) 6 * 7 * Description: 8 * Contains code to handle the various Volume Information related calls. 9 * 10 * Author: Manoj Paul Joseph 11 * 12 * 13 *************************************************************************/ 14 15 16 17 #include "ext2fsd.h" 18 19 20 21 22 // define the file specific bug-check id 23 #define EXT2_BUG_CHECK_ID EXT2_FILE_VOL_INFORMATION 24 #define DEBUG_LEVEL (DEBUG_TRACE_VOLINFO) 25 26 27 /************************************************************************* 28 * 29 * Function: Ext2QueryVolInfo() 30 * 31 * Description: 32 * The I/O Manager will invoke this routine to handle a 33 * Query Volume Info IRP 34 * 35 * Expected Interrupt Level (for execution) : 36 * 37 * ??? 38 * 39 * Arguments: 40 * 41 * DeviceObject - Supplies the volume device object where the 42 * file exists 43 * 44 * Irp - Supplies the Irp being processed 45 * 46 * 47 * Return Value: 48 * 49 * NTSTATUS - The FSD status for the IRP 50 * 51 *************************************************************************/ 52 NTSTATUS NTAPI Ext2QueryVolInfo ( 53 IN PDEVICE_OBJECT DeviceObject, 54 IN PIRP Irp) 55 { 56 57 // The Return Status 58 NTSTATUS Status = STATUS_SUCCESS; 59 60 // The IRP Stack Location 61 PIO_STACK_LOCATION IrpSp = NULL; 62 63 // Volume Control Block 64 PtrExt2VCB PtrVCB = NULL; 65 66 // The class of the query IRP 67 FS_INFORMATION_CLASS FsInformationClass; 68 69 // The System Buffer Pointer 70 PVOID Buffer = NULL; 71 72 // Parameter Length 73 ULONG Length = 0; 74 75 // Bytes copied... 76 ULONG BytesCopied = 0; 77 78 // Pointers to the Output Information... 79 PFILE_FS_VOLUME_INFORMATION PtrVolumeInformation = NULL; 80 PFILE_FS_SIZE_INFORMATION PtrSizeInformation = NULL; 81 PFILE_FS_ATTRIBUTE_INFORMATION PtrAttributeInformation = NULL; 82 PFILE_FS_DEVICE_INFORMATION PtrDeviceInformation = NULL; 83 PFILE_FS_FULL_SIZE_INFORMATION PtrFullSizeInformation = NULL; 84 85 86 // Now for the handler code... 87 DebugTrace(DEBUG_TRACE_IRP_ENTRY, "QueryVolumeInformation IRP", 0); 88 89 FsRtlEnterFileSystem(); 90 91 try 92 { 93 // Getting a pointer to the current I/O stack location 94 IrpSp = IoGetCurrentIrpStackLocation(Irp); 95 ASSERT( IrpSp ); 96 97 // Getting the VCB and Verifying it... 98 PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension ); 99 ASSERT(PtrVCB); 100 ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB); 101 102 // Getting the query parameters... 103 Length = IrpSp->Parameters.QueryVolume.Length; 104 FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass; 105 Buffer = Irp->AssociatedIrp.SystemBuffer; 106 107 // Now servicing the request depending on the type... 108 switch (FsInformationClass) 109 { 110 case FileFsVolumeInformation: 111 DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsVolumeInformation", 0); 112 PtrVolumeInformation = Buffer; 113 PtrVolumeInformation->SupportsObjects = FALSE; 114 PtrVolumeInformation->VolumeCreationTime.QuadPart = 0; 115 RtlCopyMemory( 116 PtrVolumeInformation->VolumeLabel, // destination 117 PtrVCB->PtrVPB->VolumeLabel, // source 118 PtrVCB->PtrVPB->VolumeLabelLength ); 119 PtrVolumeInformation->VolumeLabelLength = PtrVCB->PtrVPB->VolumeLabelLength; 120 PtrVolumeInformation->VolumeSerialNumber = PtrVCB->PtrVPB->SerialNumber; 121 BytesCopied = sizeof( FILE_FS_VOLUME_INFORMATION ) + PtrVolumeInformation->VolumeLabelLength - sizeof( WCHAR); 122 break; 123 124 case FileFsSizeInformation: 125 DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsSizeInformation", 0); 126 PtrSizeInformation = Buffer; 127 PtrSizeInformation->BytesPerSector = DeviceObject->SectorSize; 128 PtrSizeInformation->AvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount; 129 PtrSizeInformation->SectorsPerAllocationUnit = ( EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize; 130 PtrSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount; 131 BytesCopied = sizeof( FILE_FS_SIZE_INFORMATION ); 132 break; 133 134 case FileFsDeviceInformation: 135 DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsDeviceInformation", 0); 136 PtrDeviceInformation = Buffer; 137 PtrDeviceInformation->DeviceType = FILE_DEVICE_DISK; 138 PtrDeviceInformation->Characteristics = FILE_DEVICE_IS_MOUNTED; 139 BytesCopied = sizeof( FILE_FS_DEVICE_INFORMATION ); 140 break; 141 142 case FileFsAttributeInformation: 143 DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsAttributeInformation", 0); 144 PtrAttributeInformation = Buffer; 145 RtlCopyMemory( PtrAttributeInformation->FileSystemName, L"EXT2", 10 ); 146 PtrAttributeInformation->FileSystemNameLength = 8; 147 PtrAttributeInformation->MaximumComponentNameLength = 255; 148 PtrAttributeInformation->FileSystemAttributes = 149 FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; 150 BytesCopied = sizeof( FILE_FS_ATTRIBUTE_INFORMATION ) + 8; 151 152 break; 153 154 case FileFsFullSizeInformation: 155 DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsFullSizeInformation", 0); 156 PtrFullSizeInformation = Buffer; 157 PtrFullSizeInformation->BytesPerSector = DeviceObject->SectorSize; 158 PtrFullSizeInformation->ActualAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount; 159 PtrFullSizeInformation->SectorsPerAllocationUnit = (EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize; 160 PtrFullSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount; 161 PtrFullSizeInformation->CallerAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount - PtrVCB->ReservedBlocksCount; 162 BytesCopied = sizeof( FILE_FS_FULL_SIZE_INFORMATION ); 163 break; 164 165 default: 166 Status = STATUS_INVALID_PARAMETER; 167 DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0); 168 break; 169 } 170 171 if( IrpSp->Parameters.QueryVolume.Length < BytesCopied ) 172 { 173 BytesCopied = IrpSp->Parameters.QueryVolume.Length; 174 Status = STATUS_BUFFER_OVERFLOW; 175 DebugTrace(DEBUG_TRACE_MISC, " === Buffer insufficient", 0); 176 } 177 } 178 finally 179 { 180 Irp->IoStatus.Information = BytesCopied; 181 Ext2CompleteRequest( Irp, Status ); 182 } 183 FsRtlExitFileSystem(); 184 185 // 186 // Now return to the caller 187 // 188 189 return Status; 190 } 191 192 193 194 NTSTATUS NTAPI Ext2SetVolInfo( 195 IN PDEVICE_OBJECT DeviceObject, 196 IN PIRP Irp) 197 { 198 // The Return Status 199 NTSTATUS Status = STATUS_SUCCESS; 200 201 // The IRP Stack Location 202 PIO_STACK_LOCATION IrpSp = NULL; 203 204 // Volume Control Block 205 PtrExt2VCB PtrVCB = NULL; 206 207 // The class of the query IRP 208 FS_INFORMATION_CLASS FsInformationClass; 209 210 // Pointers to the Output Information... 211 PFILE_FS_LABEL_INFORMATION PtrVolumeLabelInformation = NULL; 212 213 // Now for the handler code... 214 DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Set Volume Information IRP", 0); 215 216 FsRtlEnterFileSystem(); 217 218 try 219 { 220 // Getting a pointer to the current I/O stack location 221 IrpSp = IoGetCurrentIrpStackLocation(Irp); 222 ASSERT( IrpSp ); 223 224 // Getting the VCB and Verifying it... 225 PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension ); 226 AssertVCB(PtrVCB); 227 228 // Getting the query parameters... 229 // Length = IrpSp->Parameters.SetVolume.Length; 230 #ifdef _GNU_NTIFS_ 231 FsInformationClass = ((PEXTENDED_IO_STACK_LOCATION)IrpSp)->Parameters.SetVolume.FsInformationClass; 232 #else 233 FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass; 234 #endif 235 236 // Now servicing the request depending on the type... 237 switch (FsInformationClass) 238 { 239 case FileFsLabelInformation: 240 PtrVolumeLabelInformation = Irp->AssociatedIrp.SystemBuffer; 241 if( PtrVolumeLabelInformation->VolumeLabelLength > MAXIMUM_VOLUME_LABEL_LENGTH || // This is the maximum that the 242 // VPB can take... 243 PtrVolumeLabelInformation->VolumeLabelLength > 32 ) // this is the maximum that Ext2 FS can support.. 244 { 245 try_return( Status = STATUS_INVALID_VOLUME_LABEL ); 246 } 247 248 PtrVCB->PtrVPB->VolumeLabelLength = (USHORT)PtrVolumeLabelInformation->VolumeLabelLength ; 249 RtlCopyMemory( 250 PtrVCB->PtrVPB->VolumeLabel, // destination 251 PtrVolumeLabelInformation->VolumeLabel, // source 252 PtrVolumeLabelInformation->VolumeLabelLength ); 253 254 { 255 // Now update the volume's super block... 256 257 PEXT2_SUPER_BLOCK PtrSuperBlock = NULL; 258 PBCB PtrSuperBlockBCB = NULL; 259 LARGE_INTEGER VolumeByteOffset; 260 ULONG LogicalBlockSize = 0; 261 ULONG NumberOfBytesToRead = 0; 262 263 264 // Reading in the super block... 265 VolumeByteOffset.QuadPart = 1024; 266 267 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 268 269 // THis shouldn't be more than a block in size... 270 NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize ); 271 272 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 273 &VolumeByteOffset, 274 NumberOfBytesToRead, 275 TRUE, 276 &PtrSuperBlockBCB, 277 (PVOID*)&PtrSuperBlock ) ) 278 { 279 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 280 try_return( Status = STATUS_INVALID_VOLUME_LABEL ); 281 } 282 else 283 { 284 ULONG i; 285 for( i = 0; i < (PtrVolumeLabelInformation->VolumeLabelLength/2) ; i++ ) 286 { 287 PtrSuperBlock->s_volume_name[i] = 288 (char) PtrVolumeLabelInformation->VolumeLabel[i] ; 289 if( PtrSuperBlock->s_volume_name[i] == 0 ) 290 { 291 break; 292 } 293 } 294 if( i < 16 ) 295 { 296 PtrSuperBlock->s_volume_name[i] = 0; 297 } 298 299 300 CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL ); 301 302 // Not saving and flushing this information synchronously... 303 // This is not a critical information.. 304 // Settling for lazy writing of this information 305 306 // Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject ); 307 308 if( PtrSuperBlockBCB ) 309 { 310 CcUnpinData( PtrSuperBlockBCB ); 311 PtrSuperBlockBCB = NULL; 312 } 313 314 } 315 } 316 317 break; 318 default: 319 Status = STATUS_INVALID_PARAMETER; 320 DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0); 321 break; 322 } 323 324 try_exit: NOTHING; 325 } 326 finally 327 { 328 Irp->IoStatus.Information = 0; 329 Ext2CompleteRequest( Irp, Status ); 330 } 331 FsRtlExitFileSystem(); 332 333 // 334 // Now return to the caller 335 // 336 337 return Status; 338 } 339