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.

4076 lines
127 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. event.c
  5. Abstract:
  6. This module contains the event handling logic for sr
  7. There are 3 main entrypoints to this module:
  8. SrHandleEvent
  9. SrHandleRename
  10. SrHandleDirectoryRename
  11. Author:
  12. Paul McDaniel (paulmcd) 18-Apr-2000
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. //
  17. // Private constants.
  18. //
  19. //
  20. // event optimization defines
  21. //
  22. //
  23. // Private types.
  24. //
  25. #define IS_VALID_TRIGGER_ITEM(pObject) \
  26. (((pObject) != NULL) && ((pObject)->Signature == SR_TRIGGER_ITEM_TAG))
  27. typedef struct _SR_TRIGGER_ITEM
  28. {
  29. //
  30. // PagedPool
  31. //
  32. //
  33. // = SR_TRIGGER_ITEM_TAG
  34. //
  35. ULONG Signature;
  36. LIST_ENTRY ListEntry;
  37. PUNICODE_STRING pDirectoryName;
  38. BOOLEAN FreeDirectoryName;
  39. HANDLE DirectoryHandle;
  40. PFILE_OBJECT pDirectoryObject;
  41. ULONG FileEntryLength;
  42. PFILE_DIRECTORY_INFORMATION pFileEntry;
  43. } SR_TRIGGER_ITEM, *PSR_TRIGGER_ITEM;
  44. typedef struct _SR_COUNTED_EVENT
  45. {
  46. //
  47. // NonPagedPool
  48. //
  49. LONG WorkItemCount;
  50. KEVENT Event;
  51. } SR_COUNTED_EVENT, *PSR_COUNTED_EVENT;
  52. #define IS_VALID_BACKUP_DIRECTORY_CONTEXT(pObject) \
  53. (((pObject) != NULL) && ((pObject)->Signature == SR_BACKUP_DIRECTORY_CONTEXT_TAG))
  54. typedef struct _SR_BACKUP_DIRECTORY_CONTEXT
  55. {
  56. //
  57. // PagedPool
  58. //
  59. //
  60. // = SR_BACKUP_DIRECTORY_CONTEXT_TAG
  61. //
  62. ULONG Signature;
  63. WORK_QUEUE_ITEM WorkItem;
  64. PSR_DEVICE_EXTENSION pExtension;
  65. UNICODE_STRING DirectoryName;
  66. BOOLEAN EventDelete;
  67. PSR_COUNTED_EVENT pEvent;
  68. } SR_BACKUP_DIRECTORY_CONTEXT, * PSR_BACKUP_DIRECTORY_CONTEXT;
  69. //
  70. // Private prototypes.
  71. //
  72. NTSTATUS
  73. SrpIsFileStillEligible (
  74. IN PSR_DEVICE_EXTENSION pExtension,
  75. IN PSR_STREAM_CONTEXT pFileContext,
  76. IN SR_EVENT_TYPE EventType,
  77. OUT PBOOLEAN pMonitorFile);
  78. VOID
  79. SrFreeTriggerItem (
  80. IN PSR_TRIGGER_ITEM pItem
  81. );
  82. NTSTATUS
  83. SrTriggerEvents (
  84. IN PSR_DEVICE_EXTENSION pExtension,
  85. IN PUNICODE_STRING pDirectoryName,
  86. IN BOOLEAN EventDelete
  87. );
  88. NTSTATUS
  89. SrHandleDelete(
  90. IN PSR_DEVICE_EXTENSION pExtension,
  91. IN PFILE_OBJECT pFileObject,
  92. IN PSR_STREAM_CONTEXT pFileContext
  93. );
  94. VOID
  95. SrCreateRestoreLocationWorker (
  96. IN PSR_WORK_ITEM pWorkItem
  97. );
  98. NTSTATUS
  99. SrHandleFileChange (
  100. IN PSR_DEVICE_EXTENSION pExtension,
  101. IN SR_EVENT_TYPE EventType,
  102. IN PFILE_OBJECT pFileObject,
  103. IN PUNICODE_STRING pFileName
  104. );
  105. NTSTATUS
  106. SrHandleFileOverwrite(
  107. IN PSR_DEVICE_EXTENSION pExtension,
  108. IN OUT PSR_OVERWRITE_INFO pOverwriteInfo,
  109. IN PSR_STREAM_CONTEXT pFileContext
  110. );
  111. NTSTATUS
  112. SrRenameFileIntoStore(
  113. IN PSR_DEVICE_EXTENSION pExtension,
  114. IN PFILE_OBJECT pFileObject,
  115. IN HANDLE FileHandle,
  116. IN PUNICODE_STRING pOriginalFileName,
  117. IN PUNICODE_STRING pFileName,
  118. IN SR_EVENT_TYPE EventType,
  119. OUT PFILE_RENAME_INFORMATION * ppRenameInfo OPTIONAL
  120. );
  121. //
  122. // linker commands
  123. //
  124. #ifdef ALLOC_PRAGMA
  125. #pragma alloc_text( PAGE, SrpIsFileStillEligible )
  126. #pragma alloc_text( PAGE, SrHandleEvent )
  127. #pragma alloc_text( PAGE, SrLogEvent )
  128. #pragma alloc_text( PAGE, SrHandleDelete )
  129. #pragma alloc_text( PAGE, SrCreateRestoreLocation )
  130. #pragma alloc_text( PAGE, SrCreateRestoreLocationWorker )
  131. #pragma alloc_text( PAGE, SrHandleFileChange )
  132. #pragma alloc_text( PAGE, SrHandleFileOverwrite )
  133. #pragma alloc_text( PAGE, SrRenameFileIntoStore )
  134. #pragma alloc_text( PAGE, SrTriggerEvents )
  135. #pragma alloc_text( PAGE, SrHandleDirectoryRename )
  136. #pragma alloc_text( PAGE, SrHandleFileRenameOutOfMonitoredSpace )
  137. #pragma alloc_text( PAGE, SrHandleOverwriteFailure )
  138. #pragma alloc_text( PAGE, SrFreeTriggerItem )
  139. #endif // ALLOC_PRAGMA
  140. //
  141. // Private globals.
  142. //
  143. //
  144. // Public globals.
  145. //
  146. //
  147. // Public functions.
  148. //
  149. /***************************************************************************++
  150. Routine Description:
  151. Arguments:
  152. Return Value:
  153. NTSTATUS - Completion status. can return STATUS_PENDING.
  154. --***************************************************************************/
  155. NTSTATUS
  156. SrpIsFileStillEligible (
  157. IN PSR_DEVICE_EXTENSION pExtension,
  158. IN PSR_STREAM_CONTEXT pFileContext,
  159. IN SR_EVENT_TYPE EventType,
  160. OUT PBOOLEAN pMonitorFile
  161. )
  162. {
  163. NTSTATUS status = STATUS_SUCCESS;
  164. PAGED_CODE();
  165. *pMonitorFile = TRUE;
  166. //
  167. // If is is not an overwrite, keep going
  168. //
  169. if (!(EventType & SrEventStreamOverwrite))
  170. {
  171. BOOLEAN HasBeenBackedUp;
  172. //
  173. // it is a match, but have we been told to skip it?
  174. // Since this routine can be called without the caller
  175. // having the activity lock acquired, we acquire it now
  176. //
  177. HasBeenBackedUp = SrHasFileBeenBackedUp( pExtension,
  178. &pFileContext->FileName,
  179. pFileContext->StreamNameLength,
  180. EventType );
  181. if (HasBeenBackedUp)
  182. {
  183. //
  184. // skip it
  185. //
  186. *pMonitorFile = FALSE;
  187. SrTrace( CONTEXT_LOG, ("Sr!SrpIsFileStillEligible:NO: (%p) Event=%06x Fl=%03x Use=%d \"%.*S\"\n",
  188. pFileContext,
  189. EventType,
  190. pFileContext->Flags,
  191. pFileContext->UseCount,
  192. (pFileContext->FileName.Length+
  193. pFileContext->StreamNameLength)/
  194. sizeof(WCHAR),
  195. pFileContext->FileName.Buffer));
  196. //
  197. // we are skipping this event due to the history, should we
  198. // log it regardless ?
  199. //
  200. if (EventType & SR_ALWAYS_LOG_EVENT_TYPES)
  201. {
  202. status = SrLogEvent( pExtension,
  203. EventType,
  204. NULL,
  205. &pFileContext->FileName,
  206. RECORD_AGAINST_STREAM( EventType,
  207. pFileContext->StreamNameLength ),
  208. NULL,
  209. NULL,
  210. 0,
  211. NULL );
  212. }
  213. }
  214. }
  215. return status;
  216. }
  217. /***************************************************************************++
  218. Routine Description:
  219. this is the main entry point for event handling.
  220. anytime an interesting event happens this function is called to see
  221. if this file is interesting to monitor, and then actually handles
  222. the event.
  223. it is possible for this to return STATUS_PENDING, in which case you must
  224. call it again after the fsd see's the event so that it can do
  225. post-processing.
  226. Delete is a case where this 2-step event handling happens.
  227. Arguments:
  228. EventType - the event that just occured
  229. pOverwriteInfo - this is only supplied from an MJ_CREATE, for use in
  230. overwrite optimizations
  231. pFileObject - the fileobject that the event occured on.
  232. pFileContext - Optionall a context structure that is passed in. Most
  233. of the time it will be NULL.
  234. Return Value:
  235. NTSTATUS - Completion status. can return STATUS_PENDING.
  236. --***************************************************************************/
  237. NTSTATUS
  238. SrHandleEvent(
  239. IN PSR_DEVICE_EXTENSION pExtension,
  240. IN SR_EVENT_TYPE EventType,
  241. IN PFILE_OBJECT pFileObject,
  242. IN PSR_STREAM_CONTEXT pFileContext OPTIONAL,
  243. IN OUT PSR_OVERWRITE_INFO pOverwriteInfo OPTIONAL,
  244. IN PUNICODE_STRING pFileName2 OPTIONAL
  245. )
  246. {
  247. NTSTATUS Status = STATUS_SUCCESS;
  248. BOOLEAN releaseLock = FALSE;
  249. BOOLEAN releaseContext = FALSE;
  250. BOOLEAN isStillInteresting;
  251. PAGED_CODE();
  252. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  253. ASSERT(IS_VALID_FILE_OBJECT(pFileObject));
  254. try {
  255. //
  256. // If a context was not passed in then get it now.
  257. //
  258. if (pFileContext == NULL)
  259. {
  260. //
  261. // Get the context for this operation. Create always calls
  262. // with the context parameter fill in so we can always so
  263. // we are NOT in create from this routine
  264. //
  265. Status = SrGetContext( pExtension,
  266. pFileObject,
  267. EventType,
  268. &pFileContext );
  269. if (!NT_SUCCESS( Status ))
  270. {
  271. leave;
  272. }
  273. //
  274. // We only want to release contexts which we have obtained
  275. // ourselves. Mark that we need to release this one
  276. //
  277. releaseContext = TRUE;
  278. }
  279. VALIDATE_FILENAME( &pFileContext->FileName );
  280. #if DBG
  281. //
  282. // Validate we have the correct directory state with the
  283. // given event.
  284. //
  285. if ((EventType & (SrEventDirectoryCreate |
  286. SrEventDirectoryRename |
  287. SrEventDirectoryDelete |
  288. SrEventMountCreate |
  289. SrEventMountDelete)) != 0)
  290. {
  291. ASSERT(FlagOn(pFileContext->Flags,CTXFL_IsDirectory));
  292. }
  293. if ((EventType & (SrEventFileCreate |
  294. SrEventFileRename |
  295. SrEventFileDelete |
  296. SrEventStreamChange |
  297. SrEventStreamOverwrite |
  298. SrEventStreamCreate)) != 0)
  299. {
  300. ASSERT(!FlagOn(pFileContext->Flags,CTXFL_IsDirectory));
  301. }
  302. #endif
  303. //
  304. // If the file is not interesting, leave now
  305. //
  306. if (!FlagOn(pFileContext->Flags,CTXFL_IsInteresting))
  307. {
  308. leave;
  309. }
  310. //
  311. // This looks to see if the file has already been backed up.
  312. // If so it handles the appropriate logging and returns that
  313. // the file is no longer eligible
  314. //
  315. Status = SrpIsFileStillEligible( pExtension,
  316. pFileContext,
  317. EventType,
  318. &isStillInteresting );
  319. if (!NT_SUCCESS( Status ) || !isStillInteresting)
  320. {
  321. leave;
  322. }
  323. //
  324. // Acquire the activity lock now
  325. //
  326. SrAcquireActivityLockShared( pExtension );
  327. releaseLock = TRUE;
  328. //
  329. // Now that we've got the ActivityLock, make sure that the volume
  330. // hasn't been disabled.
  331. //
  332. if (!SR_LOGGING_ENABLED(pExtension))
  333. {
  334. leave;
  335. }
  336. //
  337. // now mark that we are handled this file. it's IMPORTANT that
  338. // we mark it PRIOR to handling the event, to prevent any potential
  339. // recursion issues with io related to handling this file+event.
  340. //
  341. if (EventType & SR_FULL_BACKUP_EVENT_TYPES)
  342. {
  343. //
  344. // if it's a full backup (or create) we don't care about
  345. // subsequent mods
  346. //
  347. Status = SrMarkFileBackedUp( pExtension,
  348. &pFileContext->FileName,
  349. pFileContext->StreamNameLength,
  350. EventType,
  351. SR_IGNORABLE_EVENT_TYPES );
  352. if (!NT_SUCCESS( Status ))
  353. leave;
  354. }
  355. else if (EventType & SR_ONLY_ONCE_EVENT_TYPES)
  356. {
  357. Status = SrMarkFileBackedUp( pExtension,
  358. &pFileContext->FileName,
  359. pFileContext->StreamNameLength,
  360. EventType,
  361. EventType );
  362. if (!NT_SUCCESS( Status ))
  363. leave;
  364. }
  365. //
  366. // should we short circuit out of here for testing mode?
  367. //
  368. if (global->DontBackup)
  369. leave;
  370. //
  371. // and now handle the event
  372. // a manual copy?
  373. //
  374. if ( FlagOn(EventType,SR_MANUAL_COPY_EVENTS) ||
  375. FlagOn(EventType,SrEventNoOptimization) )
  376. {
  377. ASSERT(!FlagOn(pFileContext->Flags,CTXFL_IsDirectory));
  378. //
  379. // copy the file, a change has occurred
  380. //
  381. Status = SrHandleFileChange( pExtension,
  382. EventType,
  383. pFileObject,
  384. &pFileContext->FileName );
  385. if (!NT_SUCCESS( Status ))
  386. leave;
  387. }
  388. //
  389. // we only handle clearing the FCB on delete's. do it now.
  390. //
  391. else if ((FlagOn(EventType,SrEventFileDelete) ||
  392. FlagOn(EventType,SrEventDirectoryDelete)) &&
  393. !FlagOn(EventType,SrEventSimulatedDelete))
  394. {
  395. ASSERT(!FlagOn( EventType, SrEventNoOptimization ));
  396. //
  397. // handle deletes...
  398. //
  399. Status = SrHandleDelete( pExtension,
  400. pFileObject,
  401. pFileContext );
  402. //
  403. // nothing to do if this fails. it already tried
  404. // to manually copy if it had to.
  405. //
  406. if (!NT_SUCCESS( Status ))
  407. leave;
  408. }
  409. else if (FlagOn(EventType,SrEventStreamOverwrite))
  410. {
  411. ASSERT(IS_VALID_OVERWRITE_INFO(pOverwriteInfo));
  412. //
  413. // handle overwrites
  414. //
  415. Status = SrHandleFileOverwrite( pExtension,
  416. pOverwriteInfo,
  417. pFileContext );
  418. if (!NT_SUCCESS( Status ))
  419. leave;
  420. //
  421. // this should really only fail if we can't open the file.
  422. // this means the caller can't also, so his create will fail
  423. // and we have no reason to copy anything.
  424. //
  425. // if it fails it cleans up after itself.
  426. //
  427. // otherwise SrCreateCompletion checks more error scenarios
  428. //
  429. }
  430. else
  431. {
  432. SR_EVENT_TYPE eventToLog;
  433. //
  434. // If we get to here, log the event
  435. //
  436. if (FlagOn( EventType, SrEventStreamCreate ))
  437. {
  438. eventToLog = SrEventFileCreate;
  439. }
  440. else
  441. {
  442. eventToLog = EventType;
  443. }
  444. Status = SrLogEvent( pExtension,
  445. eventToLog,
  446. pFileObject,
  447. &pFileContext->FileName,
  448. (FlagOn( EventType, SrEventStreamCreate ) ?
  449. pFileContext->StreamNameLength :
  450. 0 ),
  451. NULL,
  452. pFileName2,
  453. 0,
  454. NULL );
  455. if (!NT_SUCCESS( Status ))
  456. leave;
  457. }
  458. ASSERT(Status != STATUS_PENDING);
  459. } finally {
  460. //
  461. // check for unhandled exceptions
  462. //
  463. Status = FinallyUnwind(SrHandleEvent, Status);
  464. //
  465. // Check for any bad errors; If the pFileContext is NULL,
  466. // this error was encountered in SrGetContext which already
  467. // generated the volume error.
  468. //
  469. if (CHECK_FOR_VOLUME_ERROR(Status) && pFileContext != NULL)
  470. {
  471. NTSTATUS TempStatus;
  472. //
  473. // trigger the failure notification to the service
  474. //
  475. TempStatus = SrNotifyVolumeError( pExtension,
  476. &pFileContext->FileName,
  477. Status,
  478. EventType );
  479. CHECK_STATUS(TempStatus);
  480. }
  481. //
  482. // Cleanup state
  483. //
  484. if (releaseLock)
  485. {
  486. SrReleaseActivityLock( pExtension );
  487. }
  488. if (releaseContext && (NULL != pFileContext))
  489. {
  490. SrReleaseContext( pFileContext );
  491. NULLPTR(pFileContext);
  492. }
  493. }
  494. RETURN(Status);
  495. } // SrHandleEvent
  496. /***************************************************************************++
  497. Routine Description:
  498. This function packs a log entry and then logs it.
  499. Arguments:
  500. EventType - the event being handled
  501. pFileObject - the fileobject being handled
  502. pFileName - name of the file
  503. pTempName - name of the temp file if any
  504. pFileName2 - name of the dest file if any
  505. Return Value:
  506. NTSTATUS - Completion status.
  507. --***************************************************************************/
  508. NTSTATUS
  509. SrLogEvent(
  510. IN PSR_DEVICE_EXTENSION pExtension,
  511. IN SR_EVENT_TYPE EventType,
  512. IN PFILE_OBJECT pFileObject OPTIONAL,
  513. IN PUNICODE_STRING pFileName,
  514. IN USHORT FileNameStreamLength,
  515. IN PUNICODE_STRING pTempName OPTIONAL,
  516. IN PUNICODE_STRING pFileName2 OPTIONAL,
  517. IN USHORT FileName2StreamLength OPTIONAL,
  518. IN PUNICODE_STRING pShortName OPTIONAL
  519. )
  520. {
  521. NTSTATUS Status;
  522. PSR_LOG_ENTRY pLogEntry = NULL;
  523. PBYTE pDebugBlob = NULL;
  524. ULONG Attributes = 0xFFFFFFFF; // note:paulmcd: this needs
  525. // to be -1 as this
  526. // communicates something
  527. // special to the service
  528. // when logged
  529. ULONG SecurityDescriptorSize = 0;
  530. PSECURITY_DESCRIPTOR SecurityDescriptorPtr = NULL;
  531. WCHAR ShortFileNameBuffer[SR_SHORT_NAME_CHARS+1];
  532. UNICODE_STRING ShortFileName;
  533. PAGED_CODE();
  534. ASSERT(pFileName != NULL);
  535. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  536. VALIDATE_FILENAME( pFileName );
  537. //
  538. // A stream creation event should be translated to a file create by this
  539. // point.
  540. //
  541. ASSERT( !FlagOn( EventType, SrEventStreamCreate ) );
  542. try
  543. {
  544. Status = STATUS_SUCCESS;
  545. //
  546. // make sure we have the activity lock (we might not if we are
  547. // called from IsFileEligible or SrNotifyVolumeError,
  548. // you get the idea this function need to be callable from anywhere) .
  549. //
  550. SrAcquireActivityLockShared( pExtension );
  551. //
  552. // Verify we are still enabled
  553. //
  554. if (!SR_LOGGING_ENABLED(pExtension))
  555. leave;
  556. //
  557. // should we short circuit out of here for testing mode?
  558. //
  559. if (global->DontBackup)
  560. leave;
  561. //
  562. // mask out only the event code
  563. //
  564. EventType = EventType & SrEventLogMask ;
  565. if (pFileObject == NULL)
  566. goto log_it;
  567. //
  568. // For Attribute change/Directory delete operations, get the attributes.
  569. //
  570. if ( EventType & (SrEventAttribChange |
  571. SrEventDirectoryDelete|
  572. SrEventFileDelete |
  573. SrEventStreamOverwrite|
  574. SrEventStreamChange) )
  575. {
  576. FILE_BASIC_INFORMATION BasicInformation;
  577. ASSERT(IS_VALID_FILE_OBJECT(pFileObject));
  578. //
  579. // we need to get the file attributes
  580. //
  581. Status = SrQueryInformationFile( pExtension->pTargetDevice,
  582. pFileObject,
  583. &BasicInformation,
  584. sizeof( BasicInformation ),
  585. FileBasicInformation,
  586. NULL );
  587. if (!NT_SUCCESS( Status )) {
  588. leave;
  589. }
  590. Attributes = BasicInformation.FileAttributes;
  591. }
  592. if (EventType & (SrEventAclChange |
  593. SrEventDirectoryDelete|
  594. SrEventStreamOverwrite|
  595. SrEventStreamChange|
  596. SrEventFileDelete) )
  597. {
  598. Status = SrGetAclInformation( pFileObject,
  599. pExtension,
  600. &SecurityDescriptorPtr,
  601. &SecurityDescriptorSize );
  602. if (!NT_SUCCESS(Status)) {
  603. leave;
  604. }
  605. //
  606. // did we get any acl info ? if not and this was an aclchange
  607. // event it was triggered on fat and we need to ignore it
  608. //
  609. if (SecurityDescriptorPtr == NULL &&
  610. (EventType & SrEventAclChange))
  611. {
  612. //
  613. // ignore it
  614. //
  615. SrTrace( NOTIFY, ("sr!SrLogEvent: ignoring acl change on %wZ\n",
  616. pFileName ));
  617. leave;
  618. }
  619. }
  620. //
  621. // Should we get the short name now? Only need it if the name
  622. // is changing via rename or delete. When the name changes, we need
  623. // to save the old name. Sometimes the name is passed in, like in
  624. // the file delete case and the file is already gone when we log
  625. // it, so this function can't get the short name. If we are dealing
  626. // with a file that has a named stream, it can't have a shortname
  627. // so we don't need to check for one.
  628. //
  629. if ( (EventType & (SrEventFileRename |
  630. SrEventDirectoryRename|
  631. SrEventFileDelete |
  632. SrEventDirectoryDelete)) &&
  633. (pShortName == NULL) &&
  634. (FileNameStreamLength == 0))
  635. {
  636. RtlInitEmptyUnicodeString( &ShortFileName,
  637. ShortFileNameBuffer,
  638. sizeof(ShortFileNameBuffer) );
  639. Status = SrGetShortFileName( pExtension,
  640. pFileObject,
  641. &ShortFileName );
  642. if (STATUS_OBJECT_NAME_NOT_FOUND == Status)
  643. {
  644. //
  645. // This file doesn't have a short name, so just leave
  646. // pShortName equal to NULL.
  647. //
  648. Status = STATUS_SUCCESS;
  649. }
  650. else if (!NT_SUCCESS(Status))
  651. {
  652. //
  653. // We hit an unexpected error, so leave.
  654. //
  655. leave;
  656. }
  657. else
  658. {
  659. pShortName = &ShortFileName;
  660. }
  661. }
  662. log_it:
  663. //
  664. // we need to make sure our disk structures are good and logging
  665. // has been started.
  666. //
  667. Status = SrCheckVolume(pExtension, FALSE);
  668. if (!NT_SUCCESS(Status)) {
  669. leave;
  670. }
  671. //
  672. // Debug logging
  673. //
  674. SrTrace( LOG_EVENT, ("sr!SrLogEvent(%03X)%s: %.*ls [%wZ]\n",
  675. EventType,
  676. (FlagOn(EventType, SrEventFileDelete) && pFileObject == NULL) ? "[dummy]" : "",
  677. (pFileName->Length + FileNameStreamLength)/sizeof( WCHAR ),
  678. pFileName->Buffer ? pFileName->Buffer : L"",
  679. pShortName ));
  680. #if DBG
  681. if (EventType & (SrEventFileRename|SrEventDirectoryRename))
  682. {
  683. SrTrace( LOG_EVENT, (" to %.*ls\n",
  684. (pFileName2->Length + FileName2StreamLength)/sizeof(WCHAR),
  685. pFileName2->Buffer ? pFileName2->Buffer : L""));
  686. }
  687. #endif
  688. //
  689. // Log it
  690. //
  691. if (DebugFlagSet( ADD_DEBUG_INFO ))
  692. {
  693. //
  694. // Get the debug info only in Checked build
  695. //
  696. pDebugBlob = SR_ALLOCATE_POOL( PagedPool,
  697. SR_LOG_DEBUG_INFO_SIZE,
  698. SR_DEBUG_BLOB_TAG );
  699. if ( pDebugBlob )
  700. {
  701. SrPackDebugInfo( pDebugBlob, SR_LOG_DEBUG_INFO_SIZE );
  702. }
  703. }
  704. //
  705. // This routine will allocate a log entry of the appropriate size
  706. // and fill it with the necessary data. We are responsible for
  707. // freeing the pLogEntry when we are through with it.
  708. //
  709. Status = SrPackLogEntry( &pLogEntry,
  710. EventType,
  711. Attributes,
  712. 0,
  713. SecurityDescriptorPtr,
  714. SecurityDescriptorSize,
  715. pDebugBlob,
  716. pFileName,
  717. FileNameStreamLength,
  718. pTempName,
  719. pFileName2,
  720. FileName2StreamLength,
  721. pExtension,
  722. pShortName );
  723. if (!NT_SUCCESS( Status ))
  724. {
  725. leave;
  726. }
  727. //
  728. // Get the sequence number and log the entry
  729. //
  730. Status = SrGetNextSeqNumber(&pLogEntry->SequenceNum);
  731. if (!NT_SUCCESS( Status ))
  732. leave;
  733. //
  734. // and write the log entry
  735. //
  736. Status = SrLogWrite( pExtension,
  737. NULL,
  738. pLogEntry );
  739. if (!NT_SUCCESS(Status)) {
  740. leave;
  741. }
  742. }
  743. finally
  744. {
  745. Status = FinallyUnwind(SrLogEvent, Status);
  746. SrReleaseActivityLock( pExtension );
  747. if (pLogEntry)
  748. {
  749. SrFreeLogEntry( pLogEntry );
  750. pLogEntry = NULL;
  751. }
  752. if (SecurityDescriptorPtr)
  753. {
  754. SR_FREE_POOL( SecurityDescriptorPtr, SR_SECURITY_DATA_TAG );
  755. SecurityDescriptorPtr = NULL;
  756. }
  757. if ( pDebugBlob )
  758. {
  759. SR_FREE_POOL(pDebugBlob, SR_DEBUG_BLOB_TAG);
  760. pDebugBlob = NULL;
  761. }
  762. }
  763. RETURN(Status);
  764. }
  765. /***************************************************************************++
  766. Routine Description:
  767. this will perform delete functions prior to the fsd seeing
  768. the mj_cleanup we are in the middle of intercepting.
  769. this means either copyfile (if another handle is open) or renaming the
  770. file into our store and undeleting it.
  771. Arguments:
  772. pExtension - SR's device extension for this volume.
  773. pFileObject - the file that is being deleted. we temporarily
  774. undelete it.
  775. pFileContext - SR's context for this file.
  776. Return Value:
  777. NTSTATUS - Completion status. can return STATUS_PENDING.
  778. --***************************************************************************/
  779. NTSTATUS
  780. SrHandleDelete(
  781. IN PSR_DEVICE_EXTENSION pExtension,
  782. IN PFILE_OBJECT pFileObject,
  783. IN PSR_STREAM_CONTEXT pFileContext
  784. )
  785. {
  786. NTSTATUS Status;
  787. IO_STATUS_BLOCK IoStatusBlock;
  788. OBJECT_ATTRIBUTES ObjectAttributes;
  789. HANDLE NewFileHandle = NULL;
  790. PFILE_OBJECT pNewFileObject = NULL;
  791. BOOLEAN DeleteFile = FALSE;
  792. ULONG NumberOfLinks;
  793. # define OPEN_WITH_DELETE_PENDING_RETRY_COUNT 5
  794. INT openRetryCount;
  795. BOOLEAN IsDirectory;
  796. FILE_DISPOSITION_INFORMATION DeleteInfo;
  797. SRP_NAME_CONTROL OriginalFileName;
  798. PUNICODE_STRING pOriginalFileName;
  799. BOOLEAN cleanupNameCtrl = FALSE;
  800. PAGED_CODE();
  801. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  802. ASSERT(pFileContext != NULL);
  803. ASSERT(pFileContext->FileName.Length > 0);
  804. ASSERT(IS_VALID_FILE_OBJECT(pFileObject));
  805. ASSERT( ExIsResourceAcquiredShared( &pExtension->ActivityLock ) );
  806. IsDirectory = BooleanFlagOn(pFileContext->Flags,CTXFL_IsDirectory);
  807. try {
  808. if (!IsDirectory)
  809. {
  810. //
  811. // If this is not a directory, we need to get the original name that
  812. // the user used to open this file so that we properly maintain
  813. // the name tunneling that the system provides.
  814. //
  815. SrpInitNameControl( &OriginalFileName );
  816. cleanupNameCtrl = TRUE;
  817. Status = SrpGetFileName( pExtension,
  818. pFileObject,
  819. &OriginalFileName );
  820. if (!NT_SUCCESS( Status ))
  821. leave;
  822. //
  823. // We've got the name that the user originally opened the file
  824. // with. We don't want to do anything to normalize the name
  825. // because to ensure that we don't break name tunneling we want to
  826. // use the same name that the user used to do our rename into the
  827. // store. We have our normalized name for this file in the file
  828. // context and we will use that for all logging purposes.
  829. pOriginalFileName = &(OriginalFileName.Name);
  830. }
  831. else
  832. {
  833. pOriginalFileName = &(pFileContext->FileName);
  834. }
  835. RtlZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock));
  836. //
  837. // Setup now for the open we are doing
  838. //
  839. InitializeObjectAttributes( &ObjectAttributes,
  840. pOriginalFileName,
  841. OBJ_KERNEL_HANDLE,
  842. NULL,
  843. NULL );
  844. //
  845. // Someone might delete the file between the time we mark the file
  846. // undeleted and the time we open it. We will try a few times
  847. // before giving up.
  848. //
  849. for (openRetryCount=OPEN_WITH_DELETE_PENDING_RETRY_COUNT;;) {
  850. //
  851. // undelete the file so that i can create a new FILE_OBJECT for this
  852. // file. i need to create a new FILE_OBJECT in order to get a HANDLE.
  853. // i can't get a handle of off this file object as the handle count is 0,
  854. // we are processing this in CLEANUP.
  855. //
  856. DeleteInfo.DeleteFile = FALSE;
  857. Status = SrSetInformationFile( pExtension->pTargetDevice,
  858. pFileObject,
  859. &DeleteInfo,
  860. sizeof(DeleteInfo),
  861. FileDispositionInformation );
  862. if (!NT_SUCCESS( Status ))
  863. leave;
  864. //
  865. // make sure to "re" delete the file later
  866. //
  867. DeleteFile = TRUE;
  868. //
  869. // Open the file.
  870. //
  871. // This open and all operations on this handle will only be seen by
  872. // filters BELOW SR on the filter stack.
  873. //
  874. Status = SrIoCreateFile( &NewFileHandle,
  875. FILE_READ_ATTRIBUTES|SYNCHRONIZE,
  876. &ObjectAttributes,
  877. &IoStatusBlock,
  878. NULL,
  879. FILE_ATTRIBUTE_NORMAL,
  880. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  881. FILE_OPEN_IF, // OPEN_ALWAYS
  882. FILE_SYNCHRONOUS_IO_NONALERT
  883. | FILE_WRITE_THROUGH
  884. | (IsDirectory ? FILE_DIRECTORY_FILE : 0)
  885. | FILE_OPEN_FOR_BACKUP_INTENT,
  886. NULL,
  887. 0, // EaLength
  888. IO_IGNORE_SHARE_ACCESS_CHECK,
  889. pExtension->pTargetDevice );
  890. //
  891. // If we don't get STATUS_DELETE_PENDING just go on
  892. //
  893. if (STATUS_DELETE_PENDING != Status) {
  894. break;
  895. }
  896. //
  897. // If we get STATUS_DELETE_PENDING then someone did a
  898. // SetInformation to mark the file for delete between the time
  899. // we cleared the state and did the open. We are simply going to
  900. // try this again. After too many retries we will fail the
  901. // operation and return.
  902. //
  903. if (--openRetryCount <= 0) {
  904. SrTrace( NOTIFY, ("sr!SrHandleDelete: Tried %d times to open \"%wZ\", status is still STATUS_DELETE_PENDING, giving up\n",
  905. OPEN_WITH_DELETE_PENDING_RETRY_COUNT,
  906. &(pFileContext->FileName)));
  907. leave;
  908. }
  909. }
  910. //
  911. // If we get this error it means we found a reparse point on a file
  912. // and the filter that handles it is gone. We can not copy the file
  913. // so give that up. After pondering it was decided that we should
  914. // not stop logging so we will clear the error and return.
  915. //
  916. if (STATUS_IO_REPARSE_TAG_NOT_HANDLED == Status ||
  917. STATUS_REPARSE_POINT_NOT_RESOLVED == Status)
  918. {
  919. SrTrace( NOTIFY, ("sr!SrHandleDelete: Error %x ignored trying to open \"%wZ\" for copy\n",
  920. Status,
  921. &(pFileContext->FileName) ));
  922. Status = STATUS_SUCCESS;
  923. leave;
  924. }
  925. //
  926. // Any other error should quit
  927. //
  928. if (!NT_SUCCESS( Status ))
  929. leave;
  930. //
  931. // reference the file object
  932. //
  933. Status = ObReferenceObjectByHandle( NewFileHandle,
  934. 0,
  935. *IoFileObjectType,
  936. KernelMode,
  937. (PVOID *) &pNewFileObject,
  938. NULL );
  939. if (!NT_SUCCESS( Status ))
  940. leave;
  941. //
  942. // handle directory delete's
  943. //
  944. if (IsDirectory)
  945. {
  946. //
  947. // Log the event
  948. //
  949. Status = SrLogEvent ( pExtension,
  950. SrEventDirectoryDelete,
  951. pNewFileObject,
  952. &(pFileContext->FileName),
  953. pFileContext->StreamNameLength,
  954. NULL, // pTempName
  955. NULL, // pFileName2
  956. 0,
  957. NULL ); // pShortName
  958. if (!NT_SUCCESS( Status ))
  959. leave;
  960. //
  961. // all done
  962. //
  963. leave;
  964. }
  965. //
  966. // Check to make sure that this is not a delete of a stream. If
  967. // there is no stream name, we may be able to do our rename
  968. // optimization instead of doing a full backup.
  969. //
  970. if (pFileContext->StreamNameLength == 0)
  971. {
  972. //
  973. // how many links does this file have?
  974. //
  975. Status = SrGetNumberOfLinks( pExtension->pTargetDevice,
  976. pNewFileObject,
  977. &NumberOfLinks);
  978. if (!NT_SUCCESS( Status )) {
  979. leave;
  980. }
  981. if (NumberOfLinks <= 1) {
  982. //
  983. // Try to do the rename optimization here to just rename the
  984. // file about to be deleted into our store. If this fails, we will
  985. // try to just do a full backup of the file.
  986. //
  987. // If the rename succeeds, this will also log the action.
  988. //
  989. ASSERT( pOriginalFileName != NULL );
  990. Status = SrRenameFileIntoStore( pExtension,
  991. pNewFileObject,
  992. NewFileHandle,
  993. pOriginalFileName,
  994. &(pFileContext->FileName),
  995. SrEventFileDelete,
  996. NULL );
  997. if (NT_SUCCESS( Status )) {
  998. //
  999. // Mark this file context as uninteresting now that it is
  1000. // renamed into the store.
  1001. //
  1002. SrMakeContextUninteresting( pFileContext );
  1003. //
  1004. // The rename was successful, so we do not need to re-delete
  1005. // the file.
  1006. //
  1007. DeleteFile = FALSE;
  1008. leave;
  1009. }
  1010. }
  1011. }
  1012. //
  1013. // We either couldn't do the rename optimization (because this is a
  1014. // stream delete or the file has hardlinks) or the rename optimization
  1015. // failed, so just do a full copy of the file as if a change happened.
  1016. // Do this AFTER we undelete the file so that the NtCreateFile will
  1017. // work in SrBackupFile. We will re-delete the file when we are
  1018. // finished.
  1019. //
  1020. Status = SrHandleFileChange( pExtension,
  1021. SrEventFileDelete,
  1022. pNewFileObject,
  1023. &(pFileContext->FileName) );
  1024. if (Status == STATUS_FILE_IS_A_DIRECTORY)
  1025. {
  1026. //
  1027. // This is a change to a stream on a directory. For now these
  1028. // operations are not supported, so we will just ignore this
  1029. // operation.
  1030. //
  1031. Status = STATUS_SUCCESS;
  1032. }
  1033. CHECK_STATUS( Status );
  1034. } finally {
  1035. //
  1036. // check for unhandled exceptions
  1037. //
  1038. Status = FinallyUnwind(SrHandleDelete, Status);
  1039. if (DeleteFile)
  1040. {
  1041. NTSTATUS TempStatus;
  1042. //
  1043. // "re" delete the file again, we are all done
  1044. //
  1045. DeleteInfo.DeleteFile = TRUE;
  1046. TempStatus = SrSetInformationFile( pExtension->pTargetDevice,
  1047. pFileObject,
  1048. &DeleteInfo,
  1049. sizeof(DeleteInfo),
  1050. FileDispositionInformation );
  1051. //
  1052. // bug#173339: ntfs apparently will not let you delete an already
  1053. // deleted file. this file could have been deleted again while
  1054. // we were in the middle of processing as we are aborting here
  1055. // due to multiple opens. attempt to undelete it and delete it
  1056. // to prove that this is the case.
  1057. //
  1058. if (TempStatus == STATUS_CANNOT_DELETE ||
  1059. TempStatus == STATUS_DIRECTORY_NOT_EMPTY)
  1060. {
  1061. TempStatus = STATUS_SUCCESS;
  1062. }
  1063. CHECK_STATUS(TempStatus);
  1064. }
  1065. if (pNewFileObject != NULL)
  1066. {
  1067. ObDereferenceObject(pNewFileObject);
  1068. }
  1069. if (NewFileHandle != NULL)
  1070. {
  1071. ZwClose(NewFileHandle);
  1072. }
  1073. if (cleanupNameCtrl)
  1074. {
  1075. SrpCleanupNameControl( &OriginalFileName );
  1076. }
  1077. }
  1078. RETURN(Status);
  1079. } // SrHandleDelete
  1080. /***************************************************************************++
  1081. Routine Description:
  1082. this will create a fresh restore location and current restore point.
  1083. it queue's off to the EX work queue to make sure that we are running in
  1084. the system token context so that we can access protected directories.
  1085. Arguments:
  1086. pNtVolumeName - the nt name of the volume
  1087. Return Value:
  1088. NTSTATUS - Completion status.
  1089. --***************************************************************************/
  1090. NTSTATUS
  1091. SrCreateRestoreLocation(
  1092. IN PSR_DEVICE_EXTENSION pExtension
  1093. )
  1094. {
  1095. NTSTATUS Status;
  1096. PSR_WORK_ITEM pWorkItem = NULL;
  1097. PACCESS_TOKEN pSystemToken = NULL;
  1098. PACCESS_TOKEN pSavedThreadToken = NULL;
  1099. BOOLEAN SavedCopyOnOpen;
  1100. BOOLEAN SavedEffectiveOnly;
  1101. SECURITY_IMPERSONATION_LEVEL SavedLevel;
  1102. PAGED_CODE();
  1103. ASSERT( IS_VALID_SR_DEVICE_EXTENSION( pExtension ) );
  1104. ASSERT(IS_ACTIVITY_LOCK_ACQUIRED_EXCLUSIVE( pExtension ) ||
  1105. IS_LOG_LOCK_ACQUIRED_EXCLUSIVE( pExtension ));
  1106. try {
  1107. //
  1108. // we need to create a new restore location
  1109. //
  1110. pWorkItem = SR_ALLOCATE_STRUCT( NonPagedPool,
  1111. SR_WORK_ITEM,
  1112. SR_WORK_ITEM_TAG );
  1113. if (pWorkItem == NULL)
  1114. {
  1115. Status = STATUS_INSUFFICIENT_RESOURCES;
  1116. leave;
  1117. }
  1118. RtlZeroMemory(pWorkItem, sizeof(SR_WORK_ITEM));
  1119. pWorkItem->Signature = SR_WORK_ITEM_TAG;
  1120. KeInitializeEvent(&pWorkItem->Event, SynchronizationEvent, FALSE);
  1121. pWorkItem->Parameter1 = pExtension;
  1122. //
  1123. // queue this off to another thread so that our thread token is
  1124. // NT AUTHORITY\SYSTEM . this way we can access the system volume info
  1125. // folder .
  1126. //
  1127. #ifdef USE_QUEUE
  1128. ExInitializeWorkItem( &pWorkItem->WorkItem,
  1129. &SrCreateRestoreLocationWorker,
  1130. pWorkItem );
  1131. ExQueueWorkItem( &pWorkItem->WorkItem,
  1132. DelayedWorkQueue );
  1133. //
  1134. // wait for it to finish
  1135. //
  1136. Status = KeWaitForSingleObject( &pWorkItem->Event,
  1137. Executive,
  1138. KernelMode,
  1139. FALSE,
  1140. NULL );
  1141. ASSERT(NT_SUCCESS(Status));
  1142. #else
  1143. //
  1144. // get the system token off of the system process
  1145. //
  1146. pSystemToken = PsReferencePrimaryToken(global->pSystemProcess);
  1147. if (pSystemToken == NULL)
  1148. {
  1149. Status = STATUS_NO_TOKEN;
  1150. leave;
  1151. }
  1152. //
  1153. // get this current thread's token (if any)
  1154. //
  1155. pSavedThreadToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
  1156. &SavedCopyOnOpen,
  1157. &SavedEffectiveOnly,
  1158. &SavedLevel );
  1159. //
  1160. // OK if (pSavedThreadToken == NULL)
  1161. //
  1162. //
  1163. // impersonate the system token on this thread
  1164. //
  1165. Status = PsImpersonateClient( PsGetCurrentThread(),
  1166. pSystemToken,
  1167. TRUE, // CopyOnOpen
  1168. TRUE, // EffectiveOnly
  1169. SecurityImpersonation );
  1170. if (!NT_SUCCESS( Status ))
  1171. leave;
  1172. (VOID)SrCreateRestoreLocationWorker(pWorkItem);
  1173. //
  1174. // now revert the impersonation back
  1175. //
  1176. Status = PsImpersonateClient( PsGetCurrentThread(),
  1177. pSavedThreadToken, // OK if NULL
  1178. SavedCopyOnOpen,
  1179. SavedEffectiveOnly,
  1180. SavedLevel );
  1181. if (!NT_SUCCESS( Status ))
  1182. leave;
  1183. #endif // USE_QUEUE
  1184. //
  1185. // get the status code
  1186. //
  1187. Status = pWorkItem->Status;
  1188. if (!NT_SUCCESS( Status ))
  1189. leave;
  1190. } finally {
  1191. Status = FinallyUnwind(SrCreateRestoreLocation, Status);
  1192. if (pWorkItem != NULL)
  1193. {
  1194. SR_FREE_POOL_WITH_SIG(pWorkItem, SR_WORK_ITEM_TAG);
  1195. }
  1196. if (pSavedThreadToken != NULL)
  1197. {
  1198. PsDereferencePrimaryToken(pSavedThreadToken);
  1199. pSavedThreadToken = NULL;
  1200. }
  1201. if (pSystemToken != NULL)
  1202. {
  1203. ObDereferenceObject(pSystemToken);
  1204. pSystemToken = NULL;
  1205. }
  1206. }
  1207. RETURN(Status);
  1208. } // SrCreateRestoreLocation
  1209. /***************************************************************************++
  1210. Routine Description:
  1211. this will create a fresh restore location and current restore point.
  1212. this is run off the EX work queue to make sure that we are running in
  1213. the system token context so that we can access protected directories.
  1214. Arguments:
  1215. pContext - the context (Parameter 1 is the nt name of the volume)
  1216. --***************************************************************************/
  1217. VOID
  1218. SrCreateRestoreLocationWorker(
  1219. IN PSR_WORK_ITEM pWorkItem
  1220. )
  1221. {
  1222. NTSTATUS Status;
  1223. HANDLE Handle = NULL;
  1224. ULONG CharCount;
  1225. PUNICODE_STRING pDirectoryName = NULL;
  1226. IO_STATUS_BLOCK IoStatusBlock;
  1227. OBJECT_ATTRIBUTES ObjectAttributes;
  1228. PSR_DEVICE_EXTENSION pExtension;
  1229. PUNICODE_STRING pVolumeName;
  1230. BOOLEAN DirectoryCreated;
  1231. struct {
  1232. FILE_FS_ATTRIBUTE_INFORMATION Info;
  1233. WCHAR Buffer[ 50 ];
  1234. } FileFsAttrInfoBuffer;
  1235. ASSERT(IS_VALID_WORK_ITEM(pWorkItem));
  1236. PAGED_CODE();
  1237. pExtension = (PSR_DEVICE_EXTENSION) pWorkItem->Parameter1;
  1238. ASSERT( IS_VALID_SR_DEVICE_EXTENSION( pExtension ) );
  1239. pVolumeName = pExtension->pNtVolumeName;
  1240. ASSERT(pVolumeName != NULL);
  1241. RtlZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock));
  1242. //
  1243. // grab a filename buffer
  1244. //
  1245. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, &pDirectoryName);
  1246. if (!NT_SUCCESS( Status )) {
  1247. goto SrCreateRestoreLocationWorker_Cleanup;
  1248. }
  1249. //
  1250. // first make sure the system volume info directory is there
  1251. //
  1252. CharCount = swprintf( pDirectoryName->Buffer,
  1253. VOLUME_FORMAT SYSTEM_VOLUME_INFORMATION,
  1254. pVolumeName );
  1255. pDirectoryName->Length = (USHORT)CharCount * sizeof(WCHAR);
  1256. InitializeObjectAttributes( &ObjectAttributes,
  1257. pDirectoryName,
  1258. OBJ_KERNEL_HANDLE,
  1259. NULL,
  1260. NULL );
  1261. Status = SrIoCreateFile( &Handle,
  1262. FILE_LIST_DIRECTORY
  1263. |WRITE_OWNER|WRITE_DAC|SYNCHRONIZE,
  1264. &ObjectAttributes,
  1265. &IoStatusBlock,
  1266. NULL,
  1267. FILE_ATTRIBUTE_NORMAL
  1268. | FILE_ATTRIBUTE_HIDDEN
  1269. | FILE_ATTRIBUTE_SYSTEM,
  1270. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  1271. FILE_OPEN_IF, // OPEN_ALWAYS
  1272. FILE_DIRECTORY_FILE
  1273. | FILE_WRITE_THROUGH
  1274. | FILE_SYNCHRONOUS_IO_NONALERT
  1275. | FILE_OPEN_FOR_BACKUP_INTENT,
  1276. NULL,
  1277. 0, // EaLength
  1278. 0,
  1279. pExtension->pTargetDevice );
  1280. if (!NT_SUCCESS( Status )) {
  1281. goto SrCreateRestoreLocationWorker_Cleanup;
  1282. }
  1283. DirectoryCreated = (IoStatusBlock.Information != FILE_OPENED);
  1284. //
  1285. // find out if this volume supports acl's or compression
  1286. //
  1287. Status = ZwQueryVolumeInformationFile( Handle,
  1288. &IoStatusBlock,
  1289. &FileFsAttrInfoBuffer.Info,
  1290. sizeof(FileFsAttrInfoBuffer),
  1291. FileFsAttributeInformation );
  1292. if (!NT_SUCCESS( Status )) {
  1293. goto SrCreateRestoreLocationWorker_Cleanup;
  1294. }
  1295. //
  1296. // if we created it, we should put the acl on it
  1297. //
  1298. if ( DirectoryCreated &&
  1299. (FileFsAttrInfoBuffer.Info.FileSystemAttributes & FILE_PERSISTENT_ACLS))
  1300. {
  1301. SrTrace(NOTIFY, ("sr!srCreateRestoreLocation: setting ACL on sysvolinfo\n"));
  1302. //
  1303. // put the local system dacl on the folder (not so bad if it fails)
  1304. //
  1305. Status = SrSetFileSecurity(Handle, TRUE, TRUE);
  1306. CHECK_STATUS(Status);
  1307. }
  1308. //
  1309. // all done (just needed to create it)
  1310. //
  1311. ZwClose(Handle);
  1312. Handle = NULL;
  1313. //
  1314. // and now create our _restore directory
  1315. //
  1316. CharCount = swprintf( pDirectoryName->Buffer,
  1317. VOLUME_FORMAT RESTORE_LOCATION,
  1318. pVolumeName,
  1319. global->MachineGuid );
  1320. pDirectoryName->Length = (USHORT)CharCount * sizeof(WCHAR);
  1321. InitializeObjectAttributes( &ObjectAttributes,
  1322. pDirectoryName,
  1323. OBJ_KERNEL_HANDLE,
  1324. NULL,
  1325. NULL );
  1326. Status = SrIoCreateFile( &Handle,
  1327. FILE_LIST_DIRECTORY
  1328. |WRITE_OWNER|WRITE_DAC|SYNCHRONIZE,
  1329. &ObjectAttributes,
  1330. &IoStatusBlock,
  1331. NULL,
  1332. FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
  1333. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  1334. FILE_OPEN_IF, // OPEN_ALWAYS
  1335. FILE_DIRECTORY_FILE
  1336. | FILE_SYNCHRONOUS_IO_NONALERT
  1337. | FILE_WRITE_THROUGH
  1338. | FILE_OPEN_FOR_BACKUP_INTENT,
  1339. NULL,
  1340. 0, // EaLength
  1341. 0,
  1342. pExtension->pTargetDevice );
  1343. if (!NT_SUCCESS( Status )) {
  1344. goto SrCreateRestoreLocationWorker_Cleanup;
  1345. }
  1346. //
  1347. // if we created it, we should put the acl on it
  1348. //
  1349. if (IoStatusBlock.Information != FILE_OPENED)
  1350. {
  1351. USHORT CompressionState;
  1352. if (FileFsAttrInfoBuffer.Info.FileSystemAttributes & FILE_PERSISTENT_ACLS)
  1353. {
  1354. SrTrace(NOTIFY, ("sr!srCreateRestoreLocation: setting ACL on _restore{}\n"));
  1355. //
  1356. // put the everyone dacl on the folder (not so bad if it fails)
  1357. //
  1358. Status = SrSetFileSecurity(Handle, FALSE, TRUE);
  1359. CHECK_STATUS(Status);
  1360. }
  1361. if (FileFsAttrInfoBuffer.Info.FileSystemAttributes & FILE_FILE_COMPRESSION)
  1362. {
  1363. //
  1364. // Ensure that this folder is NOT marked for compression.
  1365. // This inherits down to files created later in this folder. This
  1366. // should speed up our writes for copies and decrease the chance
  1367. // of stack overflow while we are doing our backup operations.
  1368. //
  1369. // The service will come along and compress the file in the
  1370. // directory at a later time.
  1371. //
  1372. CompressionState = COMPRESSION_FORMAT_NONE;
  1373. Status = ZwFsControlFile( Handle,
  1374. NULL, // Event
  1375. NULL, // ApcRoutine
  1376. NULL, // ApcContext
  1377. &IoStatusBlock,
  1378. FSCTL_SET_COMPRESSION,
  1379. &CompressionState,
  1380. sizeof(CompressionState),
  1381. NULL, // OutputBuffer
  1382. 0 );
  1383. ASSERT(Status != STATUS_PENDING);
  1384. CHECK_STATUS(Status);
  1385. }
  1386. }
  1387. //
  1388. // all done (just needed to create it)
  1389. //
  1390. ZwClose(Handle);
  1391. Handle = NULL;
  1392. //
  1393. // now we need to create our current restore point sub directory
  1394. //
  1395. //
  1396. // We don't need to acquire a lock to read the current restore location
  1397. // because whoever scheduled this workitem already has the ActivityLock
  1398. // and will not release it until we return. This will prevent the
  1399. // value from changing.
  1400. //
  1401. CharCount = swprintf( &pDirectoryName->Buffer[pDirectoryName->Length/sizeof(WCHAR)],
  1402. L"\\" RESTORE_POINT_PREFIX L"%d",
  1403. global->FileConfig.CurrentRestoreNumber );
  1404. pDirectoryName->Length += (USHORT)CharCount * sizeof(WCHAR);
  1405. InitializeObjectAttributes( &ObjectAttributes,
  1406. pDirectoryName,
  1407. OBJ_KERNEL_HANDLE,
  1408. NULL,
  1409. NULL );
  1410. Status = SrIoCreateFile( &Handle,
  1411. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  1412. &ObjectAttributes,
  1413. &IoStatusBlock,
  1414. NULL,
  1415. FILE_ATTRIBUTE_NORMAL,
  1416. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  1417. FILE_OPEN_IF, // OPEN_ALWAYS
  1418. FILE_DIRECTORY_FILE
  1419. | FILE_WRITE_THROUGH
  1420. | FILE_SYNCHRONOUS_IO_NONALERT
  1421. | FILE_OPEN_FOR_BACKUP_INTENT,
  1422. NULL,
  1423. 0, // EaLength
  1424. 0,
  1425. pExtension->pTargetDevice );
  1426. if (!NT_SUCCESS( Status )) {
  1427. goto SrCreateRestoreLocationWorker_Cleanup;
  1428. }
  1429. //
  1430. // all done (just needed to create it) no acl's on this subfolder,
  1431. // it inherit from the parent (everyone=full control)
  1432. //
  1433. ZwClose(Handle);
  1434. Handle = NULL;
  1435. SrTrace( NOTIFY, ("SR!SrCreateRestoreLocationWorker(%wZ)\n",
  1436. pVolumeName ));
  1437. SrCreateRestoreLocationWorker_Cleanup:
  1438. if (Handle != NULL)
  1439. {
  1440. ZwClose(Handle);
  1441. Handle = NULL;
  1442. }
  1443. if (pDirectoryName != NULL)
  1444. {
  1445. SrFreeFileNameBuffer(pDirectoryName);
  1446. pDirectoryName = NULL;
  1447. }
  1448. pWorkItem->Status = Status;
  1449. KeSetEvent(&pWorkItem->Event, 0, FALSE);
  1450. } // SrCreateRestoreLocationWorker
  1451. /***************************************************************************++
  1452. Routine Description:
  1453. this handles any change event to the file that requires the file to be
  1454. copied. it generates the dest file name then copies the source file to
  1455. the dest file.
  1456. Arguments:
  1457. EventType - the event that occurred
  1458. pFileObject - the file object that just changed
  1459. pFileName - the name of the file that changed
  1460. Return Value:
  1461. NTSTATUS - Completion status.
  1462. --***************************************************************************/
  1463. NTSTATUS
  1464. SrHandleFileChange(
  1465. IN PSR_DEVICE_EXTENSION pExtension,
  1466. IN SR_EVENT_TYPE EventType,
  1467. IN PFILE_OBJECT pFileObject,
  1468. IN PUNICODE_STRING pFileName
  1469. )
  1470. {
  1471. NTSTATUS Status;
  1472. PUNICODE_STRING pDestFileName = NULL;
  1473. PAGED_CODE();
  1474. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  1475. ASSERT(IS_VALID_FILE_OBJECT(pFileObject));
  1476. ASSERT(pFileName != NULL);
  1477. ASSERT( ExIsResourceAcquiredShared( &pExtension->ActivityLock ) );
  1478. //
  1479. // we need to make sure our disk structures are good and logging
  1480. // has been started.
  1481. //
  1482. Status = SrCheckVolume(pExtension, FALSE);
  1483. if (!NT_SUCCESS( Status ))
  1484. goto end;
  1485. //
  1486. // get the name of the destination file for this guy
  1487. //
  1488. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, &pDestFileName);
  1489. if (!NT_SUCCESS( Status ))
  1490. goto end;
  1491. Status = SrGetDestFileName( pExtension,
  1492. pFileName,
  1493. pDestFileName );
  1494. if (!NT_SUCCESS_NO_DBGBREAK( Status ))
  1495. goto end;
  1496. Status = SrBackupFileAndLog( pExtension,
  1497. EventType,
  1498. pFileObject,
  1499. pFileName,
  1500. pDestFileName,
  1501. TRUE );
  1502. if (!NT_SUCCESS_NO_DBGBREAK( Status ))
  1503. goto end;
  1504. end:
  1505. if (pDestFileName != NULL)
  1506. {
  1507. SrFreeFileNameBuffer(pDestFileName);
  1508. pDestFileName = NULL;
  1509. }
  1510. #if DBG
  1511. //
  1512. // When dealing with modifications to streams on directories, this
  1513. // is a valid error code to return.
  1514. //
  1515. if (Status == STATUS_FILE_IS_A_DIRECTORY)
  1516. {
  1517. return Status;
  1518. }
  1519. #endif
  1520. RETURN(Status);
  1521. } // SrHandleFileChange
  1522. /***************************************************************************++
  1523. Routine Description:
  1524. this will perform the optimization for overwrites. this consists of a
  1525. rename and empty file create so that the caller will be allowed to
  1526. overwrite like normal.
  1527. // NOTE: MollyBro 7-Dec-2000
  1528. //
  1529. // We cannot use the RENAME optimization here because we create
  1530. // the following window --
  1531. // Between the time we rename the file into our store and the
  1532. // time we create the stub file to take its place, there is no
  1533. // file by this name in the directory. Another request
  1534. // could come in and try to create this same file with the
  1535. // FILE_CREATE flag set. This operation would then succeed
  1536. // when it would have failed had SR not been doing its work.
  1537. //
  1538. // This is likely to break apps in hard-to-repeat ways, so just to
  1539. // be safe, we will do a full backup here.
  1540. //
  1541. Arguments:
  1542. pFileObject - the file object that just changed
  1543. pFileName - the name of the file
  1544. Return Value:
  1545. NTSTATUS - Completion status.
  1546. see comments above.
  1547. --***************************************************************************/
  1548. NTSTATUS
  1549. SrHandleFileOverwrite(
  1550. IN PSR_DEVICE_EXTENSION pExtension,
  1551. IN OUT PSR_OVERWRITE_INFO pOverwriteInfo,
  1552. IN PSR_STREAM_CONTEXT pFileContext
  1553. )
  1554. {
  1555. NTSTATUS Status;
  1556. PIO_STACK_LOCATION pIrpSp;
  1557. OBJECT_ATTRIBUTES ObjectAttributes;
  1558. HANDLE FileHandle = NULL;
  1559. PFILE_OBJECT pFileObject = NULL;
  1560. IO_STATUS_BLOCK IoStatusBlock;
  1561. ULONG DesiredAccess;
  1562. ULONG DesiredAttributes;
  1563. ULONG CreateOptions;
  1564. BOOLEAN SharingViolation = FALSE;
  1565. BOOLEAN MarkFile = FALSE;
  1566. BOOLEAN MountInPath = FALSE;
  1567. PUNICODE_STRING pTempFileName = NULL;
  1568. HANDLE TempFileHandle = NULL;
  1569. PUNICODE_STRING pFileName;
  1570. #if 0 /* NO_RENAME --- See note in function header block */
  1571. BOOLEAN RenamedFile = FALSE;
  1572. PFILE_RENAME_INFORMATION pRenameInformation = NULL;
  1573. #endif
  1574. PAGED_CODE();
  1575. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  1576. ASSERT(IS_VALID_OVERWRITE_INFO(pOverwriteInfo));
  1577. ASSERT(IS_VALID_IRP(pOverwriteInfo->pIrp));
  1578. ASSERT(pFileContext != NULL);
  1579. pFileName = &(pFileContext->FileName);
  1580. ASSERT( ExIsResourceAcquiredShared( &pExtension->ActivityLock ) );
  1581. try {
  1582. pIrpSp = IoGetCurrentIrpStackLocation(pOverwriteInfo->pIrp);
  1583. //
  1584. // we are now all done with the inputs, clear the outputs
  1585. //
  1586. RtlZeroMemory(pOverwriteInfo, sizeof(*pOverwriteInfo));
  1587. pOverwriteInfo->Signature = SR_OVERWRITE_INFO_TAG;
  1588. Status = STATUS_SUCCESS;
  1589. //
  1590. // we need to use a combination of the caller's requested desired
  1591. // access and the minimum required desired access to overwite a file.
  1592. //
  1593. // this way we gaurantee that if this NtCreateFile works, than the
  1594. // callers MJ_CREATE would also work. we absolutely need to avoid any
  1595. // possibilty of the driver's NtCreateFile working in a scenario that
  1596. // the user-mode MJ_CREATE will subsequently fail. if that were to
  1597. // happen, we would have overwritten the file when normally it would
  1598. // have failed, thus changing the behaviour of the os. very bad.
  1599. //
  1600. //
  1601. // start with the callers access requested
  1602. //
  1603. if (pIrpSp->Parameters.Create.SecurityContext == NULL)
  1604. {
  1605. pOverwriteInfo->IgnoredFile = TRUE;
  1606. Status = STATUS_SUCCESS;
  1607. leave;
  1608. }
  1609. DesiredAccess = pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
  1610. //
  1611. // now add on FILE_GENERIC_WRITE .
  1612. //
  1613. // FILE_GENERIC_WRITE is the least amount of access you must be able to
  1614. // get to overwrite a file. you don't have to ask for it, but you
  1615. // must have it. that is.. you can ask for READ access with overwrite
  1616. // specified, and the file will be overwritten, only if you had
  1617. // FILE_GENERIC_WRITE in addition to the read access
  1618. //
  1619. DesiredAccess |= FILE_GENERIC_WRITE;
  1620. //
  1621. // BUGBUG: the check for matching attributes only happens if OVERWRITE is
  1622. // set. we might need to manually check this . paulmcd 5/3/2000
  1623. //
  1624. DesiredAttributes = pIrpSp->Parameters.Create.FileAttributes;
  1625. //
  1626. // pass them back so that create can fix it if it fails really bad
  1627. //
  1628. pOverwriteInfo->CreateFileAttributes = DesiredAttributes;
  1629. //
  1630. // first open the file to see if there is one there
  1631. //
  1632. InitializeObjectAttributes( &ObjectAttributes,
  1633. pFileName,
  1634. OBJ_KERNEL_HANDLE // don't let usermode trash myhandle
  1635. |OBJ_FORCE_ACCESS_CHECK, // force ACL checking
  1636. NULL, // Root Directory
  1637. NULL );
  1638. //
  1639. // Setup the CreateOptions. Always use FILE_SYNCHRONOUS_IO_NONALERT,
  1640. // but propagate FILE_OPEN_FOR_BACKUP_INTENT if that is set in the
  1641. // FullCreateOptions.
  1642. //
  1643. CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_WRITE_THROUGH;
  1644. if (FlagOn( pIrpSp->Parameters.Create.SecurityContext->FullCreateOptions,
  1645. FILE_OPEN_FOR_BACKUP_INTENT )) {
  1646. SetFlag( CreateOptions, FILE_OPEN_FOR_BACKUP_INTENT );
  1647. }
  1648. #if 0 /* NO_RENAME --- See note in function header block */
  1649. //
  1650. // notice the ShareAccess is set to 0. we want this file exclusive.
  1651. // if there are any other opens.. this optimization will fail and
  1652. // we'll copy the file manually.
  1653. //
  1654. //
  1655. // BUGBUG: paulmcd 5/31 . what if this is an EFS file being OpenRaw'd
  1656. // it doesn't require FILE_GENERIC_WRITE .
  1657. //
  1658. Status = ZwCreateFile( &FileHandle,
  1659. DesiredAccess,
  1660. &ObjectAttributes,
  1661. &IoStatusBlock,
  1662. NULL, // AllocationSize
  1663. DesiredAttributes,
  1664. 0, // ShareAccess
  1665. FILE_OPEN, // OPEN_EXISTING
  1666. CreateOptions,
  1667. NULL,
  1668. 0 ); // EaLength
  1669. if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  1670. {
  1671. //
  1672. // this is ok.. the file that is being overwritten (at least
  1673. // CREATE_ALWAYS) doesn't exist. nothing to backup.
  1674. //
  1675. //
  1676. // we log this in SrCreateCompletion so that we know the create
  1677. // worked first
  1678. //
  1679. Status = STATUS_SUCCESS;
  1680. leave;
  1681. }
  1682. else if (Status == STATUS_SHARING_VIOLATION)
  1683. {
  1684. SharingViolation = TRUE;
  1685. Status = STATUS_SUCCESS;
  1686. }
  1687. else if (Status == STATUS_OBJECT_NAME_INVALID ||
  1688. Status == STATUS_OBJECT_PATH_INVALID ||
  1689. Status == STATUS_OBJECT_PATH_NOT_FOUND )
  1690. {
  1691. //
  1692. // the file is not a valid filename. no overwrite will happen.
  1693. //
  1694. pOverwriteInfo->IgnoredFile = TRUE;
  1695. Status = STATUS_SUCCESS;
  1696. leave;
  1697. }
  1698. else if (NT_SUCCESS_NO_DBGBREAK(Status) == FALSE)
  1699. {
  1700. //
  1701. // we failed opening it. this means the caller will fail opening it
  1702. // that's ok.
  1703. //
  1704. pOverwriteInfo->IgnoredFile = TRUE;
  1705. Status = STATUS_SUCCESS;
  1706. leave;
  1707. }
  1708. #endif /* NO_RENAME */
  1709. //
  1710. // at this point it's not a NEW file create that is going to work,
  1711. // double check that we should actually be interested in the MODIFY
  1712. // of this file
  1713. //
  1714. {
  1715. BOOLEAN HasFileBeenBackedUp;
  1716. HasFileBeenBackedUp = SrHasFileBeenBackedUp( pExtension,
  1717. pFileName,
  1718. pFileContext->StreamNameLength,
  1719. SrEventStreamChange );
  1720. if (HasFileBeenBackedUp)
  1721. {
  1722. //
  1723. // we don't care . skip it
  1724. //
  1725. Status = STATUS_SUCCESS;
  1726. leave;
  1727. }
  1728. }
  1729. #if 0 /* NO_RENAME */
  1730. //
  1731. // otherwise resume processing
  1732. //
  1733. if (SharingViolation)
  1734. {
  1735. //
  1736. // copy the file manually, we got a sharing violation, someone else
  1737. // has this file open. try to open it again allowing for sharing.
  1738. //
  1739. #endif
  1740. //
  1741. // Note: In this path, if the operation will be successful, the name
  1742. // we have should be a file. It is possible to get a directory down
  1743. // this path if the directory name could be an interesting file name
  1744. // (like c:\test.exe\) and the user has opened the directory for
  1745. // OVERWRITE, OVERWRITE_IF, or SUPERCEDE. The user's open will fail,
  1746. // so we just want to catch this problem as soon as possible by adding
  1747. // the FILE_NON_DIRECTORY_FILE CreateOption to avoid doing
  1748. // unnecessary work.
  1749. //
  1750. Status = SrIoCreateFile( &FileHandle,
  1751. DesiredAccess,
  1752. &ObjectAttributes,
  1753. &IoStatusBlock,
  1754. NULL, // AllocationSize
  1755. DesiredAttributes,
  1756. pIrpSp->Parameters.Create.ShareAccess,// ShareAccess
  1757. FILE_OPEN, // OPEN_EXISTING
  1758. CreateOptions | FILE_NON_DIRECTORY_FILE,
  1759. NULL,
  1760. 0, // EaLength
  1761. 0,
  1762. pExtension->pTargetDevice );
  1763. // NO_RENAME
  1764. // NOTE: We have to add some more error handling here since we
  1765. // are not doing the ZwCreateFile above.
  1766. //
  1767. if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  1768. {
  1769. //
  1770. // this is ok.. the file that is being overwritten (at least
  1771. // CREATE_ALWAYS) doesn't exist. nothing to backup.
  1772. //
  1773. //
  1774. // we log this in SrCreateCompletion so that we know the create
  1775. // worked first
  1776. //
  1777. Status = STATUS_SUCCESS;
  1778. leave;
  1779. }
  1780. else if (Status == STATUS_SHARING_VIOLATION)
  1781. {
  1782. //
  1783. // Caller can't open this file either, so don't worry about
  1784. // this file.
  1785. //
  1786. pOverwriteInfo->IgnoredFile = TRUE;
  1787. Status = STATUS_SUCCESS;
  1788. leave;
  1789. #if 0 /* NO_RENAME */
  1790. SharingViolation = TRUE;
  1791. Status = STATUS_SUCCESS;
  1792. #endif /* NO_RENAME */
  1793. }
  1794. #if 0 /* NO_RENAME */
  1795. else if (Status == STATUS_OBJECT_NAME_INVALID ||
  1796. Status == STATUS_OBJECT_PATH_INVALID ||
  1797. Status == STATUS_OBJECT_PATH_NOT_FOUND )
  1798. {
  1799. //
  1800. // the file is not a valid filename. no overwrite will happen.
  1801. //
  1802. pOverwriteInfo->IgnoredFile = TRUE;
  1803. Status = STATUS_SUCCESS;
  1804. leave;
  1805. }
  1806. #endif /* NO_RENAME */
  1807. else if (!NT_SUCCESS_NO_DBGBREAK(Status))
  1808. {
  1809. //
  1810. // we failed opening it. this means the caller will fail opening it
  1811. // that's ok.
  1812. //
  1813. pOverwriteInfo->IgnoredFile = TRUE;
  1814. Status = STATUS_SUCCESS;
  1815. leave;
  1816. }
  1817. //
  1818. // otherwise we are able to open it (so is the caller).
  1819. //
  1820. // Go ahead and copy off the file.
  1821. //
  1822. //
  1823. // reference the file object
  1824. //
  1825. Status = ObReferenceObjectByHandle( FileHandle,
  1826. 0,
  1827. *IoFileObjectType,
  1828. KernelMode,
  1829. (PVOID *) &pFileObject,
  1830. NULL );
  1831. if (!NT_SUCCESS( Status ))
  1832. leave;
  1833. //
  1834. // check for reparse/mount points
  1835. //
  1836. Status = SrCheckForMountsInPath( pExtension,
  1837. pFileObject,
  1838. &MountInPath );
  1839. if (!NT_SUCCESS( Status ))
  1840. leave;
  1841. //
  1842. // do we have a mount in the path
  1843. //
  1844. if (MountInPath)
  1845. {
  1846. //
  1847. // ignore this, we should reparse and come back.
  1848. //
  1849. pOverwriteInfo->IgnoredFile = TRUE;
  1850. Status = STATUS_SUCCESS;
  1851. leave;
  1852. }
  1853. Status = SrHandleFileChange( pExtension,
  1854. SrEventStreamChange,
  1855. pFileObject,
  1856. pFileName );
  1857. if (!NT_SUCCESS( Status ))
  1858. leave;
  1859. //
  1860. // we've handled this file
  1861. //
  1862. MarkFile = TRUE;
  1863. //
  1864. // let the caller know we copied the file
  1865. //
  1866. pOverwriteInfo->CopiedFile = TRUE;
  1867. Status = STATUS_SUCCESS;
  1868. leave;
  1869. #if 0 /* NO_RENAME */
  1870. }
  1871. //
  1872. // if the open succeeded, we have the right access
  1873. //
  1874. //
  1875. // reference the file object
  1876. //
  1877. Status = ObReferenceObjectByHandle( FileHandle,
  1878. 0,
  1879. *IoFileObjectType,
  1880. KernelMode,
  1881. (PVOID *) &pFileObject,
  1882. NULL );
  1883. if (!NT_SUCCESS( Status ))
  1884. leave;
  1885. //
  1886. // check for reparse/mount points
  1887. //
  1888. Status = SrCheckForMountsInPath( pExtension,
  1889. pFileObject,
  1890. &MountInPath );
  1891. if (!NT_SUCCESS( Status ))
  1892. leave;
  1893. //
  1894. // do we have a new name?
  1895. //
  1896. if (MountInPath)
  1897. {
  1898. //
  1899. // ignore this, we should reparse and come back.
  1900. //
  1901. pOverwriteInfo->IgnoredFile = TRUE;
  1902. Status = STATUS_SUCCESS;
  1903. leave;
  1904. }
  1905. //
  1906. // this get's complicated. when we rename this file out of this
  1907. // directory, the directory could temporarily be empty. this is bad
  1908. // as if sr.sys was never there, that directory would never have
  1909. // been empty. empty directories can be deleted. bug#163292 shows
  1910. // an example where we changed this semantic and broke somebody.
  1911. //
  1912. // we need to preserve the fact that this is a non-empty directory
  1913. //
  1914. // create an empty, delete_on_close, dummy file that will exist
  1915. // until we are done to keep the directory non-empty.
  1916. //
  1917. //
  1918. // first find the filename part in the full path
  1919. //
  1920. Status = SrFindCharReverse( pFileName->Buffer,
  1921. pFileName->Length,
  1922. L'\\',
  1923. &pToken,
  1924. &TokenLength );
  1925. if (!NT_SUCCESS( Status ))
  1926. leave;
  1927. Status = SrAllocateFileNameBuffer( pFileName->Length
  1928. - TokenLength
  1929. + SR_UNIQUE_TEMP_FILE_LENGTH,
  1930. &pTempFileName );
  1931. if (!NT_SUCCESS( Status ))
  1932. leave;
  1933. //
  1934. // and put our unique filename on there
  1935. //
  1936. pTempFileName->Length = pFileName->Length - (USHORT)TokenLength;
  1937. RtlCopyMemory( pTempFileName->Buffer,
  1938. pFileName->Buffer,
  1939. pTempFileName->Length );
  1940. RtlCopyMemory( &pTempFileName->Buffer[pTempFileName->Length/sizeof(WCHAR)],
  1941. SR_UNIQUE_TEMP_FILE,
  1942. SR_UNIQUE_TEMP_FILE_LENGTH );
  1943. pTempFileName->Length += SR_UNIQUE_TEMP_FILE_LENGTH;
  1944. pTempFileName->Buffer[pTempFileName->Length/sizeof(WCHAR)] = UNICODE_NULL;
  1945. InitializeObjectAttributes( &ObjectAttributes,
  1946. pTempFileName,
  1947. OBJ_KERNEL_HANDLE,
  1948. NULL,
  1949. NULL );
  1950. Status = ZwCreateFile( &TempFileHandle,
  1951. FILE_GENERIC_WRITE|DELETE,
  1952. &ObjectAttributes,
  1953. &IoStatusBlock,
  1954. NULL, // AllocationSize
  1955. FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
  1956. 0, // ShareAccess
  1957. FILE_CREATE, // CREATE_NEW
  1958. FILE_SYNCHRONOUS_IO_NONALERT|FILE_DELETE_ON_CLOSE,
  1959. NULL,
  1960. 0 ); // EaLength
  1961. if (Status == STATUS_OBJECT_NAME_COLLISION)
  1962. {
  1963. //
  1964. // there is already a file by this name. bummer. continue
  1965. // hoping that this file is not deleted so we get to maintain
  1966. // our non-empty directory status. this is ok and even normal
  1967. // if 2 overwrites are happening at the same time in the same
  1968. // directory.
  1969. //
  1970. //
  1971. // BUGBUG : paulmcd: 12/2000 : we need to fix this window also
  1972. // if we put back the rename opt code. we can't let this dummy
  1973. // file go away
  1974. //
  1975. Status = STATUS_SUCCESS;
  1976. }
  1977. else if (!NT_SUCCESS( Status ))
  1978. leave;
  1979. //
  1980. // now rename the file to the restore location
  1981. //
  1982. Status = SrRenameFileIntoStore( pExtension,
  1983. pFileObject,
  1984. FileHandle,
  1985. pFileName,
  1986. SrEventStreamOverwrite,
  1987. &pRenameInformation );
  1988. if (!NT_SUCCESS( Status ))
  1989. leave;
  1990. ASSERT(pRenameInformation != NULL);
  1991. //
  1992. // we have just renamed the file
  1993. //
  1994. RenamedFile = TRUE;
  1995. //
  1996. // and now create an empty dummy file that matches the original file
  1997. // attribs and security descriptor.
  1998. //
  1999. // we reuse SrBackupFile in this case for code-reuse. we reverse the flow
  2000. // and copy from the restore location into the volume, telling it not to
  2001. // copy any data streams.
  2002. //
  2003. RenamedFileName.Length = (USHORT)pRenameInformation->FileNameLength;
  2004. RenamedFileName.MaximumLength = (USHORT)pRenameInformation->FileNameLength;
  2005. RenamedFileName.Buffer = &pRenameInformation->FileName[0];
  2006. //
  2007. // ignore JUST this create+acl change, it's our dummy backupfile
  2008. //
  2009. Status = SrMarkFileBackedUp( pExtension,
  2010. pFileName,
  2011. SrEventFileCreate|SrEventAclChange );
  2012. if (!NT_SUCCESS( Status ))
  2013. leave;
  2014. Status = SrBackupFileAndLog( pExtension,
  2015. SrEventInvalid, // don't log this
  2016. pFileObject,
  2017. &RenamedFileName,
  2018. pFileName,
  2019. FALSE );
  2020. if (!NT_SUCCESS( Status ))
  2021. leave;
  2022. //
  2023. // restore the history back to before we added CREATE's (above just prior
  2024. // to the BackupFileKernelMode) .
  2025. //
  2026. Status = SrResetBackupHistory(pExtension, pFileName, RecordedEvents);
  2027. if (!NT_SUCCESS( Status ))
  2028. leave;
  2029. //
  2030. // we've handled this file
  2031. //
  2032. MarkFile = TRUE;
  2033. //
  2034. // let the caller know we renamed the file
  2035. //
  2036. pOverwriteInfo->RenamedFile = TRUE;
  2037. pOverwriteInfo->pRenameInformation = pRenameInformation;
  2038. pRenameInformation = NULL;
  2039. Status = STATUS_SUCCESS;
  2040. #endif /* NO_RENAME */
  2041. } finally {
  2042. //
  2043. // check for unhandled exceptions
  2044. //
  2045. Status = FinallyUnwind(SrHandleFileOverwrite, Status);
  2046. if (MarkFile)
  2047. {
  2048. NTSTATUS TempStatus;
  2049. ASSERT(NT_SUCCESS(Status));
  2050. //
  2051. // we have to mark that we handled the MODIFY, in order to ignore
  2052. // all subsequent MODIFY's
  2053. //
  2054. TempStatus = SrMarkFileBackedUp( pExtension,
  2055. pFileName,
  2056. pFileContext->StreamNameLength,
  2057. SrEventStreamChange,
  2058. SR_IGNORABLE_EVENT_TYPES );
  2059. CHECK_STATUS(TempStatus);
  2060. }
  2061. #if 0 /* NO_RENAME --- See note in function header block */
  2062. //
  2063. // did we fail AFTER renaming the file?
  2064. //
  2065. if (!NT_SUCCESS( Status ) && RenamedFile)
  2066. {
  2067. NTSTATUS TempStatus;
  2068. //
  2069. // put the file back! we might have to overwrite if our
  2070. // dummy file is there. we want to force this file back
  2071. // to it's old name.
  2072. //
  2073. ASSERT(pRenameInformation != NULL);
  2074. pRenameInformation->ReplaceIfExists = TRUE;
  2075. pRenameInformation->RootDirectory = NULL;
  2076. pRenameInformation->FileNameLength = pFileName->Length;
  2077. ASSERT(pFileName->Length <= SR_MAX_FILENAME_LENGTH);
  2078. RtlCopyMemory( &pRenameInformation->FileName[0],
  2079. pFileName->Buffer,
  2080. pFileName->Length );
  2081. TempStatus = ZwSetInformationFile( FileHandle,
  2082. &IoStatusBlock,
  2083. pRenameInformation,
  2084. SR_RENAME_BUFFER_LENGTH,
  2085. FileRenameInformation );
  2086. //
  2087. // we did the best we could!
  2088. //
  2089. ASSERTMSG("sr!SrHandleFileOverwrite: couldn't fix the failed rename, file lost!", NT_SUCCESS_NO_DBGBREAK(TempStatus));
  2090. }
  2091. if (pRenameInformation != NULL)
  2092. {
  2093. SR_FREE_POOL(pRenameInformation, SR_RENAME_BUFFER_TAG);
  2094. pRenameInformation = NULL;
  2095. }
  2096. #endif
  2097. if (pFileObject != NULL)
  2098. {
  2099. ObDereferenceObject(pFileObject);
  2100. pFileObject = NULL;
  2101. }
  2102. if (FileHandle != NULL)
  2103. {
  2104. ZwClose(FileHandle);
  2105. FileHandle = NULL;
  2106. }
  2107. if (TempFileHandle != NULL)
  2108. {
  2109. ZwClose(TempFileHandle);
  2110. TempFileHandle = NULL;
  2111. }
  2112. if (pTempFileName != NULL)
  2113. {
  2114. SrFreeFileNameBuffer(pTempFileName);
  2115. pTempFileName = NULL;
  2116. }
  2117. } // finally
  2118. RETURN(Status);
  2119. } // SrHandleFileOverwrite
  2120. /***************************************************************************++
  2121. Routine Description:
  2122. this will rename the file into the restore location.
  2123. this is for delete optimizations.
  2124. Arguments:
  2125. pExtension - SR's device extension for the volume on which this
  2126. file resides.
  2127. pFileObject - the file object to set the info on (created using
  2128. IoCreateFileSpecifyDeviceObjectHint).
  2129. FileHandle - a handle for use in queries. (created using
  2130. IoCreateFileSpecifyDeviceObjectHint).
  2131. pFileName - the original for the file that is about to be renamed.
  2132. EventType - the type of event that is causing this rename.
  2133. ppRenameInfo - you can know where we put it if you like
  2134. Return Value:
  2135. NTSTATUS - Completion status.
  2136. --***************************************************************************/
  2137. NTSTATUS
  2138. SrRenameFileIntoStore(
  2139. IN PSR_DEVICE_EXTENSION pExtension,
  2140. IN PFILE_OBJECT pFileObject,
  2141. IN HANDLE FileHandle,
  2142. IN PUNICODE_STRING pOriginalFileName,
  2143. IN PUNICODE_STRING pFileName,
  2144. IN SR_EVENT_TYPE EventType,
  2145. OUT PFILE_RENAME_INFORMATION * ppRenameInfo OPTIONAL
  2146. )
  2147. {
  2148. NTSTATUS Status;
  2149. IO_STATUS_BLOCK IoStatusBlock;
  2150. ULONG FileNameLength;
  2151. PUCHAR pDestLocation;
  2152. PFILE_RENAME_INFORMATION pRenameInformation = NULL;
  2153. PUNICODE_STRING pDestFileName = NULL;
  2154. FILE_STANDARD_INFORMATION FileInformation;
  2155. BOOLEAN RenamedFile = FALSE;
  2156. PUNICODE_STRING pShortName = NULL;
  2157. WCHAR ShortFileNameBuffer[SR_SHORT_NAME_CHARS+1];
  2158. UNICODE_STRING ShortFileName;
  2159. PAGED_CODE();
  2160. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2161. ASSERT(IS_VALID_FILE_OBJECT(pFileObject));
  2162. ASSERT(FileHandle != NULL);
  2163. ASSERT(FlagOn( pFileObject->Flags, FO_FILE_OBJECT_HAS_EXTENSION ));
  2164. try {
  2165. //
  2166. // Is our volume properly setup?
  2167. //
  2168. Status = SrCheckVolume(pExtension, FALSE);
  2169. if (!NT_SUCCESS( Status ))
  2170. leave;
  2171. //
  2172. // Do we have enough room in the data store for this file?
  2173. //
  2174. Status = SrCheckFreeDiskSpace( FileHandle, pExtension->pNtVolumeName );
  2175. if (!NT_SUCCESS( Status ))
  2176. leave;
  2177. //
  2178. // do we need to get the short name prior to the rename (for
  2179. // delete's) .
  2180. //
  2181. if (FlagOn( EventType, SrEventFileDelete ))
  2182. {
  2183. RtlInitEmptyUnicodeString( &ShortFileName,
  2184. ShortFileNameBuffer,
  2185. sizeof(ShortFileNameBuffer) );
  2186. Status = SrGetShortFileName( pExtension,
  2187. pFileObject,
  2188. &ShortFileName );
  2189. if (STATUS_OBJECT_NAME_NOT_FOUND == Status)
  2190. {
  2191. //
  2192. // This file doesn't have a short name, so just leave
  2193. // pShortName equal to NULL.
  2194. //
  2195. Status = STATUS_SUCCESS;
  2196. }
  2197. else if (!NT_SUCCESS(Status))
  2198. {
  2199. //
  2200. // We hit an unexpected error, so leave.
  2201. //
  2202. leave;
  2203. }
  2204. else
  2205. {
  2206. pShortName = &ShortFileName;
  2207. }
  2208. }
  2209. //
  2210. // now prepare to rename the file
  2211. //
  2212. pRenameInformation = SR_ALLOCATE_POOL( PagedPool,
  2213. SR_RENAME_BUFFER_LENGTH,
  2214. SR_RENAME_BUFFER_TAG );
  2215. if (pRenameInformation == NULL)
  2216. {
  2217. Status = STATUS_INSUFFICIENT_RESOURCES;
  2218. leave;
  2219. }
  2220. //
  2221. // and get a buffer for a string
  2222. //
  2223. Status = SrAllocateFileNameBuffer( SR_MAX_FILENAME_LENGTH,
  2224. &pDestFileName );
  2225. if (!NT_SUCCESS( Status ))
  2226. leave;
  2227. Status = SrGetDestFileName( pExtension,
  2228. pFileName,
  2229. pDestFileName );
  2230. if (!NT_SUCCESS( Status ))
  2231. leave;
  2232. pDestLocation = (PUCHAR)&pRenameInformation->FileName[0];
  2233. //
  2234. // save this now as it get's overwritten.
  2235. //
  2236. FileNameLength = pDestFileName->Length;
  2237. //
  2238. // and make sure it's in the right spot for the rename info now
  2239. //
  2240. RtlMoveMemory( pDestLocation,
  2241. pDestFileName->Buffer,
  2242. pDestFileName->Length + sizeof(WCHAR) );
  2243. //
  2244. // now initialize the rename info struct
  2245. //
  2246. pRenameInformation->ReplaceIfExists = TRUE;
  2247. pRenameInformation->RootDirectory = NULL;
  2248. pRenameInformation->FileNameLength = FileNameLength;
  2249. SrTrace( NOTIFY, ("SR!SrRenameFileIntoStore:\n\t%wZ\n\tto %ws\n",
  2250. pFileName,
  2251. SrpFindFilePartW(&pRenameInformation->FileName[0]) ));
  2252. //
  2253. // and perform the rename
  2254. //
  2255. RtlZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock));
  2256. Status = ZwSetInformationFile( FileHandle,
  2257. &IoStatusBlock,
  2258. pRenameInformation,
  2259. SR_FILENAME_BUFFER_LENGTH,
  2260. FileRenameInformation );
  2261. if (!NT_SUCCESS( Status ))
  2262. leave;
  2263. //
  2264. // we have now renamed the file
  2265. //
  2266. RenamedFile = TRUE;
  2267. //
  2268. // now get the filesize we just renamed
  2269. //
  2270. Status = ZwQueryInformationFile( FileHandle,
  2271. &IoStatusBlock,
  2272. &FileInformation,
  2273. sizeof(FileInformation),
  2274. FileStandardInformation );
  2275. if (!NT_SUCCESS( Status ) ||
  2276. NT_SUCCESS(IoStatusBlock.Status) == FALSE)
  2277. {
  2278. leave;
  2279. }
  2280. //
  2281. // and update the byte count as we moved this into the store
  2282. //
  2283. Status = SrUpdateBytesWritten( pExtension,
  2284. FileInformation.EndOfFile.QuadPart );
  2285. if (!NT_SUCCESS( Status ))
  2286. leave;
  2287. //
  2288. // paulmcd: 5/24/2000 decided not to do this and let the link
  2289. // tracking system hack their code to make shortcuts not work in
  2290. // our store.
  2291. //
  2292. #if 0
  2293. //
  2294. // strip out the object if of the newly renamed file.
  2295. // this prevents any existing shortcuts to link into our restore
  2296. // location. this file should be considered gone from the fs
  2297. //
  2298. Status = ZwFsControlFile( FileHandle, // file handle
  2299. NULL, // event
  2300. NULL, // apc routine
  2301. NULL, // apc context
  2302. &IoStatusBlock, // iosb
  2303. FSCTL_DELETE_OBJECT_ID, // FsControlCode
  2304. NULL, // input buffer
  2305. 0, // input buffer length
  2306. NULL, // OutputBuffer for data from the FS
  2307. 0 ); // OutputBuffer Length
  2308. //
  2309. // no big deal if this fails, it might not have had one.
  2310. //
  2311. CHECK_STATUS(Status);
  2312. Status = STATUS_SUCCESS;
  2313. #endif
  2314. //
  2315. // Now Log event
  2316. //
  2317. Status = SrLogEvent( pExtension,
  2318. EventType,
  2319. pFileObject,
  2320. pFileName,
  2321. 0,
  2322. pDestFileName,
  2323. NULL,
  2324. 0,
  2325. pShortName );
  2326. if (!NT_SUCCESS( Status ))
  2327. leave;
  2328. //
  2329. // now strip the owner SID so that the old user no longer charged
  2330. // quota for this file. it's in our store.
  2331. //
  2332. // its important to do this after we call SrLogEvent, as SrLogEvent
  2333. // needs to query the valid security descriptor for logging.
  2334. //
  2335. Status = SrSetFileSecurity(FileHandle, TRUE, FALSE);
  2336. if (!NT_SUCCESS( Status ))
  2337. leave;
  2338. //
  2339. // does the caller want to know where we just renamed it to?
  2340. //
  2341. if (ppRenameInfo != NULL)
  2342. {
  2343. //
  2344. // let him own the buffer
  2345. //
  2346. *ppRenameInfo = pRenameInformation;
  2347. pRenameInformation = NULL;
  2348. }
  2349. } finally {
  2350. Status = FinallyUnwind(SrRenameFileIntoStore, Status);
  2351. //
  2352. // it better have succeeded or we better have the rename info around
  2353. //
  2354. //
  2355. // did we fail AFTER we renamed the file ? we need to clean up after
  2356. // ourselves if we did.
  2357. //
  2358. if (!NT_SUCCESS( Status ) &&
  2359. RenamedFile &&
  2360. pRenameInformation != NULL)
  2361. {
  2362. NTSTATUS TempStatus;
  2363. SrTraceSafe( NOTIFY, ("SR!SrRenameFileIntoStore:FAILED!:renaming it back\n"));
  2364. pRenameInformation->ReplaceIfExists = TRUE;
  2365. pRenameInformation->RootDirectory = NULL;
  2366. pRenameInformation->FileNameLength = pOriginalFileName->Length;
  2367. RtlCopyMemory( &pRenameInformation->FileName[0],
  2368. pOriginalFileName->Buffer,
  2369. pOriginalFileName->Length );
  2370. //
  2371. // and perform the rename
  2372. //
  2373. RtlZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock));
  2374. TempStatus = ZwSetInformationFile( FileHandle,
  2375. &IoStatusBlock,
  2376. pRenameInformation,
  2377. SR_FILENAME_BUFFER_LENGTH,
  2378. FileRenameInformation );
  2379. //
  2380. // we did the best we could!
  2381. //
  2382. ASSERTMSG("sr!SrRenameFileIntoStore: couldn't fix the failed rename, file lost!", NT_SUCCESS_NO_DBGBREAK(TempStatus));
  2383. }
  2384. if (pRenameInformation != NULL)
  2385. {
  2386. SR_FREE_POOL(pRenameInformation, SR_RENAME_BUFFER_TAG);
  2387. pRenameInformation = NULL;
  2388. }
  2389. if (pDestFileName != NULL)
  2390. {
  2391. SrFreeFileNameBuffer(pDestFileName);
  2392. pDestFileName = NULL;
  2393. }
  2394. }
  2395. RETURN(Status);
  2396. } // SrRenameFileIntoStore
  2397. /***************************************************************************++
  2398. Routine Description:
  2399. this routine is called in the rename code path. if a directory is being
  2400. renamed out of monitored space, we simulate delete's for all of the files
  2401. in that directory.
  2402. Arguments:
  2403. EventDelete - TRUE if we should trigger deletes, FALSE to trigger creates
  2404. Return Value:
  2405. NTSTATUS - Completion status.
  2406. --***************************************************************************/
  2407. NTSTATUS
  2408. SrTriggerEvents(
  2409. IN PSR_DEVICE_EXTENSION pExtension,
  2410. IN PUNICODE_STRING pDirectoryName,
  2411. IN BOOLEAN EventDelete
  2412. )
  2413. {
  2414. NTSTATUS Status;
  2415. OBJECT_ATTRIBUTES ObjectAttributes;
  2416. IO_STATUS_BLOCK IoStatusBlock;
  2417. ULONG FileNameLength;
  2418. PUNICODE_STRING pFileName = NULL;
  2419. HANDLE FileHandle = NULL;
  2420. PFILE_OBJECT pFileObject = NULL;
  2421. UNICODE_STRING StarFilter;
  2422. PSR_TRIGGER_ITEM pCurrentItem = NULL;
  2423. LIST_ENTRY DirectoryList;
  2424. PAGED_CODE();
  2425. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2426. try {
  2427. InitializeListHead(&DirectoryList);
  2428. //
  2429. // allocate the first work item
  2430. //
  2431. pCurrentItem = SR_ALLOCATE_STRUCT( PagedPool,
  2432. SR_TRIGGER_ITEM,
  2433. SR_TRIGGER_ITEM_TAG );
  2434. if (pCurrentItem == NULL)
  2435. {
  2436. Status = STATUS_INSUFFICIENT_RESOURCES;
  2437. leave;
  2438. }
  2439. RtlZeroMemory(pCurrentItem, sizeof(SR_TRIGGER_ITEM));
  2440. pCurrentItem->Signature = SR_TRIGGER_ITEM_TAG;
  2441. pCurrentItem->pDirectoryName = pDirectoryName;
  2442. pCurrentItem->FreeDirectoryName = FALSE;
  2443. //
  2444. // make sure noboby is using this one passed in the arg list.
  2445. //
  2446. pDirectoryName = NULL;
  2447. //
  2448. // allocate a single temp filename buffer
  2449. //
  2450. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, &pFileName);
  2451. if (!NT_SUCCESS( Status ))
  2452. leave;
  2453. //
  2454. // start our outer most directory handler
  2455. //
  2456. start_directory:
  2457. SrTrace( RENAME, ("sr!SrTriggerEvents: starting dir=%wZ\n",
  2458. pCurrentItem->pDirectoryName ));
  2459. //
  2460. // Open the directory for list access
  2461. //
  2462. InitializeObjectAttributes( &ObjectAttributes,
  2463. pCurrentItem->pDirectoryName,
  2464. OBJ_KERNEL_HANDLE,
  2465. NULL,
  2466. NULL );
  2467. Status = SrIoCreateFile( &pCurrentItem->DirectoryHandle,
  2468. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  2469. &ObjectAttributes,
  2470. &IoStatusBlock,
  2471. NULL, // AllocationSize
  2472. FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_NORMAL,
  2473. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,// ShareAccess
  2474. FILE_OPEN, // OPEN_EXISTING
  2475. FILE_DIRECTORY_FILE
  2476. | FILE_OPEN_FOR_BACKUP_INTENT
  2477. | FILE_SYNCHRONOUS_IO_NONALERT,
  2478. NULL,
  2479. 0, // EaLength
  2480. IO_IGNORE_SHARE_ACCESS_CHECK,
  2481. pExtension->pTargetDevice );
  2482. if (!NT_SUCCESS( Status ))
  2483. leave;
  2484. //
  2485. // reference the file object
  2486. //
  2487. Status = ObReferenceObjectByHandle( pCurrentItem->DirectoryHandle,
  2488. 0,
  2489. *IoFileObjectType,
  2490. KernelMode,
  2491. (PVOID *) &pCurrentItem->pDirectoryObject,
  2492. NULL );
  2493. if (!NT_SUCCESS( Status ))
  2494. leave;
  2495. //
  2496. // for creates: log the directory event first
  2497. //
  2498. if (!EventDelete)
  2499. {
  2500. Status = SrHandleEvent( pExtension,
  2501. SrEventDirectoryCreate|SrEventIsDirectory,
  2502. pCurrentItem->pDirectoryObject,
  2503. NULL,
  2504. NULL,
  2505. NULL ); // pFileName2
  2506. if (!NT_SUCCESS( Status ))
  2507. leave;
  2508. }
  2509. StarFilter.Length = sizeof(WCHAR);
  2510. StarFilter.MaximumLength = sizeof(WCHAR);
  2511. StarFilter.Buffer = L"*";
  2512. pCurrentItem->FileEntryLength = SR_FILE_ENTRY_LENGTH;
  2513. pCurrentItem->pFileEntry = (PFILE_DIRECTORY_INFORMATION)(
  2514. SR_ALLOCATE_ARRAY( PagedPool,
  2515. UCHAR,
  2516. pCurrentItem->FileEntryLength,
  2517. SR_FILE_ENTRY_TAG ) );
  2518. if (pCurrentItem->pFileEntry == NULL)
  2519. {
  2520. Status = STATUS_INSUFFICIENT_RESOURCES;
  2521. leave;
  2522. }
  2523. //
  2524. // start the enumeration
  2525. //
  2526. Status = ZwQueryDirectoryFile( pCurrentItem->DirectoryHandle,
  2527. NULL,
  2528. NULL,
  2529. NULL,
  2530. &IoStatusBlock,
  2531. pCurrentItem->pFileEntry,
  2532. pCurrentItem->FileEntryLength,
  2533. FileDirectoryInformation,
  2534. TRUE, // ReturnSingleEntry
  2535. &StarFilter,
  2536. TRUE ); // RestartScan
  2537. if (Status == STATUS_NO_MORE_FILES)
  2538. {
  2539. Status = STATUS_SUCCESS;
  2540. goto finish_directory;
  2541. }
  2542. else if (!NT_SUCCESS( Status ))
  2543. {
  2544. leave;
  2545. }
  2546. //
  2547. // enumerate all of the files in this directory and back them up
  2548. //
  2549. while (TRUE)
  2550. {
  2551. //
  2552. // skip "." and ".."
  2553. //
  2554. if ((pCurrentItem->pFileEntry->FileNameLength == sizeof(WCHAR) &&
  2555. pCurrentItem->pFileEntry->FileName[0] == L'.') ||
  2556. (pCurrentItem->pFileEntry->FileNameLength == (sizeof(WCHAR)*2) &&
  2557. pCurrentItem->pFileEntry->FileName[0] == L'.' &&
  2558. pCurrentItem->pFileEntry->FileName[1] == L'.') )
  2559. {
  2560. //
  2561. // skip it
  2562. //
  2563. }
  2564. //
  2565. // is this a directory?
  2566. //
  2567. else if (pCurrentItem->pFileEntry->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2568. {
  2569. PSR_TRIGGER_ITEM pParentItem;
  2570. PUNICODE_STRING pDirNameBuffer;
  2571. USHORT DirNameLength;
  2572. //
  2573. // remember a pointer to the parent item
  2574. //
  2575. pParentItem = pCurrentItem;
  2576. //
  2577. // insert the old item to the list, we'll get back to it
  2578. //
  2579. InsertTailList(&DirectoryList, &pCurrentItem->ListEntry);
  2580. pCurrentItem = NULL;
  2581. //
  2582. // allocate a new current trigger item
  2583. //
  2584. pCurrentItem = SR_ALLOCATE_STRUCT( PagedPool,
  2585. SR_TRIGGER_ITEM,
  2586. SR_TRIGGER_ITEM_TAG );
  2587. if (pCurrentItem == NULL)
  2588. {
  2589. Status = STATUS_INSUFFICIENT_RESOURCES;
  2590. leave;
  2591. }
  2592. RtlZeroMemory(pCurrentItem, sizeof(SR_TRIGGER_ITEM));
  2593. pCurrentItem->Signature = SR_TRIGGER_ITEM_TAG;
  2594. //
  2595. // allocate a file name buffer
  2596. //
  2597. DirNameLength = (USHORT)(pParentItem->pDirectoryName->Length
  2598. + sizeof(WCHAR)
  2599. + pParentItem->pFileEntry->FileNameLength);
  2600. Status = SrAllocateFileNameBuffer( DirNameLength,
  2601. &pDirNameBuffer );
  2602. if (!NT_SUCCESS( Status ))
  2603. leave;
  2604. //
  2605. // construct a full path string for the sub directory
  2606. //
  2607. pDirNameBuffer->Length = DirNameLength;
  2608. RtlCopyMemory( pDirNameBuffer->Buffer,
  2609. pParentItem->pDirectoryName->Buffer,
  2610. pParentItem->pDirectoryName->Length );
  2611. pDirNameBuffer->Buffer
  2612. [pParentItem->pDirectoryName->Length/sizeof(WCHAR)] = L'\\';
  2613. RtlCopyMemory( &pDirNameBuffer->Buffer[(pParentItem->pDirectoryName->Length/sizeof(WCHAR)) + 1],
  2614. pParentItem->pFileEntry->FileName,
  2615. pParentItem->pFileEntry->FileNameLength );
  2616. pDirNameBuffer->Buffer
  2617. [pDirNameBuffer->Length/sizeof(WCHAR)] = UNICODE_NULL;
  2618. pCurrentItem->pDirectoryName = pDirNameBuffer;
  2619. pCurrentItem->FreeDirectoryName = TRUE;
  2620. //
  2621. // now process this child directory
  2622. //
  2623. goto start_directory;
  2624. }
  2625. else
  2626. {
  2627. //
  2628. // open the file, first construct a full path string to the file
  2629. //
  2630. FileNameLength = pCurrentItem->pDirectoryName->Length
  2631. + sizeof(WCHAR)
  2632. + pCurrentItem->pFileEntry->FileNameLength;
  2633. if (FileNameLength > pFileName->MaximumLength)
  2634. {
  2635. Status = STATUS_BUFFER_OVERFLOW;
  2636. leave;
  2637. }
  2638. pFileName->Length = (USHORT)FileNameLength;
  2639. RtlCopyMemory( pFileName->Buffer,
  2640. pCurrentItem->pDirectoryName->Buffer,
  2641. pCurrentItem->pDirectoryName->Length );
  2642. pFileName->Buffer[pCurrentItem->pDirectoryName->Length/sizeof(WCHAR)] = L'\\';
  2643. RtlCopyMemory( &(pFileName->Buffer[(pCurrentItem->pDirectoryName->Length/sizeof(WCHAR)) + 1]),
  2644. pCurrentItem->pFileEntry->FileName,
  2645. pCurrentItem->pFileEntry->FileNameLength );
  2646. SrTrace(RENAME, ("sr!SrTriggerEvents: file=%wZ\n", pFileName));
  2647. InitializeObjectAttributes( &ObjectAttributes,
  2648. pFileName,
  2649. OBJ_KERNEL_HANDLE,
  2650. NULL,
  2651. NULL );
  2652. ASSERT(FileHandle == NULL);
  2653. Status = SrIoCreateFile( &FileHandle,
  2654. FILE_READ_ATTRIBUTES|SYNCHRONIZE,
  2655. &ObjectAttributes,
  2656. &IoStatusBlock,
  2657. NULL, // AllocationSize
  2658. FILE_ATTRIBUTE_NORMAL,
  2659. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,// ShareAccess
  2660. FILE_OPEN, // OPEN_EXISTING
  2661. FILE_SEQUENTIAL_ONLY
  2662. | FILE_WRITE_THROUGH
  2663. | FILE_NO_INTERMEDIATE_BUFFERING
  2664. | FILE_NON_DIRECTORY_FILE
  2665. | FILE_OPEN_FOR_BACKUP_INTENT
  2666. | FILE_SYNCHRONOUS_IO_NONALERT,
  2667. NULL,
  2668. 0, // EaLength
  2669. IO_IGNORE_SHARE_ACCESS_CHECK,
  2670. pExtension->pTargetDevice );
  2671. if (!NT_SUCCESS( Status ))
  2672. leave;
  2673. //
  2674. // reference the file object
  2675. //
  2676. Status = ObReferenceObjectByHandle( FileHandle,
  2677. 0,
  2678. *IoFileObjectType,
  2679. KernelMode,
  2680. (PVOID *) &pFileObject,
  2681. NULL );
  2682. if (!NT_SUCCESS( Status ))
  2683. leave;
  2684. //
  2685. // simulate a delete event happening on this file
  2686. //
  2687. Status = SrHandleEvent( pExtension,
  2688. EventDelete ?
  2689. (SrEventFileDelete|SrEventNoOptimization|SrEventSimulatedDelete) :
  2690. SrEventFileCreate,
  2691. pFileObject,
  2692. NULL,
  2693. NULL,
  2694. NULL );
  2695. if (!NT_SUCCESS( Status ))
  2696. leave;
  2697. //
  2698. // all done with these
  2699. //
  2700. ObDereferenceObject(pFileObject);
  2701. pFileObject = NULL;
  2702. ZwClose(FileHandle);
  2703. FileHandle = NULL;
  2704. }
  2705. continue_directory:
  2706. //
  2707. // is there another file?
  2708. //
  2709. Status = ZwQueryDirectoryFile( pCurrentItem->DirectoryHandle,
  2710. NULL,
  2711. NULL,
  2712. NULL,
  2713. &IoStatusBlock,
  2714. pCurrentItem->pFileEntry,
  2715. pCurrentItem->FileEntryLength,
  2716. FileDirectoryInformation,
  2717. TRUE, // ReturnSingleEntry
  2718. NULL, // FileName
  2719. FALSE ); // RestartScan
  2720. if (Status == STATUS_NO_MORE_FILES)
  2721. {
  2722. Status = STATUS_SUCCESS;
  2723. break;
  2724. }
  2725. else if (!NT_SUCCESS( Status ))
  2726. {
  2727. leave;
  2728. }
  2729. } // while (TRUE)
  2730. finish_directory:
  2731. //
  2732. // for deletes: simulate the event at the end.
  2733. //
  2734. if (EventDelete)
  2735. {
  2736. Status = SrHandleEvent( pExtension,
  2737. SrEventDirectoryDelete|SrEventIsDirectory|SrEventSimulatedDelete,
  2738. pCurrentItem->pDirectoryObject,
  2739. NULL,
  2740. NULL,
  2741. NULL ); // pFileName2
  2742. if (!NT_SUCCESS( Status ))
  2743. leave;
  2744. }
  2745. //
  2746. // we just finished a directory item, remove it and free it
  2747. //
  2748. SrFreeTriggerItem(pCurrentItem);
  2749. pCurrentItem = NULL;
  2750. //
  2751. // is there another one ?
  2752. //
  2753. if (IsListEmpty(&DirectoryList) == FALSE)
  2754. {
  2755. PLIST_ENTRY pListEntry;
  2756. //
  2757. // finish it
  2758. //
  2759. pListEntry = RemoveTailList(&DirectoryList);
  2760. pCurrentItem = CONTAINING_RECORD( pListEntry,
  2761. SR_TRIGGER_ITEM,
  2762. ListEntry );
  2763. ASSERT(IS_VALID_TRIGGER_ITEM(pCurrentItem));
  2764. SrTrace( RENAME, ("sr!SrTriggerEvents: resuming dir=%wZ\n",
  2765. pCurrentItem->pDirectoryName ));
  2766. goto continue_directory;
  2767. }
  2768. //
  2769. // all done
  2770. //
  2771. } finally {
  2772. Status = FinallyUnwind(SrTriggerEvents, Status);
  2773. if (pFileObject != NULL)
  2774. {
  2775. ObDereferenceObject(pFileObject);
  2776. pFileObject = NULL;
  2777. }
  2778. if (FileHandle != NULL)
  2779. {
  2780. ZwClose(FileHandle);
  2781. FileHandle = NULL;
  2782. }
  2783. if (pFileName != NULL)
  2784. {
  2785. SrFreeFileNameBuffer(pFileName);
  2786. pFileName = NULL;
  2787. }
  2788. if (pCurrentItem != NULL)
  2789. {
  2790. ASSERT(NT_SUCCESS_NO_DBGBREAK(Status) == FALSE);
  2791. SrFreeTriggerItem(pCurrentItem);
  2792. pCurrentItem = NULL;
  2793. }
  2794. ASSERT(IsListEmpty(&DirectoryList) ||
  2795. NT_SUCCESS_NO_DBGBREAK(Status) == FALSE);
  2796. while (IsListEmpty(&DirectoryList) == FALSE)
  2797. {
  2798. PLIST_ENTRY pListEntry;
  2799. pListEntry = RemoveTailList(&DirectoryList);
  2800. pCurrentItem = CONTAINING_RECORD( pListEntry,
  2801. SR_TRIGGER_ITEM,
  2802. ListEntry );
  2803. ASSERT(IS_VALID_TRIGGER_ITEM(pCurrentItem));
  2804. SrFreeTriggerItem(pCurrentItem);
  2805. }
  2806. }
  2807. RETURN(Status);
  2808. } // SrTriggerEvents
  2809. /***************************************************************************++
  2810. Routine Description:
  2811. this is the second phase handling of a rename. if a directory is renamed
  2812. from non-monitored space to monitored space, we need to enumerate the
  2813. new directory and simluate (trigger) create events for each new file.
  2814. this results in a log entry being created for each new file that was
  2815. added .
  2816. Arguments:
  2817. --***************************************************************************/
  2818. NTSTATUS
  2819. SrHandleDirectoryRename(
  2820. IN PSR_DEVICE_EXTENSION pExtension,
  2821. IN PUNICODE_STRING pDirectoryName,
  2822. IN BOOLEAN EventDelete
  2823. )
  2824. {
  2825. NTSTATUS Status;
  2826. PAGED_CODE();
  2827. try {
  2828. //
  2829. // Acquire the activily lock for the volume
  2830. //
  2831. SrAcquireActivityLockShared( pExtension );
  2832. Status = STATUS_SUCCESS;
  2833. //
  2834. // did we just get disabled?
  2835. //
  2836. if (!SR_LOGGING_ENABLED(pExtension))
  2837. leave;
  2838. //
  2839. // don't check the volume yet, we don't if there is anything
  2840. // interesting even though this could be a new restore point.
  2841. // SrHandleEvent will check the volume (SrTriggerEvents calls it) .
  2842. //
  2843. //
  2844. // it's a directory. fire events on all of the children,
  2845. // as they are moving also!
  2846. //
  2847. Status = SrTriggerEvents( pExtension,
  2848. pDirectoryName,
  2849. EventDelete );
  2850. if (!NT_SUCCESS( Status ))
  2851. leave;
  2852. } finally {
  2853. Status = FinallyUnwind(SrHandleDirectoryRename, Status);
  2854. //
  2855. // check for any bad errors
  2856. //
  2857. if (CHECK_FOR_VOLUME_ERROR(Status))
  2858. {
  2859. NTSTATUS TempStatus;
  2860. //
  2861. // trigger the failure notification to the service
  2862. //
  2863. TempStatus = SrNotifyVolumeError( pExtension,
  2864. pDirectoryName,
  2865. Status,
  2866. SrEventDirectoryRename );
  2867. CHECK_STATUS(TempStatus);
  2868. }
  2869. SrReleaseActivityLock( pExtension );
  2870. }
  2871. RETURN(Status);
  2872. } // SrHandleDirectoryRename
  2873. /***************************************************************************++
  2874. Routine Description:
  2875. This handles when a file is being renamed out of monitored space
  2876. and we need to backup the file before the rename. We return the name
  2877. of the destination file we created so it can be logged with the
  2878. operation if the rename is successful.
  2879. Arguments:
  2880. pFileObject - the file object that just changed
  2881. pFileName - the name of the file that changed
  2882. ppDestFileName - this returns the allocated destination file name (if one
  2883. is defined, so it can be logged with the entry)
  2884. Return Value:
  2885. NTSTATUS - Completion status.
  2886. --***************************************************************************/
  2887. NTSTATUS
  2888. SrHandleFileRenameOutOfMonitoredSpace(
  2889. IN PSR_DEVICE_EXTENSION pExtension,
  2890. IN PFILE_OBJECT pFileObject,
  2891. IN PSR_STREAM_CONTEXT pFileContext,
  2892. OUT PBOOLEAN pOptimizeDelete,
  2893. OUT PUNICODE_STRING *ppDestFileName
  2894. )
  2895. {
  2896. ULONGLONG BytesWritten;
  2897. NTSTATUS Status;
  2898. BOOLEAN HasFileBeenBackedUp;
  2899. BOOLEAN releaseLock = FALSE;
  2900. PAGED_CODE();
  2901. ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
  2902. ASSERT(IS_VALID_FILE_OBJECT(pFileObject));
  2903. ASSERT( pFileContext != NULL );
  2904. //
  2905. // Initialize return parameters
  2906. //
  2907. *pOptimizeDelete = FALSE;
  2908. *ppDestFileName = NULL;
  2909. //
  2910. // See if the file has already been backed up because of a delete. If so
  2911. // don't do it again.
  2912. //
  2913. HasFileBeenBackedUp = SrHasFileBeenBackedUp( pExtension,
  2914. &(pFileContext->FileName),
  2915. pFileContext->StreamNameLength,
  2916. SrEventFileDelete );
  2917. if (HasFileBeenBackedUp)
  2918. {
  2919. *pOptimizeDelete = TRUE;
  2920. return STATUS_SUCCESS;
  2921. }
  2922. //
  2923. // Handle backing up the file
  2924. //
  2925. try {
  2926. //
  2927. // Allocate a buffer to hold destination name
  2928. //
  2929. Status = SrAllocateFileNameBuffer(SR_MAX_FILENAME_LENGTH, ppDestFileName);
  2930. if (!NT_SUCCESS( Status ))
  2931. leave;
  2932. //
  2933. // Acquire the activily lock for the volume
  2934. //
  2935. SrAcquireActivityLockShared( pExtension );
  2936. releaseLock = TRUE;
  2937. //
  2938. // we need to make sure our disk structures are good and logging
  2939. // has been started.
  2940. //
  2941. Status = SrCheckVolume(pExtension, FALSE);
  2942. if (!NT_SUCCESS( Status ))
  2943. leave;
  2944. //
  2945. // Generate a destination file name
  2946. //
  2947. Status = SrGetDestFileName( pExtension,
  2948. &(pFileContext->FileName),
  2949. *ppDestFileName );
  2950. if (!NT_SUCCESS( Status ))
  2951. leave;
  2952. //
  2953. // Backup the file
  2954. //
  2955. Status = SrBackupFile( pExtension,
  2956. pFileObject,
  2957. &(pFileContext->FileName),
  2958. *ppDestFileName,
  2959. TRUE,
  2960. &BytesWritten,
  2961. NULL );
  2962. if (Status == SR_STATUS_IGNORE_FILE)
  2963. {
  2964. //
  2965. // We weren't able to open the file because it was encrypted in
  2966. // another context. Unfortunately, we cannot recover from this
  2967. // error, so return the actual error of STATUS_ACCESS_DENIED.
  2968. //
  2969. Status = STATUS_ACCESS_DENIED;
  2970. CHECK_STATUS( Status );
  2971. leave;
  2972. }
  2973. else if (!NT_SUCCESS(Status))
  2974. leave;
  2975. //
  2976. // Update the bytes written.
  2977. //
  2978. Status = SrUpdateBytesWritten(pExtension, BytesWritten);
  2979. if (!NT_SUCCESS(Status))
  2980. leave;
  2981. }
  2982. finally
  2983. {
  2984. if (releaseLock)
  2985. {
  2986. SrReleaseActivityLock( pExtension );
  2987. }
  2988. //
  2989. // If we are returning an error then do not return the string
  2990. // (and free it).
  2991. //
  2992. if (!NT_SUCCESS_NO_DBGBREAK(Status) && (NULL != *ppDestFileName))
  2993. {
  2994. SrFreeFileNameBuffer(*ppDestFileName);
  2995. *ppDestFileName = NULL;
  2996. }
  2997. }
  2998. return Status;
  2999. }
  3000. /***************************************************************************++
  3001. Routine Description:
  3002. this routine is called from the mj_create completion routine. it
  3003. happens if the mj_create failed in it's overwrite, but we thought it was
  3004. going to work and renamed the destination file out from under the
  3005. overwrite. in this case we have to cleanup after ourselves.
  3006. Arguments:
  3007. --***************************************************************************/
  3008. NTSTATUS
  3009. SrHandleOverwriteFailure(
  3010. IN PSR_DEVICE_EXTENSION pExtension,
  3011. IN PUNICODE_STRING pOriginalFileName,
  3012. IN ULONG CreateFileAttributes,
  3013. IN PFILE_RENAME_INFORMATION pRenameInformation
  3014. )
  3015. {
  3016. NTSTATUS Status;
  3017. NTSTATUS TempStatus;
  3018. HANDLE FileHandle = NULL;
  3019. UNICODE_STRING FileName;
  3020. OBJECT_ATTRIBUTES ObjectAttributes;
  3021. IO_STATUS_BLOCK IoStatusBlock;
  3022. PAGED_CODE();
  3023. try {
  3024. SrAcquireActivityLockShared( pExtension );
  3025. //
  3026. // open the file that we renamed to.
  3027. //
  3028. FileName.Length = (USHORT)pRenameInformation->FileNameLength;
  3029. FileName.MaximumLength = (USHORT)pRenameInformation->FileNameLength;
  3030. FileName.Buffer = &pRenameInformation->FileName[0];
  3031. InitializeObjectAttributes( &ObjectAttributes,
  3032. &FileName,
  3033. OBJ_KERNEL_HANDLE,
  3034. NULL,
  3035. NULL );
  3036. Status = SrIoCreateFile( &FileHandle,
  3037. DELETE|SYNCHRONIZE,
  3038. &ObjectAttributes,
  3039. &IoStatusBlock,
  3040. NULL, // AllocationSize
  3041. CreateFileAttributes,
  3042. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,// ShareAccess
  3043. FILE_OPEN, // OPEN_EXISTING
  3044. FILE_SYNCHRONOUS_IO_NONALERT
  3045. | FILE_WRITE_THROUGH,
  3046. NULL,
  3047. 0, // EaLength
  3048. IO_IGNORE_SHARE_ACCESS_CHECK,
  3049. pExtension->pTargetDevice );
  3050. if (!NT_SUCCESS( Status ))
  3051. leave;
  3052. pRenameInformation->ReplaceIfExists = TRUE;
  3053. pRenameInformation->RootDirectory = NULL;
  3054. pRenameInformation->FileNameLength = pOriginalFileName->Length;
  3055. RtlCopyMemory( &pRenameInformation->FileName[0],
  3056. pOriginalFileName->Buffer,
  3057. pOriginalFileName->Length );
  3058. RtlZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock));
  3059. Status = ZwSetInformationFile( FileHandle,
  3060. &IoStatusBlock,
  3061. pRenameInformation,
  3062. SR_FILENAME_BUFFER_LENGTH,
  3063. FileRenameInformation );
  3064. if (!NT_SUCCESS( Status ))
  3065. leave;
  3066. } finally {
  3067. //
  3068. // always report a volume failure
  3069. //
  3070. TempStatus = SrNotifyVolumeError( pExtension,
  3071. pOriginalFileName,
  3072. STATUS_UNEXPECTED_IO_ERROR,
  3073. SrEventStreamOverwrite );
  3074. if (NT_SUCCESS(TempStatus) == FALSE && NT_SUCCESS(Status))
  3075. {
  3076. //
  3077. // only return this if we are not hiding some existing error
  3078. // status code
  3079. //
  3080. Status = TempStatus;
  3081. }
  3082. SrReleaseActivityLock( pExtension );
  3083. if (FileHandle != NULL)
  3084. {
  3085. ZwClose(FileHandle);
  3086. FileHandle = NULL;
  3087. }
  3088. }
  3089. RETURN(Status);
  3090. } // SrFixOverwriteFailure
  3091. VOID
  3092. SrFreeTriggerItem(
  3093. IN PSR_TRIGGER_ITEM pItem
  3094. )
  3095. {
  3096. PAGED_CODE();
  3097. ASSERT(IS_VALID_TRIGGER_ITEM(pItem));
  3098. if (pItem->FreeDirectoryName && pItem->pDirectoryName != NULL)
  3099. {
  3100. SrFreeFileNameBuffer(pItem->pDirectoryName);
  3101. pItem->pDirectoryName = NULL;
  3102. }
  3103. if (pItem->pFileEntry != NULL)
  3104. {
  3105. SR_FREE_POOL(pItem->pFileEntry, SR_FILE_ENTRY_TAG);
  3106. pItem->pFileEntry = NULL;
  3107. }
  3108. if (pItem->pDirectoryObject != NULL)
  3109. {
  3110. ObDereferenceObject(pItem->pDirectoryObject);
  3111. pItem->pDirectoryObject = NULL;
  3112. }
  3113. if (pItem->DirectoryHandle != NULL)
  3114. {
  3115. ZwClose(pItem->DirectoryHandle);
  3116. pItem->DirectoryHandle = NULL;
  3117. }
  3118. SR_FREE_POOL_WITH_SIG(pItem, SR_TRIGGER_ITEM_TAG);
  3119. } // SrFreeTriggerItem