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.

1022 lines
22 KiB

  1. /* ----------------------------------------------------------------------
  2. Module: ULS.DLL (Service Provider)
  3. File: splmtg.cpp
  4. Content: This file contains the local meeting 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. #ifdef ENABLE_MEETING_PLACE
  13. // Array of constant strings for user object's attribute names
  14. //
  15. const TCHAR *c_apszMtgStdAttrNames[COUNT_ENUM_MTGATTR] =
  16. {
  17. TEXT ("CN"), // Meeting ID
  18. TEXT ("ConfType"), // Meeting Type
  19. TEXT ("ConfMemberType"), // Attendee Type
  20. TEXT ("ConfDesc"), // Description
  21. TEXT ("ConfHostName"), // Host Name
  22. TEXT ("ConfHostAddress"), // IP Address
  23. TEXT ("ConfMemberList"), // Members
  24. TEXT ("ssecurity"),
  25. TEXT ("sttl"),
  26. TEXT ("objectClass"),
  27. TEXT ("o"),
  28. TEXT ("c"),
  29. };
  30. const TCHAR c_szMtgDefC[] = TEXT ("us");
  31. /* ---------- public methods ----------- */
  32. SP_CMeeting::
  33. SP_CMeeting ( DWORD dwContext )
  34. :
  35. m_cRefs (0), // Reference count
  36. m_uSignature (MTGOBJ_SIGNATURE), // Mtg object's signature
  37. m_pszMtgName (NULL), // Clean the meeting name
  38. m_pszDN (NULL), // Clean DN
  39. m_pszRefreshFilter (NULL), // Clean up the refresh search filter
  40. m_dwIPAddress (0), // Clean local IP address
  41. m_uTTL (ILS_DEF_REFRESH_MINUTE) // Reset time to live value (min)
  42. {
  43. m_dwContext = dwContext;
  44. // Clean up attached server info structure
  45. //
  46. ::ZeroMemory (&m_ServerInfo, sizeof (m_ServerInfo));
  47. // Clean up the scratch buffer for caching pointers to attribute values
  48. //
  49. ::ZeroMemory (&m_MtgInfo, sizeof (m_MtgInfo));
  50. // Indicate this user is not registered yet
  51. //
  52. SetRegNone ();
  53. }
  54. SP_CMeeting::
  55. ~SP_CMeeting ( VOID )
  56. {
  57. // Invalidate the user object's signature
  58. //
  59. m_uSignature = (ULONG) -1;
  60. // Free server info structure
  61. //
  62. ::IlsFreeServerInfo (&m_ServerInfo);
  63. // Free meeting name
  64. //
  65. MemFree (m_pszMtgName);
  66. // Free DN
  67. //
  68. MemFree (m_pszDN);
  69. // Free the refresh search filter
  70. //
  71. MemFree (m_pszRefreshFilter);
  72. // Release the previous prefix for extended attribute names
  73. //
  74. ::IlsReleaseAnyAttrsPrefix (&(m_MtgInfo.AnyAttrs));
  75. }
  76. ULONG
  77. SP_CMeeting::
  78. AddRef ( VOID )
  79. {
  80. ::InterlockedIncrement (&m_cRefs);
  81. return m_cRefs;
  82. }
  83. ULONG
  84. SP_CMeeting::
  85. Release ( VOID )
  86. {
  87. MyAssert (m_cRefs != 0);
  88. ::InterlockedDecrement (&m_cRefs);
  89. ULONG cRefs = m_cRefs;
  90. if (cRefs == 0)
  91. delete this;
  92. return cRefs;
  93. }
  94. HRESULT SP_CMeeting::
  95. Register (
  96. ULONG uRespID,
  97. SERVER_INFO *pServerInfo,
  98. LDAP_MEETINFO *pInfo )
  99. {
  100. MyAssert (pInfo != NULL);
  101. MyAssert (MyIsGoodString (pServerInfo->pszServerName));
  102. // Cache the server info
  103. //
  104. HRESULT hr = ::IlsCopyServerInfo (&m_ServerInfo, pServerInfo);
  105. if (hr != S_OK)
  106. return hr;
  107. // Cache the meeting info
  108. // lonchanc: CacheInfo() is not a method in the meeting object
  109. // because we pass in meeting name in SetMeetingInfo()
  110. // rather than meeting object handle.
  111. //
  112. hr = ::MtgCacheInfo (pInfo, &m_MtgInfo);
  113. if (hr != S_OK)
  114. return hr;
  115. // If the application sets an IP address,
  116. // then we will use what the app provides,
  117. // otherwise, we will get the IP address via winsock.
  118. //
  119. if (pInfo->uOffsetHostIPAddress == INVALID_OFFSET)
  120. {
  121. // Get local IP address
  122. //
  123. m_dwIPAddress = 0;
  124. hr = ::GetLocalIPAddress (&m_dwIPAddress);
  125. if (hr != S_OK)
  126. return hr;
  127. // Create IP address string
  128. //
  129. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_IP_ADDRESS] = &m_MtgInfo.szIPAddress[0];
  130. ::GetLongString (m_dwIPAddress, &m_MtgInfo.szIPAddress[0]);
  131. }
  132. // Create client signature string
  133. //
  134. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_CLIENT_SIG] = &m_MtgInfo.szClientSig[0];
  135. ::GetLongString (g_dwClientSig, &m_MtgInfo.szClientSig[0]);
  136. // Create TTL string
  137. //
  138. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_TTL] = &m_MtgInfo.szTTL[0];
  139. ::GetLongString (m_uTTL, &m_MtgInfo.szTTL[0]);
  140. // Ideally, o= and c= should be read in from registiry
  141. // but for now, we simply hard code it
  142. //
  143. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_OBJECT_CLASS] = (TCHAR *) &c_szRTConf[0];
  144. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_O] = (TCHAR *) &c_szDefO[0];
  145. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_C] = (TCHAR *) &c_szMtgDefC[0];
  146. // Duplicate the mtg name
  147. //
  148. m_pszMtgName = My_strdup (m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_CN]);
  149. if (m_pszMtgName == NULL)
  150. return ILS_E_MEMORY;
  151. // Build DN
  152. //
  153. m_pszDN = ::IlsBuildDN (m_ServerInfo.pszBaseDN,
  154. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_C],
  155. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_O],
  156. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_CN],
  157. m_MtgInfo.apszStdAttrValues[ENUM_MTGATTR_OBJECT_CLASS]);
  158. if (m_pszDN == NULL)
  159. return ILS_E_MEMORY;
  160. // Build refreh filter
  161. //
  162. m_pszRefreshFilter = ::MtgCreateRefreshFilter (m_pszMtgName);
  163. if (m_pszRefreshFilter == NULL)
  164. return ILS_E_MEMORY;
  165. // Build modify array for ldap_add()
  166. //
  167. LDAPMod **ppMod = NULL;
  168. hr = CreateRegModArr (&ppMod);
  169. if (hr != S_OK)
  170. return hr;
  171. MyAssert (ppMod != NULL);
  172. // so far, we are done with local preparation
  173. //
  174. // Get the connection object
  175. //
  176. SP_CSession *pSession = NULL;
  177. LDAP *ld;
  178. ULONG uMsgID = (ULONG) -1;
  179. hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  180. if (hr == S_OK)
  181. {
  182. MyAssert (pSession != NULL);
  183. // Get the ldap session
  184. //
  185. ld = pSession->GetLd ();
  186. MyAssert (ld != NULL);
  187. // Send the data over the wire
  188. //
  189. uMsgID = ldap_add (ld, m_pszDN, ppMod);
  190. if (uMsgID == -1)
  191. {
  192. hr = ::LdapError2Hresult (ld->ld_errno);
  193. }
  194. }
  195. // Free modify array
  196. //
  197. MemFree (ppMod);
  198. // Report failure if so
  199. //
  200. if (hr != S_OK)
  201. goto MyExit;
  202. // Construct a pending info
  203. //
  204. RESP_INFO ri;
  205. ::FillDefRespInfo (&ri, uRespID, ld, uMsgID, INVALID_MSG_ID);
  206. ri.uNotifyMsg = WM_ILS_REGISTER_MEETING;
  207. ri.hObject = (HANDLE) this;
  208. // Remember the pending result
  209. //
  210. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  211. if (hr != S_OK)
  212. {
  213. MyAssert (FALSE);
  214. goto MyExit;
  215. }
  216. MyExit:
  217. if (hr != S_OK)
  218. {
  219. if (uMsgID != (ULONG) -1)
  220. ::ldap_abandon (ld, uMsgID);
  221. if (pSession != NULL)
  222. pSession->Disconnect ();
  223. }
  224. return hr;
  225. }
  226. HRESULT SP_CMeeting::
  227. UnRegister ( ULONG uRespID )
  228. {
  229. MyAssert (MyIsGoodString (m_pszDN));
  230. // Make sure that there is not refresh scheduled for this object
  231. //
  232. if (g_pRefreshScheduler != NULL)
  233. {
  234. g_pRefreshScheduler->RemoveMtgObject (this);
  235. }
  236. else
  237. {
  238. MyAssert (FALSE);
  239. }
  240. // If it is not registered on the server,
  241. // the simply report success
  242. //
  243. if (! IsRegRemotely ())
  244. {
  245. SetRegNone ();
  246. ::PostMessage (g_hWndNotify, WM_ILS_UNREGISTER_MEETING, uRespID, S_OK);
  247. return S_OK;
  248. }
  249. // Indicate that we are not registered at all
  250. //
  251. SetRegNone ();
  252. // Get the session object
  253. //
  254. SP_CSession *pSession = NULL;
  255. LDAP *ld;
  256. ULONG uMsgID = (ULONG) -1;
  257. HRESULT hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
  258. if (hr == S_OK)
  259. {
  260. // Get the ldap session
  261. //
  262. MyAssert (pSession != NULL);
  263. ld = pSession->GetLd ();
  264. MyAssert (ld != NULL);
  265. // Send the data over the wire
  266. //
  267. MyAssert (MyIsGoodString (m_pszDN));
  268. uMsgID = ::ldap_delete (ld, m_pszDN);
  269. if (uMsgID == -1)
  270. {
  271. hr = ::LdapError2Hresult (ld->ld_errno);
  272. }
  273. }
  274. // Report failure if so
  275. //
  276. if (hr != S_OK)
  277. goto MyExit;
  278. // Construct a pending info
  279. //
  280. RESP_INFO ri;
  281. ::FillDefRespInfo (&ri, uRespID, ld, uMsgID, INVALID_MSG_ID);
  282. ri.uNotifyMsg = WM_ILS_UNREGISTER_MEETING;
  283. // Remember the pending request
  284. //
  285. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  286. if (hr != S_OK)
  287. {
  288. MyAssert (FALSE);
  289. goto MyExit;
  290. }
  291. MyExit:
  292. if (hr != S_OK)
  293. {
  294. if (uMsgID != (ULONG) -1)
  295. ::ldap_abandon (ld, uMsgID);
  296. if (pSession != NULL)
  297. pSession->Disconnect ();
  298. }
  299. return hr;
  300. }
  301. HRESULT SP_CMeeting::
  302. UpdateIPAddress ( VOID )
  303. {
  304. MyAssert (MyIsGoodString (m_pszDN));
  305. // Update cached ip address
  306. //
  307. HRESULT hr = ::GetLocalIPAddress (&m_dwIPAddress);
  308. if (hr != S_OK)
  309. return hr;
  310. // Update the ip address string
  311. //
  312. ::GetLongString (m_dwIPAddress, &m_MtgInfo.szIPAddress[0]);
  313. // Update IP address in the server
  314. //
  315. return ::IlsUpdateIPAddress ( &m_ServerInfo,
  316. m_pszDN,
  317. STR_MTG_IP_ADDR,
  318. &m_MtgInfo.szIPAddress[0],
  319. ISBU_MODOP_MODIFY_USER,
  320. MtgGetPrefixCount (),
  321. MtgGetPrefixString ());
  322. }
  323. /* ---------- protected methods ----------- */
  324. HRESULT SP_CMeeting::
  325. SendRefreshMsg ( VOID )
  326. {
  327. MyAssert (m_pszRefreshFilter != NULL);
  328. // Get local IP address
  329. //
  330. DWORD dwIPAddress = 0;
  331. HRESULT hr = ::GetLocalIPAddress (&dwIPAddress);
  332. if (hr != S_OK)
  333. {
  334. MyDebugMsg ((ZONE_KA, "KA(Mtg): cannot get my ip address\r\n"));
  335. // Indicate that I am not connected to the server anymore
  336. //
  337. SetRegLocally ();
  338. // Second, notify this app of the network being down
  339. //
  340. ::PostMessage (g_hWndNotify, WM_ILS_MEETING_NETWORK_DOWN,
  341. (WPARAM) this, (LPARAM) m_dwContext);
  342. // Report error
  343. //
  344. return ILS_E_NETWORK_DOWN;
  345. }
  346. // If dwIPAddress is 0, then we are not on the network any more
  347. // start relogon process
  348. //
  349. if (dwIPAddress == 0)
  350. {
  351. MyDebugMsg ((ZONE_KA, "KA(Mtg): ip-addr=0, network down.\r\n"));
  352. // Indicate that I am not connected to the server anymore
  353. //
  354. SetRegLocally ();
  355. // Second, notify this app of the network being down
  356. //
  357. ::PostMessage (g_hWndNotify, WM_ILS_MEETING_NETWORK_DOWN,
  358. (WPARAM) this, (LPARAM) m_dwContext);
  359. // Report error
  360. //
  361. return ILS_E_NETWORK_DOWN;
  362. }
  363. else
  364. // If dwIPAddress and m_dwIPAddress, alert
  365. //
  366. if (dwIPAddress != m_dwIPAddress)
  367. {
  368. UpdateIPAddress ();
  369. }
  370. // Send a refresh message to the server and parse the new TTL value
  371. //
  372. hr = ::IlsSendRefreshMsg ( &m_ServerInfo,
  373. STR_DEF_MTG_BASE_DN,
  374. STR_MTG_TTL,
  375. m_pszRefreshFilter,
  376. &m_uTTL);
  377. if (hr == ILS_E_NEED_RELOGON)
  378. {
  379. SetRegLocally ();
  380. ::PostMessage (g_hWndNotify, WM_ILS_MEETING_NEED_RELOGON,
  381. (WPARAM) this, (LPARAM) m_dwContext);
  382. }
  383. else
  384. if (hr == ILS_E_NETWORK_DOWN)
  385. {
  386. SetRegLocally ();
  387. ::PostMessage (g_hWndNotify, WM_ILS_MEETING_NETWORK_DOWN,
  388. (WPARAM) this, (LPARAM) m_dwContext);
  389. }
  390. return hr;
  391. }
  392. /* ---------- private methods ----------- */
  393. HRESULT SP_CMeeting::
  394. CreateRegModArr ( LDAPMod ***pppMod )
  395. {
  396. MyAssert (pppMod != NULL);
  397. // Calculate the modify array size
  398. //
  399. ULONG cStdAttrs = COUNT_ENUM_MTGATTR;
  400. ULONG cAnyAttrs = m_MtgInfo.AnyAttrs.cAttrsToAdd;
  401. ULONG cTotal = cStdAttrs + cAnyAttrs;
  402. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  403. // Allocate modify list
  404. //
  405. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  406. if (*pppMod == NULL)
  407. return ILS_E_MEMORY;
  408. // Lay out the modify array
  409. //
  410. LDAPMod **apMod = *pppMod;
  411. LDAPMod *pMod;
  412. TCHAR *pszName, *pszValue;
  413. pszName = m_MtgInfo.AnyAttrs.pszAttrsToAdd;
  414. for (ULONG i = 0; i < cTotal; i++)
  415. {
  416. pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
  417. pMod->mod_op = LDAP_MOD_ADD;
  418. apMod[i] = pMod;
  419. if (i < cStdAttrs)
  420. {
  421. // Put standard attributes
  422. //
  423. ::MtgFillModArrAttr (pMod, &m_MtgInfo, i);
  424. }
  425. else
  426. {
  427. // Put extended attributes
  428. //
  429. pszValue = pszName + lstrlen (pszName) + 1;
  430. ::IlsFillModifyListItem (pMod, pszName, pszValue);
  431. pszName = pszValue + lstrlen (pszValue) + 1;
  432. }
  433. }
  434. // Put null to terminate modify list
  435. //
  436. apMod[cTotal] = NULL;
  437. return S_OK;
  438. }
  439. /* ---------- helper functions ----------- */
  440. HRESULT
  441. MtgSetAttrs (
  442. SERVER_INFO *pServerInfo,
  443. TCHAR *pszMtgName,
  444. LDAP_MEETINFO *pInfo,
  445. ULONG uRespID )
  446. {
  447. MyAssert (pServerInfo != NULL);
  448. MyAssert (MyIsGoodString (pszMtgName));
  449. MyAssert (pInfo != NULL);
  450. // Cannot change lMeetingPlaceType, lAttendeeType, and MeetingID
  451. //
  452. if (pInfo->lMeetingPlaceType != INVALID_MEETING_TYPE ||
  453. pInfo->lAttendeeType != INVALID_ATTENDEE_TYPE ||
  454. pInfo->uOffsetMeetingPlaceID != INVALID_OFFSET)
  455. {
  456. return ILS_E_PARAMETER;
  457. }
  458. // Initialize locals
  459. //
  460. TCHAR *pszDN = NULL;
  461. LDAPMod **ppMod = NULL;
  462. SP_CSession *pSession = NULL;
  463. ULONG uMsgID = (ULONG) -1;
  464. MTG_INFO MtgInfo;
  465. ZeroMemory (&MtgInfo, sizeof (MtgInfo));
  466. // Cache the meeting info
  467. //
  468. HRESULT hr = MtgCacheInfo (pInfo, &MtgInfo);
  469. if (hr != S_OK)
  470. goto MyExit;
  471. // Build DN for meeting
  472. //
  473. pszDN = IlsBuildDN (pServerInfo->pszBaseDN,
  474. (TCHAR *) &c_szMtgDefC[0],
  475. (TCHAR *) &c_szDefO[0],
  476. pszMtgName,
  477. (TCHAR *) &c_szRTConf[0]);
  478. if (pszDN == NULL)
  479. {
  480. hr = ILS_E_MEMORY;
  481. goto MyExit;
  482. }
  483. // Build modify array for ldap_modify()
  484. //
  485. hr = MtgCreateSetAttrsModArr (&ppMod, &MtgInfo);
  486. if (hr != S_OK)
  487. goto MyExit;
  488. MyAssert (ppMod != NULL);
  489. // Get the session object
  490. //
  491. LDAP *ld;
  492. hr = g_pSessionContainer->GetSession (&pSession, pServerInfo);
  493. if (hr == S_OK)
  494. {
  495. MyAssert (pSession != NULL);
  496. // Get the ldap session
  497. //
  498. ld = pSession->GetLd ();
  499. MyAssert (ld != NULL);
  500. // Send the data over the wire
  501. //
  502. uMsgID = ldap_modify (ld, pszDN, ppMod);
  503. if (uMsgID == (ULONG) -1)
  504. {
  505. hr = ::LdapError2Hresult (ld->ld_errno);
  506. }
  507. }
  508. // Report failure if so
  509. //
  510. if (hr != S_OK)
  511. goto MyExit;
  512. // Construct pending info
  513. //
  514. RESP_INFO ri;
  515. FillDefRespInfo (&ri, uRespID, ld, uMsgID, INVALID_MSG_ID);
  516. ri.uNotifyMsg = WM_ILS_SET_MEETING_INFO;
  517. // Remember the pending request
  518. //
  519. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  520. if (hr != S_OK)
  521. {
  522. MyAssert (FALSE);
  523. goto MyExit;
  524. }
  525. MyExit:
  526. MemFree (pszDN);
  527. MemFree (ppMod);
  528. IlsReleaseAnyAttrsPrefix (&(MtgInfo.AnyAttrs));
  529. if (hr != S_OK)
  530. {
  531. if (uMsgID != (ULONG) -1)
  532. ::ldap_abandon (ld, uMsgID);
  533. if (pSession != NULL)
  534. pSession->Disconnect ();
  535. }
  536. return hr;
  537. }
  538. VOID
  539. MtgFillModArrAttr (
  540. LDAPMod *pMod,
  541. MTG_INFO *pMtgInfo,
  542. INT nIndex )
  543. {
  544. MyAssert (pMod != NULL);
  545. MyAssert (pMtgInfo != NULL);
  546. MyAssert (0 <= nIndex && nIndex <= COUNT_ENUM_MTGATTR);
  547. IlsFillModifyListItem ( pMod,
  548. (TCHAR *) c_apszMtgStdAttrNames[nIndex],
  549. pMtgInfo->apszStdAttrValues[nIndex]);
  550. }
  551. HRESULT
  552. MtgCreateSetAttrsModArr (
  553. LDAPMod ***pppMod,
  554. MTG_INFO *pMtgInfo )
  555. {
  556. MyAssert (pppMod != NULL);
  557. HRESULT hr;
  558. DWORD dwFlags = pMtgInfo->dwFlags;
  559. ULONG cTotal = pMtgInfo->AnyAttrs.cAttrsToAdd +
  560. pMtgInfo->AnyAttrs.cAttrsToModify +
  561. pMtgInfo->AnyAttrs.cAttrsToRemove;
  562. // Lay out the modify array for modifying standard/extended attributes
  563. //
  564. hr = IlsFillDefStdAttrsModArr (pppMod,
  565. dwFlags,
  566. COUNT_ENUM_MTGINFO,
  567. &cTotal,
  568. ISBU_MODOP_MODIFY_USER,
  569. MtgGetPrefixCount (),
  570. MtgGetPrefixString ());
  571. if (hr != S_OK)
  572. return hr;
  573. // Start to fill standard attributes
  574. //
  575. ULONG i = MtgGetPrefixCount ();
  576. LDAPMod **apMod = *pppMod;
  577. if (dwFlags & MTGOBJ_F_NAME)
  578. MtgFillModArrAttr (apMod[i++], pMtgInfo, ENUM_MTGATTR_CN);
  579. if (dwFlags & MTGOBJ_F_MTG_TYPE)
  580. MtgFillModArrAttr (apMod[i++], pMtgInfo, ENUM_MTGATTR_MTG_TYPE);
  581. if (dwFlags & MTGOBJ_F_MEMBER_TYPE)
  582. MtgFillModArrAttr (apMod[i++], pMtgInfo, ENUM_MTGATTR_MEMBER_TYPE);
  583. if (dwFlags & MTGOBJ_F_DESCRIPTION)
  584. MtgFillModArrAttr (apMod[i++], pMtgInfo, ENUM_MTGATTR_DESCRIPTION);
  585. if (dwFlags & MTGOBJ_F_HOST_NAME)
  586. MtgFillModArrAttr (apMod[i++], pMtgInfo, ENUM_MTGATTR_HOST_NAME);
  587. if (dwFlags & MTGOBJ_F_IP_ADDRESS)
  588. MtgFillModArrAttr (apMod[i++], pMtgInfo, ENUM_MTGATTR_IP_ADDRESS);
  589. // Start to fill extended attributes
  590. //
  591. ::IlsFillModifyListForAnyAttrs (apMod, &i, &(pMtgInfo->AnyAttrs));
  592. MyAssert (i == cTotal);
  593. return S_OK;
  594. }
  595. HRESULT
  596. MtgCacheInfo (
  597. LDAP_MEETINFO *pInfo,
  598. MTG_INFO *pMtgInfo )
  599. {
  600. MyAssert (pInfo != NULL);
  601. MyAssert (pMtgInfo != NULL);
  602. // Release the previous prefix for extended attribute names
  603. //
  604. IlsReleaseAnyAttrsPrefix (&(pMtgInfo->AnyAttrs));
  605. // Clean up the buffer
  606. //
  607. ZeroMemory (pMtgInfo, sizeof (*pMtgInfo));
  608. // Start to cache mtg standard attributes
  609. //
  610. if (pInfo->lMeetingPlaceType != INVALID_MEETING_TYPE)
  611. {
  612. GetLongString (pInfo->lMeetingPlaceType, &(pMtgInfo->szMtgType[0]));
  613. pMtgInfo->apszStdAttrValues[ENUM_MTGATTR_MTG_TYPE] = &(pMtgInfo->szMtgType[0]);
  614. pMtgInfo->dwFlags |= MTGOBJ_F_MTG_TYPE;
  615. }
  616. if (pInfo->lAttendeeType != INVALID_ATTENDEE_TYPE)
  617. {
  618. GetLongString (pInfo->lAttendeeType, &(pMtgInfo->szMemberType[0]));
  619. pMtgInfo->apszStdAttrValues[ENUM_MTGATTR_MEMBER_TYPE] = &(pMtgInfo->szMemberType[0]);
  620. pMtgInfo->dwFlags |= MTGOBJ_F_MEMBER_TYPE;
  621. }
  622. if (pInfo->uOffsetMeetingPlaceID != INVALID_OFFSET)
  623. {
  624. pMtgInfo->apszStdAttrValues[ENUM_MTGATTR_CN] =
  625. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetMeetingPlaceID);
  626. pMtgInfo->dwFlags |= MTGOBJ_F_NAME;
  627. }
  628. if (pInfo->uOffsetDescription != INVALID_OFFSET)
  629. {
  630. pMtgInfo->apszStdAttrValues[ENUM_MTGATTR_DESCRIPTION] =
  631. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetDescription);
  632. pMtgInfo->dwFlags |= MTGOBJ_F_DESCRIPTION;
  633. }
  634. if (pInfo->uOffsetHostName != INVALID_OFFSET)
  635. {
  636. pMtgInfo->apszStdAttrValues[ENUM_MTGATTR_HOST_NAME] =
  637. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetHostName);
  638. pMtgInfo->dwFlags |= MTGOBJ_F_HOST_NAME;
  639. }
  640. if (pInfo->uOffsetHostIPAddress != INVALID_OFFSET)
  641. {
  642. pMtgInfo->apszStdAttrValues[ENUM_MTGATTR_IP_ADDRESS] =
  643. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetHostIPAddress);
  644. pMtgInfo->dwFlags |= MTGOBJ_F_IP_ADDRESS;
  645. }
  646. // Start to cache mtg extended attributes
  647. //
  648. if (pInfo->uOffsetAttrsToAdd != INVALID_OFFSET &&
  649. pInfo->cAttrsToAdd != 0)
  650. {
  651. pMtgInfo->AnyAttrs.cAttrsToAdd = pInfo->cAttrsToAdd;
  652. pMtgInfo->AnyAttrs.pszAttrsToAdd =
  653. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAttrsToAdd);
  654. }
  655. if (pInfo->uOffsetAttrsToModify != INVALID_OFFSET &&
  656. pInfo->cAttrsToModify != 0)
  657. {
  658. pMtgInfo->AnyAttrs.cAttrsToModify = pInfo->cAttrsToModify;
  659. pMtgInfo->AnyAttrs.pszAttrsToModify =
  660. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAttrsToModify);
  661. }
  662. if (pInfo->uOffsetAttrsToRemove != INVALID_OFFSET &&
  663. pInfo->cAttrsToRemove != 0)
  664. {
  665. pMtgInfo->AnyAttrs.cAttrsToRemove = pInfo->cAttrsToRemove;
  666. pMtgInfo->AnyAttrs.pszAttrsToRemove =
  667. (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetAttrsToRemove);
  668. }
  669. // Create prefix for extended attribute names
  670. //
  671. return IlsCreateAnyAttrsPrefix (&(pMtgInfo->AnyAttrs));
  672. }
  673. HRESULT
  674. MtgUpdateMembers (
  675. ULONG uNotifyMsg,
  676. SERVER_INFO *pServerInfo,
  677. TCHAR *pszMtgName,
  678. ULONG cMembers,
  679. TCHAR *pszMemberNames,
  680. ULONG uRespID )
  681. {
  682. MyAssert ( uNotifyMsg == WM_ILS_ADD_ATTENDEE ||
  683. uNotifyMsg == WM_ILS_REMOVE_ATTENDEE);
  684. MyAssert (pServerInfo != NULL);
  685. MyAssert (MyIsGoodString (pszMtgName));
  686. MyAssert (MyIsGoodString (pszMemberNames));
  687. // Initialize locals
  688. //
  689. HRESULT hr = S_OK;
  690. TCHAR *pszDN = NULL;
  691. LDAPMod **ppMod = NULL;
  692. SP_CSession *pSession = NULL;
  693. ULONG uMsgID = (ULONG) -1;
  694. // Build DN for meeting
  695. //
  696. pszDN = IlsBuildDN (pServerInfo->pszBaseDN,
  697. (TCHAR *) &c_szMtgDefC[0],
  698. (TCHAR *) &c_szDefO[0],
  699. pszMtgName,
  700. (TCHAR *) &c_szRTConf[0]);
  701. if (pszDN == NULL)
  702. return ILS_E_MEMORY;
  703. // Build modify array for ldap_modify()
  704. //
  705. hr = MtgCreateUpdateMemberModArr ( uNotifyMsg,
  706. &ppMod,
  707. cMembers,
  708. pszMemberNames);
  709. if (hr != S_OK)
  710. goto MyExit;
  711. MyAssert (ppMod != NULL);
  712. // Get the session object
  713. //
  714. LDAP *ld;
  715. hr = g_pSessionContainer->GetSession (&pSession, pServerInfo);
  716. if (hr == S_OK)
  717. {
  718. MyAssert (pSession != NULL);
  719. // Get the ldap session
  720. //
  721. ld = pSession->GetLd ();
  722. MyAssert (ld != NULL);
  723. // Send the data over the wire
  724. //
  725. uMsgID = ldap_modify (ld, pszDN, ppMod);
  726. if (uMsgID == (ULONG) -1)
  727. {
  728. hr = ::LdapError2Hresult (ld->ld_errno);
  729. }
  730. }
  731. // Report failure if so
  732. //
  733. if (hr != S_OK)
  734. goto MyExit;
  735. // Construct pending info
  736. //
  737. RESP_INFO ri;
  738. FillDefRespInfo (&ri, uRespID, ld, uMsgID, INVALID_MSG_ID);
  739. ri.uNotifyMsg = uNotifyMsg;
  740. // Remember the pending request
  741. //
  742. hr = g_pRespQueue->EnterRequest (pSession, &ri);
  743. if (hr != S_OK)
  744. {
  745. MyAssert (FALSE);
  746. goto MyExit;
  747. }
  748. MyExit:
  749. MemFree (pszDN);
  750. MemFree (ppMod);
  751. if (hr != S_OK)
  752. {
  753. if (uMsgID != (ULONG) -1)
  754. ::ldap_abandon (ld, uMsgID);
  755. if (pSession != NULL)
  756. pSession->Disconnect ();
  757. }
  758. return hr;
  759. }
  760. HRESULT
  761. MtgCreateUpdateMemberModArr (
  762. ULONG uNotifyMsg,
  763. LDAPMod ***pppMod,
  764. ULONG cMembers,
  765. TCHAR *pszMemberNames )
  766. {
  767. MyAssert (pppMod != NULL);
  768. MyAssert (pszMemberNames != NULL);
  769. // Get meeting object prefix
  770. //
  771. ULONG cPrefix = MtgGetPrefixCount ();
  772. TCHAR *pszPrefix = MtgGetPrefixString ();
  773. // The total number of attributes is the number of prefix attributes
  774. // plus the very only ConfMemberList
  775. //
  776. ULONG cStdAttrs = 1;
  777. ULONG cTotal = cPrefix + cStdAttrs;
  778. // Calculate the modify array's total size
  779. //
  780. ULONG cbMod = IlsCalcModifyListSize (cTotal);
  781. // Add up for multi-valued attribute
  782. //
  783. cbMod += cStdAttrs * (cMembers - 1) * sizeof (TCHAR *);
  784. // Allocate the modify array
  785. //
  786. LDAPMod **apMod = *pppMod = (LDAPMod **) MemAlloc (cbMod);
  787. if (apMod == NULL)
  788. return ILS_E_MEMORY;
  789. // Fill in the modify list
  790. //
  791. LDAPMod *pMod;
  792. BYTE *pbData = (BYTE *) apMod + (cTotal + 1) * sizeof (LDAPMod *);
  793. ULONG uDispPrefix = sizeof (LDAPMod) + 2 * sizeof (TCHAR *);
  794. ULONG uDispStdAttrs = sizeof (LDAPMod) + (cMembers + 1) * sizeof (TCHAR *);
  795. for (ULONG uOffset = 0, i = 0; i < cTotal; i++)
  796. {
  797. // Locate the modify structure
  798. //
  799. pMod = (LDAPMod *) (pbData + uOffset);
  800. apMod[i] = pMod;
  801. pMod->mod_values = (TCHAR **) (pMod + 1);
  802. // Fill in the modify structure
  803. //
  804. if (i < cPrefix)
  805. {
  806. pMod->mod_op = LDAP_MOD_REPLACE;
  807. pMod->mod_type = pszPrefix;
  808. pszPrefix += lstrlen (pszPrefix) + 1;
  809. *(pMod->mod_values) = pszPrefix;
  810. pszPrefix += lstrlen (pszPrefix) + 1;
  811. }
  812. else
  813. {
  814. // Fill in attribute name
  815. //
  816. pMod->mod_op = (uNotifyMsg == WM_ILS_ADD_ATTENDEE) ?
  817. LDAP_MOD_ADD : LDAP_MOD_DELETE;
  818. pMod->mod_type = (TCHAR *) c_apszMtgStdAttrNames[ENUM_MTGATTR_MEMBERS];
  819. // Fill in multi-valued modify array
  820. //
  821. for (ULONG j = 0; j < cMembers; j++)
  822. {
  823. (pMod->mod_values)[j++] = pszMemberNames;
  824. pszMemberNames += lstrlen (pszMemberNames) + 1;
  825. }
  826. }
  827. // Calculate the modify structure's offset relative to the array's end
  828. //
  829. uOffset += (i < cPrefix) ? uDispPrefix : uDispStdAttrs;
  830. }
  831. // Fix up the first and the last ones
  832. //
  833. IlsFixUpModOp (apMod[0], LDAP_MOD_REPLACE, ISBU_MODOP_MODIFY_APP);
  834. apMod[cTotal] = NULL;
  835. return S_OK;
  836. }
  837. #endif // ENABLE_MEETING_PLACE