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.

577 lines
12 KiB

  1. /* ----------------------------------------------------------------------
  2. Module: ULS.DLL (Service Provider)
  3. File: spanyatt.cpp
  4. Content: This file contains the arbitrary-attribute 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. /* ---------- public methods ----------- */
  13. UlsLdap_CAnyAttrs::UlsLdap_CAnyAttrs ( VOID )
  14. {
  15. m_cAttrs = 0;
  16. m_AttrList = NULL;
  17. }
  18. UlsLdap_CAnyAttrs::~UlsLdap_CAnyAttrs ( VOID )
  19. {
  20. FreeAttrList (m_AttrList);
  21. }
  22. /* ---------- protected methods ----------- */
  23. HRESULT UlsLdap_CAnyAttrs::SetAnyAttrs (
  24. ULONG *puRespID,
  25. ULONG *puMsgID,
  26. ULONG uNotifyMsg,
  27. ULONG cAttrs,
  28. TCHAR *pszAttrs,
  29. ULONG cPrefix,
  30. TCHAR *pszPrefix,
  31. LONG ModOp,
  32. SERVER_INFO *pServerInfo,
  33. TCHAR *pszDN )
  34. {
  35. MyAssert (puRespID != NULL || puMsgID != NULL);
  36. MyAssert (cAttrs != 0);
  37. MyAssert (pszAttrs != NULL);
  38. MyAssert (cPrefix != 0);
  39. MyAssert (pszPrefix != NULL);
  40. MyAssert (pServerInfo != NULL);
  41. MyAssert (pszDN != NULL);
  42. MyAssert (ModOp == LDAP_MOD_REPLACE || ModOp == LDAP_MOD_ADD);
  43. // create a prefix for each attr name in the following pair
  44. pszAttrs = PrefixNameValueArray (TRUE, cAttrs, pszAttrs);
  45. if (pszAttrs == NULL)
  46. return ULS_E_MEMORY;
  47. // build modify array for ldap_modify()
  48. LDAPMod **ppMod = NULL;
  49. HRESULT hr = SetAttrsAux (cAttrs, pszAttrs, cPrefix, pszPrefix, ModOp, &ppMod);
  50. if (hr != S_OK)
  51. {
  52. MemFree (pszAttrs);
  53. return hr;
  54. }
  55. MyAssert (ppMod != NULL);
  56. // so far, we are done with local preparation
  57. // get the connection object
  58. UlsLdap_CSession *pSession = NULL;
  59. hr = g_pSessionContainer->GetSession (&pSession, pServerInfo);
  60. if (hr != S_OK)
  61. {
  62. MemFree (pszAttrs);
  63. MemFree (ppMod);
  64. return hr;
  65. }
  66. MyAssert (pSession != NULL);
  67. // get the ldap session
  68. LDAP *ld = pSession->GetLd ();
  69. MyAssert (ld != NULL);
  70. // send the data over the wire
  71. ULONG uMsgID = ldap_modify (ld, pszDN, ppMod);
  72. MemFree (pszAttrs);
  73. MemFree (ppMod);
  74. if (uMsgID == -1)
  75. {
  76. hr = ::LdapError2Hresult (ld->ld_errno);
  77. pSession->Disconnect ();
  78. return hr;
  79. }
  80. // if the caller does not ask for notify id
  81. // then do not queue a pending info
  82. if (puRespID != NULL)
  83. {
  84. PENDING_INFO PendingInfo;
  85. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
  86. PendingInfo.uLdapResType = LDAP_RES_MODIFY;
  87. PendingInfo.uNotifyMsg = uNotifyMsg;
  88. // queue it
  89. hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
  90. if (hr != S_OK)
  91. {
  92. ldap_abandon (ld, uMsgID);
  93. pSession->Disconnect ();
  94. MyAssert (FALSE);
  95. }
  96. *puRespID = PendingInfo.uRespID;
  97. }
  98. if (puMsgID)
  99. *puMsgID = uMsgID;
  100. return hr;
  101. }
  102. HRESULT UlsLdap_CAnyAttrs::RemoveAllAnyAttrs (
  103. ULONG *puMsgID,
  104. ULONG cPrefix,
  105. TCHAR *pszPrefix,
  106. SERVER_INFO *pServerInfo,
  107. TCHAR *pszDN )
  108. {
  109. ULONG cbAttrs = 0;
  110. ULONG cAttrs = 0;
  111. for (ANY_ATTR *p = m_AttrList; p != NULL; p = p->next)
  112. {
  113. cAttrs++;
  114. if (p->pszAttrName != NULL)
  115. cbAttrs += (lstrlen (p->pszAttrName) + 1) * sizeof (TCHAR);
  116. }
  117. MyAssert (cAttrs == m_cAttrs);
  118. TCHAR *pszAttrs = (TCHAR *) MemAlloc (cbAttrs);
  119. if (pszAttrs == NULL)
  120. return ULS_E_MEMORY;
  121. TCHAR *psz = pszAttrs;
  122. for (p = m_AttrList; p != NULL; p = p->next)
  123. {
  124. if (p->pszAttrName != NULL)
  125. {
  126. lstrcpy (psz, p->pszAttrName);
  127. psz += lstrlen (psz) + 1;
  128. }
  129. }
  130. HRESULT hr = RemoveAnyAttrsEx ( NULL,
  131. puMsgID,
  132. 0,
  133. cAttrs,
  134. pszAttrs,
  135. cPrefix,
  136. pszPrefix,
  137. pServerInfo,
  138. pszDN);
  139. MemFree (pszAttrs);
  140. return hr;
  141. }
  142. HRESULT UlsLdap_CAnyAttrs::RemoveAnyAttrs (
  143. ULONG *puRespID,
  144. ULONG *puMsgID,
  145. ULONG uNotifyMsg,
  146. ULONG cAttrs,
  147. TCHAR *pszAttrs,
  148. ULONG cPrefix,
  149. TCHAR *pszPrefix,
  150. SERVER_INFO *pServerInfo,
  151. TCHAR *pszDN)
  152. {
  153. MyAssert (puRespID != NULL || puMsgID != NULL);
  154. MyAssert (cAttrs != 0);
  155. MyAssert (pszAttrs != NULL);
  156. MyAssert (cPrefix != 0);
  157. MyAssert (pszPrefix != NULL);
  158. MyAssert (pServerInfo != NULL);
  159. MyAssert (pszDN != NULL);
  160. pszAttrs = PrefixNameValueArray (FALSE, cAttrs, pszAttrs);
  161. if (pszAttrs == NULL)
  162. return ULS_E_MEMORY;
  163. HRESULT hr = RemoveAnyAttrsEx ( puRespID,
  164. puMsgID,
  165. uNotifyMsg,
  166. cAttrs,
  167. pszAttrs,
  168. cPrefix,
  169. pszPrefix,
  170. pServerInfo,
  171. pszDN);
  172. MemFree (pszAttrs);
  173. return hr;
  174. }
  175. HRESULT UlsLdap_CAnyAttrs::RemoveAnyAttrsEx (
  176. ULONG *puRespID,
  177. ULONG *puMsgID,
  178. ULONG uNotifyMsg,
  179. ULONG cAttrs,
  180. TCHAR *pszAttrs,
  181. ULONG cPrefix,
  182. TCHAR *pszPrefix,
  183. SERVER_INFO *pServerInfo,
  184. TCHAR *pszDN)
  185. {
  186. MyAssert (puRespID != NULL || puMsgID != NULL);
  187. MyAssert (cAttrs != 0);
  188. MyAssert (pszAttrs != NULL);
  189. MyAssert (cPrefix != 0);
  190. MyAssert (pszPrefix != NULL);
  191. MyAssert (pServerInfo != NULL);
  192. MyAssert (pszDN != NULL);
  193. // build modify array for ldap_modify()
  194. LDAPMod **ppMod = NULL;
  195. HRESULT hr = RemoveAttrsAux (cAttrs, pszAttrs, cPrefix, pszPrefix, &ppMod);
  196. if (hr != S_OK)
  197. return hr;
  198. MyAssert (ppMod != NULL);
  199. // so far, we are done with local preparation
  200. // get the connection object
  201. UlsLdap_CSession *pSession = NULL;
  202. hr = g_pSessionContainer->GetSession (&pSession, pServerInfo);
  203. if (hr != S_OK)
  204. {
  205. MemFree (ppMod);
  206. return hr;
  207. }
  208. MyAssert (pSession != NULL);
  209. // get the ldap session
  210. LDAP *ld = pSession->GetLd ();
  211. MyAssert (ld != NULL);
  212. // send the data over the wire
  213. ULONG uMsgID = ldap_modify (ld, pszDN, ppMod);
  214. MemFree (ppMod);
  215. if (uMsgID == -1)
  216. {
  217. hr = ::LdapError2Hresult (ld->ld_errno);
  218. pSession->Disconnect ();
  219. return hr;
  220. }
  221. // if the caller does not ask for notify id
  222. // then do not queue a pending info
  223. if (puRespID != NULL)
  224. {
  225. PENDING_INFO PendingInfo;
  226. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
  227. PendingInfo.uLdapResType = LDAP_RES_MODIFY;
  228. PendingInfo.uNotifyMsg = uNotifyMsg;
  229. hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
  230. if (hr != S_OK)
  231. {
  232. ldap_abandon (ld, uMsgID);
  233. pSession->Disconnect ();
  234. MyAssert (FALSE);
  235. }
  236. *puRespID = PendingInfo.uRespID;
  237. }
  238. else
  239. {
  240. if (puMsgID != NULL)
  241. *puMsgID = uMsgID;
  242. }
  243. return hr;
  244. }
  245. /* ---------- private methods ----------- */
  246. HRESULT UlsLdap_CAnyAttrs::SetAttrsAux (
  247. ULONG cAttrs,
  248. TCHAR *pszAttrs,
  249. ULONG cPrefix,
  250. TCHAR *pszPrefix,
  251. LONG ModOp,
  252. LDAPMod ***pppMod )
  253. {
  254. MyAssert (cAttrs != 0);
  255. MyAssert (pszAttrs != NULL);
  256. MyAssert (cPrefix != 0);
  257. MyAssert (pszPrefix != NULL);
  258. MyAssert (ModOp == LDAP_MOD_REPLACE || ModOp == LDAP_MOD_ADD);
  259. MyAssert (pppMod != NULL);
  260. // create modify list
  261. ULONG cTotal = cPrefix + cAttrs;
  262. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  263. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  264. if (*pppMod == NULL)
  265. {
  266. return ULS_E_MEMORY;
  267. }
  268. LDAPMod *pMod;
  269. for (ULONG i = 0; i < cTotal; i++)
  270. {
  271. pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
  272. (*pppMod)[i] = pMod;
  273. pMod->mod_values = (TCHAR **) (pMod + 1);
  274. if (i < cPrefix)
  275. {
  276. pMod->mod_op = LDAP_MOD_REPLACE;
  277. pMod->mod_type = pszPrefix;
  278. pszPrefix += lstrlen (pszPrefix) + 1;
  279. *(pMod->mod_values) = pszPrefix;
  280. pszPrefix += lstrlen (pszPrefix) + 1;
  281. }
  282. else
  283. {
  284. pMod->mod_op = ModOp;
  285. if (LocateAttr (pszAttrs) == NULL)
  286. {
  287. pMod->mod_op = LDAP_MOD_ADD;
  288. m_cAttrs++;
  289. }
  290. if (pMod->mod_op == LDAP_MOD_ADD)
  291. {
  292. ULONG cbAttrSize = sizeof (ANY_ATTR) + sizeof (TCHAR) *
  293. (lstrlen (pszAttrs) + 1);
  294. ANY_ATTR *pNew = (ANY_ATTR *) MemAlloc (cbAttrSize);
  295. if (pNew == NULL)
  296. {
  297. return ULS_E_MEMORY;
  298. }
  299. // fill in attr name
  300. pNew->pszAttrName = (TCHAR *) (pNew + 1);
  301. lstrcpy (pNew->pszAttrName, pszAttrs);
  302. // link to the list
  303. pNew->prev = NULL;
  304. pNew->next = m_AttrList;
  305. m_AttrList = pNew;
  306. }
  307. pMod->mod_type = pszAttrs;
  308. pszAttrs += lstrlen (pszAttrs) + 1;
  309. *(pMod->mod_values) = pszAttrs;
  310. pszAttrs += lstrlen (pszAttrs) + 1;
  311. }
  312. }
  313. (*pppMod)[cTotal] = NULL;
  314. ::IlsFixUpModOp ((*pppMod)[0], ModOp, ISBU_MODOP_MODIFY_APP);
  315. return S_OK;
  316. }
  317. HRESULT UlsLdap_CAnyAttrs::RemoveAttrsAux (
  318. ULONG cAttrs,
  319. TCHAR *pszAttrs,
  320. ULONG cPrefix,
  321. TCHAR *pszPrefix,
  322. LDAPMod ***pppMod )
  323. {
  324. MyAssert (cAttrs != 0);
  325. MyAssert (pszAttrs != NULL);
  326. MyAssert (cPrefix != 0);
  327. MyAssert (pszPrefix != NULL);
  328. MyAssert (pppMod != NULL);
  329. // create modify list
  330. ULONG cTotal = cPrefix + cAttrs;
  331. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  332. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  333. if (*pppMod == NULL)
  334. {
  335. return ULS_E_MEMORY;
  336. }
  337. LDAPMod *pMod;
  338. for (ULONG i = 0; i < cTotal; i++)
  339. {
  340. pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
  341. (*pppMod)[i] = pMod;
  342. if (i < cPrefix)
  343. {
  344. pMod->mod_op = LDAP_MOD_REPLACE;
  345. pMod->mod_type = pszPrefix;
  346. pszPrefix += lstrlen (pszPrefix) + 1;
  347. pMod->mod_values = (TCHAR **) (pMod + 1);
  348. *(pMod->mod_values) = pszPrefix;
  349. pszPrefix += lstrlen (pszPrefix) + 1;
  350. }
  351. else
  352. {
  353. pMod->mod_op = LDAP_MOD_DELETE;
  354. RemoveAttrFromList (pszAttrs);
  355. pMod->mod_type = pszAttrs;
  356. pszAttrs += lstrlen (pszAttrs) + 1;
  357. }
  358. }
  359. (*pppMod)[cTotal] = NULL;
  360. ::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_REPLACE, ISBU_MODOP_MODIFY_APP);
  361. return S_OK;
  362. }
  363. VOID UlsLdap_CAnyAttrs::RemoveAttrFromList ( TCHAR *pszAttrName )
  364. {
  365. ANY_ATTR *pOld = LocateAttr (pszAttrName);
  366. if (pOld != NULL)
  367. {
  368. // remove it
  369. if (pOld->prev != NULL)
  370. {
  371. pOld->prev->next = pOld->next;
  372. }
  373. else
  374. {
  375. m_AttrList = pOld->next;
  376. }
  377. if (pOld->next != NULL)
  378. {
  379. pOld->next->prev = pOld->prev;
  380. }
  381. MyAssert (m_cAttrs != 0);
  382. m_cAttrs--;
  383. }
  384. }
  385. VOID UlsLdap_CAnyAttrs::FreeAttrList ( ANY_ATTR *AttrList )
  386. {
  387. ANY_ATTR *pCurr, *pNext;
  388. for (pCurr = AttrList; pCurr != NULL; pCurr = pNext)
  389. {
  390. pNext = pCurr->next;
  391. MemFree (pCurr);
  392. }
  393. }
  394. ANY_ATTR *UlsLdap_CAnyAttrs::LocateAttr ( TCHAR *pszAttrName )
  395. {
  396. ANY_ATTR *pAttr;
  397. for (pAttr = m_AttrList; pAttr != NULL; pAttr = pAttr->next)
  398. {
  399. if (! My_lstrcmpi (pszAttrName, pAttr->pszAttrName))
  400. {
  401. break;
  402. }
  403. }
  404. return pAttr;
  405. }
  406. // const TCHAR c_szAnyAttrPrefix[] = TEXT ("ulsaan_");
  407. const TCHAR c_szAnyAttrPrefix[] = TEXT ("ILSA");
  408. #define SIZE_ANY_ATTR_PREFIX (sizeof (c_szAnyAttrPrefix) / sizeof (TCHAR))
  409. const TCHAR *SkipAnyAttrNamePrefix ( const TCHAR *pszAttrName )
  410. {
  411. MyAssert (pszAttrName != NULL);
  412. const TCHAR *psz = IsAnyAttrName (pszAttrName);
  413. if (psz == NULL)
  414. {
  415. MyAssert (FALSE);
  416. psz = pszAttrName;
  417. }
  418. return psz;
  419. }
  420. const TCHAR *IsAnyAttrName ( const TCHAR *pszAttrName )
  421. {
  422. BOOL fRet = FALSE;
  423. TCHAR *psz = (TCHAR *) pszAttrName;
  424. if (pszAttrName != NULL)
  425. {
  426. if (lstrlen (pszAttrName) > SIZE_ANY_ATTR_PREFIX)
  427. {
  428. TCHAR c = pszAttrName[SIZE_ANY_ATTR_PREFIX-1];
  429. psz[SIZE_ANY_ATTR_PREFIX-1] = TEXT ('\0');
  430. fRet = (My_lstrcmpi (pszAttrName, &c_szAnyAttrPrefix[0]) == 0);
  431. psz[SIZE_ANY_ATTR_PREFIX-1] = c;
  432. }
  433. }
  434. return (fRet ? &pszAttrName[SIZE_ANY_ATTR_PREFIX-1] : NULL);
  435. }
  436. TCHAR *PrefixNameValueArray ( BOOL fPair, ULONG cAttrs, const TCHAR *pszAttrs )
  437. {
  438. if (cAttrs == 0 || pszAttrs == NULL)
  439. {
  440. MyAssert (FALSE);
  441. return NULL;
  442. }
  443. // compute the total size required
  444. ULONG cbTotalSize = 0;
  445. ULONG cbThisSize;
  446. TCHAR *pszSrc = (TCHAR *) pszAttrs;
  447. for (ULONG i = 0; i < cAttrs; i++)
  448. {
  449. // get name size
  450. cbThisSize = lstrlen (pszSrc) + 1;
  451. pszSrc += lstrlen (pszSrc) + 1;
  452. // get value size as needed
  453. if (fPair)
  454. {
  455. cbThisSize += lstrlen (pszSrc) + 1;
  456. pszSrc += lstrlen (pszSrc) + 1;
  457. }
  458. // adjust the size
  459. cbThisSize += SIZE_ANY_ATTR_PREFIX;
  460. cbThisSize *= sizeof (TCHAR);
  461. // accumulate it
  462. cbTotalSize += cbThisSize;
  463. }
  464. // allocate the new buffer
  465. TCHAR *pszPrefixAttrs = (TCHAR *) MemAlloc (cbTotalSize);
  466. if (pszPrefixAttrs == NULL)
  467. return NULL;
  468. // copy the strings over to the new buffer
  469. pszSrc = (TCHAR *) pszAttrs;
  470. TCHAR *pszDst = pszPrefixAttrs;
  471. for (i = 0; i < cAttrs; i++)
  472. {
  473. // copy prefix
  474. lstrcpy (pszDst, &c_szAnyAttrPrefix[0]);
  475. pszDst += lstrlen (pszDst); // no plus 1
  476. // copy name
  477. lstrcpy (pszDst, pszSrc);
  478. pszDst += lstrlen (pszDst) + 1;
  479. pszSrc += lstrlen (pszSrc) + 1;
  480. // copy value as needed
  481. if (fPair)
  482. {
  483. lstrcpy (pszDst, pszSrc);
  484. pszDst += lstrlen (pszDst) + 1;
  485. pszSrc += lstrlen (pszSrc) + 1;
  486. }
  487. }
  488. return pszPrefixAttrs;
  489. }