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.

568 lines
12 KiB

  1. /* ----------------------------------------------------------------------
  2. Module: ULS.DLL (Service Provider)
  3. File: splapp.cpp
  4. Content: This file contains the local application 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. const TCHAR *c_apszAppStdAttrNames[COUNT_ENUM_APPATTR] =
  13. {
  14. TEXT ("sappid"),
  15. TEXT ("smimetype"),
  16. TEXT ("sappguid"), // app guid
  17. // protocol attributes
  18. TEXT ("sprotid"),
  19. TEXT ("sprotmimetype"),
  20. TEXT ("sport"),
  21. };
  22. /* ---------- public methods ----------- */
  23. UlsLdap_CLocalApp::UlsLdap_CLocalApp ( UlsLdap_CLocalUser *pUser )
  24. {
  25. MyAssert (pUser != NULL);
  26. m_cRefs = 0;
  27. m_uSignature = APPOBJ_SIGNATURE;
  28. m_pUser = pUser;
  29. m_cPrefix = 0;
  30. m_pszPrefix = NULL;
  31. ZeroMemory (&m_AppInfo, sizeof (m_AppInfo));
  32. SetRegNone ();
  33. }
  34. UlsLdap_CLocalApp::~UlsLdap_CLocalApp ( VOID )
  35. {
  36. m_uSignature = (ULONG) -1;
  37. MemFree (m_pszPrefix);
  38. }
  39. ULONG UlsLdap_CLocalApp::AddRef ( VOID )
  40. {
  41. InterlockedIncrement (&m_cRefs);
  42. return m_cRefs;
  43. }
  44. ULONG UlsLdap_CLocalApp::Release ( VOID )
  45. {
  46. MyAssert (m_cRefs != 0);
  47. if (m_cRefs != 0)
  48. {
  49. InterlockedDecrement (&m_cRefs);
  50. }
  51. ULONG cRefs = m_cRefs;
  52. if (cRefs == 0)
  53. delete this;
  54. return cRefs;
  55. }
  56. HRESULT UlsLdap_CLocalApp::Register ( ULONG *puRespID, LDAP_APPINFO *pInfo )
  57. {
  58. MyAssert (puRespID != NULL);
  59. MyAssert (pInfo != NULL);
  60. TCHAR *pszDN = GetDN ();
  61. if (pszDN == NULL)
  62. {
  63. MyAssert (FALSE);
  64. return ULS_E_HANDLE;
  65. }
  66. // get app name
  67. TCHAR *pszAppName = (TCHAR *) ((BYTE *) pInfo + pInfo->uOffsetName);
  68. if (*pszAppName == TEXT ('\0'))
  69. {
  70. MyAssert (FALSE);
  71. return ULS_E_PARAMETER;
  72. }
  73. // cache app info
  74. HRESULT hr = CacheAppInfo (pInfo);
  75. if (hr != S_OK)
  76. return hr;
  77. // cache generic protocol info (per KevinMa's suggestion)
  78. m_AppInfo.apszStdAttrValues[ENUM_APPATTR_PROT_NAME] = TEXT ("h323");
  79. m_AppInfo.apszStdAttrValues[ENUM_APPATTR_PROT_MIME] = TEXT ("text/h323");
  80. m_AppInfo.apszStdAttrValues[ENUM_APPATTR_PROT_PORT] = TEXT ("1720");
  81. // create prefix info
  82. ULONG cbPrefix = sizeof (TCHAR) * (lstrlen (STR_APP_NAME) +
  83. lstrlen (pszAppName) + 2);
  84. ULONG cUserPrefix = GetUserPrefixCount ();
  85. TCHAR *pszUserPrefix = GetUserPrefixString ();
  86. for (ULONG i = 0; i < cUserPrefix; i++)
  87. {
  88. ULONG uLength = lstrlen (pszUserPrefix) + 1;
  89. cbPrefix += uLength * sizeof (TCHAR);
  90. pszUserPrefix += uLength;
  91. uLength = lstrlen (pszUserPrefix) + 1;
  92. cbPrefix += uLength * sizeof (TCHAR);
  93. pszUserPrefix += uLength;
  94. }
  95. TCHAR *psz = (TCHAR *) MemAlloc (cbPrefix);
  96. if (psz == NULL)
  97. return ULS_E_MEMORY;
  98. MemFree (m_pszPrefix);
  99. m_pszPrefix = psz;
  100. m_cPrefix = cUserPrefix + 1;
  101. // fill in prefix info
  102. pszUserPrefix = GetUserPrefixString ();
  103. for (i = 0; i < cUserPrefix; i++)
  104. {
  105. ULONG uLength = lstrlen (pszUserPrefix) + 1;
  106. lstrcpy (psz, pszUserPrefix);
  107. psz += uLength;
  108. pszUserPrefix += uLength;
  109. uLength = lstrlen (pszUserPrefix) + 1;
  110. lstrcpy (psz, pszUserPrefix);
  111. psz += uLength;
  112. pszUserPrefix += uLength;
  113. }
  114. lstrcpy (psz, STR_APP_NAME);
  115. psz += lstrlen (psz) + 1;
  116. lstrcpy (psz, pszAppName);
  117. // build modify array for ldap_modify()
  118. LDAPMod **ppMod = NULL;
  119. hr = CreateRegisterModArr (&ppMod);
  120. if (hr != S_OK)
  121. return hr;
  122. MyAssert (ppMod != NULL);
  123. // so far, we are done with local preparation
  124. // get the connection object
  125. UlsLdap_CSession *pSession = NULL;
  126. MyAssert (m_pUser != NULL);
  127. hr = g_pSessionContainer->GetSession (&pSession, GetServerInfo ());
  128. if (hr != S_OK)
  129. {
  130. MemFree (ppMod);
  131. return hr;
  132. }
  133. MyAssert (pSession != NULL);
  134. // get the ldap session
  135. LDAP *ld = pSession->GetLd ();
  136. MyAssert (ld != NULL);
  137. // send the data over the wire
  138. ULONG uMsgID = ldap_modify (ld, pszDN, ppMod);
  139. MemFree (ppMod);
  140. if (uMsgID == -1)
  141. {
  142. hr = ::LdapError2Hresult (ld->ld_errno);
  143. pSession->Disconnect ();
  144. return hr;
  145. }
  146. // if there is any arbitrary attributes,
  147. // then do not create pending info and we will use
  148. // SetAttrs's pending info
  149. ULONG u2ndMsgID = INVALID_MSG_ID;
  150. if (pInfo->cAttributes != 0)
  151. {
  152. hr = UlsLdap_CAnyAttrs::SetAnyAttrs ( NULL, // notify id (ignored)
  153. &u2ndMsgID, // out msg id
  154. 0, // notify msg (ignored)
  155. pInfo->cAttributes,
  156. (TCHAR *) ((BYTE *) pInfo + pInfo->uOffsetAttributes),
  157. m_cPrefix,
  158. m_pszPrefix,
  159. LDAP_MOD_ADD,
  160. GetServerInfo (),
  161. pszDN);
  162. if (hr != S_OK)
  163. {
  164. ldap_abandon (ld, uMsgID);
  165. pSession->Disconnect ();
  166. return hr;
  167. }
  168. }
  169. PENDING_INFO PendingInfo;
  170. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, u2ndMsgID);
  171. PendingInfo.uLdapResType = LDAP_RES_MODIFY;
  172. PendingInfo.uNotifyMsg = WM_ULS_REGISTER_APP;
  173. PendingInfo.hObject = (HANDLE) this;
  174. hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
  175. if (hr != S_OK)
  176. {
  177. ldap_abandon (ld, uMsgID);
  178. if (u2ndMsgID != INVALID_MSG_ID)
  179. ldap_abandon (ld, u2ndMsgID);
  180. pSession->Disconnect ();
  181. return hr;
  182. }
  183. *puRespID = PendingInfo.uRespID;
  184. return S_OK;
  185. }
  186. HRESULT UlsLdap_CLocalApp::UnRegister ( ULONG *puRespID )
  187. {
  188. MyAssert (puRespID != NULL);
  189. if (! IsRegRemotely ())
  190. {
  191. *puRespID = ::GetUniqueNotifyID ();
  192. SetRegNone ();
  193. PostMessage (g_hWndNotify, WM_ULS_UNREGISTER_APP, *puRespID, S_OK);
  194. return S_OK;
  195. }
  196. SetRegNone ();
  197. TCHAR *pszDN = GetDN ();
  198. if (pszDN == NULL)
  199. {
  200. MyAssert (FALSE);
  201. return ULS_E_HANDLE;
  202. }
  203. // build modify array for ldap_modify()
  204. LDAPMod **ppMod = NULL;
  205. HRESULT hr = CreateUnRegisterModArr (&ppMod);
  206. if (hr != S_OK)
  207. return hr;
  208. MyAssert (ppMod != NULL);
  209. // get the connection object
  210. UlsLdap_CSession *pSession = NULL;
  211. MyAssert (m_pUser != NULL);
  212. hr = g_pSessionContainer->GetSession (&pSession, GetServerInfo ());
  213. if (hr != S_OK)
  214. return hr;
  215. MyAssert (pSession != NULL);
  216. // get the ldap session
  217. LDAP *ld = pSession->GetLd ();
  218. MyAssert (ld != NULL);
  219. ULONG u2ndMsgID = INVALID_MSG_ID;
  220. if (UlsLdap_CAnyAttrs::GetAnyAttrsCount () != 0)
  221. {
  222. hr = UlsLdap_CAnyAttrs::RemoveAllAnyAttrs ( &u2ndMsgID,
  223. m_cPrefix,
  224. m_pszPrefix,
  225. GetServerInfo (),
  226. pszDN);
  227. if (hr != S_OK)
  228. {
  229. pSession->Disconnect ();
  230. return hr;
  231. }
  232. }
  233. // send the data over the wire
  234. ULONG uMsgID = ldap_modify (ld, pszDN, ppMod);
  235. MemFree (ppMod);
  236. if (uMsgID == -1)
  237. {
  238. hr = ::LdapError2Hresult (ld->ld_errno);
  239. pSession->Disconnect ();
  240. return hr;
  241. }
  242. // construct a pending info
  243. PENDING_INFO PendingInfo;
  244. ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, u2ndMsgID);
  245. PendingInfo.uLdapResType = LDAP_RES_MODIFY;
  246. PendingInfo.uNotifyMsg = WM_ULS_UNREGISTER_APP;
  247. // queue it
  248. hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
  249. if (hr != S_OK)
  250. {
  251. ldap_abandon (ld, uMsgID);
  252. pSession->Disconnect ();
  253. MyAssert (FALSE);
  254. }
  255. *puRespID = PendingInfo.uRespID;
  256. return hr;
  257. }
  258. HRESULT UlsLdap_CLocalApp::SetStdAttrs (
  259. ULONG *puRespID,
  260. LDAP_APPINFO *pInfo )
  261. {
  262. MyAssert (puRespID != NULL);
  263. MyAssert (pInfo != NULL);
  264. TCHAR *pszDN = GetDN ();
  265. if (pszDN == NULL)
  266. {
  267. MyAssert (FALSE);
  268. return ULS_E_HANDLE;
  269. }
  270. return UlsLdap_CStdAttrs::SetStdAttrs ( puRespID,
  271. NULL,
  272. WM_ULS_SET_APP_INFO,
  273. (VOID *) pInfo,
  274. GetServerInfo (),
  275. pszDN);
  276. }
  277. HRESULT UlsLdap_CLocalApp::SetAnyAttrs (
  278. ULONG *puRespID,
  279. ULONG cAttrs,
  280. TCHAR *pszAttrs )
  281. {
  282. MyAssert (puRespID != NULL);
  283. MyAssert (cAttrs != 0);
  284. MyAssert (pszAttrs != NULL);
  285. TCHAR *pszDN = GetDN ();
  286. if (pszDN == NULL)
  287. {
  288. MyAssert (FALSE);
  289. return ULS_E_HANDLE;
  290. }
  291. return UlsLdap_CAnyAttrs::SetAnyAttrs ( puRespID,
  292. NULL,
  293. WM_ULS_SET_APP_ATTRS,
  294. cAttrs,
  295. pszAttrs,
  296. m_cPrefix,
  297. m_pszPrefix,
  298. LDAP_MOD_REPLACE,
  299. GetServerInfo (),
  300. pszDN);
  301. }
  302. HRESULT UlsLdap_CLocalApp::RemoveAnyAttrs (
  303. ULONG *puRespID,
  304. ULONG cAttrs,
  305. TCHAR *pszAttrs )
  306. {
  307. MyAssert (puRespID != NULL);
  308. MyAssert (cAttrs != 0);
  309. MyAssert (pszAttrs != NULL);
  310. TCHAR *pszDN = GetDN ();
  311. if (pszDN == NULL)
  312. {
  313. MyAssert (FALSE);
  314. return ULS_E_HANDLE;
  315. }
  316. return UlsLdap_CAnyAttrs::RemoveAnyAttrs ( puRespID,
  317. NULL,
  318. WM_ULS_REMOVE_APP_ATTRS,
  319. cAttrs,
  320. pszAttrs,
  321. m_cPrefix,
  322. m_pszPrefix,
  323. GetServerInfo (),
  324. pszDN);
  325. }
  326. /* ---------- protected methods ----------- */
  327. /* ---------- private methods ----------- */
  328. HRESULT UlsLdap_CLocalApp::CacheInfo ( VOID *pInfo )
  329. {
  330. return CacheAppInfo ((LDAP_APPINFO *) pInfo);
  331. }
  332. HRESULT UlsLdap_CLocalApp::CacheAppInfo ( LDAP_APPINFO *pInfo )
  333. {
  334. ZeroMemory (&m_AppInfo, sizeof (m_AppInfo));
  335. TCHAR *pszName;
  336. if (::IsValidGuid (&(pInfo->guid)))
  337. {
  338. m_AppInfo.apszStdAttrValues[ENUM_APPATTR_GUID] = &m_AppInfo.szGuid[0];
  339. ::GetGuidString (&(pInfo->guid), &m_AppInfo.szGuid[0]);
  340. m_AppInfo.dwFlags |= APPOBJ_F_GUID;
  341. }
  342. if (pInfo->uOffsetName != 0)
  343. {
  344. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetName);
  345. m_AppInfo.apszStdAttrValues[ENUM_APPATTR_NAME] = pszName;
  346. m_AppInfo.dwFlags |= APPOBJ_F_NAME;
  347. }
  348. if (pInfo->uOffsetMimeType != 0)
  349. {
  350. pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetMimeType);
  351. m_AppInfo.apszStdAttrValues[ENUM_APPATTR_MIME_TYPE] = pszName;
  352. m_AppInfo.dwFlags |= APPOBJ_F_MIME_TYPE;
  353. }
  354. return S_OK;
  355. }
  356. HRESULT UlsLdap_CLocalApp::CreateRegisterModArr ( LDAPMod ***pppMod )
  357. {
  358. MyAssert (pppMod != NULL);
  359. ULONG cPrefix = m_cPrefix - 1; // skip its own app id
  360. TCHAR *pszPrefix = m_pszPrefix;
  361. ULONG cAttrs = COUNT_ENUM_APPATTR;
  362. ULONG cTotal = cPrefix + cAttrs;
  363. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  364. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  365. if (*pppMod == NULL)
  366. return ULS_E_MEMORY;
  367. LDAPMod *pMod;
  368. for (ULONG i = 0; i < cTotal; i++)
  369. {
  370. pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
  371. (*pppMod)[i] = pMod;
  372. pMod->mod_values = (TCHAR **) (pMod + 1);
  373. if (i < cPrefix)
  374. {
  375. pMod->mod_op = LDAP_MOD_REPLACE;
  376. pMod->mod_type = pszPrefix;
  377. pszPrefix += lstrlen (pszPrefix) + 1;
  378. *(pMod->mod_values) = pszPrefix;
  379. pszPrefix += lstrlen (pszPrefix) + 1;
  380. }
  381. else
  382. {
  383. pMod->mod_op = LDAP_MOD_ADD;
  384. ULONG AttrIdx = i - cPrefix;
  385. pMod->mod_type = (TCHAR *) c_apszAppStdAttrNames[AttrIdx];
  386. *(pMod->mod_values) = (m_AppInfo.apszStdAttrValues[AttrIdx] != NULL) ?
  387. m_AppInfo.apszStdAttrValues[AttrIdx] :
  388. (TCHAR *) &c_szEmptyString[0];
  389. }
  390. }
  391. ::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_ADD, ISBU_MODOP_ADD_APP);
  392. (*pppMod)[cTotal] = NULL;
  393. return S_OK;
  394. }
  395. HRESULT UlsLdap_CLocalApp::CreateUnRegisterModArr ( LDAPMod ***pppMod )
  396. {
  397. MyAssert (pppMod != NULL);
  398. ULONG cPrefix = m_cPrefix; // do NOT skip its own app id
  399. TCHAR *pszPrefix = m_pszPrefix;
  400. ULONG cAttrs = COUNT_ENUM_APPATTR;
  401. ULONG cTotal = cPrefix + cAttrs;
  402. ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
  403. *pppMod = (LDAPMod **) MemAlloc (cbMod);
  404. if (*pppMod == NULL)
  405. return ULS_E_MEMORY;
  406. LDAPMod *pMod;
  407. for (ULONG i = 0; i < cTotal; i++)
  408. {
  409. pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
  410. (*pppMod)[i] = pMod;
  411. if (i < cPrefix)
  412. {
  413. pMod->mod_op = LDAP_MOD_REPLACE;
  414. pMod->mod_type = pszPrefix;
  415. pszPrefix += lstrlen (pszPrefix) + 1;
  416. pMod->mod_values = (TCHAR **) (pMod + 1);
  417. *(pMod->mod_values) = pszPrefix;
  418. pszPrefix += lstrlen (pszPrefix) + 1;
  419. }
  420. else
  421. {
  422. pMod->mod_op = LDAP_MOD_DELETE;
  423. pMod->mod_type = (TCHAR *) c_apszAppStdAttrNames[i - cPrefix];
  424. }
  425. }
  426. ::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_DELETE, ISBU_MODOP_DELETE_APP);
  427. (*pppMod)[cTotal] = NULL;
  428. return S_OK;
  429. }
  430. HRESULT UlsLdap_CLocalApp::CreateSetStdAttrsModArr ( LDAPMod ***pppMod )
  431. {
  432. MyAssert (pppMod != NULL);
  433. HRESULT hr;
  434. ULONG cTotal = 0;
  435. hr = ::FillDefStdAttrsModArr ( pppMod,
  436. m_AppInfo.dwFlags,
  437. COUNT_ENUM_APPATTR,
  438. &cTotal,
  439. ISBU_MODOP_MODIFY_APP,
  440. m_cPrefix,
  441. m_pszPrefix);
  442. if (hr != S_OK)
  443. return hr;
  444. // start indexing
  445. ULONG i = m_cPrefix;
  446. if (m_AppInfo.dwFlags & APPOBJ_F_GUID)
  447. FillModArrAttr ((*pppMod)[i++], ENUM_APPATTR_GUID);
  448. if (m_AppInfo.dwFlags & APPOBJ_F_NAME)
  449. FillModArrAttr ((*pppMod)[i++], ENUM_APPATTR_NAME);
  450. if (m_AppInfo.dwFlags & APPOBJ_F_MIME_TYPE)
  451. FillModArrAttr ((*pppMod)[i++], ENUM_APPATTR_MIME_TYPE);
  452. MyAssert (i == cTotal);
  453. return S_OK;
  454. }
  455. VOID UlsLdap_CLocalApp::FillModArrAttr ( LDAPMod *pMod, LONG AttrIdx )
  456. {
  457. pMod->mod_type = (TCHAR *) c_apszAppStdAttrNames[AttrIdx];
  458. // single valued attr
  459. TCHAR **ppsz = (TCHAR **) (pMod + 1);
  460. pMod->mod_values = ppsz;
  461. *(pMod->mod_values) = (m_AppInfo.apszStdAttrValues[AttrIdx] != NULL) ?
  462. m_AppInfo.apszStdAttrValues[AttrIdx] :
  463. (TCHAR *) &c_szEmptyString[0];
  464. }