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.

1239 lines
28 KiB

  1. #include "StdAfx.h"
  2. #include "ADMTScript.h"
  3. #include "NameCracker.h"
  4. #include <LM.h>
  5. #include <NtDsApi.h>
  6. #pragma comment(lib, "NtDsApi.lib")
  7. #include <DsGetDC.h>
  8. #include "Error.h"
  9. #include "AdsiHelpers.h"
  10. using namespace NAMECRACKER;
  11. namespace NAMECRACKER
  12. {
  13. const _TCHAR CANONICAL_DELIMITER = _T('/');
  14. const _TCHAR RDN_DELIMITER = _T('=');
  15. const _TCHAR SAM_DELIMITER = _T('\\');
  16. const _TCHAR SAM_INVALID_CHARACTERS[] = _T("\"*+,./:;<=>?[\\]|");
  17. const _TCHAR EXCLUDE_SAM_INVALID_CHARACTERS[] = _T("\"+,./:;<=>?[\\]|");
  18. }
  19. //---------------------------------------------------------------------------
  20. // Name Cracker Class
  21. //---------------------------------------------------------------------------
  22. CNameCracker::CNameCracker()
  23. {
  24. }
  25. CNameCracker::~CNameCracker()
  26. {
  27. }
  28. void CNameCracker::CrackNames(const StringVector& vecNames)
  29. {
  30. // separate the names into canonical names,
  31. // SAM account names and relative distinguished names
  32. StringVector vecCanonicalNames;
  33. StringVector vecSamAccountNames;
  34. StringVector vecRelativeDistinguishedNames;
  35. Separate(vecNames, vecCanonicalNames, vecSamAccountNames, vecRelativeDistinguishedNames);
  36. // then crack canonical names
  37. CrackCanonicalNames(vecCanonicalNames, vecRelativeDistinguishedNames);
  38. // then crack relative distinguished names
  39. CrackRelativeDistinguishedNames(vecRelativeDistinguishedNames, vecSamAccountNames);
  40. // then crack SAM account names
  41. CrackSamAccountNames(vecSamAccountNames, m_vecUnResolvedNames);
  42. }
  43. void CNameCracker::SiftExcludeNames(const StringSet& setExcludeNames, const StringSet& setNamingAttributes, StringSet& setExcludeRDNs, StringSet& setExcludeSamAccountNames) const
  44. {
  45. //
  46. // For each specified exclude name pattern.
  47. //
  48. for (StringSet::const_iterator it = setExcludeNames.begin(); it != setExcludeNames.end(); it++)
  49. {
  50. const _bstr_t& strPattern = *it;
  51. PCTSTR pszPattern = strPattern;
  52. if (pszPattern)
  53. {
  54. //
  55. // If the exclude pattern contains an RDN delimiter character
  56. // then assume RDN exclude pattern otherwise assume sAMAccountName
  57. // exclude pattern.
  58. //
  59. tstring str = pszPattern;
  60. UINT uDelimiter = str.find_first_of(RDN_DELIMITER);
  61. if (uDelimiter == 0)
  62. {
  63. //
  64. // The RDN delimiter character must follow a valid naming attribute
  65. // therefore if the delimiter occurs at the beginning of the pattern
  66. // then an error must be generated.
  67. //
  68. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, pszPattern);
  69. }
  70. else if (uDelimiter != tstring::npos)
  71. {
  72. //
  73. // Verify exclude pattern contains a valid naming attribute. The naming attribute
  74. // must match the naming attribute(s) for the class(es) of objects being migrated.
  75. //
  76. tstring strNamingAttribute = str.substr(0, uDelimiter);
  77. bool bValidNamingAttribute = false;
  78. StringSet::const_iterator itNA;
  79. for (itNA = setNamingAttributes.begin(); itNA != setNamingAttributes.end(); itNA++)
  80. {
  81. if (_tcsicmp(strNamingAttribute.c_str(), *itNA) == 0)
  82. {
  83. bValidNamingAttribute = true;
  84. break;
  85. }
  86. }
  87. if (bValidNamingAttribute == false)
  88. {
  89. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, pszPattern);
  90. }
  91. setExcludeRDNs.insert(strPattern);
  92. }
  93. else
  94. {
  95. setExcludeSamAccountNames.insert(strPattern);
  96. }
  97. }
  98. }
  99. }
  100. void CNameCracker::Separate(
  101. const StringVector& vecNames,
  102. StringVector& vecCanonicalNames,
  103. StringVector& vecSamAccountNames,
  104. StringVector& vecRelativeDistinguishedNames
  105. )
  106. {
  107. // for each name in vector...
  108. for (StringVector::const_iterator it = vecNames.begin(); it != vecNames.end(); it++)
  109. {
  110. const tstring& strName = *it;
  111. // if non empty name...
  112. if (strName.empty() == false)
  113. {
  114. LPCTSTR pszName = strName.c_str();
  115. // then if name contains a solidus '/' character assume canonical name
  116. // else if name contains a ? '=' character assume relative distinguished name
  117. // else assume SAM account name
  118. if (_tcschr(pszName, CANONICAL_DELIMITER))
  119. {
  120. // assuming canonical name
  121. vecCanonicalNames.push_back(strName);
  122. }
  123. else if (_tcschr(pszName, RDN_DELIMITER))
  124. {
  125. // assuming relative distinguished name
  126. vecRelativeDistinguishedNames.push_back(strName);
  127. }
  128. else
  129. {
  130. // assuming SAM account name
  131. vecSamAccountNames.push_back(strName);
  132. }
  133. }
  134. }
  135. }
  136. void CNameCracker::CrackCanonicalNames(const StringVector& vecCanonicalNames, StringVector& vecUnResolvedNames)
  137. {
  138. //
  139. // for each name generate a complete canonical name
  140. //
  141. CNameVector vecNames;
  142. tstring strCanonical;
  143. for (StringVector::const_iterator it = vecCanonicalNames.begin(); it != vecCanonicalNames.end(); it++)
  144. {
  145. const tstring& strName = *it;
  146. // if first character is the solidus '/' character...
  147. if (strName[0] == CANONICAL_DELIMITER)
  148. {
  149. // then generate complete canonical name
  150. strCanonical = m_strDnsName + strName;
  151. }
  152. else
  153. {
  154. // otherwise if already complete canonical name for this domain...
  155. if (_tcsnicmp(m_strDnsName.c_str(), strName.c_str(), m_strDnsName.length()) == 0)
  156. {
  157. // then add complete canonical name
  158. strCanonical = strName;
  159. }
  160. else
  161. {
  162. // otherwise prefix DNS domain name with solidus and add
  163. strCanonical = m_strDnsName + CANONICAL_DELIMITER + strName;
  164. }
  165. }
  166. vecNames.push_back(SName(strName.c_str(), strCanonical.c_str()));
  167. }
  168. //
  169. // crack canonical names
  170. //
  171. CrackNames(CANONICAL_NAME, vecNames);
  172. for (size_t i = 0; i < vecNames.size(); i++)
  173. {
  174. const SName& name = vecNames[i];
  175. if (name.strResolved.empty() == false)
  176. {
  177. m_setResolvedNames.insert(name.strResolved);
  178. }
  179. else
  180. {
  181. vecUnResolvedNames.push_back(name.strPartial);
  182. }
  183. }
  184. }
  185. void CNameCracker::CrackSamAccountNames(const StringVector& vecSamAccountNames, StringVector& vecUnResolvedNames)
  186. {
  187. //
  188. // for each name generate a NT4 account name
  189. //
  190. CNameVector vecNames;
  191. tstring strNT4Account;
  192. for (StringVector::const_iterator it = vecSamAccountNames.begin(); it != vecSamAccountNames.end(); it++)
  193. {
  194. const tstring& strName = *it;
  195. // if first character is the reverse solidus '\' character...
  196. if (strName[0] == SAM_DELIMITER)
  197. {
  198. // then generate downlevel name
  199. strNT4Account = m_strFlatName + strName;
  200. }
  201. else
  202. {
  203. // otherwise if already downlevel name for this domain...
  204. if (_tcsnicmp(m_strFlatName.c_str(), strName.c_str(), m_strFlatName.length()) == 0)
  205. {
  206. // then add downlevel name
  207. strNT4Account = strName;
  208. }
  209. else
  210. {
  211. // otherwise prefix flat domain name with reverse solidus and add
  212. strNT4Account = m_strFlatName + SAM_DELIMITER + strName;
  213. }
  214. }
  215. vecNames.push_back(SName(strName.c_str(), strNT4Account.c_str()));
  216. }
  217. //
  218. // crack names
  219. //
  220. CrackNames(NT4_ACCOUNT_NAME, vecNames);
  221. for (size_t i = 0; i < vecNames.size(); i++)
  222. {
  223. const SName& name = vecNames[i];
  224. if (name.strResolved.empty() == false)
  225. {
  226. m_setResolvedNames.insert(name.strResolved);
  227. }
  228. else
  229. {
  230. vecUnResolvedNames.push_back(name.strPartial);
  231. }
  232. }
  233. }
  234. void CNameCracker::CrackRelativeDistinguishedNames(const StringVector& vecRelativeDistinguishedNames, StringVector& vecUnResolvedNames)
  235. {
  236. CADsContainer adscContainer(m_spDefaultContainer);
  237. CADsPathName adspnPath(adscContainer.GetADsPath());
  238. for (StringVector::const_iterator it = vecRelativeDistinguishedNames.begin(); it != vecRelativeDistinguishedNames.end(); it++)
  239. {
  240. adspnPath.AddLeafElement(it->c_str());
  241. bool bFound = false;
  242. try
  243. {
  244. CADs adsObject((LPCTSTR)adspnPath.Retrieve(ADS_FORMAT_X500));
  245. m_setResolvedNames.insert(tstring(_bstr_t(adsObject.Get(ATTRIBUTE_DISTINGUISHED_NAME))));
  246. bFound = true;
  247. }
  248. catch (_com_error& ce)
  249. {
  250. #ifdef _DEBUG
  251. _TCHAR sz[2048];
  252. _stprintf(sz, _T("'%s' : %s : 0x%08lX\n"), it->c_str(), ce.ErrorMessage(), ce.Error());
  253. OutputDebugString(sz);
  254. #endif
  255. bFound = false;
  256. }
  257. catch (...)
  258. {
  259. bFound = false;
  260. }
  261. if (!bFound)
  262. {
  263. vecUnResolvedNames.push_back(*it);
  264. }
  265. adspnPath.RemoveLeafElement();
  266. }
  267. }
  268. void CNameCracker::CrackNames(NAME_FORMAT eFormat, CNameVector& vecNames)
  269. {
  270. HANDLE hDs = NULL;
  271. LPTSTR apszNames = NULL;
  272. PDS_NAME_RESULT pdnrResult = NULL;
  273. try
  274. {
  275. if (vecNames.size() > 0)
  276. {
  277. DWORD dwError = DsBind(m_strDomainController.c_str(), NULL, &hDs);
  278. if (dwError == NO_ERROR)
  279. {
  280. DWORD dwCount = vecNames.size();
  281. LPCTSTR* apszNames = new LPCTSTR[dwCount];
  282. if (apszNames != NULL)
  283. {
  284. for (DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++)
  285. {
  286. apszNames[dwIndex] = vecNames[dwIndex].strComplete.c_str();
  287. }
  288. dwError = DsCrackNames(
  289. hDs,
  290. DS_NAME_NO_FLAGS,
  291. (eFormat == CANONICAL_NAME) ? DS_CANONICAL_NAME : (eFormat == NT4_ACCOUNT_NAME) ? DS_NT4_ACCOUNT_NAME : DS_UNKNOWN_NAME,
  292. DS_FQDN_1779_NAME,
  293. dwCount,
  294. const_cast<LPTSTR*>(apszNames),
  295. &pdnrResult
  296. );
  297. if (dwError == NO_ERROR)
  298. {
  299. DWORD c = pdnrResult->cItems;
  300. for (DWORD i = 0; i < c; i++)
  301. {
  302. DS_NAME_RESULT_ITEM& dnriItem = pdnrResult->rItems[i];
  303. if (dnriItem.status == DS_NAME_NO_ERROR)
  304. {
  305. vecNames[i].strResolved = dnriItem.pName;
  306. }
  307. }
  308. DsFreeNameResult(pdnrResult);
  309. }
  310. else
  311. {
  312. _com_issue_error(HRESULT_FROM_WIN32(dwError));
  313. }
  314. delete [] apszNames;
  315. }
  316. else
  317. {
  318. _com_issue_error(E_OUTOFMEMORY);
  319. }
  320. DsUnBind(&hDs);
  321. }
  322. else
  323. {
  324. _com_issue_error(HRESULT_FROM_WIN32(dwError));
  325. }
  326. }
  327. }
  328. catch (...)
  329. {
  330. if (pdnrResult)
  331. {
  332. DsFreeNameResult(pdnrResult);
  333. }
  334. delete [] apszNames;
  335. if (hDs)
  336. {
  337. DsUnBind(&hDs);
  338. }
  339. throw;
  340. }
  341. }
  342. namespace
  343. {
  344. // SplitCanonicalName Method
  345. //
  346. // Given 'a.company.com/Sales/West/Name' this method splits the complete
  347. // canonical name into its component parts Domain='a.company.com',
  348. // Path='/Sales/West/', Name='Name'.
  349. //
  350. // Given 'Sales/West/Name' this method splits the partial canonical name
  351. // into its component parts Domain='', Path='/Sales/West/', Name='Name'.
  352. //
  353. // Given 'Name' this method splits the partial canonical name into its
  354. // component parts Domain='', Path='/', Name='Name'.
  355. void SplitCanonicalName(LPCTSTR pszName, _bstr_t& strDomain, _bstr_t& strPath, _bstr_t& strName)
  356. {
  357. strDomain = (LPCTSTR)NULL;
  358. strPath = (LPCTSTR)NULL;
  359. strName = (LPCTSTR)NULL;
  360. if (pszName)
  361. {
  362. tstring str = pszName;
  363. UINT posA = 0;
  364. UINT posB = tstring::npos;
  365. do
  366. {
  367. posA = str.find_first_of(_T('/'), posA ? posA + 1 : posA);
  368. }
  369. while ((posA != 0) && (posA != tstring::npos) && (str[posA - 1] == _T('\\')));
  370. do
  371. {
  372. posB = str.find_last_of(_T('/'), (posB != tstring::npos) ? posB - 1 : posB);
  373. }
  374. while ((posB != 0) && (posB != tstring::npos) && (str[posB - 1] == _T('\\')));
  375. strDomain = str.substr(0, posA).c_str();
  376. strPath = str.substr(posA, posB - posA).c_str();
  377. strName = str.substr(posB).c_str();
  378. }
  379. }
  380. void SplitPath(LPCTSTR pszPath, _bstr_t& strPath, _bstr_t& strName)
  381. {
  382. strPath = (LPCTSTR)NULL;
  383. strName = (LPCTSTR)NULL;
  384. if (pszPath)
  385. {
  386. tstring str = pszPath;
  387. UINT pos = str.find_first_of(_T('\\'));
  388. if (pos != tstring::npos)
  389. {
  390. strName = pszPath;
  391. }
  392. else
  393. {
  394. UINT posA = str.find_first_of(_T('/'));
  395. if (posA == tstring::npos)
  396. {
  397. strName = (_T("/") + str).c_str();
  398. }
  399. else
  400. {
  401. UINT posB = str.find_last_of(_T('/'));
  402. strPath = str.substr(posA, posB - posA).c_str();
  403. strName = str.substr(posB).c_str();
  404. }
  405. }
  406. }
  407. }
  408. }
  409. //---------------------------------------------------------------------------
  410. // Ignore Case String Less
  411. //---------------------------------------------------------------------------
  412. struct SIgnoreCaseStringLess :
  413. public std::binary_function<tstring, tstring, bool>
  414. {
  415. bool operator()(const tstring& x, const tstring& y) const
  416. {
  417. bool bLess;
  418. LPCTSTR pszX = x.c_str();
  419. LPCTSTR pszY = y.c_str();
  420. if (pszX == pszY)
  421. {
  422. bLess = false;
  423. }
  424. else if (pszX == NULL)
  425. {
  426. bLess = true;
  427. }
  428. else if (pszY == NULL)
  429. {
  430. bLess = false;
  431. }
  432. else
  433. {
  434. bLess = _tcsicmp(pszX, pszY) < 0;
  435. }
  436. return bLess;
  437. }
  438. };
  439. //---------------------------------------------------------------------------
  440. // CDomainMap Implementation
  441. //---------------------------------------------------------------------------
  442. class CDomainMap :
  443. public std::map<_bstr_t, StringSet, IgnoreCaseStringLess>
  444. {
  445. public:
  446. CDomainMap()
  447. {
  448. }
  449. void Initialize(const StringSet& setNames)
  450. {
  451. _bstr_t strDefaultDns(_T("/"));
  452. _bstr_t strDefaultFlat(_T("\\"));
  453. for (StringSet::const_iterator it = setNames.begin(); it != setNames.end(); it++)
  454. {
  455. tstring strName = *it;
  456. // if not an empty name...
  457. if (strName.empty() == false)
  458. {
  459. // if name contains a canonical name delimiter...
  460. UINT posDelimiter = strName.find(CANONICAL_DELIMITER);
  461. if (posDelimiter != tstring::npos)
  462. {
  463. // then assume canonical name
  464. if (posDelimiter == 0)
  465. {
  466. // then generate complete canonical name
  467. Insert(strDefaultDns, *it);
  468. }
  469. else
  470. {
  471. // otherwise if path component before delimiter contains
  472. // a period
  473. UINT posDot = strName.find(_T('.'));
  474. if (posDot < posDelimiter)
  475. {
  476. // then assume a complete canonical name with DNS domain name prefix
  477. Insert(strName.substr(0, posDelimiter).c_str(), *it);
  478. }
  479. else
  480. {
  481. // otherwise assume domain name has not been specified
  482. Insert(strDefaultDns, *it);
  483. }
  484. }
  485. }
  486. else
  487. {
  488. // otherwise if name contains a NT account name delimiter
  489. // character and no invalid SAM account name characters...
  490. UINT posDelimiter = strName.find(SAM_DELIMITER);
  491. if (posDelimiter != tstring::npos)
  492. {
  493. if (strName.find_first_of(SAM_INVALID_CHARACTERS, posDelimiter + 1) == tstring::npos)
  494. {
  495. if (posDelimiter == 0)
  496. {
  497. Insert(strDefaultFlat, *it);
  498. }
  499. else
  500. {
  501. // then assume SAM account name
  502. Insert(strName.substr(0, posDelimiter).c_str(), strName.substr(posDelimiter).c_str());
  503. }
  504. }
  505. else
  506. {
  507. // otherwise assume relative distinguished name
  508. Insert(strDefaultDns, *it);
  509. }
  510. }
  511. else
  512. {
  513. Insert(strDefaultDns, *it);
  514. }
  515. }
  516. }
  517. }
  518. }
  519. protected:
  520. void Insert(_bstr_t strDomain, _bstr_t strName)
  521. {
  522. iterator it = find(strDomain);
  523. if (it == end())
  524. {
  525. std::pair<iterator, bool> pair = insert(value_type(strDomain, StringSet()));
  526. it = pair.first;
  527. }
  528. it->second.insert(strName);
  529. }
  530. };
  531. //---------------------------------------------------------------------------
  532. // CDomainToPathMap Implementation
  533. //---------------------------------------------------------------------------
  534. // Initialize Method
  535. void CDomainToPathMap::Initialize(LPCTSTR pszDefaultDomainDns, LPCTSTR pszDefaultDomainFlat, const StringSet& setNames)
  536. {
  537. CDomainMap map;
  538. map.Initialize(setNames);
  539. for (CDomainMap::const_iterator itDomain = map.begin(); itDomain != map.end(); itDomain++)
  540. {
  541. _bstr_t strDomainName = itDomain->first;
  542. LPCTSTR pszDomainName = strDomainName;
  543. if (pszDomainName && ((*pszDomainName == _T('/')) || (*pszDomainName == _T('\\'))))
  544. {
  545. strDomainName = (pszDefaultDomainDns && (_tcslen(pszDefaultDomainDns) > 0)) ? pszDefaultDomainDns : pszDefaultDomainFlat;
  546. }
  547. else
  548. {
  549. if (GetValidDomainName(strDomainName) == false)
  550. {
  551. strDomainName = (pszDefaultDomainDns && (_tcslen(pszDefaultDomainDns) > 0)) ? pszDefaultDomainDns : pszDefaultDomainFlat;
  552. }
  553. }
  554. iterator it = find(strDomainName);
  555. if (it == end())
  556. {
  557. std::pair<iterator, bool> pair = insert(value_type(strDomainName, StringSet()));
  558. it = pair.first;
  559. }
  560. StringSet& setNames = it->second;
  561. const StringSet& set = itDomain->second;
  562. for (StringSet::const_iterator itSet = set.begin(); itSet != set.end(); itSet++)
  563. {
  564. setNames.insert(*itSet);
  565. }
  566. }
  567. }
  568. // GetValidDomainName Method
  569. bool CDomainToPathMap::GetValidDomainName(_bstr_t& strDomainName)
  570. {
  571. bool bValid = false;
  572. PDOMAIN_CONTROLLER_INFO pdci;
  573. // attempt to retrieve DNS name of domain controller supporting active directory service
  574. DWORD dwError = DsGetDcName(NULL, strDomainName, NULL, NULL, DS_RETURN_DNS_NAME, &pdci);
  575. // if domain controller not found, attempt to retrieve flat name of domain controller
  576. if (dwError == ERROR_NO_SUCH_DOMAIN)
  577. {
  578. dwError = DsGetDcName(NULL, strDomainName, NULL, NULL, DS_RETURN_FLAT_NAME, &pdci);
  579. }
  580. // if domain controller found then save name otherwise generate error
  581. if (dwError == NO_ERROR)
  582. {
  583. strDomainName = pdci->DomainName;
  584. NetApiBufferFree(pdci);
  585. bValid = true;
  586. }
  587. return bValid;
  588. }
  589. //
  590. // CNameToPathMap Implementation
  591. //
  592. CNameToPathMap::CNameToPathMap()
  593. {
  594. }
  595. CNameToPathMap::CNameToPathMap(StringSet& setNames)
  596. {
  597. Initialize(setNames);
  598. }
  599. void CNameToPathMap::Initialize(StringSet& setNames)
  600. {
  601. _bstr_t strDomain;
  602. _bstr_t strPath;
  603. _bstr_t strName;
  604. for (StringSet::iterator it = setNames.begin(); it != setNames.end(); it++)
  605. {
  606. // SplitPath(*it, strPath, strName);
  607. SplitCanonicalName(*it, strDomain, strPath, strName);
  608. Add(strName, strPath);
  609. }
  610. }
  611. void CNameToPathMap::Add(_bstr_t& strName, _bstr_t& strPath)
  612. {
  613. iterator it = find(strName);
  614. if (it == end())
  615. {
  616. std::pair<iterator, bool> pair = insert(value_type(strName, StringSet()));
  617. it = pair.first;
  618. }
  619. it->second.insert(strPath);
  620. }
  621. //
  622. // IgnoreCaseStringLess Implementation
  623. //
  624. bool IgnoreCaseStringLess::operator()(const _bstr_t& x, const _bstr_t& y) const
  625. {
  626. bool bLess;
  627. LPCTSTR pszThis = x;
  628. LPCTSTR pszThat = y;
  629. if (pszThis == pszThat)
  630. {
  631. bLess = false;
  632. }
  633. else if (pszThis == NULL)
  634. {
  635. bLess = true;
  636. }
  637. else if (pszThat == NULL)
  638. {
  639. bLess = false;
  640. }
  641. else
  642. {
  643. bLess = _tcsicmp(pszThis, pszThat) < 0;
  644. }
  645. return bLess;
  646. }
  647. //
  648. // CCompareStrings Implementation
  649. //
  650. CCompareStrings::CCompareStrings()
  651. {
  652. }
  653. CCompareStrings::CCompareStrings(StringSet& setNames)
  654. {
  655. Initialize(setNames);
  656. }
  657. void CCompareStrings::Initialize(StringSet& setNames)
  658. {
  659. for (StringSet::iterator it = setNames.begin(); it != setNames.end(); it++)
  660. {
  661. m_vecCompareStrings.push_back(CCompareString(*it));
  662. }
  663. }
  664. bool CCompareStrings::IsMatch(LPCTSTR pszName)
  665. {
  666. bool bIs = false;
  667. CompareStringVector::iterator itBeg = m_vecCompareStrings.begin();
  668. CompareStringVector::iterator itEnd = m_vecCompareStrings.end();
  669. for (CompareStringVector::iterator it = itBeg; it != itEnd; it++)
  670. {
  671. if (it->IsMatch(pszName))
  672. {
  673. bIs = true;
  674. break;
  675. }
  676. }
  677. return bIs;
  678. }
  679. //
  680. // CCompareString Implementation
  681. //
  682. CCompareStrings::CCompareString::CCompareString(LPCTSTR pszCompare)
  683. {
  684. if (pszCompare)
  685. {
  686. Initialize(pszCompare);
  687. }
  688. }
  689. CCompareStrings::CCompareString::CCompareString(const CCompareString& r) :
  690. m_nType(r.m_nType),
  691. m_strCompare(r.m_strCompare)
  692. {
  693. }
  694. void CCompareStrings::CCompareString::Initialize(LPCTSTR pszCompare)
  695. {
  696. if (pszCompare)
  697. {
  698. tstring str = pszCompare;
  699. UINT uLength = str.length();
  700. if (uLength == 0)
  701. {
  702. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, pszCompare);
  703. }
  704. bool bBeg = (str[0] == _T('*'));
  705. bool bEnd = ((uLength > 1) && (str[uLength - 1] == _T('*'))) ? true : false;
  706. if (bBeg && bEnd)
  707. {
  708. // contains
  709. m_nType = 3;
  710. str = str.substr(1, uLength - 2);
  711. }
  712. else if (bBeg)
  713. {
  714. // ends with
  715. m_nType = 2;
  716. str = str.substr(1, uLength - 1);
  717. }
  718. else if (bEnd)
  719. {
  720. // begins with
  721. m_nType = 1;
  722. str = str.substr(0, uLength - 1);
  723. }
  724. else
  725. {
  726. // equals
  727. m_nType = 0;
  728. }
  729. if (str.length() > 0)
  730. {
  731. m_strCompare = str.c_str();
  732. }
  733. else
  734. {
  735. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, pszCompare);
  736. }
  737. }
  738. else
  739. {
  740. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, _T(""));
  741. }
  742. }
  743. bool CCompareStrings::CCompareString::IsMatch(LPCTSTR psz)
  744. {
  745. bool bIs = false;
  746. if (psz)
  747. {
  748. switch (m_nType)
  749. {
  750. case 0: // equals
  751. {
  752. bIs = (_tcsicmp(psz, m_strCompare) == 0);
  753. break;
  754. }
  755. case 1: // begins with
  756. {
  757. bIs = (_tcsnicmp(psz, m_strCompare, m_strCompare.length()) == 0);
  758. break;
  759. }
  760. case 2: // ends with
  761. {
  762. UINT cchT = _tcslen(psz);
  763. UINT cchC = m_strCompare.length();
  764. if (cchT >= cchC)
  765. {
  766. bIs = (_tcsnicmp(psz + cchT - cchC, m_strCompare, cchC) == 0);
  767. }
  768. break;
  769. }
  770. case 3: // contains
  771. {
  772. PTSTR pszT = NULL;
  773. PTSTR pszC = NULL;
  774. try
  775. {
  776. pszT = new _TCHAR[_tcslen(psz) + 1];
  777. pszC = new _TCHAR[m_strCompare.length() + 1];
  778. if (pszT && pszC)
  779. {
  780. _tcscpy(pszT, psz);
  781. _tcscpy(pszC, m_strCompare);
  782. _tcslwr(pszT);
  783. _tcslwr(pszC);
  784. bIs = (_tcsstr(pszT, pszC) != NULL);
  785. }
  786. else
  787. {
  788. _com_issue_error(E_OUTOFMEMORY);
  789. }
  790. }
  791. catch (...)
  792. {
  793. delete [] pszC;
  794. delete [] pszT;
  795. throw;
  796. }
  797. delete [] pszC;
  798. delete [] pszT;
  799. break;
  800. }
  801. }
  802. }
  803. return bIs;
  804. }
  805. //
  806. // CCompareRDNs Implementation
  807. //
  808. CCompareRDNs::CCompareRDNs()
  809. {
  810. }
  811. CCompareRDNs::CCompareRDNs(StringSet& setNames)
  812. {
  813. Initialize(setNames);
  814. }
  815. void CCompareRDNs::Initialize(StringSet& setNames)
  816. {
  817. for (StringSet::iterator it = setNames.begin(); it != setNames.end(); it++)
  818. {
  819. m_vecCompare.push_back(CCompareRDN(*it));
  820. }
  821. }
  822. bool CCompareRDNs::IsMatch(LPCTSTR pszName)
  823. {
  824. bool bIs = false;
  825. CompareVector::iterator itBeg = m_vecCompare.begin();
  826. CompareVector::iterator itEnd = m_vecCompare.end();
  827. for (CompareVector::iterator it = itBeg; it != itEnd; it++)
  828. {
  829. if (it->IsMatch(pszName))
  830. {
  831. bIs = true;
  832. break;
  833. }
  834. }
  835. return bIs;
  836. }
  837. //
  838. // CCompareRDN Implementation
  839. //
  840. CCompareRDNs::CCompareRDN::CCompareRDN(LPCTSTR pszCompare)
  841. {
  842. if (pszCompare)
  843. {
  844. Initialize(pszCompare);
  845. }
  846. }
  847. CCompareRDNs::CCompareRDN::CCompareRDN(const CCompareRDN& r) :
  848. m_nPatternType(r.m_nPatternType),
  849. m_strType(r.m_strType),
  850. m_strValue(r.m_strValue)
  851. {
  852. }
  853. void CCompareRDNs::CCompareRDN::Initialize(LPCTSTR pszCompare)
  854. {
  855. if (pszCompare == NULL)
  856. {
  857. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, _T(""));
  858. }
  859. tstring str = pszCompare;
  860. UINT uDelimiter = str.find_first_of(_T('='));
  861. //
  862. // The pattern must include the RDN delimiter character.
  863. //
  864. if ((uDelimiter == 0) || (uDelimiter == tstring::npos))
  865. {
  866. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, pszCompare);
  867. }
  868. //
  869. // Retrieve the naming attribute portion.
  870. //
  871. m_strType = str.substr(0, uDelimiter).c_str();
  872. //
  873. // Retrieve the naming attribute value portion.
  874. //
  875. tstring strValue = str.substr(uDelimiter + 1);
  876. UINT uLength = strValue.length();
  877. if (uLength == 0)
  878. {
  879. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, pszCompare);
  880. }
  881. //
  882. // Determine pattern type.
  883. //
  884. bool bBeg = (strValue[0] == _T('*'));
  885. bool bEnd = ((uLength > 1) && (strValue[uLength - 1] == _T('*'))) ? true : false;
  886. if (bBeg && bEnd)
  887. {
  888. // contains
  889. m_nPatternType = 3;
  890. strValue = strValue.substr(1, uLength - 2);
  891. }
  892. else if (bBeg)
  893. {
  894. // ends with
  895. m_nPatternType = 2;
  896. strValue = strValue.substr(1, uLength - 1);
  897. }
  898. else if (bEnd)
  899. {
  900. // begins with
  901. m_nPatternType = 1;
  902. strValue = strValue.substr(0, uLength - 1);
  903. }
  904. else
  905. {
  906. // equals
  907. m_nPatternType = 0;
  908. }
  909. if (strValue.length() > 0)
  910. {
  911. m_strValue = strValue.c_str();
  912. }
  913. else
  914. {
  915. AdmtThrowError(GUID_NULL, GUID_NULL, E_INVALIDARG, IDS_E_INVALID_FILTER_STRING, pszCompare);
  916. }
  917. }
  918. bool CCompareRDNs::CCompareRDN::IsMatch(LPCTSTR psz)
  919. {
  920. bool bIs = false;
  921. if (psz)
  922. {
  923. PCTSTR pszDelimiter = _tcschr(psz, _T('='));
  924. if (pszDelimiter)
  925. {
  926. if (_tcsnicmp(m_strType, psz, pszDelimiter - psz) == 0)
  927. {
  928. PCTSTR pszValue = pszDelimiter + 1;
  929. switch (m_nPatternType)
  930. {
  931. case 0: // equals
  932. {
  933. bIs = (_tcsicmp(pszValue, m_strValue) == 0);
  934. break;
  935. }
  936. case 1: // begins with
  937. {
  938. bIs = (_tcsnicmp(pszValue, m_strValue, m_strValue.length()) == 0);
  939. break;
  940. }
  941. case 2: // ends with
  942. {
  943. UINT cchT = _tcslen(pszValue);
  944. UINT cchC = m_strValue.length();
  945. if (cchT >= cchC)
  946. {
  947. bIs = (_tcsnicmp(pszValue + cchT - cchC, m_strValue, cchC) == 0);
  948. }
  949. break;
  950. }
  951. case 3: // contains
  952. {
  953. PTSTR pszT = NULL;
  954. PTSTR pszC = NULL;
  955. try
  956. {
  957. pszT = new _TCHAR[_tcslen(pszValue) + 1];
  958. pszC = new _TCHAR[m_strValue.length() + 1];
  959. if (pszT && pszC)
  960. {
  961. _tcscpy(pszT, pszValue);
  962. _tcscpy(pszC, m_strValue);
  963. _tcslwr(pszT);
  964. _tcslwr(pszC);
  965. bIs = (_tcsstr(pszT, pszC) != NULL);
  966. }
  967. else
  968. {
  969. _com_issue_error(E_OUTOFMEMORY);
  970. }
  971. }
  972. catch (...)
  973. {
  974. delete [] pszC;
  975. delete [] pszT;
  976. throw;
  977. }
  978. delete [] pszC;
  979. delete [] pszT;
  980. break;
  981. }
  982. }
  983. }
  984. }
  985. }
  986. return bIs;
  987. }