Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1183 lines
30 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fs_rec.c
  5. Abstract:
  6. This module contains the main functions for the mini-file system recognizer
  7. driver.
  8. Author:
  9. Darryl E. Havens (darrylh) 22-nov-1993
  10. Environment:
  11. Kernel mode, local to I/O system
  12. Revision History:
  13. --*/
  14. #include "fs_rec.h"
  15. //
  16. // The local debug trace level
  17. //
  18. #define Dbg (FSREC_DEBUG_LEVEL_FSREC)
  19. #if DBG
  20. #include <stdarg.h>
  21. #include <stdio.h>
  22. LONG FsRecDebugTraceLevel = 0;
  23. LONG FsRecDebugTraceIndent = 0;
  24. #endif
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text(INIT,DriverEntry)
  27. #pragma alloc_text(INIT,FsRecCreateAndRegisterDO)
  28. #pragma alloc_text(PAGE,FsRecCleanupClose)
  29. #pragma alloc_text(PAGE,FsRecCreate)
  30. #pragma alloc_text(PAGE,FsRecFsControl)
  31. #pragma alloc_text(PAGE,FsRecGetDeviceSectorSize)
  32. #pragma alloc_text(PAGE,FsRecGetDeviceSectors)
  33. #pragma alloc_text(PAGE,FsRecLoadFileSystem)
  34. #pragma alloc_text(PAGE,FsRecReadBlock)
  35. #pragma alloc_text(PAGE,FsRecUnload)
  36. #pragma alloc_text(PAGE,FsRecShutdown)
  37. #endif // ALLOC_PRAGMA
  38. //
  39. // Mutex for serializing driver loads.
  40. //
  41. PKEVENT FsRecLoadSync;
  42. NTSTATUS
  43. DriverEntry (
  44. IN PDRIVER_OBJECT DriverObject,
  45. IN PUNICODE_STRING RegistryPath
  46. )
  47. /*++
  48. Routine Description:
  49. This routine is invoked once when the driver is loaded to allow the driver
  50. to initialize itself. The initialization for the driver consists of simply
  51. creating a device object for each type of file system recognized by this
  52. driver, and then registering each as active file systems.
  53. Arguments:
  54. DriverObject - Pointer to the driver object for this driver.
  55. RegistryPath - Pointer to the registry service node for this driver.
  56. Return Value:
  57. The function value is the final status of the initialization for the driver.
  58. --*/
  59. {
  60. PDEVICE_OBJECT UdfsMainRecognizerDeviceObject;
  61. PDEVICE_OBJECT FatMainRecognizerDeviceObject;
  62. NTSTATUS status;
  63. ULONG count = 0;
  64. PAGED_CODE();
  65. //
  66. // Mark the entire driver as pagable.
  67. //
  68. MmPageEntireDriver ((PVOID)DriverEntry);
  69. //
  70. // Begin by initializing the driver object so that it the driver is
  71. // prepared to provide services.
  72. //
  73. DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
  74. DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate;
  75. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecCleanupClose;
  76. DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecCleanupClose;
  77. DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FsRecShutdown;
  78. DriverObject->DriverUnload = FsRecUnload;
  79. FsRecLoadSync = ExAllocatePoolWithTag( NonPagedPool, sizeof(KEVENT), FSREC_POOL_TAG );
  80. if (FsRecLoadSync == NULL) {
  81. return STATUS_INSUFFICIENT_RESOURCES;
  82. }
  83. KeInitializeEvent( FsRecLoadSync, SynchronizationEvent, TRUE );
  84. //
  85. // Create and initialize each of the file system driver type device
  86. // objects.
  87. //
  88. status = FsRecCreateAndRegisterDO( DriverObject,
  89. NULL,
  90. NULL,
  91. L"\\Cdfs",
  92. L"\\FileSystem\\CdfsRecognizer",
  93. CdfsFileSystem,
  94. FILE_DEVICE_CD_ROM_FILE_SYSTEM );
  95. if (NT_SUCCESS( status )) {
  96. count++;
  97. }
  98. status = FsRecCreateAndRegisterDO( DriverObject,
  99. NULL,
  100. &UdfsMainRecognizerDeviceObject,
  101. L"\\UdfsCdRom",
  102. L"\\FileSystem\\UdfsCdRomRecognizer",
  103. UdfsFileSystem,
  104. FILE_DEVICE_CD_ROM_FILE_SYSTEM );
  105. if (NT_SUCCESS( status )) {
  106. count++;
  107. }
  108. status = FsRecCreateAndRegisterDO( DriverObject,
  109. UdfsMainRecognizerDeviceObject,
  110. NULL,
  111. L"\\UdfsDisk",
  112. L"\\FileSystem\\UdfsDiskRecognizer",
  113. UdfsFileSystem,
  114. FILE_DEVICE_DISK_FILE_SYSTEM );
  115. if (NT_SUCCESS( status )) {
  116. count++;
  117. }
  118. status = FsRecCreateAndRegisterDO( DriverObject,
  119. NULL,
  120. &FatMainRecognizerDeviceObject,
  121. L"\\FatDisk",
  122. L"\\FileSystem\\FatDiskRecognizer",
  123. FatFileSystem,
  124. FILE_DEVICE_DISK_FILE_SYSTEM );
  125. if (NT_SUCCESS( status )) {
  126. count++;
  127. }
  128. status = FsRecCreateAndRegisterDO( DriverObject,
  129. FatMainRecognizerDeviceObject,
  130. NULL,
  131. L"\\FatCdrom",
  132. L"\\FileSystem\\FatCdRomRecognizer",
  133. FatFileSystem,
  134. FILE_DEVICE_CD_ROM_FILE_SYSTEM );
  135. if (NT_SUCCESS( status )) {
  136. count++;
  137. }
  138. status = FsRecCreateAndRegisterDO( DriverObject,
  139. NULL,
  140. NULL,
  141. L"\\Ntfs",
  142. L"\\FileSystem\\NtfsRecognizer",
  143. NtfsFileSystem,
  144. FILE_DEVICE_DISK_FILE_SYSTEM );
  145. if (NT_SUCCESS( status )) {
  146. count++;
  147. }
  148. if (count) {
  149. return STATUS_SUCCESS;
  150. } else {
  151. return STATUS_IMAGE_ALREADY_LOADED;
  152. }
  153. }
  154. NTSTATUS
  155. FsRecCleanupClose (
  156. IN PDEVICE_OBJECT DeviceObject,
  157. IN PIRP Irp
  158. )
  159. /*++
  160. Routine Description:
  161. This routine is invoked when someone attempts to cleanup or close one of
  162. the system recognizer's registered device objects.
  163. Arguments:
  164. DeviceObject - Pointer to the device object being closed.
  165. Irp - Pointer to the cleanup/close IRP.
  166. Return Value:
  167. The final function value is STATUS_SUCCESS.
  168. --*/
  169. {
  170. PAGED_CODE();
  171. //
  172. // Simply complete the request successfully (note that IoStatus.Status in
  173. // Irp is already initialized to STATUS_SUCCESS).
  174. //
  175. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  176. return STATUS_SUCCESS;
  177. }
  178. NTSTATUS
  179. FsRecCreate (
  180. IN PDEVICE_OBJECT DeviceObject,
  181. IN PIRP Irp
  182. )
  183. /*++
  184. Routine Description:
  185. This routine is invoked when someone attempts to open one of the file
  186. system recognizer's registered device objects.
  187. Arguments:
  188. DeviceObject - Pointer to the device object being opened.
  189. Irp - Pointer to the create IRP.
  190. Return Value:
  191. The final function value indicates whether or not the open was successful.
  192. --*/
  193. {
  194. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  195. NTSTATUS status;
  196. PAGED_CODE();
  197. //
  198. // Simply ensure that the name of the "file" being opened is NULL, and
  199. // complete the request accordingly.
  200. //
  201. if (irpSp->FileObject->FileName.Length) {
  202. status = STATUS_OBJECT_PATH_NOT_FOUND;
  203. } else {
  204. status = STATUS_SUCCESS;
  205. }
  206. Irp->IoStatus.Status = status;
  207. Irp->IoStatus.Information = FILE_OPENED;
  208. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  209. return status;
  210. }
  211. NTSTATUS
  212. FsRecCreateAndRegisterDO (
  213. IN PDRIVER_OBJECT DriverObject,
  214. IN PDEVICE_OBJECT HeadRecognizer OPTIONAL,
  215. OUT PDEVICE_OBJECT *NewRecognizer OPTIONAL,
  216. IN PWCHAR RecFileSystem,
  217. IN PWCHAR FileSystemName,
  218. IN FILE_SYSTEM_TYPE FileSystemType,
  219. IN DEVICE_TYPE DeviceType
  220. )
  221. /*++
  222. Routine Description:
  223. This routine creates a device object for the specified file system type and
  224. registers it as an active file system.
  225. Arguments:
  226. DriverObject - Pointer to the driver object for this driver.
  227. HeadRecognizer - Optionally supplies a pre-existing recognizer that the
  228. newly created DO should be jointly serialized and unregistered with.
  229. This is useful if a given filesystem exists on multiple device types
  230. and thus requires multiple recognizers.
  231. NewDeviceObject - Receives the created DO on success..
  232. RecFileSystem - Name of the file system to be recognized.
  233. FileSystemName - Name of file system device object to be registered.
  234. FileSystemType - Type of this file system recognizer device object.
  235. DeviceType - Type of media this file system recognizer device object will inspect.
  236. Return Value:
  237. The final function value indicates whether or not the device object was
  238. successfully created and registered.
  239. --*/
  240. {
  241. PDEVICE_OBJECT deviceObject;
  242. NTSTATUS status;
  243. UNICODE_STRING nameString;
  244. OBJECT_ATTRIBUTES objectAttributes;
  245. HANDLE fsHandle;
  246. IO_STATUS_BLOCK ioStatus;
  247. PDEVICE_EXTENSION deviceExtension;
  248. PAGED_CODE();
  249. if (NewRecognizer) {
  250. *NewRecognizer = NULL;
  251. }
  252. //
  253. // Begin by attempting to open the file system driver's device object. If
  254. // it works, then the file system is already loaded, so don't load this
  255. // driver. Otherwise, this mini-driver is the one that should be loaded.
  256. //
  257. RtlInitUnicodeString( &nameString, RecFileSystem );
  258. InitializeObjectAttributes( &objectAttributes,
  259. &nameString,
  260. OBJ_CASE_INSENSITIVE,
  261. (HANDLE) NULL,
  262. (PSECURITY_DESCRIPTOR) NULL );
  263. status = ZwCreateFile( &fsHandle,
  264. SYNCHRONIZE,
  265. &objectAttributes,
  266. &ioStatus,
  267. (PLARGE_INTEGER) NULL,
  268. 0,
  269. FILE_SHARE_READ | FILE_SHARE_WRITE,
  270. FILE_OPEN,
  271. 0,
  272. (PVOID) NULL,
  273. 0 );
  274. if (NT_SUCCESS( status )) {
  275. ZwClose( fsHandle );
  276. } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
  277. status = STATUS_SUCCESS;
  278. }
  279. if (NT_SUCCESS( status )) {
  280. return STATUS_IMAGE_ALREADY_LOADED;
  281. }
  282. //
  283. // Attempt to create a device object for this driver. This device object
  284. // will be used to represent the driver as an active file system in the
  285. // system.
  286. //
  287. RtlInitUnicodeString( &nameString, FileSystemName );
  288. status = IoCreateDevice( DriverObject,
  289. sizeof( DEVICE_EXTENSION ),
  290. &nameString,
  291. DeviceType,
  292. 0,
  293. FALSE,
  294. &deviceObject );
  295. if (!NT_SUCCESS( status )) {
  296. return status;
  297. }
  298. status = IoRegisterShutdownNotification (deviceObject);
  299. if (!NT_SUCCESS( status )) {
  300. IoDeleteDevice (deviceObject);
  301. return status;
  302. }
  303. //
  304. // Initialize the device extension for this device object.
  305. //
  306. deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
  307. deviceExtension->FileSystemType = FileSystemType;
  308. deviceExtension->State = Active;
  309. //
  310. // Is this a filesystem being jointly recognized by recognizers for
  311. // different device types?
  312. //
  313. if (HeadRecognizer) {
  314. //
  315. // Link into the list.
  316. //
  317. deviceExtension->CoRecognizer = ((PDEVICE_EXTENSION)HeadRecognizer->DeviceExtension)->CoRecognizer;
  318. ((PDEVICE_EXTENSION)HeadRecognizer->DeviceExtension)->CoRecognizer = deviceObject;
  319. } else {
  320. //
  321. // Initialize the list of codependant recognizer objects.
  322. //
  323. deviceExtension->CoRecognizer = deviceObject;
  324. }
  325. #if _PNP_POWER_
  326. deviceObject->DeviceObjectExtension->PowerControlNeeded = FALSE;
  327. #endif
  328. //
  329. // Finally, register this driver as an active, loaded file system and
  330. // return to the caller.
  331. //
  332. if (NewRecognizer) {
  333. *NewRecognizer = deviceObject;
  334. }
  335. IoRegisterFileSystem( deviceObject );
  336. return STATUS_SUCCESS;
  337. }
  338. NTSTATUS
  339. FsRecFsControl (
  340. IN PDEVICE_OBJECT DeviceObject,
  341. IN PIRP Irp
  342. )
  343. /*++
  344. Routine Description:
  345. This function performs the mount and driver reload functions for this mini-
  346. file system recognizer driver.
  347. Arguments:
  348. DeviceObject - Pointer to this driver's device object.
  349. Irp - Pointer to the I/O Request Packet (IRP) representing the function to
  350. be performed.
  351. Return Value:
  352. The function value is the final status of the operation.
  353. --*/
  354. {
  355. PDEVICE_EXTENSION deviceExtension;
  356. PIO_STACK_LOCATION irpSp;
  357. NTSTATUS status;
  358. PAGED_CODE();
  359. //
  360. // Simply vector to the appropriate FS control function given the type
  361. // of file system being interrogated.
  362. //
  363. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  364. irpSp = IoGetCurrentIrpStackLocation( Irp );
  365. //
  366. // Handle the inactive recognizer states directly.
  367. //
  368. if (deviceExtension->State != Active && irpSp->MinorFunction == IRP_MN_MOUNT_VOLUME) {
  369. if (deviceExtension->State == Transparent) {
  370. status = STATUS_UNRECOGNIZED_VOLUME;
  371. } else {
  372. status = STATUS_FS_DRIVER_REQUIRED;
  373. }
  374. Irp->IoStatus.Status = status;
  375. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  376. return status;
  377. }
  378. switch ( deviceExtension->FileSystemType ) {
  379. case FatFileSystem:
  380. status = FatRecFsControl( DeviceObject, Irp );
  381. break;
  382. case NtfsFileSystem:
  383. status = NtfsRecFsControl( DeviceObject, Irp );
  384. break;
  385. case CdfsFileSystem:
  386. status = CdfsRecFsControl( DeviceObject, Irp );
  387. break;
  388. case UdfsFileSystem:
  389. status = UdfsRecFsControl( DeviceObject, Irp );
  390. break;
  391. default:
  392. status = STATUS_INVALID_DEVICE_REQUEST;
  393. }
  394. return status;
  395. }
  396. NTSTATUS
  397. FsRecShutdown (
  398. IN PDEVICE_OBJECT DeviceObject,
  399. IN PIRP Irp
  400. )
  401. /*++
  402. Routine Description:
  403. This function is the shutdown handle for each of the recognisers file systems
  404. Arguments:
  405. DeviceObject - Pointer to this driver's device object.
  406. Irp - Shutdown IRP
  407. Return Value:
  408. The function value is the final status of the operation.
  409. --*/
  410. {
  411. PDEVICE_EXTENSION DeviceExtension;
  412. DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  413. if (DeviceExtension->State != Transparent) {
  414. IoUnregisterFileSystem (DeviceObject);
  415. DeviceExtension->State = Transparent;
  416. }
  417. IoDeleteDevice (DeviceObject);
  418. Irp->IoStatus.Status = STATUS_SUCCESS;
  419. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  420. return STATUS_SUCCESS;
  421. }
  422. VOID
  423. FsRecUnload (
  424. IN PDRIVER_OBJECT DriverObject
  425. )
  426. /*++
  427. Routine Description:
  428. This routine cleans up the driver's data structures so that it can be
  429. unloaded.
  430. Arguments:
  431. DriverObject - Pointer to the driver object for this driver.
  432. Return Value:
  433. None.
  434. --*/
  435. {
  436. PAGED_CODE();
  437. ExFreePool( FsRecLoadSync );
  438. return;
  439. }
  440. NTSTATUS
  441. FsRecLoadFileSystem (
  442. IN PDEVICE_OBJECT DeviceObject,
  443. IN PWCHAR DriverServiceName
  444. )
  445. /*++
  446. Routine Description:
  447. This routine performs the common work of loading a filesystem on behalf
  448. of one of our recognizers.
  449. Arguments:
  450. DeviceObject - Pointer to the device object for the recognizer.
  451. DriverServiceName - Specifies the name of the node in the registry
  452. associated with the driver to be loaded.
  453. Return Value:
  454. NTSTATUS. The recognizer will be set into a transparent mode on return.
  455. --*/
  456. {
  457. UNICODE_STRING driverName;
  458. PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  459. NTSTATUS status = STATUS_IMAGE_ALREADY_LOADED;
  460. PAGED_CODE();
  461. //
  462. // Quickly check if the recognizer has already fired.
  463. //
  464. if (deviceExtension->State != Transparent) {
  465. //
  466. // Serialize all threads trying to load this filesystem.
  467. //
  468. // We need to do this for several reasons. With the new behavior in
  469. // IoRegisterFileSystem, we do not know ahead of time whether the
  470. // filesystem has been loaded ahead or behind this recognizer in the
  471. // scan queue. This means that we cannot make this recognizer transparent
  472. // before the real filesystem has become registered, or else if the
  473. // filesystem loads behind us we may let threads go through that will
  474. // not find it in that window of time.
  475. //
  476. // The reason this is possible is that NtLoadDriver does not guarantee
  477. // that if it returns STATUS_IMAGE_ALREADY_LOADED, that the driver in
  478. // question has actually initialized itself, which *is* guaranteed if
  479. // it returns STATUS_SUCCESS. We have to keep these threads bottled
  480. // up until they can rescan with the promise that what they need is there.
  481. //
  482. // As a bonus, we can now guarantee that the recognizer goes away in
  483. // all cases, not just when the driver successfully loads itself.
  484. //
  485. KeWaitForSingleObject( FsRecLoadSync,
  486. Executive,
  487. KernelMode,
  488. FALSE,
  489. NULL );
  490. KeEnterCriticalRegion();
  491. //
  492. // Attempt the filesystem load precisely once for all recognizers
  493. // of a given filesystem.
  494. //
  495. if (deviceExtension->State == Active) {
  496. //
  497. // For bonus points, in the future we may want to log an event
  498. // on failure.
  499. //
  500. RtlInitUnicodeString( &driverName, DriverServiceName );
  501. status = ZwLoadDriver( &driverName );
  502. //
  503. // Now walk all codependant recognizers and instruct them to go
  504. // into the fast unload state. Since IO only expects the fsDO
  505. // it is asking to load a filesystem to to unregister itself, if
  506. // we unregistered all of the co-recognizers they would dangle.
  507. // Unfortunately, this means that fsrec may wind up hanging around
  508. // quite a bit longer than strictly neccesary.
  509. //
  510. // Note: we come right back to the original DeviceObject at the
  511. // end of this loop (important). It is also very important that
  512. // we only did this once since after we release the mutex the co-
  513. // recognizers may begin going away in any order.
  514. //
  515. while (deviceExtension->State != FastUnload) {
  516. deviceExtension->State = FastUnload;
  517. DeviceObject = deviceExtension->CoRecognizer;
  518. deviceExtension = DeviceObject->DeviceExtension;
  519. }
  520. }
  521. //
  522. // Unregister this recognizer precisely once.
  523. //
  524. if (deviceExtension->State != Transparent) {
  525. IoUnregisterFileSystem( DeviceObject );
  526. deviceExtension->State = Transparent;
  527. }
  528. KeSetEvent( FsRecLoadSync, 0, FALSE );
  529. KeLeaveCriticalRegion();
  530. }
  531. return status;
  532. }
  533. BOOLEAN
  534. FsRecGetDeviceSectors (
  535. IN PDEVICE_OBJECT DeviceObject,
  536. IN ULONG BytesPerSector,
  537. OUT PLARGE_INTEGER NumberOfSectors
  538. )
  539. /*++
  540. Routine Description:
  541. This routine returns information about the partition represented by the
  542. device object.
  543. Arguments:
  544. DeviceObject - Pointer to the device object from which to read.
  545. BytesPerSector - The number of bytes per sector for the device being read.
  546. NumberOfSectors - Variable to receive the number of sectors for this
  547. partition.
  548. Return Value:
  549. The function value is TRUE if the information was found, otherwise FALSE.
  550. --*/
  551. {
  552. GET_LENGTH_INFORMATION lengthInfo;
  553. IO_STATUS_BLOCK ioStatus;
  554. KEVENT event;
  555. PIRP irp;
  556. NTSTATUS status;
  557. ULONG remainder;
  558. PAGED_CODE();
  559. //
  560. // We only do this for disks right now. This is likely to change when we
  561. // have to recognize CDUDF media.
  562. //
  563. if (DeviceObject->DeviceType != FILE_DEVICE_DISK) {
  564. return FALSE;
  565. }
  566. //
  567. // Get the number of sectors on this partition.
  568. //
  569. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  570. irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_LENGTH_INFO,
  571. DeviceObject,
  572. (PVOID) NULL,
  573. 0,
  574. &lengthInfo,
  575. sizeof( lengthInfo ),
  576. FALSE,
  577. &event,
  578. &ioStatus );
  579. if (!irp) {
  580. return FALSE;
  581. }
  582. //
  583. // Override verify logic - we don't care. The fact we're in the picture means
  584. // someone is trying to mount new/changed media in the first place.
  585. //
  586. SetFlag( IoGetNextIrpStackLocation( irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
  587. status = IoCallDriver( DeviceObject, irp );
  588. if (status == STATUS_PENDING) {
  589. (VOID) KeWaitForSingleObject( &event,
  590. Executive,
  591. KernelMode,
  592. FALSE,
  593. (PLARGE_INTEGER) NULL );
  594. status = ioStatus.Status;
  595. }
  596. if (!NT_SUCCESS( status )) {
  597. return FALSE;
  598. }
  599. *NumberOfSectors = RtlExtendedLargeIntegerDivide( lengthInfo.Length,
  600. BytesPerSector,
  601. &remainder );
  602. return TRUE;
  603. }
  604. BOOLEAN
  605. FsRecGetDeviceSectorSize (
  606. IN PDEVICE_OBJECT DeviceObject,
  607. OUT PULONG BytesPerSector
  608. )
  609. /*++
  610. Routine Description:
  611. This routine returns the sector size of the underlying device.
  612. Arguments:
  613. DeviceObject - Pointer to the device object from which to read.
  614. BytesPerSector - Variable to receive the number of bytes per sector for the
  615. device being read.
  616. Return Value:
  617. The function value is TRUE if the information was found, otherwise FALSE.
  618. --*/
  619. {
  620. DISK_GEOMETRY diskGeometry;
  621. IO_STATUS_BLOCK ioStatus;
  622. KEVENT event;
  623. PIRP irp;
  624. NTSTATUS status;
  625. ULONG ControlCode;
  626. PAGED_CODE();
  627. //
  628. // Figure out what kind of device we have so we can use the right IOCTL.
  629. //
  630. switch (DeviceObject->DeviceType) {
  631. case FILE_DEVICE_CD_ROM:
  632. ControlCode = IOCTL_CDROM_GET_DRIVE_GEOMETRY;
  633. break;
  634. case FILE_DEVICE_DISK:
  635. ControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY;
  636. break;
  637. default:
  638. return FALSE;
  639. }
  640. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  641. irp = IoBuildDeviceIoControlRequest( ControlCode,
  642. DeviceObject,
  643. (PVOID) NULL,
  644. 0,
  645. &diskGeometry,
  646. sizeof( diskGeometry ),
  647. FALSE,
  648. &event,
  649. &ioStatus );
  650. if (!irp) {
  651. return FALSE;
  652. }
  653. //
  654. // Override verify logic - we don't care. The fact we're in the picture means
  655. // someone is trying to mount new/changed media in the first place.
  656. //
  657. SetFlag( IoGetNextIrpStackLocation( irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
  658. status = IoCallDriver( DeviceObject, irp );
  659. if (status == STATUS_PENDING) {
  660. (VOID) KeWaitForSingleObject( &event,
  661. Executive,
  662. KernelMode,
  663. FALSE,
  664. (PLARGE_INTEGER) NULL );
  665. status = ioStatus.Status;
  666. }
  667. if (!NT_SUCCESS( status )) {
  668. return FALSE;
  669. }
  670. //
  671. // Ensure that the drive actually knows how many bytes there are per
  672. // sector. Floppy drives do not know if the media is unformatted.
  673. //
  674. if (!diskGeometry.BytesPerSector) {
  675. return FALSE;
  676. }
  677. //
  678. // Store the return values for the caller.
  679. //
  680. *BytesPerSector = diskGeometry.BytesPerSector;
  681. return TRUE;
  682. }
  683. BOOLEAN
  684. FsRecReadBlock(
  685. IN PDEVICE_OBJECT DeviceObject,
  686. IN PLARGE_INTEGER ByteOffset,
  687. IN ULONG MinimumBytes,
  688. IN ULONG BytesPerSector,
  689. OUT PVOID *Buffer,
  690. OUT PBOOLEAN IsDeviceFailure OPTIONAL
  691. )
  692. /*++
  693. Routine Description:
  694. This routine reads a minimum numbers of bytes into a buffer starting at
  695. the byte offset from the base of the device represented by the device
  696. object.
  697. Arguments:
  698. DeviceObject - Pointer to the device object from which to read.
  699. ByteOffset - Pointer to a 64-bit byte offset from the base of the device
  700. from which to start the read.
  701. MinimumBytes - Supplies the minimum number of bytes to be read.
  702. BytesPerSector - The number of bytes per sector for the device being read.
  703. Buffer - Variable to receive a pointer to the allocated buffer containing
  704. the bytes read.
  705. IsDeviceFailure - Variable to receive an indication whether a failure
  706. was a result of talking to the device.
  707. Return Value:
  708. The function value is TRUE if the bytes were read, otherwise FALSE.
  709. --*/
  710. {
  711. #define RoundUp( x, y ) ( ((x + (y-1)) / y) * y )
  712. IO_STATUS_BLOCK ioStatus;
  713. KEVENT event;
  714. PIRP irp;
  715. NTSTATUS status;
  716. PAGED_CODE();
  717. if (IsDeviceFailure) {
  718. *IsDeviceFailure = FALSE;
  719. }
  720. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  721. //
  722. // Set the minimum number of bytes to read to the maximum of the bytes that
  723. // the caller wants to read, and the number of bytes in a sector.
  724. //
  725. if (MinimumBytes < BytesPerSector) {
  726. MinimumBytes = BytesPerSector;
  727. } else {
  728. MinimumBytes = RoundUp( MinimumBytes, BytesPerSector );
  729. }
  730. //
  731. // Allocate a buffer large enough to contain the bytes required, round the
  732. // request to a page boundary to solve any alignment requirements.
  733. //
  734. if (!*Buffer) {
  735. *Buffer = ExAllocatePoolWithTag( NonPagedPool,
  736. (MinimumBytes + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
  737. FSREC_POOL_TAG );
  738. if (!*Buffer) {
  739. return FALSE;
  740. }
  741. }
  742. //
  743. // Read the actual bytes off of the media.
  744. //
  745. irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
  746. DeviceObject,
  747. *Buffer,
  748. MinimumBytes,
  749. ByteOffset,
  750. &event,
  751. &ioStatus );
  752. if (!irp) {
  753. return FALSE;
  754. }
  755. //
  756. // Override verify logic - we don't care. The fact we're in the picture means
  757. // someone is trying to mount new/changed media in the first place.
  758. //
  759. SetFlag( IoGetNextIrpStackLocation( irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
  760. status = IoCallDriver( DeviceObject, irp );
  761. if (status == STATUS_PENDING) {
  762. (VOID) KeWaitForSingleObject( &event,
  763. Executive,
  764. KernelMode,
  765. FALSE,
  766. (PLARGE_INTEGER) NULL );
  767. status = ioStatus.Status;
  768. }
  769. if (!NT_SUCCESS( status )) {
  770. if (IsDeviceFailure) {
  771. *IsDeviceFailure = TRUE;
  772. }
  773. return FALSE;
  774. }
  775. return TRUE;
  776. }
  777. #if DBG
  778. BOOLEAN
  779. FsRecDebugTrace (
  780. LONG IndentIncrement,
  781. ULONG TraceMask,
  782. PCHAR Format,
  783. ...
  784. )
  785. /*++
  786. Routine Description:
  787. This routine is a simple debug info printer that returns a constant boolean value. This
  788. makes it possible to splice it into the middle of boolean expressions to discover which
  789. elements are firing.
  790. We will use this as our general debug printer. See udfdata.h for how we use the DebugTrace
  791. macro to accomplish the effect.
  792. Arguments:
  793. IndentIncrement - amount to change the indentation by.
  794. TraceMask - specification of what debug trace level this call should be noisy at.
  795. Return Value:
  796. USHORT - The 16bit CRC
  797. --*/
  798. {
  799. va_list Arglist;
  800. LONG i;
  801. UCHAR Buffer[128];
  802. int Bytes;
  803. #define Min(a, b) ((a) < (b) ? (a) : (b))
  804. if (TraceMask == 0 || (FsRecDebugTraceLevel & TraceMask) != 0) {
  805. //
  806. // Emit a preamble of our thread ID.
  807. //
  808. DbgPrint( "%p:", PsGetCurrentThread());
  809. if (IndentIncrement < 0) {
  810. FsRecDebugTraceIndent += IndentIncrement;
  811. }
  812. if (FsRecDebugTraceIndent < 0) {
  813. FsRecDebugTraceIndent = 0;
  814. }
  815. //
  816. // Build the indent in big chunks since calling DbgPrint repeatedly is expensive.
  817. //
  818. for (i = FsRecDebugTraceIndent; i > 0; i -= (sizeof(Buffer) - 1)) {
  819. RtlFillMemory( Buffer, Min( i, (sizeof(Buffer) - 1 )), ' ');
  820. *(Buffer + Min( i, (sizeof(Buffer) - 1 ))) = '\0';
  821. DbgPrint( Buffer );
  822. }
  823. //
  824. // Format the output into a buffer and then print it.
  825. //
  826. va_start( Arglist, Format );
  827. Bytes = _vsnprintf( Buffer, sizeof(Buffer), Format, Arglist );
  828. va_end( Arglist );
  829. //
  830. // detect buffer overflow
  831. //
  832. if (Bytes == -1) {
  833. Buffer[sizeof(Buffer) - 1] = '\n';
  834. }
  835. DbgPrint( Buffer );
  836. if (IndentIncrement > 0) {
  837. FsRecDebugTraceIndent += IndentIncrement;
  838. }
  839. }
  840. return TRUE;
  841. }
  842. #endif