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.

2012 lines
44 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cuser.cxx
  7. //
  8. // Contents: Host user object code
  9. //
  10. // History: 11-1-95 krishnag Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "winnt.hxx"
  14. #pragma hdrstop
  15. // Class CWinNTUser
  16. DEFINE_IDispatch_ExtMgr_Implementation(CWinNTUser)
  17. DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTUser)
  18. DEFINE_IADs_TempImplementation(CWinNTUser)
  19. DEFINE_IADs_PutGetImplementation(CWinNTUser,UserClass,gdwUserTableSize)
  20. DEFINE_IADsPropertyList_Implementation(CWinNTUser,UserClass,gdwUserTableSize)
  21. CWinNTUser::CWinNTUser():
  22. _pDispMgr(NULL),
  23. _pExtMgr(NULL),
  24. _pPropertyCache(NULL),
  25. _ParentType(0),
  26. _DomainName(NULL),
  27. _ServerName(NULL),
  28. _fPasswordSet(FALSE),
  29. _dwRasPermissions(0),
  30. _pCCredentialsPwdHolder(NULL),
  31. _fUseCacheForAcctLocked(TRUE),
  32. _fComputerAcct(FALSE)
  33. {
  34. ENLIST_TRACKING(CWinNTUser);
  35. }
  36. HRESULT
  37. CWinNTUser::CreateUser(
  38. BSTR Parent,
  39. ULONG ParentType,
  40. BSTR DomainName,
  41. BSTR ServerName,
  42. BSTR UserName,
  43. DWORD dwObjectState,
  44. DWORD *pdwUserFlags, // OPTIONAL
  45. LPWSTR szFullName, // OPTIONAL
  46. LPWSTR szDescription, // OPTIONAL
  47. PSID pSid, // OPTIONAL
  48. REFIID riid,
  49. CWinNTCredentials& Credentials,
  50. void **ppvObj
  51. )
  52. {
  53. CWinNTUser FAR * pUser = NULL;
  54. HRESULT hr = S_OK;
  55. hr = AllocateUserObject(&pUser);
  56. BAIL_ON_FAILURE(hr);
  57. ADsAssert(pUser->_pDispMgr);
  58. hr = pUser->InitializeCoreObject(
  59. Parent,
  60. UserName,
  61. USER_CLASS_NAME,
  62. USER_SCHEMA_NAME,
  63. CLSID_WinNTUser,
  64. dwObjectState
  65. );
  66. BAIL_ON_FAILURE(hr);
  67. pUser->_Credentials = Credentials;
  68. //
  69. // The server name will be NULL only when we create a user
  70. // by SID - WinNT://S-1-321-231-231. In this case we should
  71. // not ref the server. Parent type is used as an extra check.
  72. //
  73. if (!((ParentType == WINNT_COMPUTER_ID)
  74. && !ServerName)) {
  75. hr = pUser->_Credentials.Ref(ServerName, DomainName, ParentType);
  76. if (hr == HRESULT_FROM_WIN32(ERROR_BAD_ARGUMENTS)) {
  77. //
  78. // We had a rebind error.
  79. // This will happen in the case where the credentials
  80. // ref the current server which is a bdc, the users is
  81. // a member of a global group we are going through and
  82. // we end up trying to ref the PDC when we already have
  83. // a connection to this comp.
  84. hr = S_OK;
  85. }
  86. }
  87. BAIL_ON_FAILURE(hr);
  88. hr = ADsAllocString(DomainName, &pUser->_DomainName);
  89. BAIL_ON_FAILURE(hr);
  90. if (ParentType == WINNT_DOMAIN_ID)
  91. {
  92. pUser->_ParentType = WINNT_DOMAIN_ID;
  93. ADsAssert(DomainName && DomainName[0]!=L'\0');
  94. }
  95. else
  96. {
  97. pUser->_ParentType = WINNT_COMPUTER_ID;
  98. hr = ADsAllocString(ServerName, &pUser->_ServerName);
  99. BAIL_ON_FAILURE(hr);
  100. }
  101. //
  102. // Load ext mgr and extensions
  103. //
  104. hr = ADSILoadExtensionManager(
  105. USER_CLASS_NAME,
  106. (IADsUser *) pUser,
  107. pUser->_pDispMgr,
  108. Credentials,
  109. &pUser->_pExtMgr
  110. );
  111. BAIL_ON_FAILURE(hr);
  112. ADsAssert(pUser->_pExtMgr);
  113. //
  114. // Prepopulate the object
  115. //
  116. hr = pUser->Prepopulate(TRUE,
  117. pdwUserFlags,
  118. szFullName,
  119. szDescription,
  120. pSid);
  121. BAIL_ON_FAILURE(hr);
  122. // check if the call is from UMI
  123. if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
  124. //
  125. // we do not pass riid to InitUmiObject below. This is because UMI object
  126. // does not support IDispatch. There are several places in ADSI code where
  127. // riid passed into this function is defaulted to IID_IDispatch -
  128. // IADsContainer::Create for example. To handle these cases, we always
  129. // request IID_IUnknown from the UMI object. Subsequent code within UMI
  130. // will QI for the appropriate interface.
  131. //
  132. if(3 == pUser->_dwNumComponents) {
  133. pUser->_CompClasses[0] = L"Domain";
  134. pUser->_CompClasses[1] = L"Computer";
  135. pUser->_CompClasses[2] = L"User";
  136. }
  137. else if(2 == pUser->_dwNumComponents) {
  138. if(NULL == DomainName) {
  139. pUser->_CompClasses[0] = L"Computer";
  140. pUser->_CompClasses[1] = L"User";
  141. }
  142. else if(NULL == ServerName) {
  143. pUser->_CompClasses[0] = L"Domain";
  144. pUser->_CompClasses[1] = L"User";
  145. }
  146. else
  147. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  148. }
  149. else
  150. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  151. hr = pUser->InitUmiObject(
  152. pUser->_Credentials,
  153. UserClass,
  154. gdwUserTableSize,
  155. pUser->_pPropertyCache,
  156. (IUnknown *) (INonDelegatingUnknown *) pUser,
  157. pUser->_pExtMgr,
  158. IID_IUnknown,
  159. ppvObj
  160. );
  161. BAIL_ON_FAILURE(hr);
  162. //
  163. // UMI object was created and the interface was obtained successfully.
  164. // UMI object now has a reference to the inner unknown of IADs, since
  165. // the call to Release() below is not going to be made in this case.
  166. //
  167. RRETURN(hr);
  168. }
  169. hr = pUser->QueryInterface(riid, ppvObj);
  170. BAIL_ON_FAILURE(hr);
  171. pUser->Release();
  172. RRETURN(hr);
  173. error:
  174. delete pUser;
  175. RRETURN_EXP_IF_ERR(hr);
  176. }
  177. HRESULT
  178. CWinNTUser::CreateUser(
  179. BSTR Parent,
  180. ULONG ParentType,
  181. BSTR DomainName,
  182. BSTR ServerName,
  183. BSTR UserName,
  184. DWORD dwObjectState,
  185. REFIID riid,
  186. CWinNTCredentials& Credentials,
  187. void **ppvObj
  188. )
  189. {
  190. HRESULT hr = S_OK;
  191. hr = CWinNTUser::CreateUser(
  192. Parent,
  193. ParentType,
  194. DomainName,
  195. ServerName,
  196. UserName,
  197. dwObjectState,
  198. NULL,
  199. NULL,
  200. NULL,
  201. NULL,
  202. riid,
  203. Credentials,
  204. ppvObj
  205. );
  206. RRETURN_EXP_IF_ERR(hr);
  207. }
  208. CWinNTUser::~CWinNTUser( )
  209. {
  210. ADsFreeString(_DomainName);
  211. ADsFreeString(_ServerName);
  212. delete _pExtMgr; // created last, destroyed first
  213. delete _pDispMgr;
  214. delete _pPropertyCache;
  215. if (_pCCredentialsPwdHolder) {
  216. delete _pCCredentialsPwdHolder;
  217. }
  218. }
  219. //----------------------------------------------------------------------------
  220. // Function: QueryInterface
  221. //
  222. // Synopsis: If this object is aggregated within another object, then
  223. // all calls will delegate to the outer object. Otherwise, the
  224. // non-delegating QI is called
  225. //
  226. // Arguments:
  227. //
  228. // iid interface requested
  229. // ppInterface Returns pointer to interface requested. NULL if interface
  230. // is not supported.
  231. //
  232. // Returns: S_OK on success. Error code otherwise.
  233. //
  234. // Modifies: *ppInterface to return interface pointer
  235. //
  236. //----------------------------------------------------------------------------
  237. STDMETHODIMP CWinNTUser::QueryInterface(
  238. REFIID iid,
  239. LPVOID *ppInterface
  240. )
  241. {
  242. if(_pUnkOuter != NULL)
  243. RRETURN(_pUnkOuter->QueryInterface(
  244. iid,
  245. ppInterface
  246. ));
  247. RRETURN(NonDelegatingQueryInterface(
  248. iid,
  249. ppInterface
  250. ));
  251. }
  252. //----------------------------------------------------------------------------
  253. // Function: AddRef
  254. //
  255. // Synopsis: IUnknown::AddRef. If this object is aggregated within
  256. // another, all calls will delegate to the outer object.
  257. // Otherwise, the non-delegating AddRef is called
  258. //
  259. // Arguments:
  260. //
  261. // None
  262. //
  263. // Returns: New reference count
  264. //
  265. // Modifies: Nothing
  266. //
  267. //----------------------------------------------------------------------------
  268. STDMETHODIMP_(ULONG) CWinNTUser::AddRef(void)
  269. {
  270. if(_pUnkOuter != NULL)
  271. RRETURN(_pUnkOuter->AddRef());
  272. RRETURN(NonDelegatingAddRef());
  273. }
  274. //----------------------------------------------------------------------------
  275. // Function: Release
  276. //
  277. // Synopsis: IUnknown::Release. If this object is aggregated within
  278. // another, all calls will delegate to the outer object.
  279. // Otherwise, the non-delegating Release is called
  280. //
  281. // Arguments:
  282. //
  283. // None
  284. //
  285. // Returns: New reference count
  286. //
  287. // Modifies: Nothing
  288. //
  289. //----------------------------------------------------------------------------
  290. STDMETHODIMP_(ULONG) CWinNTUser::Release(void)
  291. {
  292. if(_pUnkOuter != NULL)
  293. RRETURN(_pUnkOuter->Release());
  294. RRETURN(NonDelegatingRelease());
  295. }
  296. //----------------------------------------------------------------------------
  297. STDMETHODIMP
  298. CWinNTUser::NonDelegatingQueryInterface(
  299. REFIID iid,
  300. LPVOID FAR* ppv
  301. )
  302. {
  303. HRESULT hr = S_OK;
  304. if (ppv == NULL) {
  305. RRETURN(E_POINTER);
  306. }
  307. if (IsEqualIID(iid, IID_IUnknown))
  308. {
  309. *ppv = (IADsUser FAR *) this;
  310. }
  311. else if (IsEqualIID(iid, IID_IADsUser))
  312. {
  313. *ppv = (IADsUser FAR *) this;
  314. }
  315. else if (IsEqualIID(iid, IID_IADs))
  316. {
  317. *ppv = (IADsUser FAR *) this;
  318. }
  319. else if (IsEqualIID(iid, IID_IADsPropertyList))
  320. {
  321. *ppv = (IADsPropertyList FAR *) this;
  322. }
  323. else if (IsEqualIID(iid, IID_IDispatch))
  324. {
  325. *ppv = (IADsUser FAR *) this;
  326. }
  327. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  328. {
  329. *ppv = (ISupportErrorInfo FAR *) this;
  330. }
  331. else if( (_pDispatch != NULL) &&
  332. IsEqualIID(iid, IID_IADsExtension) )
  333. {
  334. *ppv = (IADsExtension *) this;
  335. }
  336. else if (_pExtMgr)
  337. {
  338. RRETURN(_pExtMgr->QueryInterface(iid,ppv));
  339. }
  340. else
  341. {
  342. *ppv = NULL;
  343. return E_NOINTERFACE;
  344. }
  345. AddRef();
  346. return NOERROR;
  347. }
  348. /* ISupportErrorInfo method */
  349. STDMETHODIMP
  350. CWinNTUser::InterfaceSupportsErrorInfo(
  351. THIS_ REFIID riid
  352. )
  353. {
  354. if (IsEqualIID(riid, IID_IADs) ||
  355. IsEqualIID(riid, IID_IADsPropertyList) ||
  356. IsEqualIID(riid, IID_IADsUser)) {
  357. RRETURN(S_OK);
  358. } else {
  359. RRETURN(S_FALSE);
  360. }
  361. }
  362. /* IADs methods */
  363. STDMETHODIMP
  364. CWinNTUser::SetInfo(THIS)
  365. {
  366. HRESULT hr = S_OK;
  367. NET_API_STATUS nasStatus;
  368. WCHAR szPDCName[MAX_PATH];
  369. WCHAR *pszPassword = NULL;
  370. WCHAR *pszServerName = _ServerName;
  371. //
  372. // objects associated with invalid SIDs have neither a
  373. // corresponding server nor domain
  374. //
  375. if ((!_DomainName) && (!_ServerName)) {
  376. BAIL_ON_FAILURE(hr = E_ADS_INVALID_USER_OBJECT);
  377. }
  378. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  379. if (_ParentType == WINNT_DOMAIN_ID) {
  380. hr = WinNTGetCachedDCName(
  381. _DomainName,
  382. szPDCName,
  383. _Credentials.GetFlags()
  384. );
  385. BAIL_ON_FAILURE(hr);
  386. //
  387. // + 2 skips the backslashes when calling create
  388. //
  389. pszServerName = szPDCName + 2;
  390. }
  391. if (!_fPasswordSet) {
  392. hr = WinNTCreateUser(
  393. pszServerName,
  394. _Name
  395. );
  396. } else {
  397. hr = getPrivatePassword(&pszPassword);
  398. BAIL_ON_FAILURE(hr);
  399. hr = WinNTCreateUser(
  400. pszServerName,
  401. _Name,
  402. pszPassword
  403. );
  404. }
  405. BAIL_ON_FAILURE(hr);
  406. SetObjectState(ADS_OBJECT_BOUND);
  407. }
  408. hr = SetInfo(3);
  409. if(SUCCEEDED(hr))
  410. _pPropertyCache->ClearModifiedFlags();
  411. error:
  412. if (pszPassword) {
  413. FreeADsStr(pszPassword);
  414. }
  415. RRETURN_EXP_IF_ERR(hr);
  416. }
  417. STDMETHODIMP
  418. CWinNTUser::GetInfo(THIS)
  419. {
  420. HRESULT hr;
  421. _pPropertyCache->flushpropcache();
  422. // USER_INFO
  423. //
  424. hr = GetInfo(
  425. 3,
  426. TRUE
  427. );
  428. BAIL_ON_FAILURE(hr);
  429. //
  430. // USER_MODAL_INFO0
  431. //
  432. hr = GetInfo(
  433. 10,
  434. TRUE
  435. );
  436. BAIL_ON_FAILURE(hr);
  437. //
  438. // USER_MODAL_INFO3
  439. //
  440. hr = GetInfo(
  441. 13,
  442. TRUE
  443. );
  444. BAIL_ON_FAILURE(hr);
  445. if(FALSE == _fComputerAcct) {
  446. #ifndef WIN95
  447. //
  448. // Get the RAS permissions. Do this only for user accounts and
  449. // not for machine accounts.
  450. //
  451. //
  452. hr = GetInfo(21, TRUE);
  453. BAIL_ON_FAILURE(hr);
  454. #endif
  455. }
  456. //
  457. // objectSid. LookupAccountName fails for machine accounts on NT4, but
  458. // works on Win2K. In order for an explicit GetInfo to succeed against NT4
  459. // systems we do not check the error code returned below. If this call
  460. // fails, a subsequent Get("ObjectSid") will return
  461. // E_ADS_PROPERTY_NOT_FOUND.
  462. //
  463. GetInfo(
  464. 20,
  465. TRUE
  466. );
  467. error :
  468. RRETURN(hr);
  469. }
  470. STDMETHODIMP
  471. CWinNTUser::ImplicitGetInfo(THIS)
  472. {
  473. HRESULT hr;
  474. #ifndef WIN95
  475. //
  476. // Get the RAS permissions first
  477. //
  478. //
  479. hr = GetInfo(21, FALSE);
  480. BAIL_ON_FAILURE(hr);
  481. #endif
  482. // USER_INFO
  483. //
  484. hr = GetInfo(
  485. 3,
  486. FALSE
  487. );
  488. BAIL_ON_FAILURE(hr);
  489. //
  490. // USER_MODAL_INFO0
  491. //
  492. hr = GetInfo(
  493. 10,
  494. FALSE
  495. );
  496. BAIL_ON_FAILURE(hr);
  497. //
  498. // USER_MODAL_INFO3
  499. //
  500. hr = GetInfo(
  501. 13,
  502. FALSE
  503. );
  504. BAIL_ON_FAILURE(hr);
  505. //
  506. // objectSid
  507. //
  508. hr = GetInfo(
  509. 20,
  510. FALSE
  511. );
  512. error :
  513. RRETURN(hr);
  514. }
  515. HRESULT
  516. CWinNTUser::AllocateUserObject(
  517. CWinNTUser ** ppUser
  518. )
  519. {
  520. CWinNTUser FAR * pUser = NULL;
  521. CAggregatorDispMgr FAR * pDispMgr = NULL;
  522. CPropertyCache FAR * pPropertyCache = NULL;
  523. HRESULT hr = S_OK;
  524. pUser = new CWinNTUser();
  525. if (pUser == NULL) {
  526. hr = E_OUTOFMEMORY;
  527. }
  528. BAIL_ON_FAILURE(hr);
  529. pDispMgr = new CAggregatorDispMgr;
  530. if (pDispMgr == NULL) {
  531. hr = E_OUTOFMEMORY;
  532. }
  533. BAIL_ON_FAILURE(hr);
  534. hr = LoadTypeInfoEntry(
  535. pDispMgr,
  536. LIBID_ADs,
  537. IID_IADsUser,
  538. (IADsUser *)pUser,
  539. DISPID_REGULAR
  540. );
  541. BAIL_ON_FAILURE(hr);
  542. hr = LoadTypeInfoEntry(
  543. pDispMgr,
  544. LIBID_ADs,
  545. IID_IADsPropertyList,
  546. (IADsPropertyList *)pUser,
  547. DISPID_VALUE
  548. );
  549. BAIL_ON_FAILURE(hr);
  550. hr = CPropertyCache::createpropertycache(
  551. UserClass,
  552. gdwUserTableSize,
  553. (CCoreADsObject *)pUser,
  554. &pPropertyCache
  555. );
  556. BAIL_ON_FAILURE(hr);
  557. pDispMgr->RegisterPropertyCache(
  558. pPropertyCache
  559. );
  560. pUser->_pPropertyCache = pPropertyCache;
  561. pUser->_pDispMgr = pDispMgr;
  562. *ppUser = pUser;
  563. RRETURN(hr);
  564. error:
  565. delete pDispMgr;
  566. delete pPropertyCache;
  567. delete pUser;
  568. RRETURN(hr);
  569. }
  570. //
  571. // For current implementation in clocgroup:
  572. // If this function is called as a public function (ie. by another
  573. // modual/class), fExplicit must be FALSE since the cache is NOT
  574. // flushed in this function.
  575. //
  576. // External functions should ONLY call GetInfo(no param) for explicit
  577. // GetInfo. This will flush the cache properly.
  578. //
  579. STDMETHODIMP
  580. CWinNTUser::GetInfo(
  581. THIS_ DWORD dwApiLevel,
  582. BOOL fExplicit
  583. )
  584. {
  585. HRESULT hr = S_OK;
  586. switch (dwApiLevel) {
  587. // GetInfo(1 or 2, fExplicit) in ADSI codes should be modified
  588. // to GetInfo(3, fExplicit) to minimize calls on wire.
  589. case 3:
  590. hr = GetStandardInfo(3, fExplicit);
  591. RRETURN_EXP_IF_ERR(hr);
  592. case 10:
  593. hr = GetModalInfo(0, fExplicit);
  594. RRETURN_EXP_IF_ERR(hr);
  595. case 13:
  596. hr = GetModalInfo(3, fExplicit);
  597. RRETURN_EXP_IF_ERR(hr);
  598. case 20:
  599. hr = GetSidInfo(fExplicit);
  600. RRETURN_EXP_IF_ERR(hr);
  601. #ifndef WIN95
  602. case 21:
  603. hr = GetRasInfo(fExplicit);
  604. RRETURN_EXP_IF_ERR(hr);
  605. #endif
  606. default:
  607. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  608. }
  609. }
  610. HRESULT
  611. CWinNTUser::GetStandardInfo(
  612. THIS_ DWORD dwApiLevel,
  613. BOOL fExplicit
  614. )
  615. {
  616. NET_API_STATUS nasStatus;
  617. LPBYTE lpBuffer = NULL;
  618. HRESULT hr;
  619. WCHAR szHostServerName[MAX_PATH];
  620. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  621. RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
  622. }
  623. //
  624. // objects associated with invalid SIDs have neither a
  625. // corresponding server nor domain
  626. //
  627. if ((!_DomainName) && (!_ServerName)) {
  628. BAIL_ON_FAILURE(hr = E_ADS_INVALID_USER_OBJECT);
  629. }
  630. if (_ParentType == WINNT_DOMAIN_ID) {
  631. hr = WinNTGetCachedDCName(
  632. _DomainName,
  633. szHostServerName,
  634. _Credentials.GetFlags()
  635. );
  636. BAIL_ON_FAILURE(hr);
  637. }else {
  638. hr = MakeUncName(
  639. _ServerName,
  640. szHostServerName
  641. );
  642. }
  643. nasStatus = NetUserGetInfo(
  644. szHostServerName,
  645. _Name,
  646. dwApiLevel,
  647. &lpBuffer
  648. );
  649. hr = HRESULT_FROM_WIN32(nasStatus);
  650. BAIL_ON_FAILURE(hr);
  651. hr = UnMarshall(
  652. lpBuffer,
  653. dwApiLevel,
  654. fExplicit
  655. );
  656. BAIL_ON_FAILURE(hr);
  657. error:
  658. if (lpBuffer) {
  659. NetApiBufferFree(lpBuffer);
  660. }
  661. RRETURN_EXP_IF_ERR(hr);
  662. }
  663. HRESULT
  664. CWinNTUser::UnMarshall(
  665. LPBYTE lpBuffer,
  666. DWORD dwApiLevel,
  667. BOOL fExplicit
  668. )
  669. {
  670. VARIANT_BOOL fBool;
  671. BSTR bstrData = NULL;
  672. LONG lnData = 0L;
  673. VARIANT vaData;
  674. DATE daDate = 0;
  675. ADsAssert(lpBuffer);
  676. switch (dwApiLevel) {
  677. // GetStandardInfo currently only be called with dwApiLevel=3. If
  678. // dwApiLevel = 1 or 2 is used, modify ADSI codes to 3.
  679. case 3:
  680. RRETURN(UnMarshall_Level3(fExplicit, (LPUSER_INFO_3)lpBuffer));
  681. break;
  682. default:
  683. RRETURN(E_FAIL);
  684. }
  685. }
  686. HRESULT
  687. CWinNTUser::UnMarshall_Level3(
  688. BOOL fExplicit,
  689. LPUSER_INFO_3 pUserInfo3
  690. )
  691. {
  692. HRESULT hr = S_OK;
  693. //
  694. // Begin Account Restrictions Properties
  695. //
  696. hr = SetDWORDPropertyInCache(
  697. _pPropertyCache,
  698. TEXT("UserFlags"),
  699. pUserInfo3->usri3_flags,
  700. fExplicit
  701. );
  702. if(SUCCEEDED(hr)) {
  703. _fUseCacheForAcctLocked = TRUE;
  704. }
  705. if( (pUserInfo3->usri3_flags & UF_WORKSTATION_TRUST_ACCOUNT) ||
  706. (pUserInfo3->usri3_flags & UF_SERVER_TRUST_ACCOUNT) ||
  707. (pUserInfo3->usri3_flags & UF_INTERDOMAIN_TRUST_ACCOUNT) ) {
  708. _fComputerAcct = TRUE;
  709. }
  710. //
  711. // If usri3_acct_expires == TIMEQ_FOREVER, it means we need
  712. // to ignore the acct expiration date, the account
  713. // can never expire.
  714. //
  715. if (pUserInfo3->usri3_acct_expires != TIMEQ_FOREVER) {
  716. hr = SetDATE70PropertyInCache(
  717. _pPropertyCache,
  718. TEXT("AccountExpirationDate"),
  719. pUserInfo3->usri3_acct_expires,
  720. fExplicit
  721. );
  722. }
  723. hr = SetDelimitedStringPropertyInCache(
  724. _pPropertyCache,
  725. TEXT("LoginWorkstations"),
  726. pUserInfo3->usri3_workstations,
  727. fExplicit
  728. );
  729. hr = SetDWORDPropertyInCache(
  730. _pPropertyCache,
  731. TEXT("MaxStorage"),
  732. pUserInfo3->usri3_max_storage,
  733. fExplicit
  734. );
  735. hr = SetDWORDPropertyInCache(
  736. _pPropertyCache,
  737. TEXT("PasswordAge"),
  738. pUserInfo3->usri3_password_age,
  739. fExplicit
  740. );
  741. hr = SetDWORDPropertyInCache(
  742. _pPropertyCache,
  743. TEXT("PasswordExpired"),
  744. pUserInfo3->usri3_password_expired,
  745. fExplicit
  746. );
  747. hr = SetOctetPropertyInCache(
  748. _pPropertyCache,
  749. TEXT("LoginHours"),
  750. pUserInfo3->usri3_logon_hours,
  751. 21,
  752. fExplicit
  753. );
  754. //
  755. // Begin Business Info Properties
  756. //
  757. hr = SetLPTSTRPropertyInCache(
  758. _pPropertyCache,
  759. TEXT("FullName"),
  760. pUserInfo3->usri3_full_name,
  761. fExplicit
  762. );
  763. hr = SetLPTSTRPropertyInCache(
  764. _pPropertyCache,
  765. TEXT("Description"),
  766. pUserInfo3->usri3_comment,
  767. fExplicit
  768. );
  769. //
  770. // Begin Account Statistics Properties
  771. //
  772. hr = SetDWORDPropertyInCache(
  773. _pPropertyCache,
  774. TEXT("BadPasswordAttempts"),
  775. pUserInfo3->usri3_bad_pw_count,
  776. fExplicit
  777. );
  778. //
  779. // lasg_logon/off == 0 means user never logon/off or logon/off time unknown.
  780. //
  781. if (pUserInfo3->usri3_last_logon!=0) {
  782. hr = SetDATE70PropertyInCache(
  783. _pPropertyCache,
  784. TEXT("LastLogin"),
  785. pUserInfo3->usri3_last_logon,
  786. fExplicit
  787. );
  788. }
  789. if (pUserInfo3->usri3_last_logoff!=0) {
  790. hr = SetDATE70PropertyInCache(
  791. _pPropertyCache,
  792. TEXT("LastLogoff"),
  793. pUserInfo3->usri3_last_logoff,
  794. fExplicit
  795. );
  796. }
  797. //
  798. // Begin Other Info Properties
  799. //
  800. hr = SetLPTSTRPropertyInCache(
  801. _pPropertyCache,
  802. TEXT("HomeDirectory"),
  803. pUserInfo3->usri3_home_dir,
  804. fExplicit
  805. );
  806. hr = SetLPTSTRPropertyInCache(
  807. _pPropertyCache,
  808. TEXT("LoginScript"),
  809. pUserInfo3->usri3_script_path,
  810. fExplicit
  811. );
  812. hr = SetLPTSTRPropertyInCache(
  813. _pPropertyCache,
  814. TEXT("Profile"),
  815. pUserInfo3->usri3_profile,
  816. fExplicit
  817. );
  818. hr = SetLPTSTRPropertyInCache(
  819. _pPropertyCache,
  820. TEXT("HomeDirDrive"),
  821. pUserInfo3->usri3_home_dir_drive,
  822. fExplicit
  823. );
  824. hr = SetLPTSTRPropertyInCache(
  825. _pPropertyCache,
  826. TEXT("Parameters"),
  827. pUserInfo3->usri3_parms,
  828. fExplicit
  829. );
  830. hr = SetDWORDPropertyInCache(
  831. _pPropertyCache,
  832. TEXT("PrimaryGroupID"),
  833. pUserInfo3->usri3_primary_group_id,
  834. fExplicit
  835. );
  836. hr = SetLPTSTRPropertyInCache(
  837. _pPropertyCache,
  838. TEXT("Name"),
  839. _Name,
  840. fExplicit
  841. );
  842. RRETURN(S_OK);
  843. }
  844. HRESULT
  845. CWinNTUser::Prepopulate(
  846. BOOL fExplicit,
  847. DWORD *pdwUserFlags, // OPTIONAL
  848. LPWSTR szFullName, // OPTIONAL
  849. LPWSTR szDescription, // OPTIONAL
  850. PSID pSid // OPTIONAL
  851. )
  852. {
  853. HRESULT hr = S_OK;
  854. DWORD dwErr = 0;
  855. DWORD dwSidLength = 0;
  856. //
  857. // Prepopulate the object with supplied info,
  858. // if available
  859. //
  860. if (pdwUserFlags) {
  861. hr = SetDWORDPropertyInCache(
  862. _pPropertyCache,
  863. TEXT("UserFlags"),
  864. *pdwUserFlags,
  865. TRUE
  866. );
  867. BAIL_ON_FAILURE(hr);
  868. //
  869. // see comment on _fUseCacheForAcctLocked in cuser.hxx
  870. //
  871. _fUseCacheForAcctLocked = FALSE;
  872. }
  873. if (szFullName) {
  874. hr = SetLPTSTRPropertyInCache(
  875. _pPropertyCache,
  876. TEXT("FullName"),
  877. szFullName,
  878. TRUE
  879. );
  880. BAIL_ON_FAILURE(hr);
  881. }
  882. if (szDescription) {
  883. hr = SetLPTSTRPropertyInCache(
  884. _pPropertyCache,
  885. TEXT("Description"),
  886. szDescription,
  887. TRUE
  888. );
  889. BAIL_ON_FAILURE(hr);
  890. }
  891. if (pSid) {
  892. //
  893. // On NT4 for some reason GetLengthSID does not set lasterror to 0
  894. //
  895. SetLastError(NO_ERROR);
  896. dwSidLength = GetLengthSid(pSid);
  897. //
  898. // This is an extra check to make sure that we have the
  899. // correct length.
  900. //
  901. dwErr = GetLastError();
  902. if (dwErr != NO_ERROR) {
  903. hr = HRESULT_FROM_WIN32(dwErr);
  904. BAIL_ON_FAILURE(hr);
  905. }
  906. hr = SetOctetPropertyInCache(
  907. _pPropertyCache,
  908. TEXT("objectSid"),
  909. (PBYTE) pSid,
  910. dwSidLength,
  911. TRUE
  912. );
  913. BAIL_ON_FAILURE(hr);
  914. }
  915. error:
  916. RRETURN(hr);
  917. }
  918. HRESULT
  919. CWinNTUser::GetSidInfo(
  920. IN BOOL fExplicit
  921. )
  922. {
  923. HRESULT hr = E_FAIL;
  924. WCHAR szHostServerName[MAX_PATH];
  925. //
  926. // objects associated with invalid SIDs have neither a
  927. // corresponding server nor domain
  928. //
  929. if ((!_DomainName) && (!_ServerName)) {
  930. BAIL_ON_FAILURE(hr = E_ADS_INVALID_USER_OBJECT);
  931. }
  932. //
  933. // Get Server Name
  934. //
  935. if (_ParentType == WINNT_DOMAIN_ID) {
  936. hr = WinNTGetCachedDCName(
  937. _DomainName,
  938. szHostServerName,
  939. _Credentials.GetFlags()
  940. );
  941. BAIL_ON_FAILURE(hr);
  942. }else {
  943. hr = MakeUncName(
  944. _ServerName,
  945. szHostServerName
  946. );
  947. }
  948. //
  949. // Get Sid of this user account and store in cache if fExplicit.
  950. //
  951. hr = GetSidIntoCache(
  952. szHostServerName,
  953. _Name,
  954. _pPropertyCache,
  955. fExplicit
  956. );
  957. BAIL_ON_FAILURE(hr);
  958. error:
  959. RRETURN(hr);
  960. }
  961. HRESULT
  962. CWinNTUser::GetRasInfo(
  963. IN BOOL fExplicit
  964. )
  965. {
  966. #ifdef WIN95
  967. RRETURN(E_NOTIMPL);
  968. #else
  969. HRESULT hr = E_FAIL;
  970. WCHAR szHostServerName[MAX_PATH];
  971. RAS_USER_0 RasUser0;
  972. DWORD nasStatus = 0;
  973. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  974. RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
  975. }
  976. //
  977. // objects associated with invalid SIDs have neither a
  978. // corresponding server nor domain
  979. //
  980. if ((!_DomainName) && (!_ServerName)) {
  981. BAIL_ON_FAILURE(hr = E_ADS_INVALID_USER_OBJECT);
  982. }
  983. //
  984. // Get Server Name
  985. //
  986. if (_ParentType == WINNT_DOMAIN_ID) {
  987. hr = WinNTGetCachedDCName(
  988. _DomainName,
  989. szHostServerName,
  990. _Credentials.GetFlags()
  991. );
  992. BAIL_ON_FAILURE(hr);
  993. }else {
  994. hr = MakeUncName(
  995. _ServerName,
  996. szHostServerName
  997. );
  998. }
  999. //
  1000. // Make Ras call to get permissions.
  1001. //
  1002. nasStatus = RasAdminUserGetInfo(
  1003. szHostServerName,
  1004. _Name,
  1005. &RasUser0
  1006. );
  1007. if (nasStatus) {
  1008. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  1009. }
  1010. _dwRasPermissions = RasUser0.bfPrivilege;
  1011. hr = SetDWORDPropertyInCache(
  1012. _pPropertyCache,
  1013. TEXT("RasPermissions"),
  1014. RasUser0.bfPrivilege,
  1015. fExplicit
  1016. );
  1017. error:
  1018. RRETURN(hr);
  1019. #endif
  1020. }
  1021. HRESULT
  1022. CWinNTUser::SetInfo(THIS_ DWORD dwApiLevel)
  1023. {
  1024. NET_API_STATUS nasStatus;
  1025. HRESULT hr;
  1026. LPBYTE lpBuffer = NULL;
  1027. DWORD dwParamErr = 0;
  1028. WCHAR szHostServerName[MAX_PATH];
  1029. #ifndef WIN95
  1030. RAS_USER_0 RasUser0;
  1031. DWORD dwRasPerms = 0;
  1032. #endif
  1033. //
  1034. // objects associated with invalid SIDs have neither a
  1035. // corresponding server nor domain
  1036. //
  1037. if ((!_DomainName) && (!_ServerName)) {
  1038. BAIL_ON_FAILURE(hr = E_ADS_INVALID_USER_OBJECT);
  1039. }
  1040. if (_ParentType == WINNT_DOMAIN_ID) {
  1041. hr = WinNTGetCachedDCName(
  1042. _DomainName,
  1043. szHostServerName,
  1044. _Credentials.GetFlags()
  1045. );
  1046. BAIL_ON_FAILURE(hr);
  1047. }else {
  1048. hr = MakeUncName(
  1049. _ServerName,
  1050. szHostServerName
  1051. );
  1052. BAIL_ON_FAILURE(hr);
  1053. }
  1054. #ifndef WIN95
  1055. //
  1056. // Since Ras stuff is the new addition do this first.
  1057. // There is a chance that we may fail after creating the
  1058. // user but I do not see anyway to avoid this.
  1059. // Check to see if the value is set in the cace and only
  1060. // if it is set and is different from the value we have
  1061. // do we try and change it.
  1062. //
  1063. hr = GetDWORDPropertyFromCache(
  1064. _pPropertyCache,
  1065. TEXT("RasPermissions"),
  1066. &dwRasPerms
  1067. );
  1068. if (SUCCEEDED(hr) && (dwRasPerms != _dwRasPermissions)) {
  1069. //
  1070. // Get the permissions and then set privelege as we
  1071. // do not want to change the callback number param.
  1072. //
  1073. nasStatus = RasAdminUserGetInfo(
  1074. szHostServerName,
  1075. _Name,
  1076. &RasUser0
  1077. );
  1078. if (nasStatus) {
  1079. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  1080. }
  1081. RasUser0.bfPrivilege = (BYTE) dwRasPerms;
  1082. nasStatus = RasAdminUserSetInfo(
  1083. szHostServerName,
  1084. _Name,
  1085. &RasUser0
  1086. );
  1087. if (nasStatus) {
  1088. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  1089. }
  1090. } // Ras info.
  1091. #endif
  1092. nasStatus = NetUserGetInfo(
  1093. szHostServerName,
  1094. _Name,
  1095. dwApiLevel,
  1096. &lpBuffer
  1097. );
  1098. hr = HRESULT_FROM_WIN32(nasStatus);
  1099. BAIL_ON_FAILURE(hr);
  1100. hr = MarshallAndSet(szHostServerName, lpBuffer, dwApiLevel);
  1101. BAIL_ON_FAILURE(hr);
  1102. error:
  1103. if (lpBuffer) {
  1104. NetApiBufferFree(lpBuffer);
  1105. }
  1106. RRETURN_EXP_IF_ERR(hr);
  1107. }
  1108. HRESULT
  1109. CWinNTUser::MarshallAndSet(
  1110. LPWSTR szHostServerName,
  1111. LPBYTE lpBuffer,
  1112. DWORD dwApiLevel
  1113. )
  1114. {
  1115. ADsAssert(lpBuffer);
  1116. switch (dwApiLevel) {
  1117. //
  1118. // dwApiLevel = 1 or 2 should change to 3 in caller codes to min
  1119. // calls on wire
  1120. case 3:
  1121. RRETURN(Marshall_Set_Level3(szHostServerName, (LPUSER_INFO_3)lpBuffer));
  1122. break;
  1123. //
  1124. // caae 10:
  1125. // case 13:
  1126. // USER_MODAL_INFO should be set at domain level,
  1127. // Not at user level
  1128. //
  1129. //
  1130. // case 20:
  1131. // objectSid not writable
  1132. //
  1133. default:
  1134. RRETURN(E_FAIL);
  1135. }
  1136. }
  1137. HRESULT
  1138. CWinNTUser::Marshall_Set_Level3(
  1139. LPWSTR szHostServerName,
  1140. LPUSER_INFO_3 pUserInfo3
  1141. )
  1142. {
  1143. HRESULT hr;
  1144. DWORD dwFlags = 0;
  1145. DWORD dwAcctExpDate = 0;
  1146. LPWSTR pszDescription = NULL;
  1147. LPWSTR pszFullName = NULL;
  1148. DWORD dwBadPwCount = 0;
  1149. DWORD dwLastLogin = 0;
  1150. DWORD dwLastLogoff = 0;
  1151. LPWSTR pszHomeDir = NULL;
  1152. LPWSTR pszScript = NULL;
  1153. LPWSTR pszProfile = NULL;
  1154. LPWSTR pszLoginWorkstations = NULL;
  1155. DWORD dwMaxStorage = 0;
  1156. LPWSTR pszHomeDirDrive = NULL;
  1157. LPWSTR pszParameters = NULL;
  1158. DWORD dwPrimaryGroupId = 0;
  1159. DWORD dwPasswordExpired = 0;
  1160. OctetString octetString;
  1161. DWORD dwParmErr = 0;
  1162. NET_API_STATUS nasStatus;
  1163. hr = GetDWORDPropertyFromCache(
  1164. _pPropertyCache,
  1165. TEXT("UserFlags"),
  1166. &dwFlags
  1167. );
  1168. if(SUCCEEDED(hr)){
  1169. pUserInfo3->usri3_flags = dwFlags;
  1170. }
  1171. hr = GetDATE70PropertyFromCache(
  1172. _pPropertyCache,
  1173. TEXT("AccountExpirationDate"),
  1174. &dwAcctExpDate
  1175. );
  1176. if(SUCCEEDED(hr)){
  1177. //
  1178. // Pick an easy to remeber date to represent "account never expires" :
  1179. // 1/1/70 at 0:00. (Range <= 86400 and >= 0xffffffff-86400 is +/- one
  1180. // day from 1/1/70 at 0:00 to take time localization into account.)
  1181. //
  1182. if (dwAcctExpDate <= 86400 || dwAcctExpDate >= (0xffffffff-86400)) {
  1183. pUserInfo3->usri3_acct_expires = TIMEQ_FOREVER;
  1184. }
  1185. else {
  1186. pUserInfo3->usri3_acct_expires = dwAcctExpDate;
  1187. }
  1188. }
  1189. hr = GetDWORDPropertyFromCache(
  1190. _pPropertyCache,
  1191. TEXT("PasswordExpired"),
  1192. &dwPasswordExpired
  1193. );
  1194. if(SUCCEEDED(hr)){
  1195. pUserInfo3->usri3_password_expired = dwPasswordExpired;
  1196. }
  1197. hr = GetDWORDPropertyFromCache(
  1198. _pPropertyCache,
  1199. TEXT("MaxStorage"),
  1200. &dwMaxStorage
  1201. );
  1202. if(SUCCEEDED(hr)){
  1203. pUserInfo3->usri3_max_storage = dwMaxStorage;
  1204. }
  1205. hr = GetDelimitedStringPropertyFromCache(
  1206. _pPropertyCache,
  1207. TEXT("LoginWorkstations"),
  1208. &pszLoginWorkstations
  1209. );
  1210. if(SUCCEEDED(hr)){
  1211. pUserInfo3->usri3_workstations = pszLoginWorkstations;
  1212. }
  1213. //
  1214. // Begin Business Information Properties
  1215. //
  1216. hr = GetLPTSTRPropertyFromCache(
  1217. _pPropertyCache,
  1218. TEXT("Description"),
  1219. &pszDescription
  1220. );
  1221. if(SUCCEEDED(hr)){
  1222. pUserInfo3->usri3_comment = pszDescription;
  1223. }
  1224. hr = GetLPTSTRPropertyFromCache(
  1225. _pPropertyCache,
  1226. TEXT("FullName"),
  1227. &pszFullName
  1228. );
  1229. if(SUCCEEDED(hr)){
  1230. pUserInfo3->usri3_full_name = pszFullName;
  1231. }
  1232. hr = GetOctetPropertyFromCache(
  1233. _pPropertyCache,
  1234. TEXT("LoginHours"),
  1235. &octetString
  1236. );
  1237. if(SUCCEEDED(hr)){
  1238. memcpy(pUserInfo3->usri3_logon_hours,
  1239. octetString.pByte,
  1240. octetString.dwSize);
  1241. FreeADsMem(octetString.pByte);
  1242. }
  1243. /*
  1244. //
  1245. // Begin Account Statistics Properties - should not be writable.
  1246. //
  1247. hr = GetDWORDPropertyFromCache(
  1248. _pPropertyCache,
  1249. TEXT("BadPasswordAttempts"),
  1250. &dwBadPwCount
  1251. );
  1252. if(SUCCEEDED(hr)){
  1253. pUserInfo3->usri3_bad_pw_count = dwBadPwCount;
  1254. }
  1255. hr = GetDATE70PropertyFromCache(
  1256. _pPropertyCache,
  1257. TEXT("LastLogin"),
  1258. &dwLastLogin
  1259. );
  1260. if(SUCCEEDED(hr)){
  1261. pUserInfo3->usri3_last_logon = dwLastLogin;
  1262. }
  1263. hr = GetDATE70PropertyFromCache(
  1264. _pPropertyCache,
  1265. TEXT("LastLogoff"),
  1266. &dwLastLogoff
  1267. );
  1268. if(SUCCEEDED(hr)){
  1269. pUserInfo3->usri3_last_logoff = dwLastLogoff;
  1270. }
  1271. */
  1272. //
  1273. // Begin Other Info Properties
  1274. //
  1275. hr = GetLPTSTRPropertyFromCache(
  1276. _pPropertyCache,
  1277. TEXT("HomeDirectory"),
  1278. &pszHomeDir
  1279. );
  1280. if(SUCCEEDED(hr)){
  1281. pUserInfo3->usri3_home_dir = pszHomeDir;
  1282. }
  1283. hr = GetLPTSTRPropertyFromCache(
  1284. _pPropertyCache,
  1285. TEXT("LoginScript"),
  1286. &pszScript
  1287. );
  1288. if(SUCCEEDED(hr)){
  1289. pUserInfo3->usri3_script_path = pszScript;
  1290. }
  1291. hr = GetLPTSTRPropertyFromCache(
  1292. _pPropertyCache,
  1293. TEXT("Profile"),
  1294. &pszProfile
  1295. );
  1296. if(SUCCEEDED(hr)){
  1297. pUserInfo3->usri3_profile = pszProfile;
  1298. }
  1299. hr = GetLPTSTRPropertyFromCache(
  1300. _pPropertyCache,
  1301. TEXT("HomeDirDrive"),
  1302. &pszHomeDirDrive
  1303. );
  1304. if(SUCCEEDED(hr)){
  1305. pUserInfo3->usri3_home_dir_drive = pszHomeDirDrive;
  1306. }
  1307. hr = GetLPTSTRPropertyFromCache(
  1308. _pPropertyCache,
  1309. TEXT("Parameters"),
  1310. &pszParameters
  1311. );
  1312. if(SUCCEEDED(hr)){
  1313. pUserInfo3->usri3_parms = pszParameters;
  1314. }
  1315. hr = GetDWORDPropertyFromCache(
  1316. _pPropertyCache,
  1317. TEXT("PrimaryGroupID"),
  1318. &dwPrimaryGroupId
  1319. );
  1320. if(SUCCEEDED(hr)){
  1321. pUserInfo3->usri3_primary_group_id = dwPrimaryGroupId;
  1322. }
  1323. //
  1324. // Now perform the Set call.
  1325. //
  1326. nasStatus = NetUserSetInfo(
  1327. szHostServerName,
  1328. _Name,
  1329. 3,
  1330. (LPBYTE)pUserInfo3,
  1331. &dwParmErr
  1332. );
  1333. hr = HRESULT_FROM_WIN32(nasStatus);
  1334. BAIL_ON_FAILURE(hr);
  1335. error:
  1336. if (pszDescription) {
  1337. FreeADsStr(pszDescription);
  1338. }
  1339. if (pszFullName) {
  1340. FreeADsStr(pszFullName);
  1341. }
  1342. if (pszHomeDir) {
  1343. FreeADsStr(pszHomeDir);
  1344. }
  1345. if (pszScript) {
  1346. FreeADsStr(pszScript);
  1347. }
  1348. if (pszProfile) {
  1349. FreeADsStr(pszProfile);
  1350. }
  1351. if (pszLoginWorkstations) {
  1352. FreeADsStr(pszLoginWorkstations);
  1353. }
  1354. if (pszParameters) {
  1355. FreeADsStr(pszParameters);
  1356. }
  1357. if (pszHomeDirDrive) {
  1358. FreeADsStr(pszHomeDirDrive);
  1359. }
  1360. RRETURN(hr);
  1361. }
  1362. HRESULT
  1363. CWinNTUser::Marshall_Create_Level1(
  1364. LPWSTR szHostServerName,
  1365. LPUSER_INFO_1 pUserInfo1
  1366. )
  1367. {
  1368. HRESULT hr = S_OK;
  1369. NET_API_STATUS nasStatus;
  1370. DWORD dwParmErr;
  1371. pUserInfo1->usri1_name = _Name;
  1372. pUserInfo1->usri1_password = NULL;
  1373. pUserInfo1->usri1_password_age = DEF_MAX_PWAGE;
  1374. pUserInfo1->usri1_priv = 1;
  1375. pUserInfo1->usri1_home_dir = NULL;
  1376. pUserInfo1->usri1_comment = NULL;
  1377. pUserInfo1->usri1_flags = 0x00000201;
  1378. pUserInfo1->usri1_script_path = NULL;
  1379. nasStatus = NetUserAdd(
  1380. szHostServerName,
  1381. 1,
  1382. (LPBYTE)pUserInfo1,
  1383. &dwParmErr
  1384. );
  1385. hr = HRESULT_FROM_WIN32(nasStatus);
  1386. RRETURN(hr);
  1387. }
  1388. HRESULT
  1389. CWinNTUser::GetModalInfo(
  1390. THIS_ DWORD dwApiLevel,
  1391. BOOL fExplicit
  1392. )
  1393. {
  1394. NET_API_STATUS nasStatus;
  1395. LPBYTE lpBuffer = NULL;
  1396. HRESULT hr;
  1397. WCHAR szPDCName[MAX_PATH];
  1398. //
  1399. // objects associated with invalid SIDs have neither a
  1400. // corresponding server nor domain
  1401. //
  1402. if ((!_DomainName) && (!_ServerName)) {
  1403. BAIL_ON_FAILURE(hr = E_ADS_INVALID_USER_OBJECT);
  1404. }
  1405. if (_ParentType == WINNT_DOMAIN_ID) {
  1406. hr = WinNTGetCachedDCName(
  1407. _DomainName,
  1408. szPDCName,
  1409. _Credentials.GetFlags()
  1410. );
  1411. BAIL_ON_FAILURE(hr);
  1412. }else {
  1413. hr = MakeUncName(
  1414. _ServerName,
  1415. szPDCName
  1416. );
  1417. BAIL_ON_FAILURE(hr);
  1418. }
  1419. nasStatus = NetUserModalsGet(
  1420. szPDCName,
  1421. dwApiLevel,
  1422. &lpBuffer
  1423. );
  1424. hr = HRESULT_FROM_WIN32(nasStatus);
  1425. BAIL_ON_FAILURE(hr);
  1426. hr = UnMarshallModalInfo(lpBuffer, dwApiLevel, fExplicit);
  1427. BAIL_ON_FAILURE(hr);
  1428. error:
  1429. if (lpBuffer) {
  1430. NetApiBufferFree(lpBuffer);
  1431. }
  1432. RRETURN(hr);
  1433. }
  1434. HRESULT
  1435. CWinNTUser::UnMarshallModalInfo(
  1436. LPBYTE lpBuffer,
  1437. DWORD dwApiLevel,
  1438. BOOL fExplicit
  1439. )
  1440. {
  1441. ADsAssert(lpBuffer);
  1442. switch (dwApiLevel) {
  1443. case 0:
  1444. RRETURN(UnMarshall_ModalLevel0(fExplicit, (LPUSER_MODALS_INFO_0)lpBuffer));
  1445. break;
  1446. case 2:
  1447. RRETURN(UnMarshall_ModalLevel2(fExplicit, (LPUSER_MODALS_INFO_2)lpBuffer));
  1448. break;
  1449. case 3:
  1450. RRETURN(UnMarshall_ModalLevel3(fExplicit, (LPUSER_MODALS_INFO_3)lpBuffer));
  1451. break;
  1452. default:
  1453. RRETURN(E_FAIL);
  1454. }
  1455. }
  1456. HRESULT
  1457. CWinNTUser::UnMarshall_ModalLevel0(
  1458. BOOL fExplicit,
  1459. LPUSER_MODALS_INFO_0 pUserInfo0
  1460. )
  1461. {
  1462. HRESULT hr = S_OK;
  1463. hr = SetDWORDPropertyInCache(
  1464. _pPropertyCache,
  1465. TEXT("MinPasswordLength"),
  1466. pUserInfo0->usrmod0_min_passwd_len,
  1467. fExplicit
  1468. );
  1469. hr = SetDWORDPropertyInCache(
  1470. _pPropertyCache,
  1471. TEXT("MaxPasswordAge"),
  1472. pUserInfo0->usrmod0_max_passwd_age,
  1473. fExplicit
  1474. );
  1475. hr = SetDWORDPropertyInCache(
  1476. _pPropertyCache,
  1477. TEXT("MinPasswordAge"),
  1478. pUserInfo0->usrmod0_min_passwd_age,
  1479. fExplicit
  1480. );
  1481. hr = SetDWORDPropertyInCache(
  1482. _pPropertyCache,
  1483. TEXT("PasswordHistoryLength"),
  1484. pUserInfo0->usrmod0_password_hist_len,
  1485. fExplicit
  1486. );
  1487. RRETURN(S_OK);
  1488. }
  1489. HRESULT
  1490. CWinNTUser::UnMarshall_ModalLevel2(
  1491. BOOL fExplicit,
  1492. LPUSER_MODALS_INFO_2 pUserInfo2
  1493. )
  1494. {
  1495. RRETURN(S_OK);
  1496. }
  1497. HRESULT
  1498. CWinNTUser::UnMarshall_ModalLevel3(
  1499. BOOL fExplicit,
  1500. LPUSER_MODALS_INFO_3 pUserInfo3
  1501. )
  1502. {
  1503. HRESULT hr = S_OK;
  1504. hr = SetDWORDPropertyInCache(
  1505. _pPropertyCache,
  1506. TEXT("AutoUnlockInterval"),
  1507. pUserInfo3->usrmod3_lockout_duration,
  1508. fExplicit
  1509. );
  1510. hr = SetDWORDPropertyInCache(
  1511. _pPropertyCache,
  1512. TEXT("LockoutObservationInterval"),
  1513. pUserInfo3->usrmod3_lockout_observation_window,
  1514. fExplicit
  1515. );
  1516. hr = SetDWORDPropertyInCache(
  1517. _pPropertyCache,
  1518. TEXT("MaxBadPasswordsAllowed"),
  1519. pUserInfo3->usrmod3_lockout_threshold,
  1520. fExplicit
  1521. );
  1522. RRETURN(S_OK);
  1523. }
  1524. //
  1525. // This method is meant to set the password, so that new users
  1526. // can be created, their password set and then SetInfo can be
  1527. // called. This is necessary to allow creation of users when there
  1528. // are restrictions such as passwd should be present.
  1529. //
  1530. HRESULT
  1531. CWinNTUser::setPrivatePassword(
  1532. PWSTR pszNewPassword
  1533. )
  1534. {
  1535. HRESULT hr = S_OK;
  1536. // CCred safely stores password for us
  1537. if (_pCCredentialsPwdHolder) {
  1538. hr = _pCCredentialsPwdHolder->SetPassword(pszNewPassword);
  1539. BAIL_ON_FAILURE(hr);
  1540. } else
  1541. _pCCredentialsPwdHolder = new CCredentials(NULL, pszNewPassword, 0);
  1542. if (!_pCCredentialsPwdHolder) {
  1543. hr = E_OUTOFMEMORY;
  1544. } else
  1545. _fPasswordSet = TRUE;
  1546. error:
  1547. RRETURN(hr);
  1548. }
  1549. //
  1550. // This method is meant to set the password, so that new users
  1551. // can be created, their password set and then SetInfo can be
  1552. // called. This is necessary to allow creation of users when there
  1553. // are restrictions such as passwd should be present.
  1554. //
  1555. HRESULT
  1556. CWinNTUser::getPrivatePassword(
  1557. PWSTR * ppszPassword
  1558. )
  1559. {
  1560. HRESULT hr = S_OK;
  1561. if (_pCCredentialsPwdHolder && _fPasswordSet) {
  1562. hr = _pCCredentialsPwdHolder->GetPassword(ppszPassword);
  1563. } else
  1564. hr = E_FAIL;
  1565. RRETURN(hr);
  1566. }
  1567. HRESULT
  1568. CWinNTUser::GetUserFlags(
  1569. DWORD *pdwUserFlags
  1570. )
  1571. {
  1572. HRESULT hr = S_OK;
  1573. NET_API_STATUS nasStatus;
  1574. LPBYTE lpBuffer = NULL;
  1575. WCHAR szHostServerName[MAX_PATH];
  1576. ADsAssert(pdwUserFlags != NULL);
  1577. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  1578. RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
  1579. }
  1580. //
  1581. // objects associated with invalid SIDs have neither a
  1582. // corresponding server nor domain
  1583. //
  1584. if ((!_DomainName) && (!_ServerName)) {
  1585. BAIL_ON_FAILURE(hr = E_ADS_INVALID_USER_OBJECT);
  1586. }
  1587. if (_ParentType == WINNT_DOMAIN_ID) {
  1588. hr = WinNTGetCachedDCName(
  1589. _DomainName,
  1590. szHostServerName,
  1591. _Credentials.GetFlags()
  1592. );
  1593. BAIL_ON_FAILURE(hr);
  1594. }else {
  1595. hr = MakeUncName(
  1596. _ServerName,
  1597. szHostServerName
  1598. );
  1599. }
  1600. nasStatus = NetUserGetInfo(
  1601. szHostServerName,
  1602. _Name,
  1603. 3,
  1604. &lpBuffer
  1605. );
  1606. hr = HRESULT_FROM_WIN32(nasStatus);
  1607. BAIL_ON_FAILURE(hr);
  1608. *pdwUserFlags = ((LPUSER_INFO_3)lpBuffer)->usri3_flags;
  1609. error:
  1610. if (lpBuffer) {
  1611. NetApiBufferFree(lpBuffer);
  1612. }
  1613. RRETURN(hr);
  1614. }