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.

1556 lines
32 KiB

  1. #pragma once
  2. #include <map>
  3. #include <string>
  4. #include <vector>
  5. #include <ComDef.h>
  6. #include <ActiveDS.h>
  7. #ifndef tstring
  8. typedef std::basic_string<_TCHAR> tstring;
  9. #endif
  10. #ifndef IADsPtr
  11. _COM_SMARTPTR_TYPEDEF(IADs, IID_IADs);
  12. #endif
  13. #ifndef IADsContainerPtr
  14. _COM_SMARTPTR_TYPEDEF(IADsContainer, IID_IADsContainer);
  15. #endif
  16. #ifndef IADsUserPtr
  17. _COM_SMARTPTR_TYPEDEF(IADsUser, IID_IADsUser);
  18. #endif
  19. #ifndef IADsADSystemInfoPtr
  20. _COM_SMARTPTR_TYPEDEF(IADsADSystemInfo, IID_IADsADSystemInfo);
  21. #endif
  22. #ifndef IADsPathnamePtr
  23. _COM_SMARTPTR_TYPEDEF(IADsPathname, IID_IADsPathname);
  24. #endif
  25. #ifndef IDirectoryObjectPtr
  26. _COM_SMARTPTR_TYPEDEF(IDirectoryObject, IID_IDirectoryObject);
  27. #endif
  28. #ifndef IDirectorySearchPtr
  29. _COM_SMARTPTR_TYPEDEF(IDirectorySearch, IID_IDirectorySearch);
  30. #endif
  31. //---------------------------------------------------------------------------
  32. // CADs Class
  33. //---------------------------------------------------------------------------
  34. class CADs
  35. {
  36. public:
  37. CADs(IADsPtr spADs) :
  38. m_spADs(spADs)
  39. {
  40. }
  41. CADs(LPCTSTR pszADsPath = NULL)
  42. {
  43. if (pszADsPath)
  44. {
  45. CheckResult(ADsGetObject(pszADsPath, IID_IADs, (VOID**)&m_spADs));
  46. }
  47. }
  48. CADs(const CADs& r) :
  49. m_spADs(r.m_spADs)
  50. {
  51. }
  52. operator bool() const
  53. {
  54. return m_spADs;
  55. }
  56. operator IADs*() const
  57. {
  58. return m_spADs;
  59. }
  60. CADs& operator =(IADsPtr spADs)
  61. {
  62. m_spADs = spADs;
  63. return *this;
  64. }
  65. CADs& operator =(const CADs& r)
  66. {
  67. m_spADs = r.m_spADs;
  68. return *this;
  69. }
  70. _bstr_t GetName()
  71. {
  72. BSTR bstr;
  73. CheckResult(m_spADs->get_Name(&bstr));
  74. return _bstr_t(bstr, false);
  75. }
  76. _bstr_t GetClass()
  77. {
  78. BSTR bstr;
  79. CheckResult(m_spADs->get_Class(&bstr));
  80. return _bstr_t(bstr, false);
  81. }
  82. _bstr_t GetGUID()
  83. {
  84. BSTR bstr;
  85. CheckResult(m_spADs->get_GUID(&bstr));
  86. return _bstr_t(bstr, false);
  87. }
  88. _bstr_t GetADsPath()
  89. {
  90. BSTR bstr;
  91. CheckResult(m_spADs->get_ADsPath(&bstr));
  92. return _bstr_t(bstr, false);
  93. }
  94. _bstr_t GetParent()
  95. {
  96. BSTR bstr;
  97. CheckResult(m_spADs->get_Parent(&bstr));
  98. return _bstr_t(bstr, false);
  99. }
  100. _bstr_t GetSchema()
  101. {
  102. BSTR bstr;
  103. CheckResult(m_spADs->get_Schema(&bstr));
  104. return _bstr_t(bstr, false);
  105. }
  106. void GetInfo()
  107. {
  108. CheckResult(m_spADs->GetInfo());
  109. }
  110. void SetInfo()
  111. {
  112. CheckResult(m_spADs->SetInfo());
  113. }
  114. _variant_t Get(_bstr_t strName)
  115. {
  116. VARIANT vnt;
  117. VariantInit(&vnt);
  118. CheckResult(m_spADs->Get(strName, &vnt));
  119. return _variant_t(vnt, false);
  120. }
  121. void Put(_bstr_t strName, const _variant_t& vntValue)
  122. {
  123. CheckResult(m_spADs->Put(strName, vntValue));
  124. }
  125. _variant_t GetEx(_bstr_t strName)
  126. {
  127. VARIANT vnt;
  128. VariantInit(&vnt);
  129. CheckResult(m_spADs->GetEx(strName, &vnt));
  130. return _variant_t(vnt, false);
  131. }
  132. void PutEx(long lControlCode, _bstr_t strName, const _variant_t& vntValue)
  133. {
  134. CheckResult(m_spADs->PutEx(lControlCode, strName, vntValue));
  135. }
  136. void GetInfoEx(const _variant_t& vntProperties, long lReserved)
  137. {
  138. CheckResult(m_spADs->GetInfoEx(vntProperties, lReserved));
  139. }
  140. protected:
  141. void CheckResult(HRESULT hr)
  142. {
  143. if (FAILED(hr))
  144. {
  145. _com_issue_errorex(hr, IUnknownPtr(m_spADs), IID_IADs);
  146. }
  147. }
  148. protected:
  149. IADsPtr m_spADs;
  150. };
  151. //---------------------------------------------------------------------------
  152. // CADsContainer Class
  153. //---------------------------------------------------------------------------
  154. class CADsContainer : public CADs
  155. {
  156. protected:
  157. void CheckResult(HRESULT hr)
  158. {
  159. if (FAILED(hr))
  160. {
  161. _com_issue_errorex(hr, IUnknownPtr(m_spADsContainer), IID_IADsContainer);
  162. }
  163. }
  164. public:
  165. CADsContainer(IADsContainerPtr spADsContainer) :
  166. CADs(spADsContainer),
  167. m_spADsContainer(spADsContainer)
  168. {
  169. }
  170. CADsContainer(LPCTSTR pszADsPath = NULL) :
  171. CADs(pszADsPath)
  172. {
  173. m_spADsContainer = m_spADs;
  174. }
  175. CADsContainer(const CADsContainer& r) :
  176. CADs(r),
  177. m_spADsContainer(r.m_spADsContainer)
  178. {
  179. }
  180. operator bool() const
  181. {
  182. return m_spADsContainer;
  183. }
  184. operator IADsContainer*() const
  185. {
  186. return m_spADsContainer;
  187. }
  188. CADsContainer& operator =(IADsContainerPtr spADsContainer)
  189. {
  190. m_spADs = spADsContainer;
  191. m_spADsContainer = spADsContainer;
  192. return *this;
  193. }
  194. CADsContainer& operator =(const CADsContainer& r)
  195. {
  196. m_spADs = r.m_spADs;
  197. m_spADsContainer = r.m_spADsContainer;
  198. return *this;
  199. }
  200. long GetCount()
  201. {
  202. long l;
  203. CheckResult(m_spADsContainer->get_Count(&l));
  204. return l;
  205. }
  206. IUnknownPtr GetNewEnum()
  207. {
  208. IUnknown* punk;
  209. CheckResult(m_spADsContainer->get__NewEnum(&punk));
  210. return IUnknownPtr(punk, false);
  211. }
  212. _variant_t GetFilter()
  213. {
  214. VARIANT vnt;
  215. VariantInit(&vnt);
  216. CheckResult(m_spADsContainer->get_Filter(&vnt));
  217. return _variant_t(vnt, false);
  218. }
  219. void SetFilter(const _variant_t& vnt)
  220. {
  221. CheckResult(m_spADsContainer->put_Filter(vnt));
  222. }
  223. _variant_t GetHints()
  224. {
  225. VARIANT vnt;
  226. VariantInit(&vnt);
  227. CheckResult(m_spADsContainer->get_Hints(&vnt));
  228. return _variant_t(vnt, false);
  229. }
  230. void SetHints(const _variant_t& vnt)
  231. {
  232. CheckResult(m_spADsContainer->put_Hints(vnt));
  233. }
  234. IDispatchPtr GetObject(_bstr_t strClassName, _bstr_t strRelativeName)
  235. {
  236. IDispatch* pdisp;
  237. CheckResult(m_spADsContainer->GetObject(strClassName, strRelativeName, &pdisp));
  238. return IDispatchPtr(pdisp, false);
  239. }
  240. IDispatchPtr Create(_bstr_t strClassName, _bstr_t strRelativeName)
  241. {
  242. IDispatch* pdisp;
  243. CheckResult(m_spADsContainer->Create(strClassName, strRelativeName, &pdisp));
  244. return IDispatchPtr(pdisp, false);
  245. }
  246. void Delete(_bstr_t strClassName, _bstr_t strRelativeName)
  247. {
  248. CheckResult(m_spADsContainer->Delete(strClassName, strRelativeName));
  249. }
  250. IDispatchPtr CopyHere(_bstr_t strSourceName, _bstr_t strNewName)
  251. {
  252. IDispatch* pdisp;
  253. CheckResult(m_spADsContainer->CopyHere(strSourceName, strNewName, &pdisp));
  254. return IDispatchPtr(pdisp, false);
  255. }
  256. IDispatchPtr MoveHere(_bstr_t strSourceName, _bstr_t strNewName)
  257. {
  258. IDispatch* pdisp;
  259. CheckResult(m_spADsContainer->MoveHere(strSourceName, strNewName, &pdisp));
  260. return IDispatchPtr(pdisp, false);
  261. }
  262. protected:
  263. IADsContainerPtr m_spADsContainer;
  264. };
  265. //---------------------------------------------------------------------------
  266. // CADsUser Class
  267. //---------------------------------------------------------------------------
  268. class CADsUser : public CADs
  269. {
  270. public:
  271. CADsUser(IADsUserPtr spADsUser) :
  272. CADs(spADsUser),
  273. m_spADsUser(spADsUser)
  274. {
  275. }
  276. CADsUser(LPCTSTR pszADsPath = NULL) :
  277. CADs(pszADsPath)
  278. {
  279. m_spADsUser = m_spADs;
  280. }
  281. CADsUser(const CADsUser& r) :
  282. CADs(r),
  283. m_spADsUser(r.m_spADsUser)
  284. {
  285. }
  286. operator bool() const
  287. {
  288. return m_spADsUser;
  289. }
  290. operator IADsUser*() const
  291. {
  292. return m_spADsUser;
  293. }
  294. CADsUser& operator =(IADsUserPtr spADsUser)
  295. {
  296. m_spADs = spADsUser;
  297. m_spADsUser = spADsUser;
  298. return *this;
  299. }
  300. CADsUser& operator =(const CADsUser& r)
  301. {
  302. m_spADs = r.m_spADs;
  303. m_spADsUser = r.m_spADsUser;
  304. return *this;
  305. }
  306. _bstr_t GetBadLoginAddress()
  307. {
  308. BSTR bstr;
  309. CheckResult(m_spADsUser->get_BadLoginAddress(&bstr));
  310. return _bstr_t(bstr, false);
  311. }
  312. DATE GetLastLogin()
  313. {
  314. DATE d;
  315. CheckResult(m_spADsUser->get_LastLogin(&d));
  316. return d;
  317. }
  318. DATE GetLastLogoff()
  319. {
  320. DATE d;
  321. CheckResult(m_spADsUser->get_LastLogoff(&d));
  322. return d;
  323. }
  324. DATE GetLastFailedLogin()
  325. {
  326. DATE d;
  327. CheckResult(m_spADsUser->get_LastFailedLogin(&d));
  328. return d;
  329. }
  330. DATE GetPasswordLastChanged()
  331. {
  332. DATE d;
  333. CheckResult(m_spADsUser->get_PasswordLastChanged(&d));
  334. return d;
  335. }
  336. _bstr_t GetDescription()
  337. {
  338. BSTR bstr;
  339. CheckResult(m_spADsUser->get_Description(&bstr));
  340. return _bstr_t(bstr, false);
  341. }
  342. void SetDescription(_bstr_t strDescription)
  343. {
  344. CheckResult(m_spADsUser->put_Description(strDescription));
  345. }
  346. _bstr_t GetDivision()
  347. {
  348. BSTR bstr;
  349. CheckResult(m_spADsUser->get_Division(&bstr));
  350. return _bstr_t(bstr, false);
  351. }
  352. void SetDivision(_bstr_t strDivision)
  353. {
  354. CheckResult(m_spADsUser->put_Division(strDivision));
  355. }
  356. _bstr_t GetDepartment()
  357. {
  358. BSTR bstr;
  359. CheckResult(m_spADsUser->get_Department(&bstr));
  360. return _bstr_t(bstr, false);
  361. }
  362. void SetDepartment(_bstr_t strDepartment)
  363. {
  364. CheckResult(m_spADsUser->put_Department(strDepartment));
  365. }
  366. _bstr_t GetEmployeeId()
  367. {
  368. BSTR bstr;
  369. CheckResult(m_spADsUser->get_EmployeeID(&bstr));
  370. return _bstr_t(bstr, false);
  371. }
  372. void SetEmployeeId(_bstr_t strEmployeeId)
  373. {
  374. CheckResult(m_spADsUser->put_EmployeeID(strEmployeeId));
  375. }
  376. _bstr_t GetFullName()
  377. {
  378. BSTR bstr;
  379. CheckResult(m_spADsUser->get_FullName(&bstr));
  380. return _bstr_t(bstr, false);
  381. }
  382. void SetFullName(_bstr_t strFullName)
  383. {
  384. CheckResult(m_spADsUser->put_FullName(strFullName));
  385. }
  386. _bstr_t GetFirstName()
  387. {
  388. BSTR bstr;
  389. CheckResult(m_spADsUser->get_FirstName(&bstr));
  390. return _bstr_t(bstr, false);
  391. }
  392. void SetFirstName(_bstr_t strFirstName)
  393. {
  394. CheckResult(m_spADsUser->put_FirstName(strFirstName));
  395. }
  396. _bstr_t GetLastName()
  397. {
  398. BSTR bstr;
  399. CheckResult(m_spADsUser->get_LastName(&bstr));
  400. return _bstr_t(bstr, false);
  401. }
  402. void SetLastName(_bstr_t strLastName)
  403. {
  404. CheckResult(m_spADsUser->put_LastName(strLastName));
  405. }
  406. _bstr_t GetOtherName()
  407. {
  408. BSTR bstr;
  409. CheckResult(m_spADsUser->get_OtherName(&bstr));
  410. return _bstr_t(bstr, false);
  411. }
  412. void SetOtherName(_bstr_t strOtherName)
  413. {
  414. CheckResult(m_spADsUser->put_OtherName(strOtherName));
  415. }
  416. _bstr_t GetNamePrefix()
  417. {
  418. BSTR bstr;
  419. CheckResult(m_spADsUser->get_NamePrefix(&bstr));
  420. return _bstr_t(bstr, false);
  421. }
  422. void SetNamePrefix(_bstr_t strNamePrefix)
  423. {
  424. CheckResult(m_spADsUser->put_NamePrefix(strNamePrefix));
  425. }
  426. _bstr_t GetNameSuffix()
  427. {
  428. BSTR bstr;
  429. CheckResult(m_spADsUser->get_NameSuffix(&bstr));
  430. return _bstr_t(bstr, false);
  431. }
  432. void SetNameSuffix(_bstr_t strNameSuffix)
  433. {
  434. CheckResult(m_spADsUser->put_NameSuffix(strNameSuffix));
  435. }
  436. _bstr_t GetTitle()
  437. {
  438. BSTR bstr;
  439. CheckResult(m_spADsUser->get_Title(&bstr));
  440. return _bstr_t(bstr, false);
  441. }
  442. void SetTitle(_bstr_t strTitle)
  443. {
  444. CheckResult(m_spADsUser->put_Title(strTitle));
  445. }
  446. _bstr_t GetManager()
  447. {
  448. BSTR bstr;
  449. CheckResult(m_spADsUser->get_Manager(&bstr));
  450. return _bstr_t(bstr, false);
  451. }
  452. void SetManager(_bstr_t strManager)
  453. {
  454. CheckResult(m_spADsUser->put_Manager(strManager));
  455. }
  456. /*
  457. virtual HRESULT STDMETHODCALLTYPE get_TelephoneHome(
  458. VARIANT __RPC_FAR *retval) = 0;
  459. virtual HRESULT STDMETHODCALLTYPE put_TelephoneHome(
  460. VARIANT vTelephoneHome) = 0;
  461. virtual HRESULT STDMETHODCALLTYPE get_TelephoneMobile(
  462. VARIANT __RPC_FAR *retval) = 0;
  463. virtual HRESULT STDMETHODCALLTYPE put_TelephoneMobile(
  464. VARIANT vTelephoneMobile) = 0;
  465. virtual HRESULT STDMETHODCALLTYPE get_TelephoneNumber(
  466. VARIANT __RPC_FAR *retval) = 0;
  467. virtual HRESULT STDMETHODCALLTYPE put_TelephoneNumber(
  468. VARIANT vTelephoneNumber) = 0;
  469. virtual HRESULT STDMETHODCALLTYPE get_TelephonePager(
  470. VARIANT __RPC_FAR *retval) = 0;
  471. virtual HRESULT STDMETHODCALLTYPE put_TelephonePager(
  472. VARIANT vTelephonePager) = 0;
  473. virtual HRESULT STDMETHODCALLTYPE get_FaxNumber(
  474. VARIANT __RPC_FAR *retval) = 0;
  475. virtual HRESULT STDMETHODCALLTYPE put_FaxNumber(
  476. VARIANT vFaxNumber) = 0;
  477. virtual HRESULT STDMETHODCALLTYPE get_OfficeLocations(
  478. VARIANT __RPC_FAR *retval) = 0;
  479. virtual HRESULT STDMETHODCALLTYPE put_OfficeLocations(
  480. VARIANT vOfficeLocations) = 0;
  481. virtual HRESULT STDMETHODCALLTYPE get_PostalAddresses(
  482. VARIANT __RPC_FAR *retval) = 0;
  483. virtual HRESULT STDMETHODCALLTYPE put_PostalAddresses(
  484. VARIANT vPostalAddresses) = 0;
  485. virtual HRESULT STDMETHODCALLTYPE get_PostalCodes(
  486. VARIANT __RPC_FAR *retval) = 0;
  487. virtual HRESULT STDMETHODCALLTYPE put_PostalCodes(
  488. VARIANT vPostalCodes) = 0;
  489. virtual HRESULT STDMETHODCALLTYPE get_SeeAlso(
  490. VARIANT __RPC_FAR *retval) = 0;
  491. virtual HRESULT STDMETHODCALLTYPE put_SeeAlso(
  492. VARIANT vSeeAlso) = 0;
  493. */
  494. bool GetAccountDisabled()
  495. {
  496. VARIANT_BOOL b;
  497. CheckResult(m_spADsUser->get_AccountDisabled(&b));
  498. return b ? true : false;
  499. }
  500. void SetAccountDisabled(bool bAccountDisabled)
  501. {
  502. CheckResult(m_spADsUser->put_AccountDisabled(bAccountDisabled ? VARIANT_TRUE : VARIANT_FALSE));
  503. }
  504. /*
  505. virtual HRESULT STDMETHODCALLTYPE get_AccountExpirationDate(
  506. DATE __RPC_FAR *retval) = 0;
  507. virtual HRESULT STDMETHODCALLTYPE put_AccountExpirationDate(
  508. DATE daAccountExpirationDate) = 0;
  509. virtual HRESULT STDMETHODCALLTYPE get_GraceLoginsAllowed(
  510. long __RPC_FAR *retval) = 0;
  511. virtual HRESULT STDMETHODCALLTYPE put_GraceLoginsAllowed(
  512. long lnGraceLoginsAllowed) = 0;
  513. virtual HRESULT STDMETHODCALLTYPE get_GraceLoginsRemaining(
  514. long __RPC_FAR *retval) = 0;
  515. virtual HRESULT STDMETHODCALLTYPE put_GraceLoginsRemaining(
  516. long lnGraceLoginsRemaining) = 0;
  517. virtual HRESULT STDMETHODCALLTYPE get_IsAccountLocked(
  518. VARIANT_BOOL __RPC_FAR *retval) = 0;
  519. virtual HRESULT STDMETHODCALLTYPE put_IsAccountLocked(
  520. VARIANT_BOOL fIsAccountLocked) = 0;
  521. virtual HRESULT STDMETHODCALLTYPE get_LoginHours(
  522. VARIANT __RPC_FAR *retval) = 0;
  523. virtual HRESULT STDMETHODCALLTYPE put_LoginHours(
  524. VARIANT vLoginHours) = 0;
  525. virtual HRESULT STDMETHODCALLTYPE get_LoginWorkstations(
  526. VARIANT __RPC_FAR *retval) = 0;
  527. virtual HRESULT STDMETHODCALLTYPE put_LoginWorkstations(
  528. VARIANT vLoginWorkstations) = 0;
  529. virtual HRESULT STDMETHODCALLTYPE get_MaxLogins(
  530. long __RPC_FAR *retval) = 0;
  531. virtual HRESULT STDMETHODCALLTYPE put_MaxLogins(
  532. long lnMaxLogins) = 0;
  533. virtual HRESULT STDMETHODCALLTYPE get_MaxStorage(
  534. long __RPC_FAR *retval) = 0;
  535. virtual HRESULT STDMETHODCALLTYPE put_MaxStorage(
  536. long lnMaxStorage) = 0;
  537. virtual HRESULT STDMETHODCALLTYPE get_PasswordExpirationDate(
  538. DATE __RPC_FAR *retval) = 0;
  539. virtual HRESULT STDMETHODCALLTYPE put_PasswordExpirationDate(
  540. DATE daPasswordExpirationDate) = 0;
  541. virtual HRESULT STDMETHODCALLTYPE get_PasswordMinimumLength(
  542. long __RPC_FAR *retval) = 0;
  543. virtual HRESULT STDMETHODCALLTYPE put_PasswordMinimumLength(
  544. long lnPasswordMinimumLength) = 0;
  545. virtual HRESULT STDMETHODCALLTYPE get_PasswordRequired(
  546. VARIANT_BOOL __RPC_FAR *retval) = 0;
  547. virtual HRESULT STDMETHODCALLTYPE put_PasswordRequired(
  548. VARIANT_BOOL fPasswordRequired) = 0;
  549. virtual HRESULT STDMETHODCALLTYPE get_RequireUniquePassword(
  550. VARIANT_BOOL __RPC_FAR *retval) = 0;
  551. virtual HRESULT STDMETHODCALLTYPE put_RequireUniquePassword(
  552. VARIANT_BOOL fRequireUniquePassword) = 0;
  553. virtual HRESULT STDMETHODCALLTYPE get_EmailAddress(
  554. BSTR __RPC_FAR *retval) = 0;
  555. virtual HRESULT STDMETHODCALLTYPE put_EmailAddress(
  556. BSTR bstrEmailAddress) = 0;
  557. virtual HRESULT STDMETHODCALLTYPE get_HomeDirectory(
  558. BSTR __RPC_FAR *retval) = 0;
  559. virtual HRESULT STDMETHODCALLTYPE put_HomeDirectory(
  560. BSTR bstrHomeDirectory) = 0;
  561. virtual HRESULT STDMETHODCALLTYPE get_Languages(
  562. VARIANT __RPC_FAR *retval) = 0;
  563. virtual HRESULT STDMETHODCALLTYPE put_Languages(
  564. VARIANT vLanguages) = 0;
  565. virtual HRESULT STDMETHODCALLTYPE get_Profile(
  566. BSTR __RPC_FAR *retval) = 0;
  567. virtual HRESULT STDMETHODCALLTYPE put_Profile(
  568. BSTR bstrProfile) = 0;
  569. virtual HRESULT STDMETHODCALLTYPE get_LoginScript(
  570. BSTR __RPC_FAR *retval) = 0;
  571. virtual HRESULT STDMETHODCALLTYPE put_LoginScript(
  572. BSTR bstrLoginScript) = 0;
  573. virtual HRESULT STDMETHODCALLTYPE get_Picture(
  574. VARIANT __RPC_FAR *retval) = 0;
  575. virtual HRESULT STDMETHODCALLTYPE put_Picture(
  576. VARIANT vPicture) = 0;
  577. virtual HRESULT STDMETHODCALLTYPE get_HomePage(
  578. BSTR __RPC_FAR *retval) = 0;
  579. virtual HRESULT STDMETHODCALLTYPE put_HomePage(
  580. BSTR bstrHomePage) = 0;
  581. virtual HRESULT STDMETHODCALLTYPE Groups(
  582. IADsMembers __RPC_FAR *__RPC_FAR *ppGroups) = 0;
  583. */
  584. void SetPassword(_bstr_t strNewPassword)
  585. {
  586. CheckResult(m_spADsUser->SetPassword(strNewPassword));
  587. }
  588. void ChangePassword(_bstr_t strOldPassword, _bstr_t strNewPassword)
  589. {
  590. CheckResult(m_spADsUser->ChangePassword(strOldPassword, strNewPassword));
  591. }
  592. protected:
  593. void CheckResult(HRESULT hr)
  594. {
  595. if (FAILED(hr))
  596. {
  597. _com_issue_errorex(hr, IUnknownPtr(m_spADsUser), IID_IADsUser);
  598. }
  599. }
  600. protected:
  601. IADsUserPtr m_spADsUser;
  602. };
  603. //---------------------------------------------------------------------------
  604. // CADsADSystemInfo Class
  605. //---------------------------------------------------------------------------
  606. class CADsADSystemInfo
  607. {
  608. public:
  609. CADsADSystemInfo() :
  610. m_sp(CLSID_ADSystemInfo)
  611. {
  612. }
  613. CADsADSystemInfo(IADsADSystemInfo* pADsADSystemInfo) :
  614. m_sp(pADsADSystemInfo)
  615. {
  616. }
  617. CADsADSystemInfo(const CADsADSystemInfo& r) :
  618. m_sp(r.m_sp)
  619. {
  620. }
  621. operator IADsADSystemInfo*() const
  622. {
  623. return m_sp;
  624. }
  625. _bstr_t GetUserName()
  626. {
  627. BSTR bstr;
  628. CheckResult(m_sp->get_UserName(&bstr));
  629. return _bstr_t(bstr, false);
  630. }
  631. _bstr_t GetComputerName()
  632. {
  633. BSTR bstr;
  634. CheckResult(m_sp->get_ComputerName(&bstr));
  635. return _bstr_t(bstr, false);
  636. }
  637. _bstr_t GetSiteName()
  638. {
  639. BSTR bstr;
  640. CheckResult(m_sp->get_SiteName(&bstr));
  641. return _bstr_t(bstr, false);
  642. }
  643. _bstr_t GetDomainShortName()
  644. {
  645. BSTR bstr;
  646. CheckResult(m_sp->get_DomainShortName(&bstr));
  647. return _bstr_t(bstr, false);
  648. }
  649. _bstr_t GetDomainDNSName()
  650. {
  651. BSTR bstr;
  652. CheckResult(m_sp->get_DomainDNSName(&bstr));
  653. return _bstr_t(bstr, false);
  654. }
  655. _bstr_t GetForestDNSName()
  656. {
  657. BSTR bstr;
  658. CheckResult(m_sp->get_ForestDNSName(&bstr));
  659. return _bstr_t(bstr, false);
  660. }
  661. _bstr_t GetPDCRoleOwner()
  662. {
  663. BSTR bstr;
  664. CheckResult(m_sp->get_PDCRoleOwner(&bstr));
  665. return _bstr_t(bstr, false);
  666. }
  667. _bstr_t GetSchemaRoleOwner()
  668. {
  669. BSTR bstr;
  670. CheckResult(m_sp->get_SchemaRoleOwner(&bstr));
  671. return _bstr_t(bstr, false);
  672. }
  673. bool GetIsNativeMode()
  674. {
  675. VARIANT_BOOL b;
  676. CheckResult(m_sp->get_IsNativeMode(&b));
  677. return b ? true : false;
  678. }
  679. _bstr_t GetAnyDCName()
  680. {
  681. BSTR bstr;
  682. CheckResult(m_sp->GetAnyDCName(&bstr));
  683. return _bstr_t(bstr, false);
  684. }
  685. _bstr_t GetDCSiteName(_bstr_t strServer)
  686. {
  687. BSTR bstr;
  688. CheckResult(m_sp->GetDCSiteName(strServer, &bstr));
  689. return _bstr_t(bstr, false);
  690. }
  691. void RefreshSchemaCache()
  692. {
  693. CheckResult(m_sp->RefreshSchemaCache());
  694. }
  695. _variant_t GetTrees()
  696. {
  697. VARIANT vnt;
  698. CheckResult(m_sp->GetTrees(&vnt));
  699. return _variant_t(vnt, false);
  700. }
  701. protected:
  702. void CheckResult(HRESULT hr)
  703. {
  704. if (FAILED(hr))
  705. {
  706. _com_issue_errorex(hr, IUnknownPtr(m_sp), IID_IADsADSystemInfo);
  707. }
  708. }
  709. protected:
  710. IADsADSystemInfoPtr m_sp;
  711. };
  712. //---------------------------------------------------------------------------
  713. // CADsPathName Class
  714. //---------------------------------------------------------------------------
  715. class CADsPathName
  716. {
  717. // ADS_DISPLAY_ENUM
  718. // ADS_DISPLAY_FULL = 1
  719. // ADS_DISPLAY_VALUE_ONLY = 2
  720. // ADS_FORMAT_ENUM
  721. // ADS_FORMAT_WINDOWS = 1
  722. // ADS_FORMAT_WINDOWS_NO_SERVER = 2
  723. // ADS_FORMAT_WINDOWS_DN = 3
  724. // ADS_FORMAT_WINDOWS_PARENT = 4
  725. // ADS_FORMAT_X500 = 5
  726. // ADS_FORMAT_X500_NO_SERVER = 6
  727. // ADS_FORMAT_X500_DN = 7
  728. // ADS_FORMAT_X500_PARENT = 8
  729. // ADS_FORMAT_SERVER = 9
  730. // ADS_FORMAT_PROVIDER = 10
  731. // ADS_FORMAT_LEAF = 11
  732. // ADS_SETTYPE_ENUM
  733. // ADS_SETTYPE_FULL = 1
  734. // ADS_SETTYPE_PROVIDER = 2
  735. // ADS_SETTYPE_SERVER = 3
  736. // ADS_SETTYPE_DN = 4
  737. public:
  738. CADsPathName(_bstr_t strPath = _bstr_t(), long lSetType = ADS_SETTYPE_FULL) :
  739. m_sp(CLSID_Pathname)
  740. {
  741. if (strPath.length() > 0)
  742. {
  743. CheckResult(m_sp->Set(strPath, lSetType));
  744. }
  745. }
  746. void Set(_bstr_t strADsPath, long lSetType)
  747. {
  748. CheckResult(m_sp->Set(strADsPath, lSetType));
  749. }
  750. void SetDisplayType(long lDisplayType)
  751. {
  752. CheckResult(m_sp->SetDisplayType(lDisplayType));
  753. }
  754. _bstr_t Retrieve(long lFormatType)
  755. {
  756. BSTR bstr;
  757. CheckResult(m_sp->Retrieve(lFormatType, &bstr));
  758. return _bstr_t(bstr, false);
  759. }
  760. long GetNumElements()
  761. {
  762. long l;
  763. CheckResult(m_sp->GetNumElements(&l));
  764. return l;
  765. }
  766. _bstr_t GetElement(long lElementIndex)
  767. {
  768. BSTR bstr;
  769. CheckResult(m_sp->GetElement(lElementIndex, &bstr));
  770. return _bstr_t(bstr, false);
  771. }
  772. void AddLeafElement(_bstr_t strLeafElement)
  773. {
  774. CheckResult(m_sp->AddLeafElement(strLeafElement));
  775. }
  776. void RemoveLeafElement()
  777. {
  778. CheckResult(m_sp->RemoveLeafElement());
  779. }
  780. CADsPathName CopyPath()
  781. {
  782. IDispatch* pdisp;
  783. CheckResult(m_sp->CopyPath(&pdisp));
  784. return CADsPathName(IADsPathnamePtr(IDispatchPtr(pdisp, false)));
  785. }
  786. _bstr_t GetEscapedElement(long lReserved, _bstr_t strInStr)
  787. {
  788. BSTR bstr;
  789. CheckResult(m_sp->GetEscapedElement(lReserved, strInStr, &bstr));
  790. return _bstr_t(bstr, false);
  791. }
  792. long GetEscapedMode()
  793. {
  794. long l;
  795. CheckResult(m_sp->get_EscapedMode(&l));
  796. return l;
  797. }
  798. void PutEscapedMode(long l)
  799. {
  800. CheckResult(m_sp->put_EscapedMode(l));
  801. }
  802. protected:
  803. CADsPathName(const CADsPathName& r) :
  804. m_sp(r.m_sp)
  805. {
  806. }
  807. CADsPathName(IADsPathnamePtr& r) :
  808. m_sp(r)
  809. {
  810. }
  811. void CheckResult(HRESULT hr)
  812. {
  813. if (FAILED(hr))
  814. {
  815. _com_issue_errorex(hr, IUnknownPtr(m_sp), IID_IADsPathname);
  816. }
  817. }
  818. protected:
  819. IADsPathnamePtr m_sp;
  820. };
  821. //---------------------------------------------------------------------------
  822. // Directory Attributes Class
  823. //---------------------------------------------------------------------------
  824. class CDirectoryAttributes :
  825. public std::map<tstring, _variant_t>
  826. {
  827. public:
  828. CDirectoryAttributes()
  829. {
  830. }
  831. //
  832. void AddAttribute(LPCTSTR pszName)
  833. {
  834. insert(value_type(tstring(pszName), _variant_t()));
  835. }
  836. void ClearValues()
  837. {
  838. for (iterator it = begin(); it != end(); it++)
  839. {
  840. it->second.Clear();
  841. }
  842. }
  843. const _variant_t& GetValue(LPCTSTR pszName) const
  844. {
  845. static _variant_t s_vntEmptyValue;
  846. const_iterator it = find(tstring(pszName));
  847. if (it != end())
  848. {
  849. return it->second;
  850. }
  851. else
  852. {
  853. return s_vntEmptyValue;
  854. }
  855. }
  856. void SetADsValue(LPCTSTR pszName, ADSTYPE atType, PADSVALUE pavValue, DWORD dwCount)
  857. {
  858. iterator it = find(tstring(pszName));
  859. if (it != end())
  860. {
  861. GetADsValue(atType, pavValue, dwCount, it->second);
  862. }
  863. }
  864. protected:
  865. void GetADsValue(ADSTYPE atType, PADSVALUE pavValue, DWORD dwCount, _variant_t& vntValue)
  866. {
  867. switch (atType)
  868. {
  869. case ADSTYPE_DN_STRING:
  870. {
  871. vntValue = pavValue->DNString;
  872. break;
  873. }
  874. case ADSTYPE_CASE_EXACT_STRING:
  875. {
  876. if (dwCount == 1)
  877. {
  878. vntValue = pavValue->CaseExactString;
  879. }
  880. else
  881. {
  882. vntValue.vt = VT_ARRAY|VT_BSTR;
  883. vntValue.parray = SafeArrayCreateVector(VT_BSTR, 0, dwCount);
  884. PADSVALUE pav = pavValue;
  885. BSTR* pbstr = (BSTR*)vntValue.parray->pvData;
  886. for (DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++, pav++)
  887. {
  888. *pbstr++ = SysAllocString(pav->CaseExactString);
  889. }
  890. }
  891. break;
  892. }
  893. case ADSTYPE_CASE_IGNORE_STRING:
  894. {
  895. if (dwCount == 1)
  896. {
  897. vntValue = pavValue->CaseIgnoreString;
  898. }
  899. else
  900. {
  901. vntValue.vt = VT_ARRAY|VT_BSTR;
  902. vntValue.parray = SafeArrayCreateVector(VT_BSTR, 0, dwCount);
  903. PADSVALUE pav = pavValue;
  904. BSTR* pbstr = (BSTR*)vntValue.parray->pvData;
  905. for (DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++, pav++)
  906. {
  907. *pbstr++ = SysAllocString(pav->CaseIgnoreString);
  908. }
  909. }
  910. break;
  911. }
  912. case ADSTYPE_PRINTABLE_STRING:
  913. {
  914. vntValue = pavValue->PrintableString;
  915. break;
  916. }
  917. case ADSTYPE_NUMERIC_STRING:
  918. {
  919. vntValue = pavValue->NumericString;
  920. break;
  921. }
  922. case ADSTYPE_BOOLEAN:
  923. {
  924. vntValue = pavValue->Boolean ? true : false;
  925. break;
  926. }
  927. case ADSTYPE_INTEGER:
  928. {
  929. vntValue = static_cast<long>(pavValue->Integer);
  930. break;
  931. }
  932. case ADSTYPE_OCTET_STRING:
  933. {
  934. vntValue.vt = VT_ARRAY|VT_UI1;
  935. vntValue.parray = SafeArrayCreateVector(VT_UI1, 0, pavValue->OctetString.dwLength);
  936. memcpy(vntValue.parray->pvData, pavValue->OctetString.lpValue, pavValue->OctetString.dwLength);
  937. break;
  938. }
  939. case ADSTYPE_UTC_TIME:
  940. {
  941. DATE dt;
  942. SystemTimeToVariantTime(&pavValue->UTCTime, &dt);
  943. vntValue = dt;
  944. vntValue.ChangeType(VT_DATE);
  945. break;
  946. }
  947. // case ADSTYPE_LARGE_INTEGER:
  948. case ADSTYPE_OBJECT_CLASS:
  949. {
  950. if (dwCount == 1)
  951. {
  952. vntValue = pavValue->ClassName;
  953. }
  954. else
  955. {
  956. vntValue.vt = VT_ARRAY|VT_BSTR;
  957. vntValue.parray = SafeArrayCreateVector(VT_BSTR, 0, dwCount);
  958. PADSVALUE pav = pavValue;
  959. BSTR* pbstr = (BSTR*)vntValue.parray->pvData;
  960. for (DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++, pav++)
  961. {
  962. *pbstr++ = SysAllocString(pav->ClassName);
  963. }
  964. }
  965. break;
  966. }
  967. // case ADSTYPE_PROV_SPECIFIC:
  968. // case ADSTYPE_CASEIGNORE_LIST:
  969. // case ADSTYPE_OCTET_LIST:
  970. // case ADSTYPE_PATH:
  971. // case ADSTYPE_POSTALADDRESS:
  972. // case ADSTYPE_TIMESTAMP:
  973. // case ADSTYPE_BACKLINK:
  974. // case ADSTYPE_TYPEDNAME:
  975. // case ADSTYPE_HOLD:
  976. // case ADSTYPE_NETADDRESS:
  977. // case ADSTYPE_REPLICAPOINTER:
  978. // case ADSTYPE_FAXNUMBER:
  979. // case ADSTYPE_EMAIL:
  980. case ADSTYPE_NT_SECURITY_DESCRIPTOR:
  981. {
  982. ADS_NT_SECURITY_DESCRIPTOR& sd = pavValue->SecurityDescriptor;
  983. vntValue.vt = VT_ARRAY|VT_UI1;
  984. vntValue.parray = SafeArrayCreateVector(VT_UI1, 0, sd.dwLength);
  985. memcpy(vntValue.parray->pvData, sd.lpValue, sd.dwLength);
  986. break;
  987. }
  988. // case ADSTYPE_DN_WITH_BINARY:
  989. // case ADSTYPE_DN_WITH_STRING:
  990. default:
  991. {
  992. vntValue.Clear();
  993. break;
  994. }
  995. }
  996. }
  997. };
  998. //---------------------------------------------------------------------------
  999. // Directory Attributes Name Array Class
  1000. //---------------------------------------------------------------------------
  1001. class CDirectoryAttributesNameArray
  1002. {
  1003. public:
  1004. CDirectoryAttributesNameArray(const CDirectoryAttributes& daAttributes) :
  1005. m_ppszNames(NULL)
  1006. {
  1007. m_ppszNames = new LPTSTR[daAttributes.size()];
  1008. if (m_ppszNames)
  1009. {
  1010. LPTSTR* ppsz = m_ppszNames;
  1011. for (CDirectoryAttributes::const_iterator it = daAttributes.begin(); it != daAttributes.end(); it++)
  1012. {
  1013. *ppsz++ = const_cast<LPTSTR>(it->first.c_str());
  1014. }
  1015. }
  1016. else
  1017. {
  1018. _com_issue_error(E_OUTOFMEMORY);
  1019. }
  1020. }
  1021. ~CDirectoryAttributesNameArray()
  1022. {
  1023. if (m_ppszNames)
  1024. {
  1025. delete [] m_ppszNames;
  1026. }
  1027. }
  1028. operator LPTSTR*()
  1029. {
  1030. return m_ppszNames;
  1031. }
  1032. protected:
  1033. LPTSTR* m_ppszNames;
  1034. };
  1035. #define ATTRIBUTE_ADS_PATH _T("ADsPath")
  1036. #define ATTRIBUTE_CANONICAL_NAME _T("canonicalName")
  1037. #define ATTRIBUTE_DISTINGUISHED_NAME _T("distinguishedName")
  1038. #define ATTRIBUTE_NAME _T("name")
  1039. #define ATTRIBUTE_OBJECT_CATEGORY _T("objectCategory")
  1040. #define ATTRIBUTE_OBJECT_CLASS _T("objectClass")
  1041. #define ATTRIBUTE_OBJECT_SID _T("objectSid")
  1042. #define ATTRIBUTE_SAM_ACCOUNT_NAME _T("sAMAccountName")
  1043. #define ATTRIBUTE_USER_ACCOUNT_CONTROL _T("userAccountControl")
  1044. #define ATTRIBUTE_USER_PRINCIPAL_NAME _T("userPrincipalName")
  1045. //---------------------------------------------------------------------------
  1046. // Directory Object Class
  1047. //---------------------------------------------------------------------------
  1048. class CDirectoryObject
  1049. {
  1050. public:
  1051. CDirectoryObject(LPCTSTR pszPath = NULL)
  1052. {
  1053. if (pszPath)
  1054. {
  1055. _com_util::CheckError(ADsGetObject(pszPath, IID_IDirectoryObject, (VOID**)&m_spObject));
  1056. }
  1057. }
  1058. CDirectoryObject(IDispatchPtr spDispatch) :
  1059. m_spObject(spDispatch)
  1060. {
  1061. }
  1062. ~CDirectoryObject()
  1063. {
  1064. if (m_spObject)
  1065. {
  1066. m_spObject.Release();
  1067. }
  1068. }
  1069. CDirectoryObject& operator =(LPCTSTR pszPath)
  1070. {
  1071. _com_util::CheckError(ADsGetObject(pszPath, IID_IDirectoryObject, (VOID**)&m_spObject));
  1072. return *this;
  1073. }
  1074. void AddAttribute(LPCTSTR pszName)
  1075. {
  1076. m_daAttributes.AddAttribute(pszName);
  1077. }
  1078. void GetAttributes()
  1079. {
  1080. PADS_ATTR_INFO pAttrInfo = NULL;
  1081. try
  1082. {
  1083. // clear any existing attribute values
  1084. m_daAttributes.ClearValues();
  1085. // get attribute values
  1086. DWORD cAttr;
  1087. _com_util::CheckError(
  1088. m_spObject->GetObjectAttributes(
  1089. CDirectoryAttributesNameArray(m_daAttributes), m_daAttributes.size(), &pAttrInfo, &cAttr
  1090. )
  1091. );
  1092. // assign attribute values to directory attributes
  1093. PADS_ATTR_INFO pai = pAttrInfo;
  1094. for (DWORD iAttr = 0; iAttr < cAttr; iAttr++, pai++)
  1095. {
  1096. m_daAttributes.SetADsValue(pai->pszAttrName, pai->dwADsType, pai->pADsValues, pai->dwNumValues);
  1097. }
  1098. // clean up
  1099. if (pAttrInfo)
  1100. {
  1101. FreeADsMem(pAttrInfo);
  1102. }
  1103. }
  1104. catch (...)
  1105. {
  1106. if (pAttrInfo)
  1107. {
  1108. FreeADsMem(pAttrInfo);
  1109. }
  1110. throw;
  1111. }
  1112. }
  1113. const _variant_t& GetAttributeValue(LPCTSTR pszName)
  1114. {
  1115. return m_daAttributes.GetValue(pszName);
  1116. }
  1117. protected:
  1118. IDirectoryObjectPtr m_spObject;
  1119. CDirectoryAttributes m_daAttributes;
  1120. };
  1121. //---------------------------------------------------------------------------
  1122. // DirectorySearch Class
  1123. //---------------------------------------------------------------------------
  1124. class CDirectorySearch
  1125. {
  1126. public:
  1127. //
  1128. CDirectorySearch() :
  1129. m_hSearch(NULL)
  1130. {
  1131. }
  1132. CDirectorySearch(IDispatchPtr spDispatch) :
  1133. m_spSearch(spDispatch),
  1134. m_hSearch(NULL)
  1135. {
  1136. }
  1137. ~CDirectorySearch()
  1138. {
  1139. CloseSearchHandle();
  1140. }
  1141. void operator =(const IDispatchPtr& spDispatch)
  1142. {
  1143. m_spSearch = spDispatch;
  1144. }
  1145. //
  1146. void SetFilter(LPCTSTR pszFilter)
  1147. {
  1148. m_strFilter = pszFilter;
  1149. }
  1150. void SetPreferences(ADS_INTEGER nScope = ADS_SCOPE_SUBTREE)
  1151. {
  1152. ADS_SEARCHPREF_INFO siPreferences[4];
  1153. siPreferences[0].dwSearchPref = ADS_SEARCHPREF_ASYNCHRONOUS;
  1154. siPreferences[0].vValue.dwType = ADSTYPE_BOOLEAN;
  1155. siPreferences[0].vValue.Integer = TRUE;
  1156. siPreferences[1].dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS;
  1157. siPreferences[1].vValue.dwType = ADSTYPE_BOOLEAN;
  1158. siPreferences[1].vValue.Integer = FALSE;
  1159. siPreferences[2].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  1160. siPreferences[2].vValue.dwType = ADSTYPE_INTEGER;
  1161. siPreferences[2].vValue.Integer = 100;
  1162. siPreferences[3].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  1163. siPreferences[3].vValue.dwType = ADSTYPE_INTEGER;
  1164. siPreferences[3].vValue.Integer = nScope;
  1165. m_spSearch->SetSearchPreference(siPreferences, sizeof(siPreferences) / sizeof(siPreferences[0]));
  1166. }
  1167. void AddAttribute(LPCTSTR pszName)
  1168. {
  1169. m_daAttributes.AddAttribute(pszName);
  1170. }
  1171. void Search()
  1172. {
  1173. CloseSearchHandle();
  1174. _com_util::CheckError(m_spSearch->ExecuteSearch(
  1175. const_cast<LPTSTR>(m_strFilter.c_str()),
  1176. CDirectoryAttributesNameArray(m_daAttributes),
  1177. m_daAttributes.size(),
  1178. &m_hSearch
  1179. ));
  1180. }
  1181. bool GetFirstRow()
  1182. {
  1183. bool bGet = false;
  1184. HRESULT hr = m_spSearch->GetFirstRow(m_hSearch);
  1185. if (FAILED(hr))
  1186. {
  1187. _com_issue_error(hr);
  1188. }
  1189. if (hr == S_OK)
  1190. {
  1191. GetColumns();
  1192. bGet = true;
  1193. }
  1194. return bGet;
  1195. }
  1196. bool GetNextRow()
  1197. {
  1198. bool bGet = false;
  1199. HRESULT hr = m_spSearch->GetNextRow(m_hSearch);
  1200. if (FAILED(hr))
  1201. {
  1202. _com_issue_error(hr);
  1203. }
  1204. if (hr == S_OK)
  1205. {
  1206. GetColumns();
  1207. bGet = true;
  1208. }
  1209. return bGet;
  1210. }
  1211. const _variant_t& GetAttributeValue(LPCTSTR pszName)
  1212. {
  1213. return m_daAttributes.GetValue(pszName);
  1214. }
  1215. protected:
  1216. void GetColumns()
  1217. {
  1218. for (CDirectoryAttributes::iterator it = m_daAttributes.begin(); it != m_daAttributes.end(); it++)
  1219. {
  1220. const tstring& strName = it->first;
  1221. ADS_SEARCH_COLUMN scColumn;
  1222. if (m_spSearch->GetColumn(m_hSearch, const_cast<LPTSTR>(strName.c_str()), &scColumn) == S_OK)
  1223. {
  1224. m_daAttributes.SetADsValue(strName.c_str(), scColumn.dwADsType, scColumn.pADsValues, scColumn.dwNumValues);
  1225. m_spSearch->FreeColumn(&scColumn);
  1226. }
  1227. else
  1228. {
  1229. it->second.Clear();
  1230. }
  1231. }
  1232. }
  1233. void CloseSearchHandle()
  1234. {
  1235. if (m_hSearch)
  1236. {
  1237. m_spSearch->CloseSearchHandle(m_hSearch);
  1238. m_hSearch = NULL;
  1239. }
  1240. }
  1241. protected:
  1242. IDirectorySearchPtr m_spSearch;
  1243. tstring m_strFilter;
  1244. CDirectoryAttributes m_daAttributes;
  1245. ADS_SEARCH_HANDLE m_hSearch;
  1246. };