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.

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