/* ---------------------------------------------------------------------- Module: ULS.DLL (Service Provider) File: splapp.cpp Content: This file contains the local application object. History: 10/15/96 Chu, Lon-Chan [lonchanc] Created. Copyright (c) Microsoft Corporation 1996-1997 ---------------------------------------------------------------------- */ #include "ulsp.h" #include "spinc.h" const TCHAR *c_apszAppStdAttrNames[COUNT_ENUM_APPATTR] = { TEXT ("sappid"), TEXT ("smimetype"), TEXT ("sappguid"), // app guid // protocol attributes TEXT ("sprotid"), TEXT ("sprotmimetype"), TEXT ("sport"), }; /* ---------- public methods ----------- */ UlsLdap_CLocalApp::UlsLdap_CLocalApp ( UlsLdap_CLocalUser *pUser ) { MyAssert (pUser != NULL); m_cRefs = 0; m_uSignature = APPOBJ_SIGNATURE; m_pUser = pUser; m_cPrefix = 0; m_pszPrefix = NULL; ZeroMemory (&m_AppInfo, sizeof (m_AppInfo)); SetRegNone (); } UlsLdap_CLocalApp::~UlsLdap_CLocalApp ( VOID ) { m_uSignature = (ULONG) -1; MemFree (m_pszPrefix); } ULONG UlsLdap_CLocalApp::AddRef ( VOID ) { InterlockedIncrement (&m_cRefs); return m_cRefs; } ULONG UlsLdap_CLocalApp::Release ( VOID ) { MyAssert (m_cRefs != 0); if (m_cRefs != 0) { InterlockedDecrement (&m_cRefs); } ULONG cRefs = m_cRefs; if (cRefs == 0) delete this; return cRefs; } HRESULT UlsLdap_CLocalApp::Register ( ULONG *puRespID, LDAP_APPINFO *pInfo ) { MyAssert (puRespID != NULL); MyAssert (pInfo != NULL); TCHAR *pszDN = GetDN (); if (pszDN == NULL) { MyAssert (FALSE); return ULS_E_HANDLE; } // get app name TCHAR *pszAppName = (TCHAR *) ((BYTE *) pInfo + pInfo->uOffsetName); if (*pszAppName == TEXT ('\0')) { MyAssert (FALSE); return ULS_E_PARAMETER; } // cache app info HRESULT hr = CacheAppInfo (pInfo); if (hr != S_OK) return hr; // cache generic protocol info (per KevinMa's suggestion) m_AppInfo.apszStdAttrValues[ENUM_APPATTR_PROT_NAME] = TEXT ("h323"); m_AppInfo.apszStdAttrValues[ENUM_APPATTR_PROT_MIME] = TEXT ("text/h323"); m_AppInfo.apszStdAttrValues[ENUM_APPATTR_PROT_PORT] = TEXT ("1720"); // create prefix info ULONG cbPrefix = sizeof (TCHAR) * (lstrlen (STR_APP_NAME) + lstrlen (pszAppName) + 2); ULONG cUserPrefix = GetUserPrefixCount (); TCHAR *pszUserPrefix = GetUserPrefixString (); for (ULONG i = 0; i < cUserPrefix; i++) { ULONG uLength = lstrlen (pszUserPrefix) + 1; cbPrefix += uLength * sizeof (TCHAR); pszUserPrefix += uLength; uLength = lstrlen (pszUserPrefix) + 1; cbPrefix += uLength * sizeof (TCHAR); pszUserPrefix += uLength; } TCHAR *psz = (TCHAR *) MemAlloc (cbPrefix); if (psz == NULL) return ULS_E_MEMORY; MemFree (m_pszPrefix); m_pszPrefix = psz; m_cPrefix = cUserPrefix + 1; // fill in prefix info pszUserPrefix = GetUserPrefixString (); for (i = 0; i < cUserPrefix; i++) { ULONG uLength = lstrlen (pszUserPrefix) + 1; lstrcpy (psz, pszUserPrefix); psz += uLength; pszUserPrefix += uLength; uLength = lstrlen (pszUserPrefix) + 1; lstrcpy (psz, pszUserPrefix); psz += uLength; pszUserPrefix += uLength; } lstrcpy (psz, STR_APP_NAME); psz += lstrlen (psz) + 1; lstrcpy (psz, pszAppName); // build modify array for ldap_modify() LDAPMod **ppMod = NULL; hr = CreateRegisterModArr (&ppMod); if (hr != S_OK) return hr; MyAssert (ppMod != NULL); // so far, we are done with local preparation // get the connection object UlsLdap_CSession *pSession = NULL; MyAssert (m_pUser != NULL); hr = g_pSessionContainer->GetSession (&pSession, GetServerInfo ()); if (hr != S_OK) { MemFree (ppMod); return hr; } MyAssert (pSession != NULL); // get the ldap session LDAP *ld = pSession->GetLd (); MyAssert (ld != NULL); // send the data over the wire ULONG uMsgID = ldap_modify (ld, pszDN, ppMod); MemFree (ppMod); if (uMsgID == -1) { hr = ::LdapError2Hresult (ld->ld_errno); pSession->Disconnect (); return hr; } // if there is any arbitrary attributes, // then do not create pending info and we will use // SetAttrs's pending info ULONG u2ndMsgID = INVALID_MSG_ID; if (pInfo->cAttributes != 0) { hr = UlsLdap_CAnyAttrs::SetAnyAttrs ( NULL, // notify id (ignored) &u2ndMsgID, // out msg id 0, // notify msg (ignored) pInfo->cAttributes, (TCHAR *) ((BYTE *) pInfo + pInfo->uOffsetAttributes), m_cPrefix, m_pszPrefix, LDAP_MOD_ADD, GetServerInfo (), pszDN); if (hr != S_OK) { ldap_abandon (ld, uMsgID); pSession->Disconnect (); return hr; } } PENDING_INFO PendingInfo; ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, u2ndMsgID); PendingInfo.uLdapResType = LDAP_RES_MODIFY; PendingInfo.uNotifyMsg = WM_ULS_REGISTER_APP; PendingInfo.hObject = (HANDLE) this; hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo); if (hr != S_OK) { ldap_abandon (ld, uMsgID); if (u2ndMsgID != INVALID_MSG_ID) ldap_abandon (ld, u2ndMsgID); pSession->Disconnect (); return hr; } *puRespID = PendingInfo.uRespID; return S_OK; } HRESULT UlsLdap_CLocalApp::UnRegister ( ULONG *puRespID ) { MyAssert (puRespID != NULL); if (! IsRegRemotely ()) { *puRespID = ::GetUniqueNotifyID (); SetRegNone (); PostMessage (g_hWndNotify, WM_ULS_UNREGISTER_APP, *puRespID, S_OK); return S_OK; } SetRegNone (); TCHAR *pszDN = GetDN (); if (pszDN == NULL) { MyAssert (FALSE); return ULS_E_HANDLE; } // build modify array for ldap_modify() LDAPMod **ppMod = NULL; HRESULT hr = CreateUnRegisterModArr (&ppMod); if (hr != S_OK) return hr; MyAssert (ppMod != NULL); // get the connection object UlsLdap_CSession *pSession = NULL; MyAssert (m_pUser != NULL); hr = g_pSessionContainer->GetSession (&pSession, GetServerInfo ()); if (hr != S_OK) return hr; MyAssert (pSession != NULL); // get the ldap session LDAP *ld = pSession->GetLd (); MyAssert (ld != NULL); ULONG u2ndMsgID = INVALID_MSG_ID; if (UlsLdap_CAnyAttrs::GetAnyAttrsCount () != 0) { hr = UlsLdap_CAnyAttrs::RemoveAllAnyAttrs ( &u2ndMsgID, m_cPrefix, m_pszPrefix, GetServerInfo (), pszDN); if (hr != S_OK) { pSession->Disconnect (); return hr; } } // send the data over the wire ULONG uMsgID = ldap_modify (ld, pszDN, ppMod); MemFree (ppMod); if (uMsgID == -1) { hr = ::LdapError2Hresult (ld->ld_errno); pSession->Disconnect (); return hr; } // construct a pending info PENDING_INFO PendingInfo; ::FillDefPendingInfo (&PendingInfo, ld, uMsgID, u2ndMsgID); PendingInfo.uLdapResType = LDAP_RES_MODIFY; PendingInfo.uNotifyMsg = WM_ULS_UNREGISTER_APP; // queue it hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo); if (hr != S_OK) { ldap_abandon (ld, uMsgID); pSession->Disconnect (); MyAssert (FALSE); } *puRespID = PendingInfo.uRespID; return hr; } HRESULT UlsLdap_CLocalApp::SetStdAttrs ( ULONG *puRespID, LDAP_APPINFO *pInfo ) { MyAssert (puRespID != NULL); MyAssert (pInfo != NULL); TCHAR *pszDN = GetDN (); if (pszDN == NULL) { MyAssert (FALSE); return ULS_E_HANDLE; } return UlsLdap_CStdAttrs::SetStdAttrs ( puRespID, NULL, WM_ULS_SET_APP_INFO, (VOID *) pInfo, GetServerInfo (), pszDN); } HRESULT UlsLdap_CLocalApp::SetAnyAttrs ( ULONG *puRespID, ULONG cAttrs, TCHAR *pszAttrs ) { MyAssert (puRespID != NULL); MyAssert (cAttrs != 0); MyAssert (pszAttrs != NULL); TCHAR *pszDN = GetDN (); if (pszDN == NULL) { MyAssert (FALSE); return ULS_E_HANDLE; } return UlsLdap_CAnyAttrs::SetAnyAttrs ( puRespID, NULL, WM_ULS_SET_APP_ATTRS, cAttrs, pszAttrs, m_cPrefix, m_pszPrefix, LDAP_MOD_REPLACE, GetServerInfo (), pszDN); } HRESULT UlsLdap_CLocalApp::RemoveAnyAttrs ( ULONG *puRespID, ULONG cAttrs, TCHAR *pszAttrs ) { MyAssert (puRespID != NULL); MyAssert (cAttrs != 0); MyAssert (pszAttrs != NULL); TCHAR *pszDN = GetDN (); if (pszDN == NULL) { MyAssert (FALSE); return ULS_E_HANDLE; } return UlsLdap_CAnyAttrs::RemoveAnyAttrs ( puRespID, NULL, WM_ULS_REMOVE_APP_ATTRS, cAttrs, pszAttrs, m_cPrefix, m_pszPrefix, GetServerInfo (), pszDN); } /* ---------- protected methods ----------- */ /* ---------- private methods ----------- */ HRESULT UlsLdap_CLocalApp::CacheInfo ( VOID *pInfo ) { return CacheAppInfo ((LDAP_APPINFO *) pInfo); } HRESULT UlsLdap_CLocalApp::CacheAppInfo ( LDAP_APPINFO *pInfo ) { ZeroMemory (&m_AppInfo, sizeof (m_AppInfo)); TCHAR *pszName; if (::IsValidGuid (&(pInfo->guid))) { m_AppInfo.apszStdAttrValues[ENUM_APPATTR_GUID] = &m_AppInfo.szGuid[0]; ::GetGuidString (&(pInfo->guid), &m_AppInfo.szGuid[0]); m_AppInfo.dwFlags |= APPOBJ_F_GUID; } if (pInfo->uOffsetName != 0) { pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetName); m_AppInfo.apszStdAttrValues[ENUM_APPATTR_NAME] = pszName; m_AppInfo.dwFlags |= APPOBJ_F_NAME; } if (pInfo->uOffsetMimeType != 0) { pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetMimeType); m_AppInfo.apszStdAttrValues[ENUM_APPATTR_MIME_TYPE] = pszName; m_AppInfo.dwFlags |= APPOBJ_F_MIME_TYPE; } return S_OK; } HRESULT UlsLdap_CLocalApp::CreateRegisterModArr ( LDAPMod ***pppMod ) { MyAssert (pppMod != NULL); ULONG cPrefix = m_cPrefix - 1; // skip its own app id TCHAR *pszPrefix = m_pszPrefix; ULONG cAttrs = COUNT_ENUM_APPATTR; ULONG cTotal = cPrefix + cAttrs; ULONG cbMod = ::IlsCalcModifyListSize (cTotal); *pppMod = (LDAPMod **) MemAlloc (cbMod); if (*pppMod == NULL) return ULS_E_MEMORY; LDAPMod *pMod; for (ULONG i = 0; i < cTotal; i++) { pMod = ::IlsGetModifyListMod (pppMod, cTotal, i); (*pppMod)[i] = pMod; pMod->mod_values = (TCHAR **) (pMod + 1); if (i < cPrefix) { pMod->mod_op = LDAP_MOD_REPLACE; pMod->mod_type = pszPrefix; pszPrefix += lstrlen (pszPrefix) + 1; *(pMod->mod_values) = pszPrefix; pszPrefix += lstrlen (pszPrefix) + 1; } else { pMod->mod_op = LDAP_MOD_ADD; ULONG AttrIdx = i - cPrefix; pMod->mod_type = (TCHAR *) c_apszAppStdAttrNames[AttrIdx]; *(pMod->mod_values) = (m_AppInfo.apszStdAttrValues[AttrIdx] != NULL) ? m_AppInfo.apszStdAttrValues[AttrIdx] : (TCHAR *) &c_szEmptyString[0]; } } ::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_ADD, ISBU_MODOP_ADD_APP); (*pppMod)[cTotal] = NULL; return S_OK; } HRESULT UlsLdap_CLocalApp::CreateUnRegisterModArr ( LDAPMod ***pppMod ) { MyAssert (pppMod != NULL); ULONG cPrefix = m_cPrefix; // do NOT skip its own app id TCHAR *pszPrefix = m_pszPrefix; ULONG cAttrs = COUNT_ENUM_APPATTR; ULONG cTotal = cPrefix + cAttrs; ULONG cbMod = ::IlsCalcModifyListSize (cTotal); *pppMod = (LDAPMod **) MemAlloc (cbMod); if (*pppMod == NULL) return ULS_E_MEMORY; LDAPMod *pMod; for (ULONG i = 0; i < cTotal; i++) { pMod = ::IlsGetModifyListMod (pppMod, cTotal, i); (*pppMod)[i] = pMod; if (i < cPrefix) { pMod->mod_op = LDAP_MOD_REPLACE; pMod->mod_type = pszPrefix; pszPrefix += lstrlen (pszPrefix) + 1; pMod->mod_values = (TCHAR **) (pMod + 1); *(pMod->mod_values) = pszPrefix; pszPrefix += lstrlen (pszPrefix) + 1; } else { pMod->mod_op = LDAP_MOD_DELETE; pMod->mod_type = (TCHAR *) c_apszAppStdAttrNames[i - cPrefix]; } } ::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_DELETE, ISBU_MODOP_DELETE_APP); (*pppMod)[cTotal] = NULL; return S_OK; } HRESULT UlsLdap_CLocalApp::CreateSetStdAttrsModArr ( LDAPMod ***pppMod ) { MyAssert (pppMod != NULL); HRESULT hr; ULONG cTotal = 0; hr = ::FillDefStdAttrsModArr ( pppMod, m_AppInfo.dwFlags, COUNT_ENUM_APPATTR, &cTotal, ISBU_MODOP_MODIFY_APP, m_cPrefix, m_pszPrefix); if (hr != S_OK) return hr; // start indexing ULONG i = m_cPrefix; if (m_AppInfo.dwFlags & APPOBJ_F_GUID) FillModArrAttr ((*pppMod)[i++], ENUM_APPATTR_GUID); if (m_AppInfo.dwFlags & APPOBJ_F_NAME) FillModArrAttr ((*pppMod)[i++], ENUM_APPATTR_NAME); if (m_AppInfo.dwFlags & APPOBJ_F_MIME_TYPE) FillModArrAttr ((*pppMod)[i++], ENUM_APPATTR_MIME_TYPE); MyAssert (i == cTotal); return S_OK; } VOID UlsLdap_CLocalApp::FillModArrAttr ( LDAPMod *pMod, LONG AttrIdx ) { pMod->mod_type = (TCHAR *) c_apszAppStdAttrNames[AttrIdx]; // single valued attr TCHAR **ppsz = (TCHAR **) (pMod + 1); pMod->mod_values = ppsz; *(pMod->mod_values) = (m_AppInfo.apszStdAttrValues[AttrIdx] != NULL) ? m_AppInfo.apszStdAttrValues[AttrIdx] : (TCHAR *) &c_szEmptyString[0]; }