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.

867 lines
19 KiB

  1. /* ----------------------------------------------------------------------
  2. Module: ULS.DLL (Service Provider)
  3. File: spluser.cpp
  4. Content: This file contains the local user object.
  5. History:
  6. 10/15/96 Chu, Lon-Chan [lonchanc]
  7. Created.
  8. Copyright (c) Microsoft Corporation 1996-1997
  9. ---------------------------------------------------------------------- */
  10. #include "ulsp.h"
  11. #include "spinc.h"
  12. // Array of constant strings for user object's attribute names
  13. //
  14. const TCHAR *c_apszUserStdAttrNames[COUNT_ENUM_USERATTR] =
  15. {
  16. TEXT ("cn"),
  17. TEXT ("givenname"),
  18. TEXT ("surname"),
  19. TEXT ("rfc822mailbox"),
  20. TEXT ("location"),
  21. #ifdef USE_DEFAULT_COUNTRY
  22. TEXT ("aCountryName"),
  23. #endif
  24. TEXT ("comment"),
  25. TEXT ("sipaddress"),
  26. TEXT ("sflags"),
  27. TEXT ("c"),
  28. TEXT ("ssecurity"),
  29. TEXT ("sttl"),
  30. TEXT ("objectClass"),
  31. TEXT ("o"),
  32. };
  33. /* ---------- public methods ----------- */
  34. UlsLdap_CLocalUser::
  35. UlsLdap_CLocalUser ( VOID )
  36. {
  37. // Reference count
  38. //
  39. m_cRefs = 0;
  40. // User object's signature
  41. //
  42. m_uSignature = USEROBJ_SIGNATURE;
  43. // Clean up attached server info structure
  44. //
  45. ZeroMemory (&m_ServerInfo, sizeof (m_ServerInfo));
  46. // Clean up the scratch buffer for caching pointers to attribute values
  47. //
  48. ZeroMemory (&m_UserInfo, sizeof (m_UserInfo));
  49. // Clean up DN (old and current ones)
  50. m_pszDN = NULL;
  51. m_pszOldDN = NULL;
  52. // Clean up the refresh search filter
  53. //
  54. m_pszRefreshFilter = NULL;
  55. // Indicate this user is not registered yet
  56. //
  57. SetRegNone ();
  58. // Reset time to live value
  59. m_uTTL = ULS_DEF_REFRESH_MINUTE; // in unit of minute: no effect on current ils, but to avoid legacy issue later
  60. m_dwIPAddress = 0;
  61. }
  62. UlsLdap_CLocalUser::
  63. ~UlsLdap_CLocalUser ( VOID )
  64. {
  65. // Invalidate the user object's signature
  66. //
  67. m_uSignature = (ULONG) -1;
  68. // Free server info structure
  69. //
  70. ::IlsFreeServerInfo (&m_ServerInfo);
  71. // Free DN (old and current ones)
  72. //
  73. MemFree (m_pszDN);
  74. MemFree (m_pszOldDN);
  75. // Free the refresh search filter
  76. //
  77. MemFree (m_pszRefreshFilter);
  78. }
  79. ULONG UlsLdap_CLocalUser::
  80. AddRef ( VOID )
  81. {
  82. InterlockedIncrement (&m_cRefs);
  83. return m_cRefs;
  84. }
  85. ULONG UlsLdap_CLocalUser::
  86. Release ( VOID )
  87. {
  88. MyAssert (m_cRefs != 0);
  89. if (m_cRefs != 0)
  90. {
  91. InterlockedDecrement (&m_cRefs);
  92. }
  93. ULONG cRefs = m_cRefs;
  94. if (cRefs == 0)
  95. delete this;
  96. return cRefs;
  97. }
  98. HRESULT UlsLdap_CLocalUser::
  99. Register ( ULONG *puRespID, SERVER_INFO *pServerInfo, LDAP_USERINFO *pInfo )
  100. {
  101. MyAssert (puRespID != NULL);
  102. MyAssert (pInfo != NULL);
  103. MyAssert ( pServerInfo->pszServerName != NULL &&
  104. pServerInfo->pszServerName[0] != TEXT ('\0'));
  105. MyAssert ( pServerInfo->pszBaseDN != NULL &&
  106. pServerInfo->pszBaseDN[0] != TEXT ('\0'));
  107. // cache the server info
  108. HRESULT hr = ::IlsCopyServerInfo (&m_ServerInfo, pServerInfo);
  109. if (hr != S_OK)
  110. return hr;
  111. // cache user info
  112. hr = CacheUserInfo (pInfo);
  113. if (hr != S_OK)
  114. return hr;
  115. // get ip address
  116. m_dwIPAddress = 0;
  117. hr = ::GetLocalIPAddress (&m_dwIPAddress);
  118. if (hr != S_OK)
  119. return hr;
  120. // Create IP address string
  121. //
  122. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_IP_ADDRESS] = &m_UserInfo.szIPAddress[0];
  123. ::GetLongString (m_dwIPAddress, &m_UserInfo.szIPAddress[0]);
  124. // Create client signature string
  125. //
  126. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CLIENT_SIG] = &m_UserInfo.szClientSig[0];
  127. ::GetLongString (g_dwClientSig, &m_UserInfo.szClientSig[0]);
  128. // Create TTL string
  129. //
  130. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_TTL] = &m_UserInfo.szTTL[0];
  131. ::GetLongString (m_uTTL, &m_UserInfo.szTTL[0]);
  132. // ideally, o= and c= should be read in from registiry
  133. // but for now, we simply hard code it
  134. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_OBJECT_CLASS] = (TCHAR *) &c_szRTPerson[0];
  135. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_O] = (TCHAR *) &c_szDefO[0];
  136. #ifdef USE_DEFAULT_COUNTRY
  137. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_C] = (TCHAR *) &c_szDefC[0];
  138. #endif
  139. // build DN
  140. hr = BuildDN ();
  141. if (hr != S_OK)
  142. return hr;
  143. // build refreh filter
  144. m_pszRefreshFilter = UserCreateRefreshFilter (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN]);
  145. if (m_pszRefreshFilter == NULL)
  146. return ULS_E_MEMORY;
  147. // build modify array for ldap_add()
  148. LDAPMod **ppMod = NULL;
  149. hr = CreateRegisterModArr (&ppMod);
  150. if (hr != S_OK)
  151. return hr;
  152. MyAssert (ppMod != NULL);
  153. // so far, we are done with local preparation
  154. // get the connection object
  155. UlsLdap_CSession *pSession = NULL;
  156. hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  157. if (hr != S_OK)
  158. {
  159. MemFree (ppMod);
  160. return hr;
  161. }
  162. MyAssert (pSession != NULL);
  163. // get the ldap session
  164. LDAP *ld = pSession->GetLd ();
  165. MyAssert (ld != NULL);
  166. // send the data over the wire
  167. ULONG uMsgID = ldap_add (ld, GetDN (), ppMod);
  168. MemFree (ppMod);
  169. if (uMsgID == -1)
  170. {
  171. hr = ::LdapError2Hresult (ld->ld_errno);
  172. pSession->Disconnect ();
  173. return hr;
  174. }
  175. // construct a pending info
  176. PENDING_INFO PendingInfo;
  177. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
  178. PendingInfo.uLdapResType = LDAP_RES_ADD;
  179. PendingInfo.uNotifyMsg = WM_ULS_REGISTER_USER;
  180. PendingInfo.hObject = (HANDLE) this;
  181. // queue it
  182. hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
  183. if (hr != S_OK)
  184. {
  185. ldap_abandon (ld, uMsgID);
  186. pSession->Disconnect ();
  187. MyAssert (FALSE);
  188. }
  189. *puRespID = PendingInfo.uRespID;
  190. return hr;
  191. }
  192. HRESULT UlsLdap_CLocalUser::
  193. UnRegister ( ULONG *puRespID )
  194. {
  195. MyAssert (puRespID != NULL);
  196. // Make sure that there is not refresh scheduled for this object
  197. //
  198. if (g_pRefreshScheduler != NULL)
  199. {
  200. g_pRefreshScheduler->RemoveUserObject (this);
  201. }
  202. else
  203. {
  204. MyAssert (FALSE);
  205. }
  206. // Unregister it locally
  207. //
  208. if (! IsRegRemotely ())
  209. {
  210. *puRespID = ::GetUniqueNotifyID ();
  211. SetRegNone ();
  212. PostMessage (g_hWndNotify, WM_ULS_UNREGISTER_USER, *puRespID, S_OK);
  213. return S_OK;
  214. }
  215. SetRegNone ();
  216. // Get the session object
  217. //
  218. UlsLdap_CSession *pSession = NULL;
  219. HRESULT hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  220. if (hr != S_OK)
  221. return hr;
  222. MyAssert (pSession != NULL);
  223. // Get the ldap session
  224. //
  225. LDAP *ld = pSession->GetLd ();
  226. MyAssert (ld != NULL);
  227. // LONCHANC: notify global user object of this unregister user
  228. // send the data over the wire
  229. ULONG uMsgID = ldap_delete (ld, GetDN ());
  230. if (uMsgID == -1)
  231. {
  232. hr = ::LdapError2Hresult (ld->ld_errno);
  233. pSession->Disconnect ();
  234. return hr;
  235. }
  236. // construct a pending info
  237. PENDING_INFO PendingInfo;
  238. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
  239. PendingInfo.uLdapResType = LDAP_RES_DELETE;
  240. PendingInfo.uNotifyMsg = WM_ULS_UNREGISTER_USER;
  241. // queue it
  242. hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
  243. if (hr != S_OK)
  244. {
  245. ldap_abandon (ld, uMsgID);
  246. pSession->Disconnect ();
  247. MyAssert (FALSE);
  248. }
  249. *puRespID = PendingInfo.uRespID;
  250. return hr;
  251. }
  252. HRESULT UlsLdap_CLocalUser::
  253. SetStdAttrs ( ULONG *puRespID, LDAP_USERINFO *pInfo )
  254. {
  255. MyAssert (puRespID != NULL);
  256. MyAssert (pInfo != NULL);
  257. ULONG uMsgID_modify, uMsgID_modrdn;
  258. UlsLdap_CSession *pSession;
  259. LDAP *ld;
  260. HRESULT hr;
  261. // Get the session object
  262. //
  263. hr = g_pSessionContainer->GetSession (&pSession, GetServerInfo ());
  264. if (hr != S_OK)
  265. return hr;
  266. MyAssert (pSession != NULL);
  267. // Get the ldap session
  268. //
  269. ld = pSession->GetLd ();
  270. MyAssert (ld != NULL);
  271. // Change cn?
  272. //
  273. if (pInfo->uOffsetEMailName != 0)
  274. {
  275. // Cache user info such that cn is refreshed
  276. //
  277. hr = CacheUserInfo (pInfo);
  278. if (hr != S_OK)
  279. {
  280. pSession->Disconnect ();
  281. return hr;
  282. }
  283. // We have to use ldap_modrdn to modify cn and this must be
  284. // done before any other attribute changes
  285. //
  286. uMsgID_modrdn = ldap_modrdn2 (
  287. ld, GetDN (),
  288. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN],
  289. 1);
  290. if (uMsgID_modrdn == -1)
  291. {
  292. pSession->Disconnect ();
  293. hr = ::LdapError2Hresult (ld->ld_errno);
  294. return hr;
  295. }
  296. // Update DN
  297. //
  298. BuildDN ();
  299. }
  300. else
  301. {
  302. uMsgID_modrdn = INVALID_MSG_ID;
  303. }
  304. // Set standard attributes
  305. //
  306. hr = UlsLdap_CStdAttrs::SetStdAttrs ( NULL,
  307. &uMsgID_modify,
  308. 0,
  309. (VOID *) pInfo,
  310. GetServerInfo (),
  311. GetDN ());
  312. if (hr != S_OK)
  313. {
  314. if (uMsgID_modrdn != INVALID_MSG_ID)
  315. {
  316. ldap_abandon (ld, uMsgID_modrdn);
  317. pSession->Disconnect ();
  318. }
  319. return hr;
  320. }
  321. // Construct a pending info
  322. //
  323. PENDING_INFO PendingInfo;
  324. if (uMsgID_modrdn == INVALID_MSG_ID)
  325. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID_modify, INVALID_MSG_ID);
  326. else
  327. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID_modrdn, uMsgID_modify);
  328. PendingInfo.uLdapResType = LDAP_RES_MODIFY;
  329. PendingInfo.uNotifyMsg = WM_ULS_SET_USER_INFO;
  330. PendingInfo.hObject = (HANDLE) this; // for DN rollback
  331. // Queue it
  332. //
  333. hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
  334. if (hr != S_OK)
  335. {
  336. if (uMsgID_modrdn != INVALID_MSG_ID)
  337. {
  338. ldap_abandon (ld, uMsgID_modrdn);
  339. pSession->Disconnect ();
  340. }
  341. ldap_abandon (ld, uMsgID_modify);
  342. MyAssert (FALSE);
  343. }
  344. *puRespID = PendingInfo.uRespID;
  345. return hr;
  346. }
  347. VOID UlsLdap_CLocalUser::
  348. RollbackDN ( VOID )
  349. {
  350. if (m_pszOldDN != NULL)
  351. {
  352. MemFree (m_pszDN);
  353. m_pszDN = m_pszOldDN;
  354. m_pszOldDN = NULL;
  355. }
  356. }
  357. HRESULT UlsLdap_CLocalUser::
  358. UpdateIPAddress ( BOOL fPrimary )
  359. {
  360. // Update cached ip address
  361. //
  362. HRESULT hr = ::GetLocalIPAddress (&m_dwIPAddress);
  363. if (hr != S_OK)
  364. return hr;
  365. // Update the ip address string
  366. //
  367. ::GetLongString (m_dwIPAddress, &m_UserInfo.szIPAddress[0]);
  368. // Update ip address info on the server ONLY if primary
  369. //
  370. if (! fPrimary)
  371. return hr;
  372. // Update IP address on the server
  373. //
  374. return ::IlsUpdateIPAddress ( GetServerInfo (),
  375. GetDN (),
  376. (TCHAR *) c_apszUserStdAttrNames[ENUM_USERATTR_IP_ADDRESS],
  377. &m_UserInfo.szIPAddress[0],
  378. ISBU_MODOP_MODIFY_USER,
  379. GetPrefixCount (),
  380. GetPrefixString ());
  381. }
  382. /* ---------- protected methods ----------- */
  383. HRESULT UlsLdap_CLocalUser::
  384. SendRefreshMsg ( VOID )
  385. {
  386. if (m_pszRefreshFilter == NULL)
  387. return ULS_E_POINTER;
  388. // Get local ip address
  389. //
  390. DWORD dwIPAddress = 0;
  391. HRESULT hr = ::GetLocalIPAddress (&dwIPAddress);
  392. if (hr != S_OK)
  393. {
  394. MyDebugMsg ((ZONE_KA, "KA: cannot get my ip address\r\n"));
  395. return hr;
  396. }
  397. // If dwIPAddress is 0, then we are not on the network any more
  398. // start relogon process
  399. //
  400. if (dwIPAddress == 0)
  401. {
  402. MyDebugMsg ((ZONE_KA, "KA: my ip address is null\r\n"));
  403. // Indicate that I am not connected to the server anymore
  404. //
  405. SetRegLocally ();
  406. // Second, notify this app of the network being down
  407. //
  408. PostMessage (g_hWndHidden, WM_ULS_NETWORK_DOWN, TRUE, (LPARAM) this);
  409. // Report error
  410. //
  411. return ULS_E_NETWORK_DOWN;
  412. ;
  413. }
  414. else
  415. // If dwIPAddress and m_dwIPAddress, alert
  416. //
  417. if (dwIPAddress != m_dwIPAddress)
  418. {
  419. // Notify the com to start changing ip address
  420. // the actual change can happen later
  421. //
  422. PostMessage (g_hWndHidden, WM_ULS_IP_ADDRESS_CHANGED, TRUE, (LPARAM) this);
  423. }
  424. // get the connection object
  425. UlsLdap_CSession *pSession = NULL;
  426. hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  427. if (hr != S_OK)
  428. {
  429. MyDebugMsg ((ZONE_KA, "KA: network down, hr=0x%lX\r\n", hr));
  430. // Indicate that I am not connected to the server anymore
  431. //
  432. SetRegLocally ();
  433. // Second, notify the com of network down
  434. //
  435. PostMessage (g_hWndHidden, WM_ULS_NETWORK_DOWN, TRUE, (LPARAM) this);
  436. // Report error
  437. //
  438. return ULS_E_NETWORK_DOWN;
  439. }
  440. MyAssert (pSession != NULL);
  441. // get the ldap session
  442. LDAP *ld = pSession->GetLd ();
  443. MyAssert (ld != NULL);
  444. // Set attributes to return
  445. //
  446. TCHAR *apszAttrNames[3];
  447. apszAttrNames[0] = STR_CN;
  448. apszAttrNames[1] = (TCHAR *) c_apszUserStdAttrNames[ENUM_USERATTR_TTL];
  449. apszAttrNames[2] = NULL;
  450. // Update options in ld
  451. //
  452. ld->ld_sizelimit = 0; // no limit in the num of entries to return
  453. ld->ld_timelimit = 0; // no limit on the time to spend on the search
  454. ld->ld_deref = LDAP_DEREF_ALWAYS;
  455. // Send search query
  456. //
  457. MyDebugMsg ((ZONE_KA, "KA: calling ldap_search()...\r\n"));
  458. ULONG uMsgID = ::ldap_search (ld, (TCHAR *) &c_szDefUserBaseDN[0], // base DN
  459. LDAP_SCOPE_BASE, // scope
  460. m_pszRefreshFilter,
  461. &apszAttrNames[0], // attrs[]
  462. 0 // both type and value
  463. );
  464. if (uMsgID == -1)
  465. {
  466. MyDebugMsg ((ZONE_KA, "KA: ldap_search() failed\r\n"));
  467. hr = ::LdapError2Hresult (ld->ld_errno);
  468. pSession->Disconnect ();
  469. return hr;
  470. }
  471. // Let's wait for the result
  472. //
  473. LDAP_TIMEVAL TimeVal;
  474. TimeVal.tv_usec = 0;
  475. TimeVal.tv_sec = (m_ServerInfo.nTimeout != 0) ?
  476. m_ServerInfo.nTimeout :
  477. 90;
  478. LDAPMessage *pLdapMsg = NULL;
  479. INT ResultType = ::ldap_result (ld, uMsgID, 0, &TimeVal, &pLdapMsg);
  480. // Deal with timeout or error
  481. //
  482. if (ResultType != LDAP_RES_SEARCH_ENTRY &&
  483. ResultType != LDAP_RES_SEARCH_RESULT)
  484. {
  485. MyDebugMsg ((ZONE_KA, "KA: result type mismatches!\r\n"));
  486. hr = ULS_E_TIMEOUT;
  487. goto MyExit;
  488. }
  489. if (pLdapMsg != NULL)
  490. {
  491. switch (pLdapMsg->lm_returncode)
  492. {
  493. case LDAP_NO_SUCH_OBJECT:
  494. MyDebugMsg ((ZONE_KA, "KA: no such object!\r\n"));
  495. // Indicate that I am not connected to the server anymore
  496. //
  497. SetRegLocally ();
  498. // Second, notify this app to relogon
  499. //
  500. PostMessage (g_hWndHidden, WM_ULS_NEED_RELOGON, TRUE, (LPARAM) this);
  501. // Report error
  502. //
  503. hr = ULS_E_NEED_RELOGON;
  504. break;
  505. case LDAP_SUCCESS:
  506. // Get the new refresh period
  507. //
  508. hr = ::IlsParseRefreshPeriod (
  509. ld,
  510. pLdapMsg,
  511. c_apszUserStdAttrNames[ENUM_USERATTR_TTL],
  512. &m_uTTL);
  513. break;
  514. default:
  515. MyDebugMsg ((ZONE_KA, "KA: unknown lm_returncode=%ld\r\n", pLdapMsg->lm_returncode));
  516. MyAssert (FALSE);
  517. break;
  518. }
  519. }
  520. MyExit:
  521. // Free message
  522. //
  523. if (pLdapMsg != NULL)
  524. ldap_msgfree (pLdapMsg);
  525. // Free up the session
  526. //
  527. pSession->Disconnect ();
  528. return hr;
  529. }
  530. /* ---------- private methods ----------- */
  531. HRESULT UlsLdap_CLocalUser::
  532. CreateRegisterModArr ( LDAPMod ***pppMod )
  533. {
  534. if (pppMod == NULL)
  535. return ULS_E_POINTER;
  536. ULONG cAttrs = COUNT_ENUM_USERATTR;
  537. ULONG cbMod = ::IlsCalcModifyListSize (cAttrs);
  538. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  539. if (*pppMod == NULL)
  540. return ULS_E_MEMORY;
  541. LDAPMod *pMod;
  542. for (ULONG i = 0; i < cAttrs; i++)
  543. {
  544. pMod = ::IlsGetModifyListMod (pppMod, cAttrs, i);
  545. (*pppMod)[i] = pMod;
  546. pMod->mod_op = LDAP_MOD_ADD;
  547. FillModArrAttr (pMod, i);
  548. }
  549. // the following overwrote givenname attribute
  550. // ::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_ADD);
  551. (*pppMod)[cAttrs] = NULL;
  552. return S_OK;
  553. }
  554. HRESULT UlsLdap_CLocalUser::
  555. CreateSetStdAttrsModArr ( LDAPMod ***pppMod )
  556. {
  557. MyAssert (pppMod != NULL);
  558. DWORD dwFlags = m_UserInfo.dwFlags;
  559. HRESULT hr;
  560. ULONG cTotal = 0;
  561. hr = ::FillDefStdAttrsModArr ( pppMod,
  562. dwFlags,
  563. COUNT_ENUM_USERINFO,
  564. &cTotal,
  565. ISBU_MODOP_MODIFY_USER,
  566. GetPrefixCount (),
  567. GetPrefixString ());
  568. if (hr != S_OK)
  569. return hr;
  570. // Start indexing
  571. //
  572. ULONG i = GetPrefixCount ();
  573. // Fill in standard attributes
  574. //
  575. if (dwFlags & USEROBJ_F_FIRST_NAME)
  576. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_FIRST_NAME);
  577. if (dwFlags & USEROBJ_F_LAST_NAME)
  578. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_LAST_NAME);
  579. if (dwFlags & USEROBJ_F_EMAIL_NAME)
  580. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_EMAIL_NAME);
  581. if (dwFlags & USEROBJ_F_CITY_NAME)
  582. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_CITY_NAME);
  583. if (dwFlags & USEROBJ_F_COUNTRY_NAME)
  584. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_COUNTRY_NAME);
  585. if (dwFlags & USEROBJ_F_COMMENT)
  586. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_COMMENT);
  587. if (dwFlags & USEROBJ_F_IP_ADDRESS)
  588. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_IP_ADDRESS);
  589. if (dwFlags & USEROBJ_F_FLAGS)
  590. FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_FLAGS);
  591. MyAssert (i == cTotal);
  592. return S_OK;
  593. }
  594. VOID UlsLdap_CLocalUser::
  595. FillModArrAttr ( LDAPMod *pMod, LONG AttrIdx )
  596. {
  597. pMod->mod_type = (TCHAR *) c_apszUserStdAttrNames[AttrIdx];
  598. // single valued attr
  599. TCHAR **ppsz = (TCHAR **) (pMod + 1);
  600. pMod->mod_values = ppsz;
  601. *ppsz++ = (m_UserInfo.apszStdAttrValues[AttrIdx] != NULL) ?
  602. m_UserInfo.apszStdAttrValues[AttrIdx] :
  603. (TCHAR *) &c_szEmptyString[0];
  604. *ppsz = NULL;
  605. }
  606. HRESULT UlsLdap_CLocalUser::
  607. CacheInfo ( VOID *pInfo )
  608. {
  609. return CacheUserInfo ((LDAP_USERINFO *) pInfo);
  610. }
  611. HRESULT UlsLdap_CLocalUser::
  612. CacheUserInfo ( LDAP_USERINFO *pInfo )
  613. {
  614. ZeroMemory (&m_UserInfo, sizeof (m_UserInfo));
  615. TCHAR *pszName;
  616. if (pInfo->uOffsetName != INVALID_OFFSET)
  617. {
  618. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetName);
  619. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN] = pszName;
  620. // m_UserInfo.dwFlags |= USEROBJ_F_NAME;
  621. }
  622. if (pInfo->uOffsetFirstName != INVALID_OFFSET)
  623. {
  624. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetFirstName);
  625. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_FIRST_NAME] = pszName;
  626. m_UserInfo.dwFlags |= USEROBJ_F_FIRST_NAME;
  627. }
  628. if (pInfo->uOffsetLastName != INVALID_OFFSET)
  629. {
  630. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetLastName);
  631. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_LAST_NAME] = pszName;
  632. m_UserInfo.dwFlags |= USEROBJ_F_LAST_NAME;
  633. }
  634. if (pInfo->uOffsetEMailName != INVALID_OFFSET)
  635. {
  636. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetEMailName);
  637. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_EMAIL_NAME] = pszName;
  638. m_UserInfo.dwFlags |= USEROBJ_F_EMAIL_NAME;
  639. }
  640. if (pInfo->uOffsetCityName != INVALID_OFFSET)
  641. {
  642. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetCityName);
  643. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CITY_NAME] = pszName;
  644. m_UserInfo.dwFlags |= USEROBJ_F_CITY_NAME;
  645. }
  646. if (pInfo->uOffsetCountryName != INVALID_OFFSET)
  647. {
  648. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetCountryName);
  649. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_COUNTRY_NAME] = pszName;
  650. m_UserInfo.dwFlags |= USEROBJ_F_COUNTRY_NAME;
  651. }
  652. if (pInfo->uOffsetComment != INVALID_OFFSET)
  653. {
  654. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetComment);
  655. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_COMMENT] = pszName;
  656. m_UserInfo.dwFlags |= USEROBJ_F_COMMENT;
  657. }
  658. if (pInfo->uOffsetIPAddress != INVALID_OFFSET)
  659. {
  660. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetIPAddress);
  661. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_IP_ADDRESS] = pszName;
  662. m_UserInfo.dwFlags |= USEROBJ_F_IP_ADDRESS;
  663. }
  664. if (pInfo->dwFlags != INVALID_USER_FLAGS)
  665. {
  666. ::GetLongString (pInfo->dwFlags, &m_UserInfo.szFlags[0]);
  667. m_UserInfo.apszStdAttrValues[ENUM_USERATTR_FLAGS] = &m_UserInfo.szFlags[0];
  668. m_UserInfo.dwFlags |= USEROBJ_F_FLAGS;
  669. }
  670. return S_OK;
  671. }
  672. HRESULT UlsLdap_CLocalUser::
  673. BuildDN ( VOID )
  674. {
  675. MyAssert (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN] != NULL);
  676. TCHAR szDN[MAX_DN_LENGTH];
  677. szDN[0] = TEXT ('\0');
  678. TCHAR *pszDN = &szDN[0];
  679. if (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN] != NULL)
  680. {
  681. wsprintf (pszDN, TEXT ("%s=%s"),
  682. STR_CN, m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN]);
  683. pszDN += lstrlen (pszDN);
  684. }
  685. if (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_O] != NULL)
  686. {
  687. wsprintf (pszDN, TEXT (", %s=%s"),
  688. STR_O, m_UserInfo.apszStdAttrValues[ENUM_USERATTR_O]);
  689. pszDN += lstrlen (pszDN);
  690. }
  691. if (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_C] != NULL)
  692. {
  693. wsprintf (pszDN, TEXT (", %s=%s"),
  694. STR_C, m_UserInfo.apszStdAttrValues[ENUM_USERATTR_C]);
  695. pszDN += lstrlen (pszDN);
  696. }
  697. wsprintf (pszDN, TEXT (", %s"), &c_szDefUserBaseDN[0]);
  698. TCHAR *psz = My_strdup (&szDN[0]);
  699. if (psz == NULL)
  700. return ULS_E_MEMORY;
  701. MemFree (m_pszOldDN);
  702. m_pszOldDN = m_pszDN;
  703. m_pszDN = psz;
  704. return S_OK;
  705. }