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.

2829 lines
60 KiB

  1. /* ----------------------------------------------------------------------
  2. Module: ULS.DLL (Service Provider)
  3. File: spnotify.cpp
  4. Content: This file contains the notification handlers.
  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. typedef struct
  13. {
  14. TCHAR *pszName;
  15. TCHAR *pszValue;
  16. }
  17. ATTR_PAIR;
  18. typedef struct
  19. {
  20. ULONG cMaxAttrs;
  21. ULONG cCurrAttrs;
  22. ATTR_PAIR aPairs[1];
  23. }
  24. ATTR_PAIRS;
  25. typedef struct
  26. {
  27. CLIENT_INFO ClientInfo;
  28. ATTR_PAIRS Attrs;
  29. }
  30. CLIENT_INFO_ATTRS;
  31. #ifdef ENABLE_MEETING_PLACE
  32. typedef struct
  33. {
  34. MTG_INFO MtgInfo;
  35. ATTR_PAIRS Attrs;
  36. }
  37. MTG_INFO_ATTRS;
  38. #endif
  39. ULONG
  40. GetUniqueNotifyID ( VOID )
  41. {
  42. // Always positive number
  43. //
  44. if (g_uRespID & 0x80000000UL)
  45. g_uRespID = 1;
  46. return g_uRespID++;
  47. }
  48. BOOL
  49. NotifyGeneric (
  50. HRESULT hrServer,
  51. SP_CResponse *pItem )
  52. {
  53. MyAssert (pItem != NULL);
  54. // Get the pending info
  55. //
  56. RESP_INFO *pInfo = pItem->GetRespInfo ();
  57. MyAssert (pInfo != NULL);
  58. // Do not use the result (pLdapMsg)
  59. //
  60. // Check dependency such as modify/modrdn
  61. //
  62. if (pInfo->uMsgID[0] != INVALID_MSG_ID)
  63. {
  64. // Do we wait for the second result?
  65. // If so, remember the hr from the first result.
  66. //
  67. if (pInfo->uMsgID[1] != INVALID_MSG_ID)
  68. {
  69. // We need two results; the first one just comes in.
  70. // We still need to wait for the second one
  71. //
  72. pInfo->uMsgID[0] = INVALID_MSG_ID;
  73. pInfo->hrDependency = hrServer;
  74. // Don't destroy this item
  75. //
  76. return FALSE;
  77. }
  78. }
  79. else
  80. {
  81. // This is the second result
  82. //
  83. MyAssert (pInfo->uMsgID[1] != INVALID_MSG_ID);
  84. // Propagate the hr from the first result if needed
  85. //
  86. if (pInfo->hrDependency != S_OK)
  87. hrServer = pInfo->hrDependency;
  88. }
  89. // Post the result to the com layer
  90. //
  91. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, hrServer);
  92. // Destroy this pending item
  93. //
  94. return TRUE;
  95. }
  96. BOOL
  97. NotifyRegister (
  98. HRESULT hrServer,
  99. SP_CResponse *pItem )
  100. {
  101. MyAssert (pItem != NULL);
  102. // Get pending info
  103. //
  104. RESP_INFO *pInfo = pItem->GetRespInfo ();
  105. MyAssert (pInfo != NULL);
  106. // Get the object of user/app/prot/mtg
  107. //
  108. HANDLE hObject = pInfo->hObject;
  109. MyAssert (hObject != NULL);
  110. // Do not use the result (pLdapMsg)
  111. //
  112. // Check dependency such as modify/modrdn
  113. //
  114. if (pInfo->uMsgID[0] != INVALID_MSG_ID)
  115. {
  116. // Do we wait for the second result?
  117. // If so, remember the hr from the first result.
  118. //
  119. if (pInfo->uMsgID[1] != INVALID_MSG_ID)
  120. {
  121. // We need two results; the first one just comes in.
  122. // We still need to wait for the second one
  123. //
  124. pInfo->uMsgID[0] = INVALID_MSG_ID;
  125. pInfo->hrDependency = hrServer;
  126. // Don't destroy this item
  127. //
  128. return FALSE;
  129. }
  130. }
  131. else
  132. {
  133. // This is the second result
  134. //
  135. MyAssert (pInfo->uMsgID[1] != INVALID_MSG_ID);
  136. // Propagate the hr from the first result if needed
  137. //
  138. if (pInfo->hrDependency != S_OK)
  139. hrServer = pInfo->hrDependency;
  140. }
  141. // Notify the object of success/failure
  142. //
  143. SP_CClient *pClient;
  144. SP_CProtocol *pProt;
  145. #ifdef ENABLE_MEETING_PLACE
  146. SP_CMeeting *pMtg;
  147. #endif
  148. if (hrServer != S_OK)
  149. {
  150. // Release the object when failure
  151. //
  152. switch (pInfo->uNotifyMsg)
  153. {
  154. case WM_ILS_REGISTER_CLIENT:
  155. pClient = (SP_CClient *) hObject;
  156. if (pClient->IsValidObject ())
  157. {
  158. pClient->Release ();
  159. }
  160. break;
  161. case WM_ILS_REGISTER_PROTOCOL:
  162. pProt = (SP_CProtocol *) hObject;
  163. if (pProt->IsValidObject ())
  164. {
  165. pProt->Release ();
  166. }
  167. break;
  168. #ifdef ENABLE_MEETING_PLACE
  169. case WM_ILS_REGISTER_MEETING:
  170. pMtg = (SP_CMeeting *) hObject;
  171. if (pMtg->IsValidObject ())
  172. {
  173. pMtg->Release ();
  174. }
  175. break;
  176. #endif
  177. default:
  178. MyAssert (FALSE);
  179. break;
  180. }
  181. }
  182. else
  183. {
  184. // Set as successful registration when success
  185. //
  186. switch (pInfo->uNotifyMsg)
  187. {
  188. case WM_ILS_REGISTER_CLIENT:
  189. pClient = (SP_CClient *) hObject;
  190. if (pClient->IsValidObject ())
  191. {
  192. pClient->SetRegRemotely ();
  193. if (g_pRefreshScheduler != NULL)
  194. {
  195. g_pRefreshScheduler->EnterClientObject (pClient);
  196. }
  197. else
  198. {
  199. MyAssert (FALSE);
  200. }
  201. }
  202. break;
  203. case WM_ILS_REGISTER_PROTOCOL:
  204. pProt = (SP_CProtocol *) hObject;
  205. if (pProt->IsValidObject ())
  206. {
  207. pProt->SetRegRemotely ();
  208. }
  209. break;
  210. #ifdef ENABLE_MEETING_PLACE
  211. case WM_ILS_REGISTER_MEETING:
  212. pMtg = (SP_CMeeting *) hObject;
  213. if (pMtg->IsValidObject ())
  214. {
  215. pMtg->SetRegRemotely ();
  216. if (g_pRefreshScheduler != NULL)
  217. {
  218. g_pRefreshScheduler->EnterMtgObject (pMtg);
  219. }
  220. else
  221. {
  222. MyAssert (FALSE);
  223. }
  224. }
  225. break;
  226. #endif
  227. default:
  228. MyAssert (FALSE);
  229. break;
  230. }
  231. }
  232. // Post the result to the com layer
  233. //
  234. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) hrServer);
  235. // Destroy this pending item
  236. //
  237. return TRUE;
  238. }
  239. /* =========== ENUMERATION ============ */
  240. typedef struct
  241. {
  242. ULONG uEnumUsers; // WM_ILS_ENUM_USERS, WM_ILS_ENUM_USERINFOS, or 0
  243. ULONG cItems;
  244. ULONG cbEntrySize;
  245. BYTE bData[8]; // data starting from here
  246. }
  247. ENUM_LIST;
  248. extern HRESULT CacheEnumInfos ( ULONG uNotifyMsg, LDAP *ld, LDAPMessage *pEntry, VOID *p );
  249. extern VOID BuildEnumObjectNames ( LDAP_ENUM *pEnum, ENUM_LIST *pEnumList );
  250. extern VOID BuildEnumClientInfos ( LDAP_ENUM *pEnum, ENUM_LIST *pEnumList );
  251. extern VOID SizeEnumClientInfos ( ULONG *pcbTotalSize, CLIENT_INFO_ATTRS *pcia );
  252. extern VOID TotalSizeEnumObjectNames ( ULONG *pcbTotalSize, ULONG cEntries, TCHAR **appszObjectNames[] );
  253. extern VOID FreeStdAttrCache ( TCHAR *apszStdAttrValues[], ULONG cStdAttrs );
  254. extern VOID FreeAttrPairArrayCache ( ATTR_PAIR aAttrPair[], ULONG cPairs );
  255. extern VOID CacheAnyAttrNamesInAttrPairs ( ULONG cNames, TCHAR *pszSrcNameList, ATTR_PAIR aAttrPairs[] );
  256. #ifdef ENABLE_MEETING_PLACE
  257. extern VOID BuildEnumMtgInfos ( LDAP_ENUM *pEnum, ENUM_LIST *pEnumList );
  258. extern VOID SizeEnumMtgInfos ( ULONG *pcbTotalSize, MTG_INFO_ATTRS *pmia );
  259. #endif
  260. BOOL NotifyEnumX (
  261. ULONG uEnumType,
  262. HRESULT hrServer,
  263. SP_CResponse *pItem,
  264. TCHAR *pszRetAttrName ) // returned attribute's name
  265. {
  266. MyAssert (pItem != NULL);
  267. #if defined (DEBUG) || defined (_DEBUG)
  268. // Consistency checks
  269. //
  270. switch (uEnumType)
  271. {
  272. case WM_ILS_ENUM_CLIENTS:
  273. #ifdef ENABLE_MEETING_PLACE
  274. case WM_ILS_ENUM_MEETINGS:
  275. #endif
  276. MyAssert (pszRetAttrName != NULL && *pszRetAttrName != TEXT ('\0'));
  277. break;
  278. case WM_ILS_ENUM_CLIENTINFOS:
  279. #ifdef ENABLE_MEETING_PLACE
  280. case WM_ILS_ENUM_MEETINGINFOS:
  281. #endif
  282. MyAssert (pszRetAttrName == NULL);
  283. break;
  284. default:
  285. MyAssert (FALSE);
  286. break;
  287. }
  288. #endif
  289. // Get pending info
  290. //
  291. RESP_INFO *pInfo = pItem->GetRespInfo ();
  292. MyAssert (pInfo != NULL);
  293. // Initialize minimal info
  294. //
  295. LDAP_ENUM *pEnum = NULL;
  296. ENUM_LIST *pEnumList = NULL;
  297. // If error, simply report the error
  298. //
  299. if (hrServer != S_OK)
  300. goto MyExit;
  301. // Get the ldap result
  302. //
  303. LDAPMessage *pLdapMsg;
  304. pLdapMsg = pItem->GetResult ();
  305. if (pLdapMsg == NULL)
  306. {
  307. MyAssert (FALSE);
  308. hrServer = ILS_E_POINTER;
  309. goto MyExit;
  310. }
  311. // Get ld
  312. //
  313. LDAP *ld;
  314. ld = pItem->GetLd ();
  315. if (ld == NULL)
  316. {
  317. MyAssert (FALSE);
  318. hrServer = ILS_E_HANDLE;
  319. goto MyExit;
  320. }
  321. // Initialize the total size of LDAP_ENUM
  322. //
  323. ULONG cbTotalSize;
  324. cbTotalSize = sizeof (LDAP_ENUM) + // the minimal info
  325. sizeof (TCHAR); // the last null terminator
  326. // Let's get the count of entries in this result set
  327. //
  328. ULONG cEntries, i;
  329. cEntries = ldap_count_entries (ld, pLdapMsg);
  330. // Return now if there is nothing to handle
  331. //
  332. if (cEntries <= 0)
  333. {
  334. // I want to make sure this case happens or not
  335. //
  336. MyAssert (cEntries == 0);
  337. // Simply return without deleting this pending item
  338. //
  339. return FALSE;
  340. }
  341. // In the following, we only deal with the case (cEntries > 0)
  342. //
  343. // Calculate enum list size
  344. //
  345. ULONG cbEntrySize , cbSizeEnumList;
  346. switch (uEnumType)
  347. {
  348. case WM_ILS_ENUM_CLIENTINFOS:
  349. cbEntrySize = sizeof (CLIENT_INFO_ATTRS) +
  350. pInfo->cAnyAttrs * sizeof (ATTR_PAIR);
  351. break;
  352. #ifdef ENABLE_MEETING_PLACE
  353. case WM_ILS_ENUM_MEETINGINFOS:
  354. cbEntrySize = sizeof (MTG_INFO_ATTRS) +
  355. pInfo->cAnyAttrs * sizeof (ATTR_PAIR);
  356. break;
  357. #endif
  358. default:
  359. cbEntrySize = sizeof (TCHAR **);
  360. break;
  361. }
  362. cbSizeEnumList = sizeof (ENUM_LIST) + cEntries * cbEntrySize;
  363. // Allocate the enum list that is a temporary cache
  364. // for all attributes from wldap32.dll
  365. //
  366. pEnumList = (ENUM_LIST *) MemAlloc (cbSizeEnumList);
  367. if (pEnumList == NULL)
  368. {
  369. // Fails probably due to insane cbSizeEnumList
  370. //
  371. MyAssert (FALSE);
  372. hrServer = ILS_E_MEMORY;
  373. goto MyExit;
  374. }
  375. // Fill in enum list
  376. //
  377. pEnumList->uEnumUsers = uEnumType;
  378. pEnumList->cItems = cEntries;
  379. pEnumList->cbEntrySize = cbEntrySize;
  380. // Fill in names of extended attributes if needed
  381. //
  382. if (pInfo->cAnyAttrs > 0)
  383. {
  384. switch (uEnumType)
  385. {
  386. case WM_ILS_ENUM_CLIENTINFOS:
  387. for (i = 0; i < cEntries; i++)
  388. {
  389. CLIENT_INFO_ATTRS *p = (CLIENT_INFO_ATTRS *) (&(pEnumList->bData[0]) + i * cbEntrySize);
  390. p->Attrs.cMaxAttrs = pInfo->cAnyAttrs;
  391. CacheAnyAttrNamesInAttrPairs ( pInfo->cAnyAttrs,
  392. pInfo->pszAnyAttrNameList,
  393. &(p->Attrs.aPairs[0]));
  394. }
  395. break;
  396. #ifdef ENABLE_MEETING_PLACE
  397. case WM_ILS_ENUM_MEETINGINFOS:
  398. for (i = 0; i < cEntries; i++)
  399. {
  400. MTG_INFO_ATTRS *p = (MTG_INFO_ATTRS *) (&(pEnumList->bData[0]) + i * cbEntrySize);
  401. p->Attrs.cMaxAttrs = pInfo->cAnyAttrs;
  402. CacheAnyAttrNamesInAttrPairs ( pInfo->cAnyAttrs,
  403. pInfo->pszAnyAttrNameList,
  404. &(p->Attrs.aPairs[0]));
  405. }
  406. break;
  407. #endif
  408. default:
  409. break;
  410. }
  411. }
  412. // Get the first entry
  413. //
  414. LDAPMessage *pEntry;
  415. pEntry = ldap_first_entry (ld, pLdapMsg);
  416. if (pEntry == NULL)
  417. {
  418. MyAssert (FALSE);
  419. hrServer = ILS_E_MEMORY;
  420. goto MyExit;
  421. }
  422. // Cache the attributes in the first entry
  423. //
  424. TCHAR ***appszObjectNames;
  425. switch (uEnumType)
  426. {
  427. case WM_ILS_ENUM_CLIENTINFOS:
  428. #ifdef ENABLE_MEETING_PLACE
  429. case WM_ILS_ENUM_MEETINGINFOS:
  430. #endif
  431. hrServer = CacheEnumInfos (uEnumType, ld, pEntry, (VOID *) &(pEnumList->bData[0]));
  432. if (hrServer != S_OK)
  433. {
  434. MyAssert (FALSE);
  435. goto MyExit;
  436. }
  437. break;
  438. default:
  439. appszObjectNames = (TCHAR ***) &(pEnumList->bData[0]);
  440. appszObjectNames[0] = my_ldap_get_values (ld, pEntry, pszRetAttrName);
  441. if (appszObjectNames[0] == NULL)
  442. {
  443. MyAssert (FALSE);
  444. hrServer = ILS_E_MEMORY;
  445. goto MyExit;
  446. }
  447. break;
  448. } // switch (uEnumType)
  449. // Loop through the other entries
  450. //
  451. for (i = 1; i < cEntries; i++)
  452. {
  453. // Next entry, please
  454. //
  455. pEntry = ldap_next_entry (ld, pEntry);
  456. if (pEntry == NULL)
  457. {
  458. MyAssert (FALSE);
  459. // Failed, adjust the count to return partial result
  460. //
  461. pEnumList->cItems = cEntries = i;
  462. break;
  463. }
  464. // Cache the attributes in the subsequent entries
  465. //
  466. switch (uEnumType)
  467. {
  468. case WM_ILS_ENUM_CLIENTINFOS:
  469. #ifdef ENABLE_MEETING_PLACE
  470. case WM_ILS_ENUM_MEETINGINFOS:
  471. #endif
  472. hrServer = CacheEnumInfos (uEnumType, ld, pEntry, (CLIENT_INFO_ATTRS *)
  473. (&(pEnumList->bData[0]) + i * cbEntrySize));
  474. if (hrServer != S_OK)
  475. {
  476. MyAssert (FALSE);
  477. goto MyExit;
  478. }
  479. break;
  480. default:
  481. appszObjectNames[i] = my_ldap_get_values (ld, pEntry, pszRetAttrName);
  482. if (appszObjectNames[i] == NULL)
  483. {
  484. MyAssert (FALSE);
  485. hrServer = ILS_E_MEMORY;
  486. goto MyExit;
  487. }
  488. break;
  489. } // switch (uEnumType)
  490. } // for (i = 1; i < cEntries; i++)
  491. // We just cache all the attribute names and values.
  492. // Now, we need to calculate the total size of the return buffer.
  493. //
  494. // Calculate the total size of the LDAP_ENUM structure...
  495. //
  496. switch (uEnumType)
  497. {
  498. case WM_ILS_ENUM_CLIENTINFOS:
  499. for (i = 0; i < cEntries; i++)
  500. {
  501. SizeEnumClientInfos (&cbTotalSize, (CLIENT_INFO_ATTRS *)
  502. (&(pEnumList->bData[0]) + i * cbEntrySize));
  503. }
  504. break;
  505. #ifdef ENABLE_MEETING_PLACE
  506. case WM_ILS_ENUM_MEETINGINFOS:
  507. for (i = 0; i < cEntries; i++)
  508. {
  509. SizeEnumMtgInfos (&cbTotalSize, (MTG_INFO_ATTRS *)
  510. (&(pEnumList->bData[0]) + i * cbEntrySize));
  511. }
  512. break;
  513. #endif
  514. default:
  515. TotalSizeEnumObjectNames (&cbTotalSize, cEntries, &(appszObjectNames[0]));
  516. break;
  517. } // switch (uEnumType)
  518. // Allocate the returned LDAP_ENUM structure
  519. //
  520. pEnum = (LDAP_ENUM *) MemAlloc (cbTotalSize);
  521. if (pEnum == NULL)
  522. {
  523. // Fails probably due to insane cbTotalSize
  524. //
  525. MyAssert (FALSE);
  526. hrServer = ILS_E_MEMORY;
  527. goto MyExit;
  528. }
  529. // Fill in LDAP_ENUM common fields
  530. //
  531. pEnum->uSize = sizeof (*pEnum);
  532. pEnum->hResult = hrServer;
  533. pEnum->cItems = cEntries;
  534. pEnum->uOffsetItems = sizeof (*pEnum);
  535. // Fill in LDAP_ENUM items
  536. //
  537. switch (uEnumType)
  538. {
  539. case WM_ILS_ENUM_CLIENTINFOS:
  540. BuildEnumClientInfos (pEnum, pEnumList);
  541. break;
  542. #ifdef ENABLE_MEETING_PLACE
  543. case WM_ILS_ENUM_MEETINGINFOS:
  544. BuildEnumMtgInfos (pEnum, pEnumList);
  545. break;
  546. #endif
  547. default:
  548. BuildEnumObjectNames (pEnum, pEnumList);
  549. break;
  550. }
  551. MyAssert (hrServer == S_OK);
  552. MyExit:
  553. // Free the temporary cache
  554. //
  555. if (pEnumList != NULL)
  556. {
  557. switch (uEnumType)
  558. {
  559. case WM_ILS_ENUM_CLIENTINFOS:
  560. for (i = 0; i < pEnumList->cItems; i++)
  561. {
  562. CLIENT_INFO_ATTRS *p = (CLIENT_INFO_ATTRS *)
  563. (&(pEnumList->bData[0]) + i * cbEntrySize);
  564. // Free standard attributes
  565. //
  566. FreeStdAttrCache (&(p->ClientInfo.apszStdAttrValues[0]), COUNT_ENUM_DIR_CLIENT_INFO);
  567. // Free extended attributes
  568. //
  569. FreeAttrPairArrayCache (&(p->Attrs.aPairs[0]), pInfo->cAnyAttrs);
  570. }
  571. break;
  572. #ifdef ENABLE_MEETING_PLACE
  573. case WM_ILS_ENUM_MEETINGINFOS:
  574. for (i = 0; i < pEnumList->cItems; i++)
  575. {
  576. MTG_INFO_ATTRS *p = (MTG_INFO_ATTRS *)
  577. (&(pEnumList->bData[0]) + i * cbEntrySize);
  578. // Free standard attributes
  579. //
  580. FreeStdAttrCache (&(p->MtgInfo.apszStdAttrValues[0]), COUNT_ENUM_DIRMTGINFO);
  581. // Free extended attributes
  582. //
  583. FreeAttrPairArrayCache (&(p->Attrs.aPairs[0]), pInfo->cAnyAttrs);
  584. }
  585. break;
  586. #endif
  587. default:
  588. for (i = 0; i < pEnumList->cItems; i++)
  589. {
  590. if (appszObjectNames[i] != NULL)
  591. ldap_value_free (appszObjectNames[i]);
  592. }
  593. break;
  594. }
  595. MemFree (pEnumList);
  596. } // if
  597. // Clean up if failure
  598. //
  599. if (hrServer != S_OK)
  600. {
  601. // Special treatment of enum termination for wldap32.dll
  602. //
  603. if (hrServer == ILS_E_PARAMETER)
  604. {
  605. MemFree (pEnum);
  606. pEnum = NULL; // enum termination
  607. }
  608. else
  609. {
  610. // Make sure we have at least LDAP_ENUM buffer to return
  611. //
  612. if (pEnum != NULL)
  613. ZeroMemory (pEnum, sizeof (*pEnum));
  614. else
  615. pEnum = (LDAP_ENUM *) MemAlloc (sizeof (LDAP_ENUM));
  616. // Set up the LDAP_ENUM info
  617. //
  618. if (pEnum != NULL)
  619. {
  620. pEnum->uSize = sizeof (*pEnum);
  621. pEnum->hResult = hrServer;
  622. }
  623. }
  624. // Force to delete this pending item
  625. //
  626. cEntries = 0;
  627. }
  628. // Post a message to the com layer of this enum result
  629. //
  630. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) pEnum);
  631. return (cEntries == 0);
  632. }
  633. BOOL
  634. NotifyEnumClients (
  635. HRESULT hrServer,
  636. SP_CResponse *pItem )
  637. {
  638. return NotifyEnumX (WM_ILS_ENUM_CLIENTS,
  639. hrServer,
  640. pItem,
  641. STR_CLIENT_CN);
  642. }
  643. BOOL
  644. NotifyEnumClientInfos (
  645. HRESULT hrServer,
  646. SP_CResponse *pItem )
  647. {
  648. return NotifyEnumX (WM_ILS_ENUM_CLIENTINFOS,
  649. hrServer,
  650. pItem,
  651. NULL);
  652. }
  653. BOOL NotifyEnumProts ( HRESULT hrServer, SP_CResponse *pItem )
  654. {
  655. MyAssert (pItem != NULL);
  656. // Clean up locals
  657. //
  658. LDAP_ENUM *pEnum = NULL;
  659. TCHAR **apszProtNames = NULL;
  660. // Get the pending info
  661. //
  662. RESP_INFO *pInfo = pItem->GetRespInfo ();
  663. MyAssert (pInfo != NULL);
  664. // If error, simply report the error
  665. //
  666. if (hrServer != S_OK)
  667. goto MyExit;
  668. // Get the ldap result
  669. //
  670. LDAPMessage *pLdapMsg;
  671. pLdapMsg = pItem->GetResult ();
  672. MyAssert (pLdapMsg != NULL);
  673. if (pLdapMsg == NULL)
  674. {
  675. MyAssert (FALSE);
  676. hrServer = ILS_E_POINTER;
  677. goto MyExit;
  678. }
  679. // Get ld
  680. //
  681. LDAP *ld;
  682. ld = pItem->GetLd ();
  683. if (ld == NULL)
  684. {
  685. MyAssert (FALSE);
  686. hrServer = ILS_E_HANDLE;
  687. goto MyExit;
  688. }
  689. // Get the array
  690. //
  691. apszProtNames = my_ldap_get_values (ld, pLdapMsg, STR_PROT_NAME);
  692. if (apszProtNames == NULL)
  693. {
  694. hrServer = ILS_E_NO_SUCH_OBJECT;
  695. goto MyExit;
  696. }
  697. // Initialize minimal info size
  698. //
  699. ULONG cbEnumList;
  700. cbEnumList = sizeof (LDAP_ENUM) + // the minimal info
  701. sizeof (TCHAR); // the last null terminator
  702. // Let's see how many strings in the array
  703. //
  704. ULONG cNames;
  705. for (cNames = 0; apszProtNames[cNames] != NULL; cNames++)
  706. {
  707. cbEnumList += (lstrlen (apszProtNames[cNames]) + 1) * sizeof (TCHAR);
  708. }
  709. // Allocate the enum structure
  710. //
  711. pEnum = (LDAP_ENUM *) MemAlloc (cbEnumList);
  712. if (pEnum == NULL)
  713. {
  714. hrServer = ILS_E_MEMORY;
  715. goto MyExit;
  716. }
  717. // Fill in header
  718. //
  719. pEnum->uSize = sizeof (*pEnum);
  720. pEnum->hResult = hrServer;
  721. pEnum->cItems = cNames;
  722. pEnum->uOffsetItems = sizeof (*pEnum);
  723. // Fill in name strings
  724. //
  725. ULONG i;
  726. TCHAR *pszName;
  727. pszName = (TCHAR *) (pEnum + 1);
  728. for (i = 0; i < cNames; i++)
  729. {
  730. My_lstrcpy (pszName, apszProtNames[i]);
  731. pszName += lstrlen (pszName) + 1;
  732. }
  733. MyAssert (hrServer == S_OK);
  734. MyExit:
  735. // Free the array if allocated
  736. //
  737. if (apszProtNames != NULL)
  738. ldap_value_free (apszProtNames);
  739. // Post messages back to the COM layer
  740. //
  741. if (hrServer != S_OK)
  742. {
  743. // Make sure we have at least LDAP_ENUM buffer to return
  744. //
  745. if (pEnum != NULL)
  746. ZeroMemory (pEnum, sizeof (*pEnum));
  747. else
  748. pEnum = (LDAP_ENUM *) MemAlloc (sizeof (LDAP_ENUM));
  749. // Set up the LDAP_ENUM info
  750. //
  751. if (pEnum != NULL)
  752. {
  753. pEnum->uSize = sizeof (*pEnum);
  754. pEnum->hResult = hrServer;
  755. }
  756. }
  757. // Post a message to the com layer of this enum result
  758. //
  759. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) pEnum);
  760. // Terminate enumeration if success
  761. //
  762. if (hrServer == S_OK)
  763. {
  764. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) NULL);
  765. }
  766. // Destroy this pending item
  767. //
  768. return TRUE;
  769. }
  770. #ifdef ENABLE_MEETING_PLACE
  771. BOOL NotifyEnumMtgs ( HRESULT hrServer, SP_CResponse *pItem )
  772. {
  773. return NotifyEnumX (WM_ILS_ENUM_MEETINGS,
  774. hrServer,
  775. pItem,
  776. STR_MTG_NAME);
  777. }
  778. #endif
  779. #ifdef ENABLE_MEETING_PLACE
  780. BOOL NotifyEnumMtgInfos ( HRESULT hrServer, SP_CResponse *pItem )
  781. {
  782. return NotifyEnumX (WM_ILS_ENUM_MEETINGINFOS,
  783. hrServer,
  784. pItem,
  785. NULL);
  786. }
  787. #endif
  788. #ifdef ENABLE_MEETING_PLACE
  789. BOOL NotifyEnumAttendees ( HRESULT hrServer, SP_CResponse *pItem )
  790. {
  791. MyAssert (pItem != NULL);
  792. // Get pending info
  793. //
  794. RESP_INFO *pInfo = pItem->GetRespInfo ();
  795. MyAssert (pInfo != NULL);
  796. // Initialize minimal info
  797. //
  798. LDAP_ENUM *pEnum = NULL;
  799. // If error, simply report the error
  800. //
  801. if (hrServer != S_OK)
  802. goto MyExit;
  803. // Get the ldap result
  804. //
  805. LDAPMessage *pLdapMsg;
  806. pLdapMsg = pItem->GetResult ();
  807. if (pLdapMsg == NULL)
  808. {
  809. MyAssert (FALSE);
  810. hrServer = ILS_E_POINTER;
  811. goto MyExit;
  812. }
  813. // Get ld
  814. //
  815. LDAP *ld;
  816. ld = pItem->GetLd ();
  817. if (ld == NULL)
  818. {
  819. MyAssert (FALSE);
  820. hrServer = ILS_E_HANDLE;
  821. goto MyExit;
  822. }
  823. // Initialize the total size of LDAP_ENUM
  824. //
  825. ULONG cbTotalSize;
  826. cbTotalSize = sizeof (LDAP_ENUM) + // the minimal info
  827. sizeof (TCHAR); // the last null terminator
  828. // Get the first entry that we care about
  829. //
  830. LDAPMessage *pEntry;
  831. pEntry = ldap_first_entry (ld, pLdapMsg);
  832. if (pEntry == NULL)
  833. {
  834. MyAssert (FALSE);
  835. hrServer = ILS_E_MEMORY;
  836. goto MyExit;
  837. }
  838. // Get the Members attribute
  839. //
  840. ULONG cItems;
  841. cItems = 0;
  842. TCHAR **apszMembers;
  843. apszMembers = my_ldap_get_values (ld, pEntry, STR_MTG_MEMBERS);
  844. if (apszMembers != NULL)
  845. {
  846. // Find out how many attendees
  847. //
  848. for (TCHAR **ppsz = apszMembers; *ppsz != NULL; ppsz++)
  849. {
  850. cItems++;
  851. cbTotalSize += (lstrlen (*ppsz) + 1) * sizeof (TCHAR);
  852. }
  853. }
  854. // Allocate the returned LDAP_ENUM structure
  855. //
  856. pEnum = (LDAP_ENUM *) MemAlloc (cbTotalSize);
  857. if (pEnum == NULL)
  858. {
  859. // Fails probably due to insane cbTotalSize
  860. //
  861. MyAssert (FALSE);
  862. hrServer = ILS_E_MEMORY;
  863. goto MyExit;
  864. }
  865. // Fill in LDAP_ENUM common fields
  866. //
  867. pEnum->uSize = sizeof (*pEnum);
  868. pEnum->hResult = hrServer;
  869. pEnum->cItems = cItems;
  870. pEnum->uOffsetItems = sizeof (*pEnum);
  871. // Fill in LDAP_ENUM items
  872. //
  873. TCHAR *pszDst;
  874. ULONG i;
  875. pszDst = (TCHAR *) (pEnum + 1);
  876. for (i = 0; i < cItems; i++)
  877. {
  878. lstrcpy (pszDst, apszMembers[i]);
  879. pszDst += lstrlen (pszDst) + 1;
  880. }
  881. MyAssert (hrServer == S_OK);
  882. MyExit:
  883. // Clean up if failure
  884. //
  885. if (hrServer != S_OK)
  886. {
  887. // Make sure we have at least LDAP_ENUM buffer to return
  888. //
  889. if (pEnum != NULL)
  890. ZeroMemory (pEnum, sizeof (*pEnum));
  891. else
  892. pEnum = (LDAP_ENUM *) MemAlloc (sizeof (LDAP_ENUM));
  893. // Fill in the minimal info
  894. //
  895. if (pEnum != NULL)
  896. {
  897. pEnum->uSize = sizeof (*pEnum);
  898. pEnum->hResult = hrServer;
  899. }
  900. }
  901. // Post a message to the com layer of this enum result
  902. //
  903. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) pEnum);
  904. // Delete this pending item
  905. //
  906. return TRUE;
  907. }
  908. #endif // ENABLE_MEETING_PLACE
  909. VOID CacheEnumClientInfoAttr (
  910. CLIENT_INFO_ATTRS *puia,
  911. TCHAR *pszAttrName,
  912. TCHAR **ppszAttrValue )
  913. {
  914. ULONG i;
  915. // See if this attribute is arbitrary?
  916. //
  917. if (IlsIsAnyAttrName (pszAttrName) != NULL)
  918. {
  919. // Deal with extended attributes
  920. //
  921. for (i = 0; i < puia->Attrs.cMaxAttrs; i++)
  922. {
  923. if (My_lstrcmpi (pszAttrName, puia->Attrs.aPairs[i].pszName) == 0)
  924. {
  925. puia->Attrs.aPairs[i].pszValue = (TCHAR *) ppszAttrValue;
  926. break;
  927. }
  928. }
  929. }
  930. else
  931. {
  932. // Deal with standard attributes
  933. //
  934. for (i = 0; i < COUNT_ENUM_DIR_CLIENT_INFO; i++)
  935. {
  936. if (My_lstrcmpi (pszAttrName, c_apszClientStdAttrNames[i]) == 0)
  937. {
  938. puia->ClientInfo.apszStdAttrValues[i] = (TCHAR *) ppszAttrValue;
  939. break;
  940. }
  941. }
  942. }
  943. }
  944. #ifdef ENABLE_MEETING_PLACE
  945. VOID CacheEnumMtgInfoAttr (
  946. MTG_INFO_ATTRS *pmia,
  947. TCHAR *pszAttrName,
  948. TCHAR **ppszAttrValue )
  949. {
  950. ULONG i;
  951. // See if this attribute is arbitrary?
  952. //
  953. if (IlsIsAnyAttrName (pszAttrName) != NULL)
  954. {
  955. // Deal with extended attributes
  956. //
  957. for (i = 0; i < pmia->Attrs.cMaxAttrs; i++)
  958. {
  959. if (My_lstrcmpi (pszAttrName, pmia->Attrs.aPairs[i].pszName) == 0)
  960. {
  961. pmia->Attrs.aPairs[i].pszValue = (TCHAR *) ppszAttrValue;
  962. break;
  963. }
  964. }
  965. }
  966. else
  967. {
  968. // Deal with standard attributes
  969. //
  970. for (i = 0; i < COUNT_ENUM_DIRMTGINFO; i++)
  971. {
  972. if (My_lstrcmpi (pszAttrName, c_apszMtgStdAttrNames[i]) == 0)
  973. {
  974. pmia->MtgInfo.apszStdAttrValues[i] = (TCHAR *) ppszAttrValue;
  975. break;
  976. }
  977. }
  978. }
  979. }
  980. #endif // ENABLE_MEETING_PLACE
  981. HRESULT CacheEnumInfos (
  982. ULONG uNotifyMsg,
  983. LDAP *ld,
  984. LDAPMessage *pEntry,
  985. VOID *p )
  986. {
  987. MyAssert (ld != NULL);
  988. MyAssert (pEntry != NULL);
  989. MyAssert (p != NULL);
  990. struct berelement *pContext = NULL;
  991. // Examine the first attribute
  992. //
  993. TCHAR *pszAttrName = ldap_first_attribute (ld, pEntry, &pContext);
  994. TCHAR **ppszAttrValue = ldap_get_values (ld, pEntry, pszAttrName);
  995. if (ppszAttrValue == NULL)
  996. return ILS_E_MEMORY;
  997. // Cache the first attribute
  998. //
  999. switch (uNotifyMsg)
  1000. {
  1001. case WM_ILS_ENUM_CLIENTINFOS:
  1002. CacheEnumClientInfoAttr ( (CLIENT_INFO_ATTRS *) p,
  1003. pszAttrName, ppszAttrValue);
  1004. break;
  1005. #ifdef ENABLE_MEETING_PLACE
  1006. case WM_ILS_ENUM_MEETINGINFOS:
  1007. CacheEnumMtgInfoAttr ( (MTG_INFO_ATTRS *) p,
  1008. pszAttrName, ppszAttrValue);
  1009. break;
  1010. #endif
  1011. default:
  1012. MyAssert (FALSE);
  1013. break;
  1014. }
  1015. // Step through the others
  1016. //
  1017. while ((pszAttrName = ldap_next_attribute (ld, pEntry, pContext))
  1018. != NULL)
  1019. {
  1020. // Examine the other attributes one by one
  1021. //
  1022. ppszAttrValue = ldap_get_values (ld, pEntry, pszAttrName);
  1023. if (ppszAttrValue == NULL)
  1024. return ILS_E_MEMORY;
  1025. // Cache the other attributes one by one
  1026. //
  1027. switch (uNotifyMsg)
  1028. {
  1029. case WM_ILS_ENUM_CLIENTINFOS:
  1030. CacheEnumClientInfoAttr ( (CLIENT_INFO_ATTRS *) p,
  1031. pszAttrName, ppszAttrValue);
  1032. break;
  1033. #ifdef ENABLE_MEETING_PLACE
  1034. case WM_ILS_ENUM_MEETINGINFOS:
  1035. CacheEnumMtgInfoAttr ( (MTG_INFO_ATTRS *) p,
  1036. pszAttrName, ppszAttrValue);
  1037. break;
  1038. #endif
  1039. default:
  1040. MyAssert (FALSE);
  1041. break;
  1042. }
  1043. }
  1044. return S_OK;
  1045. }
  1046. VOID
  1047. BuildEnumObjectNames (
  1048. LDAP_ENUM *pEnum,
  1049. ENUM_LIST *pEnumList )
  1050. {
  1051. MyAssert (pEnum != NULL);
  1052. MyAssert (pEnumList != NULL);
  1053. ULONG cEntries = pEnum->cItems;
  1054. // appszObjectNames are an array of names from server
  1055. //
  1056. TCHAR *pszName = (TCHAR *) (pEnum + 1);
  1057. TCHAR ***appszObjectNames = (TCHAR ***) &(pEnumList->bData[0]);
  1058. for (ULONG i = 0; i < cEntries; i++)
  1059. {
  1060. TCHAR **ppsz = appszObjectNames[i];
  1061. if (ppsz != NULL && *ppsz != NULL)
  1062. {
  1063. My_lstrcpy (pszName, *ppsz);
  1064. pszName += lstrlen (pszName) + 1;
  1065. }
  1066. else
  1067. {
  1068. *pszName++ = TEXT ('\0'); // empty strings
  1069. }
  1070. }
  1071. }
  1072. VOID
  1073. BuildEnumClientInfos (
  1074. LDAP_ENUM *pEnum,
  1075. ENUM_LIST *pEnumList )
  1076. {
  1077. MyAssert (pEnum != NULL);
  1078. MyAssert (pEnumList != NULL);
  1079. ULONG i, j;
  1080. ULONG cEntries = pEnumList->cItems;
  1081. ULONG cbEntrySize = pEnumList->cbEntrySize;
  1082. LDAP_CLIENTINFO *plci = (LDAP_CLIENTINFO *) (pEnum + 1);
  1083. TCHAR *pszStringBuffer = (TCHAR *) (plci + cEntries);
  1084. TCHAR **ppsz;
  1085. CLIENT_INFO_ATTRS *p;
  1086. ULONG cAttrs;
  1087. // Loop through all entries
  1088. //
  1089. for (i = 0; i < cEntries; i++, plci++)
  1090. {
  1091. // Get to cached structure
  1092. //
  1093. p = (CLIENT_INFO_ATTRS *) (&(pEnumList->bData[0]) + i * cbEntrySize);
  1094. // Set the size of LDAP_USERINFO
  1095. //
  1096. plci->uSize = sizeof (*plci);
  1097. // Copy the User Name if needed
  1098. //
  1099. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CN];
  1100. if (ppsz != NULL)
  1101. {
  1102. plci->uOffsetCN = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1103. My_lstrcpy (pszStringBuffer, *ppsz);
  1104. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1105. }
  1106. // Copy the First Name if needed
  1107. //
  1108. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_FIRST_NAME];
  1109. if (ppsz != NULL)
  1110. {
  1111. plci->uOffsetFirstName = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1112. My_lstrcpy (pszStringBuffer, *ppsz);
  1113. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1114. }
  1115. // Copy the Last Name if needed
  1116. //
  1117. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_LAST_NAME];
  1118. if (ppsz != NULL)
  1119. {
  1120. plci->uOffsetLastName = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1121. My_lstrcpy (pszStringBuffer, *ppsz);
  1122. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1123. }
  1124. // Copy the Email Name if needed
  1125. //
  1126. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_EMAIL_NAME];
  1127. if (ppsz != NULL)
  1128. {
  1129. plci->uOffsetEMailName = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1130. My_lstrcpy (pszStringBuffer, *ppsz);
  1131. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1132. }
  1133. // Copy the City Name if needed
  1134. //
  1135. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CITY_NAME];
  1136. if (ppsz != NULL)
  1137. {
  1138. plci->uOffsetCityName = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1139. My_lstrcpy (pszStringBuffer, *ppsz);
  1140. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1141. }
  1142. // Copy the Country Name if needed
  1143. //
  1144. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_C];
  1145. if (ppsz != NULL)
  1146. {
  1147. plci->uOffsetCountryName = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1148. My_lstrcpy (pszStringBuffer, *ppsz);
  1149. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1150. }
  1151. // Copy the Comment Name if needed
  1152. //
  1153. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_COMMENT];
  1154. if (ppsz != NULL)
  1155. {
  1156. plci->uOffsetComment = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1157. My_lstrcpy (pszStringBuffer, *ppsz);
  1158. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1159. }
  1160. // Copy the IP Address if needed
  1161. //
  1162. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_IP_ADDRESS];
  1163. if (ppsz != NULL)
  1164. {
  1165. plci->uOffsetIPAddress = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1166. GetIPAddressString (pszStringBuffer, GetStringLong (*ppsz));
  1167. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1168. }
  1169. // Copy the Flags if needed
  1170. //
  1171. ppsz = (TCHAR **) p->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_FLAGS];
  1172. if (ppsz != NULL)
  1173. {
  1174. plci->dwFlags = (*ppsz != NULL) ? GetStringLong (*ppsz) :
  1175. INVALID_USER_FLAGS;
  1176. }
  1177. // Copy extended attributes if needed
  1178. //
  1179. plci->cAttrsReturned = cAttrs = p->Attrs.cMaxAttrs;
  1180. plci->uOffsetAttrsReturned = (ULONG)((ULONG_PTR) pszStringBuffer - (ULONG_PTR) plci);
  1181. for (j = 0; j < cAttrs; j++)
  1182. {
  1183. // Extended attribute name
  1184. //
  1185. My_lstrcpy (pszStringBuffer, IlsSkipAnyAttrNamePrefix (
  1186. (const TCHAR *) p->Attrs.aPairs[j].pszName));
  1187. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1188. // Extended attribute value
  1189. //
  1190. ppsz = (TCHAR **) p->Attrs.aPairs[j].pszValue;
  1191. if (ppsz != NULL)
  1192. {
  1193. My_lstrcpy (pszStringBuffer, *ppsz);
  1194. }
  1195. else
  1196. {
  1197. ASSERT(FALSE);
  1198. }
  1199. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1200. } // for j
  1201. } // for i
  1202. }
  1203. #ifdef ENABLE_MEETING_PLACE
  1204. VOID BuildEnumMtgInfos (
  1205. LDAP_ENUM *pEnum,
  1206. ENUM_LIST *pEnumList )
  1207. {
  1208. MyAssert (pEnum != NULL);
  1209. MyAssert (pEnumList != NULL);
  1210. ULONG i, j;
  1211. ULONG cEntries = pEnumList->cItems;
  1212. ULONG cbEntrySize = pEnumList->cbEntrySize;
  1213. LDAP_MEETINFO *plmi = (LDAP_MEETINFO *) (pEnum + 1);
  1214. TCHAR *pszStringBuffer = (TCHAR *) (plmi + cEntries);
  1215. TCHAR **ppsz;
  1216. MTG_INFO_ATTRS *p;
  1217. ULONG cAttrs;
  1218. // Loop through all entries
  1219. //
  1220. for (i = 0; i < cEntries; i++, plmi++)
  1221. {
  1222. // Get to the cache structure
  1223. //
  1224. p = (MTG_INFO_ATTRS *) (&(pEnumList->bData[0]) + i * cbEntrySize);
  1225. // Set the size of LDAP_MEETINFO
  1226. //
  1227. plmi->uSize = sizeof (*plmi);
  1228. // Copy the Meeting Name if needed
  1229. //
  1230. ppsz = (TCHAR **) p->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_CN];
  1231. if (ppsz != NULL)
  1232. {
  1233. plmi->uOffsetMeetingPlaceID = (ULONG) pszStringBuffer - (ULONG) plmi;
  1234. My_lstrcpy (pszStringBuffer, *ppsz);
  1235. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1236. }
  1237. // Copy the Meeting Type if needed
  1238. //
  1239. ppsz = (TCHAR **) p->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_MTG_TYPE];
  1240. if (ppsz != NULL)
  1241. {
  1242. plmi->lMeetingPlaceType = (*ppsz != NULL) ? GetStringLong (*ppsz) :
  1243. INVALID_MEETING_TYPE;
  1244. }
  1245. // Copy the Attendee Type if needed
  1246. //
  1247. ppsz = (TCHAR **) p->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_MEMBER_TYPE];
  1248. if (ppsz != NULL)
  1249. {
  1250. plmi->lAttendeeType = (*ppsz != NULL) ? GetStringLong (*ppsz) :
  1251. INVALID_ATTENDEE_TYPE;
  1252. }
  1253. // Copy the Description if needed
  1254. //
  1255. ppsz = (TCHAR **) p->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_DESCRIPTION];
  1256. if (ppsz != NULL)
  1257. {
  1258. plmi->uOffsetDescription = (ULONG) pszStringBuffer - (ULONG) plmi;
  1259. My_lstrcpy (pszStringBuffer, *ppsz);
  1260. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1261. }
  1262. // Copy the Host Name if needed
  1263. //
  1264. ppsz = (TCHAR **) p->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_HOST_NAME];
  1265. if (ppsz != NULL)
  1266. {
  1267. plmi->uOffsetHostName = (ULONG) pszStringBuffer - (ULONG) plmi;
  1268. My_lstrcpy (pszStringBuffer, *ppsz);
  1269. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1270. }
  1271. // Copy the Host IP Address if needed
  1272. //
  1273. ppsz = (TCHAR **) p->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_IP_ADDRESS];
  1274. if (ppsz != NULL)
  1275. {
  1276. plmi->uOffsetHostIPAddress = (ULONG) pszStringBuffer - (ULONG) plmi;
  1277. GetIPAddressString (pszStringBuffer, GetStringLong (*ppsz));
  1278. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1279. }
  1280. // Copy extended attributes if needed
  1281. //
  1282. plmi->cAttrsReturned = cAttrs = p->Attrs.cMaxAttrs;
  1283. plmi->uOffsetAttrsReturned = (ULONG) pszStringBuffer - (ULONG) plmi;
  1284. for (j = 0; j < cAttrs; j++)
  1285. {
  1286. // Extended attribute name
  1287. //
  1288. My_lstrcpy (pszStringBuffer, IlsSkipAnyAttrNamePrefix (
  1289. (const TCHAR *) p->Attrs.aPairs[j].pszName));
  1290. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1291. // Extended attribute value
  1292. //
  1293. ppsz = (TCHAR **) p->Attrs.aPairs[j].pszValue;
  1294. My_lstrcpy (pszStringBuffer, *ppsz);
  1295. pszStringBuffer += lstrlen (pszStringBuffer) + 1;
  1296. } // for j
  1297. } // for i
  1298. }
  1299. #endif // ENABLE_MEETING_PLACE
  1300. VOID TotalSizeEnumObjectNames (
  1301. ULONG *pcbTotalSize,
  1302. ULONG cEntries,
  1303. TCHAR **appszObjectNames[] )
  1304. {
  1305. ULONG i, cbThisSize;
  1306. TCHAR **ppsz;
  1307. // Loop through all the entries and compute the total size
  1308. //
  1309. for (i = 0; i < cEntries; i++)
  1310. {
  1311. ppsz = appszObjectNames[i];
  1312. // Calcualte the attribute string length
  1313. //
  1314. cbThisSize = 1;
  1315. if (ppsz != NULL && *ppsz != NULL)
  1316. cbThisSize += My_lstrlen (*ppsz);
  1317. // Convert string length to string size
  1318. //
  1319. cbThisSize *= sizeof (TCHAR);
  1320. // Add up this entry size
  1321. //
  1322. // lonchanc: BUGS BUGS the size is wrong. need to figure out the exact size
  1323. *pcbTotalSize += sizeof (LDAP_CLIENTINFO) + cbThisSize;
  1324. }
  1325. }
  1326. VOID SizeEnumClientInfos (
  1327. ULONG *pcbTotalSize,
  1328. CLIENT_INFO_ATTRS *pcia )
  1329. {
  1330. ULONG i, cbThisSize;
  1331. TCHAR **ppsz;
  1332. // Add up user info header
  1333. //
  1334. *pcbTotalSize += sizeof (LDAP_CLIENTINFO);
  1335. // Add up the total size for standard attributes
  1336. //
  1337. for (i = 0; i < COUNT_ENUM_DIR_CLIENT_INFO; i++)
  1338. {
  1339. // Get the attribute value
  1340. //
  1341. ppsz = (TCHAR **) pcia->ClientInfo.apszStdAttrValues[i];
  1342. // Calcualte the attribute string length
  1343. //
  1344. cbThisSize = 1;
  1345. if (ppsz != NULL && *ppsz != NULL)
  1346. cbThisSize += My_lstrlen (*ppsz);
  1347. // Compensate the string length if it is ip address
  1348. //
  1349. if (i == ENUM_CLIENTATTR_IP_ADDRESS)
  1350. cbThisSize += 16;
  1351. // Convert string length to string size
  1352. //
  1353. cbThisSize *= sizeof (TCHAR);
  1354. // Add up this entry size
  1355. //
  1356. *pcbTotalSize += cbThisSize;
  1357. }
  1358. // Add up the total size for extended attributes
  1359. //
  1360. for (i = 0; i < pcia->Attrs.cMaxAttrs; i++)
  1361. {
  1362. // Get the extended attribute value
  1363. //
  1364. ppsz = (TCHAR **) pcia->Attrs.aPairs[i].pszValue;
  1365. // Calcualte the attribute string length
  1366. //
  1367. cbThisSize = 1;
  1368. if (ppsz != NULL && *ppsz != NULL)
  1369. cbThisSize += My_lstrlen (*ppsz);
  1370. // Get the extended attribute name
  1371. //
  1372. cbThisSize += lstrlen (IlsSkipAnyAttrNamePrefix ((const TCHAR *)
  1373. pcia->Attrs.aPairs[i].pszName)) + 1;
  1374. // Convert string length to string size
  1375. //
  1376. cbThisSize *= sizeof (TCHAR);
  1377. // Add up this entry size
  1378. //
  1379. *pcbTotalSize += cbThisSize;
  1380. }
  1381. }
  1382. #ifdef ENABLE_MEETING_PLACE
  1383. VOID SizeEnumMtgInfos (
  1384. ULONG *pcbTotalSize,
  1385. MTG_INFO_ATTRS *pmia )
  1386. {
  1387. ULONG i, cbThisSize;
  1388. TCHAR **ppsz;
  1389. // Add up meeting info header
  1390. //
  1391. *pcbTotalSize += sizeof (LDAP_MEETINFO);
  1392. // Add up the total size for standard attributes
  1393. //
  1394. for (i = 0; i < COUNT_ENUM_DIRMTGINFO; i++)
  1395. {
  1396. // Get the standard attribute value
  1397. //
  1398. ppsz = (TCHAR **) pmia->MtgInfo.apszStdAttrValues[i];
  1399. // Calcualte the attribute string length
  1400. //
  1401. cbThisSize = 1;
  1402. if (ppsz != NULL && *ppsz != NULL)
  1403. cbThisSize += My_lstrlen (*ppsz);
  1404. // Compensate the string length if it is ip address
  1405. //
  1406. if (i == ENUM_MTGATTR_IP_ADDRESS)
  1407. cbThisSize += 16;
  1408. // Convert string length to string size
  1409. //
  1410. cbThisSize *= sizeof (TCHAR);
  1411. // Add up this entry size
  1412. //
  1413. *pcbTotalSize += cbThisSize;
  1414. }
  1415. // Add up the total size for extended attributes
  1416. //
  1417. for (i = 0; i < pmia->Attrs.cMaxAttrs; i++)
  1418. {
  1419. // Get the extended attribute value
  1420. //
  1421. ppsz = (TCHAR **) pmia->Attrs.aPairs[i].pszValue;
  1422. // Calcualte the attribute string length
  1423. //
  1424. cbThisSize = 1;
  1425. if (ppsz != NULL && *ppsz != NULL)
  1426. cbThisSize += My_lstrlen (*ppsz);
  1427. // Get the extended attribute name
  1428. //
  1429. cbThisSize += lstrlen (IlsSkipAnyAttrNamePrefix ((const TCHAR *)
  1430. pmia->Attrs.aPairs[i].pszName)) + 1;
  1431. // Convert string length to string size
  1432. //
  1433. cbThisSize *= sizeof (TCHAR);
  1434. // Add up this entry size
  1435. //
  1436. *pcbTotalSize += cbThisSize;
  1437. }
  1438. }
  1439. #endif // ENABLE_MEETING_PLACE
  1440. /* =========== RESOLVE ============ */
  1441. typedef HRESULT (INFO_HANDLER) ( VOID *, const TCHAR *, const TCHAR ** );
  1442. extern HRESULT CacheResolveClientInfoAttr ( VOID *, const TCHAR *, const TCHAR ** );
  1443. extern HRESULT CacheResolveProtInfoAttr ( VOID *, const TCHAR *, const TCHAR ** );
  1444. extern HRESULT CacheResolveMtgInfoAttr ( VOID *, const TCHAR *, const TCHAR ** );
  1445. BOOL
  1446. NotifyResolveX (
  1447. HRESULT hrServer,
  1448. SP_CResponse *pItem,
  1449. VOID *pInfo,
  1450. INFO_HANDLER *pHandler )
  1451. {
  1452. MyAssert (pItem != NULL);
  1453. MyAssert (pInfo != NULL);
  1454. MyAssert (pHandler != NULL);
  1455. // Get the ldap result
  1456. //
  1457. LDAPMessage *pLdapMsg = pItem->GetResult ();
  1458. MyAssert (pLdapMsg != NULL);
  1459. if (pLdapMsg == NULL)
  1460. {
  1461. MyAssert (FALSE);
  1462. hrServer = ILS_E_POINTER;
  1463. goto MyExit;
  1464. }
  1465. // Get ld
  1466. //
  1467. LDAP *ld;
  1468. ld = pItem->GetLd ();
  1469. if (ld == NULL)
  1470. {
  1471. MyAssert (FALSE);
  1472. hrServer = ILS_E_HANDLE;
  1473. goto MyExit;
  1474. }
  1475. // Get the first entry that we care only
  1476. //
  1477. LDAPMessage *pEntry;
  1478. pEntry = ldap_first_entry (ld, pLdapMsg);
  1479. if (pEntry == NULL)
  1480. {
  1481. MyAssert (FALSE);
  1482. hrServer = ILS_E_MEMORY;
  1483. goto MyExit;
  1484. }
  1485. // Initialize wldap32.dll context
  1486. //
  1487. struct berelement *pContext;
  1488. pContext = NULL;
  1489. // Examine the first attribute
  1490. //
  1491. TCHAR *pszAttrName;
  1492. pszAttrName = ldap_first_attribute (ld, pEntry, &pContext);
  1493. if (pszAttrName == NULL)
  1494. {
  1495. MyAssert (FALSE);
  1496. hrServer = ILS_E_MEMORY;
  1497. goto MyExit;
  1498. }
  1499. TCHAR **ppszAttrVal;
  1500. ppszAttrVal = ldap_get_values (ld, pEntry, pszAttrName);
  1501. if (ppszAttrVal == NULL)
  1502. {
  1503. MyAssert (FALSE);
  1504. hrServer = ILS_E_MEMORY;
  1505. goto MyExit;
  1506. }
  1507. // Cache this attribute name (if needed) and value
  1508. //
  1509. HRESULT hr;
  1510. hr = (*pHandler) (pInfo, pszAttrName,(const TCHAR **) ppszAttrVal);
  1511. ldap_value_free (ppszAttrVal);
  1512. if (hr != S_OK)
  1513. {
  1514. hrServer = hr;
  1515. goto MyExit;
  1516. }
  1517. // Step through the other attributes
  1518. //
  1519. while ((pszAttrName = ldap_next_attribute (ld, pEntry, pContext))
  1520. != NULL)
  1521. {
  1522. ppszAttrVal = ldap_get_values (ld, pEntry, pszAttrName);
  1523. if (ppszAttrVal == NULL)
  1524. {
  1525. MyAssert (FALSE);
  1526. hrServer = ILS_E_MEMORY;
  1527. goto MyExit;
  1528. }
  1529. // Cache the other attribute names (if needed) and values
  1530. //
  1531. hr = (*pHandler) (pInfo, pszAttrName, (const TCHAR **) ppszAttrVal);
  1532. ldap_value_free (ppszAttrVal);
  1533. if (hr != S_OK)
  1534. {
  1535. hrServer = hr;
  1536. goto MyExit;
  1537. }
  1538. }
  1539. MyAssert (hrServer == S_OK);
  1540. MyExit:
  1541. return hrServer;
  1542. }
  1543. BOOL
  1544. NotifyResolveClient (
  1545. HRESULT hrServer,
  1546. SP_CResponse *pItem )
  1547. {
  1548. MyAssert (pItem != NULL);
  1549. ULONG i;
  1550. // Get the pending info
  1551. //
  1552. RESP_INFO *pInfo = pItem->GetRespInfo ();
  1553. MyAssert (pInfo != NULL);
  1554. // Initialize minimal info
  1555. //
  1556. LDAP_CLIENTINFO_RES *pClientRes = NULL;
  1557. CLIENT_INFO_ATTRS *pcia = NULL;
  1558. // If error, simply report the error
  1559. //
  1560. if (hrServer != S_OK)
  1561. goto MyExit;
  1562. // Get the ldap result
  1563. //
  1564. LDAPMessage *pLdapMsg;
  1565. pLdapMsg = pItem->GetResult ();
  1566. if (pLdapMsg == NULL)
  1567. {
  1568. MyAssert (FALSE);
  1569. goto MyExit;
  1570. }
  1571. // Get ld
  1572. //
  1573. LDAP *ld;
  1574. ld = pItem->GetLd ();
  1575. if (ld == NULL)
  1576. {
  1577. MyAssert (FALSE);
  1578. hrServer = ILS_E_HANDLE;
  1579. goto MyExit;
  1580. }
  1581. // Get the count of attributes
  1582. //
  1583. ULONG cAttrs;
  1584. cAttrs = my_ldap_count_1st_entry_attributes (ld, pLdapMsg);
  1585. if (cAttrs == 0)
  1586. {
  1587. hrServer = ILS_E_NO_MORE;
  1588. goto MyExit;
  1589. }
  1590. // Allocate result set holder
  1591. //
  1592. pcia = (CLIENT_INFO_ATTRS *) MemAlloc (
  1593. sizeof (CLIENT_INFO_ATTRS) +
  1594. cAttrs * sizeof (ATTR_PAIR));
  1595. if (pcia == NULL)
  1596. {
  1597. hrServer = ILS_E_MEMORY;
  1598. goto MyExit;
  1599. }
  1600. // Initialize result set holder
  1601. //
  1602. pcia->Attrs.cMaxAttrs = cAttrs;
  1603. // Cache resolve set
  1604. //
  1605. hrServer = NotifyResolveX ( hrServer,
  1606. pItem,
  1607. pcia,
  1608. CacheResolveClientInfoAttr);
  1609. if (hrServer != S_OK)
  1610. {
  1611. goto MyExit;
  1612. }
  1613. // Initialize the total size
  1614. //
  1615. ULONG cbTotalSize, cbThisSize;
  1616. cbTotalSize = sizeof (LDAP_CLIENTINFO_RES);
  1617. // Loop through all attributes in order to compute the total size
  1618. //
  1619. for (i = 0; i < COUNT_ENUM_RES_CLIENT_INFO; i++)
  1620. {
  1621. if (pcia->ClientInfo.apszStdAttrValues[i] != NULL)
  1622. {
  1623. // Get the string length
  1624. //
  1625. cbThisSize = My_lstrlen (pcia->ClientInfo.apszStdAttrValues[i]) + 1;
  1626. // Compensate for the ip address
  1627. //
  1628. if (i == ENUM_CLIENTATTR_IP_ADDRESS)
  1629. cbThisSize += 16;
  1630. // Convert string length to string size
  1631. //
  1632. cbThisSize *= sizeof (TCHAR);
  1633. // Add up to the total size
  1634. //
  1635. cbTotalSize += cbThisSize;
  1636. }
  1637. }
  1638. // Loop through extended attributes
  1639. //
  1640. for (i = 0; i < pcia->Attrs.cCurrAttrs; i++)
  1641. {
  1642. cbThisSize = My_lstrlen (pcia->Attrs.aPairs[i].pszName) + 1;
  1643. cbThisSize += My_lstrlen (pcia->Attrs.aPairs[i].pszValue) + 1;
  1644. cbThisSize *= sizeof (TCHAR);
  1645. cbTotalSize += cbThisSize;
  1646. }
  1647. // Allocate LDAP_USERINFO_RES structure
  1648. //
  1649. pClientRes = (LDAP_CLIENTINFO_RES *) MemAlloc (cbTotalSize);
  1650. if (pClientRes == NULL)
  1651. {
  1652. MyAssert (FALSE); // we are in deep trouble here
  1653. hrServer = ILS_E_MEMORY;
  1654. goto MyExit;
  1655. }
  1656. // Fill in common fields
  1657. //
  1658. pClientRes->uSize = sizeof (*pClientRes);
  1659. pClientRes->hResult = hrServer;
  1660. pClientRes->lci.uSize = sizeof (pClientRes->lci);
  1661. // Prepare to copy strings
  1662. //
  1663. TCHAR *pszDst, *pszSrc;
  1664. pszDst = (TCHAR *) (pClientRes + 1);
  1665. // Copy user object's standard attributes
  1666. //
  1667. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CN];
  1668. if (pszSrc != NULL)
  1669. {
  1670. pClientRes->lci.uOffsetCN = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1671. My_lstrcpy (pszDst, pszSrc);
  1672. pszDst += lstrlen (pszDst) + 1;
  1673. }
  1674. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_FIRST_NAME];
  1675. if (pszSrc != NULL)
  1676. {
  1677. pClientRes->lci.uOffsetFirstName = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1678. My_lstrcpy (pszDst, pszSrc);
  1679. pszDst += lstrlen (pszDst) + 1;
  1680. }
  1681. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_LAST_NAME];
  1682. if (pszSrc != NULL)
  1683. {
  1684. pClientRes->lci.uOffsetLastName = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1685. My_lstrcpy (pszDst, pszSrc);
  1686. pszDst += lstrlen (pszDst) + 1;
  1687. }
  1688. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_EMAIL_NAME];
  1689. if (pszSrc != NULL)
  1690. {
  1691. pClientRes->lci.uOffsetEMailName = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1692. My_lstrcpy (pszDst, pszSrc);
  1693. pszDst += lstrlen (pszDst) + 1;
  1694. }
  1695. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_CITY_NAME];
  1696. if (pszSrc != NULL)
  1697. {
  1698. pClientRes->lci.uOffsetCityName = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1699. My_lstrcpy (pszDst, pszSrc);
  1700. pszDst += lstrlen (pszDst) + 1;
  1701. }
  1702. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_C];
  1703. if (pszSrc != NULL)
  1704. {
  1705. pClientRes->lci.uOffsetCountryName = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1706. My_lstrcpy (pszDst, pszSrc);
  1707. pszDst += lstrlen (pszDst) + 1;
  1708. }
  1709. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_COMMENT];
  1710. if (pszSrc != NULL)
  1711. {
  1712. pClientRes->lci.uOffsetComment = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1713. My_lstrcpy (pszDst, pszSrc);
  1714. pszDst += lstrlen (pszDst) + 1;
  1715. }
  1716. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_IP_ADDRESS];
  1717. if (pszSrc != NULL)
  1718. {
  1719. pClientRes->lci.uOffsetIPAddress = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1720. GetIPAddressString (pszDst, GetStringLong (pszSrc));
  1721. pszDst += lstrlen (pszDst) + 1;
  1722. }
  1723. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_FLAGS];
  1724. if (pszSrc != NULL)
  1725. {
  1726. pClientRes->lci.dwFlags = (pszSrc != NULL)? GetStringLong (pszSrc) :
  1727. INVALID_USER_FLAGS;
  1728. }
  1729. // Copy app object's standard attributes
  1730. //
  1731. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_NAME];
  1732. if (pszSrc != NULL)
  1733. {
  1734. pClientRes->lci.uOffsetAppName = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1735. My_lstrcpy (pszDst, pszSrc);
  1736. pszDst += lstrlen (pszDst) + 1;
  1737. }
  1738. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_MIME_TYPE];
  1739. if (pszSrc != NULL)
  1740. {
  1741. pClientRes->lci.uOffsetAppMimeType = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1742. My_lstrcpy (pszDst, pszSrc);
  1743. pszDst += lstrlen (pszDst) + 1;
  1744. }
  1745. pszSrc = pcia->ClientInfo.apszStdAttrValues[ENUM_CLIENTATTR_APP_GUID];
  1746. if (MyIsGoodString (pszSrc))
  1747. {
  1748. GetStringGuid (pszSrc, &(pClientRes->lci.AppGuid));
  1749. }
  1750. else
  1751. {
  1752. ZeroMemory (&(pClientRes->lci.AppGuid), sizeof (pClientRes->lci.AppGuid));
  1753. }
  1754. // Copy app object's extended attributes
  1755. //
  1756. pClientRes->lci.cAttrsReturned = pcia->Attrs.cCurrAttrs;
  1757. if (pClientRes->lci.cAttrsReturned > 0)
  1758. {
  1759. pClientRes->lci.uOffsetAttrsReturned = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pClientRes->lci));
  1760. for (i = 0; i < pcia->Attrs.cCurrAttrs; i++)
  1761. {
  1762. My_lstrcpy (pszDst, pcia->Attrs.aPairs[i].pszName);
  1763. pszDst += lstrlen (pszDst) + 1;
  1764. My_lstrcpy (pszDst, pcia->Attrs.aPairs[i].pszValue);
  1765. pszDst += lstrlen (pszDst) + 1;
  1766. }
  1767. }
  1768. MyAssert (hrServer == S_OK);
  1769. MyExit:
  1770. // Free temporary result set holder
  1771. //
  1772. if (pcia != NULL)
  1773. {
  1774. // Free standard attributes
  1775. //
  1776. for (INT i = 0; i < COUNT_ENUM_CLIENT_INFO; i++)
  1777. {
  1778. MemFree (pcia->ClientInfo.apszStdAttrValues[i]);
  1779. }
  1780. // Free arbitrary attributes
  1781. //
  1782. for (ULONG j = 0; j < pcia->Attrs.cCurrAttrs; j++)
  1783. {
  1784. MemFree (pcia->Attrs.aPairs[j].pszName);
  1785. MemFree (pcia->Attrs.aPairs[j].pszValue);
  1786. }
  1787. // Free the holder itself
  1788. //
  1789. MemFree (pcia);
  1790. }
  1791. // Clean up the return structure if failure
  1792. //
  1793. if (hrServer != S_OK)
  1794. {
  1795. // Make sure we have a return structure
  1796. //
  1797. if (pClientRes != NULL)
  1798. ZeroMemory (pClientRes, sizeof (*pClientRes));
  1799. else
  1800. pClientRes = (LDAP_CLIENTINFO_RES *) MemAlloc (sizeof (LDAP_CLIENTINFO_RES));
  1801. // Fill in the minimal info
  1802. //
  1803. if (pClientRes != NULL)
  1804. {
  1805. pClientRes->uSize = sizeof (*pClientRes);
  1806. pClientRes->hResult = hrServer;
  1807. }
  1808. }
  1809. // Post a message to the com layer
  1810. //
  1811. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) pClientRes);
  1812. // Delete this pending item
  1813. //
  1814. return TRUE;
  1815. }
  1816. HRESULT CacheResolveClientInfoAttr (
  1817. VOID *pInfo,
  1818. const TCHAR *pszAttrName,
  1819. const TCHAR **ppszAttrVal )
  1820. {
  1821. MyAssert (pInfo != NULL);
  1822. MyAssert (pszAttrName != NULL);
  1823. // Shorthand meeting info pointer
  1824. //
  1825. CLIENT_INFO_ATTRS *pcia = (CLIENT_INFO_ATTRS *) pInfo;
  1826. // See if this attribute is arbitrary?
  1827. //
  1828. const TCHAR *pszRealAnyName = IlsIsAnyAttrName (pszAttrName);
  1829. if (pszRealAnyName != NULL)
  1830. {
  1831. MyAssert (pcia->Attrs.cCurrAttrs < pcia->Attrs.cMaxAttrs);
  1832. // Duplicate the name
  1833. //
  1834. pcia->Attrs.aPairs[pcia->Attrs.cCurrAttrs].pszName =
  1835. My_strdup (pszRealAnyName);
  1836. // Duplicate the value
  1837. // BUGS: we should avoid duplicate the string here (cf. enum-user-infos)
  1838. //
  1839. if (ppszAttrVal != NULL)
  1840. {
  1841. pcia->Attrs.aPairs[pcia->Attrs.cCurrAttrs++].pszValue =
  1842. My_strdup (*ppszAttrVal);
  1843. }
  1844. else
  1845. {
  1846. // ILS server bug or wldap32.dll bug
  1847. //
  1848. MyAssert (FALSE);
  1849. }
  1850. }
  1851. else
  1852. {
  1853. // Loop through all standard attributes
  1854. //
  1855. for (INT i = 0; i < COUNT_ENUM_RES_CLIENT_INFO; i++)
  1856. {
  1857. // Figure out what attribute it is
  1858. //
  1859. if (My_lstrcmpi (c_apszClientStdAttrNames[i], pszAttrName) == 0)
  1860. {
  1861. // Free the previously allocated value if any
  1862. //
  1863. MemFree (pcia->ClientInfo.apszStdAttrValues[i]);
  1864. // Duplicate the value
  1865. // BUGS: we should avoid duplicate the string here (cf. enum-user-infos)
  1866. //
  1867. if (ppszAttrVal != NULL)
  1868. {
  1869. pcia->ClientInfo.apszStdAttrValues[i] = DuplicateGoodString (*ppszAttrVal);
  1870. }
  1871. else
  1872. {
  1873. // ILS server bug or wldap32.dll bug
  1874. //
  1875. MyAssert (FALSE);
  1876. }
  1877. break;
  1878. }
  1879. }
  1880. }
  1881. return S_OK;
  1882. }
  1883. typedef struct
  1884. {
  1885. PROT_INFO ProtInfo;
  1886. TCHAR *pszProtNameToResolve;
  1887. BOOL fFindIndex;
  1888. LONG nIndex;
  1889. }
  1890. PROT_INFO_EX;
  1891. enum { INVALID_INDEX = -1 };
  1892. BOOL NotifyResolveProt ( HRESULT hrServer, SP_CResponse *pItem )
  1893. {
  1894. MyAssert (pItem != NULL);
  1895. // Get the pending info
  1896. //
  1897. RESP_INFO *pInfo = pItem->GetRespInfo ();
  1898. MyAssert (pInfo != NULL);
  1899. // Initialize minimal info
  1900. //
  1901. LDAP_PROTINFO_RES *pProtRes = NULL;
  1902. PROT_INFO_EX *ppi = NULL;
  1903. // If error, simply report the error
  1904. //
  1905. if (hrServer != S_OK)
  1906. goto MyExit;
  1907. // Allocate result holder
  1908. //
  1909. ppi = (PROT_INFO_EX *) MemAlloc (sizeof (PROT_INFO_EX));
  1910. if (ppi == NULL)
  1911. {
  1912. hrServer = ILS_E_MEMORY;
  1913. goto MyExit;
  1914. }
  1915. // Cache the protocol name to resolve
  1916. //
  1917. MyAssert (pInfo->pszProtNameToResolve != NULL);
  1918. ppi->pszProtNameToResolve = pInfo->pszProtNameToResolve;
  1919. ppi->nIndex = INVALID_INDEX;
  1920. // Call the common routine to find the index
  1921. //
  1922. ppi->fFindIndex = TRUE;
  1923. hrServer = NotifyResolveX (hrServer, pItem, ppi, CacheResolveProtInfoAttr);
  1924. if (hrServer != S_OK)
  1925. goto MyExit;
  1926. // Check to see if we found the index
  1927. //
  1928. if (ppi->nIndex == INVALID_INDEX)
  1929. {
  1930. hrServer = ILS_E_NO_SUCH_OBJECT;
  1931. goto MyExit;
  1932. }
  1933. // Call the common routine AGAIN to save attribute values
  1934. //
  1935. ppi->fFindIndex = FALSE;
  1936. hrServer = NotifyResolveX (hrServer, pItem, ppi, CacheResolveProtInfoAttr);
  1937. if (hrServer != S_OK)
  1938. goto MyExit;
  1939. // Initialize the size
  1940. //
  1941. ULONG cbTotalSize, cbThisSize;
  1942. cbTotalSize = sizeof (LDAP_PROTINFO_RES);
  1943. // Loop through standard attrs
  1944. //
  1945. ULONG i;
  1946. for (i = 0; i < COUNT_ENUM_PROTATTR; i++)
  1947. {
  1948. if (ppi->ProtInfo.apszStdAttrValues[i] != NULL)
  1949. {
  1950. cbThisSize = My_lstrlen (ppi->ProtInfo.apszStdAttrValues[i]) + 1;
  1951. cbThisSize *= sizeof (TCHAR);
  1952. cbTotalSize += cbThisSize;
  1953. }
  1954. }
  1955. // Allocate LDAP_PROTINFO_RES structure
  1956. //
  1957. pProtRes = (LDAP_PROTINFO_RES *) MemAlloc (cbTotalSize);
  1958. if (pProtRes == NULL)
  1959. {
  1960. MyAssert (FALSE); // we are in deep trouble here
  1961. hrServer = ILS_E_MEMORY;
  1962. goto MyExit;
  1963. }
  1964. // Fill in fields
  1965. //
  1966. pProtRes->uSize = sizeof (*pProtRes);
  1967. pProtRes->hResult = hrServer;
  1968. pProtRes->lpi.uSize = sizeof (pProtRes->lpi);
  1969. TCHAR *pszSrc, *pszDst;
  1970. pszDst = (TCHAR *) (pProtRes + 1);
  1971. // Copy protocol name
  1972. //
  1973. pszSrc = ppi->ProtInfo.apszStdAttrValues[ENUM_PROTATTR_NAME];
  1974. if (pszSrc != NULL)
  1975. {
  1976. pProtRes->lpi.uOffsetName = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pProtRes->lpi));
  1977. My_lstrcpy (pszDst, pszSrc);
  1978. pszDst += lstrlen (pszDst) + 1;
  1979. }
  1980. // Copy protocol mime type
  1981. //
  1982. pszSrc = ppi->ProtInfo.apszStdAttrValues[ENUM_PROTATTR_MIME_TYPE];
  1983. if (pszSrc != NULL)
  1984. {
  1985. pProtRes->lpi.uOffsetMimeType = (ULONG)((ULONG_PTR) pszDst - (ULONG_PTR) &(pProtRes->lpi));
  1986. My_lstrcpy (pszDst, pszSrc);
  1987. pszDst += lstrlen (pszDst) + 1;
  1988. }
  1989. // Copy protocol prot number
  1990. //
  1991. pszSrc = ppi->ProtInfo.apszStdAttrValues[ENUM_PROTATTR_PORT_NUMBER];
  1992. if (pszSrc != NULL)
  1993. {
  1994. pProtRes->lpi.uPortNumber = GetStringLong (pszSrc);
  1995. }
  1996. MyAssert (hrServer == S_OK);
  1997. MyExit:
  1998. // Free temporary app result holder
  1999. //
  2000. if (ppi != NULL)
  2001. {
  2002. for (INT i = 0; i < COUNT_ENUM_PROTATTR; i++)
  2003. {
  2004. MemFree (ppi->ProtInfo.apszStdAttrValues[i]);
  2005. }
  2006. MemFree (ppi);
  2007. }
  2008. // Clean up the return structure if failure
  2009. //
  2010. if (hrServer != S_OK)
  2011. {
  2012. // Make sure we have a valid returned structure
  2013. //
  2014. if (pProtRes != NULL)
  2015. ZeroMemory (pProtRes, sizeof (*pProtRes));
  2016. else
  2017. pProtRes = (LDAP_PROTINFO_RES *) MemAlloc (sizeof (LDAP_PROTINFO_RES));
  2018. // Fill in the minimal info
  2019. //
  2020. if (pProtRes != NULL)
  2021. {
  2022. pProtRes->uSize = sizeof (*pProtRes);
  2023. pProtRes->hResult = hrServer;
  2024. }
  2025. }
  2026. // Post the result to the com layer
  2027. //
  2028. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) pProtRes);
  2029. // Destroy this pending item
  2030. //
  2031. return TRUE;
  2032. }
  2033. HRESULT CacheResolveProtInfoAttr (
  2034. VOID *pInfo,
  2035. const TCHAR *pszAttrName,
  2036. const TCHAR **ppszAttrVal )
  2037. {
  2038. MyAssert (pInfo != NULL);
  2039. MyAssert (pszAttrName != NULL);
  2040. // Shorthand prot info pointer
  2041. //
  2042. PROT_INFO_EX *ppi = (PROT_INFO_EX *) pInfo;
  2043. // Are we trying to find the index of the protocol to resolve?
  2044. //
  2045. if (ppi->fFindIndex)
  2046. {
  2047. // If we already located the index, then simply return
  2048. //
  2049. if (ppi->nIndex == INVALID_INDEX)
  2050. {
  2051. // Looking for "sprotid"
  2052. //
  2053. if (My_lstrcmpi (STR_PROT_NAME, pszAttrName) == 0)
  2054. {
  2055. // Get to the protocol name attribute
  2056. //
  2057. if (ppszAttrVal != NULL)
  2058. {
  2059. TCHAR *pszVal;
  2060. for (LONG nIndex = 0;
  2061. (pszVal = (TCHAR *) ppszAttrVal[nIndex]) != NULL;
  2062. nIndex++)
  2063. {
  2064. if (My_lstrcmpi (ppi->pszProtNameToResolve, pszVal) == 0)
  2065. {
  2066. // Locate the same protocol name, remember the index
  2067. //
  2068. ppi->nIndex = nIndex;
  2069. break;
  2070. // return S_OK; // we should be able to return from here
  2071. }
  2072. }
  2073. }
  2074. else
  2075. {
  2076. // ILS server bug or wldap32.dll bug
  2077. //
  2078. MyAssert (FALSE);
  2079. }
  2080. }
  2081. }
  2082. }
  2083. else
  2084. {
  2085. // Loop through all standard attributes
  2086. //
  2087. for (INT i = 0; i < COUNT_ENUM_PROTATTR; i++)
  2088. {
  2089. // Figure out what attribute it is
  2090. //
  2091. if (My_lstrcmpi (c_apszProtStdAttrNames[i], pszAttrName) == 0)
  2092. {
  2093. // Free the previously allocated value if any
  2094. //
  2095. MemFree (ppi->ProtInfo.apszStdAttrValues[i]);
  2096. // Duplicate the value
  2097. // BUGS: we should avoid duplicate the string here (cf. enum-user-infos)
  2098. //
  2099. if (ppszAttrVal != NULL)
  2100. {
  2101. // Make sure that we do not fault when the ILS server or wldap32.dll has a bug
  2102. //
  2103. for (LONG nIndex = 0; nIndex <= ppi->nIndex; nIndex++)
  2104. {
  2105. if (ppszAttrVal[nIndex] == NULL)
  2106. {
  2107. // ILS server bug
  2108. //
  2109. MyAssert (FALSE);
  2110. return S_OK;
  2111. }
  2112. }
  2113. // Duplicate the attribute value
  2114. //
  2115. ppi->ProtInfo.apszStdAttrValues[i] = My_strdup (ppszAttrVal[ppi->nIndex]);
  2116. }
  2117. else
  2118. {
  2119. // ILS server bug or wldap32.dll bug
  2120. //
  2121. MyAssert (FALSE);
  2122. }
  2123. break;
  2124. }
  2125. }
  2126. }
  2127. return S_OK;
  2128. }
  2129. #ifdef ENABLE_MEETING_PLACE
  2130. BOOL NotifyResolveMtg ( HRESULT hrServer, SP_CResponse *pItem )
  2131. {
  2132. MyAssert (pItem != NULL);
  2133. // Get pending info
  2134. //
  2135. RESP_INFO *pInfo = pItem->GetRespInfo ();
  2136. MyAssert (pInfo != NULL);
  2137. // Initialize minimal return info
  2138. //
  2139. LDAP_MEETINFO_RES *pMtgRes = NULL;
  2140. MTG_INFO_ATTRS *pmia = NULL;
  2141. // If error, simply report the error
  2142. //
  2143. if (hrServer != S_OK)
  2144. goto MyExit;
  2145. // Get the ldap result
  2146. //
  2147. LDAPMessage *pLdapMsg;
  2148. pLdapMsg = pItem->GetResult ();
  2149. if (pLdapMsg == NULL)
  2150. {
  2151. MyAssert (FALSE);
  2152. goto MyExit;
  2153. }
  2154. // Get ld
  2155. //
  2156. LDAP *ld;
  2157. ld = pItem->GetLd ();
  2158. if (ld == NULL)
  2159. {
  2160. MyAssert (FALSE);
  2161. hrServer = ILS_E_HANDLE;
  2162. goto MyExit;
  2163. }
  2164. // Get the count of attributes
  2165. //
  2166. ULONG cAttrs;
  2167. cAttrs = my_ldap_count_1st_entry_attributes (ld, pLdapMsg);
  2168. if (cAttrs == 0)
  2169. {
  2170. hrServer = ILS_E_NO_MORE;
  2171. goto MyExit;
  2172. }
  2173. // Allocate result set holder
  2174. //
  2175. pmia = (MTG_INFO_ATTRS *) MemAlloc (
  2176. sizeof (MTG_INFO_ATTRS) +
  2177. cAttrs * sizeof (ATTR_PAIR));
  2178. if (pmia == NULL)
  2179. {
  2180. hrServer = ILS_E_MEMORY;
  2181. goto MyExit;
  2182. }
  2183. // Initialize result set holder
  2184. //
  2185. pmia->Attrs.cMaxAttrs = cAttrs;
  2186. // Cache resolve set
  2187. //
  2188. hrServer = NotifyResolveX ( hrServer,
  2189. pItem,
  2190. pmia,
  2191. CacheResolveMtgInfoAttr);
  2192. if (hrServer != S_OK)
  2193. goto MyExit;
  2194. // Initialize the size
  2195. //
  2196. ULONG cbTotalSize, cbThisSize;
  2197. cbTotalSize = sizeof (LDAP_MEETINFO_RES);
  2198. // Loop through standard attrs to calculate the total size
  2199. //
  2200. ULONG i;
  2201. for (i = 0; i < COUNT_ENUM_MTGATTR; i++)
  2202. {
  2203. if (pmia->MtgInfo.apszStdAttrValues[i] != NULL)
  2204. {
  2205. // Compute the string length
  2206. //
  2207. cbThisSize = My_lstrlen (pmia->MtgInfo.apszStdAttrValues[i]) + 1;
  2208. // Compensate the string length if it is ip address
  2209. //
  2210. if (i == ENUM_MTGATTR_IP_ADDRESS)
  2211. cbThisSize += 16;
  2212. // Convert the string length to string size
  2213. //
  2214. cbThisSize *= sizeof (TCHAR);
  2215. // Add up to the total size
  2216. //
  2217. cbTotalSize += cbThisSize;
  2218. }
  2219. }
  2220. // Loop through arbitrary attrs to calculate the total size
  2221. //
  2222. for (i = 0; i < pmia->Attrs.cCurrAttrs; i++)
  2223. {
  2224. cbThisSize = My_lstrlen (pmia->Attrs.aPairs[i].pszName) + 1;
  2225. cbThisSize += My_lstrlen (pmia->Attrs.aPairs[i].pszValue) + 1;
  2226. cbThisSize *= sizeof (TCHAR);
  2227. cbTotalSize += cbThisSize;
  2228. }
  2229. // Allocate LDAP_MTGINFO_RES structure
  2230. //
  2231. pMtgRes = (LDAP_MEETINFO_RES *) MemAlloc (cbTotalSize);
  2232. if (pMtgRes == NULL)
  2233. {
  2234. MyAssert (FALSE); // we are in deep trouble here
  2235. hrServer = ILS_E_MEMORY;
  2236. goto MyExit;
  2237. }
  2238. // Fill in common fields
  2239. //
  2240. pMtgRes->uSize = sizeof (*pMtgRes);
  2241. pMtgRes->hResult = hrServer;
  2242. pMtgRes->lmi.uSize = sizeof (pMtgRes->lmi);
  2243. TCHAR *pszSrc, *pszDst;
  2244. pszDst = (TCHAR *) (pMtgRes + 1);
  2245. // Copy Meeting Name if needed
  2246. //
  2247. pszSrc = pmia->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_CN];
  2248. if (pszSrc != NULL)
  2249. {
  2250. pMtgRes->lmi.uOffsetMeetingPlaceID = (ULONG) pszDst - (ULONG) &(pMtgRes->lmi);
  2251. My_lstrcpy (pszDst, pszSrc);
  2252. pszDst += lstrlen (pszDst) + 1;
  2253. }
  2254. // Copy Meeting Type if needed
  2255. //
  2256. pszSrc = pmia->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_MTG_TYPE];
  2257. if (pszSrc != NULL)
  2258. {
  2259. pMtgRes->lmi.lMeetingPlaceType = (pszSrc != NULL) ? GetStringLong (pszSrc) :
  2260. INVALID_MEETING_TYPE;
  2261. }
  2262. // Copy Attendee Type if needed
  2263. //
  2264. pszSrc = pmia->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_MEMBER_TYPE];
  2265. if (pszSrc != NULL)
  2266. {
  2267. pMtgRes->lmi.lAttendeeType = (pszSrc != NULL) ? GetStringLong (pszSrc) :
  2268. INVALID_ATTENDEE_TYPE;
  2269. }
  2270. // Copy Description if needed
  2271. //
  2272. pszSrc = pmia->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_DESCRIPTION];
  2273. if (pszSrc != NULL)
  2274. {
  2275. pMtgRes->lmi.uOffsetDescription = (ULONG) pszDst - (ULONG) &(pMtgRes->lmi);
  2276. My_lstrcpy (pszDst, pszSrc);
  2277. pszDst += lstrlen (pszDst) + 1;
  2278. }
  2279. // Copy Host Name if needed
  2280. //
  2281. pszSrc = pmia->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_HOST_NAME];
  2282. if (pszSrc != NULL)
  2283. {
  2284. pMtgRes->lmi.uOffsetHostName = (ULONG) pszDst - (ULONG) &(pMtgRes->lmi);
  2285. My_lstrcpy (pszDst, pszSrc);
  2286. pszDst += lstrlen (pszDst) + 1;
  2287. }
  2288. // Copy Host IP Address if needed
  2289. //
  2290. pszSrc = pmia->MtgInfo.apszStdAttrValues[ENUM_MTGATTR_IP_ADDRESS];
  2291. if (pszSrc != NULL)
  2292. {
  2293. pMtgRes->lmi.uOffsetHostIPAddress = (ULONG) pszDst - (ULONG) &(pMtgRes->lmi);
  2294. GetIPAddressString (pszDst, GetStringLong (pszSrc));
  2295. pszDst += lstrlen (pszDst) + 1;
  2296. }
  2297. // Copy extended attributes
  2298. //
  2299. pMtgRes->lmi.cAttrsReturned = pmia->Attrs.cCurrAttrs;
  2300. if (pMtgRes->lmi.cAttrsReturned > 0)
  2301. {
  2302. pMtgRes->lmi.uOffsetAttrsReturned = (ULONG) pszDst - (ULONG) &(pMtgRes->lmi);
  2303. for (i = 0; i < pmia->Attrs.cCurrAttrs; i++)
  2304. {
  2305. My_lstrcpy (pszDst, pmia->Attrs.aPairs[i].pszName);
  2306. pszDst += lstrlen (pszDst) + 1;
  2307. My_lstrcpy (pszDst, pmia->Attrs.aPairs[i].pszValue);
  2308. pszDst += lstrlen (pszDst) + 1;
  2309. }
  2310. }
  2311. MyAssert (hrServer == S_OK);
  2312. MyExit:
  2313. // Free temporary result set holder
  2314. //
  2315. if (pmia != NULL)
  2316. {
  2317. // Free standard attributes
  2318. //
  2319. for (INT i = 0; i < COUNT_ENUM_MTGATTR; i++)
  2320. {
  2321. MemFree (pmia->MtgInfo.apszStdAttrValues[i]);
  2322. }
  2323. // Free arbitrary attributes
  2324. //
  2325. for (ULONG j = 0; j < pmia->Attrs.cCurrAttrs; j++)
  2326. {
  2327. MemFree (pmia->Attrs.aPairs[j].pszName);
  2328. MemFree (pmia->Attrs.aPairs[j].pszValue);
  2329. }
  2330. // Free the holder itself
  2331. //
  2332. MemFree (pmia);
  2333. }
  2334. // Clean up the return structure if failure
  2335. //
  2336. if (hrServer != S_OK)
  2337. {
  2338. // Make sure we have a return structure
  2339. //
  2340. if (pMtgRes != NULL)
  2341. ZeroMemory (pMtgRes, sizeof (*pMtgRes));
  2342. else
  2343. pMtgRes = (LDAP_MEETINFO_RES *) MemAlloc (sizeof (LDAP_MEETINFO_RES));
  2344. // Fill in the minimal info
  2345. //
  2346. if (pMtgRes != NULL)
  2347. {
  2348. pMtgRes->uSize = sizeof (*pMtgRes);
  2349. pMtgRes->hResult = hrServer;
  2350. }
  2351. }
  2352. // Post a message to the com layer
  2353. //
  2354. PostMessage (g_hWndNotify, pInfo->uNotifyMsg, pInfo->uRespID, (LPARAM) pMtgRes);
  2355. // Delete this pending item
  2356. //
  2357. return TRUE;
  2358. }
  2359. #endif // ENABLE_MEETING_PLACE
  2360. #ifdef ENABLE_MEETING_PLACE
  2361. HRESULT CacheResolveMtgInfoAttr (
  2362. VOID *pInfo,
  2363. const TCHAR *pszAttrName,
  2364. const TCHAR **ppszAttrVal )
  2365. {
  2366. MyAssert (pInfo != NULL);
  2367. MyAssert (pszAttrName != NULL);
  2368. // Shorthand meeting info pointer
  2369. //
  2370. MTG_INFO_ATTRS *pmia = (MTG_INFO_ATTRS *) pInfo;
  2371. // See if this attribute is arbitrary?
  2372. //
  2373. const TCHAR *pszRealAnyName = IlsIsAnyAttrName (pszAttrName);
  2374. if (pszRealAnyName != NULL)
  2375. {
  2376. MyAssert (pmia->Attrs.cCurrAttrs < pmia->Attrs.cMaxAttrs);
  2377. // Duplicate the name
  2378. //
  2379. pmia->Attrs.aPairs[pmia->Attrs.cCurrAttrs].pszName =
  2380. My_strdup (pszRealAnyName);
  2381. // Duplicate the value
  2382. // BUGS: we should avoid duplicate the string here (cf. enum-user-infos)
  2383. //
  2384. if (ppszAttrVal != NULL)
  2385. {
  2386. pmia->Attrs.aPairs[pmia->Attrs.cCurrAttrs++].pszValue =
  2387. My_strdup (*ppszAttrVal);
  2388. }
  2389. else
  2390. {
  2391. // ILS server bug or wldap32.dll bug
  2392. //
  2393. MyAssert (FALSE);
  2394. }
  2395. }
  2396. else
  2397. {
  2398. // Loop through all standard attributes
  2399. //
  2400. for (INT i = 0; i < COUNT_ENUM_RESMTGINFO; i++)
  2401. {
  2402. // Figure out what attribute it is
  2403. //
  2404. if (My_lstrcmpi (c_apszMtgStdAttrNames[i], pszAttrName) == 0)
  2405. {
  2406. // Free the previously allocated value if any
  2407. //
  2408. MemFree (pmia->MtgInfo.apszStdAttrValues[i]);
  2409. // Duplicate the value
  2410. // BUGS: we should avoid duplicate the string here (cf. enum-user-infos)
  2411. //
  2412. if (ppszAttrVal != NULL)
  2413. {
  2414. pmia->MtgInfo.apszStdAttrValues[i] = My_strdup (*ppszAttrVal);
  2415. }
  2416. else
  2417. {
  2418. // ILS server bug or wldap32.dll bug
  2419. //
  2420. MyAssert (FALSE);
  2421. }
  2422. break;
  2423. }
  2424. }
  2425. }
  2426. return S_OK;
  2427. }
  2428. #endif // ENABLE_MEETING_PLACE
  2429. VOID FreeStdAttrCache ( TCHAR *apszStdAttrValues[], ULONG cStdAttrs )
  2430. {
  2431. for (ULONG i = 0; i < cStdAttrs; i++)
  2432. {
  2433. if (apszStdAttrValues[i] != NULL)
  2434. {
  2435. ldap_value_free ((TCHAR **) apszStdAttrValues[i]);
  2436. }
  2437. }
  2438. }
  2439. VOID FreeAttrPairArrayCache ( ATTR_PAIR aAttrPair[], ULONG cPairs )
  2440. {
  2441. if (aAttrPair != NULL)
  2442. {
  2443. for (ULONG j = 0; j < cPairs; j++)
  2444. {
  2445. if (aAttrPair[j].pszValue != NULL)
  2446. {
  2447. ldap_value_free ((TCHAR **) aAttrPair[j].pszValue);
  2448. }
  2449. }
  2450. }
  2451. }
  2452. VOID CacheAnyAttrNamesInAttrPairs (
  2453. ULONG cNames,
  2454. TCHAR *pszSrcNameList,
  2455. ATTR_PAIR aPairs[] )
  2456. {
  2457. MyAssert (cNames != 0);
  2458. MyAssert (pszSrcNameList != NULL);
  2459. MyAssert (aPairs != NULL);
  2460. // Note that all these extended attribute names are already PREFIXED
  2461. //
  2462. for (ULONG i = 0; i < cNames; i++)
  2463. {
  2464. aPairs[i].pszName = pszSrcNameList;
  2465. pszSrcNameList += lstrlen (pszSrcNameList) + 1;
  2466. }
  2467. }
  2468.