Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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