WindowsXP-SP1/enduser/netmeeting/ulsldap/splapp.cpp
2020-09-30 16:53:49 +02:00

569 lines
13 KiB
C++

/* ----------------------------------------------------------------------
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];
}