Leaked source code of windows server 2003
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.

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