1415 lines
35 KiB
C++
1415 lines
35 KiB
C++
// File: ldap.cpp
|
|
|
|
#include "precomp.h"
|
|
#include "resource.h"
|
|
|
|
#include "mapidefs.h"
|
|
#include "pfnwldap.h"
|
|
#include "ldap.h"
|
|
#include "wab.h"
|
|
|
|
#include "dirutil.h"
|
|
#include "dlgcall2.h" // for WM_DISPLAY_MESSAGE
|
|
#include "upropdlg.h"
|
|
|
|
#define CDIRCACHE_IMAGES 3
|
|
|
|
// static strings
|
|
static const TCHAR s_szSearchFormat3[] = TEXT("(&(objectClass=RTPerson)(cn=%s)%s)");
|
|
static const TCHAR s_szSearchFormat2[] = TEXT("(&(objectClass=RTPerson)(cn=%s)(sappid=ms-netmeeting)(sprotid=h323)%s)");
|
|
static const TCHAR s_szSearchCategory[] = TEXT("(ILSA39321630=%d)");
|
|
|
|
static LPCTSTR s_pszOrg = TEXT("o=Microsoft");
|
|
|
|
static const TCHAR s_cszAttribShow[] = TEXT("sFlags"); // "Hide Me" (1=Show, 0=Hidden)
|
|
static const TCHAR s_cszAttribEmail[] = TEXT("cn"); // Email address
|
|
static const TCHAR s_cszAttribFirstName[] = TEXT("givenName"); // First Name
|
|
static const TCHAR s_cszAttribLastName[] = TEXT("surName"); // Last Name
|
|
static const TCHAR s_cszAttribLocation[] = TEXT("location"); // Location
|
|
static const TCHAR s_cszAttribComment[] = TEXT("comment"); // Comments
|
|
|
|
static const TCHAR s_cszAttribInACall[] = TEXT("ilsA26214430"); // 400 = in a call
|
|
static const TCHAR s_cszAttribVersion[] = TEXT("ilsA26279966"); // 401 = version number
|
|
static const TCHAR s_cszAttribAudio[] = TEXT("ilsA32833566"); // 501 = send audio
|
|
static const TCHAR s_cszAttribVideo[] = TEXT("ilsA32964638"); // 503 = send video
|
|
static const TCHAR s_cszAttribCategory[] = TEXT("ilsA39321630"); // 600 = category
|
|
|
|
|
|
static LPCTSTR s_rgAttrNameAddr[] = {
|
|
(LPTSTR) s_cszAttribShow,
|
|
(LPTSTR) s_cszAttribEmail,
|
|
(LPTSTR) s_cszAttribFirstName,
|
|
(LPTSTR) s_cszAttribLastName,
|
|
(LPTSTR) s_cszAttribLocation,
|
|
(LPTSTR) s_cszAttribInACall,
|
|
(LPTSTR) s_cszAttribAudio,
|
|
(LPTSTR) s_cszAttribVideo,
|
|
(LPTSTR) s_cszAttribComment,
|
|
NULL};
|
|
|
|
|
|
static LPCTSTR s_rgAttrAll[] = {
|
|
(LPTSTR) s_cszAttribFirstName,
|
|
(LPTSTR) s_cszAttribLastName,
|
|
(LPTSTR) s_cszAttribComment,
|
|
(LPTSTR) s_cszAttribAudio,
|
|
(LPTSTR) s_cszAttribVideo,
|
|
(LPTSTR) s_cszAttribVersion,
|
|
(LPTSTR) s_cszAttribCategory,
|
|
NULL};
|
|
|
|
|
|
static const int _rgIdMenu[] = {
|
|
IDM_DLGCALL_SPEEDDIAL,
|
|
IDM_DLGCALL_WAB,
|
|
-1,
|
|
IDM_DLGCALL_REFRESH,
|
|
IDM_DLGCALL_STOP,
|
|
0
|
|
};
|
|
|
|
// Local functions
|
|
VOID ConvertVersionInfo(LPTSTR pszVersion, LPTSTR pszCategory);
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
CLDAP::CLDAP() :
|
|
CALV(0, II_SERVER, _rgIdMenu),
|
|
m_pLdap(NULL),
|
|
m_ulPort(DEFAULT_LDAP_PORT),
|
|
m_msgId(0),
|
|
m_hThread(NULL),
|
|
m_hWnd( NULL ),
|
|
m_hSearchMutex( NULL ),
|
|
|
|
m_fDirInProgress( FALSE ),
|
|
m_cTotalEntries( 0 ),
|
|
m_cEntries( 0 ),
|
|
m_fHaveRefreshed( FALSE ),
|
|
m_dwTickStart( 0 ),
|
|
m_fIsCacheable( FALSE ),
|
|
m_fNeedsRefresh( FALSE ),
|
|
m_bSearchCancelled( false ),
|
|
m_uniqueId( 0 )
|
|
{
|
|
DbgMsg(iZONE_OBJECTS, "CLDAP - Constructed(%08X)", this);
|
|
|
|
HRESULT hr = WLDAP::Init();
|
|
SetAvailable(S_OK == hr);
|
|
|
|
m_szServer[0] = _T('\0');
|
|
m_szAddress[0] = _T('\0');
|
|
|
|
m_hSearchMutex = CreateMutex( NULL, false, NULL );
|
|
|
|
RegEntry reUI(UI_KEY, HKEY_CURRENT_USER);
|
|
m_fCacheDirectory = (0 != reUI.GetNumber(
|
|
REGVAL_CACHE_DIRECTORY, DEFAULT_CACHE_DIRECTORY));
|
|
|
|
m_cMinutesExpire = reUI.GetNumber(
|
|
REGVAL_CACHE_DIRECTORY_EXPIRATION, DEFAULT_CACHE_DIRECTORY_EXPIRATION);
|
|
|
|
}
|
|
|
|
CLDAP::~CLDAP()
|
|
{
|
|
CloseServer();
|
|
|
|
if (NULL != m_hThread)
|
|
{
|
|
WARNING_OUT(("CLDAP - waiting for AsyncSearch Thread to exit (start)"));
|
|
WaitForSingleObject(m_hThread, 10000); // 10 seconds max
|
|
WARNING_OUT(("CLDAP - waiting for AsyncSearch to exit (end)"));
|
|
}
|
|
|
|
if( m_hSearchMutex )
|
|
{
|
|
CloseHandle( m_hSearchMutex );
|
|
}
|
|
|
|
// Free any cached data
|
|
while (!m_listDirCache.IsEmpty())
|
|
{
|
|
DIRCACHE * pDirCache = (DIRCACHE *) m_listDirCache.RemoveHead();
|
|
ASSERT(NULL != pDirCache);
|
|
FreeDirCache(pDirCache);
|
|
}
|
|
|
|
DbgMsg(iZONE_OBJECTS, "CLDAP - Destroyed(%08X)", this);
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// CALV methods
|
|
|
|
|
|
/* S H O W I T E M S */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: ShowItems
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::ShowItems(HWND hwnd)
|
|
{
|
|
DBGENTRY(CLDAP::ShowItems);
|
|
|
|
m_hWnd = hwnd;
|
|
SetWindow( hwnd ); // set in base class too...
|
|
|
|
CALV::ClearItems();
|
|
DisplayDirectory();
|
|
|
|
DBGEXIT(CLDAP::ShowItems);
|
|
}
|
|
|
|
|
|
/* C L E A R I T E M S */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: ClearItems
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::ClearItems(void)
|
|
{
|
|
DBGENTRY( CLDAP::ClearItems );
|
|
|
|
StopSearch();
|
|
|
|
DBGEXIT( CLDAP::ClearItems );
|
|
}
|
|
|
|
|
|
/* virtual */
|
|
RAI * CLDAP::GetAddrInfo(void)
|
|
{
|
|
DBGENTRY(CLDAP::GetAddrInfo);
|
|
|
|
int selectedItem = CALV::GetSelection();
|
|
RAI * pRai = NULL;
|
|
|
|
if( selectedItem != -1 )
|
|
{
|
|
if( (pRai = new RAI) != NULL )
|
|
{
|
|
pRai->cItems = 1;
|
|
pRai->rgDwStr->dw = NM_ADDR_ULS;
|
|
|
|
GetSzName( pRai->szName, CCHMAX( pRai->szName ), selectedItem );
|
|
|
|
TCHAR buffer[ CCHMAXSZ ];
|
|
|
|
GetSzAddress( buffer, CCHMAX( buffer ),selectedItem );
|
|
pRai->rgDwStr->psz = PszAlloc( buffer );
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CLDAP::GetAddrInfo);
|
|
|
|
return( pRai );
|
|
}
|
|
|
|
|
|
/* G E T S Z A D D R E S S */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: GetSzAddress
|
|
|
|
-------------------------------------------------------------------------*/
|
|
BOOL CLDAP::GetSzAddress(LPTSTR psz, int cchMax, int iItem)
|
|
{
|
|
DBGENTRY(CLDAP::GetSzAddress);
|
|
|
|
BOOL bRet = TRUE;
|
|
|
|
int cch = lstrlen(m_szServer);
|
|
|
|
if ((cch+2) < cchMax)
|
|
{
|
|
lstrcpy(psz, m_szServer);
|
|
psz += cch;
|
|
*psz++ = _T('/');
|
|
cchMax -= (cch+1);
|
|
|
|
bRet = CALV::GetSzData( psz, cchMax, iItem, COLUMN_INDEX_ADDRESS );
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
|
|
DBGEXIT(CLDAP::GetSzAddress);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/* O N C O M M A N D */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: OnCommand
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDM_DLGCALL_STOP:
|
|
StopSearch();
|
|
break;
|
|
case IDM_DLGCALL_REFRESH:
|
|
if (NULL == m_hThread)
|
|
{
|
|
CALV::ClearItems();
|
|
StartSearch();
|
|
}
|
|
break;
|
|
case IDM_DLGCALL_WAB:
|
|
CmdAddToWab();
|
|
break;
|
|
default:
|
|
CALV::OnCommand(wParam, lParam);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* C M D P R O P E R T I E S */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: CmdProperties
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::CmdProperties(void)
|
|
{
|
|
DBGENTRY(CLDAP::CmdProperties);
|
|
|
|
DWORD dwThID;
|
|
|
|
HANDLE hThread = CreateThread(NULL, 0, _sAsyncPropertyThreadFn,
|
|
(LPVOID) this, 0, &dwThID);
|
|
CloseHandle(hThread);
|
|
|
|
DBGEXIT(CLDAP::CmdProperties);
|
|
}
|
|
|
|
DWORD CALLBACK CLDAP::_sAsyncPropertyThreadFn(LPVOID pv)
|
|
{
|
|
DBGENTRY(CLDAP::_sAsyncPropertyThreadFn);
|
|
|
|
CLDAP * pThis = (CLDAP *) pv;
|
|
ASSERT(NULL != pThis);
|
|
pThis->ShowProperties();
|
|
|
|
DBGEXIT(CLDAP::_sAsyncPropertyThreadFn);
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID CLDAP::ShowProperties(void)
|
|
{
|
|
DBGENTRY(CLDAP::ShowProperties);
|
|
|
|
SetBusyCursor(TRUE);
|
|
LDAPUSERDATA ldapUserData;
|
|
BOOL fOk = FGetUserData(&ldapUserData);
|
|
SetBusyCursor(FALSE);
|
|
if (!fOk)
|
|
return;
|
|
|
|
TCHAR szHasHardware[CCHMAXSZ];
|
|
FLoadString(IDS_HARDWARE_DETECTED, szHasHardware, CCHMAX(szHasHardware));
|
|
TCHAR szNoHardware[CCHMAXSZ];
|
|
FLoadString(IDS_NO_HARDWARE_DETECTED, szNoHardware, CCHMAX(szNoHardware));
|
|
|
|
UPROPDLGENTRY rgProp[] = {
|
|
{IDS_UPROP_EMAIL, ldapUserData.szEmail},
|
|
{IDS_UPROP_COMMENTS, ldapUserData.szComment},
|
|
{IDS_UPROP_VIDEO, ldapUserData.fVideoSend ? szHasHardware : szNoHardware},
|
|
{IDS_UPROP_AUDIO, ldapUserData.fAudioSend ? szHasHardware : szNoHardware},
|
|
{IDS_UPROP_VERSION, ldapUserData.szVersion},
|
|
};
|
|
|
|
CUserPropertiesDlg dlgUserProp(GetHwnd(), IDI_LARGE);
|
|
dlgUserProp.DoModal(rgProp, ARRAY_ELEMENTS(rgProp), ldapUserData.szName, NULL);
|
|
|
|
DBGEXIT(CLDAP::ShowProperties);
|
|
}
|
|
|
|
|
|
/* C M D A D D T O W A B */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: CmdAddToWab
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::CmdAddToWab(void)
|
|
{
|
|
DBGENTRY(CLDAP::CmdAddToWab);
|
|
|
|
LDAPUSERDATA ldapUserData;
|
|
if (!FGetUserData(&ldapUserData))
|
|
return;
|
|
|
|
CreateWabEntry(ldapUserData.szName, ldapUserData.szFirst, ldapUserData.szLast, ldapUserData.szEmail,
|
|
NULL, NULL, ldapUserData.szComment, m_szServer);
|
|
|
|
DBGEXIT(CLDAP::CmdAddToWab);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/* S E T S E R V E R */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: SetServer
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::SetServer(LPCTSTR pcszServer)
|
|
{
|
|
DBGENTRY(CLDAP::SetServer);
|
|
|
|
if ((0 != lstrcmpi(m_szServer, pcszServer)) || (DEFAULT_LDAP_PORT != m_ulPort))
|
|
{
|
|
CloseServer();
|
|
|
|
int cch;
|
|
LPCTSTR pszSeparator = _StrChr(pcszServer, _T(':'));
|
|
if (NULL != pszSeparator)
|
|
{
|
|
cch = (pszSeparator - pcszServer) + 1;
|
|
if (cch >= CCHMAX(m_szAddress))
|
|
return;
|
|
m_ulPort = DecimalStringToUINT(pszSeparator + 1);
|
|
}
|
|
else
|
|
{
|
|
cch = CCHMAX(m_szAddress);
|
|
m_ulPort = DEFAULT_LDAP_PORT;
|
|
}
|
|
|
|
// save the information before changing the server name
|
|
CacheServerData();
|
|
|
|
lstrcpyn(m_szAddress, pcszServer, cch);
|
|
lstrcpyn(m_szServer, pcszServer, CCHMAX(m_szServer));
|
|
}
|
|
|
|
|
|
DBGEXIT(CLDAP::SetServer);
|
|
}
|
|
|
|
|
|
/* D I R E C T O R Y S T A R T */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: DirectoryStart
|
|
|
|
Initiate directory request
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::StartSearch(void)
|
|
{
|
|
DBGENTRY(CLDAP::StartSearch);
|
|
|
|
if (NULL == m_hThread)
|
|
{
|
|
DWORD dwThID;
|
|
|
|
AddRef();
|
|
m_bSearchCancelled = false;
|
|
HANDLE hThread = CreateThread(NULL, 0, _sAsyncSearchThreadFn,
|
|
(LPVOID) this, CREATE_SUSPENDED, &dwThID);
|
|
if (NULL != hThread)
|
|
{
|
|
m_hThread = hThread;
|
|
ResumeThread(hThread);
|
|
}
|
|
else
|
|
{
|
|
Release();
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CLDAP::StartSearch);
|
|
}
|
|
|
|
DWORD CALLBACK CLDAP::_sAsyncSearchThreadFn(LPVOID pv)
|
|
{
|
|
|
|
DBGENTRY(CLDAP::_sAsyncSearchThreadFn);
|
|
|
|
CLDAP * pThis = (CLDAP *) pv;
|
|
ASSERT(NULL != pThis);
|
|
pThis->AsyncSearch();
|
|
pThis->Release();
|
|
|
|
DBGEXIT(CLDAP::_sAsyncSearchThreadFn);
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID CLDAP::AsyncSearch(void)
|
|
{
|
|
DBGENTRY(CLDAP::AsyncSearch);
|
|
|
|
HRESULT hr;
|
|
|
|
WARNING_OUT(("AsyncSearch Started"));
|
|
ASSERT(NULL != m_hThread);
|
|
|
|
SetBusyCursor(TRUE);
|
|
// We can not call EnableWindow() from this thread as it av's some of the time. This is a
|
|
// known windows bug. It also doesn't really solve the problem (#4726) it was put in here
|
|
// to solve anyway. We will work around this in a future build by re-architecting this so
|
|
// this little helper thread doesn't mess with the ui at all. It is problematic and very
|
|
// inefficient anyway.
|
|
// ::EnableWindow(GetDlgItem(GetParent(GetHwnd()), IDM_DLGCALL_REFRESH), FALSE);
|
|
|
|
m_fDirInProgress = TRUE;
|
|
m_dwTickStart = ::GetTickCount();
|
|
m_uniqueId = 0;
|
|
|
|
if( SUCCEEDED( WaitWithMessageLoop( m_hSearchMutex ) ) )
|
|
{
|
|
if (!FAvailable())
|
|
{
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
else if (!FOpenServer())
|
|
{
|
|
CloseServer();
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = DoQuery();
|
|
}
|
|
|
|
SetBusyCursor(FALSE); // This should be moved outside the if so it is always executed...
|
|
|
|
// We can not call EnableWindow() from this thread as it av's some of the time. This is a
|
|
// known windows bug. It also doesn't really solve the problem (#4726) it was put in here
|
|
// to solve anyway. We will work around this in a future build by re-architecting this so
|
|
// this little helper thread doesn't mess with the ui at all. It is problematic and very
|
|
// inefficient anyway.
|
|
// ::EnableWindow(GetDlgItem(GetParent(GetHwnd()), IDM_DLGCALL_REFRESH), TRUE);
|
|
|
|
HWND hwnd = GetHwnd();
|
|
if (-1 == ListView_GetNextItem(hwnd, -1, LVNI_ALL | LVNI_FOCUSED))
|
|
{
|
|
// No selection - set focus to the first item
|
|
ListView_SetItemState(hwnd, 0, LVIS_FOCUSED, LVIS_FOCUSED);
|
|
}
|
|
|
|
ReleaseMutex( m_hSearchMutex );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
PostMessage(GetParent(hwnd), WM_DISPLAY_MSG, IDS_ULSLOGON_ERROR, 0);
|
|
}
|
|
|
|
WARNING_OUT(("AsyncSearch Complete"));
|
|
|
|
// Close the thread handle safely
|
|
HANDLE hThread = m_hThread;
|
|
m_hThread = NULL;
|
|
CloseHandle(hThread);
|
|
}
|
|
|
|
if (m_fDirInProgress)
|
|
{
|
|
// Only cache if data took more than 2 seconds to retrieve
|
|
m_fIsCacheable = ((::GetTickCount() - m_dwTickStart) > 2000);
|
|
m_fDirInProgress = FALSE;
|
|
}
|
|
|
|
DBGEXIT(CLDAP::AsyncSearch);
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/* F O P E N S E R V E R */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: FOpenServer
|
|
|
|
Make sure the connection to the LDAP server is open
|
|
-------------------------------------------------------------------------*/
|
|
BOOL CLDAP::FOpenServer(void)
|
|
{
|
|
DBGENTRY(CLDAP::FOpenServer);
|
|
|
|
BOOL bRet = TRUE;
|
|
|
|
if( NULL == m_pLdap )
|
|
{
|
|
if( m_bSearchCancelled )
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT(("Opening Server [%s] Port [%d]", m_szAddress, m_ulPort));
|
|
|
|
m_pLdap = WLDAP::ldap_open(m_szAddress, m_ulPort);
|
|
|
|
if( (m_pLdap == NULL) && (m_ulPort == DEFAULT_LDAP_PORT) )
|
|
{
|
|
m_pLdap = WLDAP::ldap_open(m_szAddress, ALTERNATE_LDAP_PORT); // Automatically retry with alternate port...
|
|
|
|
if( m_pLdap != NULL )
|
|
{
|
|
m_ulPort = ALTERNATE_LDAP_PORT;
|
|
}
|
|
}
|
|
|
|
if(NULL != m_pLdap)
|
|
{
|
|
LONG lTimeOut = 30; // seconds for timeout
|
|
WLDAP::ldap_set_option(m_pLdap, LDAP_OPT_TIMELIMIT, &lTimeOut);
|
|
|
|
|
|
// Defaults to ILS 2
|
|
ASSERT(LDAP_VERSION2 == m_pLdap->ld_version);
|
|
|
|
ULONG ulRet = WLDAP::ldap_simple_bind_s(m_pLdap, NULL, NULL);
|
|
|
|
WARNING_OUT(("Logon [%s] complete", m_szServer));
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT(("ldap_open err=%d", GetLastError()));
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CLDAP::FOpenServer);
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/* C L O S E S E R V E R */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: CloseServer
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::CloseServer(void)
|
|
{
|
|
DBGENTRY(CLDAP::CloseServer);
|
|
|
|
if(m_pLdap)
|
|
{
|
|
StopSearch();
|
|
|
|
if( SUCCEEDED( WaitWithMessageLoop( m_hSearchMutex ) ) )
|
|
{
|
|
|
|
WLDAP::ldap_unbind(m_pLdap);
|
|
m_pLdap = NULL;
|
|
|
|
ReleaseMutex( m_hSearchMutex );
|
|
}
|
|
|
|
WARNING_OUT(("Logoff [%s] complete", m_szServer));
|
|
}
|
|
}
|
|
|
|
|
|
/* G E T N E X T A T T R I B U T E */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: GetNextAttribute
|
|
|
|
-------------------------------------------------------------------------*/
|
|
LPTSTR CLDAP::GetNextAttribute(LPCTSTR pszExpect, LPTSTR psz, int cchMax, LPTSTR pszAttrib, LDAPMessage * pEntry, BerElement * pElement)
|
|
{
|
|
|
|
DBGENTRY(CLDAP::GetNextAttribute);
|
|
|
|
ASSERT(NULL != psz);
|
|
|
|
if ((NULL == pszAttrib) || (0 != lstrcmpi(pszAttrib, pszExpect)))
|
|
{
|
|
*psz = _T('\0');
|
|
}
|
|
else
|
|
{
|
|
LPTSTR * rgVal = WLDAP::ldap_get_values(m_pLdap, pEntry, pszAttrib);
|
|
if( rgVal[0] )
|
|
{
|
|
lstrcpyn(psz, rgVal[0], cchMax);
|
|
}
|
|
else
|
|
{
|
|
psz[0] = _T('\0');
|
|
}
|
|
WLDAP::ldap_value_free(rgVal);
|
|
|
|
pszAttrib = WLDAP::ldap_next_attribute(m_pLdap, pEntry, pElement);
|
|
}
|
|
|
|
|
|
DBGEXIT(CLDAP::GetNextAttribute);
|
|
|
|
return pszAttrib;
|
|
}
|
|
|
|
|
|
/* D O Q U E R Y */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: DoQuery
|
|
|
|
-------------------------------------------------------------------------*/
|
|
HRESULT CLDAP::DoQuery(void)
|
|
{
|
|
|
|
DBGENTRY(CLDAP::DoQuery);
|
|
|
|
HRESULT hr = S_FALSE;
|
|
|
|
ASSERT(FLoggedOn());
|
|
|
|
TCHAR szSearch[MAX_PATH];
|
|
ASSERT(CCHMAX(s_szSearchFormat3) + CCHMAX(s_szSearchCategory) < CCHMAX(szSearch));
|
|
ASSERT(CCHMAX(s_szSearchFormat2) + CCHMAX(s_szSearchCategory) < CCHMAX(szSearch));
|
|
|
|
if( !m_bSearchCancelled )
|
|
{
|
|
wsprintf(szSearch,
|
|
(LDAP_VERSION2 == m_pLdap->ld_version) ? s_szSearchFormat2 : s_szSearchFormat3,
|
|
(LDAP_VERSION2 == m_pLdap->ld_version) ? TEXT("%") : TEXT("*"), _T(""));
|
|
ASSERT(lstrlen(szSearch) < CCHMAX(szSearch));
|
|
|
|
ASSERT(0 == m_msgId); // one search at a time
|
|
|
|
m_msgId = WLDAP::ldap_search(m_pLdap, (PCHAR) "objectClass=RTPerson", LDAP_SCOPE_BASE,
|
|
szSearch, (PCHAR *) s_rgAttrNameAddr, 0);
|
|
|
|
if( m_msgId == -1 )
|
|
{
|
|
m_msgId = 0;
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
SendMessage( m_hWnd, WM_SETREDRAW, FALSE, 0 );
|
|
|
|
while( (0 != m_msgId) && (!m_bSearchCancelled) )
|
|
{
|
|
LDAP_TIMEVAL timeOut = {2, 0};
|
|
LDAPMessage * pResult = NULL;
|
|
WARNING_OUT(("DoQuery calling ldap_result"));
|
|
int iResult = WLDAP::ldap_result(m_pLdap, m_msgId, 0, &timeOut, &pResult);
|
|
WARNING_OUT( ("DoQuery back from ldap_result: 0x%08X", iResult) );
|
|
if (0 == iResult)
|
|
{
|
|
SendMessage( m_hWnd, WM_SETREDRAW, TRUE, 0 );
|
|
UpdateWindow( m_hWnd );
|
|
SendMessage( m_hWnd, WM_SETREDRAW, FALSE, 0 );
|
|
continue;
|
|
}
|
|
|
|
if (LDAP_RES_SEARCH_ENTRY != iResult)
|
|
{
|
|
// S_FALSE = abandoned
|
|
// hr = (-1 == iResult) ? S_OK : S_FALSE;
|
|
hr = (-1 == iResult) ? E_FAIL : S_FALSE;
|
|
break;
|
|
}
|
|
|
|
AddEntries(pResult);
|
|
|
|
WLDAP::ldap_msgfree(pResult);
|
|
}
|
|
|
|
SendMessage( m_hWnd, WM_SETREDRAW, TRUE, 0 );
|
|
|
|
m_msgId = 0;
|
|
DirComplete( TRUE );
|
|
|
|
forceSort();
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CLDAP::DoQuery);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/* A D D E N T R I E S */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: AddEntries
|
|
|
|
Add the Entries to the listbox. (Data ordered by s_rgAttrNameAddr.)
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::AddEntries(LDAPMessage * pResult)
|
|
{
|
|
DBGENTRY(CLDAP::AddEntries);
|
|
|
|
LDAPMessage * pEntry;
|
|
BerElement * pElement;
|
|
|
|
for (pEntry = WLDAP::ldap_first_entry(m_pLdap, pResult);
|
|
NULL != pEntry;
|
|
pEntry = WLDAP::ldap_next_entry(m_pLdap, pEntry))
|
|
{
|
|
LPTSTR pszAttrib = WLDAP::ldap_first_attribute(m_pLdap, pEntry, &pElement);
|
|
if (NULL == pszAttrib)
|
|
break;
|
|
|
|
// Must have a "Show Me" attribute
|
|
if (0 != lstrcmpi(pszAttrib, s_cszAttribShow))
|
|
continue;
|
|
|
|
LPTSTR * rgVal = WLDAP::ldap_get_values(m_pLdap, pEntry, pszAttrib);
|
|
BOOL fShow = (_T('1') == *rgVal[0]);
|
|
WLDAP::ldap_value_free(rgVal);
|
|
|
|
if (!fShow)
|
|
continue;
|
|
pszAttrib = WLDAP::ldap_next_attribute(m_pLdap, pEntry, pElement);
|
|
|
|
TCHAR szEmail[CCHMAXSZ_EMAIL];
|
|
pszAttrib = GetNextAttribute(s_cszAttribEmail, szEmail, CCHMAX(szEmail),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
TCHAR szFirstName[CCHMAXSZ_FIRSTNAME];
|
|
pszAttrib = GetNextAttribute(s_cszAttribFirstName, szFirstName, CCHMAX(szFirstName),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
TCHAR szLastName[CCHMAXSZ_LASTNAME];
|
|
pszAttrib = GetNextAttribute(s_cszAttribLastName, szLastName, CCHMAX(szLastName),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
TCHAR szLocation[CCHMAXSZ_LASTNAME];
|
|
pszAttrib = GetNextAttribute(s_cszAttribLocation, szLocation, CCHMAX(szLocation),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
TCHAR szTemp[4];
|
|
pszAttrib = GetNextAttribute(s_cszAttribInACall, szTemp, CCHMAX(szTemp),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
int iInCallImage = (szTemp[0] == _T('1')) ? II_IN_A_CALL : II_COMPUTER;
|
|
|
|
pszAttrib = GetNextAttribute(s_cszAttribAudio, szTemp, CCHMAX(szTemp),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
int iAudioImage = (szTemp[0] == _T('1')) ? II_AUDIO_CAPABLE : 0;
|
|
|
|
pszAttrib = GetNextAttribute(s_cszAttribVideo, szTemp, CCHMAX(szTemp),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
int iVideoImage = (szTemp[0] == _T('1')) ? II_VIDEO_CAPABLE : 0;
|
|
|
|
TCHAR szComment[CCHMAXSZ_COMMENT];
|
|
pszAttrib = GetNextAttribute(s_cszAttribComment, szComment, CCHMAX(szComment),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
lvAddItem( 0, iInCallImage, iAudioImage, iVideoImage, szEmail, szFirstName, szLastName, szLocation, szComment );
|
|
}
|
|
|
|
DBGEXIT(CLDAP::AddEntries);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::lvAddItem. //
|
|
//--------------------------------------------------------------------------//
|
|
int
|
|
CLDAP::lvAddItem
|
|
(
|
|
int item,
|
|
int iInCallImage,
|
|
int iAudioImage,
|
|
int iVideoImage,
|
|
LPCTSTR address,
|
|
LPCTSTR firstName,
|
|
LPCTSTR lastName,
|
|
LPCTSTR location,
|
|
LPCTSTR comments
|
|
){
|
|
LV_ITEM lvItem;
|
|
|
|
ClearStruct( &lvItem );
|
|
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = item;
|
|
lvItem.lParam = m_uniqueId++; // assign a unique lParam for this item
|
|
|
|
int index = ListView_InsertItem( m_hWnd, &lvItem );
|
|
|
|
if( index != -1 )
|
|
{
|
|
if( lastName )
|
|
{
|
|
ListView_SetItemText( m_hWnd, index, COLUMN_INDEX_LAST_NAME, (LPTSTR) lastName );
|
|
}
|
|
|
|
if( firstName )
|
|
{
|
|
ListView_SetItemText( m_hWnd, index, COLUMN_INDEX_FIRST_NAME, (LPTSTR) firstName );
|
|
}
|
|
|
|
if( iAudioImage != 0 )
|
|
{
|
|
lvItem.mask = LVIF_IMAGE;
|
|
lvItem.iSubItem = COLUMN_INDEX_AUDIO;
|
|
lvItem.iImage = iAudioImage;
|
|
|
|
ListView_SetItem( m_hWnd, &lvItem );
|
|
}
|
|
|
|
if( iVideoImage != 0 )
|
|
{
|
|
lvItem.mask = LVIF_IMAGE;
|
|
lvItem.iSubItem = COLUMN_INDEX_VIDEO;
|
|
lvItem.iImage = iVideoImage;
|
|
|
|
ListView_SetItem( m_hWnd, &lvItem );
|
|
}
|
|
|
|
if( address )
|
|
{
|
|
lvItem.mask = LVIF_IMAGE | LVIF_TEXT;
|
|
lvItem.iSubItem = COLUMN_INDEX_ADDRESS;
|
|
lvItem.iImage = iInCallImage;
|
|
lvItem.pszText = (LPTSTR) address;
|
|
lvItem.cchTextMax = lstrlen( lvItem.pszText );
|
|
|
|
ListView_SetItem( m_hWnd, &lvItem );
|
|
}
|
|
|
|
if( location )
|
|
{
|
|
ListView_SetItemText( m_hWnd, index, COLUMN_INDEX_LOCATION, (LPTSTR) location );
|
|
}
|
|
|
|
if( comments )
|
|
{
|
|
ListView_SetItemText( m_hWnd, index, COLUMN_INDEX_COMMENTS, (LPTSTR) comments );
|
|
}
|
|
}
|
|
|
|
return( index );
|
|
|
|
} // End of CLDAP::lvAddItem.
|
|
|
|
|
|
/* S T O P S E A R C H */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: StopSearch
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID CLDAP::StopSearch(void)
|
|
{
|
|
DBGENTRY(CLDAP::StopSearch);
|
|
|
|
m_bSearchCancelled = true;
|
|
|
|
if (0 != m_msgId)
|
|
{
|
|
// Dont call ldap_abandon() from this thread as the search thread may be inside ldap_result()
|
|
// at the time. For now just set m_msgId to zero and the search thread will stop when ldap_result()
|
|
// returns.
|
|
// ULONG uResult = WLDAP::ldap_abandon(m_pLdap, m_msgId);
|
|
WARNING_OUT(("Stopping Search..."));
|
|
m_msgId = 0;
|
|
|
|
m_fDirInProgress = FALSE;
|
|
m_fIsCacheable = FALSE;
|
|
|
|
DirComplete(FALSE);
|
|
}
|
|
|
|
DBGEXIT(CLDAP::StopSearch);
|
|
}
|
|
|
|
|
|
|
|
/* F G E T U S E R D A T A */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: FGetUserData
|
|
|
|
Get the data for a single user.
|
|
-------------------------------------------------------------------------*/
|
|
BOOL CLDAP::FGetUserData(LDAPUSERDATA * pLdapUserData)
|
|
{
|
|
DBGENTRY(CLDAP::FGetUserData);
|
|
ClearStruct(pLdapUserData);
|
|
|
|
if (!FLoggedOn())
|
|
{
|
|
DBGEXIT(CLDAP::FGetUserData);
|
|
return FALSE;
|
|
}
|
|
|
|
int iItem = CALV::GetSelection();
|
|
if (-1 == iItem)
|
|
{
|
|
DBGEXIT(CLDAP::FGetUserData);
|
|
return FALSE;
|
|
}
|
|
if (!GetSzData(pLdapUserData->szEmail, CCHMAX(pLdapUserData->szEmail), iItem, COLUMN_INDEX_ADDRESS))
|
|
{
|
|
DBGEXIT(CLDAP::FGetUserData);
|
|
return FALSE;
|
|
}
|
|
|
|
TCHAR szSearch[CCHMAX(s_szSearchFormat2) + CCHMAXSZ_EMAIL];
|
|
wsprintf(szSearch,
|
|
(LDAP_VERSION2 == m_pLdap->ld_version) ? s_szSearchFormat2 : s_szSearchFormat3,
|
|
pLdapUserData->szEmail, g_cszEmpty);
|
|
ASSERT(lstrlen(szSearch) < CCHMAX(szSearch));
|
|
|
|
LDAPMessage * pResult = NULL;
|
|
|
|
ULONG ulRet = WLDAP::ldap_search_s(m_pLdap, (LPTSTR) "objectClass=RTPerson", LDAP_SCOPE_BASE,
|
|
szSearch, (PCHAR *) s_rgAttrAll, FALSE, &pResult);
|
|
if (LDAP_SUCCESS != ulRet)
|
|
{
|
|
WLDAP::ldap_msgfree(pResult);
|
|
WARNING_OUT(("ldap_search (code=%08X)", ulRet));
|
|
DBGEXIT(CLDAP::FGetUserData);
|
|
return FALSE;
|
|
}
|
|
|
|
LDAPMessage * pEntry = WLDAP::ldap_first_entry(m_pLdap, pResult);
|
|
if (NULL != pEntry)
|
|
{
|
|
BerElement * pElement;
|
|
LPTSTR pszAttrib = WLDAP::ldap_first_attribute(m_pLdap, pEntry, &pElement);
|
|
// Make sure that the first attribute is s_cszAttribFirstName...
|
|
if ((NULL != pszAttrib) && (0 == lstrcmpi(pszAttrib, s_cszAttribFirstName)))
|
|
{
|
|
LPTSTR * rgVal = WLDAP::ldap_get_values(m_pLdap, pEntry, pszAttrib);
|
|
WLDAP::ldap_value_free(rgVal);
|
|
// pszAttrib = WLDAP::ldap_next_attribute(m_pLdap, pEntry, pElement);
|
|
|
|
pszAttrib = GetNextAttribute(s_cszAttribFirstName,
|
|
pLdapUserData->szFirst, CCHMAX(pLdapUserData->szFirst),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
pszAttrib = GetNextAttribute(s_cszAttribLastName,
|
|
pLdapUserData->szLast, CCHMAX(pLdapUserData->szLast),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
CombineNames(pLdapUserData->szName, CCHMAX(pLdapUserData->szName),
|
|
pLdapUserData->szFirst, pLdapUserData->szLast);
|
|
|
|
pszAttrib = GetNextAttribute(s_cszAttribComment,
|
|
pLdapUserData->szComment, CCHMAX(pLdapUserData->szComment),
|
|
pszAttrib, pEntry, pElement);
|
|
|
|
TCHAR szTemp[4];
|
|
pszAttrib = GetNextAttribute(s_cszAttribAudio, szTemp, CCHMAX(szTemp),
|
|
pszAttrib, pEntry, pElement);
|
|
pLdapUserData->fAudioSend = _T('1') == szTemp[0];
|
|
pszAttrib = GetNextAttribute(s_cszAttribVideo, szTemp, CCHMAX(szTemp),
|
|
pszAttrib, pEntry, pElement);
|
|
pLdapUserData->fVideoSend = _T('1') == szTemp[0];
|
|
|
|
pszAttrib = GetNextAttribute(s_cszAttribVersion,
|
|
pLdapUserData->szVersion, CCHMAX(pLdapUserData->szVersion),
|
|
pszAttrib, pEntry, pElement);
|
|
pszAttrib = GetNextAttribute(s_cszAttribCategory, szTemp, CCHMAX(szTemp),
|
|
pszAttrib, pEntry, pElement);
|
|
ConvertVersionInfo(pLdapUserData->szVersion, szTemp);
|
|
}
|
|
}
|
|
|
|
WLDAP::ldap_msgfree(pResult);
|
|
|
|
DBGEXIT(CLDAP::FGetUserData);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* C O N V E R T V E R S I O N I N F O */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: ConvertVersionInfo
|
|
|
|
-------------------------------------------------------------------------*/
|
|
VOID ConvertVersionInfo(LPTSTR pszVersion, LPTSTR pszCategory)
|
|
{
|
|
UINT uVer = DecimalStringToUINT(pszVersion);
|
|
|
|
if (0 == uVer)
|
|
{
|
|
lstrcpy(pszVersion, FEmptySz(pszCategory) ? TEXT("1.0") : TEXT("2"));
|
|
}
|
|
else
|
|
{
|
|
LPCTSTR pszRel;
|
|
|
|
switch (LOBYTE(HIWORD(uVer)))
|
|
{
|
|
case 3: pszRel = TEXT("2.11"); break;
|
|
case 4: pszRel = TEXT("3.0"); break;
|
|
case 5: pszRel = TEXT("4.0"); break;
|
|
default: pszRel = g_cszEmpty; break;
|
|
}
|
|
|
|
TCHAR szFormat[CCHMAXSZ];
|
|
FLoadString(IDS_FORMAT_VERSION, szFormat, CCHMAX(szFormat));
|
|
wsprintf(pszVersion, szFormat, pszRel,
|
|
HIBYTE(HIWORD(uVer)), LOBYTE(HIWORD(uVer)), LOWORD(uVer));
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::FreeDirCache. //
|
|
//--------------------------------------------------------------------------//
|
|
void
|
|
CLDAP::FreeDirCache
|
|
(
|
|
DIRCACHE * pDirCache
|
|
){
|
|
TRACE_OUT(("FreeDirCache [%s] filter=%d, expire=%d",
|
|
pDirCache->pszServer, pDirCache->dwTickExpire));
|
|
|
|
ASSERT(NULL != pDirCache);
|
|
PBYTE pb = pDirCache->pData;
|
|
delete pDirCache->pszServer;
|
|
delete pDirCache;
|
|
|
|
while (NULL != pb)
|
|
{
|
|
PBYTE pTemp = pb;
|
|
pb = (PBYTE) * (DWORD_PTR *) pb;
|
|
delete pTemp;
|
|
}
|
|
|
|
} // End of CLDAP::FreeDirCache.
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::FreeDirCache. //
|
|
//--------------------------------------------------------------------------//
|
|
void
|
|
CLDAP::DirComplete
|
|
(
|
|
bool //fPostUiUpdate
|
|
){
|
|
|
|
if( m_fDirInProgress )
|
|
{
|
|
// Only cache if data took more than 2 seconds to retrieve
|
|
m_fIsCacheable = ((::GetTickCount() - m_dwTickStart) > 2000);
|
|
m_fDirInProgress = FALSE;
|
|
}
|
|
|
|
m_cTotalEntries = 0;
|
|
m_cEntries = 0;
|
|
|
|
} // End of CLDAP:DirComplete.
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::GetSzName. //
|
|
//--------------------------------------------------------------------------//
|
|
BOOL
|
|
CLDAP::GetSzName
|
|
(
|
|
LPTSTR psz,
|
|
int cchMax,
|
|
int iItem
|
|
){
|
|
TCHAR szOrder[ MAX_PATH ];
|
|
|
|
bool bFirstNameFirst = ((::LoadString( ::GetInstanceHandle(), IDS_NAME_ORDER, szOrder, CCHMAX(szOrder)) == 0) ||
|
|
(_T( '1' ) == szOrder[ 1 ]));
|
|
|
|
int iFirst = bFirstNameFirst? COLUMN_INDEX_FIRST_NAME: COLUMN_INDEX_LAST_NAME;
|
|
int iLast = bFirstNameFirst? COLUMN_INDEX_LAST_NAME: COLUMN_INDEX_FIRST_NAME;
|
|
|
|
GetSzData( psz, cchMax, iItem, iFirst );
|
|
|
|
int length = lstrlen( psz );
|
|
|
|
if( (length > 0) && (length < cchMax - 1) )
|
|
{
|
|
lstrcat( psz, TEXT( " " ) );
|
|
length++;
|
|
}
|
|
|
|
GetSzData( &psz[ length ], cchMax - length, iItem, iLast );
|
|
|
|
return( lstrlen( psz ) > 0 );
|
|
|
|
} // End of CLDAP::GetSzName.
|
|
|
|
|
|
static const int CDIRCACHE_SZ = 5; // number of strings
|
|
static const int CDIRCACHE_IMAGE = 3; // number of images
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::CacheServerData. //
|
|
//--------------------------------------------------------------------------//
|
|
void
|
|
CLDAP::CacheServerData(void)
|
|
{
|
|
DIRCACHE * pDirCache;
|
|
|
|
if (!m_fCacheDirectory)
|
|
return; // User disabled directory caching
|
|
|
|
if (!m_fIsCacheable)
|
|
{
|
|
TRACE_OUT(("CacheServerData: not caching [%s]", m_szServer));
|
|
return;
|
|
}
|
|
|
|
if (m_fDirInProgress)
|
|
return; // don't cache partial data
|
|
|
|
// Remove any previous cached data
|
|
POSITION pos = FindCachedData();
|
|
|
|
if (NULL != pos)
|
|
{
|
|
pDirCache = (DIRCACHE *) m_listDirCache.RemoveAt(pos);
|
|
ASSERT(NULL != pDirCache);
|
|
FreeDirCache(pDirCache);
|
|
}
|
|
|
|
DWORD dwTickExpire = m_dwTickStart + (m_cMinutesExpire * 60000);
|
|
|
|
if (dwTickExpire < GetTickCount())
|
|
{
|
|
TRACE_OUT(("CacheServerData: [%s] data has expired", m_szServer));
|
|
return; // data is already expired
|
|
}
|
|
|
|
int cItems = ListView_GetItemCount(m_hWnd);
|
|
if (0 == cItems)
|
|
return; // nothing to cache
|
|
|
|
pDirCache = new DIRCACHE;
|
|
if (NULL == pDirCache)
|
|
return;
|
|
|
|
pDirCache->pszServer = PszAlloc(m_szServer);
|
|
pDirCache->dwTickExpire = dwTickExpire;
|
|
pDirCache->pData = NULL;
|
|
|
|
LPTSTR pPrev = (LPTSTR) &pDirCache->pData;
|
|
|
|
m_listDirCache.AddTail(pDirCache);
|
|
|
|
LV_ITEM lvi;
|
|
lvi.cchTextMax = MAX_PATH;
|
|
for (lvi.iItem = 0; lvi.iItem < cItems; lvi.iItem++)
|
|
{
|
|
int iInCallImage = -1;
|
|
int iAudioImage = -1;
|
|
int iVideoImage = -1;
|
|
int i = 0; // index into rgcb, rgsz
|
|
int cb = 0; // total length of string data
|
|
int rgcb[CDIRCACHE_SZ]; // size of each string
|
|
TCHAR rgsz[CDIRCACHE_SZ][MAX_PATH]; // string buffers
|
|
|
|
// Get the string data for each column
|
|
lvi.mask = LVIF_IMAGE;
|
|
for (lvi.iSubItem = 0; lvi.iSubItem < MAX_DIR_COLUMNS; lvi.iSubItem++)
|
|
{
|
|
if( (lvi.iSubItem != COLUMN_INDEX_AUDIO) && (lvi.iSubItem != COLUMN_INDEX_VIDEO) )
|
|
{
|
|
lvi.mask |= LVIF_TEXT;
|
|
lvi.pszText = rgsz[i];
|
|
ListView_GetItem(m_hWnd, &lvi);
|
|
rgcb[i] = lstrlen(lvi.pszText);
|
|
cb += rgcb[i] + 1; // Plus one for the NULL...
|
|
i++;
|
|
|
|
if( lvi.iSubItem == COLUMN_INDEX_ADDRESS )
|
|
{
|
|
iInCallImage = lvi.iImage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lvi.mask &= ~LVIF_TEXT;
|
|
ListView_GetItem(m_hWnd, &lvi);
|
|
|
|
if( lvi.iSubItem == COLUMN_INDEX_AUDIO )
|
|
{
|
|
iAudioImage = lvi.iImage;
|
|
}
|
|
else if( lvi.iSubItem == COLUMN_INDEX_VIDEO)
|
|
{
|
|
iVideoImage = lvi.iImage;
|
|
}
|
|
}
|
|
}
|
|
|
|
// allocate space for: a link (DWORD), strings (cb), images (CDIRCACHE_IMAGES)
|
|
PBYTE pData = new BYTE[ sizeof(DWORD_PTR) + cb + CDIRCACHE_IMAGES ];
|
|
if (NULL == pData)
|
|
{
|
|
// can't hold all data - give up and return
|
|
ClearServerCache();
|
|
return;
|
|
}
|
|
* ((DWORD_PTR *) pData) = 0; // link to next item is null
|
|
PBYTE pb = pData + sizeof(DWORD_PTR);
|
|
|
|
// copy the string data into the buffer
|
|
for (i = 0; i < CDIRCACHE_SZ; i++)
|
|
{
|
|
lstrcpy((LPTSTR) pb, rgsz[i]);
|
|
pb += rgcb[i] + 1;
|
|
}
|
|
|
|
*pb++ = (BYTE) iInCallImage;
|
|
*pb++ = (BYTE) iAudioImage;
|
|
*pb = (BYTE) iVideoImage;
|
|
* ((DWORD_PTR *) pPrev) = (DWORD_PTR) pData; // link into the previous data
|
|
pPrev = (LPTSTR) pData;
|
|
}
|
|
|
|
TRACE_OUT(("CacheServerData: [%s] expire=%d",
|
|
m_szServer, dwTickExpire));
|
|
|
|
} // End of CLDAP::CacheServerData.
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::FindCachedData. //
|
|
//--------------------------------------------------------------------------//
|
|
POSITION
|
|
CLDAP::FindCachedData(void)
|
|
{
|
|
DWORD dwTick = GetTickCount();
|
|
TRACE_OUT(("Searching for cached data on [%s]", m_szServer));
|
|
|
|
POSITION pos = m_listDirCache.GetHeadPosition();
|
|
while (NULL != pos)
|
|
{
|
|
POSITION posSav = pos;
|
|
DIRCACHE * pDirCache = (DIRCACHE *) m_listDirCache.GetNext(pos);
|
|
ASSERT(NULL != pDirCache);
|
|
if ((0 == lstrcmp(m_szServer, pDirCache->pszServer)) &&
|
|
(pDirCache->dwTickExpire > dwTick))
|
|
{
|
|
return posSav;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} // End of CLDAP::FindCachedData.
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::ClearServerCache. //
|
|
//--------------------------------------------------------------------------//
|
|
void
|
|
CLDAP::ClearServerCache(void)
|
|
{
|
|
DWORD dwTick = GetTickCount();
|
|
|
|
POSITION pos = m_listDirCache.GetHeadPosition();
|
|
while (NULL != pos)
|
|
{
|
|
POSITION posSav = pos;
|
|
DIRCACHE * pDirCache = (DIRCACHE *) m_listDirCache.GetNext(pos);
|
|
ASSERT(NULL != pDirCache);
|
|
|
|
if ( (0 == lstrcmp(m_szServer, pDirCache->pszServer)) || (pDirCache->dwTickExpire < dwTick) )
|
|
{
|
|
m_listDirCache.RemoveAt(posSav);
|
|
FreeDirCache(pDirCache);
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
TRACE_OUT(("Keeping cached data for [%s] , expire=%d",
|
|
pDirCache->pszServer, pDirCache->dwTickExpire));
|
|
}
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
} // End of CLDAP::ClearServerCache.
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::DisplayDirectory. //
|
|
//--------------------------------------------------------------------------//
|
|
void
|
|
CLDAP::DisplayDirectory(void)
|
|
{
|
|
POSITION pos = FindCachedData();
|
|
|
|
if (NULL == pos)
|
|
{
|
|
// no cached information - request new data
|
|
StartSearch();
|
|
return;
|
|
}
|
|
|
|
DIRCACHE * pDirCache = (DIRCACHE *) m_listDirCache.GetFromPosition(pos);
|
|
ASSERT(NULL != pDirCache);
|
|
LPTSTR pDirLine = (LPTSTR) pDirCache->pData;
|
|
|
|
StopSearch(); // In case the previous server is slow
|
|
CALV::ClearItems();
|
|
|
|
m_fIsCacheable = FALSE; // don't bother attempting to re-cache this data
|
|
|
|
// Restore the cached server information
|
|
TRACE_OUT(("Restoring cached data for [%s] expire=%d",
|
|
m_szServer, pDirCache->dwTickExpire));
|
|
|
|
SendMessage( m_hWnd, WM_SETREDRAW, FALSE, 0 );
|
|
|
|
while (NULL != pDirLine)
|
|
{
|
|
DWORD_PTR *pNext = * (DWORD_PTR * * ) pDirLine; pDirLine += sizeof(DWORD_PTR);
|
|
LPTSTR pszEmail = (LPTSTR) pDirLine; pDirLine += lstrlen(pDirLine)+1;
|
|
LPTSTR pszLast = (LPTSTR) pDirLine; pDirLine += lstrlen(pDirLine)+1;
|
|
LPTSTR pszFirst = (LPTSTR) pDirLine; pDirLine += lstrlen(pDirLine)+1;
|
|
LPTSTR pszLocation = (LPTSTR) pDirLine; pDirLine += lstrlen(pDirLine)+1;
|
|
LPTSTR pszComment = (LPTSTR) pDirLine; pDirLine += lstrlen(pDirLine)+1;
|
|
int iiCall = (int) * (char *) pDirLine; pDirLine++;
|
|
int iiAudio = (int) * (char *) pDirLine; pDirLine++;
|
|
int iiVideo = (int) * (char *) pDirLine;
|
|
|
|
lvAddItem( 0, iiCall, iiAudio, iiVideo, pszEmail, pszFirst, pszLast, pszLocation, pszComment );
|
|
|
|
pDirLine = (LPTSTR) pNext;
|
|
}
|
|
|
|
forceSort();
|
|
SendMessage( m_hWnd, WM_SETREDRAW, TRUE, 0 );
|
|
|
|
} // End of CLDAP::DisplayDirectory.
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::forceSort. //
|
|
//--------------------------------------------------------------------------//
|
|
void
|
|
CLDAP::forceSort(void)
|
|
{
|
|
NM_LISTVIEW nmlv;
|
|
|
|
nmlv.hdr.code = LVN_COLUMNCLICK;
|
|
nmlv.hdr.hwndFrom = m_hWnd;
|
|
nmlv.iSubItem = -1; // default sort column...
|
|
|
|
SendMessage( GetParent( m_hWnd ), WM_NOTIFY, GetDlgCtrlID( m_hWnd ), (LPARAM) &nmlv );
|
|
|
|
} // End of CLDAP::forceSort.
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
// CLDAP::GetIconId. //
|
|
//--------------------------------------------------------------------------//
|
|
int
|
|
CLDAP::GetIconId(LPCTSTR psz)
|
|
{
|
|
|
|
return( CDirectoryManager::isWebDirectory( psz )? II_WEB_DIRECTORY: CALV::GetIconId( NULL ) );
|
|
|
|
} // End of CLDAP::GetIconId.
|