2336 lines
62 KiB
C++
2336 lines
62 KiB
C++
#include "precomp.h"
|
||
#include "resource.h"
|
||
#include "pfnwldap.h"
|
||
#include "conf.h"
|
||
#include "cr.h"
|
||
#include <cstring.hpp>
|
||
#include <ulsreg.h>
|
||
#include "NmLdap.h"
|
||
#include "version.h"
|
||
#include "call.h"
|
||
#include "confapi.h"
|
||
#include "confutil.h"
|
||
#include "dirutil.h"
|
||
|
||
// One global instance
|
||
CNmLDAP* g_pLDAP = NULL;
|
||
CPing* g_pPing = NULL;
|
||
|
||
|
||
// This flag indicates weather or not we have loaded the LDAP dll ( WLDAP::Init() )
|
||
/*static*/ bool CNmLDAP::ms_bLdapDLLLoaded = false;
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
// Helper Macros
|
||
|
||
// the ldap_modify function takes an LDAPMod** type
|
||
// If it took an array of LDAPMod ( an LDAPMod* type )
|
||
// Then life would be easier for us to make static lists
|
||
// Unfortunately, this is not how it works, so we have macros
|
||
// to pretty things up ( and hopefully not to confuse anyone )
|
||
|
||
// This is to declare an LDAPMod with one val
|
||
#define DECLARE_LDAP_MOD( t, x, y )\
|
||
LPTSTR aVals_##x[] = { y, NULL };\
|
||
LDAPMod LDAPMod_##x = { t, _T(#x), aVals_##x }
|
||
|
||
// This is to declare an LDAPMod with 2 vals
|
||
#define DECLARE_LDAP_MOD2( t, x, y1, y2 )\
|
||
LPTSTR aVals_##x[] = { y1, y2, NULL };\
|
||
LDAPMod LDAPMod_##x = { t, _T(#x), aVals_##x }
|
||
|
||
#define LDAP_MOD_ENTRY( x ) &LDAPMod_##x
|
||
#define LDAP_MOD_ADD_ENTRY( x ) &LDAPMod_add_##x
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
// Some helpful deffinitions
|
||
|
||
#define LDAP_REFRESH_BASE_DN _T("objectClass=RTPerson")
|
||
#define RESOLVE_USER_SEARCH_FILTER _T("(&(objectClass=RTPerson)(cn=%s))")
|
||
|
||
|
||
//NOTE: The LDAP_REFRESH_FILTER... notice the sttl=10... aparently, this is how you request the
|
||
// server to restart the TTL countdown... the sttl= value can be anything BUT '*' ( the value you would
|
||
// expecte it to be... ) This is a link to the "Dynamir Ldap Extension RFC" if you want more info
|
||
// http://www.critical-angle.com/ldapworld/draft-ietf-asid-ldapv3ext-04.txt
|
||
|
||
#define LDAP_REFRESH_FILTER _T("(&(objectClass=RTPerson)(cn=%s)(sttl=10))")
|
||
|
||
|
||
#define LOGIN_USER_FILTER _T("c=-,o=Microsoft,cn=%s,objectClass=RTPerson")
|
||
#define IP_ADDRESS_ATTR_NAME _T("sipaddress")
|
||
#define STTL_ATTR_NAME _T("sttl")
|
||
#define CNmLDAP_WCNAME _T("CNmLDAP_WCNAME")
|
||
|
||
#define LDAP_MODOP_ADDAPP _T("0")
|
||
#define LDAP_MODOP_DELETEAPP _T("1")
|
||
#define LDAP_MODOP_MODIFYUSER _T("2")
|
||
#define LDAP_MODOP_MODIFYAPP _T("3")
|
||
|
||
#define LDAP_ATTR_FALSE _T("0")
|
||
#define LDAP_ATTR_TRUE _T("1")
|
||
#define LDAP_ATTR_BUSINESS _T("2")
|
||
|
||
// We are not using the country name anymore, but we can't leave the country
|
||
// field blank ( empty string ), it is just the way that SiteServer is written...
|
||
#define LDAP_ATTR_DUMMY_COUNTRYNAME _T("-")
|
||
|
||
#define INVALID_MSG_ID ((ULONG) -1) // same as ldap_****()
|
||
#define LDAP_RESULT_ERROR ((ULONG) -1)
|
||
#define LDAP_RESULT_TIMEOUT 0
|
||
|
||
// When the bind helper thread function gets the result to bind_s function
|
||
// it passes it to this thread via PostMessage( m_hWndHidder, WM_USER_BIND_COMPLETE, ret, err )
|
||
#define WM_USER_BIND_COMPLETE (WM_APP + 1) // wParam = Return code from bind_s, lParam = GetLastError()
|
||
#define WM_NEED_RELOGON (WM_APP + 2)
|
||
|
||
|
||
CNmLDAP::CNmLDAP()
|
||
: m_State(Uninitialized),
|
||
m_pKeepAlive(NULL),
|
||
m_hWndHidden(NULL),
|
||
m_pLdap(NULL),
|
||
m_ResultPollTimer(0),
|
||
m_LogoffTimer(0),
|
||
m_uMsgID(INVALID_MSG_ID),
|
||
m_CurrentOp(Op_NoOp),
|
||
m_bVisible(true),
|
||
m_bDirty(false),
|
||
m_bRefreshAfterBindCompletes(false),
|
||
m_bLogoffAfterBindCompletes(false),
|
||
m_bSendInCallAttrWhenDone(false),
|
||
m_bInCall(false),
|
||
m_hEventWaitForLogoffDone(NULL),
|
||
m_hBindThread(NULL),
|
||
m_iPort(DEFAULT_LDAP_PORT),
|
||
m_bAudioHardware(false),
|
||
m_bVideoHardware(false)
|
||
|
||
|
||
{
|
||
DBGENTRY(CNmLDAP::CNmLDAP);
|
||
|
||
SetLoggedOn( false );
|
||
|
||
DBGEXIT(CNmLDAP::CNmLDAP);
|
||
}
|
||
|
||
CNmLDAP::~CNmLDAP()
|
||
{
|
||
DBGENTRY(CNmLDAP::~CNmLDAP);
|
||
|
||
if (NULL != m_pKeepAlive)
|
||
{
|
||
m_pKeepAlive->End(TRUE); // synchronous end
|
||
m_pKeepAlive = NULL;
|
||
}
|
||
|
||
if((m_State != Idle) && (m_State != Uninitialized))
|
||
{
|
||
// Make sure that someone at least has already called Logoff()
|
||
ASSERT((LoggingOff == m_State) || (Op_Logoff == m_CurrentOp));
|
||
|
||
// We are logging off, but we would like to wait a while to make sure that
|
||
// all of our async operations are completed... We don't want to wait too long,
|
||
// Though... Basically we set a timer to pass a message to us... if we get that
|
||
// message, we signal m_hEventWaitForLogoffDone.... if any of the async operations
|
||
// complete during this time, they will also signal this event....We make sure to
|
||
// hawe a message loop ( AtlWaitWithWessageLoop ) so that our wndproc will be called
|
||
m_hEventWaitForLogoffDone = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||
|
||
if(m_hEventWaitForLogoffDone)
|
||
{
|
||
m_LogoffTimer = ::SetTimer(m_hWndHidden, WaitForLogoffTimer, LOGOFF_WAIT_INTERVAL, NULL);
|
||
if(m_LogoffTimer)
|
||
{
|
||
AtlWaitWithMessageLoop(m_hEventWaitForLogoffDone);
|
||
}
|
||
|
||
CloseHandle(m_hEventWaitForLogoffDone);
|
||
m_hEventWaitForLogoffDone = NULL;
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("Create Event failed"));
|
||
}
|
||
|
||
if( Binding == m_State )
|
||
{
|
||
WARNING_OUT(("Aborting an ldap_bind because we are closing down in ~CNmLDAP"));
|
||
TerminateThread(m_hBindThread, 0);
|
||
CloseHandle(m_hBindThread);
|
||
}
|
||
else if(Idle != m_State)
|
||
{
|
||
WARNING_OUT(("Aborting pending LDAP operation in ~CNmLDAP"));
|
||
_AbandonAllAndSetToIdle();
|
||
}
|
||
}
|
||
|
||
if( NULL != m_hWndHidden )
|
||
{
|
||
DestroyWindow( m_hWndHidden );
|
||
m_hWndHidden = NULL;
|
||
}
|
||
|
||
m_State = Uninitialized;
|
||
|
||
SetLoggedOn( false );
|
||
|
||
DBGEXIT(CNmLDAP::~CNmLDAP);
|
||
}
|
||
|
||
HRESULT CNmLDAP::_bCallChangedHelper()
|
||
{
|
||
TRACE_OUT(("CNmLDAP::_bCallChangedHelper:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
HRESULT hr = S_OK;
|
||
|
||
if( IsLoggedOn() || IsBusy() )
|
||
{
|
||
if(LoggedIn == m_State)
|
||
{
|
||
// We simply have to bind and call ldap_modify
|
||
m_CurrentOp = Op_Modifying_InCallAttr;
|
||
hr = _BindAsync();
|
||
}
|
||
else if((SettingAppInfo == m_State) ||
|
||
(ModifyingAttrs == m_State) ||
|
||
(AddingUser == m_State)
|
||
)
|
||
{
|
||
// the other states will be calling ldap_mod( user Attributes ) which will pick up
|
||
// the change to m_bInCall. The states listed above are the ones that occur after
|
||
// the user attributes have been sent to the server... There are also other states
|
||
// that logoff, so they don't care about sending the update to the user attribute to the server
|
||
m_bSendInCallAttrWhenDone = true;
|
||
}
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_bCallChangedHelper:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::OnCallStarted()
|
||
{
|
||
|
||
DBGENTRY(CNmLDAP::OnCallStarted);
|
||
TRACE_OUT(("CNmLDAP::OnCallStarted:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
HRESULT hr = S_OK;
|
||
|
||
ASSERT(ms_bLdapDLLLoaded);
|
||
|
||
if( !m_bInCall )
|
||
{
|
||
m_bInCall = true;
|
||
hr = _bCallChangedHelper();
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::OnCallStarted:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::OnCallStarted,hr);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::OnCallEnded()
|
||
{
|
||
DBGENTRY(CNmLDAP::OnCallEnded);
|
||
TRACE_OUT(("CNmLDAP::OnCallEnded:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
HRESULT hr = S_OK;
|
||
|
||
ASSERT(ms_bLdapDLLLoaded);
|
||
|
||
if( m_bInCall )
|
||
{
|
||
m_bInCall = false;
|
||
hr = _bCallChangedHelper();
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::OnCallEnded:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::OnCallEnded,hr);
|
||
return hr;
|
||
}
|
||
|
||
|
||
bool CNmLDAP::IsLoggedOn() const
|
||
{
|
||
DBGENTRY(CNmLDAP::IsLoggedOn);
|
||
TRACE_OUT(("CNmLDAP::IsLoggedOn:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
bool bRet = ( ( LoggedIn == m_State ) ||
|
||
( ModifyingAttrs == m_State ) ||
|
||
( Op_Refresh_Logoff == m_CurrentOp ) ||
|
||
( Op_Modifying_InCallAttr == m_CurrentOp )
|
||
);
|
||
|
||
TRACE_OUT(("CNmLDAP::IsLoggedOn:exit(%d): m_State:%d: m_currentOp:%d", bRet, m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::IsLoggedOn);
|
||
|
||
return bRet;
|
||
}
|
||
|
||
bool CNmLDAP::IsLoggingOn() const
|
||
{
|
||
DBGENTRY(CNmLDAP::IsLoggingOn);
|
||
TRACE_OUT(("CNmLDAP::IsLoggingOn:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
bool bRet = ( ( AddingUser == m_State ) ||
|
||
( UserAdded == m_State ) ||
|
||
( SettingAppInfo == m_State ) ||
|
||
( Op_Logon == m_CurrentOp )
|
||
);
|
||
|
||
TRACE_OUT(("CNmLDAP::IsLoggingOn:exit(%d): m_State:%d: m_currentOp:%d", bRet, m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::IsLoggingOn);
|
||
|
||
return bRet;
|
||
}
|
||
|
||
bool CNmLDAP::IsBusy() const
|
||
{
|
||
DBGENTRY(CNmLDAP::IsBusy);
|
||
TRACE_OUT(("CNmLDAP::IsBusy:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
bool bRet = !((LoggedIn == m_State) || ( Idle == m_State ) || (Uninitialized == m_State));
|
||
|
||
TRACE_OUT(("CNmLDAP::IsBusy:exit(%d): m_State:%d: m_currentOp:%d", bRet, m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::IsBusy);
|
||
|
||
return bRet;
|
||
}
|
||
|
||
|
||
void CNmLDAP::_MakeStatusText(UINT uResID, LPTSTR psz, UINT cch) const
|
||
{
|
||
const TCHAR * const server = CDirectoryManager::get_displayName( m_strCurrentServer );
|
||
|
||
LPCTSTR pszFmt = RES2T(uResID);
|
||
LPTSTR pszStr = reinterpret_cast<LPTSTR>(_alloca(lstrlen(pszFmt) + lstrlen(server) - 1));
|
||
if(pszStr)
|
||
{
|
||
wsprintf(pszStr, pszFmt, server);
|
||
lstrcpyn(psz, pszStr, cch);
|
||
}
|
||
}
|
||
|
||
|
||
HRESULT CNmLDAP::GetStatusText(LPTSTR psz, int cch, UINT *idIcon ) const
|
||
{
|
||
DBGENTRY(CNmLDAP::GetStatusText);
|
||
|
||
UINT idDummy;
|
||
if (NULL == idIcon)
|
||
{
|
||
// Just so we don't need to do switches all over the place
|
||
idIcon = &idDummy;
|
||
}
|
||
|
||
HRESULT hr = S_OK;
|
||
|
||
TRACE_OUT(("m_State = %d", m_State));
|
||
TRACE_OUT(("CNmLDAP::GetStatusText:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
if(psz)
|
||
{
|
||
if( cch > 1 )
|
||
{
|
||
switch(m_State)
|
||
{
|
||
case LoggedIn:
|
||
case ModifyingAttrs:
|
||
*idIcon = IDI_NET;
|
||
_MakeStatusText(ID_STATUS_LOGGEDON_FORMAT, psz, cch);
|
||
break;
|
||
|
||
case Binding:
|
||
{
|
||
switch(m_CurrentOp)
|
||
{
|
||
case Op_Logon:
|
||
*idIcon = IDS_STATUS_WAITING;
|
||
_MakeStatusText(ID_STATUS_LOGON_FORMAT, psz, cch);
|
||
break;
|
||
|
||
case Op_Modifying_InCallAttr:
|
||
*idIcon = IDI_NET;
|
||
_MakeStatusText(ID_STATUS_LOGGEDON_FORMAT, psz, cch);
|
||
break;
|
||
|
||
case Op_Refresh_Logoff:
|
||
if( lstrcmpi(m_strServer,m_strCurrentServer))
|
||
{
|
||
*idIcon = IDS_STATUS_WAITING;
|
||
_MakeStatusText(ID_STATUS_LOGOFF_FORMAT, psz, cch);
|
||
}
|
||
else
|
||
{
|
||
*idIcon = IDI_NET;
|
||
_MakeStatusText(ID_STATUS_LOGGEDON_FORMAT, psz, cch);
|
||
}
|
||
break;
|
||
|
||
case Op_Logoff:
|
||
*idIcon = IDI_NETGRAY;
|
||
lstrcpyn(psz, RES2T(ID_STATUS_LOGGEDOFF), cch);
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
|
||
case AddingUser:
|
||
case UserAdded:
|
||
case SettingAppInfo:
|
||
*idIcon = IDS_STATUS_WAITING;
|
||
_MakeStatusText(ID_STATUS_LOGON_FORMAT, psz, cch);
|
||
break;
|
||
|
||
|
||
case LoggingOff:
|
||
*idIcon = IDS_STATUS_WAITING;
|
||
_MakeStatusText(ID_STATUS_LOGOFF_FORMAT, psz, cch);
|
||
break;
|
||
|
||
case Bound:
|
||
case Idle:
|
||
case Uninitialized:
|
||
*idIcon = IDI_NETGRAY;
|
||
lstrcpyn(psz, RES2T(ID_STATUS_LOGGEDOFF), cch);
|
||
break;
|
||
|
||
default:
|
||
ERROR_OUT(("Not a regognized state: %d", m_State));
|
||
break;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
hr = E_INVALIDARG;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hr = E_POINTER;
|
||
}
|
||
|
||
|
||
|
||
TRACE_OUT(("CNmLDAP::GetStatusText:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::GetStatusText,hr);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::OnSettingsChanged()
|
||
{
|
||
DBGENTRY(CNmLDAP::OnSettingsChanged);
|
||
TRACE_OUT(("CNmLDAP::OnSettingsChanged:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
HRESULT hr = S_OK;
|
||
ASSERT(ms_bLdapDLLLoaded);
|
||
|
||
if(S_OK == _GetUserSettingsFromRegistryAndGlobals())
|
||
{
|
||
hr = OnReLogon();
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::OnSettingsChanged:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::OnSettingsChanged,hr);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::OnReLogon(void)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
ASSERT(ms_bLdapDLLLoaded);
|
||
|
||
m_bDirty = true;
|
||
|
||
if(IsLoggedOn() || IsBusy())
|
||
{
|
||
hr = _RefreshServer();
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::_RefreshServer()
|
||
{
|
||
DBGENTRY(CNmLDAP::_RefreshServer);
|
||
TRACE_OUT(("CNmLDAP::_RefreshServer:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
HRESULT hr = S_OK;
|
||
|
||
ASSERT(ms_bLdapDLLLoaded);
|
||
|
||
if( m_bDirty )
|
||
{
|
||
if(Binding == m_State)
|
||
{
|
||
if(Op_Logon == m_CurrentOp) // we are logging on and haven't sent any user information yet
|
||
{
|
||
// Check to see if we have not changed the server name
|
||
if( !lstrcmpi(m_strServer, CDirectoryManager::get_defaultServer() ) )
|
||
{
|
||
// Simply update the user settings
|
||
_GetUserSettingsFromRegistryAndGlobals();
|
||
}
|
||
else
|
||
{
|
||
// Since the server has changed, we have to do a logoff(from old)/logon(to new)
|
||
_InternalLogoff(true);
|
||
}
|
||
}
|
||
else if(m_CurrentOp != Op_Logoff)
|
||
{
|
||
// If we are in the middle of a bind operation, which happens
|
||
// in another thread, we just have to wait for it to complete
|
||
// before we go any further
|
||
m_bRefreshAfterBindCompletes = true;
|
||
}
|
||
}
|
||
else if(Idle == m_State)
|
||
{
|
||
_GetUserSettingsFromRegistryAndGlobals();
|
||
LogonAsync();
|
||
}
|
||
else
|
||
{
|
||
_InternalLogoff(true);
|
||
}
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_RefreshServer:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::_RefreshServer,hr);
|
||
return hr;
|
||
}
|
||
|
||
void CNmLDAP::_AbandonAllAndSetState(eState new_state)
|
||
{
|
||
TRACE_OUT(("CNmLDAP::_AbandonAllAndSetState:enter: new_state=%d, m_State:%d: m_currentOp:%d", new_state, m_State, m_CurrentOp));
|
||
if(m_ResultPollTimer)
|
||
{
|
||
::KillTimer(m_hWndHidden,m_ResultPollTimer);
|
||
m_ResultPollTimer = 0;
|
||
}
|
||
|
||
if(m_pLdap)
|
||
{
|
||
if( INVALID_MSG_ID != m_uMsgID )
|
||
{
|
||
WLDAP::ldap_abandon(m_pLdap, m_uMsgID);
|
||
}
|
||
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
}
|
||
m_pLdap = NULL;
|
||
m_uMsgID = INVALID_MSG_ID;
|
||
m_State = new_state;
|
||
m_CurrentOp = Op_NoOp;
|
||
|
||
SetLoggedOn( IsLoggedOn() );
|
||
TRACE_OUT(("CNmLDAP::_AbandonAllAndSetState:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
}
|
||
|
||
|
||
HRESULT CNmLDAP::_InternalLogoff(bool bRefreshLogoff)
|
||
{
|
||
DBGENTRY(CNmLDAP::_InternalLogoff);
|
||
TRACE_OUT(("CNmLDAP::_InternalLogoff:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
HRESULT hr = S_OK;
|
||
|
||
ASSERT(ms_bLdapDLLLoaded);
|
||
|
||
if( ( LoggingOff != m_State ) && ( Idle != m_State ) )
|
||
{
|
||
if(bRefreshLogoff)
|
||
{
|
||
m_CurrentOp = Op_Refresh_Logoff;
|
||
|
||
// If the server names are different, this means
|
||
// that we should display "logging off" XXX
|
||
if( lstrcmpi(m_strServer, m_strCurrentServer) )
|
||
{
|
||
_OnLoggingOff();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_OnLoggingOff();
|
||
m_CurrentOp = Op_Logoff;
|
||
}
|
||
|
||
if( LoggedIn == m_State )
|
||
{
|
||
hr = _BindAsync();
|
||
}
|
||
else if( Binding == m_State )
|
||
{
|
||
m_bLogoffAfterBindCompletes = true;
|
||
}
|
||
else if( (INVALID_MSG_ID != m_uMsgID ) && (NULL != m_pLdap ))
|
||
{
|
||
// Kill the timer
|
||
ASSERT(m_ResultPollTimer);
|
||
::KillTimer(m_hWndHidden,m_ResultPollTimer);
|
||
m_ResultPollTimer = 0;
|
||
|
||
// Abandon the current op
|
||
WLDAP::ldap_abandon(m_pLdap, m_uMsgID);
|
||
m_uMsgID = INVALID_MSG_ID;
|
||
m_State = Bound;
|
||
|
||
SetLoggedOn( IsLoggedOn() );
|
||
}
|
||
|
||
if(Bound == m_State)
|
||
{
|
||
ASSERT(m_pLdap);
|
||
_DeleteUser();
|
||
}
|
||
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_InternalLogoff:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::_InternalLogoff,hr);
|
||
return hr;
|
||
}
|
||
HRESULT CNmLDAP::Logoff()
|
||
{
|
||
DBGENTRY(CNmLDAP::Logoff);
|
||
TRACE_OUT(("CNmLDAP::Logoff:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
HRESULT hr = _InternalLogoff(false);
|
||
|
||
TRACE_OUT(("CNmLDAP::Logoff:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::Logoff,hr);
|
||
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::Initialize( HINSTANCE hInst )
|
||
{
|
||
HRESULT hr = S_OK;
|
||
DBGENTRY(CNmLDAP::Initialize);
|
||
TRACE_OUT(("CNmLDAP::Initialize:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
ASSERT( Uninitialized == m_State );
|
||
|
||
if( ms_bLdapDLLLoaded || SUCCEEDED( hr = WLDAP::Init()))
|
||
{
|
||
ms_bLdapDLLLoaded = true;
|
||
|
||
////////////////////////////////////////
|
||
// Initialize user data
|
||
_GetUserSettingsFromRegistryAndGlobals();
|
||
|
||
////////////////////////////////////////
|
||
// Initialize hidden Window
|
||
|
||
|
||
WNDCLASS wcHidden =
|
||
{
|
||
0L,
|
||
_sWndProc,
|
||
0,
|
||
0,
|
||
hInst,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
CNmLDAP_WCNAME
|
||
};
|
||
|
||
if(RegisterClass(&wcHidden))
|
||
{
|
||
m_hWndHidden = ::CreateWindow( CNmLDAP_WCNAME, g_szEmpty, 0, 0, 0, 0, 0, NULL, NULL, hInst, this);
|
||
|
||
if( m_hWndHidden )
|
||
{
|
||
m_State = Idle;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
}
|
||
else
|
||
{
|
||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("WLDAP::Init failed ( could not load wldap32.dll? )"));
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::Initialize:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::Initialize,hr);
|
||
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::_GetUserSettingsFromRegistryAndGlobals()
|
||
{
|
||
DBGENTRY(CNmLDAP::_GetUserSettingsFromRegistryAndGlobals);
|
||
TRACE_OUT(("CNmLDAP::_GetUserSettingsFromRegistryAndGlobals:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
HRESULT hr = S_FALSE; // this would indicate that nothing changed
|
||
|
||
RegEntry reULS(ISAPI_CLIENT_KEY, HKEY_CURRENT_USER);
|
||
|
||
if(lstrcmpi(m_strSurName, reULS.GetString(ULS_REGKEY_LAST_NAME)))
|
||
{
|
||
hr = S_OK;
|
||
m_strSurName = reULS.GetString(ULS_REGKEY_LAST_NAME);
|
||
}
|
||
|
||
if(lstrcmpi(m_strGivenName, reULS.GetString(ULS_REGKEY_FIRST_NAME)))
|
||
{
|
||
hr = S_OK;
|
||
m_strGivenName = reULS.GetString(ULS_REGKEY_FIRST_NAME);
|
||
}
|
||
|
||
if(lstrcmpi(m_strEmailName, reULS.GetString(REGVAL_ULS_EMAIL_NAME)))
|
||
{
|
||
hr = S_OK;
|
||
m_strEmailName = reULS.GetString(REGVAL_ULS_EMAIL_NAME);
|
||
}
|
||
|
||
if(lstrcmpi(m_strComment, reULS.GetString(ULS_REGKEY_COMMENTS)))
|
||
{
|
||
hr = S_OK;
|
||
m_strComment = reULS.GetString(ULS_REGKEY_COMMENTS);
|
||
}
|
||
|
||
if(lstrcmpi(m_strLocation, reULS.GetString(ULS_REGKEY_LOCATION)))
|
||
{
|
||
hr = S_OK;
|
||
m_strLocation = reULS.GetString(ULS_REGKEY_LOCATION);
|
||
}
|
||
|
||
if(lstrcmpi(m_strSecurityToken, reULS.GetString(ULS_REGKEY_CLIENT_ID)))
|
||
{
|
||
hr = S_OK;
|
||
m_strSecurityToken = reULS.GetString(ULS_REGKEY_CLIENT_ID);
|
||
}
|
||
|
||
|
||
if(*m_strSecurityToken == '\0')
|
||
{ // The string was not found...
|
||
|
||
// When we log onto the LDAP server, we pass a fairly unique ID
|
||
// This is passed as the value to the ssecurity attribute
|
||
// In the case that NetMeeting goes away without actually logging
|
||
// off of the ILS server, when NetMeeting tries to log back on,
|
||
// it will pass this unique ID... if the server has not closed the
|
||
// session account for the user, the server uses this ID to "authenticate"
|
||
// that we are the same user as the last session...
|
||
TCHAR szNewClientID[MAX_PATH];
|
||
wsprintf(szNewClientID,"%lu", ::GetTickCount());
|
||
m_strSecurityToken = szNewClientID;
|
||
reULS.SetValue(ULS_REGKEY_CLIENT_ID,szNewClientID);
|
||
hr = S_OK;
|
||
}
|
||
|
||
if( lstrcmpi(m_strServer, CDirectoryManager::get_defaultServer()))
|
||
{
|
||
hr = S_OK;
|
||
m_strServer = CDirectoryManager::get_defaultServer();
|
||
m_iPort = DEFAULT_LDAP_PORT;
|
||
}
|
||
|
||
|
||
if(m_bVisible != (!reULS.GetNumber(ULS_REGKEY_DONT_PUBLISH, REGVAL_ULS_DONT_PUBLISH_DEFAULT)))
|
||
{
|
||
m_bVisible = !reULS.GetNumber(ULS_REGKEY_DONT_PUBLISH, REGVAL_ULS_DONT_PUBLISH_DEFAULT);
|
||
hr = S_OK;
|
||
}
|
||
|
||
if(m_bAudioHardware != (0 != (g_uMediaCaps & CAPFLAG_SEND_AUDIO)))
|
||
{
|
||
m_bAudioHardware = (0 != (g_uMediaCaps & CAPFLAG_SEND_AUDIO));
|
||
hr = S_OK;
|
||
}
|
||
|
||
if(m_bVideoHardware != (0 != (g_uMediaCaps & CAPFLAG_SEND_VIDEO)))
|
||
{
|
||
m_bVideoHardware = (0 != (g_uMediaCaps & CAPFLAG_SEND_VIDEO));
|
||
hr = S_OK;
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_GetUserSettingsFromRegistryAndGlobals:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::_GetUserSettingsFromRegistryAndGlobals,hr);
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT CNmLDAP::LogonAsync( LPCTSTR pcszServer /*=NULL*/)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
DBGENTRY(CNmLDAP::LogonAsync);
|
||
TRACE_OUT(("CNmLDAP::LogonAsync:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
// Idle // Normal logon
|
||
//Binding
|
||
// Op_Logoff // Change it to logon refresh
|
||
// Bound // ldap_umbind-> Logon normal
|
||
// LoggingOff // Change to Op_Refresh_Logoff
|
||
// Uninitialized // return error
|
||
// AddingUser // do nothing
|
||
// UserAdded // do nothing
|
||
// SettingAppInfo // do nothing
|
||
// ModifyingAttrs // do nothing
|
||
// LoggedIn // do nothing
|
||
// Op_Refresh_Logoff // Do nothing
|
||
// Op_Modifying_InCallAttr // Do Nothing
|
||
// Op_Logon // Do Nothing
|
||
|
||
if( Uninitialized != m_State)
|
||
{
|
||
if(Bound == m_State)
|
||
{
|
||
_AbandonAllAndSetToIdle();
|
||
}
|
||
|
||
if(Idle == m_State)
|
||
{
|
||
if(pcszServer)
|
||
{
|
||
m_strServer = pcszServer;
|
||
m_iPort = DEFAULT_LDAP_PORT;
|
||
}
|
||
else
|
||
{
|
||
if(!IsLoggedOn())
|
||
{
|
||
_GetUserSettingsFromRegistryAndGlobals();
|
||
}
|
||
}
|
||
|
||
m_strCurrentServer = m_strServer;
|
||
|
||
g_pCCallto->SetIlsServerName( m_strCurrentServer );
|
||
|
||
TCHAR* szDN = new TCHAR[ lstrlen( LOGIN_USER_FILTER ) + lstrlen(m_strEmailName) + 1 ];
|
||
if( szDN )
|
||
{
|
||
wsprintf(szDN, LOGIN_USER_FILTER, m_strEmailName);
|
||
m_strCurrentDN = szDN;
|
||
|
||
delete [] szDN;
|
||
|
||
m_CurrentOp = Op_Logon;
|
||
hr = _BindAsync();
|
||
if( SUCCEEDED(hr) )
|
||
{
|
||
_OnLoggingOn();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hr = E_OUTOFMEMORY;
|
||
}
|
||
}
|
||
else if((Op_Logoff == m_CurrentOp) || (LoggingOff == m_State))
|
||
{
|
||
m_CurrentOp = Op_Refresh_Logoff;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hr = E_FAIL;
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::LogonAsync:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::LogonAsync,hr);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT CNmLDAP::_BindAsync()
|
||
{
|
||
DBGENTRY(CNmLDAP::_BindAsync);
|
||
TRACE_OUT(("CNmLDAP::_BindAsync:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
ASSERT(( LoggedIn == m_State ) || ( Idle == m_State ));
|
||
ASSERT( m_CurrentOp != Op_NoOp );
|
||
ASSERT(m_hBindThread == NULL);
|
||
|
||
HRESULT hr = S_OK;
|
||
|
||
// Set our state to Binding
|
||
m_State = Binding;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
|
||
// Start the bind in another thread
|
||
DWORD dwBindThreadID = 0;
|
||
m_hBindThread = CreateThread(NULL, 0, _sAsyncBindThreadFn, this, 0, &dwBindThreadID);
|
||
|
||
if(NULL == m_hBindThread)
|
||
{
|
||
ERROR_OUT(("CreateThread failed"));
|
||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
m_pLdap = NULL;
|
||
m_CurrentOp = Op_NoOp;
|
||
m_State = Idle;
|
||
}
|
||
|
||
SetLoggedOn( IsLoggedOn() );
|
||
|
||
TRACE_OUT(("CNmLDAP::_BindAsync:exit(0x%08X): m_State:%d: m_currentOp:%d", hr, m_State, m_CurrentOp));
|
||
DBGEXIT_HR(CNmLDAP::_BindAsync,hr);
|
||
return hr;
|
||
}
|
||
|
||
|
||
/*static*/
|
||
DWORD CNmLDAP::_sAsyncBindThreadFn(LPVOID lpParameter)
|
||
{
|
||
|
||
DBGENTRY(CNmLDAP::_sAsyncBindThreadFn);
|
||
|
||
ASSERT(lpParameter);
|
||
|
||
CNmLDAP* pThis = reinterpret_cast<CNmLDAP*>(lpParameter);
|
||
ASSERT(pThis);
|
||
ULONG ulRet = LDAP_OPERATIONS_ERROR;
|
||
ULONG ulErr = ERROR_INVALID_HANDLE;
|
||
if( pThis )
|
||
{
|
||
WSADATA wsaData;
|
||
|
||
if( WSAStartup( 0x0101, &wsaData ) == 0 )
|
||
{
|
||
if( wsaData.wVersion > 1 )
|
||
{
|
||
pThis->m_pLdap = WLDAP::ldap_init( const_cast<LPTSTR>((LPCTSTR)pThis->m_strCurrentServer), pThis->m_iPort );
|
||
|
||
if( pThis->m_pLdap )
|
||
{
|
||
::SetLastError(NO_ERROR);
|
||
ulRet = WLDAP::ldap_bind_s(pThis->m_pLdap, const_cast<LPTSTR>(g_szEmpty), const_cast<LPTSTR>(g_szEmpty), LDAP_AUTH_SIMPLE );
|
||
|
||
if( ulRet == LDAP_SUCCESS )
|
||
{
|
||
ulErr = ::GetLastError();
|
||
::SendMessage(pThis->m_hWndHidden, WM_USER_BIND_COMPLETE, ulRet, ulErr);
|
||
}
|
||
else if( pThis->m_iPort == DEFAULT_LDAP_PORT )
|
||
{
|
||
WLDAP::ldap_unbind( pThis->m_pLdap );
|
||
pThis->m_pLdap = WLDAP::ldap_init( const_cast<LPTSTR>((LPCTSTR)pThis->m_strCurrentServer), ALTERNATE_LDAP_PORT); // Automatically retry with alternate port...
|
||
|
||
if( pThis->m_pLdap != NULL )
|
||
{
|
||
::SetLastError(NO_ERROR);
|
||
ulRet = WLDAP::ldap_bind_s(pThis->m_pLdap, const_cast<LPTSTR>(g_szEmpty), const_cast<LPTSTR>(g_szEmpty), LDAP_AUTH_SIMPLE );
|
||
|
||
if( ulRet == LDAP_SUCCESS )
|
||
{
|
||
pThis->m_iPort = ALTERNATE_LDAP_PORT;
|
||
}
|
||
|
||
ulErr = ::GetLastError();
|
||
::SendMessage(pThis->m_hWndHidden, WM_USER_BIND_COMPLETE, ulRet, ulErr);
|
||
}
|
||
else
|
||
{
|
||
TRACE_OUT(("ldap_init failed"));
|
||
pThis->m_State = Idle;
|
||
pThis->m_CurrentOp = Op_NoOp;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TRACE_OUT(("ldap_init failed"));
|
||
pThis->m_State = Idle;
|
||
pThis->m_CurrentOp = Op_NoOp;
|
||
}
|
||
}
|
||
|
||
WSACleanup();
|
||
}
|
||
}
|
||
|
||
DBGEXIT(CNmLDAP::_sAsyncBindThreadFn);
|
||
|
||
return ulRet;
|
||
}
|
||
|
||
|
||
LRESULT CNmLDAP::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
LRESULT lr = TRUE;
|
||
DBGENTRY(CNmLDAP::WndProc);
|
||
|
||
switch( uMsg )
|
||
{
|
||
case WM_USER_BIND_COMPLETE:
|
||
_OnUserBindComplete((INT)wParam, (DWORD)lParam);
|
||
break;
|
||
|
||
case WM_TIMER:
|
||
lr = FALSE; // This means that we handle the message
|
||
_OnTimer(wParam);
|
||
break;
|
||
|
||
case WM_NEED_RELOGON:
|
||
OnReLogon();
|
||
break;
|
||
|
||
default:
|
||
lr = DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||
break;
|
||
}
|
||
|
||
DBGEXIT_ULONG(CNmLDAP::WndProc,lr);
|
||
return lr;
|
||
}
|
||
|
||
|
||
void CNmLDAP::_OnTimer(UINT_PTR TimerID)
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnTimer);
|
||
TRACE_OUT(("CNmLDAP::_OnTimer:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
// We check the timer ID values first because we may have killed the timer,
|
||
// and the message couldv be simply vestigal ( that means left over from an earlier time)...
|
||
|
||
if(m_LogoffTimer && (WaitForLogoffTimer == TimerID))
|
||
{
|
||
// We are waiting in the distructor for an async operation to complete
|
||
// and we have waited too long... kill the timer and set the m_hEventWaitForLogoffDone event
|
||
::KillTimer(m_hWndHidden, m_LogoffTimer);
|
||
m_LogoffTimer = 0;
|
||
|
||
if(m_hEventWaitForLogoffDone)
|
||
{
|
||
SetEvent(m_hEventWaitForLogoffDone);
|
||
}
|
||
}
|
||
else if( (INVALID_MSG_ID != m_uMsgID) && m_ResultPollTimer && (PollForResultTimer == TimerID ))
|
||
{
|
||
ASSERT(m_pLdap);
|
||
::KillTimer( m_hWndHidden, m_ResultPollTimer );
|
||
m_ResultPollTimer = 0;
|
||
|
||
LDAPMessage *pMsg = NULL;
|
||
LDAP_TIMEVAL TimeoutVal = { 0, 0 };
|
||
INT res = WLDAP::ldap_result( m_pLdap, m_uMsgID, LDAP_MSG_ALL, &TimeoutVal, &pMsg );
|
||
|
||
if( 0 == res )
|
||
{
|
||
// ldap_result timedout
|
||
m_ResultPollTimer = ::SetTimer( m_hWndHidden, PollForResultTimer, RESULT_POLL_INTERVAL, NULL );
|
||
|
||
if( !m_ResultPollTimer )
|
||
{
|
||
ERROR_OUT(("SetTimer failed!"));
|
||
_AbandonAllAndRecoverState();
|
||
}
|
||
}
|
||
else if( LDAP_RESULT_ERROR == res )
|
||
{
|
||
ERROR_OUT(("ldap_result failed"));
|
||
_AbandonAllAndRecoverState();
|
||
}
|
||
else
|
||
{
|
||
// We got the result, so reset this
|
||
m_uMsgID = INVALID_MSG_ID;
|
||
|
||
if( AddingUser == m_State )
|
||
{
|
||
_OnAddingUserResult(pMsg->lm_returncode);
|
||
WLDAP::ldap_msgfree(pMsg);
|
||
}
|
||
else if( ( SettingAppInfo == m_State ) || ( ModifyingAttrs == m_State ) )
|
||
{
|
||
_OnSettingAppInfoOrModifyingAttrsResult(pMsg->lm_returncode);
|
||
WLDAP::ldap_msgfree(pMsg);
|
||
}
|
||
else if( LoggingOff == m_State )
|
||
{
|
||
_OnLoggingOffResult(pMsg->lm_returncode);
|
||
WLDAP::ldap_msgfree(pMsg);
|
||
}
|
||
}
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnTimer:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnTimer);
|
||
}
|
||
|
||
|
||
void CNmLDAP::_OnUserBindComplete(INT LdapResult, DWORD LastError )
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnUserBindComplete);
|
||
TRACE_OUT(("CNmLDAP::_OnUserBindComplete:enter(%d): m_State:%d: m_currentOp:%d", LdapResult, m_State, m_CurrentOp));
|
||
|
||
ASSERT(m_hBindThread);
|
||
ASSERT(Binding == m_State);
|
||
|
||
CloseHandle(m_hBindThread);
|
||
m_hBindThread = NULL;
|
||
|
||
if(LDAP_SUCCESS == LdapResult)
|
||
{
|
||
m_State = Bound;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
|
||
if( m_bRefreshAfterBindCompletes )
|
||
{
|
||
// If a refresh is attempted while
|
||
// the bind operation is in progress
|
||
// we just wait for the bind to complete
|
||
// then we well do the refresh
|
||
m_bRefreshAfterBindCompletes = false;
|
||
_RefreshServer();
|
||
}
|
||
else if( m_bLogoffAfterBindCompletes )
|
||
{
|
||
m_bLogoffAfterBindCompletes = false;
|
||
_DeleteUser();
|
||
}
|
||
else
|
||
{
|
||
if( Op_Logon == m_CurrentOp )
|
||
{
|
||
m_CurrentOp = Op_NoOp;
|
||
_AddUser();
|
||
}
|
||
else if( Op_Logoff == m_CurrentOp )
|
||
{
|
||
m_CurrentOp = Op_NoOp;
|
||
_DeleteUser();
|
||
}
|
||
else if( Op_Refresh_Logoff == m_CurrentOp )
|
||
{
|
||
_DeleteUser();
|
||
}
|
||
else if( Op_Modifying_InCallAttr == m_CurrentOp )
|
||
{
|
||
m_CurrentOp = Op_NoOp;
|
||
_ModifyInCallAttr();
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
eCurrentOp OldOp = m_CurrentOp;
|
||
_AbandonAllAndRecoverState(OldOp);
|
||
|
||
if( ( Op_Refresh_Logoff == OldOp ) && ( lstrcmpi( m_strCurrentServer, m_strServer ) ) )
|
||
{
|
||
// If the server names have changed...
|
||
// Suppose that the server you are logged on to
|
||
// goes down and then you change the server that you want
|
||
// to be logged on to ( before you have any indication that
|
||
// the server has gone down... You want to log off the old server
|
||
// But the server is not available... We are basically going to
|
||
// ignore the fact that there was a problem logging off
|
||
// from the server, and we are going to simply log on to the new server
|
||
_OnLoggedOff();
|
||
LogonAsync();
|
||
}
|
||
else if( Op_Logoff == OldOp )
|
||
{
|
||
// We don't have to put up a message box...
|
||
_OnLoggedOff();
|
||
}
|
||
else
|
||
{
|
||
if( (LDAP_SERVER_DOWN == LdapResult) || (LDAP_TIMEOUT == LdapResult) )
|
||
{
|
||
if (Op_Modifying_InCallAttr == OldOp)
|
||
{
|
||
ERROR_OUT(("ldap_bind for InCallAttr returns server-down or timeout"));
|
||
}
|
||
else
|
||
{
|
||
::PostConfMsgBox(IDS_ULSLOGON_BADSERVER);
|
||
_OnLoggedOff();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("ldap_bind returned error 0x%08x LdapResult, GetLastError == 0x%08x", LdapResult, LastError));
|
||
}
|
||
}
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnUserBindComplete:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnUserBindComplete);
|
||
}
|
||
|
||
void CNmLDAP::_OnLoggingOffResult(int Result)
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnLoggingOffResult);
|
||
TRACE_OUT(("CNmLDAP::_OnLoggingOffResult:enter(%d): m_State:%d: m_currentOp:%d", Result, m_State, m_CurrentOp));
|
||
|
||
if( (LDAP_SUCCESS == Result) || (LDAP_NO_SUCH_OBJECT == Result) || (LDAP_SERVER_DOWN == Result))
|
||
{
|
||
// We are waiting in the destructor for the ldap logof operations to complete
|
||
// Now that it has, we hawe to signal the destructor unblocks
|
||
if(m_hEventWaitForLogoffDone)
|
||
{
|
||
SetEvent(m_hEventWaitForLogoffDone);
|
||
}
|
||
|
||
_OnLoggedOff();
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("Ldap Error 0x%08x", Result));
|
||
}
|
||
|
||
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
m_State = Idle;
|
||
m_pLdap = NULL;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
|
||
if( Op_Refresh_Logoff == m_CurrentOp )
|
||
{
|
||
m_CurrentOp = Op_NoOp;
|
||
LogonAsync();
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnLoggingOffResult:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnLoggingOffResult);
|
||
}
|
||
|
||
|
||
void CNmLDAP::_OnSettingAppInfoOrModifyingAttrsResult(int Result)
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnSettingAppInfoOrModifyingAttrsResult);
|
||
TRACE_OUT(("CNmLDAP::_OnSettingAppInfoOrModifyingAttrsResult:enter(%d): m_State:%d: m_currentOp:%d", Result, m_State, m_CurrentOp));
|
||
|
||
if( LDAP_SUCCESS == Result)
|
||
{
|
||
// start the keep alive thread
|
||
if (NULL != m_pKeepAlive)
|
||
{
|
||
m_pKeepAlive->Start();
|
||
}
|
||
|
||
if(SettingAppInfo == m_State)
|
||
{
|
||
m_State = LoggedIn;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
_OnLoggedOn();
|
||
}
|
||
else
|
||
{
|
||
m_State = LoggedIn;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
}
|
||
|
||
if( m_bSendInCallAttrWhenDone )
|
||
{
|
||
m_bSendInCallAttrWhenDone = false;
|
||
_ModifyInCallAttr();
|
||
}
|
||
else
|
||
{
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
|
||
if(m_ResultPollTimer)
|
||
{
|
||
::KillTimer(m_hWndHidden,m_ResultPollTimer);
|
||
m_ResultPollTimer = 0;
|
||
}
|
||
|
||
m_uMsgID = INVALID_MSG_ID;
|
||
|
||
m_pLdap = NULL;
|
||
m_State = LoggedIn;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT( ("Ldap Error 0x%08x, DN=%s", Result, m_strCurrentDN) );
|
||
if (ModifyingAttrs == m_State && NULL != m_pKeepAlive)
|
||
{
|
||
_AbandonAllAndRecoverState();
|
||
if(LDAP_NO_SUCH_OBJECT == Result)
|
||
{
|
||
_OnLoggedOff();
|
||
LogonAsync();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_AbandonAllAndSetToIdle();
|
||
_OnLoggedOff();
|
||
|
||
if(LDAP_NO_SUCH_OBJECT == Result)
|
||
{
|
||
LogonAsync();
|
||
}
|
||
}
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnSettingAppInfoOrModifyingAttrsResult:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnSettingAppInfoOrModifyingAttrsResult);
|
||
}
|
||
|
||
|
||
void CNmLDAP::_OnAddingUserResult( int Result)
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnAddingUserResult);
|
||
TRACE_OUT(("CNmLDAP::_OnAddingUserResult:enter(%d): m_State:%d: m_currentOp:%d", Result, m_State, m_CurrentOp));
|
||
|
||
if( LDAP_SUCCESS == Result )
|
||
{
|
||
m_State = UserAdded;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
_SetAppInfo();
|
||
}
|
||
else
|
||
{
|
||
UINT uStringID;
|
||
|
||
switch( Result )
|
||
{
|
||
case LDAP_ALREADY_EXISTS:
|
||
uStringID = IDS_ULSLOGON_DUPLICATE;
|
||
break;
|
||
|
||
case LDAP_NAMING_VIOLATION:
|
||
uStringID = IDS_ULSLOGON_WORD_FILTER;
|
||
break;
|
||
|
||
case LDAP_UNWILLING_TO_PERFORM:
|
||
uStringID = IDS_ILLEGALEMAILNAME;
|
||
break;
|
||
|
||
case LDAP_UNDEFINED_TYPE:
|
||
case LDAP_SERVER_DOWN:
|
||
// W2K server returns this under heavy load situations...
|
||
uStringID = IDS_ULSLOGON_ERROR;
|
||
break;
|
||
|
||
default:
|
||
uStringID = IDS_ULSLOGON_ERROR;
|
||
ERROR_OUT( ("Ldap Error 0x%08x, DN=%s", Result, m_strCurrentDN) );
|
||
break;
|
||
}
|
||
|
||
::PostConfMsgBox( uStringID );
|
||
_OnLoggedOff();
|
||
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
m_pLdap = NULL;
|
||
m_State = Idle;
|
||
SetLoggedOn( IsLoggedOn() );
|
||
}
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnAddingUserResult:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnAddingUserResult);
|
||
}
|
||
|
||
|
||
/*static*/
|
||
LRESULT CNmLDAP::_sWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
LRESULT lr = 0;
|
||
|
||
if( WM_NCCREATE != uMsg )
|
||
{
|
||
CNmLDAP* pNmLdap = reinterpret_cast<CNmLDAP*>( ::GetWindowLongPtr( hwnd, GWLP_USERDATA ) );
|
||
|
||
if( pNmLdap )
|
||
{
|
||
lr = pNmLdap->WndProc( hwnd, uMsg, wParam, lParam );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lr = TRUE; // This means to continue creating the window
|
||
CREATESTRUCT* pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
|
||
if( pCreateStruct )
|
||
{
|
||
::SetWindowLongPtr( hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
|
||
}
|
||
}
|
||
|
||
return lr;
|
||
}
|
||
|
||
void CNmLDAP::_SetAppInfo()
|
||
{
|
||
DBGENTRY(CNmLDAP::_SetInfo);
|
||
TRACE_OUT(("CNmLDAP::_SetInfo:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
ASSERT(NULL != m_pLdap);
|
||
ASSERT(UserAdded == m_State);
|
||
ASSERT(INVALID_MSG_ID == m_uMsgID);
|
||
|
||
// These are the app attribute vals
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, smodop, LDAP_MODOP_ADDAPP);
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, sappid, _T("ms-netmeeting"));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, smimetype, _T("text/iuls"));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, sappguid, _T("008aff194794cf118796444553540000"));
|
||
DECLARE_LDAP_MOD2(LDAP_MOD_ADD, sprotid, _T("t120"), _T("h323"));
|
||
DECLARE_LDAP_MOD2(LDAP_MOD_ADD, sprotmimetype, _T("text/t120"), _T("text/h323"));
|
||
DECLARE_LDAP_MOD2(LDAP_MOD_ADD, sport, _T("1503"), _T("1720"));
|
||
|
||
// This is the app mod array
|
||
LDAPMod *apModApp[] =
|
||
{
|
||
LDAP_MOD_ENTRY(smodop),
|
||
LDAP_MOD_ENTRY(sappid),
|
||
LDAP_MOD_ENTRY(smimetype),
|
||
LDAP_MOD_ENTRY(sappguid),
|
||
LDAP_MOD_ENTRY(sprotid),
|
||
LDAP_MOD_ENTRY(sprotmimetype),
|
||
LDAP_MOD_ENTRY(sport),
|
||
NULL
|
||
};
|
||
|
||
m_uMsgID = WLDAP::ldap_modify( m_pLdap, const_cast<LPTSTR>((LPCTSTR)m_strCurrentDN), apModApp );
|
||
|
||
if( INVALID_MSG_ID != m_uMsgID )
|
||
{
|
||
m_ResultPollTimer = ::SetTimer( m_hWndHidden, PollForResultTimer, RESULT_POLL_INTERVAL, NULL );
|
||
|
||
ASSERT(m_ResultPollTimer);
|
||
|
||
m_State = SettingAppInfo;
|
||
}
|
||
else
|
||
{
|
||
DWORD dwErr;
|
||
ERROR_OUT(("ldap_modify returned error 0x%08x", (WLDAP::ldap_get_option(m_pLdap, LDAP_OPT_ERROR_NUMBER, &dwErr), dwErr)));
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
m_pLdap = NULL;
|
||
m_State = Idle;
|
||
}
|
||
|
||
SetLoggedOn( IsLoggedOn() );
|
||
TRACE_OUT(("CNmLDAP::_SetInfo:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_SetInfo);
|
||
}
|
||
|
||
|
||
void CNmLDAP::_ModifyInCallAttr()
|
||
{
|
||
TRACE_OUT(("CNmLDAP::_ModifyInCallAttr:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_REPLACE, smodop, LDAP_MODOP_MODIFYUSER);
|
||
DECLARE_LDAP_MOD(LDAP_MOD_REPLACE, ilsA26214430, m_bInCall ? LDAP_ATTR_TRUE : LDAP_ATTR_FALSE);
|
||
|
||
LDAPMod *apMod[] =
|
||
{
|
||
LDAP_MOD_ENTRY(smodop),
|
||
LDAP_MOD_ENTRY(ilsA26214430),
|
||
NULL
|
||
};
|
||
|
||
TRACE_OUT(("About to modify InCallAttrs for this person: %s", m_strCurrentDN));
|
||
m_uMsgID = WLDAP::ldap_modify( m_pLdap, const_cast<LPTSTR>((LPCTSTR)m_strCurrentDN), apMod );
|
||
|
||
if( INVALID_MSG_ID != m_uMsgID )
|
||
{
|
||
m_ResultPollTimer = ::SetTimer( m_hWndHidden, PollForResultTimer, RESULT_POLL_INTERVAL, NULL );
|
||
|
||
ASSERT(m_ResultPollTimer);
|
||
|
||
m_State = ModifyingAttrs;
|
||
}
|
||
else
|
||
{
|
||
DWORD dwErr;
|
||
ERROR_OUT(("ldap_modify returned error 0x%08x", (WLDAP::ldap_get_option(m_pLdap, LDAP_OPT_ERROR_NUMBER, &dwErr), dwErr)));
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
m_pLdap = NULL;
|
||
m_State = (NULL != m_pKeepAlive) ? LoggedIn : Idle; // restore the state
|
||
}
|
||
|
||
SetLoggedOn( IsLoggedOn() );
|
||
TRACE_OUT(("CNmLDAP::_ModifyInCallAttr:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
}
|
||
|
||
|
||
void CNmLDAP::_DeleteUser()
|
||
{
|
||
DBGENTRY(CNmLDAP::_DeleteUser);
|
||
TRACE_OUT(("CNmLDAP::_DeleteUser:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
// end the keep alive thread
|
||
if (NULL != m_pKeepAlive)
|
||
{
|
||
m_pKeepAlive->End();
|
||
m_pKeepAlive = NULL;
|
||
}
|
||
|
||
ASSERT(NULL != m_pLdap);
|
||
ASSERT(Bound == m_State);
|
||
ASSERT(INVALID_MSG_ID == m_uMsgID);
|
||
|
||
m_uMsgID = WLDAP::ldap_delete(m_pLdap, const_cast<LPTSTR>((LPCTSTR)(m_strCurrentDN)));
|
||
if( INVALID_MSG_ID != m_uMsgID )
|
||
{
|
||
m_State = LoggingOff;
|
||
m_ResultPollTimer = ::SetTimer( m_hWndHidden, PollForResultTimer, RESULT_POLL_INTERVAL, NULL );
|
||
ASSERT(m_ResultPollTimer);
|
||
}
|
||
else
|
||
{
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
m_pLdap = NULL;
|
||
m_State = Idle;
|
||
}
|
||
|
||
SetLoggedOn( IsLoggedOn() );
|
||
|
||
TRACE_OUT(("CNmLDAP::_DeleteUser:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_DeleteUser);
|
||
}
|
||
|
||
void CNmLDAP::_AddUser()
|
||
{
|
||
DBGENTRY(CNmLDAP::_AddUser);
|
||
TRACE_OUT(("CNmLDAP::_AddUser:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
ASSERT(NULL != m_pLdap);
|
||
ASSERT(Bound == m_State);
|
||
ASSERT(INVALID_MSG_ID == m_uMsgID);
|
||
|
||
// These are the user attribute values
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, cn, const_cast<LPTSTR>((LPCTSTR)m_strEmailName));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, givenname, const_cast<LPTSTR>((LPCTSTR)m_strGivenName));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, surname, const_cast<LPTSTR>((LPCTSTR)m_strSurName));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, rfc822mailbox, const_cast<LPTSTR>((LPCTSTR)m_strEmailName));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, location, const_cast<LPTSTR>((LPCTSTR)m_strLocation));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, comment, const_cast<LPTSTR>((LPCTSTR)m_strComment));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, sflags, m_bVisible ? LDAP_ATTR_TRUE : LDAP_ATTR_FALSE );
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, ilsA26214430, m_bInCall ? LDAP_ATTR_TRUE : LDAP_ATTR_FALSE );
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, ilsA32833566, m_bAudioHardware ? LDAP_ATTR_TRUE : LDAP_ATTR_FALSE );
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, ilsA32964638, m_bVideoHardware ? LDAP_ATTR_TRUE : LDAP_ATTR_FALSE );
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, ilsA39321630, LDAP_ATTR_BUSINESS );
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, ssecurity, const_cast<LPTSTR>((LPCTSTR)m_strSecurityToken));
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, c, LDAP_ATTR_DUMMY_COUNTRYNAME);
|
||
|
||
// We have to get IP address dynamically
|
||
TCHAR szIpAddr[MAX_PATH];
|
||
szIpAddr[0] = _T('\0');
|
||
|
||
DWORD dwLocalIPAddress = INADDR_NONE;
|
||
_GetIpAddressOfLdapSession( szIpAddr, CCHMAX(szIpAddr), &dwLocalIPAddress );
|
||
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, sipaddress, szIpAddr);
|
||
|
||
// We store the version info on the server
|
||
TCHAR szVer[MAX_PATH];
|
||
wsprintf(szVer,"%lu",VER_PRODUCTVERSION_DW);
|
||
DECLARE_LDAP_MOD(LDAP_MOD_ADD, ilsA26279966, szVer);
|
||
|
||
// This is the user mod array
|
||
LDAPMod *apModUser[] =
|
||
{
|
||
LDAP_MOD_ENTRY(cn),
|
||
LDAP_MOD_ENTRY(givenname),
|
||
LDAP_MOD_ENTRY(surname),
|
||
LDAP_MOD_ENTRY(rfc822mailbox),
|
||
LDAP_MOD_ENTRY(location),
|
||
LDAP_MOD_ENTRY(comment),
|
||
LDAP_MOD_ENTRY(c),
|
||
LDAP_MOD_ENTRY(sipaddress),
|
||
LDAP_MOD_ENTRY(sflags),
|
||
LDAP_MOD_ENTRY(ssecurity),
|
||
LDAP_MOD_ENTRY(ilsA26214430),
|
||
LDAP_MOD_ENTRY(ilsA26279966),
|
||
LDAP_MOD_ENTRY(ilsA32833566),
|
||
LDAP_MOD_ENTRY(ilsA32964638),
|
||
LDAP_MOD_ENTRY(ilsA39321630),
|
||
NULL
|
||
};
|
||
|
||
TCHAR* szDN = new TCHAR[ lstrlen(LOGIN_USER_FILTER) + lstrlen(m_strEmailName) + 1 ];
|
||
if( szDN )
|
||
{
|
||
wsprintf(szDN, LOGIN_USER_FILTER, m_strEmailName);
|
||
m_strCurrentDN = szDN;
|
||
delete [] szDN;
|
||
}
|
||
|
||
TCHAR* szRefresh = new TCHAR[ lstrlen(LDAP_REFRESH_FILTER) + lstrlen(m_strEmailName) + 1 ];
|
||
if( szRefresh )
|
||
{
|
||
wsprintf(szRefresh, LDAP_REFRESH_FILTER, m_strEmailName);
|
||
}
|
||
|
||
m_uMsgID = WLDAP::ldap_add( m_pLdap, const_cast<LPTSTR>((LPCTSTR)m_strCurrentDN), apModUser );
|
||
|
||
if( INVALID_MSG_ID != m_uMsgID )
|
||
{
|
||
m_State = AddingUser;
|
||
m_ResultPollTimer = ::SetTimer( m_hWndHidden, PollForResultTimer, RESULT_POLL_INTERVAL, NULL );
|
||
ASSERT(m_ResultPollTimer);
|
||
|
||
// create the keep alive object
|
||
if (NULL != m_pKeepAlive)
|
||
{
|
||
m_pKeepAlive->End();
|
||
m_pKeepAlive = NULL;
|
||
}
|
||
BOOL fRet = FALSE;
|
||
m_pKeepAlive = new CKeepAlive(&fRet,
|
||
m_hWndHidden,
|
||
dwLocalIPAddress,
|
||
m_strCurrentServer, m_iPort,
|
||
szRefresh);
|
||
ASSERT(NULL != m_pKeepAlive && fRet);
|
||
}
|
||
else
|
||
{
|
||
WLDAP::ldap_unbind(m_pLdap);
|
||
m_pLdap = NULL;
|
||
m_State = Idle;
|
||
}
|
||
|
||
delete [] szRefresh;
|
||
|
||
SetLoggedOn( IsLoggedOn() );
|
||
|
||
TRACE_OUT(("CNmLDAP::_AddUser:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_AddUser);
|
||
}
|
||
|
||
void CNmLDAP::_OnLoggedOn()
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnLoggedOn);
|
||
TRACE_OUT(("CNmLDAP::_OnLoggedOn:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
::UpdateUI(CRUI_STATUSBAR | CRUI_CALLANIM, TRUE);
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnLoggedOn:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnLoggedOn);
|
||
}
|
||
|
||
void CNmLDAP::_OnLoggedOff()
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnLoggedOff);
|
||
TRACE_OUT(("CNmLDAP::_OnLoggedOff:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
::UpdateUI(CRUI_STATUSBAR | CRUI_CALLANIM, TRUE);
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnLoggedOff:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnLoggedOff);
|
||
}
|
||
|
||
|
||
void CNmLDAP::_OnLoggingOn()
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnLoggingOn);
|
||
TRACE_OUT(("CNmLDAP::_OnLoggingOn:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
::UpdateUI(CRUI_STATUSBAR | CRUI_CALLANIM, TRUE);
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnLoggingOn:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnLoggingOn);
|
||
}
|
||
|
||
|
||
void CNmLDAP::_OnLoggingOff()
|
||
{
|
||
DBGENTRY(CNmLDAP::_OnLoggingOff);
|
||
TRACE_OUT(("CNmLDAP::_OnLoggingOff:enter: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
|
||
::UpdateUI(CRUI_STATUSBAR | CRUI_CALLANIM, TRUE);
|
||
|
||
TRACE_OUT(("CNmLDAP::_OnLoggingOff:exit: m_State:%d: m_currentOp:%d", m_State, m_CurrentOp));
|
||
DBGEXIT(CNmLDAP::_OnLoggingOff);
|
||
}
|
||
|
||
void CNmLDAP::_GetIpAddressOfLdapSession( LPTSTR szIpAddr, int cchMax, DWORD *pdwIPAddr )
|
||
{
|
||
DBGENTRY(CNmLDAP::_GetIpAddressOfLdapSession);
|
||
|
||
if (NULL != szIpAddr)
|
||
{
|
||
szIpAddr[0] = _T('\0');
|
||
}
|
||
SOCKET s = INVALID_SOCKET;
|
||
|
||
if( LDAP_SUCCESS == WLDAP::ldap_get_option(m_pLdap, LDAP_OPT_DESC, &s ))
|
||
{
|
||
SOCKADDR_IN addr;
|
||
int NameLen = sizeof(addr);
|
||
if(0 == getsockname(s, reinterpret_cast<SOCKADDR*>(&addr), &NameLen))
|
||
{
|
||
if (NULL != szIpAddr)
|
||
{
|
||
wsprintf(szIpAddr, "%u", addr.sin_addr.s_addr);
|
||
}
|
||
if (NULL != pdwIPAddr)
|
||
{
|
||
*pdwIPAddr = addr.sin_addr.s_addr;
|
||
}
|
||
}
|
||
}
|
||
|
||
DBGEXIT(CNmLDAP::_GetIpAddressOfLdapSession);
|
||
}
|
||
|
||
|
||
void InitNmLdapAndLogon()
|
||
{
|
||
ASSERT( NULL == g_pLDAP );
|
||
|
||
g_pLDAP = new CNmLDAP;
|
||
|
||
if(g_pLDAP)
|
||
{
|
||
// Initialize the LDAP object...
|
||
if( SUCCEEDED(g_pLDAP->Initialize( _Module.GetModuleInstance())))
|
||
{
|
||
g_pLDAP->LogonAsync();
|
||
}
|
||
else
|
||
{
|
||
delete g_pLDAP;
|
||
g_pLDAP = NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("new CNmLDAP returned NULL"));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////
|
||
//
|
||
// CKeepAlive
|
||
//
|
||
|
||
|
||
void CALLBACK KeepAliveTimerProc(HWND, UINT, UINT_PTR, DWORD)
|
||
{
|
||
// doing nothing at all
|
||
}
|
||
|
||
|
||
DWORD KeepAliveThreadProc(LPVOID pParam)
|
||
{
|
||
// make sure we have a valid socket
|
||
WSADATA wsaData;
|
||
int iRet = ::WSAStartup(0x0101, &wsaData);
|
||
ASSERT(! iRet);
|
||
if (! iRet)
|
||
{
|
||
CKeepAlive *pKeepAlive = (CKeepAlive *) pParam;
|
||
ASSERT(NULL != pKeepAlive);
|
||
|
||
// translate server name into ip address
|
||
if (pKeepAlive->SetServerIPAddress())
|
||
{
|
||
// start the timer
|
||
UINT nKeepAliveInterval = INITIAL_REFRESH_INTERVAL_MINUTES;
|
||
UINT_PTR nTimerID = ::SetTimer(NULL, 0, nKeepAliveInterval * 60 * 1000, KeepAliveTimerProc);
|
||
ASSERT(nTimerID);
|
||
|
||
// watch for the timer message
|
||
MSG msg, msg2;
|
||
while (::GetMessage(&msg, NULL, 0, 0))
|
||
{
|
||
msg2 = msg; // keep a copy of this message
|
||
|
||
// dispatch messages
|
||
::DispatchMessage(&msg);
|
||
|
||
// intercept the WM_TIMER message thru msg2
|
||
if (WM_TIMER == msg2.message && nTimerID == msg2.wParam)
|
||
{
|
||
BOOL fRetry = TRUE;
|
||
|
||
// kill the timer to avoid timer overrun
|
||
::KillTimer(NULL, nTimerID);
|
||
nTimerID = 0;
|
||
|
||
// ping the server in case of dialup networking
|
||
if (pKeepAlive->Ping())
|
||
{
|
||
// connect to the server
|
||
LDAP *ld = WLDAP::ldap_open(pKeepAlive->GetServerName(),
|
||
pKeepAlive->GetServerPortNumber());
|
||
if (NULL != ld)
|
||
{
|
||
if (pKeepAlive->Bind(ld))
|
||
{
|
||
if (pKeepAlive->KeepAlive(ld, &nKeepAliveInterval))
|
||
{
|
||
// successfully send a keep alive
|
||
fRetry = FALSE;
|
||
|
||
DWORD dwLocalIPAddress = pKeepAlive->GetLocalIPAddress(ld);
|
||
if (INADDR_NONE != dwLocalIPAddress)
|
||
{
|
||
if (pKeepAlive->GetLocalIPAddress() != dwLocalIPAddress)
|
||
{
|
||
pKeepAlive->SetLocalIPAddress(dwLocalIPAddress);
|
||
pKeepAlive->UpdateIPAddressOnServer();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
WLDAP::ldap_unbind(ld);
|
||
}
|
||
}
|
||
|
||
// start the new timer based on the new internal
|
||
nTimerID = ::SetTimer(NULL, 0,
|
||
fRetry ? (15 * 1000) : (nKeepAliveInterval * 60 * 1000),
|
||
KeepAliveTimerProc);
|
||
ASSERT(nTimerID);
|
||
} // if wm timer
|
||
} // while get message
|
||
|
||
if (nTimerID)
|
||
{
|
||
::KillTimer(NULL, nTimerID);
|
||
}
|
||
}
|
||
|
||
delete pKeepAlive;
|
||
::WSACleanup();
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
CKeepAlive::CKeepAlive
|
||
(
|
||
BOOL *pfRet,
|
||
HWND hwndMainThread,
|
||
DWORD dwLocalIPAddress,
|
||
const TCHAR * const pcszServerName,
|
||
UINT nPort,
|
||
LPTSTR pszKeepAliveFilter
|
||
)
|
||
:
|
||
m_hwndMainThread(hwndMainThread),
|
||
m_dwLocalIPAddress(dwLocalIPAddress),
|
||
m_dwServerIPAddress(INADDR_NONE),
|
||
m_pszServerName(NULL),
|
||
m_nPort(nPort),
|
||
m_pszKeepAliveFilter(NULL),
|
||
m_hThread(NULL),
|
||
m_dwThreadID(0),
|
||
m_fAborted(FALSE)
|
||
{
|
||
*pfRet = FALSE; // assume failure
|
||
|
||
// sanity check
|
||
ASSERT(NULL != hwndMainThread);
|
||
ASSERT(INADDR_NONE != dwLocalIPAddress && 0 != dwLocalIPAddress);
|
||
ASSERT(nPort);
|
||
|
||
// create the server name
|
||
ASSERT(NULL != pcszServerName);
|
||
ULONG nStrLen = ::lstrlen(pcszServerName) + 1;
|
||
m_pszServerName = new TCHAR[nStrLen];
|
||
if (NULL != m_pszServerName)
|
||
{
|
||
::CopyMemory(m_pszServerName, pcszServerName, nStrLen * sizeof(TCHAR));
|
||
|
||
TCHAR * const pszPort = StrChr( m_pszServerName, ':' );
|
||
|
||
if( pszPort != NULL )
|
||
{
|
||
// Truncate the server name here for dns lookup....
|
||
// and this port number overrides the nPort parameter...
|
||
*pszPort = '\0';
|
||
HRESULT hrResult = DecimalStringToUINT( pszPort + 1, m_nPort );
|
||
ASSERT( hrResult == S_OK );
|
||
if( hrResult != S_OK )
|
||
{
|
||
m_nPort = DEFAULT_LDAP_PORT;
|
||
}
|
||
}
|
||
|
||
// create the fresh filter
|
||
ASSERT(NULL != pszKeepAliveFilter);
|
||
nStrLen = ::lstrlen(pszKeepAliveFilter) + 1;
|
||
m_pszKeepAliveFilter = new TCHAR[nStrLen];
|
||
if (NULL != m_pszKeepAliveFilter)
|
||
{
|
||
::CopyMemory(m_pszKeepAliveFilter, pszKeepAliveFilter, nStrLen * sizeof(TCHAR));
|
||
*pfRet = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
CKeepAlive::~CKeepAlive(void)
|
||
{
|
||
delete m_pszServerName;
|
||
delete m_pszKeepAliveFilter;
|
||
}
|
||
|
||
|
||
BOOL CKeepAlive::Start(void)
|
||
{
|
||
if (! m_dwThreadID)
|
||
{
|
||
ASSERT(NULL == m_hThread);
|
||
|
||
// create the worker thread
|
||
m_hThread = ::CreateThread(NULL, 0, KeepAliveThreadProc, this, 0, &m_dwThreadID);
|
||
}
|
||
|
||
ASSERT(NULL != m_hThread);
|
||
return (NULL != m_hThread);
|
||
}
|
||
|
||
|
||
BOOL CKeepAlive::End(BOOL fSync)
|
||
{
|
||
DWORD dwRet = WAIT_OBJECT_0;
|
||
|
||
// cache thread handle and ID
|
||
HANDLE hThread = m_hThread;
|
||
DWORD dwThreadID = m_dwThreadID;
|
||
|
||
// abort any pending operation
|
||
m_fAborted = TRUE;
|
||
|
||
// notify the worker thread to go away
|
||
if (m_dwThreadID)
|
||
{
|
||
ASSERT(NULL != m_hThread);
|
||
m_dwThreadID = 0;
|
||
::PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
|
||
}
|
||
|
||
// wait for the worker thread exit for 5 seconds
|
||
if (NULL != hThread)
|
||
{
|
||
// need more work to unblock it
|
||
if (fSync)
|
||
{
|
||
dwRet = ::WaitForSingleObject(hThread, 5000); // 5 second timeout
|
||
ASSERT(WAIT_TIMEOUT != dwRet);
|
||
}
|
||
|
||
::CloseHandle(hThread);
|
||
}
|
||
|
||
return (WAIT_TIMEOUT != dwRet);
|
||
}
|
||
|
||
|
||
BOOL CKeepAlive::SetServerIPAddress(void)
|
||
{
|
||
ASSERT(NULL != m_pszServerName);
|
||
|
||
// check to see if the server name is a dotted IP address string
|
||
m_dwServerIPAddress = ::inet_addr(m_pszServerName);
|
||
if (INADDR_NONE == m_dwServerIPAddress)
|
||
{
|
||
// it is not a dotted string, it must be a name.
|
||
// get the host entry by name
|
||
PHOSTENT phe = ::gethostbyname(m_pszServerName);
|
||
if (phe != NULL)
|
||
{
|
||
// get info from the host entry
|
||
m_dwServerIPAddress = *(DWORD *) phe->h_addr;
|
||
}
|
||
}
|
||
|
||
ASSERT(INADDR_NONE != m_dwServerIPAddress);
|
||
return (INADDR_NONE != m_dwServerIPAddress);
|
||
}
|
||
|
||
|
||
BOOL CKeepAlive::Ping(void)
|
||
{
|
||
BOOL fRet = TRUE; // assume success
|
||
if (NULL != g_pPing)
|
||
{
|
||
if (g_pPing->IsAutodialEnabled())
|
||
{
|
||
ASSERT(INADDR_NONE != m_dwServerIPAddress);
|
||
HRESULT hr = g_pPing->Ping(m_dwServerIPAddress, PING_TIMEOUT_INTERVAL, PING_RETRIES);
|
||
fRet = (S_OK == hr);
|
||
}
|
||
}
|
||
return fRet;
|
||
}
|
||
|
||
|
||
BOOL CKeepAlive::Bind(LDAP *ld)
|
||
{
|
||
ASSERT(NULL != ld);
|
||
|
||
if (! m_fAborted)
|
||
{
|
||
// anonymous bind
|
||
ULONG nMsgID = WLDAP::ldap_bind(ld, TEXT(""), TEXT(""), LDAP_AUTH_SIMPLE);
|
||
if (INVALID_MSG_ID != nMsgID)
|
||
{
|
||
// poll the result every quarter second
|
||
const ULONG c_nTimeoutInQuarterSecond = 4 * LDAP_TIMEOUT_IN_SECONDS;
|
||
for (ULONG i = 0; (i < c_nTimeoutInQuarterSecond) && (! m_fAborted); i++)
|
||
{
|
||
// no timeout, if no result, return immediately
|
||
LDAP_TIMEVAL TimeVal;
|
||
TimeVal.tv_usec = 0;
|
||
TimeVal.tv_sec = 0;
|
||
|
||
// check the result
|
||
LDAPMessage *pMsg = NULL;
|
||
ULONG nResultType = WLDAP::ldap_result(ld, nMsgID, LDAP_MSG_ALL, &TimeVal, &pMsg);
|
||
if (nResultType == LDAP_RES_BIND)
|
||
{
|
||
ASSERT(NULL != pMsg);
|
||
WLDAP::ldap_msgfree(pMsg);
|
||
return TRUE;
|
||
}
|
||
|
||
// deal with timeout or error
|
||
if (LDAP_RESULT_TIMEOUT == nResultType)
|
||
{
|
||
if (! m_fAborted)
|
||
{
|
||
::Sleep(250); // sleep for a quarter second
|
||
continue;
|
||
}
|
||
}
|
||
|
||
ASSERT(LDAP_RESULT_ERROR != nResultType);
|
||
break;
|
||
}
|
||
|
||
// failure, do the cleanup
|
||
WLDAP::ldap_abandon(ld, nMsgID);
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
DWORD CKeepAlive::GetLocalIPAddress(LDAP *ld)
|
||
{
|
||
SOCKET s = INVALID_SOCKET;
|
||
if (LDAP_SUCCESS == WLDAP::ldap_get_option(ld, LDAP_OPT_DESC, &s))
|
||
{
|
||
SOCKADDR_IN addr;
|
||
int NameLen = sizeof(addr);
|
||
if (0 == ::getsockname(s, (SOCKADDR *) &addr, &NameLen))
|
||
{
|
||
return addr.sin_addr.s_addr;
|
||
}
|
||
}
|
||
return INADDR_NONE;
|
||
}
|
||
|
||
|
||
BOOL CKeepAlive::KeepAlive(LDAP *ld, UINT *pnKeepAliveInterval)
|
||
{
|
||
LPTSTR aTTLAttr[] = { STTL_ATTR_NAME, NULL };
|
||
UINT nMsgID = WLDAP::ldap_search(ld,
|
||
LDAP_REFRESH_BASE_DN,
|
||
LDAP_SCOPE_BASE,
|
||
m_pszKeepAliveFilter,
|
||
aTTLAttr,
|
||
FALSE);
|
||
if (INVALID_MSG_ID != nMsgID)
|
||
{
|
||
// poll the result every quarter second
|
||
const ULONG c_nTimeoutInQuarterSecond = 4 * LDAP_TIMEOUT_IN_SECONDS;
|
||
BOOL fError = FALSE;
|
||
for (ULONG i = 0; (i < c_nTimeoutInQuarterSecond) && (! m_fAborted) && (! fError); i++)
|
||
{
|
||
// no timeout, if no result, return immediately
|
||
LDAP_TIMEVAL TimeVal;
|
||
TimeVal.tv_usec = 0;
|
||
TimeVal.tv_sec = 0;
|
||
|
||
// check the result
|
||
LDAPMessage *pMsg = NULL;
|
||
ULONG nResultType = WLDAP::ldap_result(ld, nMsgID, LDAP_MSG_ALL, &TimeVal, &pMsg);
|
||
switch (nResultType)
|
||
{
|
||
case LDAP_RESULT_TIMEOUT:
|
||
if (! m_fAborted)
|
||
{
|
||
::Sleep(250); // sleep for a quarter second
|
||
}
|
||
break;
|
||
case LDAP_RESULT_ERROR:
|
||
fError = TRUE;
|
||
break;
|
||
default:
|
||
ASSERT(LDAP_RES_SEARCH_ENTRY == nResultType ||
|
||
LDAP_RES_SEARCH_RESULT == nResultType);
|
||
ASSERT(NULL != pMsg);
|
||
switch (pMsg->lm_returncode)
|
||
{
|
||
case LDAP_SUCCESS:
|
||
GetNewInterval(ld, pMsg, pnKeepAliveInterval);
|
||
break;
|
||
case LDAP_NO_SUCH_OBJECT:
|
||
ReLogon();
|
||
fError = TRUE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
WLDAP::ldap_msgfree(pMsg);
|
||
return (! fError);
|
||
}
|
||
}
|
||
|
||
// failure, do the cleanup
|
||
WLDAP::ldap_abandon(ld, nMsgID);
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
void CKeepAlive::GetNewInterval(LDAP *ld, LDAPMessage *pMsg, UINT *pnKeepAliveInterval)
|
||
{
|
||
// get the first entry which should contain the new ttl value
|
||
LDAPMessage *pEntry = WLDAP::ldap_first_entry(ld, pMsg);
|
||
if (NULL != pEntry)
|
||
{
|
||
// get the first attribute which should be the new ttl value
|
||
BerElement *pElement = NULL;
|
||
LPTSTR pszAttrib = WLDAP::ldap_first_attribute(ld, pEntry, &pElement);
|
||
if (NULL != pszAttrib)
|
||
{
|
||
// it should be ttl attribute
|
||
ASSERT(! lstrcmpi(STTL_ATTR_NAME, pszAttrib));
|
||
|
||
// get the value
|
||
LPTSTR *ppszTTL = WLDAP::ldap_get_values(ld, pEntry, pszAttrib);
|
||
if (NULL != ppszTTL)
|
||
{
|
||
if (NULL != ppszTTL[0])
|
||
{
|
||
int iRefresh = ::RtStrToInt(ppszTTL[0]) - REFRESH_TIMEOUT_MARGIN;
|
||
if (iRefresh > 0)
|
||
{
|
||
if (iRefresh < MIN_REFRESH_TIMEOUT_INTERVAL_MINUTES)
|
||
{
|
||
iRefresh = MIN_REFRESH_TIMEOUT_INTERVAL_MINUTES;
|
||
}
|
||
*pnKeepAliveInterval = (UINT) iRefresh;
|
||
}
|
||
}
|
||
WLDAP::ldap_value_free(ppszTTL);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void CKeepAlive::ReLogon(void)
|
||
{
|
||
::PostMessage(m_hwndMainThread, WM_NEED_RELOGON, 0, 0);
|
||
}
|
||
|
||
|
||
void CKeepAlive::UpdateIPAddressOnServer(void)
|
||
{
|
||
::PostMessage(m_hwndMainThread, WM_NEED_RELOGON, 0, 0);
|
||
}
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////
|
||
//
|
||
// ResolveUser
|
||
//
|
||
|
||
typedef struct tagResolveInfo
|
||
{
|
||
// given
|
||
DWORD cchMax;
|
||
LPTSTR pszIPAddress;
|
||
// created
|
||
LPTSTR pszSearchFilter;
|
||
LDAP *ld;
|
||
}
|
||
RESOLVE_INFO;
|
||
|
||
|
||
void FreeResolveInfo(RESOLVE_INFO *pInfo)
|
||
{
|
||
if (NULL != pInfo)
|
||
{
|
||
delete pInfo->pszSearchFilter;
|
||
|
||
if (NULL != pInfo->ld)
|
||
{
|
||
WLDAP::ldap_unbind(pInfo->ld);
|
||
}
|
||
|
||
delete pInfo;
|
||
}
|
||
}
|
||
|
||
|
||
DWORD ResolveUserThreadProc(LPVOID pParam)
|
||
{
|
||
RESOLVE_INFO *pInfo = (RESOLVE_INFO *) pParam;
|
||
ASSERT(NULL != pInfo);
|
||
|
||
// send the search request
|
||
TCHAR* attrs[] = { IP_ADDRESS_ATTR_NAME, NULL };
|
||
ULONG nMsgID = WLDAP::ldap_search(pInfo->ld,
|
||
TEXT("objectClass=RTPerson"),
|
||
LDAP_SCOPE_BASE,
|
||
pInfo->pszSearchFilter,
|
||
attrs,
|
||
0);
|
||
if (INVALID_MSG_ID != nMsgID)
|
||
{
|
||
LDAPMessage *pMsg = NULL;
|
||
LDAP_TIMEVAL SearchTimeout = { LDAP_TIMEOUT_IN_SECONDS, 0 };
|
||
ULONG nResultType = WLDAP::ldap_result(pInfo->ld,
|
||
nMsgID,
|
||
LDAP_MSG_ALL,
|
||
&SearchTimeout,
|
||
&pMsg);
|
||
switch (nResultType)
|
||
{
|
||
case LDAP_RESULT_TIMEOUT:
|
||
case LDAP_RESULT_ERROR:
|
||
WLDAP::ldap_abandon(pInfo->ld, nMsgID);
|
||
break;
|
||
default:
|
||
{
|
||
ASSERT(LDAP_RES_SEARCH_ENTRY == nResultType ||
|
||
LDAP_RES_SEARCH_RESULT == nResultType);
|
||
ASSERT(NULL != pMsg);
|
||
|
||
// get the first entry
|
||
LDAPMessage *pEntry = WLDAP::ldap_first_entry(pInfo->ld, pMsg);
|
||
if (NULL != pEntry)
|
||
{
|
||
BerElement *pElement = NULL;
|
||
|
||
// get the first attribute
|
||
LPTSTR pszAttrib = WLDAP::ldap_first_attribute(pInfo->ld, pEntry, &pElement);
|
||
if (NULL != pszAttrib)
|
||
{
|
||
ASSERT(! lstrcmpi(IP_ADDRESS_ATTR_NAME, pszAttrib));
|
||
|
||
// get the value
|
||
LPTSTR *ppszIPAddress = WLDAP::ldap_get_values(pInfo->ld, pEntry, pszAttrib);
|
||
if (NULL != ppszIPAddress)
|
||
{
|
||
if (NULL != ppszIPAddress[0])
|
||
{
|
||
BYTE temp[sizeof(DWORD)];
|
||
*(DWORD *) &temp[0] = ::RtStrToInt(ppszIPAddress[0]);
|
||
::wsprintf(pInfo->pszIPAddress, TEXT("%u.%u.%u.%u"),
|
||
(UINT) temp[0], (UINT) temp[1],
|
||
(UINT) temp[2], (UINT) temp[3]);
|
||
}
|
||
|
||
WLDAP::ldap_value_free(ppszIPAddress);
|
||
}
|
||
} // if attribute
|
||
} // if entry
|
||
|
||
WLDAP::ldap_msgfree(pMsg);
|
||
}
|
||
break;
|
||
} // switch
|
||
} // if msg id
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*static*/
|
||
HRESULT CNmLDAP::ResolveUser( LPCTSTR pcszName, LPCTSTR pcszServer, LPTSTR pszIPAddress, DWORD cchMax, int port )
|
||
{
|
||
HRESULT hr = E_OUTOFMEMORY;
|
||
RESOLVE_INFO *pInfo = NULL;
|
||
|
||
// clean up the return buffer
|
||
*pszIPAddress = TEXT('\0');
|
||
|
||
// make sure the wldap32.dll is loaded
|
||
if( ms_bLdapDLLLoaded || SUCCEEDED( hr = WLDAP::Init()))
|
||
{
|
||
ms_bLdapDLLLoaded = true;
|
||
|
||
// create a resolve info which exchanges info between this thread and a background thread.
|
||
pInfo = new RESOLVE_INFO;
|
||
if (NULL != pInfo)
|
||
{
|
||
// cleanup
|
||
::ZeroMemory(pInfo, sizeof(*pInfo));
|
||
|
||
// remember return buffer and its size
|
||
pInfo->pszIPAddress = pszIPAddress;
|
||
pInfo->cchMax = cchMax;
|
||
|
||
// create search filter
|
||
ULONG cbFilterSize = ::lstrlen(RESOLVE_USER_SEARCH_FILTER) + ::lstrlen(pcszName) + 2;
|
||
pInfo->pszSearchFilter = new TCHAR[cbFilterSize];
|
||
if (NULL != pInfo->pszSearchFilter)
|
||
{
|
||
// construct search filter
|
||
::wsprintf(pInfo->pszSearchFilter, RESOLVE_USER_SEARCH_FILTER, pcszName);
|
||
|
||
// create ldap block that is NOT connected to server yet.
|
||
pInfo->ld = WLDAP::ldap_init(const_cast<LPTSTR>(pcszServer), port);
|
||
|
||
if( pInfo->ld != NULL )
|
||
{
|
||
ULONG ulResult = WLDAP::ldap_bind_s(pInfo->ld, TEXT(""), TEXT(""), LDAP_AUTH_SIMPLE);
|
||
|
||
if( (ulResult != LDAP_SUCCESS) && (port == DEFAULT_LDAP_PORT) )
|
||
{
|
||
WLDAP::ldap_unbind(pInfo->ld);
|
||
pInfo->ld = WLDAP::ldap_init(const_cast<LPTSTR>(pcszServer), ALTERNATE_LDAP_PORT); // Automatically retry with alternate port...
|
||
|
||
if( pInfo->ld != NULL )
|
||
{
|
||
ulResult = WLDAP::ldap_bind_s(pInfo->ld, TEXT(""), TEXT(""), LDAP_AUTH_SIMPLE);
|
||
|
||
if( ulResult != LDAP_SUCCESS )
|
||
{
|
||
WLDAP::ldap_unbind(pInfo->ld);
|
||
pInfo->ld = NULL;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
ASSERT(NULL != pInfo->ld);
|
||
if (NULL != pInfo->ld)
|
||
{
|
||
DWORD dwThreadID = 0;
|
||
HANDLE hThread = ::CreateThread(NULL, 0, ResolveUserThreadProc, pInfo, 0, &dwThreadID);
|
||
if (NULL != hThread)
|
||
{
|
||
// wait for the thread to exit
|
||
hr = ::WaitWithMessageLoop(hThread);
|
||
DWORD dwIPAddr = ::inet_addr(pszIPAddress);
|
||
hr = (dwIPAddr && INADDR_NONE != dwIPAddr) ? S_OK : E_FAIL;
|
||
|
||
// close thread
|
||
::CloseHandle(hThread);
|
||
}
|
||
} // if ld
|
||
} // if search filter
|
||
} // if new resolve info
|
||
} // if init
|
||
|
||
::FreeResolveInfo(pInfo);
|
||
return hr;
|
||
}
|
||
|
||
|
||
|