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.

1176 lines
25 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 1992 - 1995
  6. //
  7. // File: cdomain.cxx
  8. //
  9. // Contents: Windows NT 3.5
  10. //
  11. //
  12. // History: 01-30-95 krishnag Created.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "winnt.hxx"
  16. #pragma hdrstop
  17. DECLARE_INFOLEVEL( Domain );
  18. DECLARE_DEBUG( Domain );
  19. #define DomainDebugOut(x) DomainInlineDebugOut x
  20. // Class CWinNTDomain
  21. DEFINE_IDispatch_ExtMgr_Implementation(CWinNTDomain)
  22. DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTDomain)
  23. DEFINE_IADs_TempImplementation(CWinNTDomain)
  24. DEFINE_IADs_PutGetImplementation(CWinNTDomain, DomainClass, gdwDomainTableSize)
  25. DEFINE_IADsPropertyList_Implementation(CWinNTDomain, DomainClass, gdwDomainTableSize)
  26. HRESULT
  27. MoveUserGroupObject(
  28. THIS_ BSTR SourceName,
  29. BSTR NewName,
  30. BSTR bstrParentADsPath,
  31. CWinNTCredentials& Credentials,
  32. IDispatch * FAR* ppObject
  33. );
  34. CWinNTDomain::CWinNTDomain() :
  35. _pDispMgr(NULL),
  36. _pExtMgr(NULL),
  37. _pPropertyCache(NULL)
  38. {
  39. VariantInit(&_vFilter);
  40. ENLIST_TRACKING(CWinNTDomain);
  41. }
  42. HRESULT
  43. CWinNTDomain::CreateDomain(
  44. BSTR Parent,
  45. BSTR DomainName,
  46. DWORD dwObjectState,
  47. REFIID riid,
  48. CWinNTCredentials& Credentials,
  49. void **ppvObj
  50. )
  51. {
  52. CWinNTDomain FAR * pDomain = NULL;
  53. NET_API_STATUS nasStatus;
  54. HRESULT hr = S_OK;
  55. hr = AllocateDomainObject(&pDomain);
  56. BAIL_ON_FAILURE(hr);
  57. ADsAssert(pDomain->_pDispMgr);
  58. hr = pDomain->InitializeCoreObject(
  59. Parent,
  60. DomainName,
  61. DOMAIN_CLASS_NAME,
  62. DOMAIN_SCHEMA_NAME,
  63. CLSID_WinNTDomain,
  64. dwObjectState
  65. );
  66. BAIL_ON_FAILURE(hr);
  67. pDomain->_Credentials = Credentials;
  68. hr = pDomain->_Credentials.RefDomain(DomainName);
  69. BAIL_ON_FAILURE(hr);
  70. //
  71. // Load ext mgr and extensions
  72. //
  73. hr = ADSILoadExtensionManager(
  74. DOMAIN_CLASS_NAME,
  75. (IADsDomain *) pDomain,
  76. pDomain->_pDispMgr,
  77. Credentials,
  78. &pDomain->_pExtMgr
  79. );
  80. BAIL_ON_FAILURE(hr);
  81. ADsAssert(pDomain->_pExtMgr);
  82. // check if the call is from UMI
  83. if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
  84. //
  85. // we do not pass riid to InitUmiObject below. This is because UMI object
  86. // does not support IDispatch. There are several places in ADSI code where
  87. // riid passed into this function is defaulted to IID_IDispatch -
  88. // IADsContainer::Create for example. To handle these cases, we always
  89. // request IID_IUnknown from the UMI object. Subsequent code within UMI
  90. // will QI for the appropriate interface.
  91. //
  92. if(1 == pDomain->_dwNumComponents)
  93. pDomain->_CompClasses[0] = L"Domain";
  94. else
  95. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  96. hr = pDomain->InitUmiObject(
  97. pDomain->_Credentials,
  98. DomainClass,
  99. gdwDomainTableSize,
  100. pDomain->_pPropertyCache,
  101. (IUnknown *) (INonDelegatingUnknown *) pDomain,
  102. pDomain->_pExtMgr,
  103. IID_IUnknown,
  104. ppvObj
  105. );
  106. BAIL_ON_FAILURE(hr);
  107. //
  108. // UMI object was created and the interface was obtained successfully.
  109. // UMI object now has a reference to the inner unknown of IADs, since
  110. // the call to Release() below is not going to be made in this case.
  111. //
  112. RRETURN(hr);
  113. }
  114. hr = pDomain->QueryInterface(riid, ppvObj);
  115. BAIL_ON_FAILURE(hr);
  116. pDomain->Release();
  117. RRETURN(hr);
  118. error:
  119. delete pDomain;
  120. RRETURN_EXP_IF_ERR(hr);
  121. }
  122. CWinNTDomain::~CWinNTDomain( )
  123. {
  124. VariantClear(&_vFilter);
  125. delete _pExtMgr; // created last, destroyed first
  126. delete _pDispMgr;
  127. delete _pPropertyCache;
  128. }
  129. //----------------------------------------------------------------------------
  130. // Function: QueryInterface
  131. //
  132. // Synopsis: If this object is aggregated within another object, then
  133. // all calls will delegate to the outer object. Otherwise, the
  134. // non-delegating QI is called
  135. //
  136. // Arguments:
  137. //
  138. // iid interface requested
  139. // ppInterface Returns pointer to interface requested. NULL if interface
  140. // is not supported.
  141. //
  142. // Returns: S_OK on success. Error code otherwise.
  143. //
  144. // Modifies: *ppInterface to return interface pointer
  145. //
  146. //----------------------------------------------------------------------------
  147. STDMETHODIMP CWinNTDomain::QueryInterface(
  148. REFIID iid,
  149. LPVOID *ppInterface
  150. )
  151. {
  152. if(_pUnkOuter != NULL)
  153. RRETURN(_pUnkOuter->QueryInterface(
  154. iid,
  155. ppInterface
  156. ));
  157. RRETURN(NonDelegatingQueryInterface(
  158. iid,
  159. ppInterface
  160. ));
  161. }
  162. //----------------------------------------------------------------------------
  163. // Function: AddRef
  164. //
  165. // Synopsis: IUnknown::AddRef. If this object is aggregated within
  166. // another, all calls will delegate to the outer object.
  167. // Otherwise, the non-delegating AddRef is called
  168. //
  169. // Arguments:
  170. //
  171. // None
  172. //
  173. // Returns: New reference count
  174. //
  175. // Modifies: Nothing
  176. //
  177. //----------------------------------------------------------------------------
  178. STDMETHODIMP_(ULONG) CWinNTDomain::AddRef(void)
  179. {
  180. if(_pUnkOuter != NULL)
  181. RRETURN(_pUnkOuter->AddRef());
  182. RRETURN(NonDelegatingAddRef());
  183. }
  184. //----------------------------------------------------------------------------
  185. // Function: Release
  186. //
  187. // Synopsis: IUnknown::Release. If this object is aggregated within
  188. // another, all calls will delegate to the outer object.
  189. // Otherwise, the non-delegating Release is called
  190. //
  191. // Arguments:
  192. //
  193. // None
  194. //
  195. // Returns: New reference count
  196. //
  197. // Modifies: Nothing
  198. //
  199. //----------------------------------------------------------------------------
  200. STDMETHODIMP_(ULONG) CWinNTDomain::Release(void)
  201. {
  202. if(_pUnkOuter != NULL)
  203. RRETURN(_pUnkOuter->Release());
  204. RRETURN(NonDelegatingRelease());
  205. }
  206. //----------------------------------------------------------------------------
  207. STDMETHODIMP
  208. CWinNTDomain::NonDelegatingQueryInterface(
  209. REFIID iid,
  210. LPVOID FAR* ppv
  211. )
  212. {
  213. HRESULT hr = S_OK;
  214. if (ppv == NULL) {
  215. RRETURN(E_POINTER);
  216. }
  217. if (IsEqualIID(iid, IID_IUnknown))
  218. {
  219. *ppv = (IADsDomain FAR *) this;
  220. }
  221. else if (IsEqualIID(iid, IID_IADsDomain))
  222. {
  223. *ppv = (IADsDomain FAR *) this;
  224. }
  225. else if (IsEqualIID(iid, IID_IADsContainer))
  226. {
  227. *ppv = (IADsContainer FAR *) this;
  228. }
  229. else if (IsEqualIID(iid, IID_IADs))
  230. {
  231. *ppv = (IADs FAR *) this;
  232. }
  233. else if (IsEqualIID(iid, IID_IADsPropertyList))
  234. {
  235. *ppv = (IADsPropertyList FAR *) this;
  236. }
  237. else if (IsEqualIID(iid, IID_IDispatch))
  238. {
  239. *ppv = (IADs FAR *) this;
  240. }
  241. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  242. {
  243. *ppv = (ISupportErrorInfo FAR *) this;
  244. }
  245. else if( (_pDispatch != NULL) &&
  246. IsEqualIID(iid, IID_IADsExtension) )
  247. {
  248. *ppv = (IADsExtension *) this;
  249. }
  250. else if (_pExtMgr)
  251. {
  252. RRETURN( _pExtMgr->QueryInterface(iid, ppv));
  253. }
  254. else
  255. {
  256. *ppv = NULL;
  257. return E_NOINTERFACE;
  258. }
  259. AddRef();
  260. return NOERROR;
  261. }
  262. /* ISupportErrorInfo method */
  263. STDMETHODIMP
  264. CWinNTDomain::InterfaceSupportsErrorInfo(
  265. THIS_ REFIID riid
  266. )
  267. {
  268. if (IsEqualIID(riid, IID_IADs) ||
  269. IsEqualIID(riid, IID_IADsContainer) ||
  270. IsEqualIID(riid, IID_IADsPropertyList) ||
  271. IsEqualIID(riid, IID_IADsDomain)) {
  272. RRETURN(S_OK);
  273. } else {
  274. RRETURN(S_FALSE);
  275. }
  276. }
  277. STDMETHODIMP
  278. CWinNTDomain::SetInfo(THIS)
  279. {
  280. HRESULT hr;
  281. hr = SetInfo(0);
  282. hr = SetInfo(2);
  283. hr = SetInfo(3);
  284. if(SUCCEEDED(hr))
  285. _pPropertyCache->ClearModifiedFlags();
  286. RRETURN_EXP_IF_ERR(hr);
  287. }
  288. STDMETHODIMP
  289. CWinNTDomain::GetInfo(THIS)
  290. {
  291. HRESULT hr;
  292. _pPropertyCache->flushpropcache();
  293. hr = GetInfo(0, TRUE);
  294. hr = GetInfo(2, TRUE);
  295. hr = GetInfo(3, TRUE);
  296. RRETURN_EXP_IF_ERR(hr);
  297. }
  298. STDMETHODIMP
  299. CWinNTDomain::ImplicitGetInfo(THIS)
  300. {
  301. HRESULT hr;
  302. hr = GetInfo(0, FALSE);
  303. hr = GetInfo(2, FALSE);
  304. hr = GetInfo(3, FALSE);
  305. RRETURN_EXP_IF_ERR(hr);
  306. }
  307. /* IADsContainer methods */
  308. STDMETHODIMP
  309. CWinNTDomain::get_Count(long FAR* retval)
  310. {
  311. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  312. }
  313. STDMETHODIMP
  314. CWinNTDomain::get_Filter(THIS_ VARIANT FAR* pVar)
  315. {
  316. HRESULT hr;
  317. VariantInit(pVar);
  318. hr = VariantCopy(pVar, &_vFilter);
  319. RRETURN_EXP_IF_ERR(hr);
  320. }
  321. STDMETHODIMP
  322. CWinNTDomain::put_Filter(THIS_ VARIANT Var)
  323. {
  324. HRESULT hr;
  325. hr = VariantCopy(&_vFilter, &Var);
  326. RRETURN_EXP_IF_ERR(hr);
  327. }
  328. STDMETHODIMP
  329. CWinNTDomain::put_Hints(THIS_ VARIANT Var)
  330. {
  331. RRETURN_EXP_IF_ERR( E_NOTIMPL);
  332. }
  333. STDMETHODIMP
  334. CWinNTDomain::get_Hints(THIS_ VARIANT FAR* pVar)
  335. {
  336. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  337. }
  338. STDMETHODIMP
  339. CWinNTDomain::GetObject(
  340. THIS_ BSTR ClassName,
  341. BSTR RelativeName,
  342. IDispatch * FAR* ppObject
  343. )
  344. {
  345. WCHAR szBuffer[MAX_PATH];
  346. DWORD dwLength = 0;
  347. HRESULT hr = S_OK;
  348. if (!RelativeName || !*RelativeName) {
  349. RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT);
  350. }
  351. //
  352. // Verify that the lenght of the string will not cause overflow.
  353. // +2 for / and \0
  354. //
  355. dwLength = wcslen(_ADsPath) + wcslen(RelativeName) + 2;
  356. if (dwLength > MAX_PATH) {
  357. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  358. }
  359. wcscpy(szBuffer, _ADsPath);
  360. wcscat(szBuffer, L"/");
  361. wcscat(szBuffer, RelativeName);
  362. if (ClassName) {
  363. //
  364. // +1 for the ",".
  365. //
  366. dwLength += wcslen(ClassName) + 1;
  367. //
  368. // Check for buffer overflow again.
  369. //
  370. if (dwLength > MAX_PATH) {
  371. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  372. }
  373. wcscat(szBuffer,L",");
  374. wcscat(szBuffer, ClassName);
  375. }
  376. hr = ::GetObject(
  377. szBuffer,
  378. (LPVOID *)ppObject,
  379. _Credentials
  380. );
  381. BAIL_ON_FAILURE(hr);
  382. error:
  383. RRETURN_EXP_IF_ERR(hr);
  384. }
  385. STDMETHODIMP
  386. CWinNTDomain::get__NewEnum(
  387. THIS_ IUnknown * FAR* retval
  388. )
  389. {
  390. HRESULT hr;
  391. IUnknown FAR* punkEnum=NULL;
  392. IEnumVARIANT * penum = NULL;
  393. *retval = NULL;
  394. hr = CWinNTDomainEnum::Create(
  395. (CWinNTDomainEnum **)&penum,
  396. _ADsPath,
  397. _Name,
  398. _vFilter,
  399. _Credentials
  400. );
  401. BAIL_ON_FAILURE(hr);
  402. hr = penum->QueryInterface(
  403. IID_IUnknown,
  404. (VOID FAR* FAR*)retval
  405. );
  406. BAIL_ON_FAILURE(hr);
  407. if (penum) {
  408. penum->Release();
  409. }
  410. RRETURN(NOERROR);
  411. error:
  412. if (penum) {
  413. delete penum;
  414. }
  415. RRETURN_EXP_IF_ERR(hr);
  416. }
  417. STDMETHODIMP
  418. CWinNTDomain::Create(
  419. THIS_ BSTR ClassName,
  420. BSTR RelativeName,
  421. IDispatch * FAR* ppObject
  422. )
  423. {
  424. ULONG ObjectType = 0;
  425. HRESULT hr;
  426. POBJECTINFO pObjectInfo = NULL;
  427. hr = GetObjectType(
  428. gpFilters,
  429. gdwMaxFilters,
  430. ClassName,
  431. (PDWORD)&ObjectType
  432. );
  433. BAIL_ON_FAILURE(hr);
  434. switch (ObjectType) {
  435. case WINNT_USER_ID:
  436. hr = CWinNTUser::CreateUser(
  437. _ADsPath,
  438. WINNT_DOMAIN_ID,
  439. _Name,
  440. NULL,
  441. RelativeName,
  442. ADS_OBJECT_UNBOUND,
  443. IID_IDispatch,
  444. _Credentials,
  445. (void **)ppObject
  446. );
  447. break;
  448. case WINNT_GROUP_ID:
  449. hr = CWinNTGroup::CreateGroup(
  450. _ADsPath,
  451. WINNT_DOMAIN_ID,
  452. _Name,
  453. NULL,
  454. RelativeName,
  455. WINNT_GROUP_GLOBAL,
  456. ADS_OBJECT_UNBOUND,
  457. IID_IDispatch,
  458. _Credentials,
  459. (void **)ppObject
  460. );
  461. break;
  462. case WINNT_COMPUTER_ID:
  463. hr = CWinNTComputer::CreateComputer(
  464. _ADsPath,
  465. _Name,
  466. RelativeName,
  467. ADS_OBJECT_UNBOUND,
  468. IID_IDispatch,
  469. _Credentials,
  470. (void **)ppObject
  471. );
  472. break;
  473. default:
  474. hr = E_ADS_UNKNOWN_OBJECT;
  475. break;
  476. }
  477. BAIL_ON_FAILURE(hr);
  478. error:
  479. RRETURN_EXP_IF_ERR(hr);
  480. }
  481. STDMETHODIMP
  482. CWinNTDomain::Delete(
  483. BSTR bstrClassName,
  484. BSTR bstrSourceName
  485. )
  486. {
  487. ULONG ObjectType = 0;
  488. POBJECTINFO pObjectInfo = NULL;
  489. BOOL fStatus = FALSE;
  490. HRESULT hr = S_OK;
  491. WCHAR szUncServerName[MAX_PATH];
  492. // Make sure input parameters are valid
  493. if (bstrClassName == NULL || bstrSourceName == NULL) {
  494. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  495. }
  496. hr = GetObjectType(gpFilters,
  497. gdwMaxFilters,
  498. bstrClassName,
  499. (PDWORD)&ObjectType
  500. );
  501. BAIL_ON_FAILURE(hr);
  502. hr = BuildObjectInfo(
  503. _ADsPath,
  504. bstrSourceName,
  505. &pObjectInfo
  506. );
  507. BAIL_ON_FAILURE(hr);
  508. switch (ObjectType) {
  509. case WINNT_USER_ID:
  510. hr = WinNTDeleteUser(pObjectInfo, _Credentials);
  511. break;
  512. case WINNT_GROUP_ID:
  513. //
  514. // for backward compatablity: allow user to delete by classname "group"
  515. //
  516. hr = WinNTDeleteGroup(pObjectInfo, WINNT_GROUP_EITHER, _Credentials);
  517. break;
  518. //
  519. // Global Group and LocalGroup ID's will now goto default
  520. //
  521. case WINNT_COMPUTER_ID:
  522. hr = WinNTDeleteComputer(pObjectInfo, _Credentials);
  523. break;
  524. default:
  525. hr = E_ADS_UNKNOWN_OBJECT;
  526. break;
  527. }
  528. error:
  529. if (pObjectInfo) {
  530. FreeObjectInfo(pObjectInfo);
  531. }
  532. RRETURN_EXP_IF_ERR(hr);
  533. }
  534. STDMETHODIMP
  535. CWinNTDomain::CopyHere(
  536. THIS_ BSTR SourceName,
  537. BSTR NewName,
  538. IDispatch * FAR* ppObject
  539. )
  540. {
  541. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  542. }
  543. STDMETHODIMP
  544. CWinNTDomain::MoveHere(
  545. THIS_ BSTR SourceName,
  546. BSTR NewName,
  547. IDispatch * FAR* ppObject
  548. )
  549. {
  550. return MoveUserGroupObject(SourceName,
  551. NewName,
  552. _ADsPath,
  553. _Credentials,
  554. ppObject);
  555. }
  556. /* IADsDomain methods */
  557. STDMETHODIMP
  558. CWinNTDomain::get_IsWorkgroup(THIS_ VARIANT_BOOL FAR* retval)
  559. {
  560. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  561. }
  562. HRESULT
  563. CWinNTDomain::AllocateDomainObject(
  564. CWinNTDomain ** ppDomain
  565. )
  566. {
  567. CWinNTDomain FAR * pDomain = NULL;
  568. CAggregatorDispMgr FAR * pDispMgr = NULL;
  569. CPropertyCache FAR * pPropertyCache = NULL;
  570. HRESULT hr = S_OK;
  571. pDomain = new CWinNTDomain();
  572. if (pDomain == NULL) {
  573. hr = E_OUTOFMEMORY;
  574. }
  575. BAIL_ON_FAILURE(hr);
  576. pDispMgr = new CAggregatorDispMgr;
  577. if (pDispMgr == NULL) {
  578. hr = E_OUTOFMEMORY;
  579. }
  580. BAIL_ON_FAILURE(hr);
  581. hr = LoadTypeInfoEntry(
  582. pDispMgr,
  583. LIBID_ADs,
  584. IID_IADsDomain,
  585. (IADsDomain *)pDomain,
  586. DISPID_REGULAR
  587. );
  588. BAIL_ON_FAILURE(hr);
  589. hr = LoadTypeInfoEntry(
  590. pDispMgr,
  591. LIBID_ADs,
  592. IID_IADsContainer,
  593. (IADsContainer *)pDomain,
  594. DISPID_NEWENUM
  595. );
  596. BAIL_ON_FAILURE(hr);
  597. hr = LoadTypeInfoEntry(
  598. pDispMgr,
  599. LIBID_ADs,
  600. IID_IADsPropertyList,
  601. (IADsPropertyList *)pDomain,
  602. DISPID_VALUE
  603. );
  604. BAIL_ON_FAILURE(hr);
  605. hr = CPropertyCache::createpropertycache(
  606. DomainClass,
  607. gdwDomainTableSize,
  608. (CCoreADsObject *)pDomain,
  609. &pPropertyCache
  610. );
  611. BAIL_ON_FAILURE(hr);
  612. pDispMgr->RegisterPropertyCache(
  613. pPropertyCache
  614. );
  615. pDomain->_pPropertyCache = pPropertyCache;
  616. pDomain->_pDispMgr = pDispMgr;
  617. *ppDomain = pDomain;
  618. RRETURN(hr);
  619. error:
  620. delete pPropertyCache;
  621. delete pDispMgr;
  622. delete pDomain;
  623. RRETURN(hr);
  624. }
  625. STDMETHODIMP
  626. CWinNTDomain::GetInfo(
  627. THIS_ DWORD dwApiLevel,
  628. BOOL fExplicit
  629. )
  630. {
  631. NET_API_STATUS nasStatus;
  632. LPBYTE lpBuffer = NULL;
  633. HRESULT hr;
  634. WCHAR szPDCName[MAX_PATH];
  635. hr = WinNTGetCachedDCName(
  636. _Name,
  637. szPDCName,
  638. _Credentials.GetFlags()
  639. );
  640. BAIL_ON_FAILURE(hr);
  641. nasStatus = NetUserModalsGet(
  642. szPDCName,
  643. dwApiLevel,
  644. &lpBuffer
  645. );
  646. hr = HRESULT_FROM_WIN32(nasStatus);
  647. BAIL_ON_FAILURE(hr);
  648. hr = UnMarshall(lpBuffer, dwApiLevel, fExplicit);
  649. BAIL_ON_FAILURE(hr);
  650. error:
  651. if (lpBuffer) {
  652. NetApiBufferFree(lpBuffer);
  653. }
  654. RRETURN_EXP_IF_ERR(hr);
  655. }
  656. HRESULT
  657. CWinNTDomain::UnMarshall(
  658. LPBYTE lpBuffer,
  659. DWORD dwApiLevel,
  660. BOOL fExplicit
  661. )
  662. {
  663. HRESULT hr;
  664. ADsAssert(lpBuffer);
  665. switch (dwApiLevel) {
  666. case 0:
  667. hr = UnMarshall_Level0(fExplicit, (LPUSER_MODALS_INFO_0)lpBuffer);
  668. break;
  669. case 2:
  670. hr = UnMarshall_Level2(fExplicit, (LPUSER_MODALS_INFO_2)lpBuffer);
  671. break;
  672. case 3:
  673. hr = UnMarshall_Level3(fExplicit, (LPUSER_MODALS_INFO_3)lpBuffer);
  674. break;
  675. default:
  676. hr = E_FAIL;
  677. }
  678. RRETURN_EXP_IF_ERR(hr);
  679. }
  680. HRESULT
  681. CWinNTDomain::UnMarshall_Level0(
  682. BOOL fExplicit,
  683. LPUSER_MODALS_INFO_0 pUserInfo0
  684. )
  685. {
  686. HRESULT hr = S_OK;
  687. hr = SetDWORDPropertyInCache(
  688. _pPropertyCache,
  689. TEXT("MinPasswordLength"),
  690. pUserInfo0->usrmod0_min_passwd_len,
  691. fExplicit
  692. );
  693. hr = SetDWORDPropertyInCache(
  694. _pPropertyCache,
  695. TEXT("MaxPasswordAge"),
  696. pUserInfo0->usrmod0_max_passwd_age,
  697. fExplicit
  698. );
  699. hr = SetDWORDPropertyInCache(
  700. _pPropertyCache,
  701. TEXT("MinPasswordAge"),
  702. pUserInfo0->usrmod0_min_passwd_age,
  703. fExplicit
  704. );
  705. hr = SetDWORDPropertyInCache(
  706. _pPropertyCache,
  707. TEXT("PasswordHistoryLength"),
  708. pUserInfo0->usrmod0_password_hist_len,
  709. fExplicit
  710. );
  711. hr = SetLPTSTRPropertyInCache(
  712. _pPropertyCache,
  713. TEXT("Name"),
  714. _Name,
  715. fExplicit
  716. );
  717. RRETURN_EXP_IF_ERR(hr);
  718. }
  719. HRESULT
  720. CWinNTDomain::UnMarshall_Level2(
  721. BOOL fExplicit,
  722. LPUSER_MODALS_INFO_2 pUserInfo2
  723. )
  724. {
  725. RRETURN(S_OK);
  726. }
  727. HRESULT
  728. CWinNTDomain::UnMarshall_Level3(
  729. BOOL fExplicit,
  730. LPUSER_MODALS_INFO_3 pUserInfo3
  731. )
  732. {
  733. HRESULT hr = S_OK;
  734. hr = SetDWORDPropertyInCache(
  735. _pPropertyCache,
  736. TEXT("AutoUnlockInterval"),
  737. pUserInfo3->usrmod3_lockout_duration,
  738. fExplicit
  739. );
  740. hr = SetDWORDPropertyInCache(
  741. _pPropertyCache,
  742. TEXT("LockoutObservationInterval"),
  743. pUserInfo3->usrmod3_lockout_observation_window,
  744. fExplicit
  745. );
  746. hr = SetDWORDPropertyInCache(
  747. _pPropertyCache,
  748. TEXT("MaxBadPasswordsAllowed"),
  749. pUserInfo3->usrmod3_lockout_threshold,
  750. fExplicit
  751. );
  752. RRETURN_EXP_IF_ERR(S_OK);
  753. }
  754. STDMETHODIMP
  755. CWinNTDomain::SetInfo(THIS_ DWORD dwApiLevel)
  756. {
  757. NET_API_STATUS nasStatus;
  758. HRESULT hr;
  759. LPBYTE lpBuffer = NULL;
  760. DWORD dwParamErr = 0;
  761. WCHAR szPDCName[MAX_PATH];
  762. hr = WinNTGetCachedDCName(
  763. _Name,
  764. szPDCName,
  765. _Credentials.GetFlags()
  766. );
  767. BAIL_ON_FAILURE(hr);
  768. nasStatus = NetUserModalsGet(
  769. szPDCName,
  770. dwApiLevel,
  771. &lpBuffer
  772. );
  773. hr = HRESULT_FROM_WIN32(nasStatus);
  774. BAIL_ON_FAILURE(hr);
  775. hr = MarshallAndSet(szPDCName, lpBuffer, dwApiLevel);
  776. BAIL_ON_FAILURE(hr);
  777. error:
  778. if (lpBuffer) {
  779. NetApiBufferFree(lpBuffer);
  780. }
  781. RRETURN_EXP_IF_ERR(hr);
  782. }
  783. HRESULT
  784. CWinNTDomain::MarshallAndSet(
  785. LPWSTR szServerName,
  786. LPBYTE lpBuffer,
  787. DWORD dwApiLevel
  788. )
  789. {
  790. ADsAssert(lpBuffer);
  791. switch (dwApiLevel) {
  792. case 0:
  793. RRETURN(Marshall_Set_Level0(
  794. szServerName,
  795. (LPUSER_MODALS_INFO_0)lpBuffer
  796. ));
  797. break;
  798. case 2:
  799. RRETURN(Marshall_Set_Level2(
  800. szServerName,
  801. (LPUSER_MODALS_INFO_2)lpBuffer
  802. ));
  803. break;
  804. case 3:
  805. RRETURN(Marshall_Set_Level3(
  806. szServerName,
  807. (LPUSER_MODALS_INFO_3)lpBuffer
  808. ));
  809. break;
  810. default:
  811. RRETURN(E_FAIL);
  812. }
  813. }
  814. HRESULT
  815. CWinNTDomain::Marshall_Set_Level0(
  816. LPWSTR szServerName,
  817. LPUSER_MODALS_INFO_0 pUserInfo0)
  818. {
  819. NET_API_STATUS nasStatus;
  820. DWORD dwParamErr = 0;
  821. HRESULT hr = S_OK;
  822. DWORD dwMinPasswdLen = 0;
  823. DWORD dwMaxPasswdAge = 0;
  824. DWORD dwMinPasswdAge = 0;
  825. DWORD dwPasswdHistLen = 0;
  826. hr = GetDWORDPropertyFromCache(
  827. _pPropertyCache,
  828. TEXT("MinPasswordLength"),
  829. &dwMinPasswdLen
  830. );
  831. if (SUCCEEDED(hr)) {
  832. pUserInfo0->usrmod0_min_passwd_len = dwMinPasswdLen;
  833. }
  834. hr = GetDWORDPropertyFromCache(
  835. _pPropertyCache,
  836. TEXT("MaxPasswordAge"),
  837. &dwMaxPasswdAge
  838. );
  839. if (SUCCEEDED(hr)) {
  840. pUserInfo0->usrmod0_max_passwd_age = dwMaxPasswdAge;
  841. }
  842. hr = GetDWORDPropertyFromCache(
  843. _pPropertyCache,
  844. TEXT("MinPasswordAge"),
  845. &dwMinPasswdAge
  846. );
  847. if (SUCCEEDED(hr)) {
  848. pUserInfo0->usrmod0_min_passwd_age = dwMinPasswdAge;
  849. }
  850. hr = GetDWORDPropertyFromCache(
  851. _pPropertyCache,
  852. TEXT("PasswordHistoryLength"),
  853. &dwPasswdHistLen
  854. );
  855. if (SUCCEEDED(hr)) {
  856. pUserInfo0->usrmod0_password_hist_len = dwPasswdHistLen;
  857. }
  858. //
  859. // Now Set this Data. Remember that the property store
  860. // returns to us data in its own format. It is the caller's
  861. // responsibility to free all buffers for bstrs, variants
  862. // etc
  863. //
  864. nasStatus = NetUserModalsSet(
  865. szServerName,
  866. 0,
  867. (LPBYTE)pUserInfo0,
  868. &dwParamErr
  869. );
  870. hr = HRESULT_FROM_WIN32(nasStatus);
  871. BAIL_ON_FAILURE(hr);
  872. error:
  873. RRETURN(hr);
  874. }
  875. HRESULT
  876. CWinNTDomain::Marshall_Set_Level2(
  877. LPWSTR szServerName,
  878. LPUSER_MODALS_INFO_2 pUserInfo2
  879. )
  880. {
  881. RRETURN(S_OK);
  882. }
  883. HRESULT
  884. CWinNTDomain::Marshall_Set_Level3(
  885. LPWSTR szServerName,
  886. LPUSER_MODALS_INFO_3 pUserInfo3
  887. )
  888. {
  889. NET_API_STATUS nasStatus;
  890. HRESULT hr;
  891. DWORD dwParamErr = 0;
  892. DWORD dwAutoUnlockIntrvl = 0;
  893. DWORD dwLockoutObsIntrvl = 0;
  894. DWORD dwMaxBadPasswdsAllowed = 0;
  895. hr = GetDWORDPropertyFromCache(
  896. _pPropertyCache,
  897. TEXT("AutoUnlockInterval"),
  898. &dwAutoUnlockIntrvl
  899. );
  900. if (SUCCEEDED(hr)) {
  901. pUserInfo3->usrmod3_lockout_duration = dwAutoUnlockIntrvl;
  902. }
  903. hr = GetDWORDPropertyFromCache(
  904. _pPropertyCache,
  905. TEXT("LockoutObservationInterval"),
  906. &dwLockoutObsIntrvl
  907. );
  908. if (SUCCEEDED(hr)) {
  909. pUserInfo3->usrmod3_lockout_observation_window = dwLockoutObsIntrvl;
  910. }
  911. hr = GetDWORDPropertyFromCache(
  912. _pPropertyCache,
  913. TEXT("MaxBadPasswordsAllowed"),
  914. &dwMaxBadPasswdsAllowed
  915. );
  916. if (SUCCEEDED(hr)) {
  917. pUserInfo3->usrmod3_lockout_threshold = dwMaxBadPasswdsAllowed;
  918. }
  919. //
  920. // Now Set this Data. Remember that the property store
  921. // returns to us data in its own format. It is the caller's
  922. // responsibility to free all buffers for bstrs, variants
  923. // etc
  924. //
  925. nasStatus = NetUserModalsSet(
  926. szServerName,
  927. 3,
  928. (LPBYTE)pUserInfo3,
  929. &dwParamErr
  930. );
  931. hr = HRESULT_FROM_WIN32(nasStatus);
  932. BAIL_ON_FAILURE(hr);
  933. error:
  934. RRETURN(hr);
  935. }