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.

1333 lines
31 KiB

  1. /* ----------------------------------------------------------------------
  2. Module: ULS.DLL (Service Provider)
  3. File: spclient.cpp
  4. Content: This file contains the client 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_apszClientStdAttrNames[COUNT_ENUM_CLIENTATTR] =
  15. {
  16. /* -- the following is for user -- */
  17. TEXT ("cn"),
  18. TEXT ("givenname"),
  19. TEXT ("surname"),
  20. TEXT ("rfc822mailbox"),
  21. TEXT ("location"),
  22. TEXT ("comment"),
  23. TEXT ("sipaddress"),
  24. TEXT ("sflags"),
  25. TEXT ("c"),
  26. /* -- the following is for app -- */
  27. TEXT ("sappid"),
  28. TEXT ("smimetype"),
  29. TEXT ("sappguid"),
  30. TEXT ("sprotid"),
  31. TEXT ("sprotmimetype"),
  32. TEXT ("sport"),
  33. /* -- the above are resolvable -- */
  34. TEXT ("ssecurity"),
  35. TEXT ("sttl"),
  36. /* -- the above are changeable standard attributes for RTPerson -- */
  37. TEXT ("objectClass"),
  38. TEXT ("o"),
  39. };
  40. /* ---------- public methods ----------- */
  41. SP_CClient::
  42. SP_CClient ( DWORD_PTR dwContext )
  43. :
  44. m_cRefs (0), // Reference count
  45. m_uSignature (CLIENTOBJ_SIGNATURE), // Client object's signature
  46. m_pszDN (NULL), // Clean up DN
  47. m_pszAppPrefix (NULL), // Clean up app prefix
  48. m_pszRefreshFilter (NULL), // Clean up the refresh search filter
  49. m_fExternalIPAddress (FALSE), // Default is I figure out the ip address
  50. m_dwIPAddress (0), // Assume we are not connected to the network
  51. m_uTTL (ILS_DEF_REFRESH_MINUTE) // Reset refresh time
  52. {
  53. m_dwContext = dwContext;
  54. // Clean up attached server info structure
  55. //
  56. ::ZeroMemory (&m_ServerInfo, sizeof (m_ServerInfo));
  57. // Clean up the scratch buffer for caching pointers to attribute values
  58. //
  59. ::ZeroMemory (&m_ClientInfo, sizeof (m_ClientInfo));
  60. // Indicate this client is not registered yet
  61. //
  62. SetRegNone ();
  63. }
  64. SP_CClient::
  65. ~SP_CClient ( VOID )
  66. {
  67. // Invalidate the client object's signature
  68. //
  69. m_uSignature = (ULONG) -1;
  70. // Free server info structure
  71. //
  72. ::IlsFreeServerInfo (&m_ServerInfo);
  73. // Free DN and app prefix
  74. //
  75. MemFree (m_pszDN);
  76. MemFree (m_pszAppPrefix);
  77. // Free the refresh search filter
  78. //
  79. MemFree (m_pszRefreshFilter);
  80. // Release the previous prefix for extended attribute names
  81. //
  82. ::IlsReleaseAnyAttrsPrefix (&(m_ClientInfo.AnyAttrs));
  83. }
  84. ULONG SP_CClient::
  85. AddRef ( VOID )
  86. {
  87. ::InterlockedIncrement (&m_cRefs);
  88. return m_cRefs;
  89. }
  90. ULONG SP_CClient::
  91. Release ( VOID )
  92. {
  93. MyAssert (m_cRefs != 0);
  94. ::InterlockedDecrement (&m_cRefs);
  95. ULONG cRefs = m_cRefs;
  96. if (cRefs == 0)
  97. delete this;
  98. return cRefs;
  99. }
  100. HRESULT SP_CClient::
  101. Register (
  102. ULONG uRespID,
  103. SERVER_INFO *pServerInfo,
  104. LDAP_CLIENTINFO *pInfo )
  105. {
  106. MyAssert (pInfo != NULL);
  107. MyAssert (MyIsGoodString (pServerInfo->pszServerName));
  108. // Cache the server info
  109. //
  110. HRESULT hr = ::IlsCopyServerInfo (&m_ServerInfo, pServerInfo);
  111. if (hr != S_OK)
  112. return hr;
  113. // Cache client info
  114. //
  115. hr = CacheClientInfo (pInfo);
  116. if (hr != S_OK)
  117. return hr;
  118. // If the application sets an IP address,
  119. // then we will use what the app provides,
  120. // otherwise, we will get the IP address via winsock.
  121. //
  122. // CacheClientInfo() will set up the flag if ip address is passed in
  123. //
  124. if (IsExternalIPAddressPassedIn ())
  125. {
  126. // Use whatever passed in
  127. //
  128. m_fExternalIPAddress = TRUE;
  129. // Figure out the passed in ip address is done in CacheClientInfo()
  130. // The IP address string will be setup in CacheClientInfo() too.
  131. //
  132. }
  133. else
  134. {
  135. // I will figure out the ip address
  136. //
  137. m_fExternalIPAddress = FALSE;
  138. // Get IP address
  139. //
  140. hr = ::GetLocalIPAddress (&m_dwIPAddress);
  141. if (hr != S_OK)
  142. return hr;
  143. // Create IP address string
  144. //
  145. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_IP_ADDRESS] = &m_ClientInfo.szIPAddress[0];
  146. ::GetLongString (m_dwIPAddress, &m_ClientInfo.szIPAddress[0]);
  147. }
  148. // Create client signature string
  149. //
  150. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CLIENT_SIG] = &m_ClientInfo.szClientSig[0];
  151. ::GetLongString (g_dwClientSig, &m_ClientInfo.szClientSig[0]);
  152. // Create TTL string
  153. //
  154. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_TTL] = &m_ClientInfo.szTTL[0];
  155. ::GetLongString (m_uTTL + ILS_DEF_REFRESH_MARGIN_MINUTE, &m_ClientInfo.szTTL[0]);
  156. // Set object class RTPerson
  157. //
  158. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_OBJECT_CLASS] = (TCHAR *) &c_szRTPerson[0];
  159. // Ideally, o= should be read in from registiry
  160. // but for now, we simply hard code it
  161. //
  162. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_O] = (TCHAR *) &c_szDefO[0];
  163. // Build DN
  164. //
  165. m_pszDN = ::IlsBuildDN (m_ServerInfo.pszBaseDN,
  166. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_C],
  167. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_O],
  168. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CN],
  169. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_OBJECT_CLASS]);
  170. if (m_pszDN == NULL)
  171. return ILS_E_MEMORY;
  172. // Build refreh filter
  173. //
  174. m_pszRefreshFilter = ::ClntCreateRefreshFilter (m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CN]);
  175. if (m_pszRefreshFilter == NULL)
  176. return ILS_E_MEMORY;
  177. // Cache generic protocol info (per KevinMa's suggestion)
  178. //
  179. // m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_PROT_NAME] = TEXT ("h323");
  180. // m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_PROT_MIME] = TEXT ("text/h323");
  181. // m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_PROT_PORT] = TEXT ("1720");
  182. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_PROT_NAME] = STR_EMPTY;
  183. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_PROT_MIME] = STR_EMPTY;
  184. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_PROT_PORT] = STR_EMPTY;
  185. // Allocate app prefix here
  186. //
  187. ULONG cbPrefix = g_cbUserPrefix + sizeof (TCHAR) * (2 +
  188. ::lstrlen (STR_CLIENT_APP_NAME) +
  189. ::lstrlen (m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_NAME]));
  190. m_pszAppPrefix = (TCHAR *) MemAlloc (cbPrefix);
  191. if (m_pszAppPrefix == NULL)
  192. return ILS_E_MEMORY;
  193. // Fill user prefix
  194. //
  195. ::CopyMemory (m_pszAppPrefix, g_pszUserPrefix, g_cbUserPrefix);
  196. // Fill app prefix
  197. //
  198. TCHAR *psz = (TCHAR *) ((BYTE *) m_pszAppPrefix + g_cbUserPrefix);
  199. ::lstrcpy (psz, STR_CLIENT_APP_NAME);
  200. psz += lstrlen (psz) + 1;
  201. ::lstrcpy (psz, m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_NAME]);
  202. // Build modify array for ldap_add()
  203. //
  204. LDAPMod **ppModUser = NULL;
  205. hr = CreateRegUserModArr (&ppModUser);
  206. if (hr != S_OK)
  207. {
  208. return hr;
  209. }
  210. MyAssert (ppModUser != NULL);
  211. // Build modify array for ldap_modify()
  212. //
  213. LDAPMod **ppModApp = NULL;
  214. hr = CreateRegAppModArr (&ppModApp);
  215. if (hr != S_OK)
  216. {
  217. MemFree (ppModUser);
  218. return hr;
  219. }
  220. MyAssert (ppModApp != NULL);
  221. // so far, we are done with local preparation
  222. //
  223. // Get the session object
  224. //
  225. SP_CSession *pSession = NULL;
  226. LDAP *ld;
  227. ULONG uMsgIDUser = (ULONG) -1, uMsgIDApp = (ULONG) -1;
  228. hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  229. if (hr == S_OK)
  230. {
  231. MyAssert (pSession != NULL);
  232. // Get the ldap session
  233. //
  234. ld = pSession->GetLd ();
  235. MyAssert (ld != NULL);
  236. // Send the data over the wire
  237. //
  238. uMsgIDUser = ::ldap_add (ld, m_pszDN, ppModUser);
  239. if (uMsgIDUser != -1)
  240. {
  241. uMsgIDApp = ::ldap_modify (ld, m_pszDN, ppModApp);
  242. if (uMsgIDApp == -1)
  243. {
  244. hr = ::LdapError2Hresult (ld->ld_errno);
  245. }
  246. }
  247. else
  248. {
  249. hr = ::LdapError2Hresult (ld->ld_errno);
  250. }
  251. }
  252. // Free modify arrays
  253. //
  254. MemFree (ppModUser);
  255. MemFree (ppModApp);
  256. // Report failure if so
  257. //
  258. if (hr != S_OK)
  259. goto MyExit;
  260. // Construct a pending info
  261. //
  262. RESP_INFO ri;
  263. ::FillDefRespInfo (&ri, uRespID, ld, uMsgIDUser, uMsgIDApp);
  264. ri.uNotifyMsg = WM_ILS_REGISTER_CLIENT;
  265. ri.hObject = (HANDLE) this;
  266. // Queue the pending result
  267. //
  268. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  269. if (hr != S_OK)
  270. {
  271. MyAssert (FALSE);
  272. goto MyExit;
  273. }
  274. MyExit:
  275. if (hr != S_OK)
  276. {
  277. if (uMsgIDUser != (ULONG) -1)
  278. ::ldap_abandon (ld, uMsgIDUser);
  279. if (uMsgIDApp != (ULONG) -1)
  280. ::ldap_abandon (ld, uMsgIDApp);
  281. if (pSession != NULL)
  282. pSession->Disconnect ();
  283. }
  284. return hr;
  285. }
  286. HRESULT SP_CClient::
  287. UnRegister ( ULONG uRespID )
  288. {
  289. MyAssert (MyIsGoodString (m_pszDN));
  290. // Make sure that there is not refresh scheduled for this object
  291. //
  292. if (g_pRefreshScheduler != NULL)
  293. {
  294. g_pRefreshScheduler->RemoveClientObject (this);
  295. }
  296. else
  297. {
  298. MyAssert (FALSE);
  299. }
  300. // If it is not registered on the server,
  301. // the simply report success
  302. //
  303. if (! IsRegRemotely ())
  304. {
  305. SetRegNone ();
  306. ::PostMessage (g_hWndNotify, WM_ILS_UNREGISTER_CLIENT, uRespID, S_OK);
  307. return S_OK;
  308. }
  309. // Indicate that we are not registered at all
  310. //
  311. SetRegNone ();
  312. // Get the session object
  313. //
  314. SP_CSession *pSession = NULL;
  315. LDAP *ld;
  316. ULONG uMsgID = (ULONG) -1;
  317. HRESULT hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  318. if (hr == S_OK)
  319. {
  320. // Get the ldap session
  321. //
  322. MyAssert (pSession != NULL);
  323. ld = pSession->GetLd ();
  324. MyAssert (ld != NULL);
  325. // Send the data over the wire
  326. //
  327. MyAssert (MyIsGoodString (m_pszDN));
  328. uMsgID = ::ldap_delete (ld, m_pszDN);
  329. if (uMsgID == -1)
  330. {
  331. hr = ::LdapError2Hresult (ld->ld_errno);
  332. }
  333. }
  334. // Report failure if so
  335. //
  336. if (hr != S_OK)
  337. goto MyExit;
  338. // Construct a pending info
  339. //
  340. RESP_INFO ri;
  341. ::FillDefRespInfo (&ri, uRespID, ld, uMsgID, INVALID_MSG_ID);
  342. ri.uNotifyMsg = WM_ILS_UNREGISTER_CLIENT;
  343. // Queue this pending result
  344. //
  345. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  346. if (hr != S_OK)
  347. {
  348. MyAssert (FALSE);
  349. goto MyExit;
  350. }
  351. MyExit:
  352. if (hr != S_OK)
  353. {
  354. if (uMsgID != (ULONG) -1)
  355. ::ldap_abandon (ld, uMsgID);
  356. if (pSession != NULL)
  357. pSession->Disconnect ();
  358. }
  359. return hr;
  360. }
  361. HRESULT SP_CClient::
  362. SetAttributes (
  363. ULONG uRespID,
  364. LDAP_CLIENTINFO *pInfo )
  365. {
  366. MyAssert (pInfo != NULL);
  367. MyAssert (MyIsGoodString (m_pszDN));
  368. // cache info
  369. //
  370. HRESULT hr = CacheClientInfo (pInfo);
  371. if (hr != S_OK)
  372. return hr;
  373. // Build modify array for user object's ldap_modify()
  374. //
  375. LDAPMod **ppModUser = NULL;
  376. hr = CreateSetUserAttrsModArr (&ppModUser);
  377. if (hr != S_OK)
  378. return hr;
  379. MyAssert (ppModUser != NULL);
  380. // Build modify array for app object's ldap_modify()
  381. //
  382. LDAPMod **ppModApp = NULL;
  383. hr = CreateSetAppAttrsModArr (&ppModApp);
  384. if (hr != S_OK)
  385. {
  386. MemFree (ppModUser);
  387. return hr;
  388. }
  389. MyAssert (ppModApp != NULL);
  390. // So far, we are done with local preparation
  391. //
  392. // Get the session object
  393. //
  394. SP_CSession *pSession = NULL;
  395. LDAP *ld;
  396. ULONG uMsgIDUser = (ULONG) -1, uMsgIDApp = (ULONG) -1;
  397. hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  398. if (hr == S_OK)
  399. {
  400. MyAssert (pSession != NULL);
  401. // Get the ldap session
  402. //
  403. ld = pSession->GetLd ();
  404. MyAssert (ld != NULL);
  405. // Send the data over the wire
  406. //
  407. uMsgIDUser = ::ldap_modify (ld, m_pszDN, ppModUser);
  408. if (uMsgIDUser != -1)
  409. {
  410. uMsgIDApp = ::ldap_modify (ld, m_pszDN, ppModApp);
  411. if (uMsgIDApp == -1)
  412. {
  413. hr = ::LdapError2Hresult (ld->ld_errno);
  414. }
  415. }
  416. else
  417. {
  418. hr = ::LdapError2Hresult (ld->ld_errno);
  419. }
  420. }
  421. // Free modify arrays
  422. //
  423. MemFree (ppModUser);
  424. MemFree (ppModApp);
  425. // Report failure if so
  426. //
  427. if (hr != S_OK)
  428. goto MyExit;
  429. // Initialize pending info
  430. //
  431. RESP_INFO ri;
  432. ::FillDefRespInfo (&ri, uRespID, ld, uMsgIDUser, uMsgIDApp);
  433. ri.uNotifyMsg = WM_ILS_SET_CLIENT_INFO;
  434. // Queue the pending result
  435. //
  436. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  437. if (hr != S_OK)
  438. {
  439. MyAssert (FALSE);
  440. goto MyExit;
  441. }
  442. MyExit:
  443. if (hr != S_OK)
  444. {
  445. if (uMsgIDUser != (ULONG) -1)
  446. ::ldap_abandon (ld, uMsgIDUser);
  447. if (uMsgIDApp != (ULONG) -1)
  448. ::ldap_abandon (ld, uMsgIDApp);
  449. if (pSession != NULL)
  450. pSession->Disconnect ();
  451. }
  452. else
  453. {
  454. // If the user customizes the ip address
  455. // we need to remember this
  456. //
  457. m_fExternalIPAddress |= IsExternalIPAddressPassedIn ();
  458. }
  459. return hr;
  460. }
  461. HRESULT SP_CClient::
  462. AddProtocol ( ULONG uNotifyMsg, ULONG uRespID, SP_CProtocol *pProt )
  463. {
  464. HRESULT hr = m_Protocols.Append ((VOID *) pProt);
  465. if (hr == S_OK)
  466. {
  467. hr = UpdateProtocols (uNotifyMsg, uRespID, pProt);
  468. }
  469. return hr;
  470. }
  471. HRESULT SP_CClient::
  472. RemoveProtocol ( ULONG uNotifyMsg, ULONG uRespID, SP_CProtocol *pProt )
  473. {
  474. HRESULT hr = m_Protocols.Remove ((VOID *) pProt);
  475. if (hr == S_OK)
  476. {
  477. hr = UpdateProtocols (uNotifyMsg, uRespID, pProt);
  478. }
  479. else
  480. {
  481. hr = ILS_E_NOT_REGISTERED;
  482. }
  483. return hr;
  484. }
  485. HRESULT SP_CClient::
  486. UpdateProtocols ( ULONG uNotifyMsg, ULONG uRespID, SP_CProtocol *pProt )
  487. {
  488. MyAssert ( uNotifyMsg == WM_ILS_REGISTER_PROTOCOL ||
  489. uNotifyMsg == WM_ILS_UNREGISTER_PROTOCOL ||
  490. uNotifyMsg == WM_ILS_SET_PROTOCOL_INFO);
  491. MyAssert (MyIsGoodString (m_pszDN));
  492. HRESULT hr = S_OK;
  493. // Build modify array for protocol object's ldap_modify()
  494. //
  495. LDAPMod **ppModProt = NULL;
  496. hr = CreateSetProtModArr (&ppModProt);
  497. if (hr != S_OK)
  498. return hr;
  499. MyAssert (ppModProt != NULL);
  500. // So far, we are done with local preparation
  501. //
  502. // Get the session object
  503. //
  504. SP_CSession *pSession = NULL;
  505. LDAP *ld;
  506. ULONG uMsgIDProt = (ULONG) -1;
  507. hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  508. if (hr == S_OK)
  509. {
  510. MyAssert (pSession != NULL);
  511. // Get the ldap session
  512. //
  513. ld = pSession->GetLd ();
  514. MyAssert (ld != NULL);
  515. // Send the data over the wire
  516. //
  517. uMsgIDProt = ::ldap_modify (ld, m_pszDN, ppModProt);
  518. if (uMsgIDProt == -1)
  519. {
  520. hr = ::LdapError2Hresult (ld->ld_errno);
  521. }
  522. }
  523. // Free modify arrays
  524. //
  525. MemFree (ppModProt);
  526. // Report failure if so
  527. //
  528. if (hr != S_OK)
  529. goto MyExit;
  530. // Initialize pending info
  531. //
  532. RESP_INFO ri;
  533. ::FillDefRespInfo (&ri, uRespID, ld, uMsgIDProt, INVALID_MSG_ID);
  534. ri.uNotifyMsg = uNotifyMsg;
  535. ri.hObject = (HANDLE) pProt;
  536. // Queue the pending result
  537. //
  538. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  539. if (hr != S_OK)
  540. {
  541. MyAssert (FALSE);
  542. goto MyExit;
  543. }
  544. MyExit:
  545. if (hr != S_OK)
  546. {
  547. if (uMsgIDProt != (ULONG) -1)
  548. ::ldap_abandon (ld, uMsgIDProt);
  549. if (pSession != NULL)
  550. pSession->Disconnect ();
  551. }
  552. return hr;
  553. }
  554. HRESULT SP_CClient::
  555. UpdateIPAddress ( VOID )
  556. {
  557. MyAssert (MyIsGoodString (m_pszDN));
  558. // Update cached ip address
  559. //
  560. HRESULT hr = ::GetLocalIPAddress (&m_dwIPAddress);
  561. if (hr != S_OK)
  562. return hr;
  563. // Update the ip address string
  564. //
  565. ::GetLongString (m_dwIPAddress, &m_ClientInfo.szIPAddress[0]);
  566. // Update IP address on the server
  567. //
  568. return ::IlsUpdateIPAddress ( &m_ServerInfo,
  569. m_pszDN,
  570. STR_CLIENT_IP_ADDR,
  571. &m_ClientInfo.szIPAddress[0],
  572. ISBU_MODOP_MODIFY_USER,
  573. 1,
  574. g_pszUserPrefix);
  575. }
  576. /* ---------- protected methods ----------- */
  577. HRESULT SP_CClient::
  578. SendRefreshMsg ( VOID )
  579. {
  580. MyAssert (m_pszRefreshFilter != NULL);
  581. HRESULT hr;
  582. // Send a refresh message to the server and parse the new TTL value
  583. //
  584. hr = ::IlsSendRefreshMsg ( &m_ServerInfo,
  585. STR_DEF_CLIENT_BASE_DN,
  586. STR_CLIENT_TTL,
  587. m_pszRefreshFilter,
  588. &m_uTTL);
  589. if (hr == ILS_E_NEED_RELOGON)
  590. {
  591. SetRegLocally ();
  592. ::PostMessage (g_hWndNotify, WM_ILS_CLIENT_NEED_RELOGON,
  593. (WPARAM) this, (LPARAM) m_dwContext);
  594. }
  595. else
  596. if (hr == ILS_E_NETWORK_DOWN)
  597. {
  598. SetRegLocally ();
  599. ::PostMessage (g_hWndNotify, WM_ILS_CLIENT_NETWORK_DOWN,
  600. (WPARAM) this, (LPARAM) m_dwContext);
  601. }
  602. // If the ip address is not provided by the app, then
  603. // we need to make sure that the current ip address is equal to
  604. // the one we used to register the user.
  605. //
  606. if (! m_fExternalIPAddress && hr == S_OK)
  607. {
  608. // Get local ip address
  609. //
  610. DWORD dwIPAddress = 0;
  611. if (::GetLocalIPAddress (&dwIPAddress) == S_OK)
  612. {
  613. // Now, the network appears to be up and running.
  614. // Update the ip address if they are different.
  615. //
  616. if (dwIPAddress != 0 && dwIPAddress != m_dwIPAddress)
  617. UpdateIPAddress ();
  618. }
  619. }
  620. return hr;
  621. }
  622. /* ---------- private methods ----------- */
  623. HRESULT SP_CClient::
  624. CreateRegUserModArr ( LDAPMod ***pppMod )
  625. {
  626. MyAssert (pppMod != NULL);
  627. // Calculate the modify array size
  628. //
  629. #ifdef ANY_IN_USER
  630. ULONG cStdAttrs = COUNT_ENUM_REG_USER;
  631. ULONG cAnyAttrs = m_ClientInfo.AnyAttrs.cAttrsToAdd;
  632. ULONG cTotal = cStdAttrs + cAnyAttrs;
  633. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  634. #else
  635. ULONG cStdAttrs = COUNT_ENUM_REG_USER;
  636. ULONG cTotal = cStdAttrs;
  637. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  638. #endif
  639. // Allocate the modify array
  640. //
  641. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  642. if (*pppMod == NULL)
  643. return ILS_E_MEMORY;
  644. // Lay out the modify array
  645. //
  646. LDAPMod **apMod = *pppMod;
  647. LDAPMod *pMod;
  648. ULONG i, nIndex;
  649. #ifdef ANY_IN_USER
  650. TCHAR *pszName2, *pszValue;
  651. pszName2 = m_ClientInfo.AnyAttrs.pszAttrsToAdd;
  652. #endif
  653. for (i = 0; i < cTotal; i++)
  654. {
  655. // Locate modify element
  656. //
  657. pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
  658. pMod->mod_op = LDAP_MOD_ADD;
  659. apMod[i] = pMod;
  660. #ifdef ANY_IN_USER
  661. if (i < cStdAttrs)
  662. {
  663. // Get attribute name and value
  664. //
  665. if (IsOverAppAttrLine (i))
  666. {
  667. nIndex = i + COUNT_ENUM_SKIP_APP_ATTRS;
  668. }
  669. else
  670. {
  671. nIndex = i;
  672. }
  673. // Put standard attributes
  674. //
  675. FillModArrAttr (pMod, nIndex);
  676. }
  677. else
  678. {
  679. // Put extended attributes
  680. //
  681. pszValue = pszName2 + lstrlen (pszName2) + 1;
  682. ::IlsFillModifyListItem (pMod, pszName2, pszValue);
  683. pszName2 = pszValue + lstrlen (pszValue) + 1;
  684. }
  685. #else
  686. // Get attribute name and value
  687. //
  688. if (IsOverAppAttrLine (i))
  689. {
  690. nIndex = i + COUNT_ENUM_SKIP_APP_ATTRS;
  691. }
  692. else
  693. {
  694. nIndex = i;
  695. }
  696. // Fill in modify element
  697. //
  698. FillModArrAttr (pMod, nIndex);
  699. #endif
  700. }
  701. apMod[cTotal] = NULL;
  702. return S_OK;
  703. }
  704. HRESULT SP_CClient::
  705. CreateRegAppModArr ( LDAPMod ***pppMod )
  706. {
  707. MyAssert (pppMod != NULL);
  708. // Calculate the modify array size
  709. //
  710. ULONG cPrefix = 1; // Skip its own app id
  711. ULONG cStdAttrs = COUNT_ENUM_REG_APP;
  712. #ifdef ANY_IN_USER
  713. ULONG cTotal = cPrefix + cStdAttrs;
  714. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  715. #else
  716. ULONG cAnyAttrs = m_ClientInfo.AnyAttrs.cAttrsToAdd;
  717. ULONG cTotal = cPrefix + cStdAttrs + cAnyAttrs;
  718. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  719. #endif
  720. // Allocate the modify array
  721. //
  722. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  723. if (*pppMod == NULL)
  724. return ILS_E_MEMORY;
  725. // Lay out the modify array
  726. //
  727. LDAPMod **apMod = *pppMod;
  728. LDAPMod *pMod;
  729. #ifdef ANY_IN_USER
  730. TCHAR *pszName1, *pszValue;
  731. pszName1 = m_pszAppPrefix;;
  732. #else
  733. TCHAR *pszName1, *pszName2, *pszValue;
  734. pszName1 = m_pszAppPrefix;;
  735. pszName2 = m_ClientInfo.AnyAttrs.pszAttrsToAdd;
  736. #endif
  737. for (ULONG i = 0; i < cTotal; i++)
  738. {
  739. // Locate modify element
  740. //
  741. pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
  742. pMod->mod_op = LDAP_MOD_ADD;
  743. apMod[i] = pMod;
  744. if (i < cPrefix)
  745. {
  746. // Put the prefix
  747. //
  748. pMod->mod_op = LDAP_MOD_REPLACE;
  749. pszValue = pszName1 + lstrlen (pszName1) + 1;
  750. ::IlsFillModifyListItem (pMod, pszName1, pszValue);
  751. pszName1 = pszValue + lstrlen (pszValue) + 1;
  752. }
  753. else
  754. #ifdef ANY_IN_USER
  755. {
  756. // Put standard attributes
  757. //
  758. FillModArrAttr (pMod, i - cPrefix + ENUM_CLIENTATTR_APP_NAME);
  759. }
  760. #else
  761. if (i < cPrefix + cStdAttrs)
  762. {
  763. // Put standard attributes
  764. //
  765. FillModArrAttr (pMod, i - cPrefix + ENUM_CLIENTATTR_APP_NAME);
  766. }
  767. else
  768. {
  769. // Put extended attributes
  770. //
  771. pszValue = pszName2 + lstrlen (pszName2) + 1;
  772. ::IlsFillModifyListItem (pMod, pszName2, pszValue);
  773. pszName2 = pszValue + lstrlen (pszValue) + 1;
  774. }
  775. #endif
  776. }
  777. ::IlsFixUpModOp (apMod[0], LDAP_MOD_ADD, ISBU_MODOP_ADD_APP);
  778. apMod[cTotal] = NULL;
  779. return S_OK;
  780. }
  781. HRESULT SP_CClient::
  782. CreateSetUserAttrsModArr ( LDAPMod ***pppMod )
  783. {
  784. MyAssert (pppMod != NULL);
  785. HRESULT hr;
  786. DWORD dwFlags = m_ClientInfo.dwFlags & CLIENTOBJ_F_USER_MASK;
  787. #ifdef ANY_IN_USER
  788. ULONG cTotal = m_ClientInfo.AnyAttrs.cAttrsToAdd +
  789. m_ClientInfo.AnyAttrs.cAttrsToModify +
  790. m_ClientInfo.AnyAttrs.cAttrsToRemove;
  791. #else
  792. ULONG cTotal = 0; // must be initialized to zero
  793. #endif
  794. // Lay out the modify array for modifying user standard attributes
  795. //
  796. hr = ::IlsFillDefStdAttrsModArr (pppMod,
  797. dwFlags,
  798. COUNT_ENUM_SET_USER_INFO,
  799. &cTotal,
  800. ISBU_MODOP_MODIFY_USER,
  801. 1,
  802. g_pszUserPrefix);
  803. if (hr != S_OK)
  804. return hr;
  805. // Start to fill standard attributes
  806. //
  807. ULONG i = 1;
  808. LDAPMod **apMod = *pppMod;
  809. if (dwFlags & CLIENTOBJ_F_EMAIL_NAME)
  810. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_EMAIL_NAME);
  811. if (dwFlags & CLIENTOBJ_F_FIRST_NAME)
  812. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_FIRST_NAME);
  813. if (dwFlags & CLIENTOBJ_F_LAST_NAME)
  814. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_LAST_NAME);
  815. if (dwFlags & CLIENTOBJ_F_CITY_NAME)
  816. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_CITY_NAME);
  817. if (dwFlags & CLIENTOBJ_F_C)
  818. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_C);
  819. if (dwFlags & CLIENTOBJ_F_COMMENT)
  820. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_COMMENT);
  821. if (dwFlags & CLIENTOBJ_F_IP_ADDRESS)
  822. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_IP_ADDRESS);
  823. if (dwFlags & CLIENTOBJ_F_FLAGS)
  824. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_FLAGS);
  825. #ifdef ANY_IN_USER
  826. // Start to fill extended attributes
  827. //
  828. ::IlsFillModifyListForAnyAttrs (apMod, &i, &m_ClientInfo.AnyAttrs);
  829. #else
  830. #endif
  831. MyAssert (i == cTotal);
  832. return S_OK;
  833. }
  834. HRESULT SP_CClient::
  835. CreateSetAppAttrsModArr ( LDAPMod ***pppMod )
  836. {
  837. MyAssert (pppMod != NULL);
  838. HRESULT hr;
  839. DWORD dwFlags = m_ClientInfo.dwFlags & CLIENTOBJ_F_APP_MASK;
  840. #ifdef ANY_IN_USER
  841. ULONG cTotal = 0; // must be initialized to zero
  842. #else
  843. ULONG cTotal = m_ClientInfo.AnyAttrs.cAttrsToAdd +
  844. m_ClientInfo.AnyAttrs.cAttrsToModify +
  845. m_ClientInfo.AnyAttrs.cAttrsToRemove;
  846. #endif
  847. // Lay out the modify array for modifying app standard/extended attributes
  848. //
  849. hr = ::IlsFillDefStdAttrsModArr (pppMod,
  850. dwFlags,
  851. COUNT_ENUM_SET_APP_INFO,
  852. &cTotal,
  853. ISBU_MODOP_MODIFY_APP,
  854. 2,
  855. m_pszAppPrefix);
  856. if (hr != S_OK)
  857. return hr;
  858. // Start to fill standard attributes
  859. //
  860. ULONG i = 2;
  861. LDAPMod **apMod = *pppMod;
  862. if (m_ClientInfo.dwFlags & CLIENTOBJ_F_APP_GUID)
  863. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_APP_GUID);
  864. if (m_ClientInfo.dwFlags & CLIENTOBJ_F_APP_NAME)
  865. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_APP_NAME);
  866. if (m_ClientInfo.dwFlags & CLIENTOBJ_F_APP_MIME_TYPE)
  867. FillModArrAttr (apMod[i++], ENUM_CLIENTATTR_APP_MIME_TYPE);
  868. #ifdef ANY_IN_USER
  869. #else
  870. // Start to fill extended attributes
  871. //
  872. ::IlsFillModifyListForAnyAttrs (apMod, &i, &m_ClientInfo.AnyAttrs);
  873. #endif
  874. MyAssert (i == cTotal);
  875. return S_OK;
  876. }
  877. HRESULT SP_CClient::
  878. CreateSetProtModArr ( LDAPMod ***pppMod )
  879. // We need to delete the attributes and then add the entire array back.
  880. // This is due to the ILS server limitation. We agreed to live with that.
  881. //
  882. {
  883. MyAssert (pppMod != NULL);
  884. ULONG cPrefix = 2;
  885. TCHAR *pszPrefix = m_pszAppPrefix;
  886. ULONG cStdAttrs = COUNT_ENUM_PROTATTR;
  887. ULONG cTotal = cPrefix + cStdAttrs + cStdAttrs;
  888. ULONG cProts = 0;
  889. // Find out how many protocols
  890. //
  891. HANDLE hEnum = NULL;
  892. SP_CProtocol *pProt;
  893. m_Protocols.Enumerate (&hEnum);
  894. while (m_Protocols.Next (&hEnum, (VOID **) &pProt) == NOERROR)
  895. cProts++;
  896. // Calculate the modify array's total size
  897. //
  898. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  899. // Add up for multi-valued attribute
  900. //
  901. if (cProts > 0)
  902. {
  903. cbMod += cStdAttrs * (cProts - 1) * sizeof (TCHAR *);
  904. }
  905. // Allocate the modify array
  906. //
  907. LDAPMod **apMod = *pppMod = (LDAPMod **) MemAlloc (cbMod);
  908. if (apMod == NULL)
  909. return ILS_E_MEMORY;
  910. // Fill in the modify list
  911. //
  912. LDAPMod *pMod;
  913. BYTE *pbData = (BYTE *) apMod + (cTotal + 1) * sizeof (LDAPMod *);
  914. ULONG uDispPrefix = sizeof (LDAPMod) + 2 * sizeof (TCHAR *);
  915. ULONG uDispStdAttrs = sizeof (LDAPMod) + (cProts + 1) * sizeof (TCHAR *);
  916. for (ULONG uOffset = 0, i = 0; i < cTotal; i++)
  917. {
  918. // Locate the modify structure
  919. //
  920. pMod = (LDAPMod *) (pbData + uOffset);
  921. apMod[i] = pMod;
  922. pMod->mod_values = (TCHAR **) (pMod + 1);
  923. // Fill in the modify structure
  924. //
  925. if (i < cPrefix)
  926. {
  927. pMod->mod_op = LDAP_MOD_REPLACE;
  928. pMod->mod_type = pszPrefix;
  929. pszPrefix += lstrlen (pszPrefix) + 1;
  930. *(pMod->mod_values) = pszPrefix;
  931. pszPrefix += lstrlen (pszPrefix) + 1;
  932. }
  933. else
  934. if (i < cPrefix + cStdAttrs)
  935. {
  936. // Work around the ISBU server implementation!!!
  937. // We agreed that we can live with the server implementation.
  938. //
  939. pMod->mod_op = LDAP_MOD_DELETE;
  940. ULONG nIndex = i - cPrefix;
  941. // Fill in attribute name
  942. //
  943. pMod->mod_type = (TCHAR *) c_apszProtStdAttrNames[nIndex];
  944. }
  945. else
  946. {
  947. pMod->mod_op = LDAP_MOD_ADD;
  948. ULONG nIndex = i - cPrefix - cStdAttrs;
  949. // Fill in attribute name
  950. //
  951. pMod->mod_type = (TCHAR *) c_apszProtStdAttrNames[nIndex];
  952. // Fill in multi-valued modify array
  953. //
  954. if (cProts > 0)
  955. {
  956. ULONG j = 0; // must initialized to zero
  957. TCHAR *pszVal;
  958. m_Protocols.Enumerate (&hEnum);
  959. MyAssert (hEnum != NULL);
  960. while (m_Protocols.Next (&hEnum, (VOID **) &pProt) == NOERROR)
  961. {
  962. MyAssert (pProt != NULL);
  963. pszVal = (pProt->GetProtInfo ())->apszStdAttrValues[nIndex];
  964. (pMod->mod_values)[j++] = (pszVal != NULL) ? pszVal : STR_EMPTY;
  965. }
  966. }
  967. else
  968. {
  969. (pMod->mod_values)[0] = STR_EMPTY;
  970. }
  971. }
  972. // Calculate the modify structure's offset relative to the array's end
  973. //
  974. uOffset += (i < cPrefix + cStdAttrs) ? uDispPrefix : uDispStdAttrs;
  975. }
  976. // Fix up the first and the last ones
  977. //
  978. IlsFixUpModOp (apMod[0], LDAP_MOD_REPLACE, ISBU_MODOP_MODIFY_APP);
  979. apMod[cTotal] = NULL;
  980. return S_OK;
  981. }
  982. VOID SP_CClient::
  983. FillModArrAttr ( LDAPMod *pMod, INT nIndex )
  984. {
  985. MyAssert (pMod != NULL);
  986. MyAssert (0 <= nIndex && nIndex <= COUNT_ENUM_CLIENTATTR);
  987. ::IlsFillModifyListItem ( pMod,
  988. (TCHAR *) c_apszClientStdAttrNames[nIndex],
  989. m_ClientInfo.apszStdAttrValues[nIndex]);
  990. }
  991. HRESULT SP_CClient::
  992. CacheClientInfo ( LDAP_CLIENTINFO *pInfo )
  993. {
  994. MyAssert (pInfo != NULL);
  995. // Release the previous prefix for extended attribute names
  996. //
  997. ::IlsReleaseAnyAttrsPrefix (&(m_ClientInfo.AnyAttrs));
  998. // Clean up the buffer
  999. //
  1000. ZeroMemory (&m_ClientInfo, sizeof (m_ClientInfo));
  1001. // Start to cache user standard attributes
  1002. //
  1003. if (pInfo->uOffsetCN != INVALID_OFFSET)
  1004. {
  1005. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CN] =
  1006. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetCN);
  1007. // We do not want to change CN thru ldap_modify()
  1008. // m_ClientInfo.dwFlags |= CLIENTOBJ_F_CN;
  1009. }
  1010. if (pInfo->uOffsetFirstName != INVALID_OFFSET)
  1011. {
  1012. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_FIRST_NAME] =
  1013. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetFirstName);
  1014. m_ClientInfo.dwFlags |= CLIENTOBJ_F_FIRST_NAME;
  1015. }
  1016. if (pInfo->uOffsetLastName != INVALID_OFFSET)
  1017. {
  1018. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_LAST_NAME] =
  1019. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetLastName);
  1020. m_ClientInfo.dwFlags |= CLIENTOBJ_F_LAST_NAME;
  1021. }
  1022. if (pInfo->uOffsetEMailName != INVALID_OFFSET)
  1023. {
  1024. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_EMAIL_NAME] =
  1025. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetEMailName);
  1026. m_ClientInfo.dwFlags |= CLIENTOBJ_F_EMAIL_NAME;
  1027. }
  1028. if (pInfo->uOffsetCityName != INVALID_OFFSET)
  1029. {
  1030. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CITY_NAME] =
  1031. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetCityName);
  1032. m_ClientInfo.dwFlags |= CLIENTOBJ_F_CITY_NAME;
  1033. }
  1034. if (pInfo->uOffsetCountryName != INVALID_OFFSET)
  1035. {
  1036. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_C] =
  1037. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetCountryName);
  1038. m_ClientInfo.dwFlags |= CLIENTOBJ_F_C;
  1039. }
  1040. if (pInfo->uOffsetComment != INVALID_OFFSET)
  1041. {
  1042. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_COMMENT] =
  1043. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetComment);
  1044. m_ClientInfo.dwFlags |= CLIENTOBJ_F_COMMENT;
  1045. }
  1046. if (pInfo->uOffsetIPAddress != INVALID_OFFSET)
  1047. {
  1048. DWORD dwIPAddr = ::inet_addr ((TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetIPAddress));
  1049. if (dwIPAddr != INADDR_NONE)
  1050. {
  1051. m_dwIPAddress = dwIPAddr;
  1052. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_IP_ADDRESS] = &m_ClientInfo.szIPAddress[0];
  1053. ::GetLongString (m_dwIPAddress, &m_ClientInfo.szIPAddress[0]);
  1054. m_ClientInfo.dwFlags |= CLIENTOBJ_F_IP_ADDRESS;
  1055. }
  1056. }
  1057. if (pInfo->dwFlags != INVALID_USER_FLAGS)
  1058. {
  1059. ::GetLongString (pInfo->dwFlags, &m_ClientInfo.szFlags[0]);
  1060. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_FLAGS] = &m_ClientInfo.szFlags[0];
  1061. m_ClientInfo.dwFlags |= CLIENTOBJ_F_FLAGS;
  1062. }
  1063. // Start to cache app standard attributes
  1064. //
  1065. if (pInfo->uOffsetAppName != INVALID_OFFSET)
  1066. {
  1067. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_NAME] =
  1068. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAppName);
  1069. m_ClientInfo.dwFlags |= CLIENTOBJ_F_APP_NAME;
  1070. }
  1071. if (pInfo->uOffsetAppMimeType != INVALID_OFFSET)
  1072. {
  1073. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_MIME_TYPE] =
  1074. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAppMimeType);
  1075. m_ClientInfo.dwFlags |= CLIENTOBJ_F_APP_MIME_TYPE;
  1076. }
  1077. if (::IsValidGuid (&(pInfo->AppGuid)))
  1078. {
  1079. ::GetGuidString (&(pInfo->AppGuid), &m_ClientInfo.szGuid[0]);
  1080. m_ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_GUID] = &m_ClientInfo.szGuid[0];
  1081. m_ClientInfo.dwFlags |= CLIENTOBJ_F_APP_GUID;
  1082. }
  1083. // Start to cache app extended attributes
  1084. //
  1085. if (pInfo->uOffsetAttrsToAdd != INVALID_OFFSET &&
  1086. pInfo->cAttrsToAdd != 0)
  1087. {
  1088. m_ClientInfo.AnyAttrs.cAttrsToAdd = pInfo->cAttrsToAdd;
  1089. m_ClientInfo.AnyAttrs.pszAttrsToAdd =
  1090. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAttrsToAdd);
  1091. }
  1092. if (pInfo->uOffsetAttrsToModify != INVALID_OFFSET &&
  1093. pInfo->cAttrsToModify != 0)
  1094. {
  1095. m_ClientInfo.AnyAttrs.cAttrsToModify = pInfo->cAttrsToModify;
  1096. m_ClientInfo.AnyAttrs.pszAttrsToModify =
  1097. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAttrsToModify);
  1098. }
  1099. if (pInfo->uOffsetAttrsToRemove != INVALID_OFFSET &&
  1100. pInfo->cAttrsToRemove != 0)
  1101. {
  1102. m_ClientInfo.AnyAttrs.cAttrsToRemove = pInfo->cAttrsToRemove;
  1103. m_ClientInfo.AnyAttrs.pszAttrsToRemove =
  1104. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAttrsToRemove);
  1105. }
  1106. // Create prefix for extended attribute names
  1107. //
  1108. return ::IlsCreateAnyAttrsPrefix (&(m_ClientInfo.AnyAttrs));
  1109. }
  1110.