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

1741 lines
47 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. This module performs initialization for the SR device driver.
  7. Author:
  8. Paul McDaniel (paulmcd) 23-Jan-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #ifndef DPFLTR_SR_ID
  13. #define DPFLTR_SR_ID 0x00000077
  14. #endif
  15. //
  16. // Private constants.
  17. //
  18. //
  19. // Private types.
  20. //
  21. //
  22. // Private prototypes.
  23. //
  24. EXTERN_C
  25. NTSTATUS
  26. DriverEntry (
  27. IN PDRIVER_OBJECT DriverObject,
  28. IN PUNICODE_STRING RegistryPath
  29. );
  30. VOID
  31. SrUnload (
  32. IN PDRIVER_OBJECT DriverObject
  33. );
  34. VOID
  35. SrFsNotification (
  36. IN PDEVICE_OBJECT pNewDeviceObject,
  37. IN BOOLEAN FsActive
  38. );
  39. NTSTATUS
  40. SrEnumerateFileSystemVolumes (
  41. IN PDEVICE_OBJECT pDeviceObject
  42. );
  43. //
  44. // linker commands
  45. //
  46. #ifdef ALLOC_PRAGMA
  47. #pragma alloc_text( INIT, DriverEntry )
  48. #pragma alloc_text( PAGE, SrUnload )
  49. #if DBG
  50. #pragma alloc_text( PAGE, SrDbgStatus )
  51. #endif
  52. #pragma alloc_text( PAGE, SrFsNotification )
  53. #pragma alloc_text( PAGE, SrAttachToDevice )
  54. #pragma alloc_text( PAGE, SrDetachDevice )
  55. #pragma alloc_text( PAGE, SrGetFilterDevice )
  56. #pragma alloc_text( PAGE, SrAttachToVolumeByName )
  57. #pragma alloc_text( PAGE, SrCreateAttachmentDevice )
  58. #pragma alloc_text( PAGE, SrDeleteAttachmentDevice )
  59. #pragma alloc_text( PAGE, SrEnumerateFileSystemVolumes )
  60. #endif // ALLOC_PRAGMA
  61. //
  62. // Private globals.
  63. //
  64. //
  65. // Public globals.
  66. //
  67. SR_GLOBALS _globals;
  68. PSR_GLOBALS global = &_globals;
  69. #if DBG
  70. SR_STATS SrStats;
  71. #endif
  72. //
  73. // Public functions.
  74. //
  75. /***************************************************************************++
  76. Routine Description:
  77. This is the initialization routine for the UL device driver.
  78. Arguments:
  79. DriverObject - Supplies a pointer to driver object created by the
  80. system.
  81. RegistryPath - Supplies the name of the driver's configuration
  82. registry tree.
  83. Return Value:
  84. NTSTATUS - Completion status.
  85. --***************************************************************************/
  86. NTSTATUS
  87. DriverEntry(
  88. IN PDRIVER_OBJECT DriverObject,
  89. IN PUNICODE_STRING RegistryPath
  90. )
  91. {
  92. NTSTATUS Status;
  93. UNICODE_STRING NameString;
  94. ULONG i;
  95. BOOLEAN bReleaseLock = FALSE;
  96. FS_FILTER_CALLBACKS fsFilterCallbacks;
  97. //
  98. // < dispatch!
  99. //
  100. PAGED_CODE();
  101. ASSERT(DriverObject != NULL);
  102. ASSERT(RegistryPath != NULL);
  103. try {
  104. //
  105. // allocate and clear out our global memory
  106. //
  107. RtlZeroMemory(global, sizeof(SR_GLOBALS));
  108. #if DBG
  109. RtlZeroMemory(&SrStats, sizeof(SR_STATS));
  110. #endif
  111. global->Signature = SR_GLOBALS_TAG;
  112. global->pDriverObject = DriverObject;
  113. InitializeListHead(&global->DeviceExtensionListHead);
  114. //
  115. // Read in our configuration from the registry
  116. //
  117. global->pRegistryLocation = SR_ALLOCATE_STRUCT_WITH_SPACE( PagedPool,
  118. UNICODE_STRING,
  119. RegistryPath->Length + sizeof(WCHAR),
  120. SR_REGISTRY_TAG );
  121. if (global->pRegistryLocation == NULL)
  122. {
  123. Status = STATUS_INSUFFICIENT_RESOURCES;
  124. leave;
  125. }
  126. global->pRegistryLocation->Length = RegistryPath->Length;
  127. global->pRegistryLocation->MaximumLength = RegistryPath->MaximumLength;
  128. global->pRegistryLocation->Buffer = (PWCHAR)(global->pRegistryLocation + 1);
  129. RtlCopyMemory(global->pRegistryLocation->Buffer,
  130. RegistryPath->Buffer,
  131. RegistryPath->Length );
  132. global->pRegistryLocation->Buffer[global->pRegistryLocation->Length/sizeof(WCHAR)] = UNICODE_NULL;
  133. Status = SrReadRegistry(global->pRegistryLocation, TRUE);
  134. if (!NT_SUCCESS(Status))
  135. leave;
  136. //
  137. // give someone a chance to debug startup
  138. //
  139. if (FlagOn(global->DebugControl, SR_DEBUG_BREAK_ON_LOAD))
  140. {
  141. DbgBreakPoint();
  142. }
  143. //
  144. // Init the ERESOURCE (s)
  145. //
  146. Status = ExInitializeResourceLite(&global->GlobalLock);
  147. if (!NT_SUCCESS(Status))
  148. leave;
  149. Status = ExInitializeResourceLite(&global->DeviceExtensionListLock);
  150. if (!NT_SUCCESS(Status))
  151. leave;
  152. Status = ExInitializeResourceLite(&global->BlobLock);
  153. if (!NT_SUCCESS(Status))
  154. leave;
  155. //
  156. // Create our main named device so user-mode can connect
  157. //
  158. RtlInitUnicodeString( &NameString, SR_CONTROL_DEVICE_NAME );
  159. Status = IoCreateDevice( DriverObject, // DriverObject
  160. 0, // DeviceExtension
  161. &NameString, // DeviceName
  162. FILE_DEVICE_UNKNOWN, // DeviceType
  163. FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
  164. FALSE, // Exclusive
  165. &global->pControlDevice ); // DeviceObject
  166. if (!NT_SUCCESS(Status))
  167. leave;
  168. //
  169. // loop through all of the possible major functions
  170. //
  171. for (i = 0 ; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
  172. {
  173. DriverObject->MajorFunction[i] = SrPassThrough;
  174. }
  175. //
  176. // and now hook the ones we care about
  177. //
  178. DriverObject->MajorFunction[IRP_MJ_WRITE] = SrWrite;
  179. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SrCleanup;
  180. DriverObject->MajorFunction[IRP_MJ_CREATE] = SrCreate;
  181. DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = SrSetInformation;
  182. DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = SrSetSecurity;
  183. DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SrFsControl;
  184. DriverObject->MajorFunction[IRP_MJ_PNP] = SrPnp;
  185. DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SrShutdown;
  186. //
  187. // and the fast io path
  188. //
  189. RtlZeroMemory(&global->FastIoDispatch, sizeof(FAST_IO_DISPATCH));
  190. DriverObject->FastIoDispatch = &global->FastIoDispatch;
  191. //
  192. // fill in the fast i/o dispatch pointers
  193. //
  194. DriverObject->FastIoDispatch->SizeOfFastIoDispatch =
  195. sizeof(FAST_IO_DISPATCH);
  196. DriverObject->FastIoDispatch->FastIoCheckIfPossible = SrFastIoCheckIfPossible;
  197. DriverObject->FastIoDispatch->FastIoRead = SrFastIoRead;
  198. DriverObject->FastIoDispatch->FastIoWrite = SrFastIoWrite;
  199. DriverObject->FastIoDispatch->FastIoQueryBasicInfo = SrFastIoQueryBasicInfo;
  200. DriverObject->FastIoDispatch->FastIoQueryStandardInfo = SrFastIoQueryStandardInfo;
  201. DriverObject->FastIoDispatch->FastIoLock = SrFastIoLock;
  202. DriverObject->FastIoDispatch->FastIoUnlockSingle = SrFastIoUnlockSingle;
  203. DriverObject->FastIoDispatch->FastIoUnlockAll = SrFastIoUnlockAll;
  204. DriverObject->FastIoDispatch->FastIoUnlockAllByKey = SrFastIoUnlockAllByKey;
  205. DriverObject->FastIoDispatch->FastIoDeviceControl = SrFastIoDeviceControl;
  206. DriverObject->FastIoDispatch->FastIoDetachDevice = SrFastIoDetachDevice;
  207. DriverObject->FastIoDispatch->FastIoQueryNetworkOpenInfo = SrFastIoQueryNetworkOpenInfo;
  208. DriverObject->FastIoDispatch->MdlRead = SrFastIoMdlRead;
  209. DriverObject->FastIoDispatch->MdlReadComplete = SrFastIoMdlReadComplete;
  210. DriverObject->FastIoDispatch->PrepareMdlWrite = SrFastIoPrepareMdlWrite;
  211. DriverObject->FastIoDispatch->MdlWriteComplete = SrFastIoMdlWriteComplete;
  212. DriverObject->FastIoDispatch->FastIoReadCompressed = SrFastIoReadCompressed;
  213. DriverObject->FastIoDispatch->FastIoWriteCompressed = SrFastIoWriteCompressed;
  214. DriverObject->FastIoDispatch->MdlReadCompleteCompressed = SrFastIoMdlReadCompleteCompressed;
  215. DriverObject->FastIoDispatch->MdlWriteCompleteCompressed = SrFastIoMdlWriteCompleteCompressed;
  216. DriverObject->FastIoDispatch->FastIoQueryOpen = SrFastIoQueryOpen;
  217. //
  218. // these are hooked differently. the fsrtl system does not go via
  219. // attached devices when calling these. so we need to directly hook
  220. // the driver via FsRtlRegisterFileSystemFilterCallbacks
  221. //
  222. DriverObject->FastIoDispatch->AcquireFileForNtCreateSection = NULL;
  223. DriverObject->FastIoDispatch->ReleaseFileForNtCreateSection = NULL;
  224. DriverObject->FastIoDispatch->AcquireForModWrite = NULL;
  225. DriverObject->FastIoDispatch->ReleaseForModWrite = NULL;
  226. DriverObject->FastIoDispatch->AcquireForCcFlush = NULL;
  227. DriverObject->FastIoDispatch->ReleaseForCcFlush = NULL;
  228. //
  229. // Set our unload function
  230. //
  231. if (FlagOn(global->DebugControl, SR_DEBUG_ENABLE_UNLOAD))
  232. {
  233. SrTrace(INIT, ("sr!DriverEntry enabling UNLOAD\n"));
  234. DriverObject->DriverUnload = &SrUnload;
  235. }
  236. #ifdef USE_LOOKASIDE
  237. //
  238. // initialized our lookaside lists
  239. //
  240. ExInitializePagedLookasideList( &global->FileNameBufferLookaside,// Lookaside
  241. NULL, // Allocate
  242. NULL, // Free
  243. 0, // Flags
  244. SR_FILENAME_BUFFER_LENGTH, // Size
  245. SR_FILENAME_BUFFER_TAG, // Tag
  246. SR_FILENAME_BUFFER_DEPTH ); // Depth
  247. #endif
  248. //
  249. // Setup the callbacks for the operations we receive through
  250. // the FsFilter interface.
  251. //
  252. RtlZeroMemory(&fsFilterCallbacks, sizeof(FS_FILTER_CALLBACKS));
  253. fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
  254. fsFilterCallbacks.PreAcquireForSectionSynchronization = SrPreAcquireForSectionSynchronization;
  255. Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
  256. &fsFilterCallbacks );
  257. if (!NT_SUCCESS(Status))
  258. leave;
  259. //
  260. // register for fs registrations, the io manager will also notify us
  261. // of already loaded file systems... so we catch anything regardless of
  262. // when we load. this also catches any already mounted volumes.
  263. //
  264. Status = IoRegisterFsRegistrationChange(DriverObject, SrFsNotification);
  265. if (!NT_SUCCESS(Status))
  266. leave;
  267. //
  268. // start the global logger subsystem
  269. //
  270. Status = SrLoggerStart( DriverObject->DeviceObject,
  271. &global->pLogger );
  272. if (!NT_SUCCESS(Status))
  273. leave;
  274. } finally {
  275. if (!NT_SUCCESS(Status))
  276. {
  277. //
  278. // force an unload which will cleanup all of the created and attached
  279. // devices
  280. //
  281. SrUnload(DriverObject);
  282. }
  283. }
  284. SrTrace( LOAD_UNLOAD, ("SR!DriverEntry complete\n") );
  285. RETURN(Status);
  286. } // DriverEntry
  287. //
  288. // Private functions.
  289. //
  290. /***************************************************************************++
  291. Routine Description:
  292. Unload routine called by the IO subsystem when SR is getting
  293. unloaded.
  294. --***************************************************************************/
  295. VOID
  296. SrUnload(
  297. IN PDRIVER_OBJECT DriverObject
  298. )
  299. {
  300. PSR_DEVICE_EXTENSION pExtension = NULL;
  301. NTSTATUS Status;
  302. LARGE_INTEGER Interval;
  303. PLIST_ENTRY pListEntry = NULL;
  304. //
  305. // Sanity check.
  306. //
  307. PAGED_CODE();
  308. SrTrace( LOAD_UNLOAD, ("SR!SrUnload\n") );
  309. if (global == NULL) {
  310. return;
  311. }
  312. //
  313. // unregister our interest in any new file systems
  314. //
  315. IoUnregisterFsRegistrationChange(DriverObject, SrFsNotification);
  316. //
  317. // disable the driver to prevent anyone from coming in and
  318. // causing logging to start again.
  319. //
  320. global->Disabled = TRUE;
  321. //
  322. // To clean up we need to do the following:
  323. //
  324. // 1) Detach all volumes.
  325. // 2) Wait for all outstanding IOs to complete and all the logs to flush
  326. // to disk.
  327. // 3) Delete all our device objects.
  328. // 4) Cleanup our global structures.
  329. //
  330. //
  331. // Detach all volumes
  332. //
  333. if (IS_RESOURCE_INITIALIZED( &(global->DeviceExtensionListLock) ))
  334. {
  335. try {
  336. SrAcquireDeviceExtensionListLockShared();
  337. for (pListEntry = global->DeviceExtensionListHead.Flink;
  338. pListEntry != &global->DeviceExtensionListHead;
  339. pListEntry = pListEntry->Flink)
  340. {
  341. pExtension = CONTAINING_RECORD( pListEntry,
  342. SR_DEVICE_EXTENSION,
  343. ListEntry );
  344. SrDetachDevice( pExtension->pDeviceObject, FALSE );
  345. } // while (pListEntry != &global->DeviceExtensionListHead)
  346. } finally {
  347. SrReleaseDeviceExtensionListLock();
  348. }
  349. }
  350. //
  351. // Stop the logger and wait for all outstanding IOs to complete
  352. // and all the logs to flush to disk.
  353. //
  354. if (NULL != global->pLogger)
  355. {
  356. Status = SrLoggerStop( global->pLogger );
  357. CHECK_STATUS(Status);
  358. global->pLogger = NULL;
  359. }
  360. //
  361. // wait 5 seconds to make sure the logger is done flushing and the
  362. // outstanding IRPs to complete.
  363. // normally we would never unload.. so this is for debugging
  364. // convenience only.
  365. //
  366. Interval.QuadPart = -1 * (5 * NANO_FULL_SECOND);
  367. KeDelayExecutionThread(KernelMode, TRUE, &Interval);
  368. //
  369. // Delete all our device objects.
  370. //
  371. if (IS_RESOURCE_INITIALIZED( &(global->DeviceExtensionListLock) ))
  372. {
  373. try {
  374. SrAcquireDeviceExtensionListLockExclusive();
  375. pListEntry = global->DeviceExtensionListHead.Flink;
  376. while (pListEntry != &global->DeviceExtensionListHead)
  377. {
  378. pExtension = CONTAINING_RECORD( pListEntry,
  379. SR_DEVICE_EXTENSION,
  380. ListEntry );
  381. //
  382. // Remember this for later since we are about to delete this entry
  383. //
  384. pListEntry = pListEntry->Flink;
  385. //
  386. // Detach from the list.
  387. //
  388. RemoveEntryList( &(pExtension->ListEntry) );
  389. //
  390. // Delete the device
  391. //
  392. SrDeleteAttachmentDevice( pExtension->pDeviceObject );
  393. NULLPTR( pExtension );
  394. }
  395. } finally {
  396. SrReleaseDeviceExtensionListLock();
  397. }
  398. }
  399. //
  400. // Delete our global structures
  401. //
  402. if (NULL != global->pControlDevice)
  403. {
  404. SrTrace(INIT, ( "SR!SrUnload IoDeleteDevice(%p) [control]\n",
  405. global->pControlDevice ));
  406. IoDeleteDevice( global->pControlDevice );
  407. global->pControlDevice = NULL;
  408. }
  409. //
  410. // we better not have anything else lying around.
  411. //
  412. ASSERT(IsListEmpty(&global->DeviceExtensionListHead));
  413. //
  414. // should we update our configuration file ?
  415. //
  416. if (IS_RESOURCE_INITIALIZED( &(global->GlobalLock) ))
  417. {
  418. try {
  419. SrAcquireGlobalLockExclusive();
  420. if (global->FileConfigLoaded)
  421. {
  422. //
  423. // write our the real next file / Seq number (not the +1000)
  424. //
  425. global->FileConfig.FileSeqNumber = global->LastSeqNumber;
  426. global->FileConfig.FileNameNumber = global->LastFileNameNumber;
  427. Status = SrWriteConfigFile();
  428. CHECK_STATUS(Status);
  429. }
  430. } finally {
  431. SrReleaseGlobalLock();
  432. }
  433. }
  434. //
  435. // free the blob info structure
  436. //
  437. if (global->BlobInfoLoaded)
  438. {
  439. Status = SrFreeLookupBlob(&global->BlobInfo);
  440. CHECK_STATUS(Status);
  441. }
  442. if (global->pRegistryLocation != NULL)
  443. {
  444. SR_FREE_POOL(global->pRegistryLocation, SR_REGISTRY_TAG);
  445. global->pRegistryLocation = NULL;
  446. }
  447. //
  448. // cleanup our resources
  449. //
  450. if (IS_RESOURCE_INITIALIZED(&global->GlobalLock))
  451. {
  452. Status = ExDeleteResourceLite(&global->GlobalLock);
  453. ASSERT(NT_SUCCESS(Status));
  454. }
  455. if (IS_RESOURCE_INITIALIZED(&global->BlobLock))
  456. {
  457. Status = ExDeleteResourceLite(&global->BlobLock);
  458. ASSERT(NT_SUCCESS(Status));
  459. }
  460. if (IS_RESOURCE_INITIALIZED(&global->DeviceExtensionListLock))
  461. {
  462. Status = ExDeleteResourceLite(&global->DeviceExtensionListLock);
  463. ASSERT(NT_SUCCESS(Status));
  464. }
  465. #ifdef USE_LOOKASIDE
  466. //
  467. // delete our lookaside list(s)
  468. //
  469. if (IS_LOOKASIDE_INITIALIZED(&global->FileNameBufferLookaside))
  470. {
  471. ExDeletePagedLookasideList(&global->FileNameBufferLookaside);
  472. }
  473. #endif
  474. } // SrUnload
  475. #if DBG
  476. /***************************************************************************++
  477. Routine Description:
  478. Hook for catching failed operations. This routine is called within each
  479. routine with the completion status.
  480. Arguments:
  481. Status - Supplies the completion status.
  482. pFileName - Supplies the filename of the caller.
  483. LineNumber - Supplies the line number of the caller.
  484. Return Value:
  485. NTSTATUS - Completion status.
  486. --***************************************************************************/
  487. NTSTATUS
  488. SrDbgStatus(
  489. IN NTSTATUS Status,
  490. IN PSTR pFileName,
  491. IN USHORT LineNumber
  492. )
  493. {
  494. if (!NT_SUCCESS_NO_DBGBREAK(Status))
  495. {
  496. if ((global == NULL) ||
  497. (FlagOn(global->DebugControl,
  498. SR_DEBUG_VERBOSE_ERRORS|SR_DEBUG_BREAK_ON_ERROR) &&
  499. (STATUS_BUFFER_OVERFLOW != Status) &&
  500. (SR_STATUS_CONTEXT_NOT_SUPPORTED != Status) &&
  501. (SR_STATUS_VOLUME_DISABLED != Status) &&
  502. (SR_STATUS_IGNORE_FILE != Status)))
  503. {
  504. KdPrintEx((DPFLTR_SR_ID, DPFLTR_ERROR_LEVEL,
  505. "SrDbgStatus: %s:%lu returning %08lx\n",
  506. SrpFindFilePart( pFileName ),
  507. LineNumber,
  508. Status));
  509. }
  510. if ((global != NULL) &&
  511. FlagOn(global->DebugControl, SR_DEBUG_BREAK_ON_ERROR) &&
  512. // ignore STATUS_INSUFFICIENT_RESOURCES as the verifier injects
  513. // these normally under stress
  514. (STATUS_INSUFFICIENT_RESOURCES != Status) &&
  515. // ignore DISK_FULL, this happens under stress normally
  516. (STATUS_DISK_FULL != Status) &&
  517. // this happens under stress a lot
  518. (STATUS_BUFFER_OVERFLOW != Status) &&
  519. // This also happens under IOStress because there is a test
  520. // that will just dismount and mount volumes as activity is
  521. // happening.
  522. (STATUS_VOLUME_DISMOUNTED != Status) &&
  523. // This also happens when cleaning up from IOStress. We
  524. // don't disable when we hit this error, so don't break
  525. // here either.
  526. (STATUS_FILE_CORRUPT_ERROR != Status) &&
  527. // Ignore our internal disabled error
  528. (SR_STATUS_VOLUME_DISABLED != Status) &&
  529. // Ignore our internal context not supported error
  530. (SR_STATUS_CONTEXT_NOT_SUPPORTED != Status) &&
  531. // Ignore when we decide to ignore a file
  532. (SR_STATUS_IGNORE_FILE != Status)
  533. )
  534. {
  535. KdBreakPoint();
  536. }
  537. }
  538. return Status;
  539. } // SrDbgStatus
  540. #endif
  541. /***************************************************************************++
  542. Routine Description:
  543. This routine is invoked whenever a file system has either registered or
  544. unregistered itself as an active file system.
  545. For the former case, this routine creates a device object and attaches it
  546. to the specified file system's device object. This allows this driver
  547. to filter all requests to that file system.
  548. For the latter case, this file system's device object is located,
  549. detached, and deleted. This removes this file system as a filter for
  550. the specified file system.
  551. Arguments:
  552. DeviceObject - Pointer to the file system's device object.
  553. FsActive - Boolean indicating whether the file system has registered
  554. (TRUE) or unregistered (FALSE) itself as an active file system.
  555. Return Value:
  556. None.
  557. --***************************************************************************/
  558. VOID
  559. SrFsNotification(
  560. IN PDEVICE_OBJECT pDeviceObject,
  561. IN BOOLEAN FsActive
  562. )
  563. {
  564. NTSTATUS Status;
  565. PAGED_CODE();
  566. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  567. SrTrace( NOTIFY, ( "SR!SrFsNotification: %wZ(%p)\n",
  568. &pDeviceObject->DriverObject->DriverName,
  569. pDeviceObject ));
  570. //
  571. // Begin by determining whether this file system is registering or
  572. // unregistering as an active file system.
  573. //
  574. if (FsActive)
  575. {
  576. //
  577. // The file system has registered as an active file system. attach
  578. // to it.
  579. //
  580. //
  581. // attach to the main driver's control device (like \ntfs)
  582. //
  583. if (SR_IS_SUPPORTED_DEVICE( pDeviceObject ) &&
  584. SrGetFilterDevice( pDeviceObject ) == NULL)
  585. {
  586. PSR_DEVICE_EXTENSION pNewDeviceExtension = NULL;
  587. Status = SrAttachToDevice( NULL, pDeviceObject, NULL, &pNewDeviceExtension );
  588. if (Status != STATUS_BAD_DEVICE_TYPE &&
  589. NT_SUCCESS( Status ))
  590. {
  591. //
  592. // This is a control device object, so set that flag in the
  593. // FsType of the deviceExtension.
  594. //
  595. SetFlag( pNewDeviceExtension->FsType, SrFsControlDeviceObject );
  596. //
  597. // now attach to all the volumes already mounted by this
  598. // file system
  599. //
  600. Status = SrEnumerateFileSystemVolumes( pDeviceObject );
  601. CHECK_STATUS(Status);
  602. }
  603. }
  604. }
  605. else // if (FsActive)
  606. {
  607. PDEVICE_OBJECT pSrDevice;
  608. //
  609. // Call SrGetFilterDevice to safely walk this device object chain
  610. // and find SR's device object.
  611. //
  612. pSrDevice = SrGetFilterDevice( pDeviceObject );
  613. if (pSrDevice != NULL) {
  614. //
  615. // We've found SR's device object, so now detach the device.
  616. //
  617. (VOID)SrDetachDevice(pSrDevice, TRUE);
  618. SrDeleteAttachmentDevice(pSrDevice);
  619. } // while (pNextDevice != NULL)
  620. } // if (FsActive)
  621. } // SrFsNotification
  622. /***************************************************************************++
  623. Routine Description:
  624. This will attach to a DeviceObject that represents a file system or
  625. a mounted volume.
  626. Arguments:
  627. pRealDevice - OPTIONAL if this is a mounted volume this is the disk
  628. device that can be used to fetch the name of the volume out .
  629. pDeviceObject - The file system device to attach to .
  630. pNewDeviceObject - OPTIONAL if this is passed in it is used as the device
  631. to attach to pDeviceObject. if this is NULL a fresh device is
  632. created. this allows callers to preallocate the device object if they
  633. wish. SrMountCompletion uses this.
  634. ppExtension - OPTIONAL will hold the extension of the new device on return.
  635. Return Value:
  636. NTSTATUS - Completion status.
  637. --***************************************************************************/
  638. NTSTATUS
  639. SrAttachToDevice(
  640. IN PDEVICE_OBJECT pRealDevice OPTIONAL,
  641. IN PDEVICE_OBJECT pDeviceObject,
  642. IN PDEVICE_OBJECT pNewDeviceObject OPTIONAL,
  643. OUT PSR_DEVICE_EXTENSION *ppExtension OPTIONAL
  644. )
  645. {
  646. NTSTATUS Status;
  647. PDEVICE_OBJECT pBaseFsDeviceObject = NULL;
  648. PDEVICE_OBJECT pAllocatedDeviceObject = NULL;
  649. PSR_DEVICE_EXTENSION pExtension;
  650. SR_FILESYSTEM_TYPE fsType;
  651. PAGED_CODE();
  652. ASSERT(pRealDevice == NULL || IS_VALID_DEVICE_OBJECT(pRealDevice));
  653. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  654. ASSERT(pNewDeviceObject == NULL || IS_VALID_DEVICE_OBJECT(pNewDeviceObject));
  655. ASSERT(SrGetFilterDevice(pDeviceObject) == NULL);
  656. Status = STATUS_SUCCESS;
  657. //
  658. // only hook fat + ntfs; Check this by looking at the name of the
  659. // base file system device object.
  660. //
  661. pBaseFsDeviceObject = IoGetDeviceAttachmentBaseRef ( pDeviceObject );
  662. ASSERT( pBaseFsDeviceObject != NULL );
  663. if (_wcsnicmp( pBaseFsDeviceObject->DriverObject->DriverName.Buffer,
  664. L"\\FileSystem\\Fastfat",
  665. pBaseFsDeviceObject->DriverObject->DriverName.Length/sizeof(WCHAR) ) == 0) {
  666. fsType = SrFat;
  667. } else if (_wcsnicmp( pBaseFsDeviceObject->DriverObject->DriverName.Buffer,
  668. L"\\FileSystem\\Ntfs",
  669. pBaseFsDeviceObject->DriverObject->DriverName.Length/sizeof(WCHAR) ) == 0 ) {
  670. fsType = SrNtfs;
  671. } else {
  672. Status = STATUS_BAD_DEVICE_TYPE;
  673. goto SrAttachToDevice_Exit;
  674. }
  675. //
  676. // we should only be connecting to fat + ntfs now, these are supported
  677. // device types
  678. //
  679. ASSERT( SR_IS_SUPPORTED_DEVICE( pDeviceObject ) );
  680. ASSERT( pRealDevice == NULL || SR_IS_SUPPORTED_REAL_DEVICE( pRealDevice ));
  681. if (pNewDeviceObject == NULL)
  682. {
  683. //
  684. // create a device now
  685. //
  686. Status = SrCreateAttachmentDevice( pRealDevice,
  687. pDeviceObject,
  688. &pAllocatedDeviceObject );
  689. if (!NT_SUCCESS( Status ))
  690. goto SrAttachToDevice_Exit;
  691. pNewDeviceObject = pAllocatedDeviceObject;
  692. }
  693. pExtension = pNewDeviceObject->DeviceExtension;
  694. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  695. //
  696. // initialize the rest of the device extension
  697. //
  698. pExtension->FsType = fsType;
  699. //
  700. // and create our hash list
  701. //
  702. Status = HashCreateList( BACKUP_BUCKET_COUNT,
  703. BACKUP_BUCKET_LENGTH,
  704. (pExtension->pNtVolumeName != NULL) ?
  705. pExtension->pNtVolumeName->Length : 0,
  706. NULL, // pDestructor
  707. &pExtension->pBackupHistory );
  708. if (!NT_SUCCESS(Status)) {
  709. goto SrAttachToDevice_Exit;
  710. }
  711. try {
  712. //
  713. // Propogate flags
  714. //
  715. if (FlagOn( pDeviceObject->Flags, DO_BUFFERED_IO ))
  716. {
  717. SetFlag( pNewDeviceObject->Flags, DO_BUFFERED_IO);
  718. }
  719. if (FlagOn( pDeviceObject->Flags, DO_DIRECT_IO ))
  720. {
  721. SetFlag( pNewDeviceObject->Flags, DO_DIRECT_IO );
  722. }
  723. //
  724. // Hold the device extension list lock while we attach and insert
  725. // this device extension into our list to ensure that this is done
  726. // atomically.
  727. //
  728. SrAcquireDeviceExtensionListLockExclusive();
  729. Status = IoAttachDeviceToDeviceStackSafe( pNewDeviceObject,
  730. pDeviceObject,
  731. &pExtension->pTargetDevice );
  732. if (!NT_SUCCESS(Status))
  733. {
  734. leave;
  735. }
  736. //
  737. // all done with this, it's attached now. Must NULL this here
  738. // so that it won't get freed when we cleanup.
  739. //
  740. pAllocatedDeviceObject = NULL;
  741. //
  742. // insert it into our global list now that it is attached
  743. //
  744. InsertTailList(&global->DeviceExtensionListHead, &pExtension->ListEntry);
  745. } finally {
  746. SrReleaseDeviceExtensionListLock();
  747. }
  748. if (!NT_SUCCESS( Status )) {
  749. goto SrAttachToDevice_Exit;
  750. }
  751. //
  752. // we are now done initializing our new device
  753. //
  754. ClearFlag( pNewDeviceObject->Flags, DO_DEVICE_INITIALIZING );
  755. SrTrace( INIT, ("SR!SrAttachToDevice:f=%p,t=%p,%wZ [%wZ]\n",
  756. pNewDeviceObject,
  757. pExtension->pTargetDevice,
  758. &(pExtension->pTargetDevice->DriverObject->DriverName),
  759. pExtension->pNtVolumeName ));
  760. //
  761. // return the extension
  762. //
  763. if (ppExtension != NULL)
  764. {
  765. *ppExtension = pExtension;
  766. }
  767. SrAttachToDevice_Exit:
  768. //
  769. // Clear the reference added by calling IoGetDeviceAttachmentBaseRef.
  770. //
  771. if (pBaseFsDeviceObject != NULL) {
  772. ObDereferenceObject (pBaseFsDeviceObject);
  773. }
  774. if (pAllocatedDeviceObject != NULL)
  775. {
  776. SrDeleteAttachmentDevice(pAllocatedDeviceObject);
  777. pAllocatedDeviceObject = NULL;
  778. }
  779. #if DBG
  780. if (Status == STATUS_BAD_DEVICE_TYPE)
  781. {
  782. return Status;
  783. }
  784. #endif
  785. RETURN(Status);
  786. } // SrAttachToDevice
  787. /***************************************************************************++
  788. Routine Description:
  789. this will detach pDeviceObject from it's target device.
  790. Arguments:
  791. pDeviceObject - The unnamed sr device that attached to the file
  792. system device
  793. --***************************************************************************/
  794. VOID
  795. SrDetachDevice(
  796. IN PDEVICE_OBJECT pDeviceObject,
  797. IN BOOLEAN RemoveFromDeviceList
  798. )
  799. {
  800. PSR_DEVICE_EXTENSION pExtension;
  801. NTSTATUS Status;
  802. PAGED_CODE();
  803. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  804. //
  805. // grab the extension
  806. //
  807. pExtension = pDeviceObject->DeviceExtension;
  808. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  809. if (!IS_VALID_SR_DEVICE_EXTENSION(pExtension))
  810. return;
  811. SrTrace(INIT, ( "SR!SrDetachDevice:%p,%wZ [%wZ]\n",
  812. pDeviceObject,
  813. &pExtension->pTargetDevice->DriverObject->DriverName,
  814. pExtension->pNtVolumeName ));
  815. //
  816. // detach the device
  817. //
  818. ASSERT(IS_VALID_DEVICE_OBJECT(pExtension->pTargetDevice));
  819. ASSERT(pExtension->pTargetDevice->AttachedDevice == pDeviceObject);
  820. //
  821. // detach from the device
  822. //
  823. IoDetachDevice(pExtension->pTargetDevice);
  824. try {
  825. SrAcquireActivityLockExclusive( pExtension );
  826. pExtension->Disabled = TRUE;
  827. //
  828. // stop logging ?
  829. //
  830. if (pExtension->pLogContext != NULL)
  831. {
  832. Status = SrLogStop( pExtension, TRUE, FALSE );
  833. CHECK_STATUS(Status);
  834. }
  835. } finally {
  836. SrReleaseActivityLock( pExtension );
  837. }
  838. //
  839. // is it the system volume?
  840. //
  841. if (global->pSystemVolumeExtension == pExtension) {
  842. SrTrace(INIT, ("sr!SrDetachDevice: detaching from the system volume\n"));
  843. global->pSystemVolumeExtension = NULL;
  844. }
  845. //
  846. // remove ourselves from the global list
  847. //
  848. if (RemoveFromDeviceList) {
  849. try {
  850. SrAcquireDeviceExtensionListLockExclusive();
  851. //
  852. // remove ourselves from the global list
  853. //
  854. RemoveEntryList(&pExtension->ListEntry);
  855. } finally {
  856. SrReleaseDeviceExtensionListLock();
  857. }
  858. }
  859. } // SrDetachDevice
  860. /***************************************************************************++
  861. Routine Description:
  862. This routine will see if we are already attached to the given device.
  863. if we are, it returns the device that we used to attach.
  864. Arguments:
  865. DeviceObject - The device chain we want to look through
  866. Return Value:
  867. PDEVICE_OBJECT - NULL if not attached, otherwise the device attached.
  868. --***************************************************************************/
  869. PDEVICE_OBJECT
  870. SrGetFilterDevice(
  871. PDEVICE_OBJECT pDeviceObject
  872. )
  873. {
  874. PDEVICE_OBJECT pNextDevice;
  875. PAGED_CODE();
  876. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  877. //
  878. // we might be in the middle of an attachment chain, get the top device
  879. //
  880. pDeviceObject = IoGetAttachedDeviceReference(pDeviceObject);
  881. //
  882. // now walk down the attachment chain, looking for sr.sys
  883. //
  884. do
  885. {
  886. //
  887. // See if this is OUR device object
  888. //
  889. if (IS_SR_DEVICE_OBJECT(pDeviceObject))
  890. {
  891. ObDereferenceObject(pDeviceObject);
  892. return pDeviceObject;
  893. }
  894. pNextDevice = IoGetLowerDeviceObject(pDeviceObject);
  895. ObDereferenceObject(pDeviceObject);
  896. pDeviceObject = pNextDevice;
  897. } while (NULL != pDeviceObject);
  898. ASSERT(pDeviceObject == NULL);
  899. return NULL;
  900. }
  901. NTSTATUS
  902. SrAttachToVolumeByName(
  903. IN PUNICODE_STRING pVolumeName,
  904. OUT PSR_DEVICE_EXTENSION * ppExtension OPTIONAL
  905. )
  906. {
  907. NTSTATUS Status;
  908. HANDLE VolumeHandle = NULL;
  909. OBJECT_ATTRIBUTES ObjectAttributes;
  910. IO_STATUS_BLOCK IoStatusBlock;
  911. PVPB pVpb;
  912. PFILE_OBJECT pVolumeFileObject = NULL;
  913. PDEVICE_OBJECT pDeviceObject;
  914. ASSERT(pVolumeName != NULL);
  915. PAGED_CODE();
  916. try {
  917. //
  918. // open this volume up, to see it's REAL name (no symbolic links)
  919. //
  920. InitializeObjectAttributes( &ObjectAttributes,
  921. pVolumeName,
  922. OBJ_KERNEL_HANDLE,
  923. NULL,
  924. NULL );
  925. Status = ZwCreateFile( &VolumeHandle,
  926. SYNCHRONIZE,
  927. &ObjectAttributes,
  928. &IoStatusBlock,
  929. NULL,
  930. FILE_ATTRIBUTE_NORMAL,
  931. FILE_SHARE_READ | FILE_SHARE_WRITE,
  932. FILE_OPEN, // OPEN_EXISTING
  933. FILE_SYNCHRONOUS_IO_NONALERT,
  934. NULL,
  935. 0 ); // EaLength
  936. if (!NT_SUCCESS(Status))
  937. leave;
  938. //
  939. // reference the file object
  940. //
  941. Status = ObReferenceObjectByHandle( VolumeHandle,
  942. 0,
  943. *IoFileObjectType,
  944. KernelMode,
  945. (PVOID *) &pVolumeFileObject,
  946. NULL );
  947. if (!NT_SUCCESS(Status))
  948. leave;
  949. ASSERT(IS_VALID_FILE_OBJECT(pVolumeFileObject));
  950. pVpb = pVolumeFileObject->DeviceObject->Vpb;
  951. //
  952. // does it have a real device object
  953. //
  954. // only attach to mounted volumes. we've already attached to
  955. // all of the file systems, any new volume mounts we will
  956. // catch in SrFsControl.
  957. //
  958. if (pVpb != NULL && pVpb->DeviceObject != NULL)
  959. {
  960. //
  961. // attach! are we already attached to it?
  962. //
  963. if (SR_IS_SUPPORTED_VOLUME(pVpb))
  964. {
  965. //
  966. // are we already attached?
  967. //
  968. pDeviceObject = SrGetFilterDevice(pVpb->DeviceObject);
  969. if (pDeviceObject == NULL)
  970. {
  971. //
  972. // nope, attach to the volume
  973. //
  974. Status = SrAttachToDevice( pVpb->RealDevice,
  975. pVpb->DeviceObject,
  976. NULL,
  977. ppExtension );
  978. if (!NT_SUCCESS(Status))
  979. leave;
  980. }
  981. //
  982. // we're already attached, did the caller want a copy of
  983. // the extension ?
  984. //
  985. else if (ppExtension != NULL)
  986. {
  987. ASSERT(IS_SR_DEVICE_OBJECT( pDeviceObject ));
  988. *ppExtension = pDeviceObject->DeviceExtension;
  989. }
  990. }
  991. else
  992. {
  993. Status = STATUS_BAD_DEVICE_TYPE;
  994. leave;
  995. }
  996. }
  997. else
  998. {
  999. Status = STATUS_VOLUME_DISMOUNTED;
  1000. leave;
  1001. }
  1002. } finally {
  1003. Status = FinallyUnwind(SrAttachToVolumeByName, Status);
  1004. if (pVolumeFileObject != NULL)
  1005. {
  1006. ObDereferenceObject(pVolumeFileObject);
  1007. pVolumeFileObject = NULL;
  1008. }
  1009. if (VolumeHandle != NULL)
  1010. {
  1011. ZwClose(VolumeHandle);
  1012. VolumeHandle = NULL;
  1013. }
  1014. }
  1015. #if DBG
  1016. if (Status == STATUS_BAD_DEVICE_TYPE)
  1017. {
  1018. return Status;
  1019. }
  1020. #endif
  1021. RETURN(Status);
  1022. } // SrAttachToVolumeByName
  1023. /***************************************************************************++
  1024. Routine Description:
  1025. Arguments:
  1026. Return Value:
  1027. --***************************************************************************/
  1028. NTSTATUS
  1029. SrCreateAttachmentDevice(
  1030. IN PDEVICE_OBJECT pRealDevice OPTIONAL,
  1031. IN PDEVICE_OBJECT pDeviceObject,
  1032. OUT PDEVICE_OBJECT *ppNewDeviceObject
  1033. )
  1034. {
  1035. NTSTATUS Status;
  1036. BOOLEAN Exclusive;
  1037. PDEVICE_OBJECT pNewDeviceObject = NULL;
  1038. PSR_DEVICE_EXTENSION pExtension = NULL;
  1039. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  1040. PAGED_CODE();
  1041. try {
  1042. Exclusive = FlagOn(pDeviceObject->Flags, DO_EXCLUSIVE) ? TRUE : FALSE;
  1043. Status = IoCreateDevice( global->pDriverObject,
  1044. sizeof( SR_DEVICE_EXTENSION ),
  1045. NULL, // DeviceName
  1046. pDeviceObject->DeviceType,
  1047. pDeviceObject->Characteristics,
  1048. Exclusive,
  1049. &pNewDeviceObject );
  1050. if (!NT_SUCCESS( Status ))
  1051. leave;
  1052. //
  1053. // initialize our device extension
  1054. //
  1055. pExtension = pNewDeviceObject->DeviceExtension;
  1056. RtlZeroMemory(pExtension, sizeof(SR_DEVICE_EXTENSION));
  1057. pExtension->Signature = SR_DEVICE_EXTENSION_TAG;
  1058. pExtension->pDeviceObject = pNewDeviceObject;
  1059. SrInitContextCtrl( pExtension );
  1060. //
  1061. // we only care about volume names.
  1062. //
  1063. if (pRealDevice != NULL)
  1064. {
  1065. ASSERT(SR_IS_SUPPORTED_REAL_DEVICE(pRealDevice));
  1066. //
  1067. // get the nt volume name and stuff it in the extension
  1068. //
  1069. Status = SrAllocateFileNameBuffer( SR_MAX_FILENAME_LENGTH,
  1070. &pExtension->pNtVolumeName );
  1071. if (!NT_SUCCESS(Status))
  1072. leave;
  1073. Status = SrGetObjectName( NULL,
  1074. pRealDevice,
  1075. pExtension->pNtVolumeName,
  1076. SR_FILENAME_BUFFER_LENGTH );
  1077. if (!NT_SUCCESS(Status))
  1078. leave;
  1079. }
  1080. //
  1081. // Initialize the volume activity lock
  1082. //
  1083. ExInitializeResourceLite( &(pExtension->ActivityLock) );
  1084. //
  1085. // The ActivityLockHeldExclusive boolean is initialize to false
  1086. // by zeroing the device extension above.
  1087. //
  1088. // pExtension->ActivityLockHeldExclusive = FALSE;
  1089. //
  1090. // Initialize the volume log lock
  1091. //
  1092. ExInitializeResourceLite( &(pExtension->LogLock) );
  1093. *ppNewDeviceObject = pNewDeviceObject;
  1094. pNewDeviceObject = NULL;
  1095. } finally {
  1096. Status = FinallyUnwind(SrCreateAttachmentDevice, Status);
  1097. if (pNewDeviceObject != NULL)
  1098. {
  1099. SrDeleteAttachmentDevice(pNewDeviceObject);
  1100. pNewDeviceObject = NULL;
  1101. }
  1102. }
  1103. RETURN(Status);
  1104. } // SrCreateAttachmentDevice
  1105. /***************************************************************************++
  1106. Routine Description:
  1107. Arguments:
  1108. Return Value:
  1109. --***************************************************************************/
  1110. VOID
  1111. SrDeleteAttachmentDevice(
  1112. IN PDEVICE_OBJECT pDeviceObject
  1113. )
  1114. {
  1115. PSR_DEVICE_EXTENSION pExtension;
  1116. PAGED_CODE();
  1117. pExtension = pDeviceObject->DeviceExtension;
  1118. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  1119. if (IS_VALID_SR_DEVICE_EXTENSION(pExtension))
  1120. {
  1121. if (pExtension->pNtVolumeName != NULL)
  1122. {
  1123. SrFreeFileNameBuffer(pExtension->pNtVolumeName);
  1124. pExtension->pNtVolumeName = NULL;
  1125. }
  1126. //
  1127. // clear our hash list
  1128. //
  1129. if (pExtension->pBackupHistory != NULL)
  1130. {
  1131. HashDestroyList(pExtension->pBackupHistory);
  1132. pExtension->pBackupHistory = NULL;
  1133. }
  1134. //
  1135. // Remove all existing contexts then cleanup the structure
  1136. //
  1137. SrCleanupContextCtrl( pExtension );
  1138. pExtension->Signature = MAKE_FREE_TAG(pExtension->Signature);
  1139. }
  1140. if (IS_RESOURCE_INITIALIZED( &(pExtension->ActivityLock) ))
  1141. {
  1142. ExDeleteResourceLite( &(pExtension->ActivityLock) );
  1143. }
  1144. if (IS_RESOURCE_INITIALIZED( &(pExtension->LogLock) ))
  1145. {
  1146. ExDeleteResourceLite( &(pExtension->LogLock) );
  1147. }
  1148. IoDeleteDevice(pDeviceObject);
  1149. } // SrDeleteAttachmentDevice
  1150. /***************************************************************************++
  1151. Routine Description:
  1152. Enumerate all the mounted devices that currently exist for the given file
  1153. system and attach to them. We do this because this filter could be loaded
  1154. at any time and there might already be mounted volumes for this file system.
  1155. Arguments:
  1156. pDeviceObject - The device object for the file system we want to enumerate
  1157. Return Value:
  1158. NTSTATUS - Completion status.
  1159. --***************************************************************************/
  1160. NTSTATUS
  1161. SrEnumerateFileSystemVolumes(
  1162. IN PDEVICE_OBJECT pDeviceObject
  1163. )
  1164. {
  1165. PDEVICE_OBJECT *ppDeviceList = NULL;
  1166. PDEVICE_OBJECT pRealDevice;
  1167. NTSTATUS Status;
  1168. ULONG DeviceCount;
  1169. ULONG i;
  1170. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  1171. PAGED_CODE();
  1172. //
  1173. // Find out how big of an array we need to allocate for the
  1174. // mounted device list.
  1175. //
  1176. Status = IoEnumerateDeviceObjectList( pDeviceObject->DriverObject,
  1177. NULL,
  1178. 0,
  1179. &DeviceCount);
  1180. //
  1181. // We only need to get this list of there are devices. If we
  1182. // don't get an error there are no devices so go on.
  1183. //
  1184. if (Status != STATUS_BUFFER_TOO_SMALL) {
  1185. return Status;
  1186. }
  1187. //
  1188. // Allocate memory for the list of known devices
  1189. //
  1190. DeviceCount += 2; //grab a few extra slots
  1191. ppDeviceList = SR_ALLOCATE_POOL( NonPagedPool,
  1192. (DeviceCount * sizeof(PDEVICE_OBJECT)),
  1193. SR_DEVICE_LIST_TAG );
  1194. if (NULL == ppDeviceList)
  1195. {
  1196. Status = STATUS_INSUFFICIENT_RESOURCES;
  1197. goto SrEnumerateFileSystemVolumes_Exit;
  1198. }
  1199. //
  1200. // Now get the list of devices. If we get an error again
  1201. // something is wrong, so just fail.
  1202. //
  1203. Status = IoEnumerateDeviceObjectList( pDeviceObject->DriverObject,
  1204. ppDeviceList,
  1205. (DeviceCount * sizeof(PDEVICE_OBJECT)),
  1206. &DeviceCount );
  1207. if (!NT_SUCCESS( Status )) {
  1208. goto SrEnumerateFileSystemVolumes_Exit;
  1209. }
  1210. //
  1211. // Walk the given list of devices and attach to them if we should.
  1212. //
  1213. for (i = 0; i < DeviceCount; i++)
  1214. {
  1215. //
  1216. // Do not attach if:
  1217. // - This is the control device object (the one passed in)
  1218. // - We are already attached to it
  1219. //
  1220. if (ppDeviceList[i] != pDeviceObject &&
  1221. SrGetFilterDevice(ppDeviceList[i]) == NULL)
  1222. {
  1223. //
  1224. // Get the disk device object associated with this
  1225. // file system device object. Only try to attach if we
  1226. // have a storage device object. If the device does not
  1227. // have
  1228. //
  1229. Status = IoGetDiskDeviceObject( ppDeviceList[i], &pRealDevice);
  1230. //
  1231. // don't dbgbreak, as it might not be a properly mounted
  1232. // volume, we can ignore these
  1233. //
  1234. if (NT_SUCCESS_NO_DBGBREAK( Status ) &&
  1235. SR_IS_SUPPORTED_REAL_DEVICE(pRealDevice) )
  1236. {
  1237. Status = SrAttachToDevice( pRealDevice,
  1238. ppDeviceList[i],
  1239. NULL,
  1240. NULL );
  1241. CHECK_STATUS(Status);
  1242. //
  1243. // Remove reference added by IoGetDiskDeviceObject.
  1244. // We only need to hold this reference until we are
  1245. // successfully attached to the current volume. Once
  1246. // we are successfully attached to ppDeviceList[i], the
  1247. // IO Manager will make sure that the underlying
  1248. // diskDeviceObject will not go away until the file
  1249. // system stack is torn down.
  1250. //
  1251. ObDereferenceObject(pRealDevice);
  1252. pRealDevice = NULL;
  1253. }
  1254. }
  1255. //
  1256. // Dereference the object (reference added by
  1257. // IoEnumerateDeviceObjectList)
  1258. //
  1259. ObDereferenceObject( ppDeviceList[i] );
  1260. ppDeviceList[i] = NULL;
  1261. }
  1262. //
  1263. // We are going to ignore any errors received while mounting. We
  1264. // simply won't be attached to those volumes if we get an error
  1265. //
  1266. Status = STATUS_SUCCESS;
  1267. SrEnumerateFileSystemVolumes_Exit:
  1268. //
  1269. // Free the memory we allocated for the list
  1270. //
  1271. if (ppDeviceList != NULL)
  1272. {
  1273. SR_FREE_POOL(ppDeviceList, SR_DEVICE_LIST_TAG);
  1274. }
  1275. RETURN(Status);
  1276. } // SrEnumerateFileSystemVolumes