Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

udfs_rec.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1992 Microsoft Corporation 00004 00005 Module Name: 00006 00007 udfs_rec.c 00008 00009 Abstract: 00010 00011 This module contains the mini-file system recognizer for UDFS. 00012 00013 Author: 00014 00015 Dan Lovinger (danlo) 13-Feb-1997 00016 00017 Environment: 00018 00019 Kernel mode, local to I/O system 00020 00021 Revision History: 00022 00023 00024 --*/ 00025 00026 #include "fs_rec.h" 00027 #include "udfs_rec.h" 00028 00029 // 00030 // The local debug trace level 00031 // 00032 00033 #define Dbg (FSREC_DEBUG_LEVEL_UDFS) 00034 00035 // 00036 // Tables of tokens we have to parse up from mount-time on-disk structures 00037 // 00038 00039 PARSE_KEYVALUE VsdIdentParseTable[] = { 00040 { VSD_IDENT_BEA01, VsdIdentBEA01 }, 00041 { VSD_IDENT_TEA01, VsdIdentTEA01 }, 00042 { VSD_IDENT_CDROM, VsdIdentCDROM }, 00043 { VSD_IDENT_CD001, VsdIdentCD001 }, 00044 { VSD_IDENT_CDW01, VsdIdentCDW01 }, 00045 { VSD_IDENT_CDW02, VsdIdentCDW02 }, 00046 { VSD_IDENT_NSR01, VsdIdentNSR01 }, 00047 { VSD_IDENT_NSR02, VsdIdentNSR02 }, 00048 { VSD_IDENT_BOOT2, VsdIdentBOOT2 }, 00049 { NULL, VsdIdentBad } 00050 }; 00051 00052 #ifdef ALLOC_PRAGMA 00053 #pragma alloc_text(PAGE,IsUdfsVolume) 00054 #pragma alloc_text(PAGE,UdfsFindInParseTable) 00055 #pragma alloc_text(PAGE,UdfsRecFsControl) 00056 #endif // ALLOC_PRAGMA 00057 00058 00059 NTSTATUS 00060 UdfsRecFsControl( 00061 IN PDEVICE_OBJECT DeviceObject, 00062 IN PIRP Irp 00063 ) 00064 00065 /*++ 00066 00067 Routine Description: 00068 00069 This function performs the mount and driver reload functions for this mini- 00070 file system recognizer driver. 00071 00072 Arguments: 00073 00074 DeviceObject - Pointer to this driver's device object. 00075 00076 Irp - Pointer to the I/O Request Packet (IRP) representing the function to 00077 be performed. 00078 00079 Return Value: 00080 00081 The function value is the final status of the operation. 00082 00083 00084 -*/ 00085 00086 { 00087 NTSTATUS status; 00088 PIO_STACK_LOCATION irpSp; 00089 PDEVICE_EXTENSION deviceExtension; 00090 UNICODE_STRING driverName; 00091 ULONG bytesPerSector; 00092 PDEVICE_OBJECT targetDevice; 00093 00094 PAGED_CODE(); 00095 00096 // 00097 // Begin by determining what function that is to be performed. 00098 // 00099 00100 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 00101 irpSp = IoGetCurrentIrpStackLocation( Irp ); 00102 00103 switch ( irpSp->MinorFunction ) { 00104 00105 case IRP_MN_MOUNT_VOLUME: 00106 00107 // 00108 // Attempt to mount a volume: There are two different cases here: 00109 // 00110 // 1) The device is being opened for DASD access, that is, no 00111 // file system is required, thus it is OK to allow RAW to 00112 // to open it. 00113 // 00114 // 2) We need to rummage the media to see if this is a UDF volume. 00115 // 00116 00117 status = STATUS_UNRECOGNIZED_VOLUME; 00118 00119 targetDevice = irpSp->Parameters.MountVolume.DeviceObject; 00120 00121 if (FsRecGetDeviceSectorSize( targetDevice, 00122 &bytesPerSector )) { 00123 00124 if (IsUdfsVolume( targetDevice, 00125 bytesPerSector )) { 00126 00127 status = STATUS_FS_DRIVER_REQUIRED; 00128 } 00129 } 00130 00131 break; 00132 00133 case IRP_MN_LOAD_FILE_SYSTEM: 00134 00135 status = FsRecLoadFileSystem( DeviceObject, 00136 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Udfs" ); 00137 break; 00138 00139 default: 00140 status = STATUS_INVALID_DEVICE_REQUEST; 00141 00142 } 00143 00144 // 00145 // Finally, complete the request and return the same status code to the 00146 // caller. 00147 // 00148 00149 Irp->IoStatus.Status = status; 00150 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 00151 00152 return status; 00153 } 00154 00155 00156 BOOLEAN 00157 IsUdfsVolume ( 00158 IN PDEVICE_OBJECT DeviceObject, 00159 IN ULONG SectorSize 00160 ) 00161 00162 /*++ 00163 00164 Routine Description: 00165 00166 This routine walks the Volume Recognition Sequence to determine 00167 whether this volume contains an NSR02 (ISO 13346 Section 4) image. 00168 00169 Note: this routine is pretty much diked out of UdfsRecognizeVolume 00170 in the real filesystem, modulo fitting it into the fs recognizer. 00171 00172 Arguments: 00173 00174 DeviceObject - device we are checking 00175 00176 SectorSize - size of a physical sector on this device 00177 00178 Return Value: 00179 00180 Boolean TRUE if we found NSR02, FALSE otherwise. 00181 00182 --*/ 00183 00184 { 00185 BOOLEAN FoundNSR = FALSE; 00186 00187 BOOLEAN FoundBEA = FALSE; 00188 BOOLEAN Resolved = FALSE; 00189 00190 PVSD_GENERIC VolumeStructureDescriptor = NULL; 00191 ULONGLONG Offset = SectorAlignN( SectorSize, VRA_BOUNDARY_LOCATION ); 00192 00193 PAGED_CODE(); 00194 00195 DebugTrace(( +1, Dbg, 00196 "IsUdfsVolume, DevObj %08x SectorSize %08x\n", 00197 DeviceObject, 00198 SectorSize )); 00199 00200 while (!Resolved) { 00201 00202 if (!FsRecReadBlock( DeviceObject, 00203 (PLARGE_INTEGER)&Offset, 00204 sizeof(VSD_GENERIC), 00205 SectorSize, 00206 (PVOID) &VolumeStructureDescriptor, 00207 NULL )) { 00208 00209 break; 00210 } 00211 00212 // 00213 // Now check the type of the descriptor. All ISO 13346 VSDs are 00214 // of Type 0, 9660 PVDs are Type 1, 9660 SVDs are Type 2, and 9660 00215 // terminating descriptors are Type 255. 00216 // 00217 00218 if (VolumeStructureDescriptor->Type == 0) { 00219 00220 // 00221 // In order to properly recognize the volume, we must know all of the 00222 // Structure identifiers in ISO 13346 so that we can terminate if a 00223 // badly formatted (or, shockingly, non 13346) volume is presented to us. 00224 // 00225 00226 switch (UdfsFindInParseTable( VsdIdentParseTable, 00227 VolumeStructureDescriptor->Ident, 00228 VSD_LENGTH_IDENT )) { 00229 case VsdIdentBEA01: 00230 00231 // 00232 // Only one BEA may exist and its version must be 1 (2/9.2.3) 00233 // 00234 00235 DebugTrace(( 0, Dbg, "IsUdfsVolume, got a BEA01\n" )); 00236 00237 00238 if ((FoundBEA && 00239 DebugTrace(( 0, Dbg, 00240 "IsUdfsVolume, ... but it is a duplicate!\n" ))) || 00241 00242 (VolumeStructureDescriptor->Version != 1 && 00243 DebugTrace(( 0, Dbg, 00244 "IsUdfsVolume, ... but it has a wacky version number %02x != 1!\n", 00245 VolumeStructureDescriptor->Version )))) { 00246 00247 Resolved = TRUE; 00248 break; 00249 } 00250 00251 FoundBEA = TRUE; 00252 break; 00253 00254 case VsdIdentTEA01: 00255 00256 // 00257 // If we reach the TEA it must be the case that we don't recognize 00258 // 00259 00260 DebugTrace(( 0, Dbg, "IsUdfsVolume, got a TEA01\n" )); 00261 00262 Resolved = TRUE; 00263 break; 00264 00265 case VsdIdentNSR02: 00266 00267 // 00268 // We recognize NSR02 version 1 embedded after a BEA (3/9.1.3). For 00269 // simplicity we will not bother being a complete nitpick and check 00270 // for a bounding TEA, although we will be optimistic in the case where 00271 // we fail to match the version. 00272 // 00273 00274 DebugTrace(( 0, Dbg, "IsUdfsVolume, got an NSR02\n" )); 00275 00276 if ((FoundBEA || 00277 !DebugTrace(( 0, Dbg, "IsUdfsVolume, ... but we haven't seen a BEA01 yet!\n" ))) && 00278 00279 (VolumeStructureDescriptor->Version == 1 || 00280 !DebugTrace(( 0, Dbg, "IsUdfsVolume, ... but it has a wacky version number %02x != 1\n", 00281 VolumeStructureDescriptor->Version )))) { 00282 00283 FoundNSR = Resolved = TRUE; 00284 break; 00285 } 00286 00287 break; 00288 00289 case VsdIdentCD001: 00290 case VsdIdentCDW01: 00291 case VsdIdentNSR01: 00292 case VsdIdentCDW02: 00293 case VsdIdentBOOT2: 00294 00295 DebugTrace(( 0, Dbg, "IsUdfsVolume, got a valid but uninteresting 13346 descriptor\n" )); 00296 00297 // 00298 // Valid but uninteresting (to us) descriptors 00299 // 00300 00301 break; 00302 00303 default: 00304 00305 DebugTrace(( 0, Dbg, "IsUdfsVolume, got an invalid 13346 descriptor\n" )); 00306 00307 // 00308 // Stumbling across something we don't know, it must be that this 00309 // is not a valid 13346 image 00310 // 00311 00312 Resolved = TRUE; 00313 break; 00314 00315 } 00316 00317 } else if (!FoundBEA && (VolumeStructureDescriptor->Type < 3 || 00318 VolumeStructureDescriptor->Type == 255)) { 00319 00320 DebugTrace(( 0, Dbg, "IsUdfsVolume, got a 9660 descriptor\n" )); 00321 00322 // 00323 // Only HSG (CDROM) and 9660 (CD001) are possible, and they are only legal 00324 // before the ISO 13346 BEA/TEA extent. By design, an ISO 13346 VSD precisely 00325 // overlaps a 9660 PVD/SVD in the appropriate fields. 00326 // 00327 // Note that we aren't being strict about the structure of the 9660 descriptors 00328 // since that really isn't very interesting. We care more about the 13346. 00329 // 00330 // 00331 00332 switch (UdfsFindInParseTable( VsdIdentParseTable, 00333 VolumeStructureDescriptor->Ident, 00334 VSD_LENGTH_IDENT )) { 00335 case VsdIdentCDROM: 00336 case VsdIdentCD001: 00337 00338 DebugTrace(( 0, Dbg, "IsUdfsVolume, ... seems we have 9660 here\n" )); 00339 00340 // 00341 // Note to our caller that we seem to have ISO 9660 here 00342 // 00343 00344 break; 00345 00346 default: 00347 00348 DebugTrace(( 0, Dbg, "IsUdfsVolume, ... but it looks wacky\n" )); 00349 00350 // 00351 // This probably was a false alert, but in any case there is nothing 00352 // on this volume for us. 00353 // 00354 00355 Resolved = TRUE; 00356 break; 00357 } 00358 00359 } else { 00360 00361 // 00362 // Something else must be recorded on this volume. 00363 // 00364 00365 DebugTrace(( 0, Dbg, "IsUdfsVolume, got an unrecognizeable descriptor, probably not 13346/9660\n" )); 00366 break; 00367 } 00368 00369 // 00370 // Align our next read with the sector following the current descriptor 00371 // 00372 00373 Offset += SectorAlignN( SectorSize, sizeof(VSD_GENERIC) ); 00374 } 00375 00376 DebugTrace(( -1, Dbg, "IsUdfsVolume -> %c\n", ( FoundNSR ? 'T' : 'F' ))); 00377 00378 // 00379 // Free up our temporary buffer 00380 // 00381 00382 if (VolumeStructureDescriptor) { 00383 00384 ExFreePool( VolumeStructureDescriptor ); 00385 } 00386 00387 return FoundNSR; 00388 } 00389 00390 00391 ULONG 00392 UdfsFindInParseTable ( 00393 IN PPARSE_KEYVALUE ParseTable, 00394 IN PCHAR Id, 00395 IN ULONG MaxIdLen 00396 ) 00397 00398 /*++ 00399 00400 Routine Description: 00401 00402 This routine walks a table of string key/value information for a match of the 00403 input Id. MaxIdLen can be set to get a prefix match. 00404 00405 Arguments: 00406 00407 Table - This is the table being searched. 00408 00409 Id - Key value. 00410 00411 MaxIdLen - Maximum possible length of Id. 00412 00413 Return Value: 00414 00415 Value of matching entry, or the terminating (NULL) entry's value. 00416 00417 --*/ 00418 00419 { 00420 PAGED_CODE(); 00421 00422 while (ParseTable->Key != NULL) { 00423 00424 if (RtlEqualMemory(ParseTable->Key, Id, MaxIdLen)) { 00425 00426 break; 00427 } 00428 00429 ParseTable++; 00430 } 00431 00432 return ParseTable->Value; 00433 } 00434

Generated on Sat May 15 19:42:10 2004 for test by doxygen 1.3.7