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.

5593 lines
152 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. dblattach.c
  5. Abstract:
  6. This module contains the code that implements the general purpose
  7. file system filter driver that attaches at two locations in the stack.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Darryl E. Havens (darrylh) 26-Jan-1995
  11. // @@END_DDKSPLIT
  12. Environment:
  13. Kernel mode
  14. // @@BEGIN_DDKSPLIT
  15. Revision History:
  16. Molly Brown (12-Mar-2002)
  17. Created based on SFILTER sample.
  18. // @@END_DDKSPLIT
  19. --*/
  20. #include "ntifs.h"
  21. //
  22. // Enable these warnings in the code.
  23. //
  24. #pragma warning(error:4100) // Unreferenced formal parameter
  25. #pragma warning(error:4101) // Unreferenced local variable
  26. /////////////////////////////////////////////////////////////////////////////
  27. //
  28. // Macro and Structure Definitions
  29. //
  30. /////////////////////////////////////////////////////////////////////////////
  31. //
  32. // Buffer size for local names on the stack
  33. //
  34. #define MAX_DEVNAME_LENGTH 64
  35. typedef enum _DEVICE_EXTENSION_TYPE {
  36. FsControlDeviceObject,
  37. FsVolumeUpper,
  38. FsVolumeLower,
  39. } DEVICE_EXTENSION_TYPE, *PDEVICE_EXTENSION_TYPE;
  40. //
  41. // Device extension definition for our driver. Note that the same extension
  42. // is used for the following types of device objects:
  43. // - File system device object we attach to
  44. // - Mounted volume device objects we attach to
  45. //
  46. typedef struct _DBLATTACH_DEVEXT_HEADER {
  47. //
  48. // Denotes what type of extension this is.
  49. //
  50. DEVICE_EXTENSION_TYPE ExtType;
  51. //
  52. // Pointer to the file system device object we are attached to
  53. //
  54. PDEVICE_OBJECT AttachedToDeviceObject;
  55. } DBLATTACH_DEVEXT_HEADER, *PDBLATTACH_DEVEXT_HEADER;
  56. typedef struct _DBLATTACH_SHARED_VDO_EXTENSION {
  57. //
  58. // Pointer to the real (disk) device object that is associated with
  59. // the file system device object we are attached to
  60. //
  61. PDEVICE_OBJECT DiskDeviceObject;
  62. //
  63. // The name of the physical disk drive.
  64. //
  65. UNICODE_STRING DeviceName;
  66. //
  67. // Buffer used to hold the above unicode strings
  68. //
  69. WCHAR DeviceNameBuffer[MAX_DEVNAME_LENGTH];
  70. } DBLATTACH_SHARED_VDO_EXTENSION, *PDBLATTACH_SHARED_VDO_EXTENSION;
  71. typedef struct _DBLATTACH_VDO_EXTENSION {
  72. DBLATTACH_DEVEXT_HEADER;
  73. //
  74. // Shared device extension state for this volume
  75. //
  76. PDBLATTACH_SHARED_VDO_EXTENSION SharedExt;
  77. } DBLATTACH_VDO_EXTENSION, *PDBLATTACH_VDO_EXTENSION;
  78. typedef struct _DBLATTACH_CDO_EXTENSION {
  79. DBLATTACH_DEVEXT_HEADER;
  80. //
  81. // The name of the file system's control device object.
  82. //
  83. UNICODE_STRING DeviceName;
  84. //
  85. // Buffer used to hold the above unicode strings
  86. //
  87. WCHAR DeviceNameBuffer[MAX_DEVNAME_LENGTH];
  88. } DBLATTACH_CDO_EXTENSION, *PDBLATTACH_CDO_EXTENSION;
  89. //
  90. // Macro to test if this is my device object
  91. //
  92. #define IS_MY_DEVICE_OBJECT(_devObj) \
  93. (((_devObj) != NULL) && \
  94. ((_devObj)->DriverObject == gDblAttachDriverObject) && \
  95. ((_devObj)->DeviceExtension != NULL))
  96. #define IS_UPPER_DEVICE_OBJECT(_devObj) \
  97. (ASSERT( IS_MY_DEVICE_OBJECT( _devObj ) ) && \
  98. ((PDBLATTACH_DEVEXT_HEADER)((_devObj)->DeviceExtension))->ExtType == FsVolumeUpper)
  99. #define IS_LOWER_DEVICE_OBJECT(_devObj) \
  100. (ASSERT( IS_MY_DEVICE_OBJECT( _devObj ) ) && \
  101. ((PDBLATTACH_DEVEXT_HEADER)((_devObj)->DeviceExtension))->ExtType == FsVolumeLower)
  102. #define IS_FSCDO_DEVICE_OBJECT(_devObj) \
  103. (ASSERT( IS_MY_DEVICE_OBJECT( _devObj ) ) && \
  104. ((PDBLATTACH_DEVEXT_HEADER)((_devObj)->DeviceExtension))->ExtType == FsControlDeviceObject)
  105. //
  106. // Macro to test if this is my control device object
  107. //
  108. #define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \
  109. (((_devObj) == gDblAttachControlDeviceObject) ? \
  110. (ASSERT(((_devObj)->DriverObject == gDblAttachDriverObject) && \
  111. ((_devObj)->DeviceExtension == NULL)), TRUE) : \
  112. FALSE)
  113. //
  114. // Macro to test for device types we want to attach to
  115. //
  116. #define IS_DESIRED_DEVICE_TYPE(_type) \
  117. (((_type) == FILE_DEVICE_DISK_FILE_SYSTEM) || \
  118. ((_type) == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || \
  119. ((_type) == FILE_DEVICE_NETWORK_FILE_SYSTEM))
  120. //
  121. // Macro to test if FAST_IO_DISPATCH handling routine is valid
  122. //
  123. #define VALID_FAST_IO_DISPATCH_HANDLER(_FastIoDispatchPtr, _FieldName) \
  124. (((_FastIoDispatchPtr) != NULL) && \
  125. (((_FastIoDispatchPtr)->SizeOfFastIoDispatch) >= \
  126. (FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && \
  127. ((_FastIoDispatchPtr)->_FieldName != NULL))
  128. //
  129. // Macro to validate our current IRQL level
  130. //
  131. #define VALIDATE_IRQL() (ASSERT(KeGetCurrentIrql() <= APC_LEVEL))
  132. //
  133. // TAG identifying memory DblAttach allocates
  134. //
  135. #define DA_POOL_TAG 'AlbD'
  136. //
  137. // This structure and these routines are used to retrieve the name of a file
  138. // object. To prevent allocating memory every time we get a name this
  139. // structure contains a small buffer (which should handle 90+% of all names).
  140. // If we do overflow this buffer we will allocate a buffer big enough
  141. // for the name.
  142. //
  143. typedef struct _GET_NAME_CONTROL {
  144. PCHAR AllocatedBuffer;
  145. CHAR SmallBuffer[256];
  146. } GET_NAME_CONTROL, *PGET_NAME_CONTROL;
  147. PUNICODE_STRING
  148. DaGetFileName(
  149. IN PFILE_OBJECT FileObject,
  150. IN NTSTATUS CreateStatus,
  151. IN OUT PGET_NAME_CONTROL NameControl);
  152. VOID
  153. DaGetFileNameCleanup(
  154. IN OUT PGET_NAME_CONTROL NameControl);
  155. //
  156. // Macros for SFilter DbgPrint levels.
  157. //
  158. #define DA_LOG_PRINT( _dbgLevel, _string ) \
  159. (FlagOn(DaDebug,(_dbgLevel)) ? \
  160. DbgPrint _string : \
  161. ((void)0))
  162. /////////////////////////////////////////////////////////////////////////////
  163. //
  164. // Global variables
  165. //
  166. /////////////////////////////////////////////////////////////////////////////
  167. //
  168. // Holds pointer to the driver object for this driver
  169. //
  170. PDRIVER_OBJECT gDblAttachDriverObject = NULL;
  171. //
  172. // Holds pointer to the device object that represents this driver and is used
  173. // by external programs to access this driver. This is also known as the
  174. // "control device object".
  175. //
  176. PDEVICE_OBJECT gDblAttachControlDeviceObject = NULL;
  177. //
  178. // This lock is used to synchronize our attaching to a given device object.
  179. // This lock fixes a race condition where we could accidently attach to the
  180. // same device object more then once. This race condition only occurs if
  181. // a volume is being mounted at the same time as this filter is being loaded.
  182. // This problem will never occur if this filter is loaded at boot time before
  183. // any file systems are loaded.
  184. //
  185. // This lock is used to atomically test if we are already attached to a given
  186. // device object and if not, do the attach.
  187. //
  188. FAST_MUTEX gDblAttachLock;
  189. #define TRIGGER_NAME L"\\test\\failure.txt"
  190. /////////////////////////////////////////////////////////////////////////////
  191. //
  192. // Debug Definitions
  193. //
  194. /////////////////////////////////////////////////////////////////////////////
  195. //
  196. // DEBUG display flags
  197. //
  198. #define DADEBUG_DISPLAY_ATTACHMENT_NAMES 0x00000001 //display names of device objects we attach to
  199. #define DADEBUG_DISPLAY_CREATE_NAMES 0x00000002 //get and display names during create
  200. #define DADEBUG_GET_CREATE_NAMES 0x00000004 //get name (don't display) during create
  201. #define DADEBUG_DO_CREATE_COMPLETION 0x00000008 //do create completion routine, don't get names
  202. #define DADEBUG_ATTACH_TO_FSRECOGNIZER 0x00000010 //do attach to FSRecognizer device objects
  203. ULONG DaDebug = DADEBUG_DISPLAY_ATTACHMENT_NAMES | DADEBUG_DISPLAY_CREATE_NAMES | DADEBUG_GET_CREATE_NAMES;
  204. #define VDO_ARRAY_SIZE 2
  205. //
  206. // Given a device type, return a valid name
  207. //
  208. #define GET_DEVICE_TYPE_NAME( _type ) \
  209. ((((_type) > 0) && ((_type) < (sizeof(DeviceTypeNames) / sizeof(PCHAR)))) ? \
  210. DeviceTypeNames[ (_type) ] : \
  211. "[Unknown]")
  212. //
  213. // Known device type names
  214. //
  215. static const PCHAR DeviceTypeNames[] = {
  216. "",
  217. "BEEP",
  218. "CD_ROM",
  219. "CD_ROM_FILE_SYSTEM",
  220. "CONTROLLER",
  221. "DATALINK",
  222. "DFS",
  223. "DISK",
  224. "DISK_FILE_SYSTEM",
  225. "FILE_SYSTEM",
  226. "INPORT_PORT",
  227. "KEYBOARD",
  228. "MAILSLOT",
  229. "MIDI_IN",
  230. "MIDI_OUT",
  231. "MOUSE",
  232. "MULTI_UNC_PROVIDER",
  233. "NAMED_PIPE",
  234. "NETWORK",
  235. "NETWORK_BROWSER",
  236. "NETWORK_FILE_SYSTEM",
  237. "NULL",
  238. "PARALLEL_PORT",
  239. "PHYSICAL_NETCARD",
  240. "PRINTER",
  241. "SCANNER",
  242. "SERIAL_MOUSE_PORT",
  243. "SERIAL_PORT",
  244. "SCREEN",
  245. "SOUND",
  246. "STREAMS",
  247. "TAPE",
  248. "TAPE_FILE_SYSTEM",
  249. "TRANSPORT",
  250. "UNKNOWN",
  251. "VIDEO",
  252. "VIRTUAL_DISK",
  253. "WAVE_IN",
  254. "WAVE_OUT",
  255. "8042_PORT",
  256. "NETWORK_REDIRECTOR",
  257. "BATTERY",
  258. "BUS_EXTENDER",
  259. "MODEM",
  260. "VDM",
  261. "MASS_STORAGE",
  262. "SMB",
  263. "KS",
  264. "CHANGER",
  265. "SMARTCARD",
  266. "ACPI",
  267. "DVD",
  268. "FULLSCREEN_VIDEO",
  269. "DFS_FILE_SYSTEM",
  270. "DFS_VOLUME",
  271. "SERENUM",
  272. "TERMSRV",
  273. "KSEC"
  274. };
  275. /////////////////////////////////////////////////////////////////////////////
  276. //
  277. // Function Prototypes
  278. //
  279. /////////////////////////////////////////////////////////////////////////////
  280. //
  281. // Define driver entry routine.
  282. //
  283. NTSTATUS
  284. DriverEntry(
  285. IN PDRIVER_OBJECT DriverObject,
  286. IN PUNICODE_STRING RegistryPath
  287. );
  288. #if DBG
  289. VOID
  290. DriverUnload(
  291. IN PDRIVER_OBJECT DriverObject
  292. );
  293. #endif
  294. //
  295. // Define the local routines used by this driver module. This includes a
  296. // a sample of how to filter a create file operation, and then invoke an I/O
  297. // completion routine when the file has successfully been created/opened.
  298. //
  299. NTSTATUS
  300. DaPassThrough(
  301. IN PDEVICE_OBJECT DeviceObject,
  302. IN PIRP Irp
  303. );
  304. NTSTATUS
  305. DaCreateLower (
  306. IN PDBLATTACH_VDO_EXTENSION VdoExt,
  307. IN PIRP Irp
  308. );
  309. NTSTATUS
  310. DaCreateUpper (
  311. IN PDBLATTACH_VDO_EXTENSION VdoExt,
  312. IN PIRP Irp
  313. );
  314. NTSTATUS
  315. DaCreate(
  316. IN PDEVICE_OBJECT DeviceObject,
  317. IN PIRP Irp
  318. );
  319. NTSTATUS
  320. DaCreateCompletion(
  321. IN PDEVICE_OBJECT DeviceObject,
  322. IN PIRP Irp,
  323. IN PVOID Context
  324. );
  325. NTSTATUS
  326. DaCleanupClose(
  327. IN PDEVICE_OBJECT DeviceObject,
  328. IN PIRP Irp
  329. );
  330. NTSTATUS
  331. DaFsControl(
  332. IN PDEVICE_OBJECT DeviceObject,
  333. IN PIRP Irp
  334. );
  335. NTSTATUS
  336. DaFsControlMountVolume (
  337. IN PDEVICE_OBJECT DeviceObject,
  338. IN PIRP Irp
  339. );
  340. NTSTATUS
  341. DaFsControlLoadFileSystem (
  342. IN PDEVICE_OBJECT DeviceObject,
  343. IN PIRP Irp
  344. );
  345. NTSTATUS
  346. DaFsControlCompletion(
  347. IN PDEVICE_OBJECT DeviceObject,
  348. IN PIRP Irp,
  349. IN PVOID Context
  350. );
  351. BOOLEAN
  352. DaFastIoCheckIfPossible(
  353. IN PFILE_OBJECT FileObject,
  354. IN PLARGE_INTEGER FileOffset,
  355. IN ULONG Length,
  356. IN BOOLEAN Wait,
  357. IN ULONG LockKey,
  358. IN BOOLEAN CheckForReadOperation,
  359. OUT PIO_STATUS_BLOCK IoStatus,
  360. IN PDEVICE_OBJECT DeviceObject
  361. );
  362. BOOLEAN
  363. DaFastIoRead(
  364. IN PFILE_OBJECT FileObject,
  365. IN PLARGE_INTEGER FileOffset,
  366. IN ULONG Length,
  367. IN BOOLEAN Wait,
  368. IN ULONG LockKey,
  369. OUT PVOID Buffer,
  370. OUT PIO_STATUS_BLOCK IoStatus,
  371. IN PDEVICE_OBJECT DeviceObject
  372. );
  373. BOOLEAN
  374. DaFastIoWrite(
  375. IN PFILE_OBJECT FileObject,
  376. IN PLARGE_INTEGER FileOffset,
  377. IN ULONG Length,
  378. IN BOOLEAN Wait,
  379. IN ULONG LockKey,
  380. IN PVOID Buffer,
  381. OUT PIO_STATUS_BLOCK IoStatus,
  382. IN PDEVICE_OBJECT DeviceObject
  383. );
  384. BOOLEAN
  385. DaFastIoQueryBasicInfo(
  386. IN PFILE_OBJECT FileObject,
  387. IN BOOLEAN Wait,
  388. OUT PFILE_BASIC_INFORMATION Buffer,
  389. OUT PIO_STATUS_BLOCK IoStatus,
  390. IN PDEVICE_OBJECT DeviceObject
  391. );
  392. BOOLEAN
  393. DaFastIoQueryStandardInfo(
  394. IN PFILE_OBJECT FileObject,
  395. IN BOOLEAN Wait,
  396. OUT PFILE_STANDARD_INFORMATION Buffer,
  397. OUT PIO_STATUS_BLOCK IoStatus,
  398. IN PDEVICE_OBJECT DeviceObject
  399. );
  400. BOOLEAN
  401. DaFastIoLock(
  402. IN PFILE_OBJECT FileObject,
  403. IN PLARGE_INTEGER FileOffset,
  404. IN PLARGE_INTEGER Length,
  405. PEPROCESS ProcessId,
  406. ULONG Key,
  407. BOOLEAN FailImmediately,
  408. BOOLEAN ExclusiveLock,
  409. OUT PIO_STATUS_BLOCK IoStatus,
  410. IN PDEVICE_OBJECT DeviceObject
  411. );
  412. BOOLEAN
  413. DaFastIoUnlockSingle(
  414. IN PFILE_OBJECT FileObject,
  415. IN PLARGE_INTEGER FileOffset,
  416. IN PLARGE_INTEGER Length,
  417. PEPROCESS ProcessId,
  418. ULONG Key,
  419. OUT PIO_STATUS_BLOCK IoStatus,
  420. IN PDEVICE_OBJECT DeviceObject
  421. );
  422. BOOLEAN
  423. DaFastIoUnlockAll(
  424. IN PFILE_OBJECT FileObject,
  425. PEPROCESS ProcessId,
  426. OUT PIO_STATUS_BLOCK IoStatus,
  427. IN PDEVICE_OBJECT DeviceObject
  428. );
  429. BOOLEAN
  430. DaFastIoUnlockAllByKey(
  431. IN PFILE_OBJECT FileObject,
  432. PVOID ProcessId,
  433. ULONG Key,
  434. OUT PIO_STATUS_BLOCK IoStatus,
  435. IN PDEVICE_OBJECT DeviceObject
  436. );
  437. BOOLEAN
  438. DaFastIoDeviceControl(
  439. IN PFILE_OBJECT FileObject,
  440. IN BOOLEAN Wait,
  441. IN PVOID InputBuffer OPTIONAL,
  442. IN ULONG InputBufferLength,
  443. OUT PVOID OutputBuffer OPTIONAL,
  444. IN ULONG OutputBufferLength,
  445. IN ULONG IoControlCode,
  446. OUT PIO_STATUS_BLOCK IoStatus,
  447. IN PDEVICE_OBJECT DeviceObject
  448. );
  449. VOID
  450. DaFastIoDetachDevice(
  451. IN PDEVICE_OBJECT SourceDevice,
  452. IN PDEVICE_OBJECT TargetDevice
  453. );
  454. BOOLEAN
  455. DaFastIoQueryNetworkOpenInfo(
  456. IN PFILE_OBJECT FileObject,
  457. IN BOOLEAN Wait,
  458. OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
  459. OUT PIO_STATUS_BLOCK IoStatus,
  460. IN PDEVICE_OBJECT DeviceObject
  461. );
  462. BOOLEAN
  463. DaFastIoMdlRead(
  464. IN PFILE_OBJECT FileObject,
  465. IN PLARGE_INTEGER FileOffset,
  466. IN ULONG Length,
  467. IN ULONG LockKey,
  468. OUT PMDL *MdlChain,
  469. OUT PIO_STATUS_BLOCK IoStatus,
  470. IN PDEVICE_OBJECT DeviceObject
  471. );
  472. BOOLEAN
  473. DaFastIoMdlReadComplete(
  474. IN PFILE_OBJECT FileObject,
  475. IN PMDL MdlChain,
  476. IN PDEVICE_OBJECT DeviceObject
  477. );
  478. BOOLEAN
  479. DaFastIoPrepareMdlWrite(
  480. IN PFILE_OBJECT FileObject,
  481. IN PLARGE_INTEGER FileOffset,
  482. IN ULONG Length,
  483. IN ULONG LockKey,
  484. OUT PMDL *MdlChain,
  485. OUT PIO_STATUS_BLOCK IoStatus,
  486. IN PDEVICE_OBJECT DeviceObject
  487. );
  488. BOOLEAN
  489. DaFastIoMdlWriteComplete(
  490. IN PFILE_OBJECT FileObject,
  491. IN PLARGE_INTEGER FileOffset,
  492. IN PMDL MdlChain,
  493. IN PDEVICE_OBJECT DeviceObject
  494. );
  495. BOOLEAN
  496. DaFastIoReadCompressed(
  497. IN PFILE_OBJECT FileObject,
  498. IN PLARGE_INTEGER FileOffset,
  499. IN ULONG Length,
  500. IN ULONG LockKey,
  501. OUT PVOID Buffer,
  502. OUT PMDL *MdlChain,
  503. OUT PIO_STATUS_BLOCK IoStatus,
  504. OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
  505. IN ULONG CompressedDataInfoLength,
  506. IN PDEVICE_OBJECT DeviceObject
  507. );
  508. BOOLEAN
  509. DaFastIoWriteCompressed(
  510. IN PFILE_OBJECT FileObject,
  511. IN PLARGE_INTEGER FileOffset,
  512. IN ULONG Length,
  513. IN ULONG LockKey,
  514. IN PVOID Buffer,
  515. OUT PMDL *MdlChain,
  516. OUT PIO_STATUS_BLOCK IoStatus,
  517. IN struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
  518. IN ULONG CompressedDataInfoLength,
  519. IN PDEVICE_OBJECT DeviceObject
  520. );
  521. BOOLEAN
  522. DaFastIoMdlReadCompleteCompressed(
  523. IN PFILE_OBJECT FileObject,
  524. IN PMDL MdlChain,
  525. IN PDEVICE_OBJECT DeviceObject
  526. );
  527. BOOLEAN
  528. DaFastIoMdlWriteCompleteCompressed(
  529. IN PFILE_OBJECT FileObject,
  530. IN PLARGE_INTEGER FileOffset,
  531. IN PMDL MdlChain,
  532. IN PDEVICE_OBJECT DeviceObject
  533. );
  534. BOOLEAN
  535. DaFastIoQueryOpen(
  536. IN PIRP Irp,
  537. OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
  538. IN PDEVICE_OBJECT DeviceObject
  539. );
  540. NTSTATUS
  541. DaPreFsFilterPassThrough (
  542. IN PFS_FILTER_CALLBACK_DATA Data,
  543. OUT PVOID *CompletionContext
  544. );
  545. VOID
  546. DaPostFsFilterPassThrough (
  547. IN PFS_FILTER_CALLBACK_DATA Data,
  548. IN NTSTATUS OperationStatus,
  549. IN PVOID CompletionContext
  550. );
  551. VOID
  552. DaFsNotification(
  553. IN PDEVICE_OBJECT DeviceObject,
  554. IN BOOLEAN FsActive
  555. );
  556. NTSTATUS
  557. DaCreateVolumeDeviceObjects (
  558. IN DEVICE_TYPE DeviceType,
  559. IN ULONG NumberOfArrayElements,
  560. IN OUT PDEVICE_OBJECT *VDOArray
  561. );
  562. NTSTATUS
  563. DaAttachToFileSystemDevice(
  564. IN PDEVICE_OBJECT DeviceObject,
  565. IN PUNICODE_STRING DeviceName
  566. );
  567. VOID
  568. DaDetachFromFileSystemDevice (
  569. IN PDEVICE_OBJECT DeviceObject
  570. );
  571. NTSTATUS
  572. DaAttachToMountedDevice (
  573. IN PDEVICE_OBJECT DeviceObject,
  574. IN ULONG NumberOfElements,
  575. OUT IN PDEVICE_OBJECT *VdoArray
  576. );
  577. VOID
  578. DaDeleteMountedDevices (
  579. IN ULONG NumberOfElements,
  580. IN PDEVICE_OBJECT *VdoArray
  581. );
  582. VOID
  583. DaCleanupMountedDevice(
  584. IN PDEVICE_OBJECT DeviceObject
  585. );
  586. NTSTATUS
  587. DaEnumerateFileSystemVolumes(
  588. IN PDEVICE_OBJECT FSDeviceObject,
  589. PUNICODE_STRING Name
  590. );
  591. VOID
  592. DaGetObjectName(
  593. IN PVOID Object,
  594. IN OUT PUNICODE_STRING Name
  595. );
  596. VOID
  597. DaGetBaseDeviceObjectName(
  598. IN PDEVICE_OBJECT DeviceObject,
  599. IN OUT PUNICODE_STRING DeviceName
  600. );
  601. BOOLEAN
  602. DaIsAttachedToDevice(
  603. PDEVICE_OBJECT DeviceObject,
  604. PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL
  605. );
  606. VOID
  607. DaReadDriverParameters(
  608. IN PUNICODE_STRING RegistryPath
  609. );
  610. BOOLEAN
  611. DaMonitorFile(
  612. IN PFILE_OBJECT FileObject,
  613. IN PDBLATTACH_VDO_EXTENSION VdoExtension
  614. );
  615. /////////////////////////////////////////////////////////////////////////////
  616. //
  617. // Assign text sections for each routine.
  618. //
  619. /////////////////////////////////////////////////////////////////////////////
  620. #ifdef ALLOC_PRAGMA
  621. #pragma alloc_text(INIT, DriverEntry)
  622. #if DBG
  623. #pragma alloc_text(PAGE, DriverUnload)
  624. #endif
  625. #pragma alloc_text(PAGE, DaFsNotification)
  626. #pragma alloc_text(PAGE, DaCreate)
  627. #pragma alloc_text(PAGE, DaCleanupClose)
  628. #pragma alloc_text(PAGE, DaFsControl)
  629. #pragma alloc_text(PAGE, DaFsControlMountVolume)
  630. #pragma alloc_text(PAGE, DaFsControlLoadFileSystem)
  631. #pragma alloc_text(PAGE, DaFastIoCheckIfPossible)
  632. #pragma alloc_text(PAGE, DaFastIoRead)
  633. #pragma alloc_text(PAGE, DaFastIoWrite)
  634. #pragma alloc_text(PAGE, DaFastIoQueryBasicInfo)
  635. #pragma alloc_text(PAGE, DaFastIoQueryStandardInfo)
  636. #pragma alloc_text(PAGE, DaFastIoLock)
  637. #pragma alloc_text(PAGE, DaFastIoUnlockSingle)
  638. #pragma alloc_text(PAGE, DaFastIoUnlockAll)
  639. #pragma alloc_text(PAGE, DaFastIoUnlockAllByKey)
  640. #pragma alloc_text(PAGE, DaFastIoDeviceControl)
  641. #pragma alloc_text(PAGE, DaFastIoDetachDevice)
  642. #pragma alloc_text(PAGE, DaFastIoQueryNetworkOpenInfo)
  643. #pragma alloc_text(PAGE, DaFastIoMdlRead)
  644. #pragma alloc_text(PAGE, DaFastIoPrepareMdlWrite)
  645. #pragma alloc_text(PAGE, DaFastIoMdlWriteComplete)
  646. #pragma alloc_text(PAGE, DaFastIoReadCompressed)
  647. #pragma alloc_text(PAGE, DaFastIoWriteCompressed)
  648. #pragma alloc_text(PAGE, DaFastIoQueryOpen)
  649. #pragma alloc_text(PAGE, DaPreFsFilterPassThrough)
  650. #pragma alloc_text(PAGE, DaPostFsFilterPassThrough)
  651. #pragma alloc_text(PAGE, DaAttachToFileSystemDevice)
  652. #pragma alloc_text(PAGE, DaDetachFromFileSystemDevice)
  653. #pragma alloc_text(PAGE, DaEnumerateFileSystemVolumes)
  654. #pragma alloc_text(PAGE, DaAttachToMountedDevice)
  655. #pragma alloc_text(PAGE, DaIsAttachedToDevice)
  656. #pragma alloc_text(INIT, DaReadDriverParameters)
  657. #endif
  658. /////////////////////////////////////////////////////////////////////////////
  659. //
  660. // Functions
  661. //
  662. /////////////////////////////////////////////////////////////////////////////
  663. NTSTATUS
  664. DriverEntry (
  665. IN PDRIVER_OBJECT DriverObject,
  666. IN PUNICODE_STRING RegistryPath
  667. )
  668. /*++
  669. Routine Description:
  670. This is the initialization routine for the SFILTER file system filter
  671. driver. This routine creates the device object that represents this
  672. driver in the system and registers it for watching all file systems that
  673. register or unregister themselves as active file systems.
  674. Arguments:
  675. DriverObject - Pointer to driver object created by the system.
  676. Return Value:
  677. The function value is the final status from the initialization operation.
  678. --*/
  679. {
  680. PFAST_IO_DISPATCH fastIoDispatch;
  681. UNICODE_STRING nameString;
  682. FS_FILTER_CALLBACKS fsFilterCallbacks;
  683. NTSTATUS status;
  684. ULONG i;
  685. //
  686. // Get Registry values
  687. //
  688. DaReadDriverParameters( RegistryPath );
  689. #if DBG
  690. //DbgBreakPoint();
  691. #endif
  692. //
  693. // Save our Driver Object, set our UNLOAD routine
  694. //
  695. gDblAttachDriverObject = DriverObject;
  696. #if DBG
  697. //
  698. // Unload is useful for development purposes. It is not recommended for production versions
  699. //
  700. gDblAttachDriverObject->DriverUnload = DriverUnload;
  701. #endif
  702. //
  703. // Setup other global variables
  704. //
  705. ExInitializeFastMutex( &gDblAttachLock );
  706. //
  707. // Create the Control Device Object (CDO). This object represents this
  708. // driver. Note that it does not have a device extension.
  709. //
  710. RtlInitUnicodeString( &nameString, L"\\FileSystem\\Filters\\SFilter" );
  711. status = IoCreateDevice(
  712. DriverObject,
  713. 0, //has not device extension
  714. &nameString,
  715. FILE_DEVICE_DISK_FILE_SYSTEM,
  716. FILE_DEVICE_SECURE_OPEN,
  717. FALSE,
  718. &gDblAttachControlDeviceObject );
  719. if (!NT_SUCCESS( status )) {
  720. KdPrint(( "DblAttach!DriverEntry: Error creating control device object, status=%08x\n", status ));
  721. return status;
  722. }
  723. //
  724. // Initialize the driver object with this device driver's entry points.
  725. //
  726. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  727. DriverObject->MajorFunction[i] = DaPassThrough;
  728. }
  729. DriverObject->MajorFunction[IRP_MJ_CREATE] = DaCreate;
  730. DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = DaFsControl;
  731. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DaCleanupClose;
  732. DriverObject->MajorFunction[IRP_MJ_CLOSE] = DaCleanupClose;
  733. //
  734. // Allocate fast I/O data structure and fill it in.
  735. //
  736. // NOTE: The following FastIo Routines are not supported:
  737. // AcquireFileForNtCreateSection
  738. // ReleaseFileForNtCreateSection
  739. // AcquireForModWrite
  740. // ReleaseForModWrite
  741. // AcquireForCcFlush
  742. // ReleaseForCcFlush
  743. //
  744. // For historical reasons these FastIO's have never been sent to filters
  745. // by the NT I/O system. Instead, they are sent directly to the base
  746. // file system. You should use the new system routine
  747. // "FsRtlRegisterFileSystemFilterCallbacks" if you need to intercept these
  748. // callbacks (see below).
  749. //
  750. fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool, sizeof( FAST_IO_DISPATCH ), DA_POOL_TAG );
  751. if (!fastIoDispatch) {
  752. IoDeleteDevice( gDblAttachControlDeviceObject );
  753. return STATUS_INSUFFICIENT_RESOURCES;
  754. }
  755. RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );
  756. fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH );
  757. fastIoDispatch->FastIoCheckIfPossible = DaFastIoCheckIfPossible;
  758. fastIoDispatch->FastIoRead = DaFastIoRead;
  759. fastIoDispatch->FastIoWrite = DaFastIoWrite;
  760. fastIoDispatch->FastIoQueryBasicInfo = DaFastIoQueryBasicInfo;
  761. fastIoDispatch->FastIoQueryStandardInfo = DaFastIoQueryStandardInfo;
  762. fastIoDispatch->FastIoLock = DaFastIoLock;
  763. fastIoDispatch->FastIoUnlockSingle = DaFastIoUnlockSingle;
  764. fastIoDispatch->FastIoUnlockAll = DaFastIoUnlockAll;
  765. fastIoDispatch->FastIoUnlockAllByKey = DaFastIoUnlockAllByKey;
  766. fastIoDispatch->FastIoDeviceControl = DaFastIoDeviceControl;
  767. fastIoDispatch->FastIoDetachDevice = DaFastIoDetachDevice;
  768. fastIoDispatch->FastIoQueryNetworkOpenInfo = DaFastIoQueryNetworkOpenInfo;
  769. fastIoDispatch->MdlRead = DaFastIoMdlRead;
  770. fastIoDispatch->MdlReadComplete = DaFastIoMdlReadComplete;
  771. fastIoDispatch->PrepareMdlWrite = DaFastIoPrepareMdlWrite;
  772. fastIoDispatch->MdlWriteComplete = DaFastIoMdlWriteComplete;
  773. fastIoDispatch->FastIoReadCompressed = DaFastIoReadCompressed;
  774. fastIoDispatch->FastIoWriteCompressed = DaFastIoWriteCompressed;
  775. fastIoDispatch->MdlReadCompleteCompressed = DaFastIoMdlReadCompleteCompressed;
  776. fastIoDispatch->MdlWriteCompleteCompressed = DaFastIoMdlWriteCompleteCompressed;
  777. fastIoDispatch->FastIoQueryOpen = DaFastIoQueryOpen;
  778. DriverObject->FastIoDispatch = fastIoDispatch;
  779. //
  780. // Setup the callbacks for the operations we receive through
  781. // the FsFilter interface.
  782. //
  783. // NOTE: You only need to register for those routines you really need
  784. // to handle. SFilter is registering for all routines simply to
  785. // give an example of how it is done.
  786. //
  787. fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof( FS_FILTER_CALLBACKS );
  788. fsFilterCallbacks.PreAcquireForSectionSynchronization = DaPreFsFilterPassThrough;
  789. fsFilterCallbacks.PostAcquireForSectionSynchronization = DaPostFsFilterPassThrough;
  790. fsFilterCallbacks.PreReleaseForSectionSynchronization = DaPreFsFilterPassThrough;
  791. fsFilterCallbacks.PostReleaseForSectionSynchronization = DaPostFsFilterPassThrough;
  792. fsFilterCallbacks.PreAcquireForCcFlush = DaPreFsFilterPassThrough;
  793. fsFilterCallbacks.PostAcquireForCcFlush = DaPostFsFilterPassThrough;
  794. fsFilterCallbacks.PreReleaseForCcFlush = DaPreFsFilterPassThrough;
  795. fsFilterCallbacks.PostReleaseForCcFlush = DaPostFsFilterPassThrough;
  796. fsFilterCallbacks.PreAcquireForModifiedPageWriter = DaPreFsFilterPassThrough;
  797. fsFilterCallbacks.PostAcquireForModifiedPageWriter = DaPostFsFilterPassThrough;
  798. fsFilterCallbacks.PreReleaseForModifiedPageWriter = DaPreFsFilterPassThrough;
  799. fsFilterCallbacks.PostReleaseForModifiedPageWriter = DaPostFsFilterPassThrough;
  800. status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject, &fsFilterCallbacks );
  801. if (!NT_SUCCESS( status )) {
  802. DriverObject->FastIoDispatch = NULL;
  803. ExFreePool( fastIoDispatch );
  804. IoDeleteDevice( gDblAttachControlDeviceObject );
  805. return status;
  806. }
  807. //
  808. // Register this driver for watching file systems coming and going. This
  809. // enumerates all existing file systems as well as new file systems as they
  810. // come and go.
  811. //
  812. status = IoRegisterFsRegistrationChange( DriverObject, DaFsNotification );
  813. if (!NT_SUCCESS( status )) {
  814. KdPrint(( "DblAttach!DriverEntry: Error registering FS change notification, status=%08x\n", status ));
  815. DriverObject->FastIoDispatch = NULL;
  816. ExFreePool( fastIoDispatch );
  817. IoDeleteDevice( gDblAttachControlDeviceObject );
  818. return status;
  819. }
  820. //
  821. // Attempt to attach to the RAWDISK file system device object since this
  822. // file system is not enumerated by IoRegisterFsRegistrationChange.
  823. //
  824. {
  825. PDEVICE_OBJECT rawDeviceObject;
  826. PFILE_OBJECT fileObject;
  827. RtlInitUnicodeString( &nameString, L"\\Device\\RawDisk" );
  828. status = IoGetDeviceObjectPointer(
  829. &nameString,
  830. FILE_READ_ATTRIBUTES,
  831. &fileObject,
  832. &rawDeviceObject );
  833. if (NT_SUCCESS( status )) {
  834. DaFsNotification( rawDeviceObject, TRUE );
  835. ObDereferenceObject( fileObject );
  836. }
  837. }
  838. //
  839. // Clear the initializing flag on the control device object since we
  840. // have now successfully initialized everything.
  841. //
  842. ClearFlag( gDblAttachControlDeviceObject->Flags, DO_DEVICE_INITIALIZING );
  843. return STATUS_SUCCESS;
  844. }
  845. #if DBG
  846. VOID
  847. DriverUnload (
  848. IN PDRIVER_OBJECT DriverObject
  849. )
  850. /*++
  851. Routine Description:
  852. This routine is called when a driver can be unloaded. This performs all of
  853. the necessary cleanup for unloading the driver from memory. Note that an
  854. error can NOT be returned from this routine.
  855. When a request is made to unload a driver the IO System will cache that
  856. information and not actually call this routine until the following states
  857. have occurred:
  858. - All device objects which belong to this filter are at the top of their
  859. respective attachment chains.
  860. - All handle counts for all device objects which belong to this filter have
  861. gone to zero.
  862. WARNING: Microsoft does not officially support the unloading of File
  863. System Filter Drivers. This is an example of how to unload
  864. your driver if you would like to use it during development.
  865. This should not be made available in production code.
  866. Arguments:
  867. DriverObject - Driver object for this module
  868. Return Value:
  869. None.
  870. --*/
  871. {
  872. PDBLATTACH_DEVEXT_HEADER devExtHdr;
  873. PFAST_IO_DISPATCH fastIoDispatch;
  874. NTSTATUS status;
  875. ULONG numDevices;
  876. ULONG i;
  877. LARGE_INTEGER interval;
  878. # define DEVOBJ_LIST_SIZE 64
  879. PDEVICE_OBJECT devList[DEVOBJ_LIST_SIZE];
  880. ASSERT(DriverObject == gDblAttachDriverObject);
  881. //
  882. // Log we are unloading
  883. //
  884. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  885. ("DblAttach!DriverUnload: Unloading driver (%p)\n",
  886. DriverObject) );
  887. //
  888. // Don't get anymore file system change notifications
  889. //
  890. IoUnregisterFsRegistrationChange( DriverObject, DaFsNotification );
  891. //
  892. // This is the loop that will go through all of the devices we are attached
  893. // to and detach from them. Since we don't know how many there are and
  894. // we don't want to allocate memory (because we can't return an error)
  895. // we will free them in chunks using a local array on the stack.
  896. //
  897. for (;;) {
  898. //
  899. // Get what device objects we can for this driver. Quit if there
  900. // are not any more.
  901. //
  902. status = IoEnumerateDeviceObjectList(
  903. DriverObject,
  904. devList,
  905. sizeof(devList),
  906. &numDevices);
  907. if (numDevices <= 0) {
  908. break;
  909. }
  910. numDevices = min( numDevices, DEVOBJ_LIST_SIZE );
  911. //
  912. // First go through the list and detach each of the devices.
  913. // Our control device object does not have a DeviceExtension and
  914. // is not attached to anything so don't detach it.
  915. //
  916. for (i=0; i < numDevices; i++) {
  917. devExtHdr = devList[i]->DeviceExtension;
  918. if (NULL != devExtHdr) {
  919. IoDetachDevice( devExtHdr->AttachedToDeviceObject );
  920. }
  921. }
  922. //
  923. // The IO Manager does not currently add a reference count to a device
  924. // object for each outstanding IRP. This means there is no way to
  925. // know if there are any outstanding IRPs on the given device.
  926. // We are going to wait for a reasonable amount of time for pending
  927. // irps to complete.
  928. //
  929. // WARNING: This does not work 100% of the time and the driver may be
  930. // unloaded before all IRPs are completed. This can easily
  931. // occur under stress situations and if a long lived IRP is
  932. // pending (like oplocks and directory change notifications).
  933. // The system will fault when this Irp actually completes.
  934. // This is a sample of how to do this during testing. This
  935. // is not recommended for production code.
  936. //
  937. interval.QuadPart = -5 * (10 * 1000 * 1000); //delay 5 seconds
  938. KeDelayExecutionThread( KernelMode, FALSE, &interval );
  939. //
  940. // Now go back through the list and delete the device objects.
  941. //
  942. for (i=0; i < numDevices; i++) {
  943. //
  944. // See if this is our control device object. If not then cleanup
  945. // the device extension. If so then clear the global pointer
  946. // that references it.
  947. //
  948. if (NULL != devList[i]->DeviceExtension) {
  949. DaCleanupMountedDevice( devList[i] );
  950. } else {
  951. ASSERT(devList[i] == gDblAttachControlDeviceObject);
  952. gDblAttachControlDeviceObject = NULL;
  953. }
  954. //
  955. // Delete the device object, remove reference counts added by
  956. // IoEnumerateDeviceObjectList. Note that the delete does
  957. // not actually occur until the reference count goes to zero.
  958. //
  959. IoDeleteDevice( devList[i] );
  960. ObDereferenceObject( devList[i] );
  961. }
  962. }
  963. //
  964. // Free our FastIO table
  965. //
  966. fastIoDispatch = DriverObject->FastIoDispatch;
  967. DriverObject->FastIoDispatch = NULL;
  968. ExFreePool( fastIoDispatch );
  969. }
  970. #endif
  971. VOID
  972. DaFsNotification (
  973. IN PDEVICE_OBJECT DeviceObject,
  974. IN BOOLEAN FsActive
  975. )
  976. /*++
  977. Routine Description:
  978. This routine is invoked whenever a file system has either registered or
  979. unregistered itself as an active file system.
  980. For the former case, this routine creates a device object and attaches it
  981. to the specified file system's device object. This allows this driver
  982. to filter all requests to that file system. Specifically we are looking
  983. for MOUNT requests so we can attach to newly mounted volumes.
  984. For the latter case, this file system's device object is located,
  985. detached, and deleted. This removes this file system as a filter for
  986. the specified file system.
  987. Arguments:
  988. DeviceObject - Pointer to the file system's device object.
  989. FsActive - Boolean indicating whether the file system has registered
  990. (TRUE) or unregistered (FALSE) itself as an active file system.
  991. Return Value:
  992. None.
  993. --*/
  994. {
  995. UNICODE_STRING name;
  996. WCHAR nameBuffer[MAX_DEVNAME_LENGTH];
  997. PAGED_CODE();
  998. //
  999. // Init local name buffer
  1000. //
  1001. RtlInitEmptyUnicodeString( &name, nameBuffer, sizeof(nameBuffer) );
  1002. DaGetBaseDeviceObjectName( DeviceObject, &name );
  1003. //
  1004. // Display the names of all the file system we are notified of
  1005. //
  1006. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  1007. ("DblAttach!DaFsNotification: %s %p \"%wZ\" (%s)\n",
  1008. (FsActive) ? "Activating file system " : "Deactivating file system",
  1009. DeviceObject,
  1010. &name,
  1011. GET_DEVICE_TYPE_NAME(DeviceObject->DeviceType)) );
  1012. //
  1013. // Handle attaching/detaching from the given file system.
  1014. //
  1015. if (FsActive) {
  1016. DaAttachToFileSystemDevice( DeviceObject, &name );
  1017. } else {
  1018. DaDetachFromFileSystemDevice( DeviceObject );
  1019. }
  1020. }
  1021. /////////////////////////////////////////////////////////////////////////////
  1022. //
  1023. // IRP Handling Routines
  1024. //
  1025. /////////////////////////////////////////////////////////////////////////////
  1026. NTSTATUS
  1027. DaPassThrough (
  1028. IN PDEVICE_OBJECT DeviceObject,
  1029. IN PIRP Irp
  1030. )
  1031. /*++
  1032. Routine Description:
  1033. This routine is the main dispatch routine for the general purpose file
  1034. system driver. It simply passes requests onto the next driver in the
  1035. stack, which is presumably a disk file system.
  1036. Arguments:
  1037. DeviceObject - Pointer to the device object for this driver.
  1038. Irp - Pointer to the request packet representing the I/O request.
  1039. Return Value:
  1040. The function value is the status of the operation.
  1041. Note:
  1042. A note to file system filter implementers:
  1043. This routine actually "passes" through the request by taking this
  1044. driver out of the IRP stack. If the driver would like to pass the
  1045. I/O request through, but then also see the result, then rather than
  1046. taking itself out of the loop it could keep itself in by copying the
  1047. caller's parameters to the next stack location and then set its own
  1048. completion routine.
  1049. Hence, instead of calling:
  1050. IoSkipCurrentIrpStackLocation( Irp );
  1051. You could instead call:
  1052. IoCopyCurrentIrpStackLocationToNext( Irp );
  1053. IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE );
  1054. This example actually NULLs out the caller's I/O completion routine, but
  1055. this driver could set its own completion routine so that it would be
  1056. notified when the request was completed (see DaCreate for an example of
  1057. this).
  1058. --*/
  1059. {
  1060. VALIDATE_IRQL();
  1061. //
  1062. // If this is for our control device object, fail the operation
  1063. //
  1064. if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) {
  1065. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  1066. Irp->IoStatus.Information = 0;
  1067. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1068. return STATUS_INVALID_DEVICE_REQUEST;
  1069. }
  1070. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1071. //
  1072. // Get this driver out of the driver stack and get to the next driver as
  1073. // quickly as possible.
  1074. //
  1075. IoSkipCurrentIrpStackLocation( Irp );
  1076. //
  1077. // Call the appropriate file system driver with the request.
  1078. //
  1079. return IoCallDriver( ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  1080. }
  1081. VOID
  1082. DaDisplayCreateFileName (
  1083. IN PIRP Irp
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. This function is called from DaCreate and will display the name of the
  1088. file being created. This is in a subroutine so that the local name buffer
  1089. on the stack (in nameControl) is not on the stack when we call down to
  1090. the file system for normal operations.
  1091. Arguments:
  1092. Irp - Pointer to the I/O Request Packet that represents the operation.
  1093. Return Value:
  1094. None.
  1095. --*/
  1096. {
  1097. PIO_STACK_LOCATION irpSp;
  1098. PUNICODE_STRING name;
  1099. GET_NAME_CONTROL nameControl;
  1100. //
  1101. // Get current IRP stack
  1102. //
  1103. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1104. //
  1105. // Get the name of this file object
  1106. //
  1107. name = DaGetFileName( irpSp->FileObject,
  1108. Irp->IoStatus.Status,
  1109. &nameControl );
  1110. //
  1111. // Display the name
  1112. //
  1113. if (irpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID) {
  1114. DA_LOG_PRINT( DADEBUG_DISPLAY_CREATE_NAMES,
  1115. ("DblAttach!DaDisplayCreateFileName(%p): Opened %08x:%08x %wZ (FID)\n",
  1116. irpSp->DeviceObject,
  1117. Irp->IoStatus.Status,
  1118. Irp->IoStatus.Information,
  1119. name) );
  1120. } else {
  1121. DA_LOG_PRINT( DADEBUG_DISPLAY_CREATE_NAMES,
  1122. ("DblAttach!DaDisplayCreateFileName: Opened %08x:%08x %wZ\n",
  1123. Irp->IoStatus.Status,
  1124. Irp->IoStatus.Information,
  1125. name) );
  1126. }
  1127. //
  1128. // Cleanup from getting the name
  1129. //
  1130. DaGetFileNameCleanup( &nameControl );
  1131. }
  1132. NTSTATUS
  1133. DaCreate (
  1134. IN PDEVICE_OBJECT DeviceObject,
  1135. IN PIRP Irp
  1136. )
  1137. /*++
  1138. Routine Description:
  1139. This function filters create/open operations. It simply establishes an
  1140. I/O completion routine to be invoked if the operation was successful.
  1141. Arguments:
  1142. DeviceObject - Pointer to the target device object of the create/open.
  1143. Irp - Pointer to the I/O Request Packet that represents the operation.
  1144. Return Value:
  1145. The function value is the status of the call to the file system's entry
  1146. point.
  1147. --*/
  1148. {
  1149. PDBLATTACH_DEVEXT_HEADER devExtHdr;
  1150. PAGED_CODE();
  1151. VALIDATE_IRQL();
  1152. //
  1153. // If this is for our control device object, return success
  1154. //
  1155. if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) {
  1156. //
  1157. // Allow users to open the device that represents our driver.
  1158. //
  1159. Irp->IoStatus.Status = STATUS_SUCCESS;
  1160. Irp->IoStatus.Information = FILE_OPENED;
  1161. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1162. return STATUS_SUCCESS;
  1163. }
  1164. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1165. devExtHdr = DeviceObject->DeviceExtension;
  1166. switch (devExtHdr->ExtType) {
  1167. case FsVolumeLower:
  1168. return DaCreateLower( DeviceObject->DeviceExtension, Irp );
  1169. case FsVolumeUpper:
  1170. return DaCreateUpper( DeviceObject->DeviceExtension, Irp );
  1171. case FsControlDeviceObject:
  1172. default:
  1173. IoSkipCurrentIrpStackLocation( Irp );
  1174. return IoCallDriver( devExtHdr->AttachedToDeviceObject, Irp );
  1175. }
  1176. #if 0
  1177. //
  1178. // If debugging is enabled, do the processing required to see the packet
  1179. // upon its completion. Otherwise, let the request go with no further
  1180. // processing.
  1181. //
  1182. if (!FlagOn( DaDebug, DADEBUG_DO_CREATE_COMPLETION |
  1183. DADEBUG_GET_CREATE_NAMES |
  1184. DADEBUG_DISPLAY_CREATE_NAMES )) {
  1185. //
  1186. // Don't put us on the stack then call the next driver
  1187. //
  1188. IoSkipCurrentIrpStackLocation( Irp );
  1189. return IoCallDriver( ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  1190. } else {
  1191. KEVENT waitEvent;
  1192. //
  1193. // Initialize an event to wait for the completion routine to occur
  1194. //
  1195. KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
  1196. //
  1197. // Copy the stack and set our Completion routine
  1198. //
  1199. IoCopyCurrentIrpStackLocationToNext( Irp );
  1200. IoSetCompletionRoutine( Irp,
  1201. DaCreateCompletion,
  1202. &waitEvent,
  1203. TRUE,
  1204. TRUE,
  1205. TRUE );
  1206. //
  1207. // Call the next driver in the stack.
  1208. //
  1209. status = IoCallDriver( ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  1210. //
  1211. // Wait for the completion routine to be called
  1212. //
  1213. if (STATUS_PENDING == status) {
  1214. NTSTATUS localStatus;
  1215. localStatus = KeWaitForSingleObject( &waitEvent,
  1216. Executive,
  1217. KernelMode,
  1218. FALSE,
  1219. NULL );
  1220. ASSERT(STATUS_SUCCESS == localStatus);
  1221. }
  1222. //
  1223. // Verify the IoCompleteRequest was called
  1224. //
  1225. ASSERT(KeReadStateEvent(&waitEvent) ||
  1226. !NT_SUCCESS(Irp->IoStatus.Status));
  1227. //
  1228. // Retrieve and display the filename if requested
  1229. //
  1230. if (FlagOn( DaDebug, DADEBUG_GET_CREATE_NAMES|DADEBUG_DISPLAY_CREATE_NAMES )) {
  1231. DaDisplayCreateFileName( Irp );
  1232. }
  1233. //
  1234. // Save the status and continue processing the IRP
  1235. //
  1236. status = Irp->IoStatus.Status;
  1237. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1238. return status;
  1239. }
  1240. #endif
  1241. }
  1242. NTSTATUS
  1243. DaCreateUpper (
  1244. IN PDBLATTACH_VDO_EXTENSION VdoExt,
  1245. IN PIRP Irp
  1246. )
  1247. {
  1248. PIO_STACK_LOCATION irpSp;
  1249. PFILE_OBJECT fileObject;
  1250. KEVENT waitEvent;
  1251. NTSTATUS status;
  1252. ASSERT( VdoExt->ExtType == FsVolumeUpper );
  1253. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1254. fileObject = irpSp->FileObject;
  1255. if (DaMonitorFile( fileObject, VdoExt )) {
  1256. KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
  1257. IoCopyCurrentIrpStackLocationToNext( Irp );
  1258. IoSetCompletionRoutine( Irp,
  1259. DaCreateCompletion,
  1260. &waitEvent,
  1261. TRUE,
  1262. TRUE,
  1263. TRUE );
  1264. //
  1265. // Call the next driver in the stack.
  1266. //
  1267. status = IoCallDriver( VdoExt->AttachedToDeviceObject, Irp );
  1268. //
  1269. // Wait for the completion routine to be called
  1270. //
  1271. if (STATUS_PENDING == status) {
  1272. NTSTATUS localStatus;
  1273. localStatus = KeWaitForSingleObject( &waitEvent,
  1274. Executive,
  1275. KernelMode,
  1276. FALSE,
  1277. NULL );
  1278. ASSERT(STATUS_SUCCESS == localStatus);
  1279. }
  1280. //
  1281. // Verify the IoCompleteRequest was called
  1282. //
  1283. ASSERT(KeReadStateEvent(&waitEvent) ||
  1284. !NT_SUCCESS(Irp->IoStatus.Status));
  1285. status = Irp->IoStatus.Status;
  1286. if (Irp->IoStatus.Status == STATUS_UNSUCCESSFUL) {
  1287. irpSp->Parameters.Create.ShareAccess = FILE_SHARE_READ;
  1288. KeClearEvent( &waitEvent );
  1289. IoCopyCurrentIrpStackLocationToNext( Irp );
  1290. IoSetCompletionRoutine( Irp,
  1291. DaCreateCompletion,
  1292. &waitEvent,
  1293. TRUE,
  1294. TRUE,
  1295. TRUE );
  1296. //
  1297. // Call the next driver in the stack.
  1298. //
  1299. status = IoCallDriver( VdoExt->AttachedToDeviceObject, Irp );
  1300. //
  1301. // Wait for the completion routine to be called
  1302. //
  1303. if (STATUS_PENDING == status) {
  1304. NTSTATUS localStatus;
  1305. localStatus = KeWaitForSingleObject( &waitEvent,
  1306. Executive,
  1307. KernelMode,
  1308. FALSE,
  1309. NULL );
  1310. ASSERT(STATUS_SUCCESS == localStatus);
  1311. }
  1312. status = Irp->IoStatus.Status;
  1313. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1314. return status;
  1315. } else {
  1316. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1317. return status;
  1318. }
  1319. } else {
  1320. IoSkipCurrentIrpStackLocation( Irp );
  1321. return IoCallDriver( VdoExt->AttachedToDeviceObject, Irp );
  1322. }
  1323. }
  1324. NTSTATUS
  1325. DaCreateLower (
  1326. IN PDBLATTACH_VDO_EXTENSION VdoExt,
  1327. IN PIRP Irp
  1328. )
  1329. {
  1330. PIO_STACK_LOCATION irpSp;
  1331. PFILE_OBJECT fileObject;
  1332. KEVENT waitEvent;
  1333. NTSTATUS status;
  1334. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1335. fileObject = irpSp->FileObject;
  1336. ASSERT( VdoExt->ExtType == FsVolumeLower );
  1337. if (irpSp->Parameters.Create.ShareAccess != FILE_SHARE_READ &&
  1338. DaMonitorFile( fileObject, VdoExt )) {
  1339. KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
  1340. IoCopyCurrentIrpStackLocationToNext( Irp );
  1341. IoSetCompletionRoutine( Irp,
  1342. DaCreateCompletion,
  1343. &waitEvent,
  1344. TRUE,
  1345. TRUE,
  1346. TRUE );
  1347. //
  1348. // Call the next driver in the stack.
  1349. //
  1350. status = IoCallDriver( VdoExt->AttachedToDeviceObject, Irp );
  1351. //
  1352. // Wait for the completion routine to be called
  1353. //
  1354. if (STATUS_PENDING == status) {
  1355. NTSTATUS localStatus;
  1356. localStatus = KeWaitForSingleObject( &waitEvent,
  1357. Executive,
  1358. KernelMode,
  1359. FALSE,
  1360. NULL );
  1361. ASSERT(STATUS_SUCCESS == localStatus);
  1362. }
  1363. //
  1364. // Verify the IoCompleteRequest was called
  1365. //
  1366. ASSERT(KeReadStateEvent( &waitEvent ) || !NT_SUCCESS(Irp->IoStatus.Status));
  1367. status = Irp->IoStatus.Status;
  1368. if (NT_SUCCESS( status ) && status != STATUS_REPARSE) {
  1369. //
  1370. // Cancel this create and fail this open.
  1371. //
  1372. IoCancelFileOpen( VdoExt->AttachedToDeviceObject, irpSp->FileObject );
  1373. Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
  1374. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1375. return status;
  1376. } else {
  1377. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1378. return status;
  1379. }
  1380. } else {
  1381. IoSkipCurrentIrpStackLocation( Irp );
  1382. return IoCallDriver( VdoExt->AttachedToDeviceObject, Irp );
  1383. }
  1384. }
  1385. NTSTATUS
  1386. DaCreateCompletion (
  1387. IN PDEVICE_OBJECT DeviceObject,
  1388. IN PIRP Irp,
  1389. IN PVOID Context
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. This function is the create/open completion routine for this filter
  1394. file system driver. If debugging is enabled, then this function prints
  1395. the name of the file that was successfully opened/created by the file
  1396. system as a result of the specified I/O request.
  1397. Arguments:
  1398. DeviceObject - Pointer to the device on which the file was created.
  1399. Irp - Pointer to the I/O Request Packet the represents the operation.
  1400. Context - This driver's context parameter - unused;
  1401. Return Value:
  1402. The function value is STATUS_SUCCESS.
  1403. --*/
  1404. {
  1405. PKEVENT event = Context;
  1406. UNREFERENCED_PARAMETER( DeviceObject );
  1407. UNREFERENCED_PARAMETER( Irp );
  1408. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1409. KeSetEvent(event, IO_NO_INCREMENT, FALSE);
  1410. return STATUS_MORE_PROCESSING_REQUIRED;
  1411. }
  1412. NTSTATUS
  1413. DaCleanupClose (
  1414. IN PDEVICE_OBJECT DeviceObject,
  1415. IN PIRP Irp
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. This routine is invoked whenever a cleanup or a close request is to be
  1420. processed.
  1421. Arguments:
  1422. DeviceObject - Pointer to the device object for this driver.
  1423. Irp - Pointer to the request packet representing the I/O request.
  1424. Return Value:
  1425. The function value is the status of the operation.
  1426. Note:
  1427. See notes for DaPassThrough for this routine.
  1428. --*/
  1429. {
  1430. PAGED_CODE();
  1431. VALIDATE_IRQL();
  1432. //
  1433. // If this is for our control device object, return success
  1434. //
  1435. if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) {
  1436. Irp->IoStatus.Status = STATUS_SUCCESS;
  1437. Irp->IoStatus.Information = 0;
  1438. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1439. return STATUS_SUCCESS;
  1440. }
  1441. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1442. //
  1443. // Get this driver out of the driver stack and get to the next driver as
  1444. // quickly as possible.
  1445. //
  1446. IoSkipCurrentIrpStackLocation( Irp );
  1447. //
  1448. // Now call the appropriate file system driver with the request.
  1449. //
  1450. return IoCallDriver( ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  1451. }
  1452. NTSTATUS
  1453. DaFsControl (
  1454. IN PDEVICE_OBJECT DeviceObject,
  1455. IN PIRP Irp
  1456. )
  1457. /*++
  1458. Routine Description:
  1459. This routine is invoked whenever an I/O Request Packet (IRP) w/a major
  1460. function code of IRP_MJ_FILE_SYSTEM_CONTROL is encountered. For most
  1461. IRPs of this type, the packet is simply passed through. However, for
  1462. some requests, special processing is required.
  1463. Arguments:
  1464. DeviceObject - Pointer to the device object for this driver.
  1465. Irp - Pointer to the request packet representing the I/O request.
  1466. Return Value:
  1467. The function value is the status of the operation.
  1468. --*/
  1469. {
  1470. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  1471. PAGED_CODE();
  1472. VALIDATE_IRQL();
  1473. //
  1474. // If this is for our control device object, fail the operation
  1475. //
  1476. if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) {
  1477. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  1478. Irp->IoStatus.Information = 0;
  1479. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1480. return STATUS_INVALID_DEVICE_REQUEST;
  1481. }
  1482. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1483. //
  1484. // Process the minor function code.
  1485. //
  1486. switch (irpSp->MinorFunction) {
  1487. case IRP_MN_MOUNT_VOLUME:
  1488. return DaFsControlMountVolume( DeviceObject, Irp );
  1489. case IRP_MN_LOAD_FILE_SYSTEM:
  1490. return DaFsControlLoadFileSystem( DeviceObject, Irp );
  1491. case IRP_MN_USER_FS_REQUEST:
  1492. {
  1493. switch (irpSp->Parameters.FileSystemControl.FsControlCode) {
  1494. case FSCTL_DISMOUNT_VOLUME:
  1495. {
  1496. PDBLATTACH_VDO_EXTENSION devExt = DeviceObject->DeviceExtension;
  1497. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  1498. ("DblAttach!DaFsControl: Dismounting volume %p \"%wZ\"\n",
  1499. devExt->AttachedToDeviceObject,
  1500. &devExt->SharedExt->DeviceName) );
  1501. break;
  1502. }
  1503. }
  1504. break;
  1505. }
  1506. }
  1507. //
  1508. // Pass all other file system control requests through.
  1509. //
  1510. IoSkipCurrentIrpStackLocation( Irp );
  1511. return IoCallDriver( ((PDBLATTACH_DEVEXT_HEADER)DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  1512. }
  1513. NTSTATUS
  1514. DaFsControlCompletion (
  1515. IN PDEVICE_OBJECT DeviceObject,
  1516. IN PIRP Irp,
  1517. IN PVOID Context
  1518. )
  1519. /*++
  1520. Routine Description:
  1521. This routine is invoked for the completion of an FsControl request. It
  1522. signals an event used to re-sync back to the dispatch routine.
  1523. Arguments:
  1524. DeviceObject - Pointer to this driver's device object that was attached to
  1525. the file system device object
  1526. Irp - Pointer to the IRP that was just completed.
  1527. Context - Pointer to the event to signal
  1528. --*/
  1529. {
  1530. UNREFERENCED_PARAMETER( DeviceObject );
  1531. UNREFERENCED_PARAMETER( Irp );
  1532. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1533. ASSERT(Context != NULL);
  1534. KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
  1535. return STATUS_MORE_PROCESSING_REQUIRED;
  1536. }
  1537. NTSTATUS
  1538. DaFsControlMountVolume (
  1539. IN PDEVICE_OBJECT DeviceObject,
  1540. IN PIRP Irp
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. This processes a MOUNT VOLUME request.
  1545. NOTE: The device object in the MountVolume parameters points
  1546. to the top of the storage stack and should not be used.
  1547. Arguments:
  1548. DeviceObject - Pointer to the device object for this driver.
  1549. Irp - Pointer to the request packet representing the I/O request.
  1550. Return Value:
  1551. The status of the operation.
  1552. --*/
  1553. {
  1554. PDBLATTACH_CDO_EXTENSION devExt = DeviceObject->DeviceExtension;
  1555. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  1556. PDEVICE_OBJECT vdoArray[ VDO_ARRAY_SIZE ];
  1557. PDBLATTACH_VDO_EXTENSION newDevExt;
  1558. PDBLATTACH_SHARED_VDO_EXTENSION sharedDevExt;
  1559. PDEVICE_OBJECT attachedDeviceObject;
  1560. PVPB vpb;
  1561. KEVENT waitEvent;
  1562. NTSTATUS status;
  1563. PAGED_CODE();
  1564. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1565. ASSERT(IS_DESIRED_DEVICE_TYPE(DeviceObject->DeviceType));
  1566. //
  1567. // This is a mount request. Create a device object that can be
  1568. // attached to the file system's volume device object if this request
  1569. // is successful. We allocate this memory now since we can not return
  1570. // an error in the completion routine.
  1571. //
  1572. // Since the device object we are going to attach to has not yet been
  1573. // created (it is created by the base file system) we are going to use
  1574. // the type of the file system control device object. We are assuming
  1575. // that the file system control device object will have the same type
  1576. // as the volume device objects associated with it.
  1577. //
  1578. status = DaCreateVolumeDeviceObjects( DeviceObject->DeviceType,
  1579. VDO_ARRAY_SIZE,
  1580. vdoArray );
  1581. if (!NT_SUCCESS( status )) {
  1582. //
  1583. // If we can not attach to the volume, then don't allow the volume
  1584. // to be mounted.
  1585. //
  1586. KdPrint(( "DblAttach!DaFsControlMountVolume: Error creating volume device object, status=%08x\n", status ));
  1587. Irp->IoStatus.Information = 0;
  1588. Irp->IoStatus.Status = status;
  1589. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1590. return status;
  1591. }
  1592. //
  1593. // We need to save the RealDevice object pointed to by the vpb
  1594. // parameter because this vpb may be changed by the underlying
  1595. // file system. Both FAT and CDFS may change the VPB address if
  1596. // the volume being mounted is one they recognize from a previous
  1597. // mount.
  1598. //
  1599. newDevExt = vdoArray[0]->DeviceExtension;
  1600. sharedDevExt = newDevExt->SharedExt;
  1601. sharedDevExt->DiskDeviceObject = irpSp->Parameters.MountVolume.Vpb->RealDevice;
  1602. //
  1603. // Get the name of this device
  1604. //
  1605. RtlInitEmptyUnicodeString( &sharedDevExt->DeviceName,
  1606. sharedDevExt->DeviceNameBuffer,
  1607. sizeof(sharedDevExt->DeviceNameBuffer) );
  1608. DaGetObjectName( sharedDevExt->DiskDeviceObject,
  1609. &sharedDevExt->DeviceName );
  1610. //
  1611. // Initialize our completion routine
  1612. //
  1613. KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
  1614. IoCopyCurrentIrpStackLocationToNext( Irp );
  1615. IoSetCompletionRoutine( Irp,
  1616. DaFsControlCompletion,
  1617. &waitEvent, //context parameter
  1618. TRUE,
  1619. TRUE,
  1620. TRUE );
  1621. //
  1622. // Call the driver
  1623. //
  1624. status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
  1625. //
  1626. // Wait for the completion routine to be called.
  1627. // Note: Once we get to this point we can no longer fail this operation.
  1628. //
  1629. if (STATUS_PENDING == status) {
  1630. NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);
  1631. ASSERT(STATUS_SUCCESS == localStatus);
  1632. }
  1633. //
  1634. // Verify the IoCompleteRequest was called
  1635. //
  1636. ASSERT(KeReadStateEvent(&waitEvent) ||
  1637. !NT_SUCCESS(Irp->IoStatus.Status));
  1638. //
  1639. // Get the correct VPB from the real device object saved in our
  1640. // device extension. We do this because the VPB in the IRP stack
  1641. // may not be the correct VPB when we get here. The underlying
  1642. // file system may change VPBs if it detects a volume it has
  1643. // mounted previously.
  1644. //
  1645. vpb = sharedDevExt->DiskDeviceObject->Vpb;
  1646. //
  1647. // Display a message when we detect that the VPB for the given
  1648. // device object has changed.
  1649. //
  1650. if (vpb != irpSp->Parameters.MountVolume.Vpb) {
  1651. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  1652. ("DblAttach!DaFsControlMountVolume: VPB in IRP stack changed %p IRPVPB=%p VPB=%p\n",
  1653. vpb->DeviceObject,
  1654. irpSp->Parameters.MountVolume.Vpb,
  1655. vpb) );
  1656. }
  1657. //
  1658. // See if the mount was successful.
  1659. //
  1660. if (NT_SUCCESS( Irp->IoStatus.Status )) {
  1661. //
  1662. // Acquire lock so we can atomically test if we area already attached
  1663. // and if not, then attach. This prevents a double attach race
  1664. // condition.
  1665. //
  1666. ExAcquireFastMutex( &gDblAttachLock );
  1667. //
  1668. // The mount succeeded. If we are not already attached, attach to the
  1669. // device object. Note: one reason we could already be attached is
  1670. // if the underlying file system revived a previous mount.
  1671. //
  1672. if (!DaIsAttachedToDevice( vpb->DeviceObject, &attachedDeviceObject )) {
  1673. //
  1674. // Attach to the new mounted volume. The file system device
  1675. // object that was just mounted is pointed to by the VPB.
  1676. //
  1677. status = DaAttachToMountedDevice( vpb->DeviceObject,
  1678. VDO_ARRAY_SIZE,
  1679. vdoArray );
  1680. if (!NT_SUCCESS( status )) {
  1681. //
  1682. // The attachment failed, cleanup. Since we are in the
  1683. // post-mount phase, we can not fail this operation.
  1684. // We simply won't be attached. The only reason this should
  1685. // ever happen at this point is if somebody already started
  1686. // dismounting the volume therefore not attaching should
  1687. // not be a problem.
  1688. //
  1689. DaDeleteMountedDevices( VDO_ARRAY_SIZE, vdoArray );
  1690. }
  1691. } else {
  1692. //
  1693. // We were already attached, handle it
  1694. //
  1695. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  1696. ("DblAttach!DaFsControlMountVolume Mount volume failure for %p \"%wZ\", already attached\n",
  1697. ((attachedDeviceObject != NULL) ?
  1698. ((PDBLATTACH_DEVEXT_HEADER)attachedDeviceObject->DeviceExtension)->AttachedToDeviceObject :
  1699. NULL),
  1700. &newDevExt->SharedExt->DeviceName) );
  1701. //
  1702. // Cleanup and delete the device object we created
  1703. //
  1704. DaDeleteMountedDevices( VDO_ARRAY_SIZE, vdoArray );
  1705. }
  1706. //
  1707. // Release the lock
  1708. //
  1709. ExReleaseFastMutex( &gDblAttachLock );
  1710. } else {
  1711. //
  1712. // The mount request failed, handle it.
  1713. //
  1714. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  1715. ("DblAttach!DaFsControlMountVolume: Mount volume failure for %p \"%wZ\", status=%08x\n",
  1716. DeviceObject,
  1717. &newDevExt->SharedExt->DeviceName,
  1718. Irp->IoStatus.Status) );
  1719. //
  1720. // Cleanup and delete the device object we created
  1721. //
  1722. DaDeleteMountedDevices( VDO_ARRAY_SIZE, vdoArray );
  1723. }
  1724. //
  1725. // Complete the request.
  1726. // NOTE: We must save the status before completing because after
  1727. // completing the IRP we can not longer access it (it might be
  1728. // freed).
  1729. //
  1730. status = Irp->IoStatus.Status;
  1731. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1732. return status;
  1733. }
  1734. NTSTATUS
  1735. DaFsControlLoadFileSystem (
  1736. IN PDEVICE_OBJECT DeviceObject,
  1737. IN PIRP Irp
  1738. )
  1739. /*++
  1740. Routine Description:
  1741. This routine is invoked whenever an I/O Request Packet (IRP) w/a major
  1742. function code of IRP_MJ_FILE_SYSTEM_CONTROL is encountered. For most
  1743. IRPs of this type, the packet is simply passed through. However, for
  1744. some requests, special processing is required.
  1745. Arguments:
  1746. DeviceObject - Pointer to the device object for this driver.
  1747. Irp - Pointer to the request packet representing the I/O request.
  1748. Return Value:
  1749. The function value is the status of the operation.
  1750. --*/
  1751. {
  1752. PDBLATTACH_CDO_EXTENSION devExt = DeviceObject->DeviceExtension;
  1753. KEVENT waitEvent;
  1754. NTSTATUS status;
  1755. PAGED_CODE();
  1756. ASSERT( IS_FSCDO_DEVICE_OBJECT( DeviceObject ) );
  1757. //
  1758. // This is a "load file system" request being sent to a file system
  1759. // recognizer device object. This IRP_MN code is only sent to
  1760. // file system recognizers.
  1761. //
  1762. // NOTE: Since we no longer are attaching to the standard Microsoft file
  1763. // system recognizers we will normally never execute this code.
  1764. // However, there might be 3rd party file systems which have their
  1765. // own recognizer which may still trigger this IRP.
  1766. //
  1767. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  1768. ("DblAttach!DaFscontrolLoadFileSystem: Loading File System, Detaching from \"%wZ\"\n",
  1769. &devExt->DeviceName) );
  1770. //
  1771. // Set a completion routine so we can delete the device object when
  1772. // the load is complete.
  1773. //
  1774. KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
  1775. IoCopyCurrentIrpStackLocationToNext( Irp );
  1776. IoSetCompletionRoutine( Irp,
  1777. DaFsControlCompletion,
  1778. &waitEvent,
  1779. TRUE,
  1780. TRUE,
  1781. TRUE );
  1782. //
  1783. // Detach from the file system recognizer device object.
  1784. //
  1785. IoDetachDevice( devExt->AttachedToDeviceObject );
  1786. //
  1787. // Call the driver
  1788. //
  1789. status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
  1790. //
  1791. // Wait for the completion routine to be called
  1792. //
  1793. if (STATUS_PENDING == status) {
  1794. NTSTATUS localStatus = KeWaitForSingleObject( &waitEvent,
  1795. Executive,
  1796. KernelMode,
  1797. FALSE,
  1798. NULL );
  1799. ASSERT(STATUS_SUCCESS == localStatus);
  1800. }
  1801. //
  1802. // Verify the IoCompleteRequest was called
  1803. //
  1804. ASSERT(KeReadStateEvent(&waitEvent) ||
  1805. !NT_SUCCESS(Irp->IoStatus.Status));
  1806. //
  1807. // Display the name if requested
  1808. //
  1809. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  1810. ("DblAttach!DaFsControlLoadFileSystem: Detaching from recognizer %p \"%wZ\", status=%08x\n",
  1811. DeviceObject,
  1812. &devExt->DeviceName,
  1813. Irp->IoStatus.Status) );
  1814. //
  1815. // Check status of the operation
  1816. //
  1817. if (!NT_SUCCESS( Irp->IoStatus.Status ) &&
  1818. (Irp->IoStatus.Status != STATUS_IMAGE_ALREADY_LOADED)) {
  1819. //
  1820. // The load was not successful. Simply reattach to the recognizer
  1821. // driver in case it ever figures out how to get the driver loaded
  1822. // on a subsequent call. There is not a lot we can do if this
  1823. // reattach fails.
  1824. //
  1825. IoAttachDeviceToDeviceStackSafe( DeviceObject,
  1826. devExt->AttachedToDeviceObject,
  1827. &devExt->AttachedToDeviceObject );
  1828. ASSERT(devExt->AttachedToDeviceObject != NULL);
  1829. } else {
  1830. //
  1831. // The load was successful, delete the Device object
  1832. //
  1833. IoDeleteDevice( DeviceObject );
  1834. }
  1835. //
  1836. // Continue processing the operation
  1837. //
  1838. status = Irp->IoStatus.Status;
  1839. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1840. return status;
  1841. }
  1842. /////////////////////////////////////////////////////////////////////////////
  1843. //
  1844. // FastIO Handling routines
  1845. //
  1846. /////////////////////////////////////////////////////////////////////////////
  1847. BOOLEAN
  1848. DaFastIoCheckIfPossible (
  1849. IN PFILE_OBJECT FileObject,
  1850. IN PLARGE_INTEGER FileOffset,
  1851. IN ULONG Length,
  1852. IN BOOLEAN Wait,
  1853. IN ULONG LockKey,
  1854. IN BOOLEAN CheckForReadOperation,
  1855. OUT PIO_STATUS_BLOCK IoStatus,
  1856. IN PDEVICE_OBJECT DeviceObject
  1857. )
  1858. /*++
  1859. Routine Description:
  1860. This routine is the fast I/O "pass through" routine for checking to see
  1861. whether fast I/O is possible for this file.
  1862. This function simply invokes the file system's corresponding routine, or
  1863. returns FALSE if the file system does not implement the function.
  1864. Arguments:
  1865. FileObject - Pointer to the file object to be operated on.
  1866. FileOffset - Byte offset in the file for the operation.
  1867. Length - Length of the operation to be performed.
  1868. Wait - Indicates whether or not the caller is willing to wait if the
  1869. appropriate locks, etc. cannot be acquired
  1870. LockKey - Provides the caller's key for file locks.
  1871. CheckForReadOperation - Indicates whether the caller is checking for a
  1872. read (TRUE) or a write operation.
  1873. IoStatus - Pointer to a variable to receive the I/O status of the
  1874. operation.
  1875. DeviceObject - Pointer to this driver's device object, the device on
  1876. which the operation is to occur.
  1877. Return Value:
  1878. The function value is TRUE or FALSE based on whether or not fast I/O
  1879. is possible for this file.
  1880. --*/
  1881. {
  1882. PDEVICE_OBJECT nextDeviceObject;
  1883. PFAST_IO_DISPATCH fastIoDispatch;
  1884. PAGED_CODE();
  1885. VALIDATE_IRQL();
  1886. if (DeviceObject->DeviceExtension) {
  1887. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1888. //
  1889. // Pass through logic for this type of Fast I/O
  1890. //
  1891. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  1892. ASSERT(nextDeviceObject);
  1893. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  1894. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoCheckIfPossible )) {
  1895. return (fastIoDispatch->FastIoCheckIfPossible)(
  1896. FileObject,
  1897. FileOffset,
  1898. Length,
  1899. Wait,
  1900. LockKey,
  1901. CheckForReadOperation,
  1902. IoStatus,
  1903. nextDeviceObject );
  1904. }
  1905. }
  1906. return FALSE;
  1907. }
  1908. BOOLEAN
  1909. DaFastIoRead (
  1910. IN PFILE_OBJECT FileObject,
  1911. IN PLARGE_INTEGER FileOffset,
  1912. IN ULONG Length,
  1913. IN BOOLEAN Wait,
  1914. IN ULONG LockKey,
  1915. OUT PVOID Buffer,
  1916. OUT PIO_STATUS_BLOCK IoStatus,
  1917. IN PDEVICE_OBJECT DeviceObject
  1918. )
  1919. /*++
  1920. Routine Description:
  1921. This routine is the fast I/O "pass through" routine for reading from a
  1922. file.
  1923. This function simply invokes the file system's corresponding routine, or
  1924. returns FALSE if the file system does not implement the function.
  1925. Arguments:
  1926. FileObject - Pointer to the file object to be read.
  1927. FileOffset - Byte offset in the file of the read.
  1928. Length - Length of the read operation to be performed.
  1929. Wait - Indicates whether or not the caller is willing to wait if the
  1930. appropriate locks, etc. cannot be acquired
  1931. LockKey - Provides the caller's key for file locks.
  1932. Buffer - Pointer to the caller's buffer to receive the data read.
  1933. IoStatus - Pointer to a variable to receive the I/O status of the
  1934. operation.
  1935. DeviceObject - Pointer to this driver's device object, the device on
  1936. which the operation is to occur.
  1937. Return Value:
  1938. The function value is TRUE or FALSE based on whether or not fast I/O
  1939. is possible for this file.
  1940. --*/
  1941. {
  1942. PDEVICE_OBJECT nextDeviceObject;
  1943. PFAST_IO_DISPATCH fastIoDispatch;
  1944. PAGED_CODE();
  1945. VALIDATE_IRQL();
  1946. if (DeviceObject->DeviceExtension) {
  1947. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  1948. //
  1949. // Pass through logic for this type of Fast I/O
  1950. //
  1951. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  1952. ASSERT(nextDeviceObject);
  1953. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  1954. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoRead )) {
  1955. return (fastIoDispatch->FastIoRead)(
  1956. FileObject,
  1957. FileOffset,
  1958. Length,
  1959. Wait,
  1960. LockKey,
  1961. Buffer,
  1962. IoStatus,
  1963. nextDeviceObject );
  1964. }
  1965. }
  1966. return FALSE;
  1967. }
  1968. BOOLEAN
  1969. DaFastIoWrite (
  1970. IN PFILE_OBJECT FileObject,
  1971. IN PLARGE_INTEGER FileOffset,
  1972. IN ULONG Length,
  1973. IN BOOLEAN Wait,
  1974. IN ULONG LockKey,
  1975. IN PVOID Buffer,
  1976. OUT PIO_STATUS_BLOCK IoStatus,
  1977. IN PDEVICE_OBJECT DeviceObject
  1978. )
  1979. /*++
  1980. Routine Description:
  1981. This routine is the fast I/O "pass through" routine for writing to a
  1982. file.
  1983. This function simply invokes the file system's corresponding routine, or
  1984. returns FALSE if the file system does not implement the function.
  1985. Arguments:
  1986. FileObject - Pointer to the file object to be written.
  1987. FileOffset - Byte offset in the file of the write operation.
  1988. Length - Length of the write operation to be performed.
  1989. Wait - Indicates whether or not the caller is willing to wait if the
  1990. appropriate locks, etc. cannot be acquired
  1991. LockKey - Provides the caller's key for file locks.
  1992. Buffer - Pointer to the caller's buffer that contains the data to be
  1993. written.
  1994. IoStatus - Pointer to a variable to receive the I/O status of the
  1995. operation.
  1996. DeviceObject - Pointer to this driver's device object, the device on
  1997. which the operation is to occur.
  1998. Return Value:
  1999. The function value is TRUE or FALSE based on whether or not fast I/O
  2000. is possible for this file.
  2001. --*/
  2002. {
  2003. PDEVICE_OBJECT nextDeviceObject;
  2004. PFAST_IO_DISPATCH fastIoDispatch;
  2005. PAGED_CODE();
  2006. VALIDATE_IRQL();
  2007. if (DeviceObject->DeviceExtension) {
  2008. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2009. //
  2010. // Pass through logic for this type of Fast I/O
  2011. //
  2012. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2013. ASSERT(nextDeviceObject);
  2014. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2015. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWrite )) {
  2016. return (fastIoDispatch->FastIoWrite)(
  2017. FileObject,
  2018. FileOffset,
  2019. Length,
  2020. Wait,
  2021. LockKey,
  2022. Buffer,
  2023. IoStatus,
  2024. nextDeviceObject );
  2025. }
  2026. }
  2027. return FALSE;
  2028. }
  2029. BOOLEAN
  2030. DaFastIoQueryBasicInfo (
  2031. IN PFILE_OBJECT FileObject,
  2032. IN BOOLEAN Wait,
  2033. OUT PFILE_BASIC_INFORMATION Buffer,
  2034. OUT PIO_STATUS_BLOCK IoStatus,
  2035. IN PDEVICE_OBJECT DeviceObject
  2036. )
  2037. /*++
  2038. Routine Description:
  2039. This routine is the fast I/O "pass through" routine for querying basic
  2040. information about the file.
  2041. This function simply invokes the file system's corresponding routine, or
  2042. returns FALSE if the file system does not implement the function.
  2043. Arguments:
  2044. FileObject - Pointer to the file object to be queried.
  2045. Wait - Indicates whether or not the caller is willing to wait if the
  2046. appropriate locks, etc. cannot be acquired
  2047. Buffer - Pointer to the caller's buffer to receive the information about
  2048. the file.
  2049. IoStatus - Pointer to a variable to receive the I/O status of the
  2050. operation.
  2051. DeviceObject - Pointer to this driver's device object, the device on
  2052. which the operation is to occur.
  2053. Return Value:
  2054. The function value is TRUE or FALSE based on whether or not fast I/O
  2055. is possible for this file.
  2056. --*/
  2057. {
  2058. PDEVICE_OBJECT nextDeviceObject;
  2059. PFAST_IO_DISPATCH fastIoDispatch;
  2060. PAGED_CODE();
  2061. VALIDATE_IRQL();
  2062. if (DeviceObject->DeviceExtension) {
  2063. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2064. //
  2065. // Pass through logic for this type of Fast I/O
  2066. //
  2067. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2068. ASSERT(nextDeviceObject);
  2069. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2070. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryBasicInfo )) {
  2071. return (fastIoDispatch->FastIoQueryBasicInfo)(
  2072. FileObject,
  2073. Wait,
  2074. Buffer,
  2075. IoStatus,
  2076. nextDeviceObject );
  2077. }
  2078. }
  2079. return FALSE;
  2080. }
  2081. BOOLEAN
  2082. DaFastIoQueryStandardInfo (
  2083. IN PFILE_OBJECT FileObject,
  2084. IN BOOLEAN Wait,
  2085. OUT PFILE_STANDARD_INFORMATION Buffer,
  2086. OUT PIO_STATUS_BLOCK IoStatus,
  2087. IN PDEVICE_OBJECT DeviceObject
  2088. )
  2089. /*++
  2090. Routine Description:
  2091. This routine is the fast I/O "pass through" routine for querying standard
  2092. information about the file.
  2093. This function simply invokes the file system's corresponding routine, or
  2094. returns FALSE if the file system does not implement the function.
  2095. Arguments:
  2096. FileObject - Pointer to the file object to be queried.
  2097. Wait - Indicates whether or not the caller is willing to wait if the
  2098. appropriate locks, etc. cannot be acquired
  2099. Buffer - Pointer to the caller's buffer to receive the information about
  2100. the file.
  2101. IoStatus - Pointer to a variable to receive the I/O status of the
  2102. operation.
  2103. DeviceObject - Pointer to this driver's device object, the device on
  2104. which the operation is to occur.
  2105. Return Value:
  2106. The function value is TRUE or FALSE based on whether or not fast I/O
  2107. is possible for this file.
  2108. --*/
  2109. {
  2110. PDEVICE_OBJECT nextDeviceObject;
  2111. PFAST_IO_DISPATCH fastIoDispatch;
  2112. PAGED_CODE();
  2113. VALIDATE_IRQL();
  2114. if (DeviceObject->DeviceExtension) {
  2115. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2116. //
  2117. // Pass through logic for this type of Fast I/O
  2118. //
  2119. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2120. ASSERT(nextDeviceObject);
  2121. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2122. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryStandardInfo )) {
  2123. return (fastIoDispatch->FastIoQueryStandardInfo)(
  2124. FileObject,
  2125. Wait,
  2126. Buffer,
  2127. IoStatus,
  2128. nextDeviceObject );
  2129. }
  2130. }
  2131. return FALSE;
  2132. }
  2133. BOOLEAN
  2134. DaFastIoLock (
  2135. IN PFILE_OBJECT FileObject,
  2136. IN PLARGE_INTEGER FileOffset,
  2137. IN PLARGE_INTEGER Length,
  2138. PEPROCESS ProcessId,
  2139. ULONG Key,
  2140. BOOLEAN FailImmediately,
  2141. BOOLEAN ExclusiveLock,
  2142. OUT PIO_STATUS_BLOCK IoStatus,
  2143. IN PDEVICE_OBJECT DeviceObject
  2144. )
  2145. /*++
  2146. Routine Description:
  2147. This routine is the fast I/O "pass through" routine for locking a byte
  2148. range within a file.
  2149. This function simply invokes the file system's corresponding routine, or
  2150. returns FALSE if the file system does not implement the function.
  2151. Arguments:
  2152. FileObject - Pointer to the file object to be locked.
  2153. FileOffset - Starting byte offset from the base of the file to be locked.
  2154. Length - Length of the byte range to be locked.
  2155. ProcessId - ID of the process requesting the file lock.
  2156. Key - Lock key to associate with the file lock.
  2157. FailImmediately - Indicates whether or not the lock request is to fail
  2158. if it cannot be immediately be granted.
  2159. ExclusiveLock - Indicates whether the lock to be taken is exclusive (TRUE)
  2160. or shared.
  2161. IoStatus - Pointer to a variable to receive the I/O status of the
  2162. operation.
  2163. DeviceObject - Pointer to this driver's device object, the device on
  2164. which the operation is to occur.
  2165. Return Value:
  2166. The function value is TRUE or FALSE based on whether or not fast I/O
  2167. is possible for this file.
  2168. --*/
  2169. {
  2170. PDEVICE_OBJECT nextDeviceObject;
  2171. PFAST_IO_DISPATCH fastIoDispatch;
  2172. PAGED_CODE();
  2173. VALIDATE_IRQL();
  2174. if (DeviceObject->DeviceExtension) {
  2175. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2176. //
  2177. // Pass through logic for this type of Fast I/O
  2178. //
  2179. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2180. ASSERT(nextDeviceObject);
  2181. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2182. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoLock )) {
  2183. return (fastIoDispatch->FastIoLock)(
  2184. FileObject,
  2185. FileOffset,
  2186. Length,
  2187. ProcessId,
  2188. Key,
  2189. FailImmediately,
  2190. ExclusiveLock,
  2191. IoStatus,
  2192. nextDeviceObject );
  2193. }
  2194. }
  2195. return FALSE;
  2196. }
  2197. BOOLEAN
  2198. DaFastIoUnlockSingle (
  2199. IN PFILE_OBJECT FileObject,
  2200. IN PLARGE_INTEGER FileOffset,
  2201. IN PLARGE_INTEGER Length,
  2202. PEPROCESS ProcessId,
  2203. ULONG Key,
  2204. OUT PIO_STATUS_BLOCK IoStatus,
  2205. IN PDEVICE_OBJECT DeviceObject
  2206. )
  2207. /*++
  2208. Routine Description:
  2209. This routine is the fast I/O "pass through" routine for unlocking a byte
  2210. range within a file.
  2211. This function simply invokes the file system's corresponding routine, or
  2212. returns FALSE if the file system does not implement the function.
  2213. Arguments:
  2214. FileObject - Pointer to the file object to be unlocked.
  2215. FileOffset - Starting byte offset from the base of the file to be
  2216. unlocked.
  2217. Length - Length of the byte range to be unlocked.
  2218. ProcessId - ID of the process requesting the unlock operation.
  2219. Key - Lock key associated with the file lock.
  2220. IoStatus - Pointer to a variable to receive the I/O status of the
  2221. operation.
  2222. DeviceObject - Pointer to this driver's device object, the device on
  2223. which the operation is to occur.
  2224. Return Value:
  2225. The function value is TRUE or FALSE based on whether or not fast I/O
  2226. is possible for this file.
  2227. --*/
  2228. {
  2229. PDEVICE_OBJECT nextDeviceObject;
  2230. PFAST_IO_DISPATCH fastIoDispatch;
  2231. PAGED_CODE();
  2232. VALIDATE_IRQL();
  2233. if (DeviceObject->DeviceExtension) {
  2234. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2235. //
  2236. // Pass through logic for this type of Fast I/O
  2237. //
  2238. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2239. ASSERT(nextDeviceObject);
  2240. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2241. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockSingle )) {
  2242. return (fastIoDispatch->FastIoUnlockSingle)(
  2243. FileObject,
  2244. FileOffset,
  2245. Length,
  2246. ProcessId,
  2247. Key,
  2248. IoStatus,
  2249. nextDeviceObject );
  2250. }
  2251. }
  2252. return FALSE;
  2253. }
  2254. BOOLEAN
  2255. DaFastIoUnlockAll (
  2256. IN PFILE_OBJECT FileObject,
  2257. PEPROCESS ProcessId,
  2258. OUT PIO_STATUS_BLOCK IoStatus,
  2259. IN PDEVICE_OBJECT DeviceObject
  2260. )
  2261. /*++
  2262. Routine Description:
  2263. This routine is the fast I/O "pass through" routine for unlocking all
  2264. locks within a file.
  2265. This function simply invokes the file system's corresponding routine, or
  2266. returns FALSE if the file system does not implement the function.
  2267. Arguments:
  2268. FileObject - Pointer to the file object to be unlocked.
  2269. ProcessId - ID of the process requesting the unlock operation.
  2270. IoStatus - Pointer to a variable to receive the I/O status of the
  2271. operation.
  2272. DeviceObject - Pointer to this driver's device object, the device on
  2273. which the operation is to occur.
  2274. Return Value:
  2275. The function value is TRUE or FALSE based on whether or not fast I/O
  2276. is possible for this file.
  2277. --*/
  2278. {
  2279. PDEVICE_OBJECT nextDeviceObject;
  2280. PFAST_IO_DISPATCH fastIoDispatch;
  2281. PAGED_CODE();
  2282. VALIDATE_IRQL();
  2283. if (DeviceObject->DeviceExtension) {
  2284. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2285. //
  2286. // Pass through logic for this type of Fast I/O
  2287. //
  2288. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2289. if (nextDeviceObject) {
  2290. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2291. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAll )) {
  2292. return (fastIoDispatch->FastIoUnlockAll)(
  2293. FileObject,
  2294. ProcessId,
  2295. IoStatus,
  2296. nextDeviceObject );
  2297. }
  2298. }
  2299. }
  2300. return FALSE;
  2301. }
  2302. BOOLEAN
  2303. DaFastIoUnlockAllByKey (
  2304. IN PFILE_OBJECT FileObject,
  2305. PVOID ProcessId,
  2306. ULONG Key,
  2307. OUT PIO_STATUS_BLOCK IoStatus,
  2308. IN PDEVICE_OBJECT DeviceObject
  2309. )
  2310. /*++
  2311. Routine Description:
  2312. This routine is the fast I/O "pass through" routine for unlocking all
  2313. locks within a file based on a specified key.
  2314. This function simply invokes the file system's corresponding routine, or
  2315. returns FALSE if the file system does not implement the function.
  2316. Arguments:
  2317. FileObject - Pointer to the file object to be unlocked.
  2318. ProcessId - ID of the process requesting the unlock operation.
  2319. Key - Lock key associated with the locks on the file to be released.
  2320. IoStatus - Pointer to a variable to receive the I/O status of the
  2321. operation.
  2322. DeviceObject - Pointer to this driver's device object, the device on
  2323. which the operation is to occur.
  2324. Return Value:
  2325. The function value is TRUE or FALSE based on whether or not fast I/O
  2326. is possible for this file.
  2327. --*/
  2328. {
  2329. PDEVICE_OBJECT nextDeviceObject;
  2330. PFAST_IO_DISPATCH fastIoDispatch;
  2331. PAGED_CODE();
  2332. VALIDATE_IRQL();
  2333. if (DeviceObject->DeviceExtension) {
  2334. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2335. //
  2336. // Pass through logic for this type of Fast I/O
  2337. //
  2338. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2339. ASSERT(nextDeviceObject);
  2340. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2341. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAllByKey )) {
  2342. return (fastIoDispatch->FastIoUnlockAllByKey)(
  2343. FileObject,
  2344. ProcessId,
  2345. Key,
  2346. IoStatus,
  2347. nextDeviceObject );
  2348. }
  2349. }
  2350. return FALSE;
  2351. }
  2352. BOOLEAN
  2353. DaFastIoDeviceControl (
  2354. IN PFILE_OBJECT FileObject,
  2355. IN BOOLEAN Wait,
  2356. IN PVOID InputBuffer OPTIONAL,
  2357. IN ULONG InputBufferLength,
  2358. OUT PVOID OutputBuffer OPTIONAL,
  2359. IN ULONG OutputBufferLength,
  2360. IN ULONG IoControlCode,
  2361. OUT PIO_STATUS_BLOCK IoStatus,
  2362. IN PDEVICE_OBJECT DeviceObject
  2363. )
  2364. /*++
  2365. Routine Description:
  2366. This routine is the fast I/O "pass through" routine for device I/O control
  2367. operations on a file.
  2368. This function simply invokes the file system's corresponding routine, or
  2369. returns FALSE if the file system does not implement the function.
  2370. Arguments:
  2371. FileObject - Pointer to the file object representing the device to be
  2372. serviced.
  2373. Wait - Indicates whether or not the caller is willing to wait if the
  2374. appropriate locks, etc. cannot be acquired
  2375. InputBuffer - Optional pointer to a buffer to be passed into the driver.
  2376. InputBufferLength - Length of the optional InputBuffer, if one was
  2377. specified.
  2378. OutputBuffer - Optional pointer to a buffer to receive data from the
  2379. driver.
  2380. OutputBufferLength - Length of the optional OutputBuffer, if one was
  2381. specified.
  2382. IoControlCode - I/O control code indicating the operation to be performed
  2383. on the device.
  2384. IoStatus - Pointer to a variable to receive the I/O status of the
  2385. operation.
  2386. DeviceObject - Pointer to this driver's device object, the device on
  2387. which the operation is to occur.
  2388. Return Value:
  2389. The function value is TRUE or FALSE based on whether or not fast I/O
  2390. is possible for this file.
  2391. --*/
  2392. {
  2393. PDEVICE_OBJECT nextDeviceObject;
  2394. PFAST_IO_DISPATCH fastIoDispatch;
  2395. PAGED_CODE();
  2396. VALIDATE_IRQL();
  2397. if (DeviceObject->DeviceExtension) {
  2398. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2399. //
  2400. // Pass through logic for this type of Fast I/O
  2401. //
  2402. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2403. ASSERT(nextDeviceObject);
  2404. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2405. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoDeviceControl )) {
  2406. return (fastIoDispatch->FastIoDeviceControl)(
  2407. FileObject,
  2408. Wait,
  2409. InputBuffer,
  2410. InputBufferLength,
  2411. OutputBuffer,
  2412. OutputBufferLength,
  2413. IoControlCode,
  2414. IoStatus,
  2415. nextDeviceObject );
  2416. }
  2417. }
  2418. return FALSE;
  2419. }
  2420. VOID
  2421. DaFastIoDetachDevice (
  2422. IN PDEVICE_OBJECT SourceDevice,
  2423. IN PDEVICE_OBJECT TargetDevice
  2424. )
  2425. /*++
  2426. Routine Description:
  2427. This routine is invoked on the fast path to detach from a device that
  2428. is being deleted. This occurs when this driver has attached to a file
  2429. system volume device object, and then, for some reason, the file system
  2430. decides to delete that device (it is being dismounted, it was dismounted
  2431. at some point in the past and its last reference has just gone away, etc.)
  2432. Arguments:
  2433. SourceDevice - Pointer to my device object, which is attached
  2434. to the file system's volume device object.
  2435. TargetDevice - Pointer to the file system's volume device object.
  2436. Return Value:
  2437. None
  2438. --*/
  2439. {
  2440. PDBLATTACH_DEVEXT_HEADER devExtHdr;
  2441. PDBLATTACH_CDO_EXTENSION cdoDevExt;
  2442. PDBLATTACH_VDO_EXTENSION vdoDevExt;
  2443. PAGED_CODE();
  2444. VALIDATE_IRQL();
  2445. ASSERT(IS_MY_DEVICE_OBJECT( SourceDevice ));
  2446. devExtHdr = SourceDevice->DeviceExtension;
  2447. //
  2448. // Display name information
  2449. //
  2450. switch (devExtHdr->ExtType) {
  2451. case FsControlDeviceObject:
  2452. cdoDevExt = (PDBLATTACH_CDO_EXTENSION)devExtHdr;
  2453. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  2454. ("DblAttach!DaFastIoDetachDevice: Detaching from volume %p \"%wZ\"\n",
  2455. TargetDevice,
  2456. &cdoDevExt->DeviceName) );
  2457. break;
  2458. case FsVolumeLower:
  2459. vdoDevExt = (PDBLATTACH_VDO_EXTENSION)devExtHdr;
  2460. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  2461. ("DblAttach!DaFastIoDetachDevice: Detaching from volume %p \"%wZ\"\n",
  2462. TargetDevice,
  2463. &vdoDevExt->SharedExt->DeviceName) );
  2464. break;
  2465. case FsVolumeUpper:
  2466. default:
  2467. //
  2468. // The device name is freed when the lower device goes away,
  2469. // so don't try to print the name for the upper device object.
  2470. //
  2471. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  2472. ("DblAttach!DaFastIoDetachDevice: Detaching from volume %p\n",
  2473. TargetDevice) );
  2474. }
  2475. //
  2476. // Detach from the file system's volume device object.
  2477. //
  2478. DaCleanupMountedDevice( SourceDevice );
  2479. IoDetachDevice( TargetDevice );
  2480. IoDeleteDevice( SourceDevice );
  2481. }
  2482. BOOLEAN
  2483. DaFastIoQueryNetworkOpenInfo (
  2484. IN PFILE_OBJECT FileObject,
  2485. IN BOOLEAN Wait,
  2486. OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
  2487. OUT PIO_STATUS_BLOCK IoStatus,
  2488. IN PDEVICE_OBJECT DeviceObject
  2489. )
  2490. /*++
  2491. Routine Description:
  2492. This routine is the fast I/O "pass through" routine for querying network
  2493. information about a file.
  2494. This function simply invokes the file system's corresponding routine, or
  2495. returns FALSE if the file system does not implement the function.
  2496. Arguments:
  2497. FileObject - Pointer to the file object to be queried.
  2498. Wait - Indicates whether or not the caller can handle the file system
  2499. having to wait and tie up the current thread.
  2500. Buffer - Pointer to a buffer to receive the network information about the
  2501. file.
  2502. IoStatus - Pointer to a variable to receive the final status of the query
  2503. operation.
  2504. DeviceObject - Pointer to this driver's device object, the device on
  2505. which the operation is to occur.
  2506. Return Value:
  2507. The function value is TRUE or FALSE based on whether or not fast I/O
  2508. is possible for this file.
  2509. --*/
  2510. {
  2511. PDEVICE_OBJECT nextDeviceObject;
  2512. PFAST_IO_DISPATCH fastIoDispatch;
  2513. PAGED_CODE();
  2514. VALIDATE_IRQL();
  2515. if (DeviceObject->DeviceExtension) {
  2516. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2517. //
  2518. // Pass through logic for this type of Fast I/O
  2519. //
  2520. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2521. ASSERT(nextDeviceObject);
  2522. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2523. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryNetworkOpenInfo )) {
  2524. return (fastIoDispatch->FastIoQueryNetworkOpenInfo)(
  2525. FileObject,
  2526. Wait,
  2527. Buffer,
  2528. IoStatus,
  2529. nextDeviceObject );
  2530. }
  2531. }
  2532. return FALSE;
  2533. }
  2534. BOOLEAN
  2535. DaFastIoMdlRead (
  2536. IN PFILE_OBJECT FileObject,
  2537. IN PLARGE_INTEGER FileOffset,
  2538. IN ULONG Length,
  2539. IN ULONG LockKey,
  2540. OUT PMDL *MdlChain,
  2541. OUT PIO_STATUS_BLOCK IoStatus,
  2542. IN PDEVICE_OBJECT DeviceObject
  2543. )
  2544. /*++
  2545. Routine Description:
  2546. This routine is the fast I/O "pass through" routine for reading a file
  2547. using MDLs as buffers.
  2548. This function simply invokes the file system's corresponding routine, or
  2549. returns FALSE if the file system does not implement the function.
  2550. Arguments:
  2551. FileObject - Pointer to the file object that is to be read.
  2552. FileOffset - Supplies the offset into the file to begin the read operation.
  2553. Length - Specifies the number of bytes to be read from the file.
  2554. LockKey - The key to be used in byte range lock checks.
  2555. MdlChain - A pointer to a variable to be filled in w/a pointer to the MDL
  2556. chain built to describe the data read.
  2557. IoStatus - Variable to receive the final status of the read operation.
  2558. DeviceObject - Pointer to this driver's device object, the device on
  2559. which the operation is to occur.
  2560. Return Value:
  2561. The function value is TRUE or FALSE based on whether or not fast I/O
  2562. is possible for this file.
  2563. --*/
  2564. {
  2565. PDEVICE_OBJECT nextDeviceObject;
  2566. PFAST_IO_DISPATCH fastIoDispatch;
  2567. PAGED_CODE();
  2568. VALIDATE_IRQL();
  2569. if (DeviceObject->DeviceExtension) {
  2570. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2571. //
  2572. // Pass through logic for this type of Fast I/O
  2573. //
  2574. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2575. ASSERT(nextDeviceObject);
  2576. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2577. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlRead )) {
  2578. return (fastIoDispatch->MdlRead)(
  2579. FileObject,
  2580. FileOffset,
  2581. Length,
  2582. LockKey,
  2583. MdlChain,
  2584. IoStatus,
  2585. nextDeviceObject );
  2586. }
  2587. }
  2588. return FALSE;
  2589. }
  2590. BOOLEAN
  2591. DaFastIoMdlReadComplete (
  2592. IN PFILE_OBJECT FileObject,
  2593. IN PMDL MdlChain,
  2594. IN PDEVICE_OBJECT DeviceObject
  2595. )
  2596. /*++
  2597. Routine Description:
  2598. This routine is the fast I/O "pass through" routine for completing an
  2599. MDL read operation.
  2600. This function simply invokes the file system's corresponding routine, if
  2601. it has one. It should be the case that this routine is invoked only if
  2602. the MdlRead function is supported by the underlying file system, and
  2603. therefore this function will also be supported, but this is not assumed
  2604. by this driver.
  2605. Arguments:
  2606. FileObject - Pointer to the file object to complete the MDL read upon.
  2607. MdlChain - Pointer to the MDL chain used to perform the read operation.
  2608. DeviceObject - Pointer to this driver's device object, the device on
  2609. which the operation is to occur.
  2610. Return Value:
  2611. The function value is TRUE or FALSE, depending on whether or not it is
  2612. possible to invoke this function on the fast I/O path.
  2613. --*/
  2614. {
  2615. PDEVICE_OBJECT nextDeviceObject;
  2616. PFAST_IO_DISPATCH fastIoDispatch;
  2617. if (DeviceObject->DeviceExtension) {
  2618. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2619. //
  2620. // Pass through logic for this type of Fast I/O
  2621. //
  2622. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2623. ASSERT(nextDeviceObject);
  2624. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2625. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadComplete )) {
  2626. return (fastIoDispatch->MdlReadComplete)(
  2627. FileObject,
  2628. MdlChain,
  2629. nextDeviceObject );
  2630. }
  2631. }
  2632. return FALSE;
  2633. }
  2634. BOOLEAN
  2635. DaFastIoPrepareMdlWrite (
  2636. IN PFILE_OBJECT FileObject,
  2637. IN PLARGE_INTEGER FileOffset,
  2638. IN ULONG Length,
  2639. IN ULONG LockKey,
  2640. OUT PMDL *MdlChain,
  2641. OUT PIO_STATUS_BLOCK IoStatus,
  2642. IN PDEVICE_OBJECT DeviceObject
  2643. )
  2644. /*++
  2645. Routine Description:
  2646. This routine is the fast I/O "pass through" routine for preparing for an
  2647. MDL write operation.
  2648. This function simply invokes the file system's corresponding routine, or
  2649. returns FALSE if the file system does not implement the function.
  2650. Arguments:
  2651. FileObject - Pointer to the file object that will be written.
  2652. FileOffset - Supplies the offset into the file to begin the write operation.
  2653. Length - Specifies the number of bytes to be write to the file.
  2654. LockKey - The key to be used in byte range lock checks.
  2655. MdlChain - A pointer to a variable to be filled in w/a pointer to the MDL
  2656. chain built to describe the data written.
  2657. IoStatus - Variable to receive the final status of the write operation.
  2658. DeviceObject - Pointer to this driver's device object, the device on
  2659. which the operation is to occur.
  2660. Return Value:
  2661. The function value is TRUE or FALSE based on whether or not fast I/O
  2662. is possible for this file.
  2663. --*/
  2664. {
  2665. PDEVICE_OBJECT nextDeviceObject;
  2666. PFAST_IO_DISPATCH fastIoDispatch;
  2667. PAGED_CODE();
  2668. VALIDATE_IRQL();
  2669. if (DeviceObject->DeviceExtension) {
  2670. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2671. //
  2672. // Pass through logic for this type of Fast I/O
  2673. //
  2674. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2675. ASSERT(nextDeviceObject);
  2676. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2677. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, PrepareMdlWrite )) {
  2678. return (fastIoDispatch->PrepareMdlWrite)(
  2679. FileObject,
  2680. FileOffset,
  2681. Length,
  2682. LockKey,
  2683. MdlChain,
  2684. IoStatus,
  2685. nextDeviceObject );
  2686. }
  2687. }
  2688. return FALSE;
  2689. }
  2690. BOOLEAN
  2691. DaFastIoMdlWriteComplete (
  2692. IN PFILE_OBJECT FileObject,
  2693. IN PLARGE_INTEGER FileOffset,
  2694. IN PMDL MdlChain,
  2695. IN PDEVICE_OBJECT DeviceObject
  2696. )
  2697. /*++
  2698. Routine Description:
  2699. This routine is the fast I/O "pass through" routine for completing an
  2700. MDL write operation.
  2701. This function simply invokes the file system's corresponding routine, if
  2702. it has one. It should be the case that this routine is invoked only if
  2703. the PrepareMdlWrite function is supported by the underlying file system,
  2704. and therefore this function will also be supported, but this is not
  2705. assumed by this driver.
  2706. Arguments:
  2707. FileObject - Pointer to the file object to complete the MDL write upon.
  2708. FileOffset - Supplies the file offset at which the write took place.
  2709. MdlChain - Pointer to the MDL chain used to perform the write operation.
  2710. DeviceObject - Pointer to this driver's device object, the device on
  2711. which the operation is to occur.
  2712. Return Value:
  2713. The function value is TRUE or FALSE, depending on whether or not it is
  2714. possible to invoke this function on the fast I/O path.
  2715. --*/
  2716. {
  2717. PDEVICE_OBJECT nextDeviceObject;
  2718. PFAST_IO_DISPATCH fastIoDispatch;
  2719. PAGED_CODE();
  2720. VALIDATE_IRQL();
  2721. if (DeviceObject->DeviceExtension) {
  2722. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2723. //
  2724. // Pass through logic for this type of Fast I/O
  2725. //
  2726. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2727. ASSERT(nextDeviceObject);
  2728. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2729. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteComplete )) {
  2730. return (fastIoDispatch->MdlWriteComplete)(
  2731. FileObject,
  2732. FileOffset,
  2733. MdlChain,
  2734. nextDeviceObject );
  2735. }
  2736. }
  2737. return FALSE;
  2738. }
  2739. /*********************************************************************************
  2740. UNIMPLEMENTED FAST IO ROUTINES
  2741. The following four Fast IO routines are for compression on the wire
  2742. which is not yet implemented in NT.
  2743. NOTE: It is highly recommended that you include these routines (which
  2744. do a pass-through call) so your filter will not need to be
  2745. modified in the future when this functionality is implemented in
  2746. the OS.
  2747. FastIoReadCompressed, FastIoWriteCompressed,
  2748. FastIoMdlReadCompleteCompressed, FastIoMdlWriteCompleteCompressed
  2749. **********************************************************************************/
  2750. BOOLEAN
  2751. DaFastIoReadCompressed (
  2752. IN PFILE_OBJECT FileObject,
  2753. IN PLARGE_INTEGER FileOffset,
  2754. IN ULONG Length,
  2755. IN ULONG LockKey,
  2756. OUT PVOID Buffer,
  2757. OUT PMDL *MdlChain,
  2758. OUT PIO_STATUS_BLOCK IoStatus,
  2759. OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
  2760. IN ULONG CompressedDataInfoLength,
  2761. IN PDEVICE_OBJECT DeviceObject
  2762. )
  2763. /*++
  2764. Routine Description:
  2765. This routine is the fast I/O "pass through" routine for reading compressed
  2766. data from a file.
  2767. This function simply invokes the file system's corresponding routine, or
  2768. returns FALSE if the file system does not implement the function.
  2769. Arguments:
  2770. FileObject - Pointer to the file object that will be read.
  2771. FileOffset - Supplies the offset into the file to begin the read operation.
  2772. Length - Specifies the number of bytes to be read from the file.
  2773. LockKey - The key to be used in byte range lock checks.
  2774. Buffer - Pointer to a buffer to receive the compressed data read.
  2775. MdlChain - A pointer to a variable to be filled in w/a pointer to the MDL
  2776. chain built to describe the data read.
  2777. IoStatus - Variable to receive the final status of the read operation.
  2778. CompressedDataInfo - A buffer to receive the description of the compressed
  2779. data.
  2780. CompressedDataInfoLength - Specifies the size of the buffer described by
  2781. the CompressedDataInfo parameter.
  2782. DeviceObject - Pointer to this driver's device object, the device on
  2783. which the operation is to occur.
  2784. Return Value:
  2785. The function value is TRUE or FALSE based on whether or not fast I/O
  2786. is possible for this file.
  2787. --*/
  2788. {
  2789. PDEVICE_OBJECT nextDeviceObject;
  2790. PFAST_IO_DISPATCH fastIoDispatch;
  2791. PAGED_CODE();
  2792. VALIDATE_IRQL();
  2793. if (DeviceObject->DeviceExtension) {
  2794. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2795. //
  2796. // Pass through logic for this type of Fast I/O
  2797. //
  2798. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2799. ASSERT(nextDeviceObject);
  2800. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2801. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoReadCompressed )) {
  2802. return (fastIoDispatch->FastIoReadCompressed)(
  2803. FileObject,
  2804. FileOffset,
  2805. Length,
  2806. LockKey,
  2807. Buffer,
  2808. MdlChain,
  2809. IoStatus,
  2810. CompressedDataInfo,
  2811. CompressedDataInfoLength,
  2812. nextDeviceObject );
  2813. }
  2814. }
  2815. return FALSE;
  2816. }
  2817. BOOLEAN
  2818. DaFastIoWriteCompressed (
  2819. IN PFILE_OBJECT FileObject,
  2820. IN PLARGE_INTEGER FileOffset,
  2821. IN ULONG Length,
  2822. IN ULONG LockKey,
  2823. IN PVOID Buffer,
  2824. OUT PMDL *MdlChain,
  2825. OUT PIO_STATUS_BLOCK IoStatus,
  2826. IN struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
  2827. IN ULONG CompressedDataInfoLength,
  2828. IN PDEVICE_OBJECT DeviceObject
  2829. )
  2830. /*++
  2831. Routine Description:
  2832. This routine is the fast I/O "pass through" routine for writing compressed
  2833. data to a file.
  2834. This function simply invokes the file system's corresponding routine, or
  2835. returns FALSE if the file system does not implement the function.
  2836. Arguments:
  2837. FileObject - Pointer to the file object that will be written.
  2838. FileOffset - Supplies the offset into the file to begin the write operation.
  2839. Length - Specifies the number of bytes to be write to the file.
  2840. LockKey - The key to be used in byte range lock checks.
  2841. Buffer - Pointer to the buffer containing the data to be written.
  2842. MdlChain - A pointer to a variable to be filled in w/a pointer to the MDL
  2843. chain built to describe the data written.
  2844. IoStatus - Variable to receive the final status of the write operation.
  2845. CompressedDataInfo - A buffer to containing the description of the
  2846. compressed data.
  2847. CompressedDataInfoLength - Specifies the size of the buffer described by
  2848. the CompressedDataInfo parameter.
  2849. DeviceObject - Pointer to this driver's device object, the device on
  2850. which the operation is to occur.
  2851. Return Value:
  2852. The function value is TRUE or FALSE based on whether or not fast I/O
  2853. is possible for this file.
  2854. --*/
  2855. {
  2856. PDEVICE_OBJECT nextDeviceObject;
  2857. PFAST_IO_DISPATCH fastIoDispatch;
  2858. PAGED_CODE();
  2859. VALIDATE_IRQL();
  2860. if (DeviceObject->DeviceExtension) {
  2861. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2862. //
  2863. // Pass through logic for this type of Fast I/O
  2864. //
  2865. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2866. ASSERT(nextDeviceObject);
  2867. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2868. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWriteCompressed )) {
  2869. return (fastIoDispatch->FastIoWriteCompressed)(
  2870. FileObject,
  2871. FileOffset,
  2872. Length,
  2873. LockKey,
  2874. Buffer,
  2875. MdlChain,
  2876. IoStatus,
  2877. CompressedDataInfo,
  2878. CompressedDataInfoLength,
  2879. nextDeviceObject );
  2880. }
  2881. }
  2882. return FALSE;
  2883. }
  2884. BOOLEAN
  2885. DaFastIoMdlReadCompleteCompressed (
  2886. IN PFILE_OBJECT FileObject,
  2887. IN PMDL MdlChain,
  2888. IN PDEVICE_OBJECT DeviceObject
  2889. )
  2890. /*++
  2891. Routine Description:
  2892. This routine is the fast I/O "pass through" routine for completing an
  2893. MDL read compressed operation.
  2894. This function simply invokes the file system's corresponding routine, if
  2895. it has one. It should be the case that this routine is invoked only if
  2896. the read compressed function is supported by the underlying file system,
  2897. and therefore this function will also be supported, but this is not assumed
  2898. by this driver.
  2899. Arguments:
  2900. FileObject - Pointer to the file object to complete the compressed read
  2901. upon.
  2902. MdlChain - Pointer to the MDL chain used to perform the read operation.
  2903. DeviceObject - Pointer to this driver's device object, the device on
  2904. which the operation is to occur.
  2905. Return Value:
  2906. The function value is TRUE or FALSE, depending on whether or not it is
  2907. possible to invoke this function on the fast I/O path.
  2908. --*/
  2909. {
  2910. PDEVICE_OBJECT nextDeviceObject;
  2911. PFAST_IO_DISPATCH fastIoDispatch;
  2912. if (DeviceObject->DeviceExtension) {
  2913. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2914. //
  2915. // Pass through logic for this type of Fast I/O
  2916. //
  2917. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2918. ASSERT(nextDeviceObject);
  2919. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2920. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadCompleteCompressed )) {
  2921. return (fastIoDispatch->MdlReadCompleteCompressed)(
  2922. FileObject,
  2923. MdlChain,
  2924. nextDeviceObject );
  2925. }
  2926. }
  2927. return FALSE;
  2928. }
  2929. BOOLEAN
  2930. DaFastIoMdlWriteCompleteCompressed (
  2931. IN PFILE_OBJECT FileObject,
  2932. IN PLARGE_INTEGER FileOffset,
  2933. IN PMDL MdlChain,
  2934. IN PDEVICE_OBJECT DeviceObject
  2935. )
  2936. /*++
  2937. Routine Description:
  2938. This routine is the fast I/O "pass through" routine for completing a
  2939. write compressed operation.
  2940. This function simply invokes the file system's corresponding routine, if
  2941. it has one. It should be the case that this routine is invoked only if
  2942. the write compressed function is supported by the underlying file system,
  2943. and therefore this function will also be supported, but this is not assumed
  2944. by this driver.
  2945. Arguments:
  2946. FileObject - Pointer to the file object to complete the compressed write
  2947. upon.
  2948. FileOffset - Supplies the file offset at which the file write operation
  2949. began.
  2950. MdlChain - Pointer to the MDL chain used to perform the write operation.
  2951. DeviceObject - Pointer to this driver's device object, the device on
  2952. which the operation is to occur.
  2953. Return Value:
  2954. The function value is TRUE or FALSE, depending on whether or not it is
  2955. possible to invoke this function on the fast I/O path.
  2956. --*/
  2957. {
  2958. PDEVICE_OBJECT nextDeviceObject;
  2959. PFAST_IO_DISPATCH fastIoDispatch;
  2960. if (DeviceObject->DeviceExtension) {
  2961. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  2962. //
  2963. // Pass through logic for this type of Fast I/O
  2964. //
  2965. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  2966. ASSERT(nextDeviceObject);
  2967. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  2968. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteCompleteCompressed )) {
  2969. return (fastIoDispatch->MdlWriteCompleteCompressed)(
  2970. FileObject,
  2971. FileOffset,
  2972. MdlChain,
  2973. nextDeviceObject );
  2974. }
  2975. }
  2976. return FALSE;
  2977. }
  2978. BOOLEAN
  2979. DaFastIoQueryOpen (
  2980. IN PIRP Irp,
  2981. OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
  2982. IN PDEVICE_OBJECT DeviceObject
  2983. )
  2984. /*++
  2985. Routine Description:
  2986. This routine is the fast I/O "pass through" routine for opening a file
  2987. and returning network information for it.
  2988. This function simply invokes the file system's corresponding routine, or
  2989. returns FALSE if the file system does not implement the function.
  2990. Arguments:
  2991. Irp - Pointer to a create IRP that represents this open operation. It is
  2992. to be used by the file system for common open/create code, but not
  2993. actually completed.
  2994. NetworkInformation - A buffer to receive the information required by the
  2995. network about the file being opened.
  2996. DeviceObject - Pointer to this driver's device object, the device on
  2997. which the operation is to occur.
  2998. Return Value:
  2999. The function value is TRUE or FALSE based on whether or not fast I/O
  3000. is possible for this file.
  3001. --*/
  3002. {
  3003. PDEVICE_OBJECT nextDeviceObject;
  3004. PFAST_IO_DISPATCH fastIoDispatch;
  3005. BOOLEAN result;
  3006. PAGED_CODE();
  3007. VALIDATE_IRQL();
  3008. if (DeviceObject->DeviceExtension) {
  3009. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  3010. //
  3011. // Pass through logic for this type of Fast I/O
  3012. //
  3013. nextDeviceObject = ((PDBLATTACH_DEVEXT_HEADER) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  3014. ASSERT(nextDeviceObject);
  3015. fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
  3016. if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryOpen )) {
  3017. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  3018. irpSp->DeviceObject = nextDeviceObject;
  3019. result = (fastIoDispatch->FastIoQueryOpen)(
  3020. Irp,
  3021. NetworkInformation,
  3022. nextDeviceObject );
  3023. if (!result) {
  3024. irpSp->DeviceObject = DeviceObject;
  3025. }
  3026. return result;
  3027. }
  3028. }
  3029. return FALSE;
  3030. }
  3031. /////////////////////////////////////////////////////////////////////////////
  3032. //
  3033. // FSFilter callback handling routines
  3034. //
  3035. /////////////////////////////////////////////////////////////////////////////
  3036. NTSTATUS
  3037. DaPreFsFilterPassThrough (
  3038. IN PFS_FILTER_CALLBACK_DATA Data,
  3039. OUT PVOID *CompletionContext
  3040. )
  3041. /*++
  3042. Routine Description:
  3043. This routine is the FS Filter pre-operation "pass through" routine.
  3044. Arguments:
  3045. Data - The FS_FILTER_CALLBACK_DATA structure containing the information
  3046. about this operation.
  3047. CompletionContext - A context set by this operation that will be passed
  3048. to the corresponding DaPostFsFilterOperation call.
  3049. Return Value:
  3050. Returns STATUS_SUCCESS if the operation can continue or an appropriate
  3051. error code if the operation should fail.
  3052. --*/
  3053. {
  3054. PAGED_CODE();
  3055. VALIDATE_IRQL();
  3056. UNREFERENCED_PARAMETER( Data );
  3057. UNREFERENCED_PARAMETER( CompletionContext );
  3058. ASSERT( IS_MY_DEVICE_OBJECT( Data->DeviceObject ) );
  3059. return STATUS_SUCCESS;
  3060. }
  3061. VOID
  3062. DaPostFsFilterPassThrough (
  3063. IN PFS_FILTER_CALLBACK_DATA Data,
  3064. IN NTSTATUS OperationStatus,
  3065. IN PVOID CompletionContext
  3066. )
  3067. /*++
  3068. Routine Description:
  3069. This routine is the FS Filter post-operation "pass through" routine.
  3070. Arguments:
  3071. Data - The FS_FILTER_CALLBACK_DATA structure containing the information
  3072. about this operation.
  3073. OperationStatus - The status of this operation.
  3074. CompletionContext - A context that was set in the pre-operation
  3075. callback by this driver.
  3076. Return Value:
  3077. None.
  3078. --*/
  3079. {
  3080. VALIDATE_IRQL();
  3081. UNREFERENCED_PARAMETER( Data );
  3082. UNREFERENCED_PARAMETER( OperationStatus );
  3083. UNREFERENCED_PARAMETER( CompletionContext );
  3084. ASSERT( IS_MY_DEVICE_OBJECT( Data->DeviceObject ) );
  3085. }
  3086. /////////////////////////////////////////////////////////////////////////////
  3087. //
  3088. // Support routines
  3089. //
  3090. /////////////////////////////////////////////////////////////////////////////
  3091. NTSTATUS
  3092. DaCreateVolumeDeviceObjects (
  3093. IN DEVICE_TYPE DeviceType,
  3094. IN ULONG NumberOfArrayElements,
  3095. IN OUT PDEVICE_OBJECT *VDOArray
  3096. )
  3097. {
  3098. PDBLATTACH_SHARED_VDO_EXTENSION sharedExt;
  3099. PDBLATTACH_VDO_EXTENSION currentExt;
  3100. ULONG index;
  3101. NTSTATUS status = STATUS_SUCCESS;
  3102. for (index = 0; index < NumberOfArrayElements; index ++) {
  3103. VDOArray[index] = NULL;
  3104. }
  3105. sharedExt = ExAllocatePoolWithTag( NonPagedPool,
  3106. sizeof( DBLATTACH_SHARED_VDO_EXTENSION ),
  3107. DA_POOL_TAG );
  3108. if (sharedExt == NULL ) {
  3109. status = STATUS_INSUFFICIENT_RESOURCES;
  3110. goto DaCreateVolumeDeviceObjects_Exit;
  3111. }
  3112. for (index = 0; index < NumberOfArrayElements; index ++) {
  3113. status = IoCreateDevice( gDblAttachDriverObject,
  3114. sizeof( DBLATTACH_VDO_EXTENSION ),
  3115. NULL,
  3116. DeviceType,
  3117. 0,
  3118. FALSE,
  3119. &VDOArray[index] );
  3120. if (!NT_SUCCESS( status )) {
  3121. goto DaCreateVolumeDeviceObjects_Error;
  3122. }
  3123. currentExt = VDOArray[index]->DeviceExtension;
  3124. currentExt->SharedExt = sharedExt;
  3125. }
  3126. goto DaCreateVolumeDeviceObjects_Exit;
  3127. DaCreateVolumeDeviceObjects_Error:
  3128. for (index = 0; index < NumberOfArrayElements; index ++) {
  3129. if (VDOArray[index] != NULL) {
  3130. IoDeleteDevice( VDOArray[index] );
  3131. }
  3132. }
  3133. ExFreePoolWithTag( sharedExt, DA_POOL_TAG );
  3134. DaCreateVolumeDeviceObjects_Exit:
  3135. return status;
  3136. }
  3137. NTSTATUS
  3138. DaAttachToFileSystemDevice (
  3139. IN PDEVICE_OBJECT DeviceObject,
  3140. IN PUNICODE_STRING DeviceName
  3141. )
  3142. /*++
  3143. Routine Description:
  3144. This will attach to the given file system device object. We attach to
  3145. these devices so we will know when new volumes are mounted.
  3146. Arguments:
  3147. DeviceObject - The device to attach to
  3148. Name - An already initialized unicode string used to retrieve names.
  3149. This is passed in to reduce the number of strings buffers on
  3150. the stack.
  3151. Return Value:
  3152. Status of the operation
  3153. --*/
  3154. {
  3155. PDEVICE_OBJECT newDeviceObject;
  3156. PDBLATTACH_CDO_EXTENSION devExt;
  3157. UNICODE_STRING fsrecName;
  3158. NTSTATUS status;
  3159. UNICODE_STRING tempName;
  3160. WCHAR tempNameBuffer[MAX_DEVNAME_LENGTH];
  3161. PAGED_CODE();
  3162. //
  3163. // See if this is a file system type we care about. If not, return.
  3164. //
  3165. if (!IS_DESIRED_DEVICE_TYPE(DeviceObject->DeviceType)) {
  3166. return STATUS_SUCCESS;
  3167. }
  3168. //
  3169. // always init NAME buffer
  3170. //
  3171. RtlInitEmptyUnicodeString( &tempName,
  3172. tempNameBuffer,
  3173. sizeof(tempNameBuffer) );
  3174. //
  3175. // See if we should attach to the standard file system recognizer device
  3176. // or not
  3177. //
  3178. if (!FlagOn( DaDebug, DADEBUG_ATTACH_TO_FSRECOGNIZER )) {
  3179. //
  3180. // See if this is one of the standard Microsoft file system recognizer
  3181. // devices (see if this device is in the FS_REC driver). If so skip it.
  3182. // We no longer attach to file system recognizer devices, we simply wait
  3183. // for the real file system driver to load.
  3184. //
  3185. RtlInitUnicodeString( &fsrecName, L"\\FileSystem\\Fs_Rec" );
  3186. DaGetObjectName( DeviceObject->DriverObject, &tempName );
  3187. if (RtlCompareUnicodeString( &tempName, &fsrecName, TRUE ) == 0) {
  3188. return STATUS_SUCCESS;
  3189. }
  3190. }
  3191. //
  3192. // We want to attach to this file system. Create a new device object we
  3193. // can attach with.
  3194. //
  3195. status = IoCreateDevice( gDblAttachDriverObject,
  3196. sizeof( DBLATTACH_CDO_EXTENSION ),
  3197. NULL,
  3198. DeviceObject->DeviceType,
  3199. 0,
  3200. FALSE,
  3201. &newDeviceObject );
  3202. if (!NT_SUCCESS( status )) {
  3203. return status;
  3204. }
  3205. //
  3206. // Propagate flags from Device Object we are trying to attach to.
  3207. // Note that we do this before the actual attachment to make sure
  3208. // the flags are properly set once we are attached (since an IRP
  3209. // can come in immediately after attachment but before the flags would
  3210. // be set).
  3211. //
  3212. if ( FlagOn( DeviceObject->Flags, DO_BUFFERED_IO )) {
  3213. SetFlag( newDeviceObject->Flags, DO_BUFFERED_IO );
  3214. }
  3215. if ( FlagOn( DeviceObject->Flags, DO_DIRECT_IO )) {
  3216. SetFlag( newDeviceObject->Flags, DO_DIRECT_IO );
  3217. }
  3218. //
  3219. // Do the attachment
  3220. //
  3221. devExt = newDeviceObject->DeviceExtension;
  3222. status = IoAttachDeviceToDeviceStackSafe( newDeviceObject,
  3223. DeviceObject,
  3224. &devExt->AttachedToDeviceObject );
  3225. if (!NT_SUCCESS( status )) {
  3226. goto ErrorCleanupDevice;
  3227. }
  3228. devExt->ExtType = FsControlDeviceObject;
  3229. //
  3230. // Set the name
  3231. //
  3232. RtlInitEmptyUnicodeString( &devExt->DeviceName,
  3233. devExt->DeviceNameBuffer,
  3234. sizeof(devExt->DeviceNameBuffer) );
  3235. RtlCopyUnicodeString( &devExt->DeviceName, DeviceName ); //Save Name
  3236. //
  3237. // Mark we are done initializing
  3238. //
  3239. ClearFlag( newDeviceObject->Flags, DO_DEVICE_INITIALIZING );
  3240. //
  3241. // Display who we have attached to
  3242. //
  3243. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  3244. ("DblAttach!DaAttachToFileSystemDevice: Attaching to file system %p \"%wZ\" (%s)\n",
  3245. DeviceObject,
  3246. &devExt->DeviceName,
  3247. GET_DEVICE_TYPE_NAME(newDeviceObject->DeviceType)) );
  3248. //
  3249. // Enumerate all the mounted devices that currently
  3250. // exist for this file system and attach to them.
  3251. //
  3252. status = DaEnumerateFileSystemVolumes( DeviceObject, &tempName );
  3253. if (!NT_SUCCESS( status )) {
  3254. goto ErrorCleanupAttachment;
  3255. }
  3256. return STATUS_SUCCESS;
  3257. /////////////////////////////////////////////////////////////////////
  3258. // Cleanup error handling
  3259. /////////////////////////////////////////////////////////////////////
  3260. ErrorCleanupAttachment:
  3261. IoDetachDevice( devExt->AttachedToDeviceObject );
  3262. ErrorCleanupDevice:
  3263. DaCleanupMountedDevice( newDeviceObject );
  3264. IoDeleteDevice( newDeviceObject );
  3265. return status;
  3266. }
  3267. VOID
  3268. DaDetachFromFileSystemDevice (
  3269. IN PDEVICE_OBJECT DeviceObject
  3270. )
  3271. /*++
  3272. Routine Description:
  3273. Given a base file system device object, this will scan up the attachment
  3274. chain looking for our attached device object. If found it will detach
  3275. us from the chain.
  3276. Arguments:
  3277. DeviceObject - The file system device to detach from.
  3278. Return Value:
  3279. --*/
  3280. {
  3281. PDEVICE_OBJECT ourAttachedDevice;
  3282. PDBLATTACH_CDO_EXTENSION devExt;
  3283. PAGED_CODE();
  3284. //
  3285. // Skip the base file system device object (since it can't be us)
  3286. //
  3287. ourAttachedDevice = DeviceObject->AttachedDevice;
  3288. while (NULL != ourAttachedDevice) {
  3289. if (IS_MY_DEVICE_OBJECT( ourAttachedDevice )) {
  3290. devExt = ourAttachedDevice->DeviceExtension;
  3291. //
  3292. // Display who we detached from
  3293. //
  3294. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  3295. ("DblAttach!DaDetachFromFileSystemDevice: Detaching from file system %p \"%wZ\" (%s)\n",
  3296. devExt->AttachedToDeviceObject,
  3297. &devExt->DeviceName,
  3298. GET_DEVICE_TYPE_NAME(ourAttachedDevice->DeviceType)) );
  3299. //
  3300. // Detach us from the object just below us
  3301. // Cleanup and delete the object
  3302. //
  3303. DaCleanupMountedDevice( ourAttachedDevice );
  3304. IoDetachDevice( DeviceObject );
  3305. IoDeleteDevice( ourAttachedDevice );
  3306. return;
  3307. }
  3308. //
  3309. // Look at the next device up in the attachment chain
  3310. //
  3311. DeviceObject = ourAttachedDevice;
  3312. ourAttachedDevice = ourAttachedDevice->AttachedDevice;
  3313. }
  3314. }
  3315. NTSTATUS
  3316. DaEnumerateFileSystemVolumes (
  3317. IN PDEVICE_OBJECT FSDeviceObject,
  3318. IN PUNICODE_STRING Name
  3319. )
  3320. /*++
  3321. Routine Description:
  3322. Enumerate all the mounted devices that currently exist for the given file
  3323. system and attach to them. We do this because this filter could be loaded
  3324. at any time and there might already be mounted volumes for this file system.
  3325. Arguments:
  3326. FSDeviceObject - The device object for the file system we want to enumerate
  3327. Name - An already initialized unicode string used to retrieve names
  3328. This is passed in to reduce the number of strings buffers on
  3329. the stack.
  3330. Return Value:
  3331. The status of the operation
  3332. --*/
  3333. {
  3334. PDBLATTACH_VDO_EXTENSION newDevExt;
  3335. PDBLATTACH_SHARED_VDO_EXTENSION sharedDevExt;
  3336. PDEVICE_OBJECT *devList;
  3337. PDEVICE_OBJECT diskDeviceObject;
  3338. NTSTATUS status;
  3339. ULONG numDevices;
  3340. ULONG i;
  3341. PAGED_CODE();
  3342. //
  3343. // Find out how big of an array we need to allocate for the
  3344. // mounted device list.
  3345. //
  3346. status = IoEnumerateDeviceObjectList(
  3347. FSDeviceObject->DriverObject,
  3348. NULL,
  3349. 0,
  3350. &numDevices);
  3351. //
  3352. // We only need to get this list of there are devices. If we
  3353. // don't get an error there are no devices so go on.
  3354. //
  3355. if (!NT_SUCCESS( status )) {
  3356. ASSERT(STATUS_BUFFER_TOO_SMALL == status);
  3357. //
  3358. // Allocate memory for the list of known devices
  3359. //
  3360. numDevices += 8; //grab a few extra slots
  3361. devList = ExAllocatePoolWithTag( NonPagedPool,
  3362. (numDevices * sizeof(PDEVICE_OBJECT)),
  3363. DA_POOL_TAG );
  3364. if (NULL == devList) {
  3365. return STATUS_INSUFFICIENT_RESOURCES;
  3366. }
  3367. //
  3368. // Now get the list of devices. If we get an error again
  3369. // something is wrong, so just fail.
  3370. //
  3371. status = IoEnumerateDeviceObjectList(
  3372. FSDeviceObject->DriverObject,
  3373. devList,
  3374. (numDevices * sizeof(PDEVICE_OBJECT)),
  3375. &numDevices);
  3376. if (!NT_SUCCESS( status )) {
  3377. ExFreePool( devList );
  3378. return status;
  3379. }
  3380. //
  3381. // Walk the given list of devices and attach to them if we should.
  3382. //
  3383. for (i=0; i < numDevices; i++) {
  3384. //
  3385. // Do not attach if:
  3386. // - This is the control device object (the one passed in)
  3387. // - We are already attached to it.
  3388. //
  3389. if ((devList[i] != FSDeviceObject) &&
  3390. !DaIsAttachedToDevice( devList[i], NULL )) {
  3391. //
  3392. // See if this device has a name. If so, then it must
  3393. // be a control device so don't attach to it. This handles
  3394. // drivers with more then one control device.
  3395. //
  3396. DaGetBaseDeviceObjectName( devList[i], Name );
  3397. if (Name->Length <= 0) {
  3398. //
  3399. // Get the real (disk) device object associated with this
  3400. // file system device object. Only try to attach if we
  3401. // have a disk device object.
  3402. //
  3403. status = IoGetDiskDeviceObject( devList[i], &diskDeviceObject );
  3404. if (NT_SUCCESS( status )) {
  3405. PDEVICE_OBJECT vdoArray[ VDO_ARRAY_SIZE ];
  3406. //
  3407. // Allocate a new device object to attach with
  3408. //
  3409. status = DaCreateVolumeDeviceObjects( devList[i]->DeviceType,
  3410. VDO_ARRAY_SIZE,
  3411. vdoArray );
  3412. if (NT_SUCCESS( status )) {
  3413. //
  3414. // Set disk device object
  3415. //
  3416. newDevExt = vdoArray[0]->DeviceExtension;
  3417. sharedDevExt = newDevExt->SharedExt;
  3418. sharedDevExt->DiskDeviceObject = diskDeviceObject;
  3419. //
  3420. // Set Device Name
  3421. //
  3422. RtlInitEmptyUnicodeString( &sharedDevExt->DeviceName,
  3423. sharedDevExt->DeviceNameBuffer,
  3424. sizeof(sharedDevExt->DeviceNameBuffer) );
  3425. DaGetObjectName( diskDeviceObject,
  3426. &sharedDevExt->DeviceName );
  3427. //
  3428. // We have done a lot of work since the last time
  3429. // we tested to see if we were already attached
  3430. // to this device object. Test again, this time
  3431. // with a lock, and attach if we are not attached.
  3432. // The lock is used to atomically test if we are
  3433. // attached, and then do the attach.
  3434. //
  3435. ExAcquireFastMutex( &gDblAttachLock );
  3436. if (!DaIsAttachedToDevice( devList[i], NULL )) {
  3437. //
  3438. // Attach to volume.
  3439. //
  3440. status = DaAttachToMountedDevice( devList[i],
  3441. VDO_ARRAY_SIZE,
  3442. vdoArray );
  3443. if (!NT_SUCCESS( status )) {
  3444. //
  3445. // The attachment failed, cleanup. Note that
  3446. // we continue processing so we will cleanup
  3447. // the reference counts and try to attach to
  3448. // the rest of the volumes.
  3449. //
  3450. // One of the reasons this could have failed
  3451. // is because this volume is just being
  3452. // mounted as we are attaching and the
  3453. // DO_DEVICE_INITIALIZING flag has not yet
  3454. // been cleared. A filter could handle
  3455. // this situation by pausing for a short
  3456. // period of time and retrying the attachment.
  3457. //
  3458. DaDeleteMountedDevices( VDO_ARRAY_SIZE, vdoArray );
  3459. }
  3460. } else {
  3461. //
  3462. // We were already attached, cleanup this
  3463. // device object.
  3464. //
  3465. DaDeleteMountedDevices( VDO_ARRAY_SIZE, vdoArray );
  3466. }
  3467. //
  3468. // Release the lock
  3469. //
  3470. ExReleaseFastMutex( &gDblAttachLock );
  3471. }
  3472. //
  3473. // Remove reference added by IoGetDiskDeviceObject.
  3474. // We only need to hold this reference until we are
  3475. // successfully attached to the current volume. Once
  3476. // we are successfully attached to devList[i], the
  3477. // IO Manager will make sure that the underlying
  3478. // diskDeviceObject will not go away until the file
  3479. // system stack is torn down.
  3480. //
  3481. ObDereferenceObject( diskDeviceObject );
  3482. }
  3483. }
  3484. }
  3485. //
  3486. // Dereference the object (reference added by
  3487. // IoEnumerateDeviceObjectList)
  3488. //
  3489. ObDereferenceObject( devList[i] );
  3490. }
  3491. //
  3492. // We are going to ignore any errors received while loading. We
  3493. // simply won't be attached to those volumes if we get an error
  3494. //
  3495. status = STATUS_SUCCESS;
  3496. //
  3497. // Free the memory we allocated for the list
  3498. //
  3499. ExFreePool( devList );
  3500. }
  3501. return status;
  3502. }
  3503. NTSTATUS
  3504. DaAttachToMountedDevice (
  3505. IN PDEVICE_OBJECT DeviceObject,
  3506. IN ULONG NumberOfElements,
  3507. IN OUT PDEVICE_OBJECT *VdoArray
  3508. )
  3509. /*++
  3510. Routine Description:
  3511. This will attach to a DeviceObject that represents a mounted volume.
  3512. Arguments:
  3513. DeviceObject - The device to attach to
  3514. SFilterDeviceObject - Our device object we are going to attach
  3515. DiskDeviceObject - The real device object associated with DeviceObject
  3516. Return Value:
  3517. Status of the operation
  3518. --*/
  3519. {
  3520. PDBLATTACH_VDO_EXTENSION newDevExt;
  3521. NTSTATUS status;
  3522. ULONG index;
  3523. PAGED_CODE();
  3524. ASSERT(IS_MY_DEVICE_OBJECT( VdoArray[0] ));
  3525. ASSERT(!DaIsAttachedToDevice ( DeviceObject, NULL ));
  3526. //
  3527. // Propagate flags from Device Object we are trying to attach to.
  3528. // Note that we do this before the actual attachment to make sure
  3529. // the flags are properly set once we are attached (since an IRP
  3530. // can come in immediately after attachment but before the flags would
  3531. // be set).
  3532. //
  3533. for (index = 0; index < NumberOfElements; index ++) {
  3534. if (FlagOn( DeviceObject->Flags, DO_BUFFERED_IO )) {
  3535. SetFlag( VdoArray[index]->Flags, DO_BUFFERED_IO );
  3536. }
  3537. if (FlagOn( DeviceObject->Flags, DO_DIRECT_IO )) {
  3538. SetFlag( VdoArray[index]->Flags, DO_DIRECT_IO );
  3539. }
  3540. }
  3541. ASSERT( NumberOfElements == 2 );
  3542. //
  3543. // Attach our device object to the given device object
  3544. // The only reason this can fail is if someone is trying to dismount
  3545. // this volume while we are attaching to it.
  3546. //
  3547. //
  3548. // First attach the bottom device.
  3549. //
  3550. newDevExt = VdoArray[0]->DeviceExtension;
  3551. newDevExt->ExtType = FsVolumeLower;
  3552. status = IoAttachDeviceToDeviceStackSafe( VdoArray[0],
  3553. DeviceObject,
  3554. &newDevExt->AttachedToDeviceObject );
  3555. if (!NT_SUCCESS(status)) {
  3556. return status;
  3557. }
  3558. ClearFlag( VdoArray[0]->Flags, DO_DEVICE_INITIALIZING );
  3559. //
  3560. // Second, attach top device
  3561. //
  3562. newDevExt = VdoArray[1]->DeviceExtension;
  3563. newDevExt->ExtType = FsVolumeUpper;
  3564. status = IoAttachDeviceToDeviceStackSafe( VdoArray[1],
  3565. DeviceObject,
  3566. &newDevExt->AttachedToDeviceObject );
  3567. if (!NT_SUCCESS(status)) {
  3568. //
  3569. // Detach our first device object.
  3570. //
  3571. IoDetachDevice( VdoArray[0] );
  3572. return status;
  3573. }
  3574. ClearFlag( VdoArray[1]->Flags, DO_DEVICE_INITIALIZING );
  3575. //
  3576. // Display the name
  3577. //
  3578. newDevExt = VdoArray[0]->DeviceExtension;
  3579. DA_LOG_PRINT( DADEBUG_DISPLAY_ATTACHMENT_NAMES,
  3580. ("DblAttach!DaAttachToMountedDevice: Attaching to volume %p \"%wZ\"\n",
  3581. newDevExt->AttachedToDeviceObject,
  3582. &newDevExt->SharedExt->DeviceName) );
  3583. return status;
  3584. }
  3585. VOID
  3586. DaDeleteMountedDevices (
  3587. IN ULONG NumberOfElements,
  3588. IN PDEVICE_OBJECT *VdoArray
  3589. )
  3590. /*++
  3591. Routine Description:
  3592. Deletes
  3593. Arguments:
  3594. DeviceObject - The device we are cleaning up
  3595. Return Value:
  3596. --*/
  3597. {
  3598. ULONG index;
  3599. ASSERT( NumberOfElements > 0 );
  3600. ASSERT(IS_MY_DEVICE_OBJECT( VdoArray[0] ));
  3601. for (index = 0; index < NumberOfElements; index++ ){
  3602. DaCleanupMountedDevice( VdoArray[index] );
  3603. IoDeleteDevice( VdoArray[index] );
  3604. }
  3605. }
  3606. VOID
  3607. DaCleanupMountedDevice (
  3608. IN PDEVICE_OBJECT DeviceObject
  3609. )
  3610. /*++
  3611. Routine Description:
  3612. This cleans up any allocated memory in the device extension.
  3613. Arguments:
  3614. DeviceObject - The device we are cleaning up
  3615. Return Value:
  3616. --*/
  3617. {
  3618. PDBLATTACH_VDO_EXTENSION devExt;
  3619. devExt = DeviceObject->DeviceExtension;
  3620. if (devExt->ExtType == FsVolumeLower) {
  3621. ExFreePoolWithTag( devExt->SharedExt, DA_POOL_TAG );
  3622. }
  3623. }
  3624. VOID
  3625. DaGetObjectName (
  3626. IN PVOID Object,
  3627. IN OUT PUNICODE_STRING Name
  3628. )
  3629. /*++
  3630. Routine Description:
  3631. This routine will return the name of the given object.
  3632. If a name can not be found an empty string will be returned.
  3633. Arguments:
  3634. Object - The object whose name we want
  3635. Name - A unicode string that is already initialized with a buffer that
  3636. receives the name of the object.
  3637. Return Value:
  3638. None
  3639. --*/
  3640. {
  3641. NTSTATUS status;
  3642. CHAR nibuf[512]; //buffer that receives NAME information and name
  3643. POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION)nibuf;
  3644. ULONG retLength;
  3645. status = ObQueryNameString( Object, nameInfo, sizeof(nibuf), &retLength);
  3646. Name->Length = 0;
  3647. if (NT_SUCCESS( status )) {
  3648. RtlCopyUnicodeString( Name, &nameInfo->Name );
  3649. }
  3650. }
  3651. VOID
  3652. DaGetBaseDeviceObjectName (
  3653. IN PDEVICE_OBJECT DeviceObject,
  3654. IN OUT PUNICODE_STRING Name
  3655. )
  3656. /*++
  3657. Routine Description:
  3658. This locates the base device object in the given attachment chain and then
  3659. returns the name of that object.
  3660. If no name can be found, an empty string is returned.
  3661. Arguments:
  3662. Object - The object whose name we want
  3663. Name - A unicode string that is already initialized with a buffer that
  3664. receives the name of the device object.
  3665. Return Value:
  3666. None
  3667. --*/
  3668. {
  3669. //
  3670. // Get the base file system device object
  3671. //
  3672. DeviceObject = IoGetDeviceAttachmentBaseRef( DeviceObject );
  3673. //
  3674. // Get the name of that object
  3675. //
  3676. DaGetObjectName( DeviceObject, Name );
  3677. //
  3678. // Remove the reference added by IoGetDeviceAttachmentBaseRef
  3679. //
  3680. ObDereferenceObject( DeviceObject );
  3681. }
  3682. BOOLEAN
  3683. DaMonitorFile(
  3684. IN PFILE_OBJECT FileObject,
  3685. IN PDBLATTACH_VDO_EXTENSION VdoExtension
  3686. )
  3687. {
  3688. UNICODE_STRING triggerName;
  3689. UNREFERENCED_PARAMETER( VdoExtension );
  3690. RtlInitUnicodeString( &triggerName, TRIGGER_NAME );
  3691. return RtlEqualUnicodeString( &triggerName, &FileObject->FileName, FALSE );
  3692. }
  3693. PUNICODE_STRING
  3694. DaGetFileName(
  3695. IN PFILE_OBJECT FileObject,
  3696. IN NTSTATUS CreateStatus,
  3697. IN OUT PGET_NAME_CONTROL NameControl
  3698. )
  3699. /*++
  3700. Routine Description:
  3701. This routine will try and get the name of the given file object. This
  3702. is guaranteed to always return a printable string (though it may be NULL).
  3703. This will allocate a buffer if it needs to.
  3704. Arguments:
  3705. FileObject - the file object we want the name for
  3706. CreateStatus - status of the create operation
  3707. NameControl - control structure used for retrieving the name. It keeps
  3708. track if a buffer was allocated or if we are using the internal
  3709. buffer.
  3710. Return Value:
  3711. Pointer to the unicode string with the name
  3712. --*/
  3713. {
  3714. POBJECT_NAME_INFORMATION nameInfo;
  3715. NTSTATUS status;
  3716. ULONG size;
  3717. ULONG bufferSize;
  3718. //
  3719. // Mark we have not allocated the buffer
  3720. //
  3721. NameControl->AllocatedBuffer = NULL;
  3722. //
  3723. // Use the small buffer in the structure (that will handle most cases)
  3724. // for the name
  3725. //
  3726. nameInfo = (POBJECT_NAME_INFORMATION)NameControl->SmallBuffer;
  3727. bufferSize = sizeof(NameControl->SmallBuffer);
  3728. //
  3729. // If the open succeeded, get the name of the file, if it
  3730. // failed, get the name of the device.
  3731. //
  3732. status = ObQueryNameString(
  3733. (NT_SUCCESS( CreateStatus ) ?
  3734. (PVOID)FileObject :
  3735. (PVOID)FileObject->DeviceObject),
  3736. nameInfo,
  3737. bufferSize,
  3738. &size );
  3739. //
  3740. // See if the buffer was to small
  3741. //
  3742. if (status == STATUS_BUFFER_OVERFLOW) {
  3743. //
  3744. // The buffer was too small, allocate one big enough
  3745. //
  3746. bufferSize = size + sizeof(WCHAR);
  3747. NameControl->AllocatedBuffer = ExAllocatePoolWithTag(
  3748. NonPagedPool,
  3749. bufferSize,
  3750. DA_POOL_TAG );
  3751. if (NULL == NameControl->AllocatedBuffer) {
  3752. //
  3753. // Failed allocating a buffer, return an empty string for the name
  3754. //
  3755. RtlInitEmptyUnicodeString(
  3756. (PUNICODE_STRING)&NameControl->SmallBuffer,
  3757. (PWCHAR)(NameControl->SmallBuffer + sizeof(UNICODE_STRING)),
  3758. (USHORT)(sizeof(NameControl->SmallBuffer) - sizeof(UNICODE_STRING)) );
  3759. return (PUNICODE_STRING)&NameControl->SmallBuffer;
  3760. }
  3761. //
  3762. // Set the allocated buffer and get the name again
  3763. //
  3764. nameInfo = (POBJECT_NAME_INFORMATION)NameControl->AllocatedBuffer;
  3765. status = ObQueryNameString(
  3766. FileObject,
  3767. nameInfo,
  3768. bufferSize,
  3769. &size );
  3770. }
  3771. //
  3772. // If we got a name and an error opening the file then we
  3773. // just received the device name. Grab the rest of the name
  3774. // from the FileObject (note that this can only be done if being called
  3775. // from Create). This only happens if we got an error back from the
  3776. // create.
  3777. //
  3778. if (NT_SUCCESS( status ) && !NT_SUCCESS( CreateStatus )) {
  3779. ULONG newSize;
  3780. PCHAR newBuffer;
  3781. POBJECT_NAME_INFORMATION newNameInfo;
  3782. //
  3783. // Calculate the size of the buffer we will need to hold
  3784. // the combined names
  3785. //
  3786. newSize = size + FileObject->FileName.Length;
  3787. //
  3788. // If there is a related file object add in the length
  3789. // of that plus space for a separator
  3790. //
  3791. if (NULL != FileObject->RelatedFileObject) {
  3792. newSize += FileObject->RelatedFileObject->FileName.Length +
  3793. sizeof(WCHAR);
  3794. }
  3795. //
  3796. // See if it will fit in the existing buffer
  3797. //
  3798. if (newSize > bufferSize) {
  3799. //
  3800. // It does not fit, allocate a bigger buffer
  3801. //
  3802. newBuffer = ExAllocatePoolWithTag(
  3803. NonPagedPool,
  3804. newSize,
  3805. DA_POOL_TAG );
  3806. if (NULL == newBuffer) {
  3807. //
  3808. // Failed allocating a buffer, return an empty string for the name
  3809. //
  3810. RtlInitEmptyUnicodeString(
  3811. (PUNICODE_STRING)&NameControl->SmallBuffer,
  3812. (PWCHAR)(NameControl->SmallBuffer + sizeof(UNICODE_STRING)),
  3813. (USHORT)(sizeof(NameControl->SmallBuffer) - sizeof(UNICODE_STRING)) );
  3814. return (PUNICODE_STRING)&NameControl->SmallBuffer;
  3815. }
  3816. //
  3817. // Now initialize the new buffer with the information
  3818. // from the old buffer.
  3819. //
  3820. newNameInfo = (POBJECT_NAME_INFORMATION)newBuffer;
  3821. RtlInitEmptyUnicodeString(
  3822. &newNameInfo->Name,
  3823. (PWCHAR)(newBuffer + sizeof(OBJECT_NAME_INFORMATION)),
  3824. (USHORT)(newSize - sizeof(OBJECT_NAME_INFORMATION)) );
  3825. RtlCopyUnicodeString( &newNameInfo->Name,
  3826. &nameInfo->Name );
  3827. //
  3828. // Free the old allocated buffer (if there is one)
  3829. // and save off the new allocated buffer address. It
  3830. // would be very rare that we should have to free the
  3831. // old buffer because device names should always fit
  3832. // inside it.
  3833. //
  3834. if (NULL != NameControl->AllocatedBuffer) {
  3835. ExFreePool( NameControl->AllocatedBuffer );
  3836. }
  3837. //
  3838. // Readjust our pointers
  3839. //
  3840. NameControl->AllocatedBuffer = newBuffer;
  3841. bufferSize = newSize;
  3842. nameInfo = newNameInfo;
  3843. } else {
  3844. //
  3845. // The MaximumLength was set by ObQueryNameString to
  3846. // one char larger then the length. Set it to the
  3847. // true size of the buffer (so we can append the names)
  3848. //
  3849. nameInfo->Name.MaximumLength = (USHORT)(bufferSize -
  3850. sizeof(OBJECT_NAME_INFORMATION));
  3851. }
  3852. //
  3853. // If there is a related file object, append that name
  3854. // first onto the device object along with a separator
  3855. // character
  3856. //
  3857. if (NULL != FileObject->RelatedFileObject) {
  3858. RtlAppendUnicodeStringToString(
  3859. &nameInfo->Name,
  3860. &FileObject->RelatedFileObject->FileName );
  3861. RtlAppendUnicodeToString( &nameInfo->Name, L"\\" );
  3862. }
  3863. //
  3864. // Append the name from the file object
  3865. //
  3866. RtlAppendUnicodeStringToString( &nameInfo->Name,
  3867. &FileObject->FileName );
  3868. ASSERT(nameInfo->Name.Length <= nameInfo->Name.MaximumLength);
  3869. }
  3870. //
  3871. // Return the name
  3872. //
  3873. return &nameInfo->Name;
  3874. }
  3875. VOID
  3876. DaGetFileNameCleanup(
  3877. IN OUT PGET_NAME_CONTROL NameControl
  3878. )
  3879. /*++
  3880. Routine Description:
  3881. This will see if a buffer was allocated and will free it if it was
  3882. Arguments:
  3883. NameControl - control structure used for retrieving the name. It keeps
  3884. track if a buffer was allocated or if we are using the internal
  3885. buffer.
  3886. Return Value:
  3887. None
  3888. --*/
  3889. {
  3890. if (NULL != NameControl->AllocatedBuffer) {
  3891. ExFreePool( NameControl->AllocatedBuffer);
  3892. NameControl->AllocatedBuffer = NULL;
  3893. }
  3894. }
  3895. BOOLEAN
  3896. DaIsAttachedToDevice (
  3897. PDEVICE_OBJECT DeviceObject,
  3898. PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL
  3899. )
  3900. /*++
  3901. Routine Description:
  3902. This walks down the attachment chain looking for a device object that
  3903. belongs to this driver.
  3904. Arguments:
  3905. DeviceObject - The device chain we want to look through
  3906. Return Value:
  3907. TRUE if we are attached, FALSE if not
  3908. --*/
  3909. {
  3910. PDEVICE_OBJECT currentDevObj;
  3911. PDEVICE_OBJECT nextDevObj;
  3912. //
  3913. // Get the device object at the TOP of the attachment chain
  3914. //
  3915. currentDevObj = IoGetAttachedDeviceReference( DeviceObject );
  3916. //
  3917. // Scan down the list to find our device object.
  3918. //
  3919. do {
  3920. if (IS_MY_DEVICE_OBJECT( currentDevObj )) {
  3921. //
  3922. // We have found that we are already attached. Always remove
  3923. // the reference on this device object, even if we are returning
  3924. // it.
  3925. //
  3926. if (ARGUMENT_PRESENT(AttachedDeviceObject)) {
  3927. *AttachedDeviceObject = currentDevObj;
  3928. }
  3929. ObDereferenceObject( currentDevObj );
  3930. return TRUE;
  3931. }
  3932. //
  3933. // Get the next attached object. This puts a reference on
  3934. // the device object.
  3935. //
  3936. nextDevObj = IoGetLowerDeviceObject( currentDevObj );
  3937. //
  3938. // Dereference our current device object, before
  3939. // moving to the next one.
  3940. //
  3941. ObDereferenceObject( currentDevObj );
  3942. currentDevObj = nextDevObj;
  3943. } while (NULL != currentDevObj);
  3944. //
  3945. // We did not find ourselves on the attachment chain. Return a NULL
  3946. // device object pointer (if requested) and return we did not find
  3947. // ourselves.
  3948. //
  3949. if (ARGUMENT_PRESENT(AttachedDeviceObject)) {
  3950. *AttachedDeviceObject = NULL;
  3951. }
  3952. return FALSE;
  3953. }
  3954. VOID
  3955. DaReadDriverParameters (
  3956. IN PUNICODE_STRING RegistryPath
  3957. )
  3958. /*++
  3959. Routine Description:
  3960. This routine tries to read the sfilter-specific parameters from
  3961. the registry. These values will be found in the registry location
  3962. indicated by the RegistryPath passed in.
  3963. Arguments:
  3964. RegistryPath - the path key passed to the driver during driver entry.
  3965. Return Value:
  3966. None.
  3967. --*/
  3968. {
  3969. OBJECT_ATTRIBUTES attributes;
  3970. HANDLE driverRegKey;
  3971. NTSTATUS status;
  3972. ULONG resultLength;
  3973. UNICODE_STRING valueName;
  3974. UCHAR buffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( LONG )];
  3975. PAGED_CODE();
  3976. //
  3977. // If this value is not zero then somebody has already explicitly set it
  3978. // so don't override those settings.
  3979. //
  3980. if (0 == DaDebug) {
  3981. //
  3982. // Open the desired registry key
  3983. //
  3984. InitializeObjectAttributes( &attributes,
  3985. RegistryPath,
  3986. OBJ_CASE_INSENSITIVE,
  3987. NULL,
  3988. NULL );
  3989. status = ZwOpenKey( &driverRegKey,
  3990. KEY_READ,
  3991. &attributes );
  3992. if (!NT_SUCCESS( status )) {
  3993. return;
  3994. }
  3995. //
  3996. // Read the DebugDisplay value from the registry.
  3997. //
  3998. RtlInitUnicodeString( &valueName, L"DebugFlags" );
  3999. status = ZwQueryValueKey( driverRegKey,
  4000. &valueName,
  4001. KeyValuePartialInformation,
  4002. buffer,
  4003. sizeof(buffer),
  4004. &resultLength );
  4005. if (NT_SUCCESS( status )) {
  4006. DaDebug = *((PLONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data));
  4007. }
  4008. //
  4009. // Close the registry entry
  4010. //
  4011. ZwClose(driverRegKey);
  4012. }
  4013. }