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.

3650 lines
95 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. dispatch.c
  5. Abstract:
  6. this is the major function code dispatch filter layer.
  7. Author:
  8. Paul McDaniel (paulmcd) 23-Jan-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. //
  13. // Private constants.
  14. //
  15. #if DBG
  16. PWSTR IrpMjCodes[] =
  17. {
  18. L"IRP_MJ_CREATE",
  19. L"IRP_MJ_CREATE_NAMED_PIPE",
  20. L"IRP_MJ_CLOSE",
  21. L"IRP_MJ_READ",
  22. L"IRP_MJ_WRITE",
  23. L"IRP_MJ_QUERY_INFORMATION",
  24. L"IRP_MJ_SET_INFORMATION",
  25. L"IRP_MJ_QUERY_EA",
  26. L"IRP_MJ_SET_EA",
  27. L"IRP_MJ_FLUSH_BUFFERS",
  28. L"IRP_MJ_QUERY_VOLUME_INFORMATION",
  29. L"IRP_MJ_SET_VOLUME_INFORMATION",
  30. L"IRP_MJ_DIRECTORY_CONTROL",
  31. L"IRP_MJ_FILE_SYSTEM_CONTROL",
  32. L"IRP_MJ_DEVICE_CONTROL",
  33. L"IRP_MJ_INTERNAL_DEVICE_CONTROL",
  34. L"IRP_MJ_SHUTDOWN",
  35. L"IRP_MJ_LOCK_CONTROL",
  36. L"IRP_MJ_CLEANUP",
  37. L"IRP_MJ_CREATE_MAILSLOT",
  38. L"IRP_MJ_QUERY_SECURITY",
  39. L"IRP_MJ_SET_SECURITY",
  40. L"IRP_MJ_POWER",
  41. L"IRP_MJ_SYSTEM_CONTROL",
  42. L"IRP_MJ_DEVICE_CHANGE",
  43. L"IRP_MJ_QUERY_QUOTA",
  44. L"IRP_MJ_SET_QUOTA",
  45. L"IRP_MJ_PNP",
  46. L"IRP_MJ_MAXIMUM_FUNCTION",
  47. };
  48. #endif // DBG
  49. //
  50. // Private types.
  51. //
  52. //
  53. // Private prototypes.
  54. //
  55. NTSTATUS
  56. SrCreateRestorePointIoctl (
  57. IN PIRP pIrp,
  58. IN PIO_STACK_LOCATION IrpSp
  59. );
  60. NTSTATUS
  61. SrGetNextSeqNumIoctl (
  62. IN PIRP pIrp,
  63. IN PIO_STACK_LOCATION IrpSp
  64. );
  65. NTSTATUS
  66. SrReloadConfigurationIoctl (
  67. IN PIRP pIrp,
  68. IN PIO_STACK_LOCATION IrpSp
  69. );
  70. NTSTATUS
  71. SrSwitchAllLogsIoctl (
  72. IN PIRP pIrp,
  73. IN PIO_STACK_LOCATION IrpSp
  74. );
  75. NTSTATUS
  76. SrDisableVolumeIoctl (
  77. IN PIRP pIrp,
  78. IN PIO_STACK_LOCATION IrpSp
  79. );
  80. NTSTATUS
  81. SrStartMonitoringIoctl (
  82. IN PIRP pIrp,
  83. IN PIO_STACK_LOCATION IrpSp
  84. );
  85. NTSTATUS
  86. SrStopMonitoringIoctl (
  87. IN PIRP pIrp,
  88. IN PIO_STACK_LOCATION IrpSp
  89. );
  90. NTSTATUS
  91. SrDismountCompletion(
  92. IN PDEVICE_OBJECT DeviceObject,
  93. IN PIRP Irp,
  94. IN PVOID Context
  95. );
  96. //
  97. // linker commands
  98. //
  99. #ifdef ALLOC_PRAGMA
  100. #pragma alloc_text( PAGE, SrMajorFunction )
  101. #pragma alloc_text( PAGE, SrCleanup )
  102. #pragma alloc_text( PAGE, SrCreate )
  103. #pragma alloc_text( PAGE, SrSetInformation )
  104. #pragma alloc_text( PAGE, SrSetHardLink )
  105. #pragma alloc_text( PAGE, SrSetSecurity )
  106. #pragma alloc_text( PAGE, SrCreateRestorePointIoctl )
  107. #pragma alloc_text( PAGE, SrFsControl )
  108. #pragma alloc_text( PAGE, SrFsControlReparsePoint )
  109. #pragma alloc_text( PAGE, SrFsControlMount )
  110. #pragma alloc_text( PAGE, SrFsControlLockOrDismount)
  111. #pragma alloc_text( PAGE, SrFsControlWriteRawEncrypted )
  112. #pragma alloc_text( PAGE, SrFsControlSetSparse )
  113. #pragma alloc_text( PAGE, SrPnp )
  114. #pragma alloc_text( PAGE, SrGetNextSeqNumIoctl )
  115. #pragma alloc_text( PAGE, SrReloadConfigurationIoctl )
  116. #pragma alloc_text( PAGE, SrSwitchAllLogsIoctl )
  117. #pragma alloc_text( PAGE, SrDisableVolumeIoctl )
  118. #pragma alloc_text( PAGE, SrStartMonitoringIoctl )
  119. #pragma alloc_text( PAGE, SrStopMonitoringIoctl )
  120. #pragma alloc_text( PAGE, SrShutdown )
  121. #endif // ALLOC_PRAGMA
  122. #if 0
  123. NOT PAGEABLE -- SrPassThrough
  124. NOT PAGEABLE -- SrWrite
  125. #endif // 0
  126. //
  127. // Private globals.
  128. //
  129. //
  130. // Lookup table to verify incoming IOCTL codes.
  131. //
  132. typedef
  133. NTSTATUS
  134. (NTAPI * PFN_IOCTL_HANDLER)(
  135. IN PIRP pIrp,
  136. IN PIO_STACK_LOCATION IrpSp
  137. );
  138. typedef struct _SR_IOCTL_TABLE
  139. {
  140. ULONG IoControlCode;
  141. PFN_IOCTL_HANDLER Handler;
  142. } SR_IOCTL_TABLE, *PSR_IOCTL_TABLE;
  143. SR_IOCTL_TABLE SrIoctlTable[] =
  144. {
  145. { IOCTL_SR_CREATE_RESTORE_POINT, &SrCreateRestorePointIoctl },
  146. { IOCTL_SR_RELOAD_CONFIG, &SrReloadConfigurationIoctl },
  147. { IOCTL_SR_START_MONITORING, &SrStartMonitoringIoctl },
  148. { IOCTL_SR_STOP_MONITORING, &SrStopMonitoringIoctl },
  149. { IOCTL_SR_WAIT_FOR_NOTIFICATION, &SrWaitForNotificationIoctl },
  150. { IOCTL_SR_SWITCH_LOG, &SrSwitchAllLogsIoctl },
  151. { IOCTL_SR_DISABLE_VOLUME, &SrDisableVolumeIoctl },
  152. { IOCTL_SR_GET_NEXT_SEQUENCE_NUM, &SrGetNextSeqNumIoctl }
  153. };
  154. C_ASSERT( SR_NUM_IOCTLS == DIMENSION(SrIoctlTable) );
  155. //
  156. // Public globals.
  157. //
  158. //
  159. // Public functions.
  160. //
  161. /***************************************************************************++
  162. Routine Description:
  163. Does any pre or post work for the IRP then passes it through to the
  164. lower layer driver.
  165. NOTE: This routine is NOT pageable
  166. Arguments:
  167. Return Value:
  168. NTSTATUS - Status code.
  169. --***************************************************************************/
  170. NTSTATUS
  171. SrPassThrough(
  172. IN PDEVICE_OBJECT DeviceObject,
  173. IN PIRP pIrp
  174. )
  175. {
  176. PSR_DEVICE_EXTENSION pExtension;
  177. //
  178. // this is NonPaged code!
  179. //
  180. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  181. ASSERT(IS_VALID_DEVICE_OBJECT(DeviceObject));
  182. ASSERT(IS_VALID_IRP(pIrp));
  183. //
  184. // Is this a function for our Control Device Object?
  185. //
  186. if (DeviceObject == _globals.pControlDevice)
  187. {
  188. return SrMajorFunction(DeviceObject, pIrp);
  189. }
  190. //
  191. // else it is a device we've attached to , grab our extension
  192. //
  193. ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
  194. pExtension = DeviceObject->DeviceExtension;
  195. //
  196. // Now call the appropriate file system driver with the request.
  197. //
  198. IoSkipCurrentIrpStackLocation(pIrp);
  199. return IoCallDriver(pExtension->pTargetDevice, pIrp);
  200. } // SrPassThrough
  201. /***************************************************************************++
  202. Routine Description:
  203. Handles IRPs for the actual device control object vs. the sub-level
  204. fsd we are attached to .
  205. Arguments:
  206. Return Value:
  207. NTSTATUS - Status code.
  208. --***************************************************************************/
  209. NTSTATUS
  210. SrMajorFunction(
  211. IN PDEVICE_OBJECT pDeviceObject,
  212. IN PIRP pIrp
  213. )
  214. {
  215. NTSTATUS Status;
  216. PIO_STACK_LOCATION pIrpSp;
  217. PSR_CONTROL_OBJECT pControlObject;
  218. ULONG Code;
  219. ULONG FunctionCode;
  220. PFILE_FULL_EA_INFORMATION pEaBuffer;
  221. PSR_OPEN_PACKET pOpenPacket;
  222. UNREFERENCED_PARAMETER( pDeviceObject );
  223. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  224. ASSERT(IS_VALID_IRP(pIrp));
  225. ASSERT(pDeviceObject == _globals.pControlDevice);
  226. //
  227. // < dispatch!
  228. //
  229. PAGED_CODE();
  230. SrTrace(FUNC_ENTRY, (
  231. "SR!SrMajorFunction(Function=%ls)\n",
  232. IrpMjCodes[IoGetCurrentIrpStackLocation(pIrp)->MajorFunction]
  233. ));
  234. Status = STATUS_SUCCESS;
  235. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  236. switch (pIrpSp->MajorFunction)
  237. {
  238. //
  239. // IRP_MJ_CREATE is called to create a new HANDLE on
  240. // SR_CONTROL_DEVICE_NAME
  241. //
  242. case IRP_MJ_CREATE:
  243. //
  244. // Find and validate the open packet.
  245. //
  246. pEaBuffer = (PFILE_FULL_EA_INFORMATION)
  247. (pIrp->AssociatedIrp.SystemBuffer);
  248. if (pEaBuffer == NULL ||
  249. pEaBuffer->EaValueLength != sizeof(*pOpenPacket) ||
  250. pEaBuffer->EaNameLength != SR_OPEN_PACKET_NAME_LENGTH ||
  251. strcmp( pEaBuffer->EaName, SR_OPEN_PACKET_NAME ) )
  252. {
  253. Status = STATUS_REVISION_MISMATCH;
  254. goto CompleteTheIrp;
  255. }
  256. pOpenPacket =
  257. (PSR_OPEN_PACKET)( pEaBuffer->EaName + pEaBuffer->EaNameLength + 1 );
  258. ASSERT( (((ULONG_PTR)pOpenPacket) & 7) == 0 );
  259. //
  260. // For now, we'll fail if the incoming version doesn't EXACTLY match
  261. // the expected version. In future, we may need to be a bit more
  262. // flexible to allow down-level clients.
  263. //
  264. if (pOpenPacket->MajorVersion != SR_INTERFACE_VERSION_MAJOR ||
  265. pOpenPacket->MinorVersion != SR_INTERFACE_VERSION_MINOR)
  266. {
  267. Status = STATUS_REVISION_MISMATCH;
  268. goto CompleteTheIrp;
  269. }
  270. if (_globals.pControlObject != NULL)
  271. {
  272. Status = STATUS_DEVICE_ALREADY_ATTACHED;
  273. goto CompleteTheIrp;
  274. }
  275. try {
  276. //
  277. // grab the lock
  278. //
  279. SrAcquireGlobalLockExclusive();
  280. //
  281. // Double check to make sure that the ControlObject hasn't
  282. // been created while we were waiting to get the lock.
  283. //
  284. if (_globals.pControlObject != NULL)
  285. {
  286. Status = STATUS_DEVICE_ALREADY_ATTACHED;
  287. leave;
  288. }
  289. //
  290. // Create a new OBJECT
  291. //
  292. Status = SrCreateControlObject(&pControlObject, 0);
  293. if (!NT_SUCCESS(Status))
  294. {
  295. leave;
  296. }
  297. ASSERT(IS_VALID_CONTROL_OBJECT(pControlObject));
  298. //
  299. // store the object in the file
  300. //
  301. pIrpSp->FileObject->FsContext = pControlObject;
  302. pIrpSp->FileObject->FsContext2 = SR_CONTROL_OBJECT_CONTEXT;
  303. //
  304. // and keep a global copy
  305. //
  306. _globals.pControlObject = pControlObject;
  307. } finally {
  308. SrReleaseGlobalLock();
  309. }
  310. if (!NT_SUCCESS( Status )) {
  311. goto CompleteTheIrp;
  312. }
  313. break;
  314. //
  315. // IRP_MJ_CLOSE is called when all references are gone.
  316. // Note: this operation can not be failed. It must succeed.
  317. //
  318. case IRP_MJ_CLOSE:
  319. pControlObject = pIrpSp->FileObject->FsContext;
  320. ASSERT(_globals.pControlObject == pControlObject);
  321. ASSERT(IS_VALID_CONTROL_OBJECT(pControlObject));
  322. ASSERT(pIrpSp->FileObject->FsContext2 == SR_CONTROL_OBJECT_CONTEXT);
  323. try {
  324. SrAcquireGlobalLockExclusive();
  325. //
  326. // delete the control object
  327. //
  328. Status = SrDeleteControlObject(pControlObject);
  329. if (!NT_SUCCESS(Status))
  330. {
  331. leave;
  332. }
  333. pIrpSp->FileObject->FsContext2 = NULL;
  334. pIrpSp->FileObject->FsContext = NULL;
  335. //
  336. // clear out the global
  337. //
  338. _globals.pControlObject = NULL;
  339. } finally {
  340. SrReleaseGlobalLock();
  341. }
  342. break;
  343. //
  344. // IRP_MJ_DEVICE_CONTROL is how most user-mode api's drop into here
  345. //
  346. case IRP_MJ_DEVICE_CONTROL:
  347. //
  348. // Extract the IOCTL control code and process the request.
  349. //
  350. Code = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
  351. FunctionCode = IoGetFunctionCodeFromCtlCode(Code);
  352. if (FunctionCode < SR_NUM_IOCTLS &&
  353. SrIoctlTable[FunctionCode].IoControlCode == Code)
  354. {
  355. #if DBG
  356. KIRQL oldIrql = KeGetCurrentIrql();
  357. #endif // DBG
  358. Status = (SrIoctlTable[FunctionCode].Handler)( pIrp, pIrpSp );
  359. ASSERT( KeGetCurrentIrql() == oldIrql );
  360. if (!NT_SUCCESS(Status)) {
  361. goto CompleteTheIrp;
  362. }
  363. }
  364. else
  365. {
  366. //
  367. // If we made it this far, then the ioctl is invalid.
  368. //
  369. Status = STATUS_INVALID_DEVICE_REQUEST;
  370. goto CompleteTheIrp;
  371. }
  372. break;
  373. //
  374. // IRP_MJ_CLEANUP is called when all handles are closed
  375. // Note: this operation can not be failed. It must succeed.
  376. //
  377. case IRP_MJ_CLEANUP:
  378. pControlObject = pIrpSp->FileObject->FsContext;
  379. ASSERT(_globals.pControlObject == pControlObject);
  380. ASSERT(IS_VALID_CONTROL_OBJECT(pControlObject));
  381. ASSERT(pIrpSp->FileObject->FsContext2 == SR_CONTROL_OBJECT_CONTEXT);
  382. try {
  383. SrAcquireGlobalLockExclusive();
  384. //
  385. // cancel all IO on this object
  386. //
  387. Status = SrCancelControlIo(pControlObject);
  388. CHECK_STATUS(Status);
  389. } finally {
  390. SrReleaseGlobalLock();
  391. }
  392. break;
  393. default:
  394. //
  395. // unsupported!
  396. //
  397. Status = STATUS_INVALID_DEVICE_REQUEST;
  398. break;
  399. }
  400. //
  401. // Complete the request if we are DONE.
  402. //
  403. CompleteTheIrp:
  404. if (Status != STATUS_PENDING)
  405. {
  406. pIrp->IoStatus.Status = Status;
  407. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  408. NULLPTR(pIrp);
  409. }
  410. ASSERT(Status != SR_STATUS_VOLUME_DISABLED);
  411. #if DBG
  412. if (Status == STATUS_INVALID_DEVICE_REQUEST ||
  413. Status == STATUS_DEVICE_ALREADY_ATTACHED ||
  414. Status == STATUS_REVISION_MISMATCH)
  415. {
  416. //
  417. // don't DbgBreak on this, test tools pass garbage in normally
  418. // to test this code path out.
  419. //
  420. return Status;
  421. }
  422. #endif
  423. RETURN(Status);
  424. } // SrMajorFunction
  425. /***************************************************************************++
  426. Routine Description:
  427. Arguments:
  428. Handle WRITE Irps.
  429. NOTE: This routine is NOT pageable.
  430. Return Value:
  431. NTSTATUS - Status code.
  432. --***************************************************************************/
  433. NTSTATUS
  434. SrWrite(
  435. IN PDEVICE_OBJECT DeviceObject,
  436. IN PIRP pIrp
  437. )
  438. {
  439. PSR_DEVICE_EXTENSION pExtension;
  440. PIO_STACK_LOCATION pIrpSp;
  441. PSR_STREAM_CONTEXT pFileContext;
  442. NTSTATUS eventStatus;
  443. //
  444. // This cannot be paged because it is called from
  445. // the paging path.
  446. //
  447. ASSERT(IS_VALID_DEVICE_OBJECT(DeviceObject));
  448. ASSERT(IS_VALID_IRP(pIrp));
  449. //
  450. // Is this a function for our control device object (vs an attachee)?
  451. //
  452. if (DeviceObject == _globals.pControlDevice)
  453. {
  454. return SrMajorFunction(DeviceObject, pIrp);
  455. }
  456. //
  457. // else it is a device we've attached to , grab our extension
  458. //
  459. ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
  460. pExtension = DeviceObject->DeviceExtension;
  461. //
  462. // See if logging is enabled and we don't care about this type of IO
  463. // to the file systems' control device objects.
  464. //
  465. if (!SR_LOGGING_ENABLED(pExtension) ||
  466. SR_IS_FS_CONTROL_DEVICE(pExtension))
  467. {
  468. goto CompleteTheIrp;
  469. }
  470. //
  471. // ignore all paging i/o for now. we catch all write's prior to
  472. // the cache manager even seeing them.
  473. //
  474. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  475. if (FlagOn(pIrp->Flags, IRP_PAGING_IO))
  476. {
  477. goto CompleteTheIrp;
  478. }
  479. //
  480. // Ignore files with no name
  481. //
  482. if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pIrpSp->FileObject ) ||
  483. FILE_OBJECT_DOES_NOT_HAVE_VPB( pIrpSp->FileObject ))
  484. {
  485. goto CompleteTheIrp;
  486. }
  487. //
  488. // Get the context now so we can determine if this is a
  489. // directory or not
  490. //
  491. eventStatus = SrGetContext( pExtension,
  492. pIrpSp->FileObject,
  493. SrEventStreamChange,
  494. &pFileContext );
  495. if (!NT_SUCCESS( eventStatus ))
  496. {
  497. goto CompleteTheIrp;
  498. }
  499. //
  500. // If this is a directory don't bother logging because the
  501. // operation will fail.
  502. //
  503. if (FlagOn(pFileContext->Flags,CTXFL_IsInteresting) && !FlagOn(pFileContext->Flags,CTXFL_IsDirectory))
  504. {
  505. SrHandleEvent( pExtension,
  506. SrEventStreamChange,
  507. pIrpSp->FileObject,
  508. pFileContext,
  509. NULL,
  510. NULL );
  511. }
  512. //
  513. // Release the context
  514. //
  515. SrReleaseContext( pFileContext );
  516. //
  517. // call the AttachedTo driver
  518. //
  519. CompleteTheIrp:
  520. IoSkipCurrentIrpStackLocation(pIrp);
  521. return IoCallDriver(pExtension->pTargetDevice, pIrp);
  522. } // SrWrite
  523. /***************************************************************************++
  524. Routine Description:
  525. Handle Cleanup IRPs
  526. Arguments:
  527. Return Value:
  528. NTSTATUS - Status code.
  529. --***************************************************************************/
  530. NTSTATUS
  531. SrCleanup(
  532. IN PDEVICE_OBJECT DeviceObject,
  533. IN PIRP pIrp
  534. )
  535. {
  536. PSR_DEVICE_EXTENSION pExtension;
  537. PIO_STACK_LOCATION pIrpSp;
  538. //
  539. // < dispatch!
  540. //
  541. PAGED_CODE();
  542. ASSERT(IS_VALID_DEVICE_OBJECT(DeviceObject));
  543. ASSERT(IS_VALID_IRP(pIrp));
  544. //
  545. // Is this a function for our control device object (vs an attachee)?
  546. //
  547. if (DeviceObject == _globals.pControlDevice)
  548. {
  549. return SrMajorFunction(DeviceObject, pIrp);
  550. }
  551. //
  552. // else it is a device we've attached to, grab our extension
  553. //
  554. ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
  555. pExtension = DeviceObject->DeviceExtension;
  556. //
  557. // See if logging is enabled and we don't care about this type of IO
  558. // to the file systems' control device objects.
  559. //
  560. if (!SR_LOGGING_ENABLED(pExtension) ||
  561. SR_IS_FS_CONTROL_DEVICE(pExtension))
  562. {
  563. goto CompleteTheIrp;
  564. }
  565. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  566. //
  567. // does this file have a name? skip unnamed files
  568. //
  569. if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pIrpSp->FileObject ) ||
  570. FILE_OBJECT_DOES_NOT_HAVE_VPB( pIrpSp->FileObject ))
  571. {
  572. goto CompleteTheIrp;
  573. }
  574. //
  575. // is this file about to be deleted ? we do this here as file's can
  576. // be marked for deletion throughout their lifetime via
  577. // IRP_MJ_SET_INFORMATION .
  578. //
  579. //
  580. // for delete we only clean the FCB, not the CCB delete_on_close.
  581. // this was handled in SrCreate.
  582. //
  583. if (pIrpSp->FileObject->DeletePending)
  584. {
  585. NTSTATUS eventStatus;
  586. PSR_STREAM_CONTEXT pFileContext;
  587. //
  588. // Get the context now so we can determine if this is a directory or not
  589. //
  590. eventStatus = SrGetContext( pExtension,
  591. pIrpSp->FileObject,
  592. SrEventFileDelete,
  593. &pFileContext );
  594. if (!NT_SUCCESS( eventStatus ))
  595. {
  596. goto CompleteTheIrp;
  597. }
  598. //
  599. // If interesting, log it
  600. //
  601. if (FlagOn(pFileContext->Flags,CTXFL_IsInteresting))
  602. {
  603. SrHandleEvent( pExtension,
  604. FlagOn(pFileContext->Flags,CTXFL_IsDirectory) ?
  605. SrEventDirectoryDelete :
  606. SrEventFileDelete,
  607. pIrpSp->FileObject,
  608. pFileContext,
  609. NULL,
  610. NULL);
  611. }
  612. //
  613. // Release the context
  614. //
  615. SrReleaseContext( pFileContext );
  616. }
  617. //
  618. // call on to the next filter
  619. //
  620. CompleteTheIrp:
  621. IoSkipCurrentIrpStackLocation(pIrp);
  622. return IoCallDriver(pExtension->pTargetDevice, pIrp);
  623. } // SrCleanup
  624. /***************************************************************************++
  625. Routine Description:
  626. Handle Create IRPS
  627. Arguments:
  628. Return Value:
  629. NTSTATUS - Status code.
  630. --***************************************************************************/
  631. NTSTATUS
  632. SrCreate(
  633. IN PDEVICE_OBJECT DeviceObject,
  634. IN PIRP pIrp
  635. )
  636. {
  637. PSR_DEVICE_EXTENSION pExtension;
  638. PIO_STACK_LOCATION pIrpSp;
  639. NTSTATUS eventStatus;
  640. NTSTATUS IrpStatus;
  641. ULONG CreateDisposition;
  642. ULONG CreateOptions;
  643. USHORT FileAttributes;
  644. SR_OVERWRITE_INFO OverwriteInfo;
  645. KEVENT waitEvent;
  646. PFILE_OBJECT pFileObject;
  647. PSR_STREAM_CONTEXT pFileContext = NULL;
  648. BOOLEAN willCreateUnnamedStream = TRUE;
  649. PAGED_CODE();
  650. ASSERT(IS_VALID_DEVICE_OBJECT(DeviceObject));
  651. ASSERT(IS_VALID_IRP(pIrp));
  652. //
  653. // Is this a function for our control device object (vs an attachee)?
  654. //
  655. if (DeviceObject == _globals.pControlDevice)
  656. {
  657. return SrMajorFunction(DeviceObject, pIrp);
  658. }
  659. //
  660. // else it is a device we've attached to, grab our extension
  661. //
  662. ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
  663. pExtension = DeviceObject->DeviceExtension;
  664. //
  665. // See if logging is enabled and we don't care about this type of IO
  666. // to the file systems' control device objects.
  667. //
  668. if (!SR_LOGGING_ENABLED(pExtension) ||
  669. SR_IS_FS_CONTROL_DEVICE(pExtension))
  670. {
  671. goto CompleteTheIrpAndReturn;
  672. }
  673. //
  674. // Finish Initialization
  675. //
  676. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  677. pFileObject = pIrpSp->FileObject;
  678. //
  679. // does this file have a name? skip unnamed files. Also skip paging
  680. // files. (NULL Vpb is normal - the file is not open yet)
  681. //
  682. if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pFileObject ) ||
  683. FlagOn(pIrpSp->Flags,SL_OPEN_PAGING_FILE))
  684. {
  685. goto CompleteTheIrpAndReturn;
  686. }
  687. //
  688. // Finish initialization and save some information
  689. //
  690. RtlZeroMemory( &OverwriteInfo, sizeof(OverwriteInfo) );
  691. OverwriteInfo.Signature = SR_OVERWRITE_INFO_TAG;
  692. CreateOptions = pIrpSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
  693. CreateDisposition = pIrpSp->Parameters.Create.Options >> 24;
  694. FileAttributes = pIrpSp->Parameters.Create.FileAttributes;
  695. //
  696. // Handle OVERWRITE and SUPERSEEDE cases.
  697. //
  698. if ((CreateDisposition == FILE_OVERWRITE) ||
  699. (CreateDisposition == FILE_OVERWRITE_IF) ||
  700. (CreateDisposition == FILE_SUPERSEDE))
  701. {
  702. SR_EVENT_TYPE event;
  703. //
  704. // The file may be changed by this open so save a copy before going
  705. // down to the filesystem.
  706. //
  707. // First get the context to determine if this is interesting. Since
  708. // this is in the PRE-Create stage we can not tell if this file
  709. // has a context or not (the FsContext field is not initialized yet).
  710. // We will always create a context. Then in the Post-Create section
  711. // we will see if a context was already defined. If not we will add
  712. // this context to the system. If so then we will free this
  713. // context.
  714. //
  715. // Note: If a user opens a directory with any of these
  716. // CreateDisposition flags set, we will go down this path, treating
  717. // the directory name like a file. If the directory name is
  718. // interesting, we will try to back it up and at that point we will
  719. // realize that it is a directory and bail.
  720. //
  721. event = SrEventStreamOverwrite|SrEventIsNotDirectory|SrEventInPreCreate;
  722. if (FlagOn( CreateOptions, FILE_OPEN_BY_FILE_ID ))
  723. {
  724. event |= SrEventOpenById;
  725. }
  726. eventStatus = SrCreateContext( pExtension,
  727. pFileObject,
  728. event,
  729. FileAttributes,
  730. &pFileContext );
  731. if (!NT_SUCCESS_NO_DBGBREAK(eventStatus))
  732. {
  733. goto CompleteTheIrpAndReturn;
  734. }
  735. SrTrace( CONTEXT_LOG, ("Sr!SrCreate: Created (%p) Event=%06x Fl=%03x Use=%d \"%.*S\"\n",
  736. pFileContext,
  737. SrEventStreamOverwrite|SrEventIsNotDirectory,
  738. pFileContext->Flags,
  739. pFileContext->UseCount,
  740. (pFileContext->FileName.Length+
  741. pFileContext->StreamNameLength)/
  742. sizeof(WCHAR),
  743. pFileContext->FileName.Buffer) );
  744. //
  745. // If the file is interesting then handle it
  746. //
  747. if (FlagOn(pFileContext->Flags,CTXFL_IsInteresting))
  748. {
  749. OverwriteInfo.pIrp = pIrp;
  750. eventStatus = SrHandleEvent( pExtension,
  751. SrEventStreamOverwrite,
  752. pFileObject,
  753. pFileContext,
  754. &OverwriteInfo,
  755. NULL );
  756. OverwriteInfo.pIrp = NULL;
  757. if (!NT_SUCCESS(eventStatus))
  758. {
  759. //
  760. // This context has never been linked into a list so nobody
  761. // else can be refrencing it. Release it (which will delete
  762. // it since the use count is at 1.
  763. //
  764. ASSERT(pFileContext != NULL);
  765. ASSERT(pFileContext->UseCount == 1);
  766. SrReleaseContext( pFileContext );
  767. pFileContext = NULL;
  768. goto CompleteTheIrpAndReturn;
  769. }
  770. }
  771. }
  772. //
  773. // As long as the file is not marked delete on close, if the file is simply
  774. // opened, we can do not need to set a completion routine. Otherwise,
  775. // we need a completion routine so that we can see the result of the
  776. // create before we do any logging work.
  777. //
  778. if (!FlagOn( CreateOptions, FILE_DELETE_ON_CLOSE ) &&
  779. CreateDisposition == FILE_OPEN)
  780. {
  781. goto CompleteTheIrpAndReturn;
  782. }
  783. //
  784. // If this is a CREATE operation that could result in the creation of
  785. // a named data stream on a file (FILE_OPEN and FILE_OVERWRITE will never
  786. // create a new file), we need to see if the non-named data
  787. // stream of this file already exists. If the file already exists,
  788. // then so does the non-named data stream.
  789. //
  790. if (((CreateDisposition == FILE_CREATE) ||
  791. (CreateDisposition == FILE_OPEN_IF) ||
  792. (CreateDisposition == FILE_SUPERSEDE) ||
  793. (CreateDisposition == FILE_OVERWRITE_IF)) &&
  794. SrFileNameContainsStream( pExtension, pFileObject, pFileContext ))
  795. {
  796. if (SrFileAlreadyExists( pExtension, pFileObject, pFileContext ))
  797. {
  798. willCreateUnnamedStream = FALSE;
  799. }
  800. }
  801. //
  802. // It is an operation we may care about, go to the completion routine
  803. // to handle what happened.
  804. //
  805. KeInitializeEvent( &waitEvent, SynchronizationEvent, FALSE );
  806. IoCopyCurrentIrpStackLocationToNext(pIrp);
  807. IoSetCompletionRoutine( pIrp,
  808. SrStopProcessingCompletion,
  809. &waitEvent,
  810. TRUE,
  811. TRUE,
  812. TRUE );
  813. IrpStatus = IoCallDriver(pExtension->pTargetDevice, pIrp);
  814. //
  815. // Wait for the completion routine to be called
  816. //
  817. if (STATUS_PENDING == IrpStatus)
  818. {
  819. NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);
  820. ASSERT(STATUS_SUCCESS == localStatus);
  821. }
  822. //=======================================================================
  823. //
  824. // The create operation is completed and we have re-syncronized back
  825. // to the dispatch routine from the completion routine. Handle
  826. // post-create operations.
  827. //
  828. //=======================================================================
  829. //
  830. // Load status of the operation. We need to remember this status in
  831. // IrpStatus so that we can return it from this dispatch routine. Status
  832. // we get the status of our event handling routines as we do our post-
  833. // CREATE operation work.
  834. //
  835. IrpStatus = pIrp->IoStatus.Status;
  836. //
  837. // Handle the File Overwrite/Supersede cases
  838. //
  839. if ((CreateDisposition == FILE_OVERWRITE) ||
  840. (CreateDisposition == FILE_OVERWRITE_IF) ||
  841. (CreateDisposition == FILE_SUPERSEDE))
  842. {
  843. ASSERT(pFileContext != NULL);
  844. ASSERT(pFileContext->UseCount == 1);
  845. //
  846. // See if it was successful (do not change this to NU_SUCCESS macro
  847. // because STATUS_REPARSE is a success code)
  848. //
  849. if (STATUS_SUCCESS == IrpStatus)
  850. {
  851. //
  852. // Now that the create is completed (and we have context state in
  853. // the file object) insert this context into the context hash
  854. // table. This routine will look to see if a context structure
  855. // already exists for this file. If so, it will free this
  856. // structure and return the one that already existed. It will
  857. // properly ref count the context
  858. //
  859. ASSERT(pFileContext != NULL);
  860. ASSERT(pFileContext->UseCount == 1);
  861. //
  862. // Check to see if we need to be concerned that this name was
  863. // tunneled. If this context is temporary and we are not going
  864. // to need to use this context to log any operations, there is
  865. // not need to go through this extra work.
  866. //
  867. if (!FlagOn( pFileContext->Flags, CTXFL_Temporary ) ||
  868. (FILE_CREATED == pIrp->IoStatus.Information))
  869. {
  870. //
  871. // We are in a case where name tunneling could affect the
  872. // correctness of the name we log.
  873. //
  874. eventStatus = SrCheckForNameTunneling( pExtension,
  875. &pFileContext );
  876. if (!NT_SUCCESS( eventStatus ))
  877. {
  878. goto AfterCompletionCleanup;
  879. }
  880. }
  881. SrLinkContext( pExtension,
  882. pFileObject,
  883. &pFileContext );
  884. SrTrace( CONTEXT_LOG, ("Sr!SrCreate: Link (%p) Event=%06x Fl=%03x Use=%d \"%.*S\"\n",
  885. pFileContext,
  886. SrEventStreamOverwrite|SrEventIsNotDirectory,
  887. pFileContext->Flags,
  888. pFileContext->UseCount,
  889. (pFileContext->FileName.Length+
  890. pFileContext->StreamNameLength)/
  891. sizeof(WCHAR),
  892. pFileContext->FileName.Buffer));
  893. //
  894. // Handle if the file was actually created
  895. //
  896. if (FILE_CREATED == pIrp->IoStatus.Information)
  897. {
  898. //
  899. // If the file is interesting, log it
  900. //
  901. if (FlagOn(pFileContext->Flags,CTXFL_IsInteresting))
  902. {
  903. SrHandleEvent( pExtension,
  904. ((willCreateUnnamedStream) ?
  905. SrEventFileCreate :
  906. SrEventStreamCreate),
  907. pFileObject,
  908. pFileContext,
  909. NULL,
  910. NULL);
  911. }
  912. }
  913. //
  914. // make sure it didn't succeed when we thought it would fail
  915. //
  916. else if (!OverwriteInfo.RenamedFile &&
  917. !OverwriteInfo.CopiedFile &&
  918. OverwriteInfo.IgnoredFile )
  919. {
  920. //
  921. // ouch, the caller's create worked, but we didn't think
  922. // it would. this is a bad bug. nothing we can do now, as
  923. // the file is gone.
  924. //
  925. ASSERT(!"sr!SrCreate(post complete): overwrite succeeded with NO BACKUP");
  926. //
  927. // trigger the failure notification to the service
  928. //
  929. SrNotifyVolumeError( pExtension,
  930. &pFileContext->FileName,
  931. STATUS_FILE_INVALID,
  932. SrEventStreamOverwrite );
  933. }
  934. }
  935. else
  936. {
  937. //
  938. // handle it failing when we thought it would succeed
  939. //
  940. if (OverwriteInfo.RenamedFile)
  941. {
  942. //
  943. // the call failed (or returned some weird info code)
  944. // but we renamed the file! we need to fix it.
  945. //
  946. eventStatus = SrHandleOverwriteFailure( pExtension,
  947. &pFileContext->FileName,
  948. OverwriteInfo.CreateFileAttributes,
  949. OverwriteInfo.pRenameInformation );
  950. ASSERTMSG("sr!SrCreate(post complete): failed to correct a failed overwrite!\n", NT_SUCCESS(eventStatus));
  951. }
  952. //
  953. // The create failed, the releaseContext below will free
  954. // the structure since we didn't link it into any lists
  955. //
  956. }
  957. }
  958. //
  959. // If it did not work, return now. Don't bother getting a context
  960. //
  961. else if ((STATUS_REPARSE == IrpStatus) ||
  962. !NT_SUCCESS_NO_DBGBREAK(IrpStatus))
  963. {
  964. ASSERT(pFileContext == NULL);
  965. }
  966. //
  967. // is this open for DELETE_ON_CLOSE? if so, handle the delete now,
  968. // we won't have any other chance until MJ_CLEANUP, and it's hard
  969. // to manipulate the object during cleanup. we do not perform any
  970. // optimization on deletes in this manner. kernel32!deletefile does
  971. // not use FILE_DELETE_ON_CLOSE so this should be rare if ever seen.
  972. //
  973. else if (FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
  974. {
  975. //
  976. // Get the context so we can see if this is a directory or not
  977. //
  978. ASSERT(pFileContext == NULL);
  979. eventStatus = SrGetContext( pExtension,
  980. pFileObject,
  981. SrEventFileDelete,
  982. &pFileContext );
  983. if (!NT_SUCCESS(eventStatus))
  984. {
  985. goto AfterCompletionCleanup;
  986. }
  987. //
  988. // Log the operation. If this is a file, we want to make sure that
  989. // we don't try to rename the file into the store since it will be
  990. // deleted when it is closed. On a directory delete, we don't have
  991. // this problem since we only log an entry for a directory delete
  992. // and don't need to actually backup anything.
  993. //
  994. SrHandleEvent( pExtension,
  995. (FlagOn(pFileContext->Flags,CTXFL_IsDirectory) ?
  996. SrEventDirectoryDelete :
  997. (SrEventFileDelete | SrEventNoOptimization)) ,
  998. pFileObject,
  999. pFileContext,
  1000. NULL,
  1001. NULL );
  1002. }
  1003. //
  1004. // was a brand new file just created?
  1005. //
  1006. else if ((CreateDisposition == FILE_CREATE) ||
  1007. (pIrp->IoStatus.Information == FILE_CREATED))
  1008. {
  1009. ASSERT(pFileContext == NULL);
  1010. //
  1011. // LOG the create
  1012. //
  1013. SrHandleEvent( pExtension,
  1014. (FlagOn( CreateOptions, FILE_DIRECTORY_FILE ) ?
  1015. SrEventDirectoryCreate|SrEventIsDirectory :
  1016. (willCreateUnnamedStream ?
  1017. SrEventFileCreate|SrEventIsNotDirectory :
  1018. SrEventStreamCreate|SrEventIsNotDirectory)),
  1019. pFileObject,
  1020. NULL,
  1021. NULL,
  1022. NULL );
  1023. }
  1024. //
  1025. // This is for doing any cleanup that occured after we synced with
  1026. // the completion routine
  1027. //
  1028. AfterCompletionCleanup:
  1029. if (OverwriteInfo.pRenameInformation != NULL)
  1030. {
  1031. SR_FREE_POOL( OverwriteInfo.pRenameInformation,
  1032. SR_RENAME_BUFFER_TAG );
  1033. NULLPTR(OverwriteInfo.pRenameInformation);
  1034. }
  1035. if (NULL != pFileContext)
  1036. {
  1037. SrReleaseContext( pFileContext );
  1038. NULLPTR(pFileContext);
  1039. }
  1040. //
  1041. // Complete the request and return status
  1042. //
  1043. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  1044. return IrpStatus;
  1045. //
  1046. // We come here if we got an error before the completion routine. This
  1047. // means we don't need to wait for the completion routine.
  1048. //
  1049. CompleteTheIrpAndReturn:
  1050. IoSkipCurrentIrpStackLocation(pIrp);
  1051. return IoCallDriver(pExtension->pTargetDevice, pIrp);
  1052. } // SrCreate
  1053. /***************************************************************************++
  1054. Routine Description:
  1055. Handle SetSecurit IRPS
  1056. Arguments:
  1057. Return Value:
  1058. NTSTATUS - Status code.
  1059. --***************************************************************************/
  1060. NTSTATUS
  1061. SrSetSecurity(
  1062. IN PDEVICE_OBJECT DeviceObject,
  1063. IN PIRP pIrp
  1064. )
  1065. {
  1066. PSR_DEVICE_EXTENSION pExtension;
  1067. PIO_STACK_LOCATION pIrpSp;
  1068. //
  1069. // < dispatch!
  1070. //
  1071. PAGED_CODE();
  1072. ASSERT(IS_VALID_DEVICE_OBJECT(DeviceObject));
  1073. ASSERT(IS_VALID_IRP(pIrp));
  1074. //
  1075. // Is this a function for our device (vs an attachee) .
  1076. //
  1077. if (DeviceObject == _globals.pControlDevice)
  1078. {
  1079. return SrMajorFunction(DeviceObject, pIrp);
  1080. }
  1081. //
  1082. // else it is a device we've attached to, grab our extension
  1083. //
  1084. ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
  1085. pExtension = DeviceObject->DeviceExtension;
  1086. //
  1087. // See if logging is enabled and we don't care about this type of IO
  1088. // to the file systems' control device objects.
  1089. //
  1090. if (!SR_LOGGING_ENABLED(pExtension)||
  1091. SR_IS_FS_CONTROL_DEVICE(pExtension))
  1092. {
  1093. goto CompleteTheIrp;
  1094. }
  1095. //
  1096. // does this file have a name? skip unnamed files
  1097. //
  1098. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1099. if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pIrpSp->FileObject ) ||
  1100. FILE_OBJECT_DOES_NOT_HAVE_VPB( pIrpSp->FileObject ))
  1101. {
  1102. goto CompleteTheIrp;
  1103. }
  1104. //
  1105. // log the change
  1106. //
  1107. SrHandleEvent( pExtension,
  1108. SrEventAclChange,
  1109. pIrpSp->FileObject,
  1110. NULL,
  1111. NULL,
  1112. NULL);
  1113. //
  1114. // call the AttachedTo driver
  1115. //
  1116. CompleteTheIrp:
  1117. IoSkipCurrentIrpStackLocation(pIrp);
  1118. return IoCallDriver(pExtension->pTargetDevice, pIrp);
  1119. } // SrSetSecurity
  1120. /***************************************************************************++
  1121. Routine Description:
  1122. handles IRP_MJ_FILE_SYSTEM_CONTROL. the main thing we watch for here
  1123. are set reparse points to monitor volume mounts.
  1124. Arguments:
  1125. DeviceObject - the device object being processed
  1126. pIrp - the irp
  1127. Return Value:
  1128. NTSTATUS - Status code.
  1129. --***************************************************************************/
  1130. NTSTATUS
  1131. SrFsControl(
  1132. IN PDEVICE_OBJECT pDeviceObject,
  1133. IN PIRP pIrp
  1134. )
  1135. {
  1136. PSR_DEVICE_EXTENSION pExtension = NULL;
  1137. PIO_STACK_LOCATION pIrpSp;
  1138. NTSTATUS Status = STATUS_SUCCESS;
  1139. ULONG FsControlCode;
  1140. PIO_COMPLETION_ROUTINE pCompletionRoutine = NULL;
  1141. PAGED_CODE();
  1142. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  1143. ASSERT(IS_VALID_DEVICE_OBJECT(pDeviceObject));
  1144. ASSERT(IS_VALID_IRP(pIrp));
  1145. //
  1146. // Is this a function for our control device object (vs an attachee)?
  1147. //
  1148. if (pDeviceObject == _globals.pControlDevice)
  1149. {
  1150. return SrMajorFunction(pDeviceObject, pIrp);
  1151. }
  1152. //
  1153. // else it is a device we've attached to , grab our extension
  1154. //
  1155. ASSERT(IS_SR_DEVICE_OBJECT(pDeviceObject));
  1156. pExtension = pDeviceObject->DeviceExtension;
  1157. //
  1158. // Begin by determining the minor function code for this file
  1159. // system control function.
  1160. //
  1161. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1162. if ( pIrpSp->MinorFunction == IRP_MN_MOUNT_VOLUME )
  1163. {
  1164. if (SR_IS_SUPPORTED_REAL_DEVICE(pIrpSp->Parameters.MountVolume.Vpb->RealDevice)) {
  1165. //
  1166. // We mount devices even if we are disabled right now so that the
  1167. // filter can be enabled later and already be attached to each
  1168. // device at the appropriate location in the stack.
  1169. //
  1170. return SrFsControlMount( pDeviceObject, pExtension, pIrp );
  1171. } else {
  1172. //
  1173. // We don't care about this type of device so jump down to where
  1174. // we take SR out of the stack and pass the IO through.
  1175. //
  1176. goto SrFsControl_Skip;
  1177. }
  1178. }
  1179. else if (pIrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST)
  1180. {
  1181. //
  1182. // See if logging is enabled and we don't care about this type of IO
  1183. // to the file systems' control device objects.
  1184. //
  1185. if (!SR_LOGGING_ENABLED(pExtension) ||
  1186. SR_IS_FS_CONTROL_DEVICE(pExtension))
  1187. {
  1188. goto SrFsControl_Skip;
  1189. }
  1190. FsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
  1191. switch (FsControlCode) {
  1192. case FSCTL_SET_REPARSE_POINT:
  1193. case FSCTL_DELETE_REPARSE_POINT:
  1194. //
  1195. // In this case, we need to do work after the IO has completed
  1196. // and we have synchronized back to this thread, so
  1197. // SrFsControlReparsePoint contains the call to IoCallDriver and
  1198. // we just want to return the status of this routine.
  1199. //
  1200. return SrFsControlReparsePoint(pExtension, pIrp);
  1201. case FSCTL_LOCK_VOLUME:
  1202. SrTrace( NOTIFY, ("sr!SrFsControl:FSCTL_LOCK_VOLUME(%wZ)\n",
  1203. pExtension->pNtVolumeName ));
  1204. SrFsControlLockOrDismount(pExtension, pIrp);
  1205. //
  1206. // Jump down to where take SR out of the stack and pass this
  1207. // IO through.
  1208. //
  1209. goto SrFsControl_Skip;
  1210. case FSCTL_DISMOUNT_VOLUME:
  1211. SrTrace( NOTIFY, ("sr!SrFsControl:FSCTL_DISMOUNT_VOLUME(%wZ)\n",
  1212. pExtension->pNtVolumeName ));
  1213. //
  1214. // First, disable the log while we shutdown the log context
  1215. // and wait for the filesystem to handle the dismount. If
  1216. // the dismount fails, we will reenable the volume.
  1217. //
  1218. pExtension->Disabled = TRUE;
  1219. //
  1220. // Stop the logging on the volume.
  1221. //
  1222. SrFsControlLockOrDismount(pExtension, pIrp);
  1223. //
  1224. // We need to see the completion of this operation so we
  1225. // can see the final status. If we see that the dismount has
  1226. // failed, we need to reenable the volume.
  1227. //
  1228. pCompletionRoutine = SrDismountCompletion;
  1229. goto SrFsControl_SetCompletion;
  1230. case FSCTL_WRITE_RAW_ENCRYPTED:
  1231. SrFsControlWriteRawEncrypted(pExtension, pIrp);
  1232. //
  1233. // Jump down to where take SR out of the stack and pass this
  1234. // IO through.
  1235. //
  1236. goto SrFsControl_Skip;
  1237. case FSCTL_SET_SPARSE:
  1238. SrFsControlSetSparse( pExtension, pIrp );
  1239. //
  1240. // Jump down to where take SR out of the stack and pass this
  1241. // IO through.
  1242. //
  1243. goto SrFsControl_Skip;
  1244. default:
  1245. //
  1246. // For all other FSCTL just skip the current IRP stack location.
  1247. //
  1248. //
  1249. // Jump down to where take SR out of the stack and pass this
  1250. // IO through.
  1251. //
  1252. goto SrFsControl_Skip;
  1253. } // switch (FsControlCode)
  1254. } // else if (pIrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST)
  1255. else
  1256. {
  1257. //
  1258. // We don't care about any other operations so simply get out of
  1259. // the stack.
  1260. //
  1261. goto SrFsControl_Skip;
  1262. }
  1263. SrFsControl_SetCompletion:
  1264. ASSERT( pCompletionRoutine != NULL );
  1265. IoCopyCurrentIrpStackLocationToNext(pIrp);
  1266. IoSetCompletionRoutine( pIrp,
  1267. pCompletionRoutine,
  1268. NULL, // CompletionContext
  1269. TRUE,
  1270. TRUE,
  1271. TRUE );
  1272. return IoCallDriver( pExtension->pTargetDevice, pIrp );
  1273. SrFsControl_Skip:
  1274. ASSERT( pCompletionRoutine == NULL );
  1275. IoSkipCurrentIrpStackLocation( pIrp );
  1276. return IoCallDriver( pExtension->pTargetDevice, pIrp );
  1277. } // SrFsControl
  1278. /***************************************************************************++
  1279. Routine Description:
  1280. Arguments:
  1281. Return Value:
  1282. NTSTATUS - Status code.
  1283. --***************************************************************************/
  1284. NTSTATUS
  1285. SrFsControlReparsePoint (
  1286. IN PSR_DEVICE_EXTENSION pExtension,
  1287. IN PIRP pIrp
  1288. )
  1289. {
  1290. PREPARSE_DATA_BUFFER pReparseHeader;
  1291. PUNICODE_STRING pMountVolume = NULL;
  1292. PFILE_OBJECT pFileObject = NULL;
  1293. ULONG TotalLength;
  1294. PIO_STACK_LOCATION pIrpSp;
  1295. KEVENT EventToWaitOn;
  1296. NTSTATUS IrpStatus;
  1297. NTSTATUS eventStatus;
  1298. ULONG FsControlCode;
  1299. PSR_STREAM_CONTEXT pFileContext = NULL;
  1300. BOOLEAN isFile = FALSE;
  1301. #if DBG
  1302. //
  1303. // This is to verify that the original request gets the same error
  1304. // we got when querying the reparse point.
  1305. //
  1306. BOOLEAN ExpectError = FALSE;
  1307. NTSTATUS ExpectedErrorCode = STATUS_SUCCESS;
  1308. #endif
  1309. PAGED_CODE();
  1310. pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
  1311. FsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
  1312. //
  1313. // See if it has a name
  1314. //
  1315. if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pIrpSp->FileObject ) ||
  1316. FILE_OBJECT_DOES_NOT_HAVE_VPB( pIrpSp->FileObject ))
  1317. {
  1318. goto SrFsControlReparsePoint_SkipFilter;
  1319. }
  1320. //
  1321. // Get the context now so we can determine if this is a directory or not
  1322. //
  1323. eventStatus = SrGetContext( pExtension,
  1324. pIrpSp->FileObject,
  1325. SrEventInvalid,
  1326. &pFileContext );
  1327. if (!NT_SUCCESS( eventStatus ))
  1328. {
  1329. goto SrFsControlReparsePoint_SkipFilter;
  1330. }
  1331. //
  1332. // If it is not a directory, return
  1333. //
  1334. if (!FlagOn(pFileContext->Flags,CTXFL_IsDirectory))
  1335. {
  1336. isFile = TRUE;
  1337. goto SrFsControlReparsePoint_SkipFilter;
  1338. }
  1339. //
  1340. // is there enough space for the header?
  1341. //
  1342. pReparseHeader = pIrp->AssociatedIrp.SystemBuffer;
  1343. if (pReparseHeader == NULL ||
  1344. pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1345. REPARSE_DATA_BUFFER_HEADER_SIZE)
  1346. {
  1347. goto SrFsControlReparsePoint_SkipFilter;
  1348. }
  1349. //
  1350. // is this a mount point?
  1351. //
  1352. if (pReparseHeader->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
  1353. {
  1354. goto SrFsControlReparsePoint_SkipFilter;
  1355. }
  1356. //
  1357. // keep a copy for post processing
  1358. //
  1359. pFileObject = pIrpSp->FileObject;
  1360. ObReferenceObject(pFileObject);
  1361. //
  1362. // now let's see what we have to do
  1363. //
  1364. if (FsControlCode == FSCTL_SET_REPARSE_POINT)
  1365. {
  1366. //
  1367. // If there is no data this is invalid
  1368. //
  1369. if (pReparseHeader->ReparseDataLength <= 0)
  1370. {
  1371. goto SrFsControlReparsePoint_SkipFilter;
  1372. }
  1373. //
  1374. // is there enough space for the header + data?
  1375. // (according to him - not trusted)
  1376. //
  1377. //
  1378. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1379. pReparseHeader->ReparseDataLength + ((ULONG)REPARSE_DATA_BUFFER_HEADER_SIZE))
  1380. {
  1381. goto SrFsControlReparsePoint_SkipFilter;
  1382. }
  1383. //
  1384. // did he lie about the length of the string?
  1385. //
  1386. TotalLength = DIFF( (((PUCHAR)pReparseHeader->MountPointReparseBuffer.PathBuffer)
  1387. + pReparseHeader->MountPointReparseBuffer.SubstituteNameLength)
  1388. - ((PUCHAR)pReparseHeader) );
  1389. if (TotalLength >
  1390. pIrpSp->Parameters.DeviceIoControl.InputBufferLength)
  1391. {
  1392. goto SrFsControlReparsePoint_SkipFilter;
  1393. }
  1394. //
  1395. // grab the volume name
  1396. //
  1397. eventStatus = SrAllocateFileNameBuffer( pReparseHeader->MountPointReparseBuffer.SubstituteNameLength,
  1398. &pMountVolume );
  1399. if (!NT_SUCCESS(eventStatus))
  1400. {
  1401. goto SrFsControlReparsePoint_VolumeError;
  1402. }
  1403. RtlCopyMemory( pMountVolume->Buffer,
  1404. pReparseHeader->MountPointReparseBuffer.PathBuffer,
  1405. pReparseHeader->MountPointReparseBuffer.SubstituteNameLength );
  1406. pMountVolume->Length = pReparseHeader->MountPointReparseBuffer.SubstituteNameLength;
  1407. }
  1408. else
  1409. {
  1410. ASSERT(FsControlCode == FSCTL_DELETE_REPARSE_POINT);
  1411. //
  1412. // it's a delete, get the old mount location for logging
  1413. //
  1414. eventStatus = SrGetMountVolume( pFileObject,
  1415. &pMountVolume );
  1416. if (eventStatus == STATUS_INSUFFICIENT_RESOURCES)
  1417. {
  1418. //
  1419. // Must notify service of volume error and shut down
  1420. // before passing the IO through.
  1421. //
  1422. goto SrFsControlReparsePoint_VolumeError;
  1423. }
  1424. #if DBG
  1425. if (!NT_SUCCESS_NO_DBGBREAK( eventStatus ))
  1426. {
  1427. ExpectError = TRUE;
  1428. ExpectedErrorCode = eventStatus;
  1429. goto SrFsControlReparsePoint_SkipFilter;
  1430. }
  1431. #else
  1432. if (!NT_SUCCESS( eventStatus ))
  1433. {
  1434. goto SrFsControlReparsePoint_SkipFilter;
  1435. }
  1436. #endif
  1437. }
  1438. //
  1439. // If we get to this point, this is a reparse point we care about
  1440. // so set a completion routine so that we can see the result of this
  1441. // operation.
  1442. //
  1443. KeInitializeEvent( &EventToWaitOn, NotificationEvent, FALSE );
  1444. IoCopyCurrentIrpStackLocationToNext( pIrp );
  1445. IoSetCompletionRoutine( pIrp,
  1446. SrStopProcessingCompletion,
  1447. &EventToWaitOn,
  1448. TRUE,
  1449. TRUE,
  1450. TRUE );
  1451. IrpStatus = IoCallDriver( pExtension->pTargetDevice, pIrp );
  1452. if (STATUS_PENDING == IrpStatus )
  1453. {
  1454. NTSTATUS localStatus = KeWaitForSingleObject( &EventToWaitOn,
  1455. Executive,
  1456. KernelMode,
  1457. FALSE,
  1458. NULL );
  1459. ASSERT(STATUS_SUCCESS == localStatus);
  1460. }
  1461. //
  1462. // The Irp is still good since we have returned
  1463. // STATUS_MORE_PROCESSING_REQUIRED from the completion
  1464. // routine.
  1465. //
  1466. //
  1467. // If the status in the IRP was STATUS_PENDING,
  1468. // we want to change the status to STATUS_SUCCESS
  1469. // since we have just performed the necessary synchronization
  1470. // with the orginating thread.
  1471. //
  1472. if (pIrp->IoStatus.Status == STATUS_PENDING)
  1473. {
  1474. ASSERT(!"I want to see if this ever happens");
  1475. pIrp->IoStatus.Status = STATUS_SUCCESS;
  1476. }
  1477. IrpStatus = pIrp->IoStatus.Status;
  1478. //
  1479. // We are done with the Irp, so complete the Irp.
  1480. //
  1481. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  1482. //
  1483. // Now these pointers are no longer valid.
  1484. //
  1485. NULLPTR(pIrp);
  1486. NULLPTR(pIrpSp);
  1487. //
  1488. // Check to make sure the operation successfully
  1489. // completed.
  1490. //
  1491. if (!NT_SUCCESS_NO_DBGBREAK(IrpStatus))
  1492. {
  1493. goto SrFsControlReparsePoint_Exit;
  1494. }
  1495. //
  1496. // The reparse point change occurred successfully, so
  1497. // log the reparse point change.
  1498. //
  1499. ASSERT(pFileObject != NULL);
  1500. ASSERT(pFileContext != NULL);
  1501. ASSERT(FlagOn(pFileContext->Flags,CTXFL_IsDirectory));
  1502. ASSERT(FsControlCode == FSCTL_DELETE_REPARSE_POINT ||
  1503. FsControlCode == FSCTL_SET_REPARSE_POINT);
  1504. SrHandleEvent( pExtension,
  1505. ((FSCTL_SET_REPARSE_POINT == FsControlCode) ?
  1506. SrEventMountCreate :
  1507. SrEventMountDelete),
  1508. pFileObject,
  1509. pFileContext,
  1510. NULL,
  1511. pMountVolume );
  1512. goto SrFsControlReparsePoint_Exit;
  1513. SrFsControlReparsePoint_VolumeError:
  1514. //
  1515. // We've gotten a volume error sometime before we passed the IRP
  1516. // along to the base file system. Do the right thing to shut down
  1517. // the volume logging.
  1518. //
  1519. SrNotifyVolumeError( pExtension,
  1520. NULL,
  1521. eventStatus,
  1522. SrNotificationVolumeError );
  1523. //
  1524. // We will now fall through to skip our filter as we pass the IO
  1525. // down to the remaining filters and file system.
  1526. //
  1527. SrFsControlReparsePoint_SkipFilter:
  1528. //
  1529. // If this was a file, we need to clear out our context on this file
  1530. // since we don't want to monitor files with Reparse Points. On the
  1531. // next access to this file, we will requery this information.
  1532. //
  1533. if (isFile)
  1534. {
  1535. ASSERT( pFileContext != NULL );
  1536. SrDeleteContext( pExtension, pFileContext );
  1537. }
  1538. //
  1539. // We don't need a completion routine, call to next driver
  1540. //
  1541. IoSkipCurrentIrpStackLocation( pIrp );
  1542. IrpStatus = IoCallDriver( pExtension->pTargetDevice, pIrp );
  1543. NULLPTR(pIrp);
  1544. NULLPTR(pIrpSp);
  1545. ASSERT(!ExpectError || ((ExpectedErrorCode == IrpStatus) ||
  1546. (STATUS_PENDING == IrpStatus )));
  1547. //
  1548. // Cleanup state
  1549. //
  1550. SrFsControlReparsePoint_Exit:
  1551. if (NULL != pMountVolume)
  1552. {
  1553. SrFreeFileNameBuffer( pMountVolume );
  1554. NULLPTR(pMountVolume);
  1555. }
  1556. if (NULL != pFileObject)
  1557. {
  1558. ObDereferenceObject( pFileObject );
  1559. NULLPTR(pFileObject);
  1560. }
  1561. if (NULL != pFileContext)
  1562. {
  1563. SrReleaseContext( pFileContext );
  1564. NULLPTR(pFileContext);
  1565. }
  1566. return IrpStatus;
  1567. }
  1568. /***************************************************************************++
  1569. Routine Description:
  1570. Arguments:
  1571. Return Value:
  1572. NTSTATUS - Status code.
  1573. --***************************************************************************/
  1574. NTSTATUS
  1575. SrFsControlMount (
  1576. IN PDEVICE_OBJECT pDeviceObject,
  1577. IN PSR_DEVICE_EXTENSION pExtension,
  1578. IN PIRP pIrp
  1579. )
  1580. {
  1581. PIO_STACK_LOCATION pIrpSp;
  1582. PDEVICE_OBJECT pNewDeviceObject = NULL;
  1583. KEVENT EventToWaitOn;
  1584. PVPB pVpb = NULL;
  1585. PDEVICE_OBJECT pRealDevice;
  1586. NTSTATUS Status;
  1587. PAGED_CODE();
  1588. ASSERT( SR_IS_FS_CONTROL_DEVICE(pExtension) );
  1589. //
  1590. // create our device we are going to attach to this new volume
  1591. //
  1592. pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
  1593. pRealDevice = pIrpSp->Parameters.MountVolume.Vpb->RealDevice;
  1594. Status = SrCreateAttachmentDevice( pRealDevice,
  1595. pDeviceObject,
  1596. &pNewDeviceObject );
  1597. if (!NT_SUCCESS( Status ))
  1598. {
  1599. IoSkipCurrentIrpStackLocation( pIrp );
  1600. return IoCallDriver( pExtension->pTargetDevice, pIrp );
  1601. }
  1602. //
  1603. // If we get here, we need to set our completion routine then
  1604. // wait for it to signal us before we continue with the post processing
  1605. // of the mount.
  1606. //
  1607. KeInitializeEvent( &EventToWaitOn, NotificationEvent, FALSE );
  1608. IoCopyCurrentIrpStackLocationToNext(pIrp);
  1609. IoSetCompletionRoutine( pIrp,
  1610. SrStopProcessingCompletion,
  1611. &EventToWaitOn, // CompletionContext
  1612. TRUE,
  1613. TRUE,
  1614. TRUE );
  1615. pIrpSp->Parameters.MountVolume.DeviceObject =
  1616. pIrpSp->Parameters.MountVolume.Vpb->RealDevice;
  1617. Status = IoCallDriver( pExtension->pTargetDevice, pIrp );
  1618. if (STATUS_PENDING == Status)
  1619. {
  1620. NTSTATUS localStatus = KeWaitForSingleObject( &EventToWaitOn,
  1621. Executive,
  1622. KernelMode,
  1623. FALSE,
  1624. NULL );
  1625. ASSERT( NT_SUCCESS( localStatus ) );
  1626. }
  1627. //
  1628. // skip out if the mount failed
  1629. //
  1630. if (!NT_SUCCESS_NO_DBGBREAK(pIrp->IoStatus.Status))
  1631. {
  1632. goto SrFsControlMount_Error;
  1633. }
  1634. //
  1635. // Note that the VPB must be picked up from the real device object
  1636. // so that we can see the DeviceObject that the file system created
  1637. // to represent this newly mounted volume.
  1638. //
  1639. pVpb = pRealDevice->Vpb;
  1640. ASSERT(pVpb != NULL);
  1641. //
  1642. // SrFsControl made sure that we support this volume type
  1643. //
  1644. ASSERT(SR_IS_SUPPORTED_VOLUME(pVpb));
  1645. //
  1646. // are we already attached to this device?
  1647. //
  1648. if (NT_SUCCESS( pIrp->IoStatus.Status ) &&
  1649. (SrGetFilterDevice(pVpb->DeviceObject) == NULL))
  1650. {
  1651. //
  1652. // now attach to the new volume
  1653. //
  1654. Status = SrAttachToDevice( pVpb->RealDevice,
  1655. pVpb->DeviceObject,
  1656. pNewDeviceObject,
  1657. NULL );
  1658. if (NT_SUCCESS(Status))
  1659. {
  1660. goto SrFsControlMount_Exit;
  1661. }
  1662. }
  1663. SrFsControlMount_Error:
  1664. ASSERT( pNewDeviceObject != NULL );
  1665. SrDeleteAttachmentDevice( pNewDeviceObject );
  1666. SrFsControlMount_Exit:
  1667. Status = pIrp->IoStatus.Status;
  1668. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  1669. return Status;
  1670. }
  1671. /***************************************************************************++
  1672. Routine Description:
  1673. Arguments:
  1674. Return Value:
  1675. NTSTATUS - Status code.
  1676. --***************************************************************************/
  1677. NTSTATUS
  1678. SrFsControlLockOrDismount (
  1679. IN PSR_DEVICE_EXTENSION pExtension,
  1680. IN PIRP pIrp
  1681. )
  1682. {
  1683. NTSTATUS Status = STATUS_SUCCESS;
  1684. UNREFERENCED_PARAMETER( pIrp );
  1685. PAGED_CODE();
  1686. try {
  1687. //
  1688. // close our log file handle on this volume , it's being
  1689. // locked. it's ok if the lock attempt fails, we will open
  1690. // our handle again automatically since DriveChecked is also
  1691. // being cleared.
  1692. //
  1693. SrAcquireActivityLockExclusive( pExtension);
  1694. if (pExtension->pLogContext != NULL)
  1695. {
  1696. Status = SrLogStop( pExtension, TRUE, FALSE );
  1697. CHECK_STATUS( Status );
  1698. }
  1699. } finally {
  1700. SrReleaseActivityLock(pExtension);
  1701. }
  1702. return Status;
  1703. }
  1704. /***************************************************************************++
  1705. Routine Description:
  1706. Arguments:
  1707. Return Value:
  1708. NTSTATUS - Status code.
  1709. --***************************************************************************/
  1710. VOID
  1711. SrFsControlWriteRawEncrypted (
  1712. IN PSR_DEVICE_EXTENSION pExtension,
  1713. IN PIRP pIrp
  1714. )
  1715. {
  1716. PIO_STACK_LOCATION pIrpSp;
  1717. NTSTATUS Status;
  1718. PSR_STREAM_CONTEXT pFileContext = NULL;
  1719. PAGED_CODE();
  1720. pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
  1721. if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pIrpSp->FileObject ) ||
  1722. FILE_OBJECT_DOES_NOT_HAVE_VPB( pIrpSp->FileObject )) {
  1723. return;
  1724. }
  1725. //
  1726. // Look up the context for this file object so that we can figure out
  1727. // if this is a file or a directory. If this is a directory, the
  1728. // file system will fail the operation, so there is no need to try to
  1729. // back it up.
  1730. //
  1731. Status = SrGetContext( pExtension,
  1732. pIrpSp->FileObject,
  1733. SrEventStreamChange,
  1734. &pFileContext );
  1735. if (!NT_SUCCESS( Status ))
  1736. {
  1737. //
  1738. // We hit some error trying to get the context. If this should
  1739. // generate a volume error, it has already been taken care of inside
  1740. // SrGetContext. Otherwise, this just means that the actual operation
  1741. // will fail, so there is no work for us to do here.
  1742. //
  1743. return;
  1744. }
  1745. ASSERT( NULL != pFileContext );
  1746. //
  1747. // Make sure that we have an interesting file. This operation
  1748. // is invalid on directories.
  1749. //
  1750. if (FlagOn( pFileContext->Flags, CTXFL_IsInteresting )&&
  1751. !FlagOn( pFileContext->Flags, CTXFL_IsDirectory ))
  1752. {
  1753. SrHandleEvent( pExtension,
  1754. SrEventStreamChange,
  1755. pIrpSp->FileObject,
  1756. pFileContext,
  1757. NULL,
  1758. NULL );
  1759. }
  1760. //
  1761. // We are all done with this context, so now release it.
  1762. //
  1763. ASSERT( NULL != pFileContext );
  1764. SrReleaseContext( pFileContext );
  1765. NULLPTR(pFileContext);
  1766. return;
  1767. }
  1768. /***************************************************************************++
  1769. Routine Description:
  1770. When a file is set to sparse, we need to clear out our context for this
  1771. file. On the next interesting operation for this file, we will regenerate
  1772. a correct context.
  1773. This work is done since SR doesn't want to monitor files that are SPARSE.
  1774. Arguments:
  1775. Return Value:
  1776. None.
  1777. --***************************************************************************/
  1778. VOID
  1779. SrFsControlSetSparse (
  1780. IN PSR_DEVICE_EXTENSION pExtension,
  1781. IN PIRP pIrp
  1782. )
  1783. {
  1784. PIO_STACK_LOCATION irpSp;
  1785. PFILE_OBJECT pFileObject;
  1786. PSR_STREAM_CONTEXT pFileContext = NULL;
  1787. PAGED_CODE();
  1788. irpSp = IoGetCurrentIrpStackLocation( pIrp );
  1789. pFileObject = irpSp->FileObject;
  1790. pFileContext = SrFindExistingContext( pExtension, pFileObject );
  1791. if (pFileContext != NULL)
  1792. {
  1793. SrDeleteContext( pExtension, pFileContext );
  1794. SrReleaseContext( pFileContext );
  1795. }
  1796. return;
  1797. }
  1798. /***************************************************************************++
  1799. Routine Description:
  1800. handles IRP_MJ_PNP. SR needs to close its handle to the log when it sees
  1801. that the volume is going away and reopen it when the drive reappears.
  1802. Arguments:
  1803. DeviceObject - the device object being processed
  1804. pIrp - the irp
  1805. Return Value:
  1806. NTSTATUS - Status code.
  1807. --***************************************************************************/
  1808. NTSTATUS
  1809. SrPnp (
  1810. IN PDEVICE_OBJECT DeviceObject,
  1811. IN PIRP Irp
  1812. )
  1813. {
  1814. PSR_DEVICE_EXTENSION pExtension;
  1815. PIO_STACK_LOCATION irpSp;
  1816. PAGED_CODE();
  1817. ASSERT(IS_VALID_DEVICE_OBJECT(DeviceObject));
  1818. ASSERT(IS_VALID_IRP(Irp));
  1819. //
  1820. // Get this driver out of the driver stack and get to the next driver as
  1821. // quickly as possible.
  1822. //
  1823. //
  1824. // Is this a function for our device (vs an attachee) .
  1825. //
  1826. if (DeviceObject == _globals.pControlDevice)
  1827. {
  1828. return SrMajorFunction(DeviceObject, Irp);
  1829. }
  1830. //
  1831. // else it is a device we've attached to, grab our extension
  1832. //
  1833. ASSERT( IS_SR_DEVICE_OBJECT( DeviceObject ) );
  1834. pExtension = DeviceObject->DeviceExtension;
  1835. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1836. switch ( irpSp->MinorFunction ) {
  1837. case IRP_MN_QUERY_REMOVE_DEVICE:
  1838. SrTrace( PNP, ( "SR!SrPnp: QUERY_REMOVE_DEVICE [%wZ]\n",
  1839. pExtension->pNtVolumeName ) );
  1840. //
  1841. // If this is a SURPRISE_REMOVAL, the device has already gone away
  1842. // and we are not going to see any more operations to this volume, but
  1843. // the OS won't call us to detach and delete our device object until
  1844. // all the handles that are outstanding on this volume are closed. Do
  1845. // our part by closing down the handle to our log.
  1846. //
  1847. try {
  1848. SrAcquireActivityLockExclusive( pExtension );
  1849. pExtension->Disabled = TRUE;
  1850. if (pExtension->pLogContext != NULL)
  1851. {
  1852. SrLogStop( pExtension, TRUE, FALSE );
  1853. }
  1854. } finally {
  1855. SrReleaseActivityLock( pExtension );
  1856. }
  1857. break;
  1858. case IRP_MN_SURPRISE_REMOVAL:
  1859. SrTrace( PNP, ( "SR!SrPnp: SURPRISE_REMOVAL [%wZ]\n",
  1860. pExtension->pNtVolumeName ) );
  1861. //
  1862. // If this is a SURPRISE_REMOVAL, the device has already gone away
  1863. // and we are not going to see any more operations to this volume, but
  1864. // the OS won't call us to detach and delete our device object until
  1865. // all the handles that are outstanding on this volume are closed. Do
  1866. // our part by closing down the handle to our log.
  1867. //
  1868. try {
  1869. SrAcquireActivityLockExclusive( pExtension );
  1870. pExtension->Disabled = TRUE;
  1871. if (pExtension->pLogContext != NULL)
  1872. {
  1873. SrLogStop( pExtension, TRUE, FALSE );
  1874. }
  1875. } finally {
  1876. SrReleaseActivityLock( pExtension );
  1877. }
  1878. break;
  1879. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1880. SrTrace( PNP, ( "SR!SrPnp: CANCEL_REMOVE_DEVICE [%wZ]\n",
  1881. pExtension->pNtVolumeName ) );
  1882. //
  1883. // The removal is not going to happen, so reenable the device and
  1884. // the log will be restarted on the next interesting operation.
  1885. //
  1886. if (pExtension->Disabled) {
  1887. try {
  1888. SrAcquireActivityLockExclusive( pExtension );
  1889. pExtension->Disabled = FALSE;
  1890. } finally {
  1891. SrReleaseActivityLock( pExtension );
  1892. }
  1893. }
  1894. break;
  1895. default:
  1896. //
  1897. // All PNP minor codes we don't care about, so just pass
  1898. // the IO through.
  1899. //
  1900. break;
  1901. }
  1902. //
  1903. // If we have gotten here, we don't need to wait to see the result of this
  1904. // operation, so just call the appropriate file system driver with
  1905. // the request.
  1906. //
  1907. IoSkipCurrentIrpStackLocation( Irp );
  1908. return IoCallDriver( pExtension->pTargetDevice, Irp );
  1909. }
  1910. /***************************************************************************++
  1911. Routine Description:
  1912. this does the actual work for creating a new restore point.
  1913. this is called by the user mode SrCreateRestorePoint .
  1914. this IOCTL is METHOD_BUFFERED !
  1915. Arguments:
  1916. pIrp - the irp
  1917. pIrpSp - the irp stack
  1918. Return Value:
  1919. NTSTATUS - Status code.
  1920. --***************************************************************************/
  1921. NTSTATUS
  1922. SrCreateRestorePointIoctl(
  1923. IN PIRP pIrp,
  1924. IN PIO_STACK_LOCATION pIrpSp
  1925. )
  1926. {
  1927. NTSTATUS Status;
  1928. PUNICODE_STRING pVolumeName = NULL;
  1929. PLIST_ENTRY pListEntry;
  1930. PSR_DEVICE_EXTENSION pExtension;
  1931. BOOLEAN releaseActivityLocks = TRUE;
  1932. PSR_DEVICE_EXTENSION pSystemVolumeExtension = NULL;
  1933. PAGED_CODE();
  1934. ASSERT(IS_VALID_IRP(pIrp));
  1935. SrTrace( IOCTL, ("SR!SrCreateRestorePointIoctl -- ENTER\n") );
  1936. try {
  1937. //
  1938. // Grab the device extension list lock since we are
  1939. // going to have to pause all the volume activity.
  1940. //
  1941. SrAcquireDeviceExtensionListLockShared();
  1942. //
  1943. // We've got the device extension lock, so now try to pause
  1944. // activity on all the volumes.
  1945. //
  1946. Status = SrPauseVolumeActivity();
  1947. if (!NT_SUCCESS( Status )) {
  1948. releaseActivityLocks = FALSE;
  1949. leave;
  1950. }
  1951. try {
  1952. SrAcquireGlobalLockExclusive();
  1953. //
  1954. // make sure we've loaded the config file
  1955. //
  1956. if (!_globals.FileConfigLoaded)
  1957. {
  1958. Status = SrReadConfigFile();
  1959. if (!NT_SUCCESS(Status))
  1960. leave;
  1961. _globals.FileConfigLoaded = TRUE;
  1962. }
  1963. } finally {
  1964. SrReleaseGlobalLock();
  1965. }
  1966. if (!NT_SUCCESS( Status )) {
  1967. leave;
  1968. }
  1969. //
  1970. // Clear the volumes' DriveChecked flag so that we check the volumes
  1971. // again. this will create the restore point directories.
  1972. //
  1973. // also stop logging on all volumes. new log files will be created in
  1974. // the restore locations.
  1975. //
  1976. // We need to do this before we increment the current restore point
  1977. // counter.
  1978. //
  1979. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  1980. pListEntry != &_globals.DeviceExtensionListHead;
  1981. pListEntry = pListEntry->Flink)
  1982. {
  1983. pExtension = CONTAINING_RECORD( pListEntry,
  1984. SR_DEVICE_EXTENSION,
  1985. ListEntry );
  1986. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  1987. //
  1988. // We only have to do work if this is a volume device object,
  1989. // not if this is a device object that is attached to a file
  1990. // system's control device object.
  1991. //
  1992. if (FlagOn( pExtension->FsType, SrFsControlDeviceObject ))
  1993. {
  1994. continue;
  1995. }
  1996. //
  1997. // stop logging for this volume
  1998. //
  1999. if (pExtension->pLogContext != NULL)
  2000. {
  2001. Status = SrLogStop( pExtension, FALSE, TRUE );
  2002. CHECK_STATUS( Status );
  2003. }
  2004. else
  2005. {
  2006. ASSERT(!pExtension->DriveChecked);
  2007. Status = SrLogNormalize( pExtension );
  2008. CHECK_STATUS( Status );
  2009. }
  2010. //
  2011. // make sure to enable all of the volumes again. If the user
  2012. // has disabled the volume, this is tracked in the blob info.
  2013. //
  2014. pExtension->Disabled = FALSE;
  2015. //
  2016. // make sure the drive is checked again for the new restore point
  2017. //
  2018. pExtension->DriveChecked = FALSE;
  2019. //
  2020. // reset the byte count, it's a new restore point
  2021. //
  2022. pExtension->BytesWritten = 0;
  2023. //
  2024. // clear out the backup history so that we start backing
  2025. // up files again
  2026. //
  2027. Status = SrResetBackupHistory(pExtension, NULL, 0, SrEventInvalid);
  2028. if (!NT_SUCCESS(Status))
  2029. leave;
  2030. }
  2031. try {
  2032. SrAcquireGlobalLockExclusive();
  2033. //
  2034. // bump up the restore point number
  2035. //
  2036. _globals.FileConfig.CurrentRestoreNumber += 1;
  2037. SrTrace( INIT, ("sr!SrCreateRestorePointIoctl: RestorePoint=%d\n",
  2038. _globals.FileConfig.CurrentRestoreNumber ));
  2039. //
  2040. // save out the config file
  2041. //
  2042. Status = SrWriteConfigFile();
  2043. if (!NT_SUCCESS(Status))
  2044. leave;
  2045. } finally {
  2046. SrReleaseGlobalLock();
  2047. }
  2048. if (!NT_SUCCESS( Status )) {
  2049. leave;
  2050. }
  2051. //
  2052. // allocate space for a filename
  2053. //
  2054. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, &pVolumeName);
  2055. if (!NT_SUCCESS(Status))
  2056. leave;
  2057. //
  2058. // get the location of the system volume
  2059. //
  2060. Status = SrGetSystemVolume( pVolumeName,
  2061. &pSystemVolumeExtension,
  2062. SR_FILENAME_BUFFER_LENGTH );
  2063. //
  2064. // This should only happen if there was some problem with SR attaching
  2065. // in the mount path. This check was added to make SR more robust to
  2066. // busted filters above us. If other filters cause us to get mounted,
  2067. // we won't have an extension to return here. While those filters are
  2068. // broken, we don't want to AV.
  2069. //
  2070. if (pSystemVolumeExtension == NULL)
  2071. {
  2072. Status = STATUS_UNSUCCESSFUL;
  2073. leave;
  2074. }
  2075. if (!NT_SUCCESS(Status))
  2076. leave;
  2077. ASSERT( IS_VALID_SR_DEVICE_EXTENSION( pSystemVolumeExtension ) );
  2078. //
  2079. // create the restore point dir on the system volume
  2080. //
  2081. Status = SrCreateRestoreLocation( pSystemVolumeExtension );
  2082. if (!NT_SUCCESS(Status))
  2083. leave;
  2084. //
  2085. // return the restore point number
  2086. //
  2087. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  2088. sizeof(ULONG))
  2089. {
  2090. RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,
  2091. &_globals.FileConfig.CurrentRestoreNumber,
  2092. sizeof(ULONG) );
  2093. pIrp->IoStatus.Information = sizeof(ULONG);
  2094. }
  2095. //
  2096. // all done
  2097. //
  2098. } finally {
  2099. Status = FinallyUnwind(SrCreateRestorePointIoctl, Status);
  2100. if (releaseActivityLocks) {
  2101. SrResumeVolumeActivity ();
  2102. }
  2103. SrReleaseDeviceExtensionListLock();
  2104. if (pVolumeName != NULL)
  2105. {
  2106. SrFreeFileNameBuffer(pVolumeName);
  2107. pVolumeName = NULL;
  2108. }
  2109. }
  2110. SrTrace( IOCTL, ("SR!SrCreateRestorePointIoctl -- EXIT -- status 0x%08lx\n",
  2111. Status));
  2112. //
  2113. // At this point if Status != PENDING, the ioctl wrapper will
  2114. // complete pIrp
  2115. //
  2116. RETURN(Status);
  2117. } // SrCreateRestorePointIoctl
  2118. /***************************************************************************++
  2119. Routine Description:
  2120. this does the actual work for getting the next seq number from the filter
  2121. this is called by the user mode SrGetNextSequenceNum .
  2122. this IOCTL is METHOD_BUFFERED !
  2123. Arguments:
  2124. pIrp - the irp
  2125. pIrpSp - the irp stack
  2126. Return Value:
  2127. NTSTATUS - Status code.
  2128. --***************************************************************************/
  2129. NTSTATUS
  2130. SrGetNextSeqNumIoctl(
  2131. IN PIRP pIrp,
  2132. IN PIO_STACK_LOCATION pIrpSp
  2133. )
  2134. {
  2135. NTSTATUS Status;
  2136. PAGED_CODE();
  2137. ASSERT(IS_VALID_IRP(pIrp));
  2138. SrTrace( IOCTL, ("SR!SrGetNextSeqNumIoctl -- ENTER\n") );
  2139. try
  2140. {
  2141. INT64 SeqNum = 0;
  2142. //
  2143. // grab the global lock
  2144. //
  2145. SrAcquireGlobalLockExclusive();
  2146. //
  2147. // make sure we've loaded the config file
  2148. //
  2149. if (!_globals.FileConfigLoaded)
  2150. {
  2151. Status = SrReadConfigFile();
  2152. if (!NT_SUCCESS(Status))
  2153. leave;
  2154. _globals.FileConfigLoaded = TRUE;
  2155. }
  2156. //
  2157. // Get the next sequence number
  2158. //
  2159. Status = SrGetNextSeqNumber(&SeqNum);
  2160. if (NT_SUCCESS(Status))
  2161. {
  2162. //
  2163. // return the restore point number
  2164. //
  2165. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  2166. sizeof(INT64))
  2167. {
  2168. RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,
  2169. &SeqNum,
  2170. sizeof(INT64) );
  2171. pIrp->IoStatus.Information = sizeof(INT64);
  2172. }
  2173. }
  2174. }
  2175. finally
  2176. {
  2177. Status = FinallyUnwind(SrGetNextSeqNumIoctl, Status);
  2178. SrReleaseGlobalLock();
  2179. }
  2180. SrTrace( IOCTL, ("SR!SrGetNextSeqNumIoctl -- EXIT -- status 0x%08lx\n",
  2181. Status) );
  2182. //
  2183. // At this point if Status != PENDING, the ioctl wrapper will
  2184. // complete pIrp
  2185. //
  2186. RETURN(Status);
  2187. } // SrGetNextSeqNumIoctl
  2188. NTSTATUS
  2189. SrReloadConfigurationIoctl(
  2190. IN PIRP pIrp,
  2191. IN PIO_STACK_LOCATION IrpSp
  2192. )
  2193. {
  2194. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  2195. PUNICODE_STRING pFileName = NULL;
  2196. ULONG CharCount;
  2197. PLIST_ENTRY pListEntry;
  2198. PSR_DEVICE_EXTENSION pExtension;
  2199. BOOLEAN releaseDeviceExtensionListLock = FALSE;
  2200. PSR_DEVICE_EXTENSION pSystemVolumeExtension = NULL;
  2201. UNREFERENCED_PARAMETER( pIrp );
  2202. UNREFERENCED_PARAMETER( IrpSp );
  2203. PAGED_CODE();
  2204. SrTrace( IOCTL, ("SR!SrReloadConfigurationIoctl -- ENTER\n") );
  2205. try {
  2206. //
  2207. // allocate space for a filename
  2208. //
  2209. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, &pFileName);
  2210. if (!NT_SUCCESS(Status))
  2211. leave;
  2212. //
  2213. // get the location of the system volume
  2214. //
  2215. Status = SrGetSystemVolume( pFileName,
  2216. &pSystemVolumeExtension,
  2217. SR_FILENAME_BUFFER_LENGTH );
  2218. //
  2219. // This should only happen if there was some problem with SR attaching
  2220. // in the mount path. This check was added to make SR more robust to
  2221. // busted filters above us. If other filters cause us to get mounted,
  2222. // we won't have an extension to return here. While those filters are
  2223. // broken, we don't want to AV.
  2224. //
  2225. if (pSystemVolumeExtension == NULL)
  2226. {
  2227. Status = STATUS_UNSUCCESSFUL;
  2228. leave;
  2229. }
  2230. if (!NT_SUCCESS(Status))
  2231. leave;
  2232. ASSERT( IS_VALID_SR_DEVICE_EXTENSION( pSystemVolumeExtension ) );
  2233. //
  2234. // load the file list config data
  2235. //
  2236. CharCount = swprintf( &pFileName->Buffer[pFileName->Length/sizeof(WCHAR)],
  2237. RESTORE_FILELIST_LOCATION,
  2238. _globals.MachineGuid );
  2239. pFileName->Length += (USHORT)CharCount * sizeof(WCHAR);
  2240. Status = SrReloadLookupBlob( pFileName,
  2241. pSystemVolumeExtension->pTargetDevice,
  2242. &_globals.BlobInfo );
  2243. if (!NT_SUCCESS(Status))
  2244. {
  2245. leave;
  2246. }
  2247. //
  2248. // flush our volume configuration, it needs to be reconfigured as to
  2249. // which drives are enabled or not
  2250. //
  2251. //
  2252. // loop over all volumes reseting their disabled config
  2253. //
  2254. SrAcquireDeviceExtensionListLockShared();
  2255. releaseDeviceExtensionListLock = TRUE;
  2256. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  2257. pListEntry != &_globals.DeviceExtensionListHead;
  2258. pListEntry = pListEntry->Flink)
  2259. {
  2260. pExtension = CONTAINING_RECORD( pListEntry,
  2261. SR_DEVICE_EXTENSION,
  2262. ListEntry );
  2263. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2264. try {
  2265. SrAcquireActivityLockExclusive( pExtension );
  2266. pExtension->Disabled = FALSE;
  2267. } finally {
  2268. SrReleaseActivityLock( pExtension );
  2269. }
  2270. }
  2271. } finally {
  2272. //
  2273. // check for unhandled exceptions
  2274. //
  2275. Status = FinallyUnwind(SrReloadConfigurationIoctl, Status);
  2276. if (releaseDeviceExtensionListLock) {
  2277. SrReleaseDeviceExtensionListLock();
  2278. }
  2279. if (pFileName != NULL)
  2280. {
  2281. SrFreeFileNameBuffer(pFileName);
  2282. pFileName = NULL;
  2283. }
  2284. }
  2285. SrTrace( IOCTL, ("SR!SrReloadConfigurationIoctl -- EXIT -- status 0x%08lx\n",
  2286. Status));
  2287. RETURN(Status);
  2288. } // SrReloadConfigurationIoctl
  2289. NTSTATUS
  2290. SrSwitchAllLogsIoctl(
  2291. IN PIRP pIrp,
  2292. IN PIO_STACK_LOCATION IrpSp
  2293. )
  2294. {
  2295. NTSTATUS Status;
  2296. PAGED_CODE();
  2297. UNREFERENCED_PARAMETER( pIrp );
  2298. UNREFERENCED_PARAMETER( IrpSp );
  2299. SrTrace( IOCTL, ("SR!SrSwitchAllLogsIoctl -- ENTER\n") );
  2300. Status = SrLoggerSwitchLogs(_globals.pLogger);
  2301. SrTrace( IOCTL, ("SR!SrSwitchAllLogsIoctl -- EXIT -- status 0x%08lx\n",
  2302. Status));
  2303. RETURN(Status);
  2304. } // SrSwitchAllLogsIoctl
  2305. NTSTATUS
  2306. SrDisableVolumeIoctl(
  2307. IN PIRP pIrp,
  2308. IN PIO_STACK_LOCATION pIrpSp
  2309. )
  2310. {
  2311. NTSTATUS Status;
  2312. PSR_DEVICE_EXTENSION pExtension;
  2313. UNICODE_STRING VolumeName;
  2314. PAGED_CODE();
  2315. ASSERT(IS_VALID_IRP(pIrp));
  2316. SrTrace( IOCTL, ("SR!SrDisableVolumeIoctl -- ENTER\n") );
  2317. if (pIrp->AssociatedIrp.SystemBuffer == NULL ||
  2318. pIrpSp->Parameters.DeviceIoControl.InputBufferLength <= sizeof(WCHAR) ||
  2319. pIrpSp->Parameters.DeviceIoControl.InputBufferLength > SR_MAX_FILENAME_LENGTH)
  2320. {
  2321. RETURN ( STATUS_INVALID_DEVICE_REQUEST );
  2322. }
  2323. //
  2324. // get the volume name out
  2325. //
  2326. VolumeName.Buffer = pIrp->AssociatedIrp.SystemBuffer;
  2327. VolumeName.Length = (USHORT)(pIrpSp->Parameters.DeviceIoControl.InputBufferLength - sizeof(WCHAR));
  2328. VolumeName.MaximumLength = VolumeName.Length;
  2329. //
  2330. // attach to it. it will check for a previous attachement and do the
  2331. // right thing .
  2332. //
  2333. Status = SrAttachToVolumeByName(&VolumeName, &pExtension);
  2334. if (!NT_SUCCESS(Status)) {
  2335. RETURN( Status );
  2336. }
  2337. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2338. try {
  2339. SrAcquireActivityLockExclusive( pExtension );
  2340. //
  2341. // now turn it off
  2342. //
  2343. pExtension->Disabled = TRUE;
  2344. //
  2345. // stop logging on the volume
  2346. //
  2347. if (pExtension->pLogContext != NULL)
  2348. {
  2349. SrLogStop( pExtension, TRUE, TRUE );
  2350. }
  2351. else
  2352. {
  2353. ASSERT(!pExtension->DriveChecked);
  2354. }
  2355. //
  2356. // Reset the backup history since the information stored there
  2357. // is no longer valid.
  2358. //
  2359. Status = SrResetBackupHistory(pExtension, NULL, 0, SrEventInvalid);
  2360. } finally {
  2361. //
  2362. // check for unhandled exceptions
  2363. //
  2364. Status = FinallyUnwind(SrDisableVolumeIoctl, Status);
  2365. SrReleaseActivityLock( pExtension );
  2366. //
  2367. // At this point if Status != PENDING, the ioctl wrapper will
  2368. // complete pIrp
  2369. //
  2370. }
  2371. SrTrace( IOCTL, ("SR!SrDisableVolumeIoctl -- EXIT -- status 0x%08lx\n",
  2372. Status));
  2373. RETURN(Status);
  2374. } // SrDisableVolumeIoctl
  2375. NTSTATUS
  2376. SrStartMonitoringIoctl(
  2377. IN PIRP pIrp,
  2378. IN PIO_STACK_LOCATION IrpSp
  2379. )
  2380. {
  2381. NTSTATUS Status = STATUS_SUCCESS;
  2382. UNREFERENCED_PARAMETER( pIrp );
  2383. UNREFERENCED_PARAMETER( IrpSp );
  2384. PAGED_CODE();
  2385. SrTrace( IOCTL, ("SR!SrStartMonitoringIoctl -- ENTER\n") );
  2386. ASSERT(IS_VALID_IRP(pIrp));
  2387. //
  2388. // no locks better be held, the registry hits the disk with it's own
  2389. // locks held so we deadlock .
  2390. //
  2391. ASSERT(!IS_GLOBAL_LOCK_ACQUIRED());
  2392. //
  2393. // reload the registry information, on firstrun, we would have
  2394. // no valid machine guid until we are started manually by the service
  2395. //
  2396. Status = SrReadRegistry(_globals.pRegistryLocation, FALSE);
  2397. if (!NT_SUCCESS(Status))
  2398. {
  2399. goto SrStartMonitoringIoctl_Exit;
  2400. }
  2401. //
  2402. // Before we enable, we should clear our all old notifications.
  2403. //
  2404. SrClearOutstandingNotifications();
  2405. //
  2406. // now turn us on
  2407. //
  2408. _globals.Disabled = FALSE;
  2409. SrStartMonitoringIoctl_Exit:
  2410. SrTrace( IOCTL, ("SR!SrStartMonitoringIoctl -- EXIT -- status 0x%08lx\n",
  2411. Status));
  2412. RETURN(Status);
  2413. } // SrStartMonitoringIoctl
  2414. NTSTATUS
  2415. SrStopMonitoringIoctl(
  2416. IN PIRP pIrp,
  2417. IN PIO_STACK_LOCATION IrpSp
  2418. )
  2419. {
  2420. NTSTATUS Status;
  2421. PLIST_ENTRY pListEntry;
  2422. PSR_DEVICE_EXTENSION pExtension;
  2423. UNREFERENCED_PARAMETER( pIrp );
  2424. UNREFERENCED_PARAMETER( IrpSp );
  2425. PAGED_CODE();
  2426. SrTrace( IOCTL, ("SR!SrStopMonitoringIoctl -- ENTER\n") );
  2427. ASSERT(IS_VALID_IRP(pIrp));
  2428. try {
  2429. //
  2430. // Disable the driver before we start shutting down each volume
  2431. // so that a volume isn't reenabled while we are shutting down
  2432. // other volumes.
  2433. //
  2434. _globals.Disabled = TRUE;
  2435. //
  2436. // Stop logging on all volumes
  2437. //
  2438. SrAcquireDeviceExtensionListLockShared();
  2439. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  2440. pListEntry != &_globals.DeviceExtensionListHead;
  2441. pListEntry = pListEntry->Flink)
  2442. {
  2443. pExtension = CONTAINING_RECORD( pListEntry,
  2444. SR_DEVICE_EXTENSION,
  2445. ListEntry );
  2446. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2447. //
  2448. // We only have to do work if this is a volume device object,
  2449. // not if this is a device object that is attached to a file
  2450. // system's control device object.
  2451. //
  2452. if (FlagOn( pExtension->FsType, SrFsControlDeviceObject ))
  2453. {
  2454. continue;
  2455. }
  2456. try {
  2457. //
  2458. // Take a reference on the DeviceObject associated with this
  2459. // extension to ensure that the DeviceObject won't get detached
  2460. // until we return from SrLogStop. SrLogStop could have the
  2461. // last open handle on this volume, so during shutdown, closing
  2462. // this handle could cause the base file system to initiate
  2463. // the tearing down of the filter stack. If this happens,
  2464. // without this extra reference, we will call SrFastIoDetach
  2465. // before we return from SrLogStop. This will cause the
  2466. // machine to deadlock on the device extension list lock (we
  2467. // currently have the device extension list lock shared and
  2468. // SrFastIoDetach needs to acquire it exclusive).
  2469. //
  2470. ObReferenceObject( pExtension->pDeviceObject );
  2471. SrAcquireActivityLockExclusive( pExtension );
  2472. pExtension->Disabled = FALSE;
  2473. if (pExtension->pLogContext != NULL)
  2474. {
  2475. Status = SrLogStop( pExtension, TRUE, TRUE );
  2476. CHECK_STATUS( Status );
  2477. }
  2478. else
  2479. {
  2480. ASSERT(!pExtension->DriveChecked);
  2481. Status = SrLogNormalize( pExtension );
  2482. CHECK_STATUS( Status );
  2483. }
  2484. } finally {
  2485. SrReleaseActivityLock( pExtension );
  2486. ObDereferenceObject( pExtension->pDeviceObject );
  2487. }
  2488. }
  2489. //
  2490. // check logger status
  2491. //
  2492. ASSERT( _globals.pLogger->ActiveContexts == 0 );
  2493. //
  2494. // Unload the blob config -- SrFreeLookupBlock acquires the appropriate
  2495. // locks.
  2496. //
  2497. Status = SrFreeLookupBlob(&_globals.BlobInfo);
  2498. if (!NT_SUCCESS(Status))
  2499. leave;
  2500. ASSERT(!_globals.BlobInfoLoaded);
  2501. Status = STATUS_SUCCESS;
  2502. } finally {
  2503. Status = FinallyUnwind(SrStopMonitoringIoctl, Status);
  2504. SrReleaseDeviceExtensionListLock();
  2505. }
  2506. SrTrace( IOCTL, ("SR!SrStopMonitoringIoctl -- EXIT -- status 0x%08lx\n",
  2507. Status));
  2508. RETURN(Status);
  2509. } // SrStopMonitoringIoctl
  2510. /***************************************************************************++
  2511. Routine Description:
  2512. This is a generic completion routine that signals the event passed in
  2513. then returns STATUS_MORE_PROCESSING_REQUIRED so that the dispatch routine
  2514. that it is synchronizing with can still access the Irp. The dispatch
  2515. routine is responsible for restarting the completion processing.
  2516. Arguments:
  2517. DeviceObject - Pointer to this driver's device object.
  2518. Irp - Pointer to the IRP that was just completed.
  2519. EventToSignal - Pointer to the event to signal.
  2520. Return Value:
  2521. The return value is always STATUS_MORE_PROCESSING_REQUIRED.
  2522. --***************************************************************************/
  2523. NTSTATUS
  2524. SrDismountCompletion (
  2525. IN PDEVICE_OBJECT DeviceObject,
  2526. IN PIRP Irp,
  2527. IN PVOID Context
  2528. )
  2529. {
  2530. PSR_DEVICE_EXTENSION pExtension;
  2531. UNREFERENCED_PARAMETER( Context );
  2532. ASSERT(IS_SR_DEVICE_OBJECT( DeviceObject ));
  2533. pExtension = DeviceObject->DeviceExtension;
  2534. if (!NT_SUCCESS_NO_DBGBREAK(Irp->IoStatus.Status)) {
  2535. //
  2536. // The volume failed to dismount, so we want to enable this
  2537. // extension so that the log will get reinitialized on the
  2538. // first interesting operation.
  2539. //
  2540. pExtension->Disabled = FALSE;
  2541. }
  2542. //
  2543. // Propogate the pending flag as needed.
  2544. //
  2545. if (Irp->PendingReturned) {
  2546. IoMarkIrpPending( Irp );
  2547. }
  2548. return STATUS_SUCCESS;
  2549. } // SrStopProcessingCompletion
  2550. /***************************************************************************++
  2551. Routine Description:
  2552. This is a generic completion routine that signals the event passed in
  2553. then returns STATUS_MORE_PROCESSING_REQUIRED so that the dispatch routine
  2554. that it is synchronizing with can still access the Irp. The dispatch
  2555. routine is responsible for restarting the completion processing.
  2556. Arguments:
  2557. DeviceObject - Pointer to this driver's device object.
  2558. Irp - Pointer to the IRP that was just completed.
  2559. EventToSignal - Pointer to the event to signal.
  2560. Return Value:
  2561. The return value is always STATUS_MORE_PROCESSING_REQUIRED.
  2562. --***************************************************************************/
  2563. NTSTATUS
  2564. SrStopProcessingCompletion (
  2565. IN PDEVICE_OBJECT DeviceObject,
  2566. IN PIRP Irp,
  2567. IN PKEVENT EventToSignal
  2568. )
  2569. {
  2570. UNREFERENCED_PARAMETER( Irp );
  2571. UNREFERENCED_PARAMETER( DeviceObject );
  2572. ASSERT( IS_SR_DEVICE_OBJECT( DeviceObject ) );
  2573. ASSERT(NULL != EventToSignal);
  2574. KeSetEvent( EventToSignal, IO_NO_INCREMENT, FALSE );
  2575. //
  2576. // We don't propagate the pending flag here since
  2577. // we are doing the synchronization with the originating
  2578. // thread.
  2579. //
  2580. //
  2581. // By return STATUS_MORE_PROCESSING_REQUIRED, we stop all further
  2582. // processing of the IRP by the IO Manager. This means that the IRP
  2583. // will still be good when the thread waiting on the above event.
  2584. // The waiting thread needs the IRP to check and update the
  2585. // Irp->IoStatus.Status as appropriate.
  2586. //
  2587. return STATUS_MORE_PROCESSING_REQUIRED;
  2588. } // SrStopProcessingCompletion
  2589. /***************************************************************************++
  2590. Routine Description:
  2591. shutdown is happening. flushes our config file to the disk.
  2592. Arguments:
  2593. Return Value:
  2594. NTSTATUS - Status code.
  2595. --***************************************************************************/
  2596. NTSTATUS
  2597. SrShutdown(
  2598. IN PDEVICE_OBJECT DeviceObject,
  2599. IN PIRP pIrp
  2600. )
  2601. {
  2602. PSR_DEVICE_EXTENSION pExtension = NULL;
  2603. //
  2604. // < dispatch!
  2605. //
  2606. PAGED_CODE();
  2607. ASSERT( IS_VALID_DEVICE_OBJECT( DeviceObject ) );
  2608. ASSERT( IS_VALID_IRP( pIrp ) );
  2609. ASSERT( IS_SR_DEVICE_OBJECT( DeviceObject ) );
  2610. pExtension = DeviceObject->DeviceExtension;
  2611. SrTrace(INIT, ( "SR!SrShutdown:%p,%wZ [%wZ]\n",
  2612. DeviceObject,
  2613. &pExtension->pTargetDevice->DriverObject->DriverName,
  2614. pExtension->pNtVolumeName ));
  2615. //
  2616. // Get this driver out of the driver stack and get to the next driver as
  2617. // quickly as possible.
  2618. //
  2619. //
  2620. // Is this a function for our device (vs an attachee) .
  2621. //
  2622. if (DeviceObject == _globals.pControlDevice)
  2623. {
  2624. return SrMajorFunction(DeviceObject, pIrp);
  2625. }
  2626. //
  2627. // We get SHUTDOWN irp directed at each file system control device
  2628. // object that we are attached to when the system is shutting down.
  2629. //
  2630. // At this time, we need to loop through the SR device objects and
  2631. // find all the SR device objects associated with volumes that are running
  2632. // this file system. We use the FsType field in the device extension
  2633. // to figure this out.
  2634. //
  2635. // We need to shutdown the log for all volumes that use this file system
  2636. // because after this operation gets to the file system, all volumes
  2637. // using this file system will no longer be able to satify write operations
  2638. // from us.
  2639. //
  2640. ASSERT(SR_IS_FS_CONTROL_DEVICE(pExtension));
  2641. //
  2642. // SR's extensions that are attached to control device objects should
  2643. // never get disabled.
  2644. //
  2645. ASSERT( !pExtension->Disabled );
  2646. try {
  2647. PLIST_ENTRY pListEntry;
  2648. SR_FILESYSTEM_TYPE interestingFsType;
  2649. PSR_DEVICE_EXTENSION pCurrentExtension;
  2650. interestingFsType = pExtension->FsType;
  2651. ClearFlag( interestingFsType, SrFsControlDeviceObject );
  2652. SrAcquireDeviceExtensionListLockShared();
  2653. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  2654. pListEntry != &(_globals.DeviceExtensionListHead);
  2655. pListEntry = pListEntry->Flink ) {
  2656. pCurrentExtension = CONTAINING_RECORD( pListEntry,
  2657. SR_DEVICE_EXTENSION,
  2658. ListEntry );
  2659. if (pCurrentExtension->FsType == interestingFsType) {
  2660. try {
  2661. SrAcquireActivityLockExclusive( pCurrentExtension );
  2662. //
  2663. // Disable this drive so that we do not log any more
  2664. // activity on it.
  2665. //
  2666. pCurrentExtension->Disabled = TRUE;
  2667. //
  2668. // Now cleanup the log on this volume so that the log
  2669. // we get flushed to the disk before the file system
  2670. // shuts down.
  2671. //
  2672. if (pCurrentExtension->pLogContext != NULL)
  2673. {
  2674. SrLogStop( pCurrentExtension, TRUE, FALSE );
  2675. }
  2676. } finally {
  2677. SrReleaseActivityLock( pCurrentExtension );
  2678. }
  2679. }
  2680. }
  2681. } finally {
  2682. SrReleaseDeviceExtensionListLock();
  2683. }
  2684. //
  2685. // time to update our configuration file ?
  2686. //
  2687. try {
  2688. SrAcquireGlobalLockExclusive();
  2689. if (_globals.FileConfigLoaded)
  2690. {
  2691. //
  2692. // write our the real next file number (not the +1000)
  2693. //
  2694. _globals.FileConfig.FileSeqNumber = _globals.LastSeqNumber;
  2695. _globals.FileConfig.FileNameNumber = _globals.LastFileNameNumber;
  2696. SrWriteConfigFile();
  2697. //
  2698. // only need to do this once
  2699. //
  2700. _globals.FileConfigLoaded = FALSE;
  2701. }
  2702. } finally {
  2703. SrReleaseGlobalLock();
  2704. }
  2705. //
  2706. // Now pass this operation to the next device in the stack. We don't
  2707. // need a completion routine, so just skip our current stack location.
  2708. //
  2709. IoSkipCurrentIrpStackLocation(pIrp);
  2710. return IoCallDriver(pExtension->pTargetDevice, pIrp);
  2711. } // SrShutdown