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.

958 lines
26 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. fsascan.cpp
  5. Abstract:
  6. This class represents a scanning process that is being carried out upon one FsaResource.
  7. Author:
  8. Chuck Bardeen [cbardeen] 16-Feb-1997
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "wsb.h"
  13. #include "fsa.h"
  14. #include "job.h"
  15. #include "hsmscan.h"
  16. #define WSB_TRACE_IS WSB_TRACE_BIT_JOB
  17. DWORD HsmStartScanner(
  18. void* pVoid
  19. )
  20. /*++
  21. --*/
  22. {
  23. return(((CHsmScanner*) pVoid)->StartScan());
  24. }
  25. HRESULT
  26. CHsmScanner::Cancel(
  27. HSM_JOB_EVENT event
  28. )
  29. /*++
  30. Implements:
  31. IHsmScanner::Cancel().
  32. --*/
  33. {
  34. HRESULT hr = S_OK;
  35. try {
  36. // If we have started, but haven't finished, then change the state of the job. The thread
  37. // will exit on it's own.
  38. if ((HSM_JOB_STATE_IDLE != m_state) &&
  39. (HSM_JOB_STATE_DONE != m_state) &&
  40. (HSM_JOB_STATE_FAILED != m_state) &&
  41. (HSM_JOB_STATE_CANCELLED != m_state)) {
  42. if (HSM_JOB_EVENT_CANCEL == event) {
  43. WsbAffirmHr(SetState(HSM_JOB_STATE_CANCELLED));
  44. } else if (HSM_JOB_EVENT_SUSPEND == event) {
  45. WsbAffirmHr(SetState(HSM_JOB_STATE_SUSPENDED));
  46. } else if (HSM_JOB_EVENT_FAIL == event) {
  47. WsbAffirmHr(SetState(HSM_JOB_STATE_FAILED));
  48. } else {
  49. WsbAssert(FALSE, E_UNEXPECTED);
  50. }
  51. }
  52. } WsbCatch(hr);
  53. return(hr);
  54. }
  55. HRESULT
  56. CHsmScanner::DoIfMatches(
  57. IN IFsaScanItem* pScanItem
  58. )
  59. /*++
  60. Implements:
  61. IHsmScanner::DoIfMatches().
  62. --*/
  63. {
  64. HRESULT hr = S_OK;
  65. HRESULT hrDo = S_OK;
  66. HRESULT hrShould = S_OK;
  67. BOOL notMatched = TRUE;
  68. BOOL shouldDo = FALSE;
  69. CComPtr<IHsmRuleStack> pRuleStack;
  70. WsbTraceIn(OLESTR("CFsaScanner::DoIfMatches"), OLESTR(""));
  71. try {
  72. // Each policy has it's own rule stack, check each one of until a match is found (if
  73. // one exists).
  74. WsbAffirmHr(m_pEnumStacks->First(IID_IHsmRuleStack, (void**) &pRuleStack));
  75. while (notMatched) {
  76. hr = pRuleStack->DoesMatch(pScanItem, &shouldDo);
  77. if (S_OK == hr) {
  78. notMatched = FALSE;
  79. if (!shouldDo) {
  80. hrShould = JOB_E_FILEEXCLUDED;
  81. }
  82. } else if (S_FALSE == hr) {
  83. pRuleStack = 0;
  84. WsbAffirmHr(m_pEnumStacks->Next(IID_IHsmRuleStack, (void**) &pRuleStack));
  85. } else {
  86. // Something totally unexpected happened so we'd better quit
  87. WsbThrow(hr);
  88. }
  89. }
  90. } WsbCatchAndDo(hr,
  91. if (WSB_E_NOTFOUND == hr) {
  92. hrShould = JOB_E_DOESNTMATCH;
  93. hr = S_OK;
  94. } else {
  95. hrShould = hr;
  96. }
  97. );
  98. // Just Do It!!
  99. if (SUCCEEDED(hr) && shouldDo) {
  100. hrDo = pRuleStack->Do(pScanItem);
  101. // Tell the session if we ended up skipping the file or not.
  102. m_pSession->ProcessItem(HSM_JOB_PHASE_SCAN, HSM_JOB_ACTION_SCAN, pScanItem, hrDo);
  103. } else {
  104. // Tell the session if we decided to skip the file.
  105. m_pSession->ProcessItem(HSM_JOB_PHASE_SCAN, HSM_JOB_ACTION_SCAN, pScanItem, hrShould);
  106. }
  107. WsbTraceOut(OLESTR("CFsaScanner::DoIfMatches"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  108. return(hr);
  109. }
  110. #pragma optimize("g", off)
  111. HRESULT
  112. CHsmScanner::FinalConstruct(
  113. void
  114. )
  115. /*++
  116. Implements:
  117. CComObjectRoot::FinalConstruct().
  118. --*/
  119. {
  120. HRESULT hr = S_OK;
  121. try {
  122. WsbAffirmHr(CComObjectRoot::FinalConstruct());
  123. m_state = HSM_JOB_STATE_IDLE;
  124. m_priority = HSM_JOB_PRIORITY_NORMAL;
  125. m_threadHandle = 0;
  126. m_threadId = 0;
  127. m_threadHr = S_OK;
  128. m_eventCookie = 0;
  129. m_skipHiddenItems = TRUE;
  130. m_skipSystemItems = TRUE;
  131. m_useRPIndex = FALSE;
  132. m_useDbIndex = FALSE;
  133. m_event = 0;
  134. // Create a collection for the rule stacks, and store an enumerator to it.
  135. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_ALL, IID_IWsbCollection, (void**) &m_pRuleStacks));
  136. WsbAffirmHr(m_pRuleStacks->Enum(&m_pEnumStacks));
  137. } WsbCatch(hr);
  138. return(hr);
  139. }
  140. #pragma optimize("", on)
  141. void
  142. CHsmScanner::FinalRelease(
  143. void
  144. )
  145. /*++
  146. Implements:
  147. CComObjectRoot::FinalRelease().
  148. --*/
  149. {
  150. HRESULT hr = S_OK;
  151. // Cleanup the thread we were using.
  152. if (m_threadHandle != 0) {
  153. m_state = HSM_JOB_STATE_DONE;
  154. if (0 != m_event) {
  155. SetEvent(m_event);
  156. }
  157. // Should we wait for the thread to end?
  158. CloseHandle(m_threadHandle);
  159. m_threadHandle = 0;
  160. }
  161. if (m_event) {
  162. CloseHandle(m_event);
  163. m_event = 0;
  164. }
  165. CComObjectRoot::FinalRelease();
  166. }
  167. HRESULT
  168. CHsmScanner::LowerPriority(
  169. void
  170. )
  171. /*++
  172. --*/
  173. {
  174. HRESULT hr = S_OK;
  175. try {
  176. WsbAssert(0 != m_threadHandle, E_UNEXPECTED);
  177. WsbAssert(m_pSession != 0, E_UNEXPECTED);
  178. switch(m_priority) {
  179. case HSM_JOB_PRIORITY_IDLE:
  180. WsbAffirm(FALSE, E_UNEXPECTED);
  181. break;
  182. case HSM_JOB_PRIORITY_LOWEST:
  183. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_IDLE));
  184. m_priority = HSM_JOB_PRIORITY_IDLE;
  185. break;
  186. case HSM_JOB_PRIORITY_LOW:
  187. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_LOWEST));
  188. m_priority = HSM_JOB_PRIORITY_LOWEST;
  189. break;
  190. case HSM_JOB_PRIORITY_NORMAL:
  191. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_BELOW_NORMAL));
  192. m_priority = HSM_JOB_PRIORITY_LOW;
  193. break;
  194. case HSM_JOB_PRIORITY_HIGH:
  195. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_NORMAL));
  196. m_priority = HSM_JOB_PRIORITY_NORMAL;
  197. break;
  198. case HSM_JOB_PRIORITY_HIGHEST:
  199. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_ABOVE_NORMAL));
  200. m_priority = HSM_JOB_PRIORITY_HIGH;
  201. break;
  202. default:
  203. case HSM_JOB_PRIORITY_CRITICAL:
  204. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_HIGHEST));
  205. m_priority = HSM_JOB_PRIORITY_HIGHEST;
  206. break;
  207. }
  208. WsbAffirmHr(m_pSession->ProcessPriority(HSM_JOB_PHASE_SCAN, m_priority));
  209. } WsbCatch(hr);
  210. return(hr);
  211. }
  212. HRESULT
  213. CHsmScanner::Pause(
  214. void
  215. )
  216. /*++
  217. Implements:
  218. IHsmScanner::Pause().
  219. --*/
  220. {
  221. HRESULT hr = S_OK;
  222. WsbTraceIn(OLESTR("CFsaScanner::Pause"), OLESTR(""));
  223. // Lock();
  224. try {
  225. // If we are running, then suspend the thread.
  226. WsbAssert((HSM_JOB_STATE_STARTING == m_state) || (HSM_JOB_STATE_ACTIVE == m_state)
  227. || (HSM_JOB_STATE_RESUMING == m_state), E_UNEXPECTED);
  228. // Set state to pausing -- the thread will pause itself when it
  229. // sees the state
  230. WsbAffirmHr(SetState(HSM_JOB_STATE_PAUSING));
  231. } WsbCatch(hr);
  232. // Unlock();
  233. WsbTraceOut(OLESTR("CFsaScanner::Pause"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  234. return(hr);
  235. }
  236. HRESULT
  237. CHsmScanner::PopRules(
  238. IN OLECHAR* path
  239. )
  240. /*++
  241. --*/
  242. {
  243. HRESULT hr = S_OK;
  244. CComPtr<IHsmRuleStack> pRuleStack;
  245. try {
  246. // Each policy has it's own rule stack, and each of them will need to have rules removed
  247. // from it for this directory (if any rules were added).
  248. for (hr = m_pEnumStacks->First(IID_IHsmRuleStack, (void**) &pRuleStack);
  249. SUCCEEDED(hr);
  250. hr = m_pEnumStacks->Next(IID_IHsmRuleStack, (void**) &pRuleStack)) {
  251. WsbAffirmHr(pRuleStack->Pop(path));
  252. pRuleStack = 0;
  253. }
  254. if (WSB_E_NOTFOUND == hr) {
  255. hr = S_OK;
  256. }
  257. } WsbCatch(hr);
  258. return(hr);
  259. }
  260. HRESULT
  261. CHsmScanner::ProcessSessionEvent(
  262. IN IHsmSession* pSession,
  263. IN HSM_JOB_PHASE phase,
  264. IN HSM_JOB_EVENT event
  265. )
  266. /*++
  267. --*/
  268. {
  269. HRESULT hr = S_OK;
  270. try {
  271. WsbAssert(0 != pSession, E_POINTER);
  272. // If the phase applies to use (SCAN or ALL), then do any work required by the
  273. // event.
  274. if ((HSM_JOB_PHASE_ALL == phase) || (HSM_JOB_PHASE_SCAN == phase)) {
  275. switch(event) {
  276. case HSM_JOB_EVENT_SUSPEND:
  277. case HSM_JOB_EVENT_CANCEL:
  278. case HSM_JOB_EVENT_FAIL:
  279. WsbAffirmHr(Cancel(event));
  280. break;
  281. case HSM_JOB_EVENT_PAUSE:
  282. WsbAffirmHr(Pause());
  283. break;
  284. case HSM_JOB_EVENT_RESUME:
  285. WsbAffirmHr(Resume());
  286. break;
  287. case HSM_JOB_EVENT_RAISE_PRIORITY:
  288. WsbAffirmHr(RaisePriority());
  289. break;
  290. case HSM_JOB_EVENT_LOWER_PRIORITY:
  291. WsbAffirmHr(LowerPriority());
  292. break;
  293. default:
  294. case HSM_JOB_EVENT_START:
  295. WsbAssert(FALSE, E_UNEXPECTED);
  296. break;
  297. }
  298. }
  299. } WsbCatch(hr);
  300. return(S_OK);
  301. }
  302. HRESULT
  303. CHsmScanner::PushRules(
  304. IN OLECHAR* path
  305. )
  306. /*++
  307. --*/
  308. {
  309. HRESULT hr = S_OK;
  310. CComPtr<IHsmRuleStack> pRuleStack;
  311. try {
  312. // Save an indicator to where we are in the scan, so we can use it if we are interrupted
  313. // or need to give an indication to the session.
  314. m_currentPath = path;
  315. // Each policy has it's own rule stack, and each of them will need to have rules added
  316. // for this directory (if any rules exist).
  317. for (hr = m_pEnumStacks->First(IID_IHsmRuleStack, (void**) &pRuleStack);
  318. SUCCEEDED(hr);
  319. hr = m_pEnumStacks->Next(IID_IHsmRuleStack, (void**) &pRuleStack)) {
  320. WsbAffirmHr(pRuleStack->Push(path));
  321. pRuleStack = 0;
  322. }
  323. if (WSB_E_NOTFOUND == hr) {
  324. hr = S_OK;
  325. }
  326. } WsbCatch(hr);
  327. return(hr);
  328. }
  329. HRESULT
  330. CHsmScanner::RaisePriority(
  331. void
  332. )
  333. /*++
  334. --*/
  335. {
  336. HRESULT hr = S_OK;
  337. try {
  338. WsbAssert(0 != m_threadHandle, E_UNEXPECTED);
  339. WsbAssert(m_pSession != 0, E_UNEXPECTED);
  340. switch(m_priority) {
  341. case HSM_JOB_PRIORITY_IDLE:
  342. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_LOWEST));
  343. m_priority = HSM_JOB_PRIORITY_LOWEST;
  344. break;
  345. case HSM_JOB_PRIORITY_LOWEST:
  346. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_BELOW_NORMAL));
  347. m_priority = HSM_JOB_PRIORITY_LOW;
  348. break;
  349. case HSM_JOB_PRIORITY_LOW:
  350. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_NORMAL));
  351. m_priority = HSM_JOB_PRIORITY_NORMAL;
  352. break;
  353. case HSM_JOB_PRIORITY_NORMAL:
  354. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_ABOVE_NORMAL));
  355. m_priority = HSM_JOB_PRIORITY_HIGH;
  356. break;
  357. case HSM_JOB_PRIORITY_HIGH:
  358. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_HIGHEST));
  359. m_priority = HSM_JOB_PRIORITY_HIGHEST;
  360. break;
  361. case HSM_JOB_PRIORITY_HIGHEST:
  362. WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_TIME_CRITICAL));
  363. m_priority = HSM_JOB_PRIORITY_CRITICAL;
  364. break;
  365. default:
  366. case HSM_JOB_PRIORITY_CRITICAL:
  367. WsbAffirm(FALSE, E_UNEXPECTED);
  368. break;
  369. }
  370. WsbAffirmHr(m_pSession->ProcessPriority(HSM_JOB_PHASE_SCAN, m_priority));
  371. } WsbCatch(hr);
  372. return(hr);
  373. }
  374. HRESULT
  375. CHsmScanner::Resume(
  376. void
  377. )
  378. /*++
  379. Implements:
  380. IHsmScanner::Resume().
  381. --*/
  382. {
  383. HRESULT hr = S_OK;
  384. HSM_JOB_STATE oldState;
  385. WsbTraceIn(OLESTR("CFsaScanner::Resume"), OLESTR(""));
  386. // Lock();
  387. try {
  388. // If we are paused, then suspend the thread.
  389. WsbAffirm((HSM_JOB_STATE_PAUSING == m_state) || (HSM_JOB_STATE_PAUSED == m_state), E_UNEXPECTED);
  390. oldState = m_state;
  391. WsbAffirmHr(SetState(HSM_JOB_STATE_RESUMING));
  392. // If we are unable to resume, then return to the former state.
  393. try {
  394. WsbAffirm(SetEvent(m_event), HRESULT_FROM_WIN32(GetLastError()));
  395. } WsbCatchAndDo(hr, SetState(oldState););
  396. } WsbCatch(hr);
  397. // Unlock();
  398. WsbTraceOut(OLESTR("CFsaScanner::Resume"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  399. return(hr);
  400. }
  401. HRESULT
  402. CHsmScanner::ScanPath(
  403. IN OLECHAR* dirPath
  404. )
  405. /*++
  406. --*/
  407. {
  408. HRESULT hr = S_OK;
  409. CComPtr<IFsaScanItem> pScanItem;
  410. CWsbStringPtr searchPath;
  411. WsbTraceIn(OLESTR("CFsaScanner::ScanPath"), OLESTR("%ls"), WsbAbbreviatePath(dirPath, WSB_TRACE_BUFF_SIZE));
  412. try {
  413. WsbAssert(0 != dirPath, E_POINTER);
  414. WsbAssert(0 != dirPath[0], E_INVALIDARG);
  415. // Pop the rules for this files. This sets the context for the scan to follow.
  416. WsbAffirmHr(PushRules(dirPath));
  417. try {
  418. // Iterate over all the files and directories in the specified path.
  419. searchPath = dirPath;
  420. if (searchPath[(int) (wcslen(searchPath) - 1)] == L'\\') {
  421. WsbAffirmHr(searchPath.Append("*"));
  422. } else {
  423. WsbAffirmHr(searchPath.Append("\\*"));
  424. }
  425. if (m_useDbIndex) {
  426. hr = m_pResource->FindFirstInDbIndex(m_pSession, &pScanItem);
  427. } else if (m_useRPIndex) {
  428. hr = m_pResource->FindFirstInRPIndex(m_pSession, &pScanItem);
  429. } else {
  430. hr = m_pResource->FindFirst(searchPath, m_pSession, &pScanItem);
  431. }
  432. while (SUCCEEDED(hr) && ((HSM_JOB_STATE_ACTIVE == m_state) ||
  433. (HSM_JOB_STATE_RESUMING == m_state) ||
  434. (HSM_JOB_STATE_PAUSING == m_state))) {
  435. // Check for a pause request
  436. // Lock();
  437. if (HSM_JOB_STATE_PAUSING == m_state) {
  438. hr = SetState(HSM_JOB_STATE_PAUSED);
  439. // Unlock();
  440. WsbAffirmHr(hr);
  441. // Suspend the thread here & wait for resume signal
  442. WsbTrace(OLESTR("CHsmScanner::ScanPath: pausing\n"));
  443. WaitForSingleObject(m_event, 0xffffffff);
  444. WsbTrace(OLESTR("CHsmScanner::ScanPath: woke up, state = %d\n"),
  445. (int)m_state);
  446. // Lock();
  447. if (HSM_JOB_STATE_RESUMING != m_state) {
  448. // Unlock();
  449. break;
  450. }
  451. hr = SetState(HSM_JOB_STATE_ACTIVE);
  452. if (S_OK != hr) {
  453. // Unlock();
  454. WsbThrow(hr);
  455. }
  456. }
  457. // Unlock();
  458. // Skip hidden and/or system items if so configured.
  459. if (!((m_skipHiddenItems && (pScanItem->IsHidden() == S_OK)) ||
  460. (m_skipSystemItems && (pScanItem->IsSystem() == S_OK)))) {
  461. // Ignore ".", "..", symbolic links and mount points.
  462. if ((pScanItem->IsARelativeParent() == S_FALSE) &&
  463. (pScanItem->IsALink() == S_FALSE)) {
  464. // Recursively scan subdirectories.
  465. if (pScanItem->IsAParent() == S_OK) {
  466. WsbAffirmHr(pScanItem->GetPathAndName(OLESTR(""), &searchPath, 0));
  467. WsbAffirmHr(ScanPath(searchPath));
  468. }
  469. // If this file matches a policy then perform the action.
  470. else {
  471. WsbAffirmHr(DoIfMatches(pScanItem));
  472. }
  473. } else {
  474. WsbTrace(OLESTR("CHsmScanner::ScanPath skipping - symbolic link, '.', or '..'\n"));
  475. }
  476. } else {
  477. WsbTrace(OLESTR("CHsmScanner::ScanPath skipping - hidden/system\n"));
  478. }
  479. if (m_useDbIndex) {
  480. hr = m_pResource->FindNextInDbIndex(pScanItem);
  481. } else if (m_useRPIndex) {
  482. hr = m_pResource->FindNextInRPIndex(pScanItem);
  483. } else {
  484. hr = m_pResource->FindNext(pScanItem);
  485. }
  486. }
  487. // If we broke out as a result of end of scan or some other error ...
  488. if (hr != S_OK) {
  489. WsbAssert(hr == WSB_E_NOTFOUND, hr);
  490. hr = S_OK;
  491. }
  492. } WsbCatch(hr);
  493. // Pop the rules for this directory. This restores the context as we pop back up the directory
  494. // structure.
  495. WsbAffirmHr(PopRules(dirPath));
  496. } WsbCatchAndDo(hr, if (JOB_E_DIREXCLUDED == hr) {hr = S_OK;});
  497. WsbTraceOut(OLESTR("CFsaScanner::ScanPath"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  498. return(hr);
  499. }
  500. HRESULT
  501. CHsmScanner::SetState(
  502. IN HSM_JOB_STATE state
  503. )
  504. /*++
  505. --*/
  506. {
  507. HRESULT hr = S_OK;
  508. BOOL bLog = TRUE;
  509. WsbTraceIn(OLESTR("CFsaScanner::SetState"), OLESTR("old state = %d, new state = %d"),
  510. (int)m_state, (int)state);
  511. // Lock();
  512. try {
  513. // Change the state and report the change to the session.
  514. m_state = state;
  515. WsbAffirmHr(m_pSession->ProcessState(HSM_JOB_PHASE_SCAN, m_state, m_currentPath, bLog));
  516. } WsbCatch(hr);
  517. // Unlock();
  518. WsbTraceOut(OLESTR("CFsaScanner::SetState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  519. return(hr);
  520. }
  521. HRESULT
  522. CHsmScanner::Start(
  523. IN IHsmSession* pSession,
  524. IN OLECHAR* path
  525. )
  526. /*++
  527. Implements:
  528. IHsmScanner::Start().
  529. --*/
  530. {
  531. HRESULT hr = S_OK;
  532. CComPtr<IHsmJobDef> pDef;
  533. CComPtr<IHsmPolicy> pPolicy;
  534. CComPtr<IHsmRuleStack> pRuleStack;
  535. CComPtr<IWsbEnum> pEnumPolicies;
  536. CComPtr<IConnectionPointContainer> pCPC;
  537. CComPtr<IConnectionPoint> pCP;
  538. CComPtr<IHsmSessionSinkEveryEvent> pSink;
  539. DWORD cookie;
  540. try {
  541. // Make sure that we were given a session, and that we haven't started already.
  542. WsbAssert(0 != pSession, E_POINTER);
  543. WsbAssert(HSM_JOB_STATE_IDLE == m_state, E_UNEXPECTED);
  544. // Store off the session.
  545. m_pSession = pSession;
  546. // If no directory was specified, then start in the root of the resource.
  547. if ((0 != path) && (0 != *path)) {
  548. m_startingPath = path;
  549. } else {
  550. m_startingPath = OLESTR("\\");
  551. }
  552. m_currentPath = m_startingPath;
  553. // Tell them we are starting.
  554. WsbAffirmHr(SetState(HSM_JOB_STATE_STARTING));
  555. // Create an event to control pause/resume for the scan.
  556. if (0 == m_event) {
  557. CWsbStringPtr nameString;
  558. GUID id;
  559. WsbAffirmHr(m_pSession->GetIdentifier(&id));
  560. nameString = id;
  561. nameString.Prepend(OLESTR("Scanner Pause and Resume Event for session "));
  562. m_event = CreateEvent(NULL, FALSE, FALSE, nameString);
  563. }
  564. // Ask the session to advise of every event.
  565. WsbAffirmHr(pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
  566. WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryEvent, &pCP));
  567. WsbAffirmHr(((IUnknown*) (IHsmScanner*) this)->QueryInterface(IID_IHsmSessionSinkEveryEvent, (void**) &pSink));
  568. WsbAffirmHr(pCP->Advise(pSink, &cookie));
  569. // Store off the information needed to latter unadvise.
  570. m_eventCookie = cookie;
  571. try {
  572. // Locate the resource that is being scanned.
  573. WsbAffirmHr(m_pSession->GetResource(&m_pResource));
  574. // Create and initialize a rule stack for each policy.
  575. WsbAffirmHr(pSession->GetJob(&m_pJob));
  576. WsbAffirmHr(m_pJob->GetDef(&pDef));
  577. WsbAffirmHr(pDef->EnumPolicies(&pEnumPolicies));
  578. for (hr = pEnumPolicies->First(IID_IHsmPolicy, (void**) &pPolicy);
  579. SUCCEEDED(hr);
  580. hr = pEnumPolicies->Next(IID_IHsmPolicy, (void**) &pPolicy)) {
  581. WsbAffirmHr(CoCreateInstance(CLSID_CHsmRuleStack, NULL, CLSCTX_ALL, IID_IHsmRuleStack, (void**) &pRuleStack));
  582. WsbAffirmHr(pRuleStack->Init(pPolicy, m_pResource));
  583. WsbAffirmHr(m_pRuleStacks->Add(pRuleStack));
  584. pRuleStack = 0;
  585. pPolicy = 0;
  586. }
  587. if (WSB_E_NOTFOUND == hr) {
  588. hr = S_OK;
  589. }
  590. // Determine whether hidden and system items should be skipped?
  591. if (pDef->SkipHiddenItems() == S_FALSE) {
  592. m_skipHiddenItems = FALSE;
  593. }
  594. if (pDef->SkipSystemItems() == S_FALSE) {
  595. m_skipSystemItems = FALSE;
  596. }
  597. // Determine whether to use the Reparse Point Index for the scan?
  598. if (pDef->UseRPIndex() == S_OK) {
  599. m_useRPIndex = TRUE;
  600. }
  601. // Determine whether to use the Database Index for the scan?
  602. if (pDef->UseDbIndex() == S_OK) {
  603. m_useDbIndex = TRUE;
  604. }
  605. try {
  606. // Now that we have prepared, create the thread that will do the scanning!
  607. WsbAffirm((m_threadHandle = CreateThread(0, 0, HsmStartScanner, (void*) this, 0, &m_threadId)) != 0, HRESULT_FROM_WIN32(GetLastError()));
  608. } WsbCatchAndDo(hr, SetState(HSM_JOB_STATE_FAILED););
  609. if (FAILED(hr)) {
  610. WsbThrow(hr);
  611. }
  612. } WsbCatchAndDo(hr,
  613. pCP->Unadvise(m_eventCookie);
  614. m_eventCookie = 0;
  615. );
  616. } WsbCatch(hr);
  617. return(hr);
  618. }
  619. HRESULT
  620. CHsmScanner::StartScan(
  621. void
  622. )
  623. /*++
  624. --*/
  625. {
  626. HRESULT hr = S_OK;
  627. HRESULT hr2 = S_OK;
  628. CComPtr<IConnectionPointContainer> pCPC;
  629. CComPtr<IConnectionPoint> pCP;
  630. WsbTraceIn(OLESTR("CFsaScanner::StartScan"), OLESTR(""));
  631. try {
  632. CComPtr<IFsaTruncator> pTruncator;
  633. CComPtr<IHsmSession> pTruncatorSession;
  634. CComPtr<IHsmJobDef> pDef;
  635. CComPtr<IHsmActionOnResourcePreScan> pActionPreScan;
  636. // The thread is running.
  637. WsbAffirmHr(SetState(HSM_JOB_STATE_ACTIVE));
  638. // To avoid having the RP Index order changed by the truncator,
  639. // we pause the truncator
  640. if (m_useRPIndex) {
  641. WsbAffirmHr(m_pResource->GetTruncator(&pTruncator));
  642. if (pTruncator) {
  643. WsbAffirmHr(pTruncator->GetSession(&pTruncatorSession));
  644. if (pTruncatorSession) {
  645. WsbAffirmHr(pTruncatorSession->ProcessEvent(HSM_JOB_PHASE_ALL,
  646. HSM_JOB_EVENT_PAUSE));
  647. }
  648. }
  649. }
  650. // Get the pre-scan action and do it (if exists)
  651. WsbAffirmHr(m_pJob->GetDef(&pDef));
  652. WsbAffirmHr(pDef->GetPreScanActionOnResource(&pActionPreScan));
  653. if (pActionPreScan) {
  654. WsbTrace(OLESTR("CHsmScanner::StartScan: doing pre-scan action\n"));
  655. //Don't throw hr - we need the cleanup code that is done after the scanning
  656. hr = pActionPreScan->Do(m_pResource, m_pSession);
  657. }
  658. // Start with the first path and scan the resource (only if pre-scan succeeded)
  659. if (SUCCEEDED(hr)) {
  660. m_threadHr = ScanPath(m_startingPath);
  661. }
  662. // Resume the truncator if we paused it
  663. if (pTruncatorSession) {
  664. pTruncatorSession->ProcessEvent(HSM_JOB_PHASE_ALL,
  665. HSM_JOB_EVENT_RESUME);
  666. }
  667. // Clear out the information about the thread;
  668. WsbAffirmStatus(CloseHandle(m_threadHandle));
  669. m_threadId = 0;
  670. m_threadHandle = 0;
  671. } WsbCatch(hr);
  672. // The thread is exiting, so record
  673. if (FAILED(hr) || FAILED(m_threadHr)) {
  674. hr2 = SetState(HSM_JOB_STATE_FAILED);
  675. if (FAILED(hr2)) {
  676. m_pSession->ProcessHr(HSM_JOB_PHASE_ALL, __FILE__, __LINE__, hr2);
  677. }
  678. } else {
  679. hr2 = SetState(HSM_JOB_STATE_DONE);
  680. if (FAILED(hr2)) {
  681. m_pSession->ProcessHr(HSM_JOB_PHASE_ALL, __FILE__, __LINE__, hr2);
  682. }
  683. }
  684. // Regardless of how this thread is exiting, we need to unadvise from the session.
  685. // Indicate that we no longer want to be advised of events.
  686. if ((m_pSession != 0) && (m_eventCookie != 0)) {
  687. try {
  688. WsbAffirmHr(m_pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
  689. WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryEvent, &pCP));
  690. pCP->Unadvise(m_eventCookie);
  691. } WsbCatch(hr);
  692. }
  693. WsbTraceOut(OLESTR("CFsaScanner::StartScan"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  694. return(hr);
  695. }