Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1184 lines
28 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. hsmrule.cpp
  5. Abstract:
  6. This component represents a rule for a job's policy.
  7. Author:
  8. Chuck Bardeen [cbardeen] 29-Oct-1996
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "wsb.h"
  13. #include "job.h"
  14. #include "hsmrule.h"
  15. #define WSB_TRACE_IS WSB_TRACE_BIT_JOB
  16. // These are defined in nt.h, but it takes all sorts of grief to try to include them. Since
  17. // they are just used internally, it isn't even inportant that we have the same definitions.
  18. #if !defined(DOS_STAR)
  19. #define DOS_STAR (L'<')
  20. #endif
  21. #if !defined(DOS_QM)
  22. #define DOS_QM (L'>')
  23. #endif
  24. #if !defined(DOS_DOT)
  25. #define DOS_DOT (L'"')
  26. #endif
  27. HRESULT
  28. CHsmRule::CompareTo(
  29. IN IUnknown* pUnknown,
  30. OUT SHORT* pResult
  31. )
  32. /*++
  33. Implements:
  34. IWsbCollectable::CompareTo().
  35. --*/
  36. {
  37. HRESULT hr = S_OK;
  38. CComPtr<IHsmRule> pRule;
  39. WsbTraceIn(OLESTR("CHsmRule::CompareTo"), OLESTR(""));
  40. try {
  41. // Did they give us a valid item to compare to?
  42. WsbAssert(0 != pUnknown, E_POINTER);
  43. // We need the IWsbBool interface to get the value of the object.
  44. WsbAffirmHr(pUnknown->QueryInterface(IID_IHsmRule, (void**) &pRule));
  45. // Compare the rules.
  46. hr = CompareToIRule(pRule, pResult);
  47. } WsbCatch(hr);
  48. WsbTraceOut(OLESTR("CHsmRule::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  49. return(hr);
  50. }
  51. HRESULT
  52. CHsmRule::CompareToIRule(
  53. IN IHsmRule* pRule,
  54. OUT SHORT* pResult
  55. )
  56. /*++
  57. Implements:
  58. IHsmRule::CompareToIRule().
  59. --*/
  60. {
  61. HRESULT hr = S_OK;
  62. OLECHAR* path = 0;
  63. OLECHAR* name = 0;
  64. WsbTraceIn(OLESTR("CHsmRule::CompareToIRule"), OLESTR(""));
  65. try {
  66. // Did they give us a valid item to compare to?
  67. WsbAssert(0 != pRule, E_POINTER);
  68. // Get the path and name.
  69. WsbAffirmHr(pRule->GetPath(&path, 0));
  70. WsbAffirmHr(pRule->GetName(&name, 0));
  71. // Compare to the path and name.
  72. hr = CompareToPathAndName(path, name, pResult);
  73. } WsbCatch(hr);
  74. if (0 != path) {
  75. WsbFree(path);
  76. }
  77. if (0 != name) {
  78. WsbFree(name);
  79. }
  80. WsbTraceOut(OLESTR("CHsmRule::CompareToIRule"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  81. return(hr);
  82. }
  83. HRESULT
  84. CHsmRule::CompareToPathAndName(
  85. IN OLECHAR* path,
  86. IN OLECHAR* name,
  87. OUT SHORT* pResult
  88. )
  89. /*++
  90. Implements:
  91. IHsmRule::CompareToPathAndName().
  92. --*/
  93. {
  94. HRESULT hr = S_OK;
  95. SHORT aResult = 0;
  96. WsbTraceIn(OLESTR("CHsmRule::CompareToPathAndName"), OLESTR("path = <%ls>, name = <%ls>"), path, name);
  97. try {
  98. // Compare the path.
  99. aResult = (SHORT)_wcsicmp(m_path, path);
  100. // Compare the name.
  101. if (0 == aResult) {
  102. aResult = (SHORT)_wcsicmp(m_name, name);
  103. }
  104. if (0 != aResult) {
  105. hr = S_FALSE;
  106. }
  107. if (0 != pResult) {
  108. *pResult = aResult;
  109. }
  110. } WsbCatch(hr);
  111. WsbTraceOut(OLESTR("CHsmRule::CompareToIRule"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  112. return(hr);
  113. }
  114. HRESULT
  115. CHsmRule::Criteria(
  116. OUT IWsbCollection** ppCriteria
  117. )
  118. /*++
  119. Implements:
  120. IHsmRule::Criteria().
  121. --*/
  122. {
  123. HRESULT hr = S_OK;
  124. try {
  125. WsbAssert(0 != ppCriteria, E_POINTER);
  126. *ppCriteria = m_pCriteria;
  127. m_pCriteria->AddRef();
  128. } WsbCatch(hr);
  129. return(hr);
  130. }
  131. HRESULT
  132. CHsmRule::DoesNameContainWildcards(
  133. OLECHAR* name
  134. )
  135. /*++
  136. Implements:
  137. IHsmRule::DoesNameContainWildcards().
  138. --*/
  139. {
  140. HRESULT hr = S_FALSE;
  141. try {
  142. WsbAssert(0 != name, E_POINTER);
  143. if (wcscspn(name, OLESTR("*?<>\"")) < wcslen(name)) {
  144. hr = S_OK;
  145. }
  146. } WsbCatch(hr);
  147. return(hr);
  148. }
  149. HRESULT
  150. CHsmRule::EnumCriteria(
  151. OUT IWsbEnum** ppEnum
  152. )
  153. /*++
  154. Implements:
  155. IHsmRule::EnumCriteria().
  156. --*/
  157. {
  158. HRESULT hr = S_OK;
  159. try {
  160. WsbAssert(0 != ppEnum, E_POINTER);
  161. WsbAffirmHr(m_pCriteria->Enum(ppEnum));
  162. } WsbCatch(hr);
  163. return(hr);
  164. }
  165. HRESULT
  166. CHsmRule::FinalConstruct(
  167. void
  168. )
  169. /*++
  170. Implements:
  171. CComObjectRoot::FinalConstruct().
  172. --*/
  173. {
  174. HRESULT hr = S_OK;
  175. try {
  176. WsbAffirmHr(CWsbObject::FinalConstruct());
  177. m_isInclude = TRUE;
  178. m_isUserDefined = TRUE;
  179. m_isUsedInSubDirs = TRUE;
  180. //Create the criteria collection.
  181. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_ALL, IID_IWsbCollection, (void**) &m_pCriteria));
  182. } WsbCatch(hr);
  183. return(hr);
  184. }
  185. HRESULT
  186. CHsmRule::GetClassID(
  187. OUT CLSID* pClsid
  188. )
  189. /*++
  190. Implements:
  191. IPersist::GetClassID().
  192. --*/
  193. {
  194. HRESULT hr = S_OK;
  195. WsbTraceIn(OLESTR("CHsmRule::GetClassID"), OLESTR(""));
  196. try {
  197. WsbAssert(0 != pClsid, E_POINTER);
  198. *pClsid = CLSID_CHsmRule;
  199. } WsbCatch(hr);
  200. WsbTraceOut(OLESTR("CHsmRule::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  201. return(hr);
  202. }
  203. HRESULT
  204. CHsmRule::GetName(
  205. OUT OLECHAR** pName,
  206. IN ULONG bufferSize
  207. )
  208. /*++
  209. Implements:
  210. IHsmRule::GetName().
  211. --*/
  212. {
  213. HRESULT hr = S_OK;
  214. try {
  215. WsbAssert(0 != pName, E_POINTER);
  216. WsbAffirmHr(m_name.CopyTo(pName, bufferSize));
  217. } WsbCatch(hr);
  218. return(hr);
  219. }
  220. HRESULT
  221. CHsmRule::GetPath(
  222. OUT OLECHAR** pPath,
  223. IN ULONG bufferSize
  224. )
  225. /*++
  226. Implements:
  227. IHsmRule::GetPath().
  228. --*/
  229. {
  230. HRESULT hr = S_OK;
  231. try {
  232. WsbAssert(0 != pPath, E_POINTER);
  233. WsbAffirmHr(m_path.CopyTo(pPath, bufferSize));
  234. } WsbCatch(hr);
  235. return(hr);
  236. }
  237. HRESULT
  238. CHsmRule::GetSearchName(
  239. OUT OLECHAR** pName,
  240. IN ULONG bufferSize
  241. )
  242. /*++
  243. Implements:
  244. IHsmRule::GetSearchName().
  245. --*/
  246. {
  247. HRESULT hr = S_OK;
  248. try {
  249. WsbAssert(0 != pName, E_POINTER);
  250. WsbAffirmHr(m_searchName.CopyTo(pName, bufferSize));
  251. } WsbCatch(hr);
  252. return(hr);
  253. }
  254. HRESULT
  255. CHsmRule::GetSizeMax(
  256. OUT ULARGE_INTEGER* pSize
  257. )
  258. /*++
  259. Implements:
  260. IPersistStream::GetSizeMax().
  261. --*/
  262. {
  263. HRESULT hr = S_OK;
  264. CComPtr<IPersistStream> pPersistStream;
  265. ULARGE_INTEGER entrySize;
  266. WsbTraceIn(OLESTR("CHsmRule::GetSizeMax"), OLESTR(""));
  267. try {
  268. WsbAssert(0 != pSize, E_POINTER);
  269. // Determine the size for a rule with no criteria.
  270. pSize->QuadPart = WsbPersistSize((wcslen(m_path) + 1) * sizeof(OLECHAR)) + WsbPersistSize((wcslen(m_name) + 1) * sizeof(OLECHAR)) + WsbPersistSize((wcslen(m_searchName) + 1) * sizeof(OLECHAR)) + 3 * WsbPersistSizeOf(BOOL) + WsbPersistSizeOf(ULONG);
  271. // Now allocate space for the criteria (assume they are all the
  272. // same size).
  273. WsbAffirmHr(m_pCriteria->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  274. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  275. pSize->QuadPart += entrySize.QuadPart;
  276. } WsbCatch(hr);
  277. WsbTraceOut(OLESTR("CHsmRule::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  278. return(hr);
  279. }
  280. HRESULT
  281. CHsmRule::IsUserDefined(
  282. void
  283. )
  284. /*++
  285. Implements:
  286. IHsmRule::IsUserDefined().
  287. --*/
  288. {
  289. HRESULT hr = S_OK;
  290. if (!m_isUserDefined) {
  291. hr = S_FALSE;
  292. }
  293. return(hr);
  294. }
  295. HRESULT
  296. CHsmRule::IsInclude(
  297. void
  298. )
  299. /*++
  300. Implements:
  301. IHsmRule::IsInclude().
  302. --*/
  303. {
  304. HRESULT hr = S_OK;
  305. if (!m_isInclude) {
  306. hr = S_FALSE;
  307. }
  308. return(hr);
  309. }
  310. HRESULT
  311. CHsmRule::IsNameInExpression(
  312. IN OLECHAR* expression,
  313. IN OLECHAR* name,
  314. IN BOOL ignoreCase
  315. )
  316. /*++
  317. Implements:
  318. CHsmRule::IsNameInExpression().
  319. --*/
  320. {
  321. HRESULT hr = S_FALSE;
  322. USHORT nameLength;
  323. USHORT expressionLength;
  324. WsbTraceIn(OLESTR("CHsmRule::IsNameInExpression"), OLESTR("expression = %ls, name = %ls, ignoreCase = %ls"), expression, name, WsbBoolAsString(ignoreCase));
  325. try {
  326. // This is algorithm is from FsRtlIsNameInExpressionPrivate(), but has been rewritten to fit
  327. // our coding standards, data structures, and to remove other dependencies on Rtl...() code.
  328. // The idea behind the algorithm is pretty simple. We keep track of
  329. // all possible locations in the regular expression that are matching
  330. // the name. If when the name has been exhausted one of the locations
  331. // in the expression is also just exhausted, the name is in the language
  332. // defined by the regular expression.
  333. WsbAssert(name != 0, E_POINTER);
  334. WsbAssert(expression != 0, E_POINTER);
  335. nameLength = (SHORT)wcslen(name);
  336. expressionLength = (SHORT)wcslen(expression);
  337. // If one string is empty return FALSE. If both are empty return TRUE.
  338. if ((nameLength == 0) && (expressionLength == 0)) {
  339. hr = S_OK;
  340. } else if ((nameLength != 0) && (expressionLength != 0)) {
  341. // Special case by far the most common wild card search of *
  342. if ((expressionLength == 1) && (expression[0] == L'*')) {
  343. hr = S_OK;
  344. }
  345. // Also special case expressions of the form *X. With this and the prior
  346. // case we have covered virtually all normal queries.
  347. else if (expression[0] == L'*') {
  348. // Only special case an expression with a single *
  349. if (DoesNameContainWildcards(&expression[1]) == S_FALSE) {
  350. // If the name is smaller than the expression, than it isn't a match. Otherwise,
  351. // we need to check.
  352. if (nameLength >= (expressionLength - 1)) {
  353. // Do a simple memory compare if case sensitive, otherwise
  354. // we have got to check this one character at a time.
  355. if (ignoreCase) {
  356. if (_wcsicmp(&expression[1], &name[nameLength - (expressionLength - 1)]) == 0) {
  357. hr = S_OK;
  358. }
  359. } else {
  360. if (wcscmp(&expression[1], &name[nameLength - (expressionLength - 1)]) == 0) {
  361. hr = S_OK;
  362. }
  363. }
  364. }
  365. }
  366. }
  367. else {
  368. // This is the general matching code. Since it is messy, it is put in its
  369. // own method.
  370. hr = IsNameInExpressionGuts(expression, expressionLength, name, nameLength, ignoreCase);
  371. }
  372. }
  373. } WsbCatch(hr);
  374. WsbTraceOut(OLESTR("CHsmRule::IsNameInExpression"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  375. return(hr);
  376. }
  377. HRESULT
  378. CHsmRule::IsNameInExpressionGuts(
  379. IN OLECHAR* expression,
  380. IN USHORT expressionLength,
  381. IN OLECHAR* name,
  382. IN USHORT nameLength,
  383. IN BOOL ignoreCase
  384. )
  385. /*++
  386. Implements:
  387. CHsmRule::IsNameInExpressionGuts().
  388. --*/
  389. {
  390. HRESULT hr = S_FALSE;
  391. USHORT nameOffset = 0;
  392. OLECHAR nameChar = '0';
  393. USHORT exprOffset = 0;
  394. OLECHAR exprChar;
  395. BOOL nameFinished = FALSE;
  396. ULONG srcCount;
  397. ULONG destCount;
  398. ULONG previousDestCount;
  399. ULONG matchesCount;
  400. USHORT* previousMatches = 0;
  401. USHORT* currentMatches = 0;
  402. USHORT maxState;
  403. USHORT currentState;
  404. // Walk through the name string, picking off characters. We go one
  405. // character beyond the end because some wild cards are able to match
  406. // zero characters beyond the end of the string.
  407. //
  408. // With each new name character we determine a new set of states that
  409. // match the name so far. We use two arrays that we swap back and forth
  410. // for this purpose. One array lists the possible expression states for
  411. // all name characters up to but not including the current one, and other
  412. // array is used to build up the list of states considering the current
  413. // name character as well. The arrays are then switched and the process
  414. // repeated.
  415. //
  416. // There is not a one-to-one correspondence between state number and
  417. // offset into the expression. This is evident from the NFAs in the
  418. // initial comment to this function. State numbering is not continuous.
  419. // This allows a simple conversion between state number and expression
  420. // offset. Each character in the expression can represent one or two
  421. // states. * and DOS_STAR generate two states: ExprOffset*2 and
  422. // ExprOffset*2 + 1. All other expreesion characters can produce only
  423. // a single state. Thus ExprOffset = State/2.
  424. //
  425. //
  426. // Here is a short description of the variables involved:
  427. //
  428. // nameOffset - The offset of the current name char being processed.
  429. // exprOffset - The offset of the current expression char being processed.
  430. //
  431. // srcCount - Prior match being investigated with current name char
  432. // previousDestCount - This is used to prevent entry duplication, see comment
  433. // previousMatches - Holds the previous set of matches (the Src array)
  434. //
  435. // destCount - Next location to put a match assuming current name char
  436. // currentMatches - Holds the current set of matches (the Dest array)
  437. //
  438. // nameFinished - Allows one more itteration through the Matches array
  439. // after the name is exhusted (to come *s for example)
  440. try {
  441. // Since you can get at most two matches per character in the expression, the
  442. // biggest arrays you will need is twice the expression length.
  443. currentMatches = (USHORT*)WsbAlloc(nameLength * 2 * expressionLength * sizeof(USHORT));
  444. WsbAffirm(0 != currentMatches, E_OUTOFMEMORY);
  445. previousMatches = (USHORT*)WsbAlloc(nameLength * 2 * expressionLength * sizeof(USHORT));
  446. WsbAffirm(0 != previousMatches, E_OUTOFMEMORY);
  447. previousMatches[0] = 0;
  448. matchesCount = 1;
  449. maxState = (USHORT)( expressionLength * 2 );
  450. while (!nameFinished) {
  451. if (nameOffset < nameLength) {
  452. nameChar = name[nameOffset];
  453. nameOffset++;
  454. } else {
  455. nameFinished = TRUE;
  456. // If we have already exhasted the expression, cool. Don't
  457. // continue.
  458. if (previousMatches[matchesCount - 1] == maxState) {
  459. break;
  460. }
  461. }
  462. // Now, for each of the previous stored expression matches, see what
  463. // we can do with this name character.
  464. srcCount = 0;
  465. destCount = 0;
  466. previousDestCount = 0;
  467. while (srcCount < matchesCount) {
  468. USHORT length;
  469. // We have to carry on our expression analysis as far as possible
  470. // for each character of name, so we loop here until the
  471. // expression stops matching. A clue here is that expression
  472. // cases that can match zero or more characters end with a
  473. // continue, while those that can accept only a single character
  474. // end with a break.
  475. exprOffset = (USHORT)( ( ( previousMatches[srcCount++] + 1 ) / 2 ) );
  476. length = 0;
  477. while (TRUE) {
  478. if (exprOffset == expressionLength) {
  479. break;
  480. }
  481. // The first time through the loop we don't want
  482. // to increment ExprOffset.
  483. exprOffset = (USHORT)( exprOffset + length );
  484. length = 1;
  485. currentState = (USHORT)( exprOffset * 2 );
  486. if (exprOffset == expressionLength) {
  487. currentMatches[destCount++] = maxState;
  488. break;
  489. }
  490. exprChar = expression[exprOffset];
  491. // * matches any character zero or more times.
  492. if (exprChar == L'*') {
  493. currentMatches[destCount++] = currentState;
  494. currentMatches[destCount++] = (USHORT)( currentState + 1 );
  495. continue;
  496. }
  497. // DOS_STAR matches any character except . zero or more times.
  498. if (exprChar == DOS_STAR) {
  499. BOOLEAN iCanEatADot = FALSE;
  500. // If we are at a period, determine if we are allowed to
  501. // consume it, ie. make sure it is not the last one.
  502. if (!nameFinished && (nameChar == '.')) {
  503. USHORT offset;
  504. for (offset = nameOffset; offset < nameLength; offset++) {
  505. if (name[offset] == L'.') {
  506. iCanEatADot = TRUE;
  507. break;
  508. }
  509. }
  510. }
  511. if (nameFinished || (nameChar != L'.') || iCanEatADot) {
  512. currentMatches[destCount++] = currentState;
  513. currentMatches[destCount++] = (USHORT)( currentState + 1 );
  514. continue;
  515. } else {
  516. // We are at a period. We can only match zero
  517. // characters (ie. the epsilon transition).
  518. currentMatches[destCount++] = (USHORT)( currentState + 1 );
  519. continue;
  520. }
  521. }
  522. // The following expreesion characters all match by consuming
  523. // a character, thus force the expression, and thus state
  524. // forward.
  525. currentState += 2;
  526. // DOS_QM is the most complicated. If the name is finished,
  527. // we can match zero characters. If this name is a '.', we
  528. // don't match, but look at the next expression. Otherwise
  529. // we match a single character.
  530. if (exprChar == DOS_QM) {
  531. if (nameFinished || (nameChar == L'.')) {
  532. continue;
  533. }
  534. currentMatches[destCount++] = currentState;
  535. break;
  536. }
  537. // A DOS_DOT can match either a period, or zero characters
  538. // beyond the end of name.
  539. if (exprChar == DOS_DOT) {
  540. if (nameFinished) {
  541. continue;
  542. }
  543. if (nameChar == L'.') {
  544. currentMatches[destCount++] = currentState;
  545. break;
  546. }
  547. }
  548. // From this point on a name character is required to even
  549. // continue, let alone make a match.
  550. if (nameFinished) {
  551. break;
  552. }
  553. // If this expression was a '?' we can match it once.
  554. if (exprChar == L'?') {
  555. currentMatches[destCount++] = currentState;
  556. break;
  557. }
  558. // Finally, check if the expression char matches the name char
  559. if (ignoreCase) {
  560. if (towlower(exprChar) == towlower(nameChar)) {
  561. currentMatches[destCount++] = currentState;
  562. break;
  563. }
  564. } else if (exprChar == nameChar) {
  565. currentMatches[destCount++] = currentState;
  566. break;
  567. }
  568. // The expression didn't match so go look at the next
  569. // previous match.
  570. break;
  571. }
  572. // Prevent duplication in the destination array.
  573. //
  574. // Each of the arrays is montonically increasing and non-
  575. // duplicating, thus we skip over any source element in the src
  576. // array if we just added the same element to the destination
  577. // array. This guarentees non-duplication in the dest. array.
  578. if ((srcCount < matchesCount) && (previousDestCount < destCount) ) {
  579. while (previousDestCount < destCount) {
  580. while (previousMatches[srcCount] < currentMatches[previousDestCount]) {
  581. srcCount += 1;
  582. }
  583. previousDestCount += 1;
  584. }
  585. }
  586. }
  587. // If we found no matches in the just finished itteration, it's time
  588. // to bail.
  589. if (destCount == 0) {
  590. WsbThrow(S_FALSE);
  591. }
  592. // Swap the meaning the two arrays
  593. {
  594. USHORT* tmp;
  595. tmp = previousMatches;
  596. previousMatches = currentMatches;
  597. currentMatches = tmp;
  598. }
  599. matchesCount = destCount;
  600. }
  601. currentState = previousMatches[matchesCount - 1];
  602. if (currentState == maxState) {
  603. hr = S_OK;
  604. }
  605. } WsbCatch(hr);
  606. // Free the matches buffers that we allocated previously.
  607. if (0 != currentMatches) {
  608. WsbFree(currentMatches);
  609. }
  610. if (0 != previousMatches) {
  611. WsbFree(previousMatches);
  612. }
  613. return(hr);
  614. }
  615. HRESULT
  616. CHsmRule::IsUsedInSubDirs(
  617. void
  618. )
  619. /*++
  620. Implements:
  621. IHsmRule::IsUsedInSubDirs().
  622. --*/
  623. {
  624. HRESULT hr = S_OK;
  625. if (!m_isUsedInSubDirs) {
  626. hr = S_FALSE;
  627. }
  628. return(hr);
  629. }
  630. HRESULT
  631. CHsmRule::Load(
  632. IN IStream* pStream
  633. )
  634. /*++
  635. Implements:
  636. IPersistStream::Load().
  637. --*/
  638. {
  639. HRESULT hr = S_OK;
  640. CComPtr<IPersistStream> pPersistStream;
  641. CComPtr<IWsbCollectable> pCollectable;
  642. WsbTraceIn(OLESTR("CHsmRule::Load"), OLESTR(""));
  643. try {
  644. WsbAssert(0 != pStream, E_POINTER);
  645. // Do the easy stuff, but make sure that this order matches the order
  646. // in the save method.
  647. WsbAffirmHr(WsbLoadFromStream(pStream, &m_path, 0));
  648. WsbAffirmHr(WsbLoadFromStream(pStream, &m_name, 0));
  649. WsbAffirmHr(WsbLoadFromStream(pStream, &m_searchName, 0));
  650. WsbAffirmHr(WsbLoadFromStream(pStream, &m_isUserDefined));
  651. WsbAffirmHr(WsbLoadFromStream(pStream, &m_isInclude));
  652. WsbAffirmHr(WsbLoadFromStream(pStream, &m_isUsedInSubDirs));
  653. // Load all the criteria.
  654. WsbAffirmHr(m_pCriteria->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  655. WsbAffirmHr(pPersistStream->Load(pStream));
  656. } WsbCatch(hr);
  657. WsbTraceOut(OLESTR("CHsmRule::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  658. return(hr);
  659. }
  660. HRESULT
  661. CHsmRule::MatchesName(
  662. IN OLECHAR* name
  663. )
  664. /*++
  665. Implements:
  666. IHsmRule::MatchesName().
  667. --*/
  668. {
  669. HRESULT hr = S_OK;
  670. WsbTraceIn(OLESTR("CHsmRule::MatchesName"), OLESTR("name = <%ls>"), (OLECHAR *)name);
  671. try {
  672. WsbAssert(0 != name, E_POINTER);
  673. // It is assumed that these names have been converted from they way they
  674. // might have been input into proper names for IsNameInExpression()
  675. // function. See NameToSearchName().
  676. hr = IsNameInExpression(m_searchName, name, TRUE);
  677. } WsbCatch(hr);
  678. WsbTraceOut(OLESTR("CHsmRule::MatchesName"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  679. return(hr);
  680. }
  681. HRESULT
  682. CHsmRule::NameToSearchName(
  683. void
  684. )
  685. /*++
  686. Implements:
  687. CHsmRule::NameToSearchName().
  688. --*/
  689. {
  690. HRESULT hr = S_OK;
  691. int length;
  692. int i;
  693. try {
  694. WsbAssert(m_name != 0, E_POINTER);
  695. // These name alterations are copied from the NT FindFirstFileExW() code;
  696. // although the code had to be changed to work with the data structures that
  697. // are available.
  698. //
  699. // *.* -> *
  700. // ? -> DOS_QM
  701. // . followed by ? or * -> DOS_DOT
  702. // * followed by a . -> DOS_STAR
  703. if (_wcsicmp(m_name, OLESTR("*.*")) == 0) {
  704. m_searchName = OLESTR("*");
  705. } else {
  706. m_searchName = m_name;
  707. length = wcslen(m_searchName);
  708. for (i = 0; i < length; i++) {
  709. if ((i != 0) && (m_searchName[i] == L'.') && (m_searchName[i-1] == L'*')) {
  710. m_searchName[i-1] = DOS_STAR;
  711. }
  712. if ((m_searchName[i] == L'?') || (m_searchName[i] == L'*')) {
  713. if (m_searchName[i] == L'?') {
  714. m_searchName[i] = DOS_QM;
  715. }
  716. if ((i != 0) && (m_searchName[i-1] == L'.')) {
  717. m_searchName[i-1] = DOS_DOT;
  718. }
  719. }
  720. }
  721. }
  722. } WsbCatch(hr);
  723. return(hr);
  724. }
  725. HRESULT
  726. CHsmRule::Save(
  727. IN IStream* pStream,
  728. IN BOOL clearDirty
  729. )
  730. /*++
  731. Implements:
  732. IPersistStream::Save().
  733. --*/
  734. {
  735. HRESULT hr = S_OK;
  736. CComPtr<IPersistStream> pPersistStream;
  737. WsbTraceIn(OLESTR("CHsmRule::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  738. try {
  739. WsbAssert(0 != pStream, E_POINTER);
  740. // Do the easy stuff, but make sure that this order matches the order
  741. // in the save method.
  742. WsbAffirmHr(WsbSaveToStream(pStream, m_path));
  743. WsbAffirmHr(WsbSaveToStream(pStream, m_name));
  744. WsbAffirmHr(WsbSaveToStream(pStream, m_searchName));
  745. WsbAffirmHr(WsbSaveToStream(pStream, m_isUserDefined));
  746. WsbAffirmHr(WsbSaveToStream(pStream, m_isInclude));
  747. WsbAffirmHr(WsbSaveToStream(pStream, m_isUsedInSubDirs));
  748. // Save off all the criteria.
  749. WsbAffirmHr(m_pCriteria->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  750. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  751. // If we got it saved and we were asked to clear the dirty bit, then
  752. // do so now.
  753. if (clearDirty) {
  754. m_isDirty = FALSE;
  755. }
  756. } WsbCatch(hr);
  757. WsbTraceOut(OLESTR("CHsmRule::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  758. return(hr);
  759. }
  760. HRESULT
  761. CHsmRule::SetIsInclude(
  762. IN BOOL isInclude
  763. )
  764. /*++
  765. Implements:
  766. IHsmRule::SetIsInclude().
  767. --*/
  768. {
  769. m_isInclude = isInclude;
  770. m_isDirty = TRUE;
  771. return(S_OK);
  772. }
  773. HRESULT
  774. CHsmRule::SetIsUserDefined(
  775. IN BOOL isUserDefined
  776. )
  777. /*++
  778. Implements:
  779. IHsmRule::SetIsUserDefined().
  780. --*/
  781. {
  782. m_isUserDefined = isUserDefined;
  783. m_isDirty = TRUE;
  784. return(S_OK);
  785. }
  786. HRESULT
  787. CHsmRule::SetIsUsedInSubDirs(
  788. IN BOOL isUsed
  789. )
  790. /*++
  791. Implements:
  792. IHsmRule::SetIsUsedInSubDirs().
  793. --*/
  794. {
  795. m_isUsedInSubDirs = isUsed;
  796. m_isDirty = TRUE;
  797. return(S_OK);
  798. }
  799. HRESULT
  800. CHsmRule::SetName(
  801. IN OLECHAR* name
  802. )
  803. /*++
  804. Implements:
  805. IHsmRule::SetName().
  806. --*/
  807. {
  808. HRESULT hr = S_OK;
  809. try {
  810. m_name = name;
  811. WsbAffirmHr(NameToSearchName());
  812. m_isDirty = TRUE;
  813. } WsbCatch(hr);
  814. return(hr);
  815. }
  816. HRESULT
  817. CHsmRule::SetPath(
  818. IN OLECHAR* path
  819. )
  820. /*++
  821. Implements:
  822. IHsmRule::SetPath().
  823. --*/
  824. {
  825. HRESULT hr = S_OK;
  826. try {
  827. m_path = path;
  828. m_isDirty = TRUE;
  829. } WsbCatch(hr);
  830. return(hr);
  831. }
  832. HRESULT
  833. CHsmRule::Test(
  834. USHORT* passed,
  835. USHORT* failed
  836. )
  837. /*++
  838. Implements:
  839. IWsbTestable::Test().
  840. --*/
  841. {
  842. HRESULT hr = S_OK;
  843. try {
  844. WsbAssert(0 != passed, E_POINTER);
  845. WsbAssert(0 != failed, E_POINTER);
  846. *passed = 0;
  847. *failed = 0;
  848. } WsbCatch(hr);
  849. return(hr);
  850. }