Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3650 lines
98 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. BOOLEAN ReleaseLock = FALSE;
  1588. PAGED_CODE();
  1589. ASSERT( SR_IS_FS_CONTROL_DEVICE(pExtension) );
  1590. //
  1591. // create our device we are going to attach to this new volume
  1592. //
  1593. pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
  1594. pRealDevice = pIrpSp->Parameters.MountVolume.Vpb->RealDevice;
  1595. Status = SrCreateAttachmentDevice( pRealDevice,
  1596. pDeviceObject,
  1597. &pNewDeviceObject );
  1598. if (!NT_SUCCESS( Status ))
  1599. {
  1600. IoSkipCurrentIrpStackLocation( pIrp );
  1601. return IoCallDriver( pExtension->pTargetDevice, pIrp );
  1602. }
  1603. //
  1604. // If we get here, we need to set our completion routine then
  1605. // wait for it to signal us before we continue with the post processing
  1606. // of the mount.
  1607. //
  1608. KeInitializeEvent( &EventToWaitOn, NotificationEvent, FALSE );
  1609. IoCopyCurrentIrpStackLocationToNext(pIrp);
  1610. IoSetCompletionRoutine( pIrp,
  1611. SrStopProcessingCompletion,
  1612. &EventToWaitOn, // CompletionContext
  1613. TRUE,
  1614. TRUE,
  1615. TRUE );
  1616. pIrpSp->Parameters.MountVolume.DeviceObject =
  1617. pIrpSp->Parameters.MountVolume.Vpb->RealDevice;
  1618. Status = IoCallDriver( pExtension->pTargetDevice, pIrp );
  1619. if (STATUS_PENDING == Status)
  1620. {
  1621. NTSTATUS localStatus = KeWaitForSingleObject( &EventToWaitOn,
  1622. Executive,
  1623. KernelMode,
  1624. FALSE,
  1625. NULL );
  1626. ASSERT( NT_SUCCESS( localStatus ) );
  1627. }
  1628. //
  1629. // skip out if the mount failed
  1630. //
  1631. if (!NT_SUCCESS_NO_DBGBREAK(pIrp->IoStatus.Status))
  1632. {
  1633. goto SrFsControlMount_Error;
  1634. }
  1635. //
  1636. // Note that the VPB must be picked up from the real device object
  1637. // so that we can see the DeviceObject that the file system created
  1638. // to represent this newly mounted volume.
  1639. //
  1640. pVpb = pRealDevice->Vpb;
  1641. ASSERT(pVpb != NULL);
  1642. //
  1643. // SrFsControl made sure that we support this volume type
  1644. //
  1645. ASSERT(SR_IS_SUPPORTED_VOLUME(pVpb));
  1646. //
  1647. // Are we already attached to this device? We need to hold the
  1648. // AttachToVolumeLock while we do this to ensure that we don't hit
  1649. // a race condition with once of the other paths that can cause us to
  1650. // attach to a volume.
  1651. //
  1652. SrAcquireAttachToVolumeLock();
  1653. ReleaseLock = TRUE;
  1654. if (NT_SUCCESS( pIrp->IoStatus.Status ) &&
  1655. (SrGetFilterDevice(pVpb->DeviceObject) == NULL))
  1656. {
  1657. //
  1658. // now attach to the new volume
  1659. //
  1660. Status = SrAttachToDevice( pVpb->RealDevice,
  1661. pVpb->DeviceObject,
  1662. pNewDeviceObject,
  1663. NULL );
  1664. if (NT_SUCCESS(Status))
  1665. {
  1666. goto SrFsControlMount_Exit;
  1667. }
  1668. }
  1669. SrFsControlMount_Error:
  1670. ASSERT( pNewDeviceObject != NULL );
  1671. SrDeleteAttachmentDevice( pNewDeviceObject );
  1672. SrFsControlMount_Exit:
  1673. if (ReleaseLock)
  1674. {
  1675. SrReleaseAttachToVolumeLock();
  1676. }
  1677. Status = pIrp->IoStatus.Status;
  1678. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  1679. return Status;
  1680. }
  1681. /***************************************************************************++
  1682. Routine Description:
  1683. Arguments:
  1684. Return Value:
  1685. NTSTATUS - Status code.
  1686. --***************************************************************************/
  1687. NTSTATUS
  1688. SrFsControlLockOrDismount (
  1689. IN PSR_DEVICE_EXTENSION pExtension,
  1690. IN PIRP pIrp
  1691. )
  1692. {
  1693. NTSTATUS Status = STATUS_SUCCESS;
  1694. UNREFERENCED_PARAMETER( pIrp );
  1695. PAGED_CODE();
  1696. try {
  1697. //
  1698. // close our log file handle on this volume , it's being
  1699. // locked. it's ok if the lock attempt fails, we will open
  1700. // our handle again automatically since DriveChecked is also
  1701. // being cleared.
  1702. //
  1703. SrAcquireActivityLockExclusive( pExtension);
  1704. if (pExtension->pLogContext != NULL)
  1705. {
  1706. Status = SrLogStop( pExtension, TRUE );
  1707. CHECK_STATUS( Status );
  1708. }
  1709. } finally {
  1710. SrReleaseActivityLock(pExtension);
  1711. }
  1712. return Status;
  1713. }
  1714. /***************************************************************************++
  1715. Routine Description:
  1716. Arguments:
  1717. Return Value:
  1718. NTSTATUS - Status code.
  1719. --***************************************************************************/
  1720. VOID
  1721. SrFsControlWriteRawEncrypted (
  1722. IN PSR_DEVICE_EXTENSION pExtension,
  1723. IN PIRP pIrp
  1724. )
  1725. {
  1726. PIO_STACK_LOCATION pIrpSp;
  1727. NTSTATUS Status;
  1728. PSR_STREAM_CONTEXT pFileContext = NULL;
  1729. PAGED_CODE();
  1730. pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
  1731. if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pIrpSp->FileObject ) ||
  1732. FILE_OBJECT_DOES_NOT_HAVE_VPB( pIrpSp->FileObject )) {
  1733. return;
  1734. }
  1735. //
  1736. // Look up the context for this file object so that we can figure out
  1737. // if this is a file or a directory. If this is a directory, the
  1738. // file system will fail the operation, so there is no need to try to
  1739. // back it up.
  1740. //
  1741. Status = SrGetContext( pExtension,
  1742. pIrpSp->FileObject,
  1743. SrEventStreamChange,
  1744. &pFileContext );
  1745. if (!NT_SUCCESS( Status ))
  1746. {
  1747. //
  1748. // We hit some error trying to get the context. If this should
  1749. // generate a volume error, it has already been taken care of inside
  1750. // SrGetContext. Otherwise, this just means that the actual operation
  1751. // will fail, so there is no work for us to do here.
  1752. //
  1753. return;
  1754. }
  1755. ASSERT( NULL != pFileContext );
  1756. //
  1757. // Make sure that we have an interesting file. This operation
  1758. // is invalid on directories.
  1759. //
  1760. if (FlagOn( pFileContext->Flags, CTXFL_IsInteresting )&&
  1761. !FlagOn( pFileContext->Flags, CTXFL_IsDirectory ))
  1762. {
  1763. SrHandleEvent( pExtension,
  1764. SrEventStreamChange,
  1765. pIrpSp->FileObject,
  1766. pFileContext,
  1767. NULL,
  1768. NULL );
  1769. }
  1770. //
  1771. // We are all done with this context, so now release it.
  1772. //
  1773. ASSERT( NULL != pFileContext );
  1774. SrReleaseContext( pFileContext );
  1775. NULLPTR(pFileContext);
  1776. return;
  1777. }
  1778. /***************************************************************************++
  1779. Routine Description:
  1780. When a file is set to sparse, we need to clear out our context for this
  1781. file. On the next interesting operation for this file, we will regenerate
  1782. a correct context.
  1783. This work is done since SR doesn't want to monitor files that are SPARSE.
  1784. Arguments:
  1785. Return Value:
  1786. None.
  1787. --***************************************************************************/
  1788. VOID
  1789. SrFsControlSetSparse (
  1790. IN PSR_DEVICE_EXTENSION pExtension,
  1791. IN PIRP pIrp
  1792. )
  1793. {
  1794. PIO_STACK_LOCATION irpSp;
  1795. PFILE_OBJECT pFileObject;
  1796. PSR_STREAM_CONTEXT pFileContext = NULL;
  1797. PAGED_CODE();
  1798. irpSp = IoGetCurrentIrpStackLocation( pIrp );
  1799. pFileObject = irpSp->FileObject;
  1800. pFileContext = SrFindExistingContext( pExtension, pFileObject );
  1801. if (pFileContext != NULL)
  1802. {
  1803. SrDeleteContext( pExtension, pFileContext );
  1804. SrReleaseContext( pFileContext );
  1805. }
  1806. return;
  1807. }
  1808. /***************************************************************************++
  1809. Routine Description:
  1810. handles IRP_MJ_PNP. SR needs to close its handle to the log when it sees
  1811. that the volume is going away and reopen it when the drive reappears.
  1812. Arguments:
  1813. DeviceObject - the device object being processed
  1814. pIrp - the irp
  1815. Return Value:
  1816. NTSTATUS - Status code.
  1817. --***************************************************************************/
  1818. NTSTATUS
  1819. SrPnp (
  1820. IN PDEVICE_OBJECT DeviceObject,
  1821. IN PIRP Irp
  1822. )
  1823. {
  1824. PSR_DEVICE_EXTENSION pExtension;
  1825. PIO_STACK_LOCATION irpSp;
  1826. PAGED_CODE();
  1827. ASSERT(IS_VALID_DEVICE_OBJECT(DeviceObject));
  1828. ASSERT(IS_VALID_IRP(Irp));
  1829. //
  1830. // Get this driver out of the driver stack and get to the next driver as
  1831. // quickly as possible.
  1832. //
  1833. //
  1834. // Is this a function for our device (vs an attachee) .
  1835. //
  1836. if (DeviceObject == _globals.pControlDevice)
  1837. {
  1838. return SrMajorFunction(DeviceObject, Irp);
  1839. }
  1840. //
  1841. // else it is a device we've attached to, grab our extension
  1842. //
  1843. ASSERT( IS_SR_DEVICE_OBJECT( DeviceObject ) );
  1844. pExtension = DeviceObject->DeviceExtension;
  1845. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1846. switch ( irpSp->MinorFunction ) {
  1847. case IRP_MN_QUERY_REMOVE_DEVICE:
  1848. SrTrace( PNP, ( "SR!SrPnp: QUERY_REMOVE_DEVICE [%wZ]\n",
  1849. pExtension->pNtVolumeName ) );
  1850. //
  1851. // If this is a SURPRISE_REMOVAL, the device has already gone away
  1852. // and we are not going to see any more operations to this volume, but
  1853. // the OS won't call us to detach and delete our device object until
  1854. // all the handles that are outstanding on this volume are closed. Do
  1855. // our part by closing down the handle to our log.
  1856. //
  1857. try {
  1858. SrAcquireActivityLockExclusive( pExtension );
  1859. pExtension->Disabled = TRUE;
  1860. if (pExtension->pLogContext != NULL)
  1861. {
  1862. SrLogStop( pExtension, TRUE );
  1863. }
  1864. } finally {
  1865. SrReleaseActivityLock( pExtension );
  1866. }
  1867. break;
  1868. case IRP_MN_SURPRISE_REMOVAL:
  1869. SrTrace( PNP, ( "SR!SrPnp: SURPRISE_REMOVAL [%wZ]\n",
  1870. pExtension->pNtVolumeName ) );
  1871. //
  1872. // If this is a SURPRISE_REMOVAL, the device has already gone away
  1873. // and we are not going to see any more operations to this volume, but
  1874. // the OS won't call us to detach and delete our device object until
  1875. // all the handles that are outstanding on this volume are closed. Do
  1876. // our part by closing down the handle to our log.
  1877. //
  1878. try {
  1879. SrAcquireActivityLockExclusive( pExtension );
  1880. pExtension->Disabled = TRUE;
  1881. if (pExtension->pLogContext != NULL)
  1882. {
  1883. SrLogStop( pExtension, TRUE );
  1884. }
  1885. } finally {
  1886. SrReleaseActivityLock( pExtension );
  1887. }
  1888. break;
  1889. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1890. SrTrace( PNP, ( "SR!SrPnp: CANCEL_REMOVE_DEVICE [%wZ]\n",
  1891. pExtension->pNtVolumeName ) );
  1892. //
  1893. // The removal is not going to happen, so reenable the device and
  1894. // the log will be restarted on the next interesting operation.
  1895. //
  1896. if (pExtension->Disabled) {
  1897. try {
  1898. SrAcquireActivityLockExclusive( pExtension );
  1899. pExtension->Disabled = FALSE;
  1900. } finally {
  1901. SrReleaseActivityLock( pExtension );
  1902. }
  1903. }
  1904. break;
  1905. default:
  1906. //
  1907. // All PNP minor codes we don't care about, so just pass
  1908. // the IO through.
  1909. //
  1910. break;
  1911. }
  1912. //
  1913. // If we have gotten here, we don't need to wait to see the result of this
  1914. // operation, so just call the appropriate file system driver with
  1915. // the request.
  1916. //
  1917. IoSkipCurrentIrpStackLocation( Irp );
  1918. return IoCallDriver( pExtension->pTargetDevice, Irp );
  1919. }
  1920. /***************************************************************************++
  1921. Routine Description:
  1922. this does the actual work for creating a new restore point.
  1923. this is called by the user mode SrCreateRestorePoint .
  1924. this IOCTL is METHOD_BUFFERED !
  1925. Arguments:
  1926. pIrp - the irp
  1927. pIrpSp - the irp stack
  1928. Return Value:
  1929. NTSTATUS - Status code.
  1930. --***************************************************************************/
  1931. NTSTATUS
  1932. SrCreateRestorePointIoctl(
  1933. IN PIRP pIrp,
  1934. IN PIO_STACK_LOCATION pIrpSp
  1935. )
  1936. {
  1937. NTSTATUS Status;
  1938. PUNICODE_STRING pVolumeName = NULL;
  1939. PLIST_ENTRY pListEntry;
  1940. PSR_DEVICE_EXTENSION pExtension;
  1941. BOOLEAN releaseActivityLocks = TRUE;
  1942. PSR_DEVICE_EXTENSION pSystemVolumeExtension = NULL;
  1943. PAGED_CODE();
  1944. ASSERT(IS_VALID_IRP(pIrp));
  1945. SrTrace( IOCTL, ("SR!SrCreateRestorePointIoctl -- ENTER\n") );
  1946. try {
  1947. //
  1948. // Grab the device extension list lock since we are
  1949. // going to have to pause all the volume activity.
  1950. //
  1951. SrAcquireDeviceExtensionListLockShared();
  1952. //
  1953. // We've got the device extension lock, so now try to pause
  1954. // activity on all the volumes.
  1955. //
  1956. Status = SrPauseVolumeActivity();
  1957. if (!NT_SUCCESS( Status )) {
  1958. releaseActivityLocks = FALSE;
  1959. leave;
  1960. }
  1961. try {
  1962. SrAcquireGlobalLockExclusive();
  1963. //
  1964. // make sure we've loaded the config file
  1965. //
  1966. if (!_globals.FileConfigLoaded)
  1967. {
  1968. Status = SrReadConfigFile();
  1969. if (!NT_SUCCESS(Status))
  1970. leave;
  1971. _globals.FileConfigLoaded = TRUE;
  1972. }
  1973. } finally {
  1974. SrReleaseGlobalLock();
  1975. }
  1976. if (!NT_SUCCESS( Status )) {
  1977. leave;
  1978. }
  1979. //
  1980. // Clear the volumes' DriveChecked flag so that we check the volumes
  1981. // again. this will create the restore point directories.
  1982. //
  1983. // also stop logging on all volumes. new log files will be created in
  1984. // the restore locations.
  1985. //
  1986. // We need to do this before we increment the current restore point
  1987. // counter.
  1988. //
  1989. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  1990. pListEntry != &_globals.DeviceExtensionListHead;
  1991. pListEntry = pListEntry->Flink)
  1992. {
  1993. pExtension = CONTAINING_RECORD( pListEntry,
  1994. SR_DEVICE_EXTENSION,
  1995. ListEntry );
  1996. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  1997. //
  1998. // We only have to do work if this is a volume device object,
  1999. // not if this is a device object that is attached to a file
  2000. // system's control device object.
  2001. //
  2002. if (FlagOn( pExtension->FsType, SrFsControlDeviceObject ))
  2003. {
  2004. continue;
  2005. }
  2006. //
  2007. // stop logging for this volume
  2008. //
  2009. if (pExtension->pLogContext != NULL)
  2010. {
  2011. Status = SrLogStop( pExtension, FALSE );
  2012. CHECK_STATUS( Status );
  2013. }
  2014. //
  2015. // make sure to enable all of the volumes again. If the user
  2016. // has disabled the volume, this is tracked in the blob info.
  2017. //
  2018. pExtension->Disabled = FALSE;
  2019. //
  2020. // make sure the drive is checked again for the new restore point
  2021. //
  2022. pExtension->DriveChecked = FALSE;
  2023. //
  2024. // reset the byte count, it's a new restore point
  2025. //
  2026. pExtension->BytesWritten = 0;
  2027. //
  2028. // clear out the backup history so that we start backing
  2029. // up files again
  2030. //
  2031. Status = SrResetBackupHistory(pExtension, NULL, 0, SrEventInvalid);
  2032. if (!NT_SUCCESS(Status))
  2033. leave;
  2034. }
  2035. try {
  2036. SrAcquireGlobalLockExclusive();
  2037. //
  2038. // bump up the restore point number
  2039. //
  2040. _globals.FileConfig.CurrentRestoreNumber += 1;
  2041. SrTrace( INIT, ("sr!SrCreateRestorePointIoctl: RestorePoint=%d\n",
  2042. _globals.FileConfig.CurrentRestoreNumber ));
  2043. //
  2044. // save out the config file
  2045. //
  2046. Status = SrWriteConfigFile();
  2047. if (!NT_SUCCESS(Status))
  2048. leave;
  2049. } finally {
  2050. SrReleaseGlobalLock();
  2051. }
  2052. if (!NT_SUCCESS( Status )) {
  2053. leave;
  2054. }
  2055. //
  2056. // allocate space for a filename
  2057. //
  2058. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, &pVolumeName);
  2059. if (!NT_SUCCESS(Status))
  2060. leave;
  2061. //
  2062. // get the location of the system volume
  2063. //
  2064. Status = SrGetSystemVolume( pVolumeName,
  2065. &pSystemVolumeExtension,
  2066. SR_FILENAME_BUFFER_LENGTH );
  2067. //
  2068. // This should only happen if there was some problem with SR attaching
  2069. // in the mount path. This check was added to make SR more robust to
  2070. // busted filters above us. If other filters cause us to get mounted,
  2071. // we won't have an extension to return here. While those filters are
  2072. // broken, we don't want to AV.
  2073. //
  2074. if (pSystemVolumeExtension == NULL)
  2075. {
  2076. Status = STATUS_UNSUCCESSFUL;
  2077. leave;
  2078. }
  2079. if (!NT_SUCCESS(Status))
  2080. leave;
  2081. ASSERT( IS_VALID_SR_DEVICE_EXTENSION( pSystemVolumeExtension ) );
  2082. //
  2083. // create the restore point dir on the system volume
  2084. //
  2085. Status = SrCreateRestoreLocation( pSystemVolumeExtension );
  2086. if (!NT_SUCCESS(Status))
  2087. leave;
  2088. //
  2089. // return the restore point number
  2090. //
  2091. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  2092. sizeof(ULONG))
  2093. {
  2094. RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,
  2095. &_globals.FileConfig.CurrentRestoreNumber,
  2096. sizeof(ULONG) );
  2097. pIrp->IoStatus.Information = sizeof(ULONG);
  2098. }
  2099. //
  2100. // all done
  2101. //
  2102. } finally {
  2103. Status = FinallyUnwind(SrCreateRestorePointIoctl, Status);
  2104. if (releaseActivityLocks) {
  2105. SrResumeVolumeActivity ();
  2106. }
  2107. SrReleaseDeviceExtensionListLock();
  2108. if (pVolumeName != NULL)
  2109. {
  2110. SrFreeFileNameBuffer(pVolumeName);
  2111. pVolumeName = NULL;
  2112. }
  2113. }
  2114. SrTrace( IOCTL, ("SR!SrCreateRestorePointIoctl -- EXIT -- status 0x%08lx\n",
  2115. Status));
  2116. //
  2117. // At this point if Status != PENDING, the ioctl wrapper will
  2118. // complete pIrp
  2119. //
  2120. RETURN(Status);
  2121. } // SrCreateRestorePointIoctl
  2122. /***************************************************************************++
  2123. Routine Description:
  2124. this does the actual work for getting the next seq number from the filter
  2125. this is called by the user mode SrGetNextSequenceNum .
  2126. this IOCTL is METHOD_BUFFERED !
  2127. Arguments:
  2128. pIrp - the irp
  2129. pIrpSp - the irp stack
  2130. Return Value:
  2131. NTSTATUS - Status code.
  2132. --***************************************************************************/
  2133. NTSTATUS
  2134. SrGetNextSeqNumIoctl(
  2135. IN PIRP pIrp,
  2136. IN PIO_STACK_LOCATION pIrpSp
  2137. )
  2138. {
  2139. NTSTATUS Status;
  2140. PAGED_CODE();
  2141. ASSERT(IS_VALID_IRP(pIrp));
  2142. SrTrace( IOCTL, ("SR!SrGetNextSeqNumIoctl -- ENTER\n") );
  2143. try
  2144. {
  2145. INT64 SeqNum = 0;
  2146. //
  2147. // grab the global lock
  2148. //
  2149. SrAcquireGlobalLockExclusive();
  2150. //
  2151. // make sure we've loaded the config file
  2152. //
  2153. if (!_globals.FileConfigLoaded)
  2154. {
  2155. Status = SrReadConfigFile();
  2156. if (!NT_SUCCESS(Status))
  2157. leave;
  2158. _globals.FileConfigLoaded = TRUE;
  2159. }
  2160. //
  2161. // Get the next sequence number
  2162. //
  2163. Status = SrGetNextSeqNumber(&SeqNum);
  2164. if (NT_SUCCESS(Status))
  2165. {
  2166. //
  2167. // return the restore point number
  2168. //
  2169. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  2170. sizeof(INT64))
  2171. {
  2172. RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,
  2173. &SeqNum,
  2174. sizeof(INT64) );
  2175. pIrp->IoStatus.Information = sizeof(INT64);
  2176. }
  2177. }
  2178. }
  2179. finally
  2180. {
  2181. Status = FinallyUnwind(SrGetNextSeqNumIoctl, Status);
  2182. SrReleaseGlobalLock();
  2183. }
  2184. SrTrace( IOCTL, ("SR!SrGetNextSeqNumIoctl -- EXIT -- status 0x%08lx\n",
  2185. Status) );
  2186. //
  2187. // At this point if Status != PENDING, the ioctl wrapper will
  2188. // complete pIrp
  2189. //
  2190. RETURN(Status);
  2191. } // SrGetNextSeqNumIoctl
  2192. NTSTATUS
  2193. SrReloadConfigurationIoctl(
  2194. IN PIRP pIrp,
  2195. IN PIO_STACK_LOCATION IrpSp
  2196. )
  2197. {
  2198. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  2199. PUNICODE_STRING pFileName = NULL;
  2200. ULONG CharCount;
  2201. PLIST_ENTRY pListEntry;
  2202. PSR_DEVICE_EXTENSION pExtension;
  2203. BOOLEAN releaseDeviceExtensionListLock = FALSE;
  2204. PSR_DEVICE_EXTENSION pSystemVolumeExtension = NULL;
  2205. UNREFERENCED_PARAMETER( pIrp );
  2206. UNREFERENCED_PARAMETER( IrpSp );
  2207. PAGED_CODE();
  2208. SrTrace( IOCTL, ("SR!SrReloadConfigurationIoctl -- ENTER\n") );
  2209. try {
  2210. //
  2211. // allocate space for a filename
  2212. //
  2213. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, &pFileName);
  2214. if (!NT_SUCCESS(Status))
  2215. leave;
  2216. //
  2217. // get the location of the system volume
  2218. //
  2219. Status = SrGetSystemVolume( pFileName,
  2220. &pSystemVolumeExtension,
  2221. SR_FILENAME_BUFFER_LENGTH );
  2222. //
  2223. // This should only happen if there was some problem with SR attaching
  2224. // in the mount path. This check was added to make SR more robust to
  2225. // busted filters above us. If other filters cause us to get mounted,
  2226. // we won't have an extension to return here. While those filters are
  2227. // broken, we don't want to AV.
  2228. //
  2229. if (pSystemVolumeExtension == NULL)
  2230. {
  2231. Status = STATUS_UNSUCCESSFUL;
  2232. leave;
  2233. }
  2234. if (!NT_SUCCESS(Status))
  2235. leave;
  2236. ASSERT( IS_VALID_SR_DEVICE_EXTENSION( pSystemVolumeExtension ) );
  2237. //
  2238. // load the file list config data
  2239. //
  2240. CharCount = swprintf( &pFileName->Buffer[pFileName->Length/sizeof(WCHAR)],
  2241. RESTORE_FILELIST_LOCATION,
  2242. _globals.MachineGuid );
  2243. pFileName->Length += (USHORT)CharCount * sizeof(WCHAR);
  2244. Status = SrReloadLookupBlob( pFileName,
  2245. pSystemVolumeExtension->pTargetDevice,
  2246. &_globals.BlobInfo );
  2247. if (!NT_SUCCESS(Status))
  2248. {
  2249. leave;
  2250. }
  2251. //
  2252. // flush our volume configuration, it needs to be reconfigured as to
  2253. // which drives are enabled or not
  2254. //
  2255. //
  2256. // loop over all volumes reseting their disabled config
  2257. //
  2258. SrAcquireDeviceExtensionListLockShared();
  2259. releaseDeviceExtensionListLock = TRUE;
  2260. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  2261. pListEntry != &_globals.DeviceExtensionListHead;
  2262. pListEntry = pListEntry->Flink)
  2263. {
  2264. pExtension = CONTAINING_RECORD( pListEntry,
  2265. SR_DEVICE_EXTENSION,
  2266. ListEntry );
  2267. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2268. try {
  2269. SrAcquireActivityLockExclusive( pExtension );
  2270. pExtension->Disabled = FALSE;
  2271. } finally {
  2272. SrReleaseActivityLock( pExtension );
  2273. }
  2274. }
  2275. } finally {
  2276. //
  2277. // check for unhandled exceptions
  2278. //
  2279. Status = FinallyUnwind(SrReloadConfigurationIoctl, Status);
  2280. if (releaseDeviceExtensionListLock) {
  2281. SrReleaseDeviceExtensionListLock();
  2282. }
  2283. if (pFileName != NULL)
  2284. {
  2285. SrFreeFileNameBuffer(pFileName);
  2286. pFileName = NULL;
  2287. }
  2288. }
  2289. SrTrace( IOCTL, ("SR!SrReloadConfigurationIoctl -- EXIT -- status 0x%08lx\n",
  2290. Status));
  2291. RETURN(Status);
  2292. } // SrReloadConfigurationIoctl
  2293. NTSTATUS
  2294. SrSwitchAllLogsIoctl(
  2295. IN PIRP pIrp,
  2296. IN PIO_STACK_LOCATION IrpSp
  2297. )
  2298. {
  2299. NTSTATUS Status;
  2300. PAGED_CODE();
  2301. UNREFERENCED_PARAMETER( pIrp );
  2302. UNREFERENCED_PARAMETER( IrpSp );
  2303. SrTrace( IOCTL, ("SR!SrSwitchAllLogsIoctl -- ENTER\n") );
  2304. Status = SrLoggerSwitchLogs(_globals.pLogger);
  2305. SrTrace( IOCTL, ("SR!SrSwitchAllLogsIoctl -- EXIT -- status 0x%08lx\n",
  2306. Status));
  2307. RETURN(Status);
  2308. } // SrSwitchAllLogsIoctl
  2309. NTSTATUS
  2310. SrDisableVolumeIoctl(
  2311. IN PIRP pIrp,
  2312. IN PIO_STACK_LOCATION pIrpSp
  2313. )
  2314. {
  2315. NTSTATUS Status;
  2316. PSR_DEVICE_EXTENSION pExtension;
  2317. UNICODE_STRING VolumeName;
  2318. PAGED_CODE();
  2319. ASSERT(IS_VALID_IRP(pIrp));
  2320. SrTrace( IOCTL, ("SR!SrDisableVolumeIoctl -- ENTER\n") );
  2321. if (pIrp->AssociatedIrp.SystemBuffer == NULL ||
  2322. pIrpSp->Parameters.DeviceIoControl.InputBufferLength <= sizeof(WCHAR) ||
  2323. pIrpSp->Parameters.DeviceIoControl.InputBufferLength > SR_MAX_FILENAME_LENGTH)
  2324. {
  2325. RETURN ( STATUS_INVALID_DEVICE_REQUEST );
  2326. }
  2327. //
  2328. // get the volume name out
  2329. //
  2330. VolumeName.Buffer = pIrp->AssociatedIrp.SystemBuffer;
  2331. VolumeName.Length = (USHORT)(pIrpSp->Parameters.DeviceIoControl.InputBufferLength - sizeof(WCHAR));
  2332. VolumeName.MaximumLength = VolumeName.Length;
  2333. //
  2334. // attach to it. it will check for a previous attachement and do the
  2335. // right thing .
  2336. //
  2337. Status = SrAttachToVolumeByName(&VolumeName, &pExtension);
  2338. if (!NT_SUCCESS(Status)) {
  2339. RETURN( Status );
  2340. }
  2341. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2342. try {
  2343. SrAcquireActivityLockExclusive( pExtension );
  2344. //
  2345. // now turn it off
  2346. //
  2347. pExtension->Disabled = TRUE;
  2348. //
  2349. // stop logging on the volume
  2350. //
  2351. if (pExtension->pLogContext != NULL)
  2352. {
  2353. SrLogStop( pExtension, TRUE );
  2354. }
  2355. else
  2356. {
  2357. ASSERT(!pExtension->DriveChecked);
  2358. }
  2359. //
  2360. // Reset the backup history since the information stored there
  2361. // is no longer valid.
  2362. //
  2363. Status = SrResetBackupHistory(pExtension, NULL, 0, SrEventInvalid);
  2364. } finally {
  2365. //
  2366. // check for unhandled exceptions
  2367. //
  2368. Status = FinallyUnwind(SrDisableVolumeIoctl, Status);
  2369. SrReleaseActivityLock( pExtension );
  2370. //
  2371. // At this point if Status != PENDING, the ioctl wrapper will
  2372. // complete pIrp
  2373. //
  2374. }
  2375. SrTrace( IOCTL, ("SR!SrDisableVolumeIoctl -- EXIT -- status 0x%08lx\n",
  2376. Status));
  2377. RETURN(Status);
  2378. } // SrDisableVolumeIoctl
  2379. NTSTATUS
  2380. SrStartMonitoringIoctl(
  2381. IN PIRP pIrp,
  2382. IN PIO_STACK_LOCATION IrpSp
  2383. )
  2384. {
  2385. NTSTATUS Status = STATUS_SUCCESS;
  2386. UNREFERENCED_PARAMETER( pIrp );
  2387. UNREFERENCED_PARAMETER( IrpSp );
  2388. PAGED_CODE();
  2389. SrTrace( IOCTL, ("SR!SrStartMonitoringIoctl -- ENTER\n") );
  2390. ASSERT(IS_VALID_IRP(pIrp));
  2391. //
  2392. // no locks better be held, the registry hits the disk with it's own
  2393. // locks held so we deadlock .
  2394. //
  2395. ASSERT(!IS_GLOBAL_LOCK_ACQUIRED());
  2396. //
  2397. // reload the registry information, on firstrun, we would have
  2398. // no valid machine guid until we are started manually by the service
  2399. //
  2400. Status = SrReadRegistry(_globals.pRegistryLocation, FALSE);
  2401. if (!NT_SUCCESS(Status))
  2402. {
  2403. goto SrStartMonitoringIoctl_Exit;
  2404. }
  2405. //
  2406. // Before we enable, we should clear our all old notifications.
  2407. //
  2408. SrClearOutstandingNotifications();
  2409. //
  2410. // now turn us on
  2411. //
  2412. _globals.Disabled = FALSE;
  2413. SrStartMonitoringIoctl_Exit:
  2414. SrTrace( IOCTL, ("SR!SrStartMonitoringIoctl -- EXIT -- status 0x%08lx\n",
  2415. Status));
  2416. RETURN(Status);
  2417. } // SrStartMonitoringIoctl
  2418. NTSTATUS
  2419. SrStopMonitoringIoctl(
  2420. IN PIRP pIrp,
  2421. IN PIO_STACK_LOCATION IrpSp
  2422. )
  2423. {
  2424. NTSTATUS Status;
  2425. PLIST_ENTRY pListEntry;
  2426. PSR_DEVICE_EXTENSION pExtension;
  2427. UNREFERENCED_PARAMETER( pIrp );
  2428. UNREFERENCED_PARAMETER( IrpSp );
  2429. PAGED_CODE();
  2430. SrTrace( IOCTL, ("SR!SrStopMonitoringIoctl -- ENTER\n") );
  2431. ASSERT(IS_VALID_IRP(pIrp));
  2432. try {
  2433. //
  2434. // Disable the driver before we start shutting down each volume
  2435. // so that a volume isn't reenabled while we are shutting down
  2436. // other volumes.
  2437. //
  2438. _globals.Disabled = TRUE;
  2439. //
  2440. // Stop logging on all volumes
  2441. //
  2442. SrAcquireDeviceExtensionListLockShared();
  2443. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  2444. pListEntry != &_globals.DeviceExtensionListHead;
  2445. pListEntry = pListEntry->Flink)
  2446. {
  2447. pExtension = CONTAINING_RECORD( pListEntry,
  2448. SR_DEVICE_EXTENSION,
  2449. ListEntry );
  2450. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2451. //
  2452. // We only have to do work if this is a volume device object,
  2453. // not if this is a device object that is attached to a file
  2454. // system's control device object.
  2455. //
  2456. if (FlagOn( pExtension->FsType, SrFsControlDeviceObject ))
  2457. {
  2458. continue;
  2459. }
  2460. try {
  2461. //
  2462. // Take a reference on the DeviceObject associated with this
  2463. // extension to ensure that the DeviceObject won't get detached
  2464. // until we return from SrLogStop. SrLogStop could have the
  2465. // last open handle on this volume, so during shutdown, closing
  2466. // this handle could cause the base file system to initiate
  2467. // the tearing down of the filter stack. If this happens,
  2468. // without this extra reference, we will call SrFastIoDetach
  2469. // before we return from SrLogStop. This will cause the
  2470. // machine to deadlock on the device extension list lock (we
  2471. // currently have the device extension list lock shared and
  2472. // SrFastIoDetach needs to acquire it exclusive).
  2473. //
  2474. ObReferenceObject( pExtension->pDeviceObject );
  2475. SrAcquireActivityLockExclusive( pExtension );
  2476. pExtension->Disabled = FALSE;
  2477. if (pExtension->pLogContext != NULL)
  2478. {
  2479. Status = SrLogStop( pExtension, TRUE );
  2480. CHECK_STATUS( Status );
  2481. }
  2482. } finally {
  2483. SrReleaseActivityLock( pExtension );
  2484. ObDereferenceObject( pExtension->pDeviceObject );
  2485. }
  2486. }
  2487. //
  2488. // check logger status
  2489. //
  2490. ASSERT( _globals.pLogger->ActiveContexts == 0 );
  2491. //
  2492. // Unload the blob config -- SrFreeLookupBlock acquires the appropriate
  2493. // locks.
  2494. //
  2495. Status = SrFreeLookupBlob(&_globals.BlobInfo);
  2496. if (!NT_SUCCESS(Status))
  2497. leave;
  2498. ASSERT(!_globals.BlobInfoLoaded);
  2499. Status = STATUS_SUCCESS;
  2500. } finally {
  2501. Status = FinallyUnwind(SrStopMonitoringIoctl, Status);
  2502. SrReleaseDeviceExtensionListLock();
  2503. }
  2504. SrTrace( IOCTL, ("SR!SrStopMonitoringIoctl -- EXIT -- status 0x%08lx\n",
  2505. Status));
  2506. RETURN(Status);
  2507. } // SrStopMonitoringIoctl
  2508. /***************************************************************************++
  2509. Routine Description:
  2510. This is a generic completion routine that signals the event passed in
  2511. then returns STATUS_MORE_PROCESSING_REQUIRED so that the dispatch routine
  2512. that it is synchronizing with can still access the Irp. The dispatch
  2513. routine is responsible for restarting the completion processing.
  2514. Arguments:
  2515. DeviceObject - Pointer to this driver's device object.
  2516. Irp - Pointer to the IRP that was just completed.
  2517. EventToSignal - Pointer to the event to signal.
  2518. Return Value:
  2519. The return value is always STATUS_MORE_PROCESSING_REQUIRED.
  2520. --***************************************************************************/
  2521. NTSTATUS
  2522. SrDismountCompletion (
  2523. IN PDEVICE_OBJECT DeviceObject,
  2524. IN PIRP Irp,
  2525. IN PVOID Context
  2526. )
  2527. {
  2528. PSR_DEVICE_EXTENSION pExtension;
  2529. UNREFERENCED_PARAMETER( Context );
  2530. ASSERT(IS_SR_DEVICE_OBJECT( DeviceObject ));
  2531. pExtension = DeviceObject->DeviceExtension;
  2532. if (!NT_SUCCESS_NO_DBGBREAK(Irp->IoStatus.Status)) {
  2533. //
  2534. // The volume failed to dismount, so we want to enable this
  2535. // extension so that the log will get reinitialized on the
  2536. // first interesting operation.
  2537. //
  2538. pExtension->Disabled = FALSE;
  2539. }
  2540. //
  2541. // Propogate the pending flag as needed.
  2542. //
  2543. if (Irp->PendingReturned) {
  2544. IoMarkIrpPending( Irp );
  2545. }
  2546. return STATUS_SUCCESS;
  2547. } // SrStopProcessingCompletion
  2548. /***************************************************************************++
  2549. Routine Description:
  2550. This is a generic completion routine that signals the event passed in
  2551. then returns STATUS_MORE_PROCESSING_REQUIRED so that the dispatch routine
  2552. that it is synchronizing with can still access the Irp. The dispatch
  2553. routine is responsible for restarting the completion processing.
  2554. Arguments:
  2555. DeviceObject - Pointer to this driver's device object.
  2556. Irp - Pointer to the IRP that was just completed.
  2557. EventToSignal - Pointer to the event to signal.
  2558. Return Value:
  2559. The return value is always STATUS_MORE_PROCESSING_REQUIRED.
  2560. --***************************************************************************/
  2561. NTSTATUS
  2562. SrStopProcessingCompletion (
  2563. IN PDEVICE_OBJECT DeviceObject,
  2564. IN PIRP Irp,
  2565. IN PKEVENT EventToSignal
  2566. )
  2567. {
  2568. UNREFERENCED_PARAMETER( Irp );
  2569. UNREFERENCED_PARAMETER( DeviceObject );
  2570. ASSERT( IS_SR_DEVICE_OBJECT( DeviceObject ) );
  2571. ASSERT(NULL != EventToSignal);
  2572. KeSetEvent( EventToSignal, IO_NO_INCREMENT, FALSE );
  2573. //
  2574. // We don't propagate the pending flag here since
  2575. // we are doing the synchronization with the originating
  2576. // thread.
  2577. //
  2578. //
  2579. // By return STATUS_MORE_PROCESSING_REQUIRED, we stop all further
  2580. // processing of the IRP by the IO Manager. This means that the IRP
  2581. // will still be good when the thread waiting on the above event.
  2582. // The waiting thread needs the IRP to check and update the
  2583. // Irp->IoStatus.Status as appropriate.
  2584. //
  2585. return STATUS_MORE_PROCESSING_REQUIRED;
  2586. } // SrStopProcessingCompletion
  2587. /***************************************************************************++
  2588. Routine Description:
  2589. shutdown is happening. flushes our config file to the disk.
  2590. Arguments:
  2591. Return Value:
  2592. NTSTATUS - Status code.
  2593. --***************************************************************************/
  2594. NTSTATUS
  2595. SrShutdown(
  2596. IN PDEVICE_OBJECT DeviceObject,
  2597. IN PIRP pIrp
  2598. )
  2599. {
  2600. PSR_DEVICE_EXTENSION pExtension = NULL;
  2601. //
  2602. // < dispatch!
  2603. //
  2604. PAGED_CODE();
  2605. ASSERT( IS_VALID_DEVICE_OBJECT( DeviceObject ) );
  2606. ASSERT( IS_VALID_IRP( pIrp ) );
  2607. ASSERT( IS_SR_DEVICE_OBJECT( DeviceObject ) );
  2608. pExtension = DeviceObject->DeviceExtension;
  2609. SrTrace(INIT, ( "SR!SrShutdown:%p,%wZ [%wZ]\n",
  2610. DeviceObject,
  2611. &pExtension->pTargetDevice->DriverObject->DriverName,
  2612. pExtension->pNtVolumeName ));
  2613. //
  2614. // Get this driver out of the driver stack and get to the next driver as
  2615. // quickly as possible.
  2616. //
  2617. //
  2618. // Is this a function for our device (vs an attachee) .
  2619. //
  2620. if (DeviceObject == _globals.pControlDevice)
  2621. {
  2622. return SrMajorFunction(DeviceObject, pIrp);
  2623. }
  2624. //
  2625. // We get SHUTDOWN irp directed at each file system control device
  2626. // object that we are attached to when the system is shutting down.
  2627. //
  2628. // At this time, we need to loop through the SR device objects and
  2629. // find all the SR device objects associated with volumes that are running
  2630. // this file system. We use the FsType field in the device extension
  2631. // to figure this out.
  2632. //
  2633. // We need to shutdown the log for all volumes that use this file system
  2634. // because after this operation gets to the file system, all volumes
  2635. // using this file system will no longer be able to satify write operations
  2636. // from us.
  2637. //
  2638. ASSERT(SR_IS_FS_CONTROL_DEVICE(pExtension));
  2639. //
  2640. // SR's extensions that are attached to control device objects should
  2641. // never get disabled.
  2642. //
  2643. ASSERT( !pExtension->Disabled );
  2644. try {
  2645. PLIST_ENTRY pListEntry;
  2646. SR_FILESYSTEM_TYPE interestingFsType;
  2647. PSR_DEVICE_EXTENSION pCurrentExtension;
  2648. interestingFsType = pExtension->FsType;
  2649. ClearFlag( interestingFsType, SrFsControlDeviceObject );
  2650. SrAcquireDeviceExtensionListLockShared();
  2651. for (pListEntry = _globals.DeviceExtensionListHead.Flink;
  2652. pListEntry != &(_globals.DeviceExtensionListHead);
  2653. pListEntry = pListEntry->Flink ) {
  2654. pCurrentExtension = CONTAINING_RECORD( pListEntry,
  2655. SR_DEVICE_EXTENSION,
  2656. ListEntry );
  2657. if (pCurrentExtension->FsType == interestingFsType) {
  2658. try {
  2659. SrAcquireActivityLockExclusive( pCurrentExtension );
  2660. //
  2661. // Disable this drive so that we do not log any more
  2662. // activity on it.
  2663. //
  2664. pCurrentExtension->Disabled = TRUE;
  2665. //
  2666. // Now cleanup the log on this volume so that the log
  2667. // we get flushed to the disk before the file system
  2668. // shuts down.
  2669. //
  2670. if (pCurrentExtension->pLogContext != NULL)
  2671. {
  2672. SrLogStop( pCurrentExtension, TRUE );
  2673. }
  2674. } finally {
  2675. SrReleaseActivityLock( pCurrentExtension );
  2676. }
  2677. }
  2678. }
  2679. } finally {
  2680. SrReleaseDeviceExtensionListLock();
  2681. }
  2682. //
  2683. // time to update our configuration file ?
  2684. //
  2685. try {
  2686. SrAcquireGlobalLockExclusive();
  2687. if (_globals.FileConfigLoaded)
  2688. {
  2689. //
  2690. // write our the real next file number (not the +1000)
  2691. //
  2692. _globals.FileConfig.FileSeqNumber = _globals.LastSeqNumber;
  2693. _globals.FileConfig.FileNameNumber = _globals.LastFileNameNumber;
  2694. SrWriteConfigFile();
  2695. //
  2696. // only need to do this once
  2697. //
  2698. _globals.FileConfigLoaded = FALSE;
  2699. }
  2700. } finally {
  2701. SrReleaseGlobalLock();
  2702. }
  2703. //
  2704. // Now pass this operation to the next device in the stack. We don't
  2705. // need a completion routine, so just skip our current stack location.
  2706. //
  2707. IoSkipCurrentIrpStackLocation(pIrp);
  2708. return IoCallDriver(pExtension->pTargetDevice, pIrp);
  2709. } // SrShutdown