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.

888 lines
22 KiB

  1. #include "stdafx.h"
  2. #include "Pop3Auth.h"
  3. #include "AuthDomainAccount.h"
  4. void CAuthDomainAccount::CleanDS()
  5. {
  6. if(m_hDS!=NULL)
  7. {
  8. DsUnBind(&m_hDS);
  9. m_hDS=NULL;
  10. }
  11. if(m_pDCInfo!=NULL)
  12. {
  13. NetApiBufferFree(m_pDCInfo);
  14. m_pDCInfo=NULL;
  15. }
  16. }
  17. HRESULT CAuthDomainAccount::ConnectDS()
  18. {
  19. HRESULT hr=S_OK;
  20. DWORD dwRt;
  21. if(NULL==m_pDCInfo)
  22. {
  23. dwRt=DsGetDcName(m_bstrServerName, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &m_pDCInfo);
  24. if(NO_ERROR != dwRt)
  25. {
  26. hr= HRESULT_FROM_WIN32(dwRt );
  27. goto EXIT;
  28. }
  29. }
  30. dwRt=DsBind(m_pDCInfo->DomainControllerName,
  31. NULL,
  32. &m_hDS);
  33. if(NO_ERROR != dwRt)
  34. {
  35. hr= HRESULT_FROM_WIN32(dwRt );
  36. goto EXIT;
  37. }
  38. EXIT:
  39. if(FAILED(hr))
  40. {
  41. CleanDS();
  42. }
  43. return hr;
  44. }
  45. HRESULT CAuthDomainAccount::ADGetUserObject(LPWSTR wszUserName, IADs **ppUserObj,DS_NAME_FORMAT formatUserName)
  46. {
  47. HRESULT hr=S_OK;
  48. PDS_NAME_RESULT pDSNR=NULL;
  49. BSTR bstrDN=NULL;
  50. IADsPathname *pADPath=NULL;
  51. if(NULL==wszUserName ||
  52. NULL == ppUserObj )
  53. {
  54. return E_POINTER;
  55. }
  56. if(FAILED(hr=CheckDS(FALSE)))
  57. {
  58. goto EXIT;
  59. }
  60. if(DS_NAME_NO_ERROR!=DsCrackNames(m_hDS,
  61. DS_NAME_NO_FLAGS,
  62. formatUserName,
  63. DS_FQDN_1779_NAME,
  64. 1,
  65. &wszUserName,
  66. &pDSNR) )
  67. {
  68. hr=HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
  69. //Re-connect to DS and try again
  70. if(SUCCEEDED(CheckDS(TRUE)))
  71. {
  72. if(DS_NAME_NO_ERROR!=DsCrackNames(m_hDS,
  73. DS_NAME_NO_FLAGS,
  74. formatUserName,
  75. DS_FQDN_1779_NAME,
  76. 1,
  77. &wszUserName,
  78. &pDSNR) )
  79. {
  80. goto EXIT;
  81. }
  82. else
  83. {
  84. hr=S_OK;
  85. }
  86. }
  87. else
  88. {
  89. goto EXIT;
  90. }
  91. }
  92. if( NULL == pDSNR )
  93. {
  94. hr=HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
  95. goto EXIT;
  96. }
  97. else
  98. {
  99. if((pDSNR->cItems != 1 ) ||
  100. (pDSNR->rItems->status != DS_NAME_NO_ERROR))
  101. {
  102. if(pDSNR->rItems->status != DS_NAME_NO_ERROR)
  103. {
  104. if(ERROR_FILE_NOT_FOUND == pDSNR->rItems->status)
  105. {
  106. hr=HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
  107. }
  108. else
  109. {
  110. hr=HRESULT_FROM_WIN32(pDSNR->rItems->status);
  111. }
  112. }
  113. else
  114. {
  115. hr=E_FAIL;
  116. }
  117. goto EXIT;
  118. }
  119. }
  120. // Escaped Mode of the DN
  121. hr = CoCreateInstance(CLSID_Pathname,
  122. NULL,
  123. CLSCTX_INPROC_SERVER,
  124. IID_IADsPathname,
  125. (void**)&pADPath);
  126. if(SUCCEEDED(hr))
  127. {
  128. hr=pADPath->Set(pDSNR->rItems->pName, ADS_SETTYPE_DN);
  129. if(SUCCEEDED(hr))
  130. {
  131. hr=pADPath->put_EscapedMode(ADS_ESCAPEDMODE_ON);
  132. if(SUCCEEDED(hr))
  133. {
  134. hr=pADPath->Retrieve(ADS_FORMAT_X500_NO_SERVER, &bstrDN);
  135. if(SUCCEEDED(hr))
  136. {
  137. hr=ADsGetObject(bstrDN, IID_IADs, (void **)ppUserObj);
  138. }
  139. }
  140. }
  141. pADPath->Release();
  142. }
  143. EXIT:
  144. if(pDSNR)
  145. {
  146. DsFreeNameResult(pDSNR);
  147. }
  148. if(bstrDN)
  149. {
  150. SysFreeString(bstrDN);
  151. }
  152. return hr;
  153. }
  154. HRESULT CAuthDomainAccount::ADSetUserProp(LPWSTR wszValue, LPWSTR wszLdapPropName)
  155. {
  156. HRESULT hr=S_OK;
  157. IADs *pUserObj=NULL;
  158. WCHAR wszUserName[POP3_MAX_ADDRESS_LENGTH];
  159. WCHAR *pAt;
  160. VARIANT var;
  161. if(NULL == wszValue || NULL == wszLdapPropName)
  162. {
  163. return E_INVALIDARG;
  164. }
  165. var.vt=VT_BSTR;
  166. var.bstrVal=SysAllocString(wszValue);
  167. if(NULL == var.bstrVal)
  168. {
  169. return E_OUTOFMEMORY;
  170. }
  171. int iNameLen=0;
  172. pAt=wcschr(wszValue, L'@');
  173. if( (NULL == pAt ) ||
  174. ((iNameLen =(int)(pAt - wszValue)) >= (sizeof(wszUserName)/sizeof(WCHAR)-1)) )
  175. {
  176. return E_INVALIDARG;
  177. }
  178. if( SUCCEEDED(hr=CheckDS(FALSE)) &&
  179. (NULL != m_pDCInfo) )
  180. {
  181. memset(wszUserName, 0, sizeof(wszUserName));
  182. // Copy username@ to the buffer
  183. memcpy(wszUserName, wszValue, (iNameLen+1)*sizeof(WCHAR));
  184. if(wcslen(m_pDCInfo->DomainName)+iNameLen+1 >= sizeof(wszUserName)/sizeof(WCHAR)-1 )
  185. {
  186. hr=E_FAIL;
  187. }
  188. else
  189. {
  190. //This size is already calculated to fit in the buffer
  191. //Create the User's principal name username@domainname
  192. wcscat(wszUserName, m_pDCInfo->DomainName );
  193. hr=ADGetUserObject(wszUserName, &pUserObj,DS_USER_PRINCIPAL_NAME);
  194. if(SUCCEEDED(hr))
  195. {
  196. hr=pUserObj->Put(wszLdapPropName, var);
  197. if(SUCCEEDED(hr))
  198. {
  199. hr=pUserObj->SetInfo();
  200. }
  201. }
  202. if(pUserObj)
  203. {
  204. pUserObj->Release();
  205. }
  206. }
  207. }
  208. VariantClear(&var);
  209. return hr;
  210. }
  211. // wszUserName must be in the UPN format
  212. HRESULT CAuthDomainAccount::ADGetUserProp(LPWSTR wszUserName,LPWSTR wszPropName, VARIANT *pVar)
  213. {
  214. HRESULT hr=S_OK;
  215. if( NULL==pVar ||
  216. wszUserName==NULL )
  217. {
  218. return E_POINTER;
  219. }
  220. IADs *pUserObj=NULL;
  221. VariantInit(pVar);
  222. if(NULL == wcschr(wszUserName, L'@'))
  223. {
  224. hr=ADGetUserObject(wszUserName, &pUserObj, DS_NT4_ACCOUNT_NAME);
  225. }
  226. else
  227. {
  228. hr=ADGetUserObject(wszUserName, &pUserObj, DS_USER_PRINCIPAL_NAME);
  229. }
  230. if(SUCCEEDED(hr))
  231. {
  232. hr=pUserObj->Get(wszPropName, pVar);
  233. pUserObj->Release();
  234. }
  235. return hr;
  236. }
  237. HRESULT CAuthDomainAccount::CheckDS(BOOL bForceReconnect)
  238. {
  239. HRESULT hr=S_OK;
  240. EnterCriticalSection(&m_DSLock);
  241. if(bForceReconnect)
  242. {
  243. CleanDS();
  244. }
  245. if(NULL == m_hDS)
  246. {
  247. hr=ConnectDS();
  248. }
  249. LeaveCriticalSection(&m_DSLock);
  250. return hr;
  251. }
  252. CAuthDomainAccount::CAuthDomainAccount()
  253. {
  254. m_bstrServerName=NULL;
  255. m_hDS=NULL;
  256. m_pDCInfo=NULL;
  257. InitializeCriticalSection(&m_DSLock);
  258. }
  259. CAuthDomainAccount::~CAuthDomainAccount()
  260. {
  261. if(m_bstrServerName!=NULL)
  262. {
  263. SysFreeString(m_bstrServerName);
  264. m_bstrServerName=NULL;
  265. }
  266. CleanDS();
  267. DeleteCriticalSection(&m_DSLock);
  268. }
  269. STDMETHODIMP CAuthDomainAccount::Authenticate(/*[in]*/BSTR bstrUserName,/*[in]*/VARIANT vPassword)
  270. {
  271. WCHAR *pDomain=NULL;
  272. if(vPassword.vt != VT_BSTR)
  273. {
  274. return E_INVALIDARG;
  275. }
  276. if(NULL==bstrUserName)
  277. {
  278. return E_POINTER;
  279. }
  280. HANDLE hToken;
  281. //UPN name logon
  282. if( LogonUser(bstrUserName,
  283. NULL,
  284. vPassword.bstrVal,
  285. LOGON32_LOGON_NETWORK,
  286. LOGON32_PROVIDER_DEFAULT,
  287. &hToken))
  288. {
  289. CloseHandle(hToken);
  290. return S_OK;
  291. }
  292. return E_FAIL;
  293. }
  294. STDMETHODIMP CAuthDomainAccount::get_Name(/*[out]*/BSTR *pVal)
  295. {
  296. WCHAR wszBuffer[MAX_PATH+1];
  297. if(NULL==pVal)
  298. {
  299. return E_POINTER;
  300. }
  301. if(LoadString(_Module.GetResourceInstance(), IDS_AUTH_DOMAIN_ACCOUNT, wszBuffer, sizeof(wszBuffer)/sizeof(WCHAR)-1))
  302. {
  303. *pVal=SysAllocString(wszBuffer);
  304. if(NULL==*pVal)
  305. {
  306. return E_OUTOFMEMORY;
  307. }
  308. else
  309. {
  310. return S_OK;
  311. }
  312. }
  313. else
  314. {
  315. return E_FAIL;
  316. }
  317. }
  318. STDMETHODIMP CAuthDomainAccount::get_ID(/*[out]*/BSTR *pVal)
  319. {
  320. if(NULL==pVal)
  321. {
  322. return E_POINTER;
  323. }
  324. *pVal=SysAllocString(SZ_AUTH_ID_DOMAIN_AD);
  325. if(NULL==*pVal)
  326. {
  327. return E_OUTOFMEMORY;
  328. }
  329. else
  330. {
  331. return S_OK;
  332. }
  333. }
  334. STDMETHODIMP CAuthDomainAccount::Get(/*[in]*/BSTR bstrName, /*[in, out]*/VARIANT *pVal)
  335. {
  336. BSTR bstrUserName=NULL;
  337. HRESULT hr;
  338. if(NULL == bstrName ||
  339. NULL == pVal)
  340. {
  341. return E_INVALIDARG;
  342. }
  343. if( 0 == wcscmp(bstrName, SZ_EMAILADDR ))
  344. {
  345. if(pVal->vt!=VT_BSTR)
  346. {
  347. return E_INVALIDARG;
  348. }
  349. bstrUserName=SysAllocString(pVal->bstrVal);
  350. if(NULL == bstrUserName)
  351. {
  352. return E_OUTOFMEMORY;
  353. }
  354. VariantClear(pVal);
  355. hr=ADGetUserProp(bstrUserName,SZ_LDAP_EMAIL, pVal);
  356. SysFreeString(bstrUserName);
  357. return hr;
  358. }
  359. else if( 0== wcscmp(bstrName, SZ_SAMACCOUNT_NAME ) )
  360. {
  361. if(pVal->vt!=VT_BSTR)
  362. {
  363. return E_INVALIDARG;
  364. }
  365. bstrUserName=SysAllocString(pVal->bstrVal);
  366. if(NULL == bstrUserName)
  367. {
  368. return E_OUTOFMEMORY;
  369. }
  370. VariantClear(pVal);
  371. hr=ADGetUserProp(bstrUserName,SZ_LDAP_SAM_NAME, pVal);
  372. SysFreeString(bstrUserName);
  373. return hr;
  374. }
  375. return S_FALSE;
  376. }
  377. STDMETHODIMP CAuthDomainAccount::Put(/*[in]*/BSTR bstrName, /*[in]*/VARIANT vVal)
  378. {
  379. if(NULL == bstrName)
  380. {
  381. return E_INVALIDARG;
  382. }
  383. if(0==wcscmp(bstrName,SZ_SERVER_NAME ))
  384. {
  385. if( (vVal.vt!=VT_BSTR) ||
  386. (vVal.bstrVal==NULL ) )
  387. {
  388. return E_INVALIDARG;
  389. }
  390. else
  391. {
  392. if(m_bstrServerName!=NULL)
  393. {
  394. SysFreeString(m_bstrServerName);
  395. m_bstrServerName=NULL;
  396. }
  397. m_bstrServerName = SysAllocString(vVal.bstrVal);
  398. if(NULL == m_bstrServerName)
  399. {
  400. return E_OUTOFMEMORY;
  401. }
  402. // If AD verify both machine are members of the same domain
  403. HRESULT hr = E_ACCESSDENIED;
  404. NET_API_STATUS netStatus;
  405. LPWSTR psNameBufferRemote, psNameBufferLocal;
  406. NETSETUP_JOIN_STATUS enumJoinStatus;
  407. netStatus = NetGetJoinInformation( m_bstrServerName, &psNameBufferRemote, &enumJoinStatus );
  408. if ( NERR_Success == netStatus && NetSetupDomainName == enumJoinStatus )
  409. {
  410. netStatus = NetGetJoinInformation( NULL, &psNameBufferLocal, &enumJoinStatus );
  411. if ( NERR_Success == netStatus && NetSetupDomainName == enumJoinStatus )
  412. {
  413. if ( 0 == wcscmp( psNameBufferLocal, psNameBufferRemote ))
  414. hr = S_OK;
  415. NetApiBufferFree( psNameBufferLocal );
  416. }
  417. NetApiBufferFree( psNameBufferRemote );
  418. }
  419. return hr;
  420. }
  421. }
  422. else if( 0==wcscmp(bstrName,SZ_EMAILADDR))
  423. {
  424. //Set the email address to the user object in AD
  425. //vVal must be of array of 2 bstr Variants
  426. if(vVal.vt!=VT_BSTR)
  427. {
  428. return E_INVALIDARG;
  429. }
  430. return ADSetUserProp(vVal.bstrVal, SZ_LDAP_EMAIL);
  431. }
  432. else if( 0==wcscmp(bstrName, SZ_USERPRICIPALNAME))
  433. {
  434. if(vVal.vt!=VT_BSTR)
  435. {
  436. return E_INVALIDARG;
  437. }
  438. return ADSetUserProp(vVal.bstrVal, SZ_LDAP_UPN_NAME);
  439. }
  440. return S_FALSE;
  441. }
  442. STDMETHODIMP CAuthDomainAccount::CreateUser(/*[in]*/BSTR bstrUserName,/*[in]*/VARIANT vPassword)
  443. {
  444. WCHAR wszUserSAMName[MAX_USER_NAME_LENGTH+MAX_PATH+1];
  445. WCHAR wszUserName[MAX_USER_NAME_LENGTH+1];
  446. DWORD dwRt;
  447. BOOL bServerName=FALSE;
  448. VARIANT var;
  449. VariantInit(&var);
  450. IADs *pUserObj=NULL;
  451. HRESULT hr=E_FAIL;
  452. if( NULL == bstrUserName )
  453. {
  454. return E_POINTER;
  455. }
  456. if( vPassword.vt!= VT_BSTR )
  457. {
  458. return E_INVALIDARG;
  459. }
  460. if(NULL==m_pDCInfo)
  461. {
  462. dwRt=DsGetDcName(m_bstrServerName, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &m_pDCInfo);
  463. if(NO_ERROR != dwRt)
  464. {
  465. return HRESULT_FROM_WIN32(dwRt);
  466. }
  467. if(wcslen(m_pDCInfo->DomainName) >= MAX_PATH)
  468. {
  469. return E_FAIL;
  470. }
  471. }
  472. //First find out if the UPN name / Email address is in use
  473. hr=ADGetUserObject(bstrUserName, &pUserObj,DS_USER_PRINCIPAL_NAME);
  474. if(SUCCEEDED(hr))
  475. {
  476. pUserObj->Release();
  477. hr=HRESULT_FROM_WIN32(ERROR_USER_EXISTS);
  478. }
  479. else
  480. {
  481. hr=S_OK;
  482. }
  483. if( (S_OK==hr) &&
  484. (FindSAMName(bstrUserName, wszUserName)) )
  485. {
  486. USER_INFO_1 UserInfoBuf;
  487. UserInfoBuf.usri1_name=wszUserName;
  488. UserInfoBuf.usri1_password=vPassword.bstrVal;
  489. UserInfoBuf.usri1_priv=USER_PRIV_USER;
  490. UserInfoBuf.usri1_home_dir=NULL;
  491. UserInfoBuf.usri1_comment=NULL;
  492. UserInfoBuf.usri1_flags=UF_NORMAL_ACCOUNT;
  493. UserInfoBuf.usri1_script_path=NULL;
  494. dwRt=NetUserAdd(m_pDCInfo->DomainControllerName,
  495. 1,
  496. (LPBYTE)(&UserInfoBuf),
  497. NULL);
  498. if(NERR_Success==dwRt)
  499. {
  500. //The lengh of m_pDCInfo->DomainName is at most MAX_PATH-1
  501. //and SAM account name is at most MAX_USER_NAME_LENGTH
  502. wcscpy(wszUserSAMName,wszUserName );
  503. wcscat(wszUserSAMName,L"@");
  504. wcscat(wszUserSAMName,m_pDCInfo->DomainName);
  505. hr=ADGetUserObject(wszUserSAMName, &pUserObj, DS_USER_PRINCIPAL_NAME);
  506. //Set the email address and UPN name to the AD account
  507. if(SUCCEEDED(hr))
  508. {
  509. var.vt=VT_BSTR;
  510. var.bstrVal=bstrUserName;
  511. hr=pUserObj->Put(SZ_LDAP_EMAIL, var);
  512. if(SUCCEEDED(hr))
  513. {
  514. hr=pUserObj->Put(SZ_LDAP_UPN_NAME, var);
  515. if(SUCCEEDED(hr))
  516. {
  517. hr=pUserObj->SetInfo();
  518. }
  519. }
  520. pUserObj->Release();
  521. }
  522. if(FAILED(hr)) //In this case, delete the user just created
  523. {
  524. dwRt=NetUserDel(m_pDCInfo->DomainControllerName, wszUserName);
  525. //Don't care about the return value dwRt
  526. }
  527. }
  528. else
  529. {
  530. hr=HRESULT_FROM_WIN32(dwRt);
  531. }
  532. }
  533. return hr;
  534. }
  535. STDMETHODIMP CAuthDomainAccount::DeleteUser(/*[in]*/BSTR bstrUserName)
  536. {
  537. DWORD dwRt;
  538. HRESULT hr=E_FAIL;
  539. if( NULL == bstrUserName)
  540. {
  541. return E_POINTER;
  542. }
  543. if(NULL==m_pDCInfo)
  544. {
  545. dwRt=DsGetDcName(m_bstrServerName, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &m_pDCInfo);
  546. if(NO_ERROR != dwRt)
  547. {
  548. return HRESULT_FROM_WIN32(dwRt);
  549. }
  550. }
  551. VARIANT var;
  552. VariantInit(&var);
  553. hr=ADGetUserProp(bstrUserName,SZ_LDAP_SAM_NAME, &var);
  554. if(SUCCEEDED(hr))
  555. {
  556. dwRt=NetUserDel(m_pDCInfo->DomainControllerName,
  557. var.bstrVal);
  558. if(NERR_Success==dwRt)
  559. {
  560. hr= S_OK;
  561. }
  562. else
  563. {
  564. hr=HRESULT_FROM_WIN32(dwRt);
  565. }
  566. VariantClear(&var);
  567. }
  568. return hr;
  569. }
  570. STDMETHODIMP CAuthDomainAccount::ChangePassword(/*[in]*/BSTR bstrUserName,/*[in]*/VARIANT vNewPassword,/*[in]*/VARIANT vOldPassword)
  571. {
  572. HRESULT hr=E_FAIL;
  573. DWORD dwRt;
  574. if( NULL == bstrUserName)
  575. {
  576. return E_POINTER;
  577. }
  578. if( vNewPassword.vt!= VT_BSTR )
  579. {
  580. return E_INVALIDARG;
  581. }
  582. if(NULL==m_pDCInfo)
  583. {
  584. dwRt=DsGetDcName(m_bstrServerName, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &m_pDCInfo);
  585. if(NO_ERROR != dwRt)
  586. {
  587. return HRESULT_FROM_WIN32(dwRt);
  588. }
  589. }
  590. VARIANT var;
  591. VariantInit(&var);
  592. hr=ADGetUserProp(bstrUserName,SZ_LDAP_SAM_NAME, &var);
  593. if(SUCCEEDED(hr))
  594. {
  595. USER_INFO_1 * pUserInfo=NULL;
  596. dwRt=NetUserGetInfo(m_pDCInfo->DomainControllerName,
  597. var.bstrVal,
  598. 1,
  599. (LPBYTE *)&pUserInfo);
  600. if(NERR_Success==dwRt)
  601. {
  602. pUserInfo->usri1_password=vNewPassword.bstrVal;
  603. dwRt=NetUserSetInfo(m_pDCInfo->DomainControllerName,
  604. var.bstrVal,
  605. 1,
  606. (LPBYTE)pUserInfo,
  607. NULL);
  608. pUserInfo->usri1_password=NULL;
  609. NetApiBufferFree(pUserInfo);
  610. }
  611. if(NERR_Success==dwRt)
  612. {
  613. hr = S_OK;
  614. }
  615. hr = HRESULT_FROM_WIN32(dwRt);
  616. }
  617. return hr;
  618. }
  619. STDMETHODIMP CAuthDomainAccount::AssociateEmailWithUser(/*[in]*/BSTR bstrEmailAddr)
  620. {
  621. IADs *pUserObj=NULL;
  622. HRESULT hr=E_FAIL;
  623. WCHAR *pAt=NULL;
  624. WCHAR wszUserName[POP3_MAX_ADDRESS_LENGTH];
  625. VARIANT var;
  626. VariantInit(&var);
  627. DWORD dwRt=0;
  628. if( NULL == bstrEmailAddr)
  629. {
  630. return E_POINTER;
  631. }
  632. //First check if the email address is already used
  633. hr=ADGetUserObject(bstrEmailAddr, &pUserObj,DS_USER_PRINCIPAL_NAME);
  634. if(SUCCEEDED(hr))
  635. {
  636. //Now set the UPN name and the Email address
  637. var.vt=VT_BSTR;
  638. var.bstrVal=bstrEmailAddr;
  639. hr=pUserObj->Put(SZ_LDAP_EMAIL, var);
  640. if(SUCCEEDED(hr))
  641. {
  642. hr=pUserObj->SetInfo();
  643. }
  644. pUserObj->Release();
  645. return hr;
  646. }
  647. if(NULL==m_pDCInfo)
  648. {
  649. dwRt=DsGetDcName(m_bstrServerName, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &m_pDCInfo);
  650. if(NO_ERROR != dwRt)
  651. {
  652. return HRESULT_FROM_WIN32(dwRt );
  653. }
  654. }
  655. int iNameLen=0;
  656. //Check if the AD account exists
  657. pAt=wcschr(bstrEmailAddr, L'@');
  658. if( (NULL == pAt ) ||
  659. ((iNameLen =(int)(pAt - bstrEmailAddr)) >= sizeof(wszUserName)/sizeof(WCHAR)-1) )
  660. {
  661. return E_FAIL;
  662. }
  663. if(wcslen(m_pDCInfo->DomainName)+iNameLen+1 >= sizeof(wszUserName)/sizeof(WCHAR)-1 )
  664. {
  665. hr=E_FAIL;
  666. }
  667. else
  668. {
  669. //This size is already calculated to fit in the buffer
  670. //Create the User's principal name username@domainname
  671. memset(wszUserName, 0, sizeof(wszUserName));
  672. // Copy username@ to the buffer
  673. memcpy(wszUserName, bstrEmailAddr, (iNameLen+1)*sizeof(WCHAR));
  674. wcscat(wszUserName, m_pDCInfo->DomainName );
  675. hr=ADGetUserObject(wszUserName, &pUserObj, DS_USER_PRINCIPAL_NAME);
  676. //Set the email address and UPN name to the AD account
  677. if(SUCCEEDED(hr))
  678. {
  679. var.vt=VT_BSTR;
  680. var.bstrVal=bstrEmailAddr;
  681. hr=pUserObj->Put(SZ_LDAP_EMAIL, var);
  682. if(SUCCEEDED(hr))
  683. {
  684. hr=pUserObj->Put(SZ_LDAP_UPN_NAME, var);
  685. if(SUCCEEDED(hr))
  686. {
  687. hr=pUserObj->SetInfo();
  688. }
  689. }
  690. pUserObj->Release();
  691. }
  692. }
  693. return hr;
  694. }
  695. STDMETHODIMP CAuthDomainAccount::UnassociateEmailWithUser(/*[in]*/BSTR bstrEmailAddr)
  696. {
  697. IADs *pUserObj=NULL;
  698. HRESULT hr=E_FAIL;
  699. BSTR bstrSAMAccountName=NULL;
  700. VARIANT var;
  701. VariantInit(&var);
  702. if( NULL == bstrEmailAddr)
  703. {
  704. return E_POINTER;
  705. }
  706. //Find the user account with the email address
  707. hr=ADGetUserObject(bstrEmailAddr, &pUserObj, DS_USER_PRINCIPAL_NAME);
  708. if(SUCCEEDED(hr))
  709. {
  710. //Remove the email address and UPN name from the account
  711. hr=pUserObj->PutEx(ADS_PROPERTY_CLEAR,SZ_LDAP_EMAIL, var);
  712. if(SUCCEEDED(hr))
  713. {
  714. hr=pUserObj->PutEx(ADS_PROPERTY_CLEAR, SZ_LDAP_UPN_NAME, var);
  715. if(SUCCEEDED(hr))
  716. {
  717. hr=pUserObj->SetInfo();
  718. }
  719. }
  720. pUserObj->Release();
  721. }
  722. return hr;
  723. }
  724. BOOL CAuthDomainAccount::FindSAMName(/*[in]*/LPWSTR wszEmailAddr,/*[out]*/ LPWSTR wszSAMName)
  725. {
  726. WCHAR *pAt=NULL;
  727. USER_INFO_1 * pUserInfo=NULL;
  728. DWORD dwRt=0;
  729. int iLen=0;
  730. if(wszEmailAddr == NULL || wszSAMName == NULL)
  731. {
  732. return FALSE;
  733. }
  734. wcsncpy(wszSAMName, wszEmailAddr, MAX_USER_NAME_LENGTH);
  735. wszSAMName[MAX_USER_NAME_LENGTH]=0;
  736. pAt=wcschr(wszSAMName, L'@');
  737. if(pAt)
  738. {
  739. *pAt=0;
  740. }
  741. dwRt=NetUserGetInfo(m_pDCInfo->DomainControllerName,
  742. wszSAMName,
  743. 1,
  744. (LPBYTE *)&pUserInfo);
  745. if(NERR_UserNotFound==dwRt)
  746. {
  747. return TRUE; //Found the available SAM name
  748. }
  749. else
  750. {
  751. NetApiBufferFree(pUserInfo);
  752. }
  753. iLen=wcslen(wszSAMName);
  754. if(iLen>MAX_USER_NAME_LENGTH-3)
  755. {
  756. iLen=MAX_USER_NAME_LENGTH-3;
  757. }
  758. while(iLen && L'.'==wszSAMName[iLen-1] )
  759. {
  760. iLen--;
  761. }
  762. if(0==iLen)
  763. {
  764. return FALSE;
  765. }
  766. for(WCHAR chD1=L'0'; chD1<=L'9'; chD1++)
  767. {
  768. wszSAMName[iLen]=chD1;
  769. for(WCHAR chD2=L'0'; chD2<=L'9'; chD2++)
  770. {
  771. wszSAMName[iLen+1]=chD2;
  772. for(WCHAR chD3=L'0'; chD3<=L'9'; chD3++)
  773. {
  774. wszSAMName[iLen+2]=chD3;
  775. wszSAMName[iLen+3]=0;
  776. dwRt=NetUserGetInfo(m_pDCInfo->DomainControllerName,
  777. wszSAMName,
  778. 1,
  779. (LPBYTE *)&pUserInfo);
  780. if(NERR_UserNotFound==dwRt)
  781. {
  782. return TRUE; //Found the available SAM name
  783. }
  784. else
  785. {
  786. NetApiBufferFree(pUserInfo);
  787. }
  788. }
  789. }
  790. }
  791. return FALSE;
  792. }