windows-nt/Source/XPSP1/NT/net/mmc/tapi/tapidb.cpp
2020-09-26 16:20:57 +08:00

2425 lines
74 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
tapidb.h
FILE HISTORY:
*/
#include "stdafx.h"
#include "DynamLnk.h"
#include "tapidb.h"
#include "security.h"
#include "lm.h"
#include "service.h"
#include <shlwapi.h>
#include <shlwapip.h>
#define DEFAULT_SECURITY_PKG _T("negotiate")
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
// internal functions
BOOL IsUserAdmin(LPCTSTR pszMachine, PSID AccountSid);
BOOL LookupAliasFromRid(LPWSTR TargetComputer, DWORD Rid, LPWSTR Name, PDWORD cchName);
DWORD ValidateDomainAccount(IN CString Machine, IN CString UserName, IN CString Domain, OUT PSID * AccountSid);
NTSTATUS ValidatePassword(IN LPCWSTR UserName, IN LPCWSTR Domain, IN LPCWSTR Password);
DWORD GetCurrentUser(CString & strAccount);
DEBUG_DECLARE_INSTANCE_COUNTER(CTapiInfo);
DynamicDLL g_TapiDLL( _T("TAPI32.DLL"), g_apchFunctionNames );
CTapiInfo::CTapiInfo()
: m_hServer(NULL),
m_pTapiConfig(NULL),
m_pProviderList(NULL),
m_pAvailProviderList(NULL),
m_hReinit(NULL),
m_dwApiVersion(TAPI_CURRENT_VERSION),
m_hResetEvent(NULL),
m_cRef(1),
m_fIsLocalMachine(FALSE),
m_dwCachedLineSize(0),
m_dwCachedPhoneSize(0),
m_fCacheDirty(0)
{
DEBUG_INCREMENT_INSTANCE_COUNTER(CTapiInfo);
for (int i = 0; i < DEVICE_TYPE_MAX; i++)
m_paDeviceInfo[i] = NULL;
}
CTapiInfo::~CTapiInfo()
{
DEBUG_DECREMENT_INSTANCE_COUNTER(CTapiInfo);
CSingleLock cl(&m_csData);
if (m_hServer)
{
Destroy();
}
cl.Lock();
if (m_pTapiConfig)
{
free(m_pTapiConfig);
m_pTapiConfig = NULL;
}
for (int i = 0; i < DEVICE_TYPE_MAX; i++)
{
if (m_paDeviceInfo[i])
{
free(m_paDeviceInfo[i]);
m_paDeviceInfo[i] = NULL;
}
}
if (m_pProviderList)
{
free(m_pProviderList);
m_pProviderList = NULL;
}
if (m_pAvailProviderList)
{
free(m_pAvailProviderList);
m_pAvailProviderList = NULL;
}
if (m_hResetEvent)
{
CloseHandle(m_hResetEvent);
m_hResetEvent = NULL;
}
cl.Unlock();
}
// Although this object is not a COM Interface, we want to be able to
// take advantage of recounting, so we have basic addref/release/QI support
IMPLEMENT_ADDREF_RELEASE(CTapiInfo)
IMPLEMENT_SIMPLE_QUERYINTERFACE(CTapiInfo, ITapiInfo)
/*!--------------------------------------------------------------------------
CTapiInfo::Initialize()
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::Initialize()
{
HRESULT hr = hrOK;
LONG lReturn = 0;
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer)
{
// already initialized
return S_OK;
}
CString strLocalMachineName;
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
LPTSTR pBuf = strLocalMachineName.GetBuffer(dwSize);
::GetComputerName(pBuf, &dwSize);
strLocalMachineName.ReleaseBuffer();
if (m_strComputerName.IsEmpty())
{
m_strComputerName = strLocalMachineName;
m_fIsLocalMachine = TRUE;
Trace1("CTapiInfo::Initialize - Using local computer %s\n", m_strComputerName);
}
else
{
m_fIsLocalMachine = (0 == m_strComputerName.CompareNoCase(strLocalMachineName)) ?
TRUE : FALSE;
Trace1("CTapiInfo::Initialize - Using computer %s\n", m_strComputerName);
}
if (m_hResetEvent == NULL)
{
m_hResetEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hResetEvent == NULL)
{
return HRESULT_FROM_WIN32(GetLastError());
}
}
lReturn = ((INITIALIZE) g_TapiDLL[TAPI_INITIALIZE])(m_strComputerName, &m_hServer, &m_dwApiVersion, &m_hResetEvent);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::Initialize - Initialize failed! %lx\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
// check to see if the local user is an admin on the machine
::IsAdmin(m_strComputerName, NULL, NULL, &m_fIsAdmin);
// get the local user name for later to compare against list of tapi admins
GetCurrentUser();
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::Reset()
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::Reset()
{
LONG lReturn = 0;
for (int i = 0; i < DEVICE_TYPE_MAX; i++)
{
m_IndexMgr[i].Reset();
}
return S_OK;
}
/*!--------------------------------------------------------------------------
CTapiInfo::Destroy()
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::Destroy()
{
LONG lReturn = 0;
HRESULT hr = S_OK;
if ( !g_TapiDLL.LoadFunctionPointers() )
return hr;
if (m_hServer == NULL)
{
return hr;
}
lReturn = ((SHUTDOWN) g_TapiDLL[TAPI_SHUTDOWN])(m_hServer);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::Destroy - Shutdown failed! %lx\n", lReturn);
hr = HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
m_hServer = NULL;
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::EnumConfigInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::EnumConfigInfo()
{
CSingleLock cl(&m_csData);
LONG lReturn = 0;
TAPISERVERCONFIG tapiServerConfig = {0};
LPTAPISERVERCONFIG pTapiServerConfig = NULL;
HRESULT hr = hrOK;
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::GetConfigInfo - Server not initialized!\n");
return E_FAIL;
}
COM_PROTECT_TRY
{
// the first call will tell us how big of a buffer we need to allocate
// to hold the config info struct
tapiServerConfig.dwTotalSize = sizeof(TAPISERVERCONFIG);
lReturn = ((GETSERVERCONFIG) g_TapiDLL[TAPI_GET_SERVER_CONFIG])(m_hServer, &tapiServerConfig);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::GetConfigInfo - 1st MMCGetServerConfig returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
pTapiServerConfig = (LPTAPISERVERCONFIG) malloc(tapiServerConfig.dwNeededSize);
if (NULL == pTapiServerConfig)
{
return E_OUTOFMEMORY;
}
memset(pTapiServerConfig, 0, tapiServerConfig.dwNeededSize);
pTapiServerConfig->dwTotalSize = tapiServerConfig.dwNeededSize;
lReturn = ((GETSERVERCONFIG) g_TapiDLL[TAPI_GET_SERVER_CONFIG])(m_hServer, pTapiServerConfig);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::GetConfigInfo - 2nd MMCGetServerConfig returned %x!\n", lReturn);
free(pTapiServerConfig);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
cl.Lock();
if (m_pTapiConfig)
{
free(m_pTapiConfig);
}
m_pTapiConfig = pTapiServerConfig;
cl.Unlock();
}
COM_PROTECT_CATCH
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetConfigInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::GetConfigInfo(CTapiConfigInfo * ptapiConfigInfo)
{
CSingleLock cl(&m_csData);
cl.Lock();
if (m_pTapiConfig)
{
TapiConfigToInternal(m_pTapiConfig, *ptapiConfigInfo);
}
else
{
return E_FAIL;
}
return S_OK;
}
/*!--------------------------------------------------------------------------
CTapiInfo::SetConfigInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::SetConfigInfo(CTapiConfigInfo * ptapiConfigInfo)
{
CSingleLock cl(&m_csData);
LPTAPISERVERCONFIG pServerConfig = NULL;
HRESULT hr = hrOK;
LONG lReturn = 0;
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::SetConfigInfo - Server not initialized!\n");
return E_FAIL;
}
InternalToTapiConfig(*ptapiConfigInfo, &pServerConfig);
Assert(pServerConfig);
if (pServerConfig)
{
// make the call
lReturn = ((SETSERVERCONFIG) g_TapiDLL[TAPI_SET_SERVER_CONFIG])(m_hServer, pServerConfig);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::SetConfigInfo - MMCSetServerConfig returned %x!\n", lReturn);
free(pServerConfig);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
// free up the old config struct if there was one
cl.Lock();
if (m_pTapiConfig)
free(m_pTapiConfig);
m_pTapiConfig = pServerConfig;
//Bug 276787 We should clear the two write bits
m_pTapiConfig->dwFlags &= ~(TAPISERVERCONFIGFLAGS_SETACCOUNT |
TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS);
cl.Unlock();
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::IsServer
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(BOOL)
CTapiInfo::IsServer()
{
CSingleLock cl(&m_csData);
cl.Lock();
if (m_pTapiConfig)
return m_pTapiConfig->dwFlags & TAPISERVERCONFIGFLAGS_ISSERVER;
else if (!m_strComputerName.IsEmpty())
{
BOOL fIsNTS = FALSE;
TFSIsNTServer(m_strComputerName, &fIsNTS);
return fIsNTS;
}
else
return FALSE; // assume workstation
}
/*!--------------------------------------------------------------------------
CTapiInfo::IsTapiServer
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(BOOL)
CTapiInfo::IsTapiServer()
{
CSingleLock cl(&m_csData);
cl.Lock();
if (m_pTapiConfig)
return m_pTapiConfig->dwFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER;
else
return FALSE; // assume not a tapi server
}
STDMETHODIMP
CTapiInfo::SetComputerName(LPCTSTR pComputer)
{
m_strComputerName = pComputer;
return hrOK;
}
STDMETHODIMP_(LPCTSTR)
CTapiInfo::GetComputerName()
{
return m_strComputerName;
}
/*!--------------------------------------------------------------------------
CTapiInfo::IsLocalMachine
Says whether this machine is local or remote
Author: NSun
---------------------------------------------------------------------------*/
STDMETHODIMP_(BOOL)
CTapiInfo::IsLocalMachine()
{
return m_fIsLocalMachine;
}
/*!--------------------------------------------------------------------------
CTapiInfo::FHasServiceControl
Says whether we the access of service control for tapisrv
Author: NSun
---------------------------------------------------------------------------*/
STDMETHODIMP_(BOOL)
CTapiInfo::FHasServiceControl()
{
CSingleLock cl(&m_csData);
cl.Lock();
if (m_pTapiConfig)
return !(m_pTapiConfig->dwFlags & TAPISERVERCONFIGFLAGS_NOSERVICECONTROL);
else
return FALSE; // assume workstation
}
STDMETHODIMP
CTapiInfo::SetCachedLineBuffSize(DWORD dwLineSize)
{
m_dwCachedLineSize = dwLineSize;
return S_OK;
}
STDMETHODIMP
CTapiInfo::SetCachedPhoneBuffSize(DWORD dwPhoneSize)
{
m_dwCachedPhoneSize = dwPhoneSize;
return S_OK;
}
STDMETHODIMP_(DWORD)
CTapiInfo::GetCachedLineBuffSize()
{
return m_dwCachedLineSize;
}
STDMETHODIMP_(DWORD)
CTapiInfo::GetCachedPhoneBuffSize()
{
return m_dwCachedPhoneSize;
}
STDMETHODIMP_(BOOL)
CTapiInfo::IsCacheDirty()
{
return m_fCacheDirty;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetProviderCount
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CTapiInfo::GetProviderCount()
{
CSingleLock cl(&m_csData);
cl.Lock();
if (m_pProviderList)
{
return m_pProviderList->dwNumProviders;
}
else
{
return 0;
}
}
/*!--------------------------------------------------------------------------
CTapiInfo::EnumProviders
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::EnumProviders()
{
CSingleLock cl(&m_csData);
LINEPROVIDERLIST tapiProviderList = {0};
LPLINEPROVIDERLIST pProviderList = NULL;
HRESULT hr = hrOK;
LONG lReturn = 0;
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::GetConfigInfo - Server not initialized!\n");
return E_FAIL;
}
COM_PROTECT_TRY
{
// the first call will tell us how big of a buffer we need to allocate
// to hold the provider list struct
tapiProviderList.dwTotalSize = sizeof(LINEPROVIDERLIST);
lReturn = ((GETPROVIDERLIST) g_TapiDLL[TAPI_GET_PROVIDER_LIST])(m_hServer, &tapiProviderList);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::EnumProviders - 1st MMCGetProviderList returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
pProviderList = (LPLINEPROVIDERLIST) malloc(tapiProviderList.dwNeededSize);
if (NULL == pProviderList)
{
return E_OUTOFMEMORY;
}
memset(pProviderList, 0, tapiProviderList.dwNeededSize);
pProviderList->dwTotalSize = tapiProviderList.dwNeededSize;
lReturn = ((GETPROVIDERLIST) g_TapiDLL[TAPI_GET_PROVIDER_LIST])(m_hServer, pProviderList);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::EnumProviders - 2nd MMCGetProviderList returned %x!\n", lReturn);
free(pProviderList);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
cl.Lock();
if (m_pProviderList)
{
free(m_pProviderList);
}
m_pProviderList = pProviderList;
cl.Unlock();
}
COM_PROTECT_CATCH
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetProviderInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::GetProviderInfo(CTapiProvider * pproviderInfo, int nIndex)
{
CSingleLock cl(&m_csData);
cl.Lock();
HRESULT hr = hrOK;
LPLINEPROVIDERENTRY pProvider = NULL;
if (m_pProviderList == NULL)
return E_FAIL;
if ((UINT) nIndex > m_pProviderList->dwNumProviders)
return E_FAIL;
pProvider = (LPLINEPROVIDERENTRY) ((LPBYTE) m_pProviderList + m_pProviderList->dwProviderListOffset);
for (int i = 0; i < nIndex; i++)
{
pProvider++;
}
pproviderInfo->m_dwProviderID = pProvider->dwPermanentProviderID;
pproviderInfo->m_strFilename = (LPCWSTR) ((LPBYTE) m_pProviderList + pProvider->dwProviderFilenameOffset);
pproviderInfo->m_strName = GetProviderName(pproviderInfo->m_dwProviderID, pproviderInfo->m_strFilename, &pproviderInfo->m_dwFlags);
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetProviderInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::GetProviderInfo(CTapiProvider * pproviderInfo, DWORD dwProviderID)
{
CSingleLock cl(&m_csData);
cl.Lock();
HRESULT hr = hrOK;
LPLINEPROVIDERENTRY pProvider = NULL;
if (m_pProviderList == NULL)
return E_FAIL;
pProvider = (LPLINEPROVIDERENTRY) ((LPBYTE) m_pProviderList + m_pProviderList->dwProviderListOffset);
for (UINT i = 0; i < m_pProviderList->dwNumProviders; i++)
{
if (pProvider->dwPermanentProviderID == dwProviderID)
break;
pProvider++;
}
pproviderInfo->m_dwProviderID = pProvider->dwPermanentProviderID;
pproviderInfo->m_strFilename = (LPCWSTR) ((LPBYTE) m_pProviderList + pProvider->dwProviderFilenameOffset);
pproviderInfo->m_strName = GetProviderName(pproviderInfo->m_dwProviderID, pproviderInfo->m_strFilename, &pproviderInfo->m_dwFlags);
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::AddProvider
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::AddProvider(LPCTSTR pProviderFilename, LPDWORD pdwProviderID, HWND hWnd)
{
CSingleLock cl(&m_csData);
cl.Lock();
LONG lReturn = 0;
HRESULT hr = hrOK;
HWND hWndParent;
if (hWnd == NULL)
{
hWndParent = ::FindMMCMainWindow();
}
else
{
hWndParent = hWnd;
}
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::AddProvider - Server not initialized!\n");
return E_FAIL;
}
lReturn = ((ADDPROVIDER) g_TapiDLL[TAPI_ADD_PROVIDER])(m_hServer, hWndParent, pProviderFilename, pdwProviderID);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::AddProvider - MMCAddProvider returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::ConfigureProvider
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::ConfigureProvider(DWORD dwProviderID, HWND hWnd)
{
LONG lReturn = 0;
HRESULT hr = hrOK;
HWND hWndParent;
if (hWnd == NULL)
{
hWndParent = ::FindMMCMainWindow();
}
else
{
hWndParent = hWnd;
}
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::ConfigureProvider - Server not initialized!\n");
return E_FAIL;
}
lReturn = ((CONFIGPROVIDER) g_TapiDLL[TAPI_CONFIG_PROVIDER])(m_hServer, hWndParent, dwProviderID);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::ConfigureProvider - MMCConfigureProvider returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::RemoveProvider
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::RemoveProvider(DWORD dwProviderID, HWND hWnd)
{
LONG lReturn = 0;
HRESULT hr = hrOK;
HWND hWndParent;
if (hWnd == NULL)
{
hWndParent = ::FindMMCMainWindow();
}
else
{
hWndParent = hWnd;
}
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::RemoveProvider - Server not initialized!\n");
return E_FAIL;
}
lReturn = ((REMOVEPROVIDER) g_TapiDLL[TAPI_REMOVE_PROVIDER])(m_hServer, hWndParent, dwProviderID);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::RemoveProvider - MMCRemoveProvider returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetAvailableProviderCount
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CTapiInfo::GetAvailableProviderCount()
{
CSingleLock cl(&m_csData);
cl.Lock();
if (m_pAvailProviderList)
{
return m_pAvailProviderList->dwNumProviderListEntries;
}
else
{
return 0;
}
}
/*!--------------------------------------------------------------------------
CTapiInfo::EnumAvailableProviders
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::EnumAvailableProviders()
{
CSingleLock cl(&m_csData);
AVAILABLEPROVIDERLIST tapiProviderList = {0};
LPAVAILABLEPROVIDERLIST pProviderList = NULL;
HRESULT hr = hrOK;
LONG lReturn = 0;
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::GetConfigInfo - Server not initialized!\n");
return E_FAIL;
}
COM_PROTECT_TRY
{
// the first call will tell us how big of a buffer we need to allocate
// to hold the provider list struct
tapiProviderList.dwTotalSize = sizeof(LINEPROVIDERLIST);
lReturn = ((GETAVAILABLEPROVIDERS) g_TapiDLL[TAPI_GET_AVAILABLE_PROVIDERS])(m_hServer, &tapiProviderList);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::EnumProviders - 1st MMCGetAvailableProviders returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
pProviderList = (LPAVAILABLEPROVIDERLIST) malloc(tapiProviderList.dwNeededSize);
memset(pProviderList, 0, tapiProviderList.dwNeededSize);
pProviderList->dwTotalSize = tapiProviderList.dwNeededSize;
lReturn = ((GETAVAILABLEPROVIDERS) g_TapiDLL[TAPI_GET_AVAILABLE_PROVIDERS])(m_hServer, pProviderList);
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::EnumProviders - 2nd MMCGetAvailableProviders returned %x!\n", lReturn);
free(pProviderList);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
cl.Lock();
if (m_pAvailProviderList)
{
free(m_pAvailProviderList);
}
m_pAvailProviderList = pProviderList;
cl.Unlock();
}
COM_PROTECT_CATCH
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetAvailableProviderInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::GetAvailableProviderInfo(CTapiProvider * pproviderInfo, int nIndex)
{
CSingleLock cl(&m_csData);
cl.Lock();
HRESULT hr = hrOK;
LPAVAILABLEPROVIDERENTRY pProvider = NULL;
if (m_pAvailProviderList == NULL)
return E_FAIL;
if ((UINT) nIndex > m_pAvailProviderList->dwNumProviderListEntries)
return E_FAIL;
pProvider = (LPAVAILABLEPROVIDERENTRY) ((LPBYTE) m_pAvailProviderList + m_pAvailProviderList->dwProviderListOffset);
for (int i = 0; i < nIndex; i++)
{
pProvider++;
}
// available providers do not have ProviderIDs until they are installed
pproviderInfo->m_dwProviderID = 0;
pproviderInfo->m_dwFlags = pProvider->dwOptions;
pproviderInfo->m_strName = (LPCWSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFriendlyNameOffset);
pproviderInfo->m_strFilename = (LPCWSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFileNameOffset);
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::EnumDevices
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::EnumDevices(DEVICE_TYPE deviceType)
{
CSingleLock cl(&m_csData);
LONG lReturn = 0;
HRESULT hr = hrOK;
LPDEVICEINFOLIST pDeviceInfoList = NULL;
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
return E_FAIL;
}
// the first call will tell us how big of a buffer we need to allocate
// to hold the provider list struct
COM_PROTECT_TRY
{
// Fix bug 381469
// First allocate the cached size of memory to get line info
DWORD dwCachedSize = (DEVICE_LINE == deviceType) ? m_dwCachedLineSize : m_dwCachedPhoneSize;
if (dwCachedSize < sizeof(DEVICEINFOLIST))
{
//if we didn't have the cached size, then use the default size
dwCachedSize = TAPI_DEFAULT_DEVICE_BUFF_SIZE;
m_fCacheDirty = TRUE;
}
DWORD dwTotalSize = dwCachedSize + DEVICEINFO_GROW_SIZE;
pDeviceInfoList = (LPDEVICEINFOLIST) malloc(dwTotalSize);
if (NULL == pDeviceInfoList)
{
return E_OUTOFMEMORY;
}
memset(pDeviceInfoList, 0, dwTotalSize);
pDeviceInfoList->dwTotalSize = dwTotalSize;
switch (deviceType)
{
case DEVICE_LINE:
lReturn = ((GETLINEINFO) g_TapiDLL[TAPI_GET_LINE_INFO])(m_hServer, pDeviceInfoList);
break;
case DEVICE_PHONE:
lReturn = ((GETPHONEINFO) g_TapiDLL[TAPI_GET_PHONE_INFO])(m_hServer, pDeviceInfoList);
break;
}
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::EnumDevices - 1st MMCGetDeviceInfo returned %x!\n", lReturn);
free (pDeviceInfoList);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
if (pDeviceInfoList->dwNeededSize > pDeviceInfoList->dwTotalSize)
{
// the cached size is too small, now allocate the buffer and call again to the the info
DWORD dwNeededSize = pDeviceInfoList->dwNeededSize;
free (pDeviceInfoList);
dwNeededSize += DEVICEINFO_GROW_SIZE;
pDeviceInfoList = (LPDEVICEINFOLIST) malloc(dwNeededSize);
memset(pDeviceInfoList, 0, dwNeededSize);
pDeviceInfoList->dwTotalSize = dwNeededSize;
switch (deviceType)
{
case DEVICE_LINE:
lReturn = ((GETLINEINFO) g_TapiDLL[TAPI_GET_LINE_INFO])(m_hServer, pDeviceInfoList);
break;
case DEVICE_PHONE:
lReturn = ((GETPHONEINFO) g_TapiDLL[TAPI_GET_PHONE_INFO])(m_hServer, pDeviceInfoList);
break;
}
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::EnumDevices - 2nd MMCGetDeviceInfo returned %x!\n", lReturn);
free(pDeviceInfoList);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
}
//update the cache
if (DEVICE_LINE == deviceType && m_dwCachedLineSize != pDeviceInfoList->dwNeededSize)
{
m_dwCachedLineSize = pDeviceInfoList->dwNeededSize;
m_fCacheDirty = TRUE;
}
else if (DEVICE_PHONE == deviceType && m_dwCachedPhoneSize != pDeviceInfoList->dwNeededSize)
{
m_dwCachedPhoneSize = pDeviceInfoList->dwNeededSize;
m_fCacheDirty = TRUE;
}
cl.Lock();
if (m_paDeviceInfo[deviceType])
{
free (m_paDeviceInfo[deviceType]);
}
m_paDeviceInfo[deviceType] = pDeviceInfoList;
// build our index list for sorting
if (pDeviceInfoList->dwNumDeviceInfoEntries)
{
LPDEVICEINFO pDevice = NULL;
pDevice = (LPDEVICEINFO) ((LPBYTE) pDeviceInfoList + pDeviceInfoList->dwDeviceInfoOffset);
// now add all of the devices to our index
for (int i = 0; i < GetTotalDeviceCount(deviceType); i++)
{
// walk the list of device info structs and add to the index mgr
m_IndexMgr[deviceType].AddHDevice(pDevice->dwProviderID, (HDEVICE) pDevice, TRUE);
pDevice++;
}
}
cl.Unlock();
}
COM_PROTECT_CATCH
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetTotalDeviceCount
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CTapiInfo::GetTotalDeviceCount(DEVICE_TYPE deviceType)
{
CSingleLock cl(&m_csData);
cl.Lock();
if (m_paDeviceInfo[deviceType])
{
return m_paDeviceInfo[deviceType]->dwNumDeviceInfoEntries;
}
else
{
return 0;
}
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetDeviceCount
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CTapiInfo::GetDeviceCount(DEVICE_TYPE deviceType, DWORD dwProviderID)
{
m_IndexMgr[deviceType].SetCurrentProvider(dwProviderID);
return m_IndexMgr[deviceType].GetCurrentCount();
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetDeviceInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::GetDeviceInfo(DEVICE_TYPE deviceType, CTapiDevice * ptapiDevice, DWORD dwProviderID, int nIndex)
{
CSingleLock cl(&m_csData);
cl.Lock();
LPDEVICEINFO pDevice = NULL;
HDEVICE hdevice = NULL;
HRESULT hr = hrOK;
if (m_paDeviceInfo[deviceType] == NULL)
return E_FAIL;
if ((UINT) nIndex > m_paDeviceInfo[deviceType]->dwNumDeviceInfoEntries)
return E_INVALIDARG;
hr = m_IndexMgr[deviceType].GetHDevice(dwProviderID, nIndex, &hdevice);
if (FAILED(hr))
return hr;
pDevice = (LPDEVICEINFO) hdevice;
if (pDevice == NULL)
return E_FAIL;
TapiDeviceToInternal(deviceType, pDevice, *ptapiDevice);
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::SetDeviceInfo
Sets the device info on a TAPI server. First builds a deviceinfolist
struct to user for the SetDeviceInfo call then updates the internal
device info list.
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::SetDeviceInfo(DEVICE_TYPE deviceType, CTapiDevice * ptapiDevice)
{
CSingleLock cl(&m_csData);
cl.Lock();
HRESULT hr = hrOK;
LONG lReturn = 0;
LPDEVICEINFOLIST pDeviceInfoList = NULL, pNewDeviceInfoList;
LPDEVICEINFO pDeviceInfo = NULL;
int i;
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
return E_FAIL;
}
InternalToTapiDevice(*ptapiDevice, &pDeviceInfoList);
Assert(pDeviceInfoList);
if (!pDeviceInfoList)
return E_OUTOFMEMORY;
// make the call...
switch (deviceType)
{
case DEVICE_LINE:
lReturn = ((SETLINEINFO) g_TapiDLL[TAPI_SET_LINE_INFO])(m_hServer, pDeviceInfoList);
break;
case DEVICE_PHONE:
lReturn = ((SETPHONEINFO) g_TapiDLL[TAPI_SET_PHONE_INFO])(m_hServer, pDeviceInfoList);
break;
}
if (lReturn != ERROR_SUCCESS)
{
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
// finally, update our internal struct to reflect the changes
Assert(m_paDeviceInfo[deviceType]);
pDeviceInfo = (LPDEVICEINFO) ((LPBYTE) pDeviceInfoList + pDeviceInfoList->dwDeviceInfoOffset);
// find the device in the list
LPDEVICEINFO pDevice = NULL;
pDevice = (LPDEVICEINFO) ((LPBYTE) m_paDeviceInfo[deviceType] + m_paDeviceInfo[deviceType]->dwDeviceInfoOffset);
for (i = 0; i < GetTotalDeviceCount(deviceType); i++)
{
// walk the list of device info structs and add to the index mgr
if (pDevice->dwPermanentDeviceID == ptapiDevice->m_dwPermanentID)
{
// update the device info here. First check to make sure we have enough room to grow
if (m_paDeviceInfo[deviceType]->dwTotalSize < (m_paDeviceInfo[deviceType]->dwUsedSize + pDeviceInfo->dwDomainUserNamesSize + pDeviceInfo->dwFriendlyUserNamesSize))
{
// we've run out of room. Realloc a bigger piece
pNewDeviceInfoList = (LPDEVICEINFOLIST) realloc(m_paDeviceInfo[deviceType], m_paDeviceInfo[deviceType]->dwTotalSize + DEVICEINFO_GROW_SIZE);
if (pNewDeviceInfoList == NULL)
{
free(pDeviceInfoList);
return E_OUTOFMEMORY;
}
else
{
m_paDeviceInfo[deviceType] = pNewDeviceInfoList;
}
// Update the dwTotalSize
m_paDeviceInfo[deviceType]->dwTotalSize = m_paDeviceInfo[deviceType]->dwTotalSize + DEVICEINFO_GROW_SIZE;
}
// update the sizes
pDevice->dwDomainUserNamesSize = pDeviceInfo->dwDomainUserNamesSize;
pDevice->dwFriendlyUserNamesSize = pDeviceInfo->dwFriendlyUserNamesSize;
// update the new domain name info
pDevice->dwDomainUserNamesOffset = m_paDeviceInfo[deviceType]->dwUsedSize;
memcpy(((LPBYTE) m_paDeviceInfo[deviceType] + pDevice->dwDomainUserNamesOffset),
((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDomainUserNamesOffset),
pDeviceInfo->dwDomainUserNamesSize);
// update the new friendly name info
pDevice->dwFriendlyUserNamesOffset = m_paDeviceInfo[deviceType]->dwUsedSize + pDevice->dwDomainUserNamesSize;
memcpy(((LPBYTE) m_paDeviceInfo[deviceType] + pDevice->dwFriendlyUserNamesOffset),
((LPBYTE) pDeviceInfoList + pDeviceInfo->dwFriendlyUserNamesOffset),
pDeviceInfo->dwFriendlyUserNamesOffset);
m_paDeviceInfo[deviceType]->dwUsedSize += (pDevice->dwDomainUserNamesSize + pDevice->dwFriendlyUserNamesSize);
}
pDevice++;
}
free(pDeviceInfoList);
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::SortDeviceInfo
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::SortDeviceInfo(DEVICE_TYPE deviceType, DWORD dwProviderID, INDEX_TYPE indexType, DWORD dwSortOptions)
{
CSingleLock cl(&m_csData);
cl.Lock();
HRESULT hr = hrOK;
if (m_paDeviceInfo[deviceType])
m_IndexMgr[deviceType].Sort(dwProviderID, indexType, dwSortOptions, (LPBYTE) m_paDeviceInfo[deviceType]);
return hr;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetDeviceStatus
-
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CTapiInfo::GetDeviceStatus(DEVICE_TYPE deviceType, CString * pstrStatus, DWORD dwProviderID, int nIndex, HWND hWnd)
{
CSingleLock cl(&m_csData);
HRESULT hr = hrOK;
LPDEVICEINFO pDevice = NULL;
HDEVICE hdevice;
LONG lReturn = 0;
BYTE data[256] = {0};
LPVARSTRING pVarStatus = (LPVARSTRING) &data[0];
int nHash;
CString strStatus;
CString strData;
HWND hWndParent;
if (hWnd == NULL)
{
hWndParent = ::FindMMCMainWindow();
}
else
{
hWndParent = hWnd;
}
if ( !g_TapiDLL.LoadFunctionPointers() )
return S_OK;
if (m_hServer == NULL)
{
Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
return E_FAIL;
}
cl.Lock();
hr = m_IndexMgr[deviceType].GetHDevice(dwProviderID, nIndex, &hdevice);
if (FAILED(hr))
return hr;
pDevice = (LPDEVICEINFO) hdevice;
if (pDevice == NULL)
return E_FAIL;
// try to get the string
pVarStatus->dwTotalSize = sizeof(data);
switch (deviceType)
{
case DEVICE_LINE:
lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_LINE_STATUS])(m_hServer,
hWndParent,
0,
pDevice->dwProviderID,
pDevice->dwPermanentDeviceID,
pVarStatus);
break;
case DEVICE_PHONE:
lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_PHONE_STATUS])(m_hServer,
hWndParent,
0,
pDevice->dwProviderID,
pDevice->dwPermanentDeviceID,
pVarStatus);
break;
}
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::GetDeviceStatus - 1st call to GetDeviceStatus returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
if (pVarStatus->dwNeededSize > pVarStatus->dwTotalSize)
{
// buffer not big enough, try again.
pVarStatus = (LPVARSTRING) alloca(pVarStatus->dwNeededSize);
memset(pVarStatus, 0, pVarStatus->dwNeededSize);
pVarStatus->dwTotalSize = pVarStatus->dwNeededSize;
switch (deviceType)
{
case DEVICE_LINE:
lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_LINE_STATUS])(m_hServer,
hWndParent,
0,
pDevice->dwProviderID,
pDevice->dwPermanentDeviceID,
pVarStatus);
break;
case DEVICE_PHONE:
lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_PHONE_STATUS])(m_hServer,
hWndParent,
0,
pDevice->dwProviderID,
pDevice->dwPermanentDeviceID,
pVarStatus);
break;
}
if (lReturn != ERROR_SUCCESS)
{
Trace1("CTapiInfo::GetDeviceStatus - 2nd call to GetDeviceStatus returned %x!\n", lReturn);
return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
}
}
cl.Unlock();
// now see if the string exists in our table. If so, return a pointer to that,
// otherwise add and return a pointer to our table.
strStatus = (LPCTSTR) ((LPBYTE) pVarStatus + pVarStatus->dwStringOffset);
if (!m_mapStatusStrings.Lookup(strStatus, strData))
{
Trace1("CTapiInfo::GetDeviceStatus - Entry for %s added.\n", strStatus);
strData = strStatus;
m_mapStatusStrings.SetAt(strStatus, strData);
}
else
{
// entry is already in our map
}
*pstrStatus = strData;
return hr;
}
/*!--------------------------------------------------------------------------
Internal functions
---------------------------------------------------------------------------*/
/*!--------------------------------------------------------------------------
CTapiInfo::TapiConfigToInternal
-
Author: EricDav
---------------------------------------------------------------------------*/
void
CTapiInfo::TapiConfigToInternal(LPTAPISERVERCONFIG pTapiConfig, CTapiConfigInfo & tapiConfigInfo)
{
HRESULT hr = hrOK;
UINT uAdminLength = (pTapiConfig->dwAdministratorsSize != 0) ? pTapiConfig->dwAdministratorsSize - sizeof(WCHAR) : 0;
UINT uAdminOffset = 0;
CUserInfo userTemp;
COM_PROTECT_TRY
{
if (pTapiConfig->dwDomainNameSize)
tapiConfigInfo.m_strDomainName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwDomainNameOffset);
if (pTapiConfig->dwUserNameSize)
tapiConfigInfo.m_strUserName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwUserNameOffset);
if (pTapiConfig->dwPasswordSize)
tapiConfigInfo.m_strPassword = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwPasswordOffset);
// add all of the administrators from the list
while (uAdminOffset < uAdminLength)
{
userTemp.m_strName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwAdministratorsOffset + uAdminOffset);
if (!userTemp.m_strName.IsEmpty())
{
int nIndex = (int)tapiConfigInfo.m_arrayAdministrators.Add(userTemp);
}
uAdminOffset += (userTemp.m_strName.GetLength() + 1) * sizeof(TCHAR);
}
tapiConfigInfo.m_dwFlags = pTapiConfig->dwFlags;
}
COM_PROTECT_CATCH
}
/*!--------------------------------------------------------------------------
CTapiInfo::InternalToTapiConfig
-
Author: EricDav
---------------------------------------------------------------------------*/
void
CTapiInfo::InternalToTapiConfig(CTapiConfigInfo & tapiConfigInfo, LPTAPISERVERCONFIG * ppTapiConfig)
{
LPTAPISERVERCONFIG pTapiConfig = NULL;
HRESULT hr = hrOK;
UINT uSize = sizeof(TAPISERVERCONFIG);
UINT uDomainNameSize = 0;
UINT uUserNameSize = 0;
UINT uPasswordSize = 0;
UINT uAdministratorsSize = 0;
UINT uAdminOffset = 0;
int i;
COM_PROTECT_TRY
{
*ppTapiConfig = NULL;
// calculate the size of the struct we will need
uDomainNameSize = (tapiConfigInfo.m_strDomainName.GetLength() + 1) * sizeof(WCHAR);
uUserNameSize = (tapiConfigInfo.m_strUserName.GetLength() + 1) * sizeof(WCHAR);
uPasswordSize = (tapiConfigInfo.m_strPassword.GetLength() + 1) * sizeof(WCHAR);
for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
{
uAdministratorsSize += (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
}
// for the extra null terminator
if (uAdministratorsSize > 0)
uAdministratorsSize += sizeof(WCHAR);
else
// if there are no names then we need two null terminators
uAdministratorsSize += 2 * sizeof(WCHAR);
uSize += uDomainNameSize + uUserNameSize + uPasswordSize + uAdministratorsSize;
pTapiConfig = (LPTAPISERVERCONFIG) malloc(uSize);
if (NULL == pTapiConfig)
{
return;
}
ZeroMemory(pTapiConfig, uSize);
// fill in the structure
pTapiConfig->dwTotalSize = uSize;
pTapiConfig->dwNeededSize = uSize;
pTapiConfig->dwUsedSize = uSize;
pTapiConfig->dwFlags = tapiConfigInfo.m_dwFlags;
pTapiConfig->dwDomainNameSize = uDomainNameSize;
pTapiConfig->dwDomainNameOffset = sizeof(TAPISERVERCONFIG);
memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwDomainNameOffset),
(LPCTSTR) tapiConfigInfo.m_strDomainName,
uDomainNameSize );
pTapiConfig->dwUserNameSize = uUserNameSize;
pTapiConfig->dwUserNameOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize;
memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwUserNameOffset),
(LPCTSTR) tapiConfigInfo.m_strUserName,
uUserNameSize );
pTapiConfig->dwPasswordSize = uPasswordSize;
pTapiConfig->dwPasswordOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize + uUserNameSize;
memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwPasswordOffset),
(LPCTSTR) tapiConfigInfo.m_strPassword,
uPasswordSize );
pTapiConfig->dwAdministratorsSize = uAdministratorsSize;
pTapiConfig->dwAdministratorsOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize + uUserNameSize + uPasswordSize;
if (uAdministratorsSize > 0)
{
for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
{
memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwAdministratorsOffset + uAdminOffset),
(LPCTSTR) tapiConfigInfo.m_arrayAdministrators[i].m_strName,
(tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR) );
uAdminOffset += (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
}
}
*ppTapiConfig = pTapiConfig;
}
COM_PROTECT_CATCH
}
/*!--------------------------------------------------------------------------
CTapiInfo::TapiDeviceToInternal
-
Author: EricDav
---------------------------------------------------------------------------*/
void
CTapiInfo::TapiDeviceToInternal(DEVICE_TYPE deviceType, LPDEVICEINFO pTapiDeviceInfo, CTapiDevice & tapiDevice)
{
HRESULT hr = hrOK;
UINT uCurSize = 0;
UINT uCurOffset = 0;
CUserInfo userTemp;
int nCount = 0;
COM_PROTECT_TRY
{
tapiDevice.m_dwPermanentID = pTapiDeviceInfo->dwPermanentDeviceID;
tapiDevice.m_dwProviderID = pTapiDeviceInfo->dwProviderID;
if (pTapiDeviceInfo->dwDeviceNameSize > 0)
{
DWORD cch = pTapiDeviceInfo->dwDeviceNameSize / sizeof(TCHAR) + 1;
LPTSTR sz = tapiDevice.m_strName.GetBufferSetLength (cch);
LPTSTR pLastChar = sz + cch - 1;
memcpy (
sz,
(LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwDeviceNameOffset,
pTapiDeviceInfo->dwDeviceNameSize
);
// append NULL;
*pLastChar = _T('\0');
}
else
tapiDevice.m_strName.Empty();
// build a list of all of the devicess
// in the case that the string is empty then it will have 2 NULL terminators, one for the
// name and one for the overall string
if (pTapiDeviceInfo->dwAddressesSize > (2 * sizeof(WCHAR)))
{
uCurSize = pTapiDeviceInfo->dwAddressesSize - sizeof(WCHAR);
while (uCurOffset < uCurSize)
{
int nIndex = (int)tapiDevice.m_arrayAddresses.Add((LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwAddressesOffset + uCurOffset));
uCurOffset += (tapiDevice.m_arrayAddresses[nIndex].GetLength() + 1) * sizeof(TCHAR);
}
}
// add all of the usernames from the list
// in the case that the string is empty then it will have 2 NULL terminators, one for the
// name and one for the overall string
if (pTapiDeviceInfo->dwDomainUserNamesSize > (2 * sizeof(WCHAR)))
{
uCurOffset = 0;
uCurSize = pTapiDeviceInfo->dwDomainUserNamesSize - sizeof(WCHAR);
while (uCurOffset < uCurSize)
{
userTemp.m_strName = (LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwDomainUserNamesOffset + uCurOffset);
int nIndex = (int)tapiDevice.m_arrayUsers.Add(userTemp);
uCurOffset += (userTemp.m_strName.GetLength() + 1) * sizeof(TCHAR);
}
}
// in the case that the string is empty then it will have 2 NULL terminators, one for the
// name and one for the overall string
if (pTapiDeviceInfo->dwFriendlyUserNamesSize > (2 * sizeof(WCHAR)))
{
uCurOffset = 0;
uCurSize = pTapiDeviceInfo->dwFriendlyUserNamesSize - sizeof(WCHAR);
while (uCurOffset < uCurSize)
{
tapiDevice.m_arrayUsers[nCount].m_strFullName = (LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwFriendlyUserNamesOffset + uCurOffset);
uCurOffset += (tapiDevice.m_arrayUsers[nCount].m_strFullName.GetLength() + 1) * sizeof(TCHAR);
nCount++;
}
}
}
COM_PROTECT_CATCH
}
/*!--------------------------------------------------------------------------
CTapiInfo::InternalToTapiDevice
Takes one tapi device internal struct and builds a TAPIDEVICEINFO
struct for it.
Author: EricDav
---------------------------------------------------------------------------*/
void
CTapiInfo::InternalToTapiDevice(CTapiDevice & tapiDevice, LPDEVICEINFOLIST * ppTapiDeviceInfoList)
{
LPDEVICEINFO pDeviceInfo;
LPDEVICEINFOLIST pDeviceInfoList;
HRESULT hr = hrOK;
UINT uSize = 0;
int i;
COM_PROTECT_TRY
{
*ppTapiDeviceInfoList = NULL;
// first calculate the size of the buffer we need
uSize += (tapiDevice.m_strName.GetLength() + 1) * sizeof(WCHAR);
for (i = 0; i < tapiDevice.m_arrayAddresses.GetSize(); i++)
{
uSize += (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR);
}
for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
{
uSize += (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
uSize += (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR);
}
// for the terminating NULLs for both addresses, domain and friendly names
uSize += 3 * sizeof(WCHAR);
uSize += sizeof(DEVICEINFO);
uSize += sizeof(DEVICEINFOLIST);
// now allocate a buffer
pDeviceInfoList = (LPDEVICEINFOLIST) malloc(uSize);
if (!pDeviceInfoList)
return;
ZeroMemory(pDeviceInfoList, uSize);
// now fill in the info
pDeviceInfoList->dwTotalSize = uSize;
pDeviceInfoList->dwNeededSize = uSize;
pDeviceInfoList->dwUsedSize = uSize;
pDeviceInfoList->dwNumDeviceInfoEntries = 1;
pDeviceInfoList->dwDeviceInfoSize = sizeof(DEVICEINFO);
pDeviceInfoList->dwDeviceInfoOffset = sizeof(DEVICEINFOLIST);
pDeviceInfo = (LPDEVICEINFO) (((LPBYTE) pDeviceInfoList) + pDeviceInfoList->dwDeviceInfoOffset);
pDeviceInfo->dwPermanentDeviceID = tapiDevice.m_dwPermanentID;
pDeviceInfo->dwProviderID = tapiDevice.m_dwProviderID;
// Device name
pDeviceInfo->dwDeviceNameSize = (tapiDevice.m_strName.GetLength() + 1) * sizeof(WCHAR);
pDeviceInfo->dwDeviceNameOffset = pDeviceInfoList->dwDeviceInfoOffset + sizeof(DEVICEINFO);
memcpy((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDeviceNameOffset, (LPCTSTR) tapiDevice.m_strName, pDeviceInfo->dwDeviceNameSize);
// Device addresses
pDeviceInfo->dwAddressesOffset = pDeviceInfo->dwDeviceNameOffset + pDeviceInfo->dwDeviceNameSize;
for (i = 0; i < tapiDevice.m_arrayAddresses.GetSize(); i++)
{
memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwAddressesOffset + pDeviceInfo->dwAddressesSize),
(LPCTSTR) tapiDevice.m_arrayAddresses[i],
(tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR));
pDeviceInfo->dwAddressesSize += (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR);
}
// increment size by 1 for the extra null terminator
pDeviceInfo->dwAddressesSize += sizeof(WCHAR);
// now the user info
pDeviceInfo->dwDomainUserNamesOffset = pDeviceInfo->dwAddressesOffset + pDeviceInfo->dwAddressesSize;
for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
{
memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDomainUserNamesOffset + pDeviceInfo->dwDomainUserNamesSize),
(LPCTSTR) tapiDevice.m_arrayUsers[i].m_strName,
(tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR));
pDeviceInfo->dwDomainUserNamesSize += (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
}
// increment size by 1 for the extra null terminator
pDeviceInfo->dwDomainUserNamesSize += sizeof(WCHAR);
// now the friendly names
pDeviceInfo->dwFriendlyUserNamesOffset = pDeviceInfo->dwDomainUserNamesOffset + pDeviceInfo->dwDomainUserNamesSize;
for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
{
memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwFriendlyUserNamesOffset + pDeviceInfo->dwFriendlyUserNamesSize),
(LPCTSTR) tapiDevice.m_arrayUsers[i].m_strFullName,
(tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR));
pDeviceInfo->dwFriendlyUserNamesSize += (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR);
}
// increment size by 1 for the extra null terminator
pDeviceInfo->dwFriendlyUserNamesSize += sizeof(WCHAR);
*ppTapiDeviceInfoList = pDeviceInfoList;
}
COM_PROTECT_CATCH
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetProviderName
Takes a provider filename and tries to locate the friendly name.
Author: EricDav
---------------------------------------------------------------------------*/
LPCTSTR
CTapiInfo::GetProviderName(DWORD dwProviderID, LPCTSTR pszFilename, LPDWORD pdwFlags)
{
UINT i;
if (m_pAvailProviderList)
{
LPAVAILABLEPROVIDERENTRY pProvider = NULL;
pProvider = (LPAVAILABLEPROVIDERENTRY) ((LPBYTE) m_pAvailProviderList + m_pAvailProviderList->dwProviderListOffset);
for (i = 0; i < m_pAvailProviderList->dwNumProviderListEntries; i++)
{
// walk the available provider info and see if we can find
// a friendly name
LPCTSTR pszCurFilename = (LPCWSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFileNameOffset);
if (lstrcmpi(pszFilename, pszCurFilename) == 0)
{
// found it, return
if (pdwFlags)
*pdwFlags = pProvider->dwOptions;
return (LPCTSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFriendlyNameOffset);
}
pProvider++;
}
}
// if we can't find a friendly name for the provider,
// then just return the filename that was passed in.
return pszFilename;
}
/*!--------------------------------------------------------------------------
CTapiInfo::IsAdmin
Says whether on not the current user is an admin on the machine
Author: EricDav
---------------------------------------------------------------------------*/
BOOL
CTapiInfo::IsAdmin()
{
HRESULT hr = hrOK;
BOOL fIsAdmin = m_fIsAdmin;
BOOL fIsTapiAdmin = FALSE;
CTapiConfigInfo tapiConfigInfo;
DWORD dwErr = 0;
int i = 0;
CORg(GetConfigInfo(&tapiConfigInfo));
if (m_strCurrentUser.IsEmpty())
{
dwErr = GetCurrentUser();
}
if (dwErr == ERROR_SUCCESS)
{
for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
{
if (tapiConfigInfo.m_arrayAdministrators[i].m_strName.CompareNoCase(m_strCurrentUser) == 0)
{
fIsTapiAdmin = TRUE;
break;
}
}
}
if (fIsTapiAdmin)
{
fIsAdmin = TRUE;
}
COM_PROTECT_ERROR_LABEL;
return fIsAdmin;
}
/*!--------------------------------------------------------------------------
CTapiInfo::GetCurrentUser
Get the current user
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CTapiInfo::GetCurrentUser()
{
DWORD dwErr;
dwErr = ::GetCurrentUser(m_strCurrentUser);
return dwErr;
}
STDMETHODIMP
CTapiInfo::GetDeviceFlags (DWORD dwProviderID, DWORD dwPermanentID, DWORD * pdwFlags)
{
HRESULT hr;
DWORD dwDeviceID;
hr = ((GETDEVICEFLAGS) g_TapiDLL[TAPI_GET_DEVICE_FLAGS])(
m_hServer,
TRUE,
dwProviderID,
dwPermanentID,
pdwFlags,
&dwDeviceID
);
return hr;
}
/*!--------------------------------------------------------------------------
CreateTapiInfo
Helper to create the TapiInfo object.
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CreateTapiInfo(ITapiInfo ** ppTapiInfo)
{
AFX_MANAGE_STATE(AfxGetModuleState());
SPITapiInfo spTapiInfo;
ITapiInfo * pTapiInfo = NULL;
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
pTapiInfo = new CTapiInfo;
// Do this so that it will get freed on error
spTapiInfo = pTapiInfo;
*ppTapiInfo = spTapiInfo.Transfer();
}
COM_PROTECT_CATCH
return hr;
}
/*!--------------------------------------------------------------------------
UnloadTapiDll
Unloads the TAPI32.DLL file. This is necessary whenever we stop the
TAPI service because the DLL keeps and internal handle to the service
and if the service goes away and comes back then it is confused.
The only way to reset that state is to unload the DLL.
Author: EricDav
---------------------------------------------------------------------------*/
void UnloadTapiDll()
{
g_TapiDLL.Unload();
//if ( !g_TapiDLL.LoadFunctionPointers() )
// Assert("Could not reload the TAPI32 DLL!!!");
}
DWORD GetCurrentUser(CString & strAccount)
{
LPBYTE pBuf;
NET_API_STATUS status = NetWkstaUserGetInfo(NULL, 1, &pBuf);
if (status == NERR_Success)
{
strAccount.Empty();
WKSTA_USER_INFO_1 * pwkstaUserInfo = (WKSTA_USER_INFO_1 *) pBuf;
strAccount = pwkstaUserInfo->wkui1_logon_domain;
strAccount += _T("\\");
strAccount += pwkstaUserInfo->wkui1_username;
NetApiBufferFree(pBuf);
}
return (DWORD) status;
}
/*!--------------------------------------------------------------------------
IsAdmin
Connect to the remote machine as administrator with user-supplied
credentials to see if the user has admin priviledges
Returns
TRUE - the user has admin rights
FALSE - if user doesn't
Author: EricDav, KennT
---------------------------------------------------------------------------*/
DWORD IsAdmin(LPCTSTR szMachineName, LPCTSTR szAccount, LPCTSTR szPassword, BOOL * pIsAdmin)
{
CString stAccount;
CString stDomain;
CString stUser;
CString stMachineName;
DWORD dwStatus;
BOOL fIsAdmin = FALSE;
// get the current user info
if (szAccount == NULL)
{
GetCurrentUser(stAccount);
}
else
{
stAccount = szAccount;
}
// separate the user and domain
int nPos = stAccount.Find(_T("\\"));
stDomain = stAccount.Left(nPos);
stUser = stAccount.Right(stAccount.GetLength() - nPos - 1);
// build the machine string
stMachineName = szMachineName;
if ( stMachineName.Left(2) != TEXT( "\\\\" ) )
{
stMachineName = TEXT( "\\\\" ) + stMachineName;
}
// validate the domain account and get the sid
PSID connectSid;
dwStatus = ValidateDomainAccount( stMachineName, stUser, stDomain, &connectSid );
if ( dwStatus != ERROR_SUCCESS )
{
goto Error;
}
// if a password was supplied, is it correct?
if (szPassword)
{
dwStatus = ValidatePassword( stUser, stDomain, szPassword );
if ( dwStatus != SEC_E_OK )
{
switch ( dwStatus )
{
case SEC_E_LOGON_DENIED:
dwStatus = ERROR_INVALID_PASSWORD;
break;
case SEC_E_INVALID_HANDLE:
dwStatus = ERROR_INTERNAL_ERROR;
break;
default:
dwStatus = ERROR_INTERNAL_ERROR;
break;
} // end of switch
goto Error;
} // Did ValidatePassword succeed?
}
// now check the machine to see if this account has admin access
fIsAdmin = IsUserAdmin( stMachineName, connectSid );
Error:
if (pIsAdmin)
*pIsAdmin = fIsAdmin;
return dwStatus;
}
BOOL
IsUserAdmin(LPCTSTR pszMachine,
PSID AccountSid)
/*++
Routine Description:
Determine if the specified account is a member of the local admin's group
Arguments:
AccountSid - pointer to service account Sid
Return Value:
True if member
--*/
{
NET_API_STATUS status;
DWORD count;
WCHAR adminGroupName[UNLEN+1];
WCHAR pwszMachine[MAX_COMPUTERNAME_LENGTH+1];
DWORD cchName = UNLEN;
PLOCALGROUP_MEMBERS_INFO_0 grpMemberInfo;
PLOCALGROUP_MEMBERS_INFO_0 pInfo;
DWORD entriesRead;
DWORD totalEntries;
DWORD_PTR resumeHandle = NULL;
DWORD bufferSize = 128;
BOOL foundEntry = FALSE;
// get the name of the admin's group
SHTCharToUnicode(pszMachine, pwszMachine, MAX_COMPUTERNAME_LENGTH+1);
if (!LookupAliasFromRid(pwszMachine,
DOMAIN_ALIAS_RID_ADMINS,
adminGroupName,
&cchName)) {
return(FALSE);
}
// get the Sids of the members of the admin's group
do
{
status = NetLocalGroupGetMembers(pwszMachine,
adminGroupName,
0, // level 0 - just the Sid
(LPBYTE *)&grpMemberInfo,
bufferSize,
&entriesRead,
&totalEntries,
&resumeHandle);
bufferSize *= 2;
if ( status == ERROR_MORE_DATA )
{
// we got some of the data but I want it all; free this buffer and
// reset the context handle for the API
NetApiBufferFree( grpMemberInfo );
resumeHandle = NULL;
}
} while ( status == NERR_BufTooSmall || status == ERROR_MORE_DATA );
if ( status == NERR_Success )
{
// loop through the members of the admin group, comparing the supplied
// Sid to that of the group members' Sids
for ( count = 0, pInfo = grpMemberInfo; count < totalEntries; ++count, ++pInfo )
{
if ( EqualSid( AccountSid, pInfo->lgrmi0_sid ))
{
foundEntry = TRUE;
break;
}
}
NetApiBufferFree( grpMemberInfo );
}
return foundEntry;
}
//
//
//
BOOL
LookupAliasFromRid(
LPWSTR TargetComputer,
DWORD Rid,
LPWSTR Name,
PDWORD cchName
)
{
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
SID_NAME_USE snu;
PSID pSid;
WCHAR DomainName[DNLEN+1];
DWORD cchDomainName = DNLEN;
BOOL bSuccess = FALSE;
//
// Sid is the same regardless of machine, since the well-known
// BUILTIN domain is referenced.
//
if(AllocateAndInitializeSid(&sia,
2,
SECURITY_BUILTIN_DOMAIN_RID,
Rid,
0, 0, 0, 0, 0, 0,
&pSid)) {
bSuccess = LookupAccountSidW(TargetComputer,
pSid,
Name,
cchName,
DomainName,
&cchDomainName,
&snu);
FreeSid(pSid);
}
return bSuccess;
} // LookupAliasFromRid
DWORD
ValidateDomainAccount(
IN CString Machine,
IN CString UserName,
IN CString Domain,
OUT PSID * AccountSid
)
/*++
Routine Description:
For the given credentials, look up the account SID for the specified
domain. As a side effect, the Sid is stored in theData->m_Sid.
Arguments:
pointers to strings that describe the user name, domain name, and password
AccountSid - address of pointer that receives the SID for this user
Return Value:
TRUE if everything validated ok.
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwSidSize = 128;
DWORD dwDomainNameSize = 128;
LPWSTR pwszDomainName;
SID_NAME_USE SidType;
CString domainAccount;
PSID accountSid;
domainAccount = Domain + _T("\\") + UserName;
do {
// Attempt to allocate a buffer for the SID. Note that apparently in the
// absence of any error theData->m_Sid is freed only when theData goes
// out of scope.
accountSid = LocalAlloc( LMEM_FIXED, dwSidSize );
pwszDomainName = (LPWSTR) LocalAlloc( LMEM_FIXED, dwDomainNameSize * sizeof(WCHAR) );
// Was space allocated for the SID and domain name successfully?
if ( accountSid == NULL || pwszDomainName == NULL ) {
if ( accountSid != NULL ) {
LocalFree( accountSid );
}
if ( pwszDomainName != NULL ) {
LocalFree( pwszDomainName );
}
//FATALERR( IDS_ERR_NOT_ENOUGH_MEMORY, GetLastError() ); // no return
break;
}
// Attempt to Retrieve the SID and domain name. If LookupAccountName failes
// because of insufficient buffer size(s) dwSidSize and dwDomainNameSize
// will be set correctly for the next attempt.
if ( !LookupAccountName( Machine,
domainAccount,
accountSid,
&dwSidSize,
pwszDomainName,
&dwDomainNameSize,
&SidType ))
{
// free the Sid buffer and find out why we failed
LocalFree( accountSid );
dwStatus = GetLastError();
}
// domain name isn't needed at any time
LocalFree( pwszDomainName );
pwszDomainName = NULL;
} while ( dwStatus == ERROR_INSUFFICIENT_BUFFER );
if ( dwStatus == ERROR_SUCCESS ) {
*AccountSid = accountSid;
}
return dwStatus;
} // ValidateDomainAccount
NTSTATUS
ValidatePassword(
IN LPCWSTR UserName,
IN LPCWSTR Domain,
IN LPCWSTR Password
)
/*++
Routine Description:
Uses SSPI to validate the specified password
Arguments:
UserName - Supplies the user name
Domain - Supplies the user's domain
Password - Supplies the password
Return Value:
TRUE if the password is valid.
FALSE otherwise.
--*/
{
SECURITY_STATUS SecStatus;
SECURITY_STATUS AcceptStatus;
SECURITY_STATUS InitStatus;
CredHandle ClientCredHandle;
CredHandle ServerCredHandle;
BOOL ClientCredAllocated = FALSE;
BOOL ServerCredAllocated = FALSE;
CtxtHandle ClientContextHandle;
CtxtHandle ServerContextHandle;
TimeStamp Lifetime;
ULONG ContextAttributes;
PSecPkgInfo PackageInfo = NULL;
ULONG ClientFlags;
ULONG ServerFlags;
SEC_WINNT_AUTH_IDENTITY_W AuthIdentity;
SecBufferDesc NegotiateDesc;
SecBuffer NegotiateBuffer;
SecBufferDesc ChallengeDesc;
SecBuffer ChallengeBuffer;
SecBufferDesc AuthenticateDesc;
SecBuffer AuthenticateBuffer;
SecBufferDesc *pChallengeDesc = NULL;
CtxtHandle * pClientContextHandle = NULL;
CtxtHandle * pServerContextHandle = NULL;
AuthIdentity.User = (LPWSTR)UserName;
AuthIdentity.UserLength = lstrlenW(UserName);
AuthIdentity.Domain = (LPWSTR)Domain;
AuthIdentity.DomainLength = lstrlenW(Domain);
AuthIdentity.Password = (LPWSTR)Password;
AuthIdentity.PasswordLength = lstrlenW(Password);
AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
NegotiateBuffer.pvBuffer = NULL;
ChallengeBuffer.pvBuffer = NULL;
AuthenticateBuffer.pvBuffer = NULL;
//
// Get info about the security packages.
//
SecStatus = QuerySecurityPackageInfo( DEFAULT_SECURITY_PKG, &PackageInfo );
if ( SecStatus != STATUS_SUCCESS ) {
goto error_exit;
}
//
// Acquire a credential handle for the server side
//
SecStatus = AcquireCredentialsHandle(
NULL,
DEFAULT_SECURITY_PKG,
SECPKG_CRED_INBOUND,
NULL,
&AuthIdentity,
NULL,
NULL,
&ServerCredHandle,
&Lifetime );
if ( SecStatus != STATUS_SUCCESS ) {
goto error_exit;
}
ServerCredAllocated = TRUE;
//
// Acquire a credential handle for the client side
//
SecStatus = AcquireCredentialsHandle(
NULL, // New principal
DEFAULT_SECURITY_PKG,
SECPKG_CRED_OUTBOUND,
NULL,
&AuthIdentity,
NULL,
NULL,
&ClientCredHandle,
&Lifetime );
if ( SecStatus != STATUS_SUCCESS ) {
goto error_exit;
}
ClientCredAllocated = TRUE;
NegotiateBuffer.pvBuffer = LocalAlloc( 0, PackageInfo->cbMaxToken ); // [CHKCHK] check or allocate this earlier //
if ( NegotiateBuffer.pvBuffer == NULL ) {
SecStatus = SEC_E_INSUFFICIENT_MEMORY;
goto error_exit;
}
ChallengeBuffer.pvBuffer = LocalAlloc( 0, PackageInfo->cbMaxToken ); // [CHKCHK]
if ( ChallengeBuffer.pvBuffer == NULL ) {
SecStatus = SEC_E_INSUFFICIENT_MEMORY;
goto error_exit;
}
do {
//
// Get the NegotiateMessage (ClientSide)
//
NegotiateDesc.ulVersion = 0;
NegotiateDesc.cBuffers = 1;
NegotiateDesc.pBuffers = &NegotiateBuffer;
NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
ClientFlags = 0; // ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT; // [CHKCHK] 0
InitStatus = InitializeSecurityContext(
&ClientCredHandle,
pClientContextHandle, // (NULL on the first pass, partially formed ctx on the next)
NULL, // [CHKCHK] szTargetName
ClientFlags,
0, // Reserved 1
SECURITY_NATIVE_DREP,
pChallengeDesc, // (NULL on the first pass)
0, // Reserved 2
&ClientContextHandle,
&NegotiateDesc,
&ContextAttributes,
&Lifetime );
if ( !NT_SUCCESS(InitStatus) ) {
SecStatus = InitStatus;
goto error_exit;
}
// ValidateBuffer( &NegotiateDesc ) // [CHKCHK]
pClientContextHandle = &ClientContextHandle;
//
// Get the ChallengeMessage (ServerSide)
//
NegotiateBuffer.BufferType |= SECBUFFER_READONLY;
ChallengeDesc.ulVersion = 0;
ChallengeDesc.cBuffers = 1;
ChallengeDesc.pBuffers = &ChallengeBuffer;
ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
ServerFlags = ASC_REQ_ALLOW_NON_USER_LOGONS; // ASC_REQ_EXTENDED_ERROR; [CHKCHK]
AcceptStatus = AcceptSecurityContext(
&ServerCredHandle,
pServerContextHandle, // (NULL on the first pass)
&NegotiateDesc,
ServerFlags,
SECURITY_NATIVE_DREP,
&ServerContextHandle,
&ChallengeDesc,
&ContextAttributes,
&Lifetime );
if ( !NT_SUCCESS(AcceptStatus) ) {
SecStatus = AcceptStatus;
goto error_exit;
}
// ValidateBuffer( &NegotiateDesc ) // [CHKCHK]
pChallengeDesc = &ChallengeDesc;
pServerContextHandle = &ServerContextHandle;
} while ( AcceptStatus == SEC_I_CONTINUE_NEEDED ); // || InitStatus == SEC_I_CONTINUE_NEEDED );
error_exit:
if (ServerCredAllocated) {
FreeCredentialsHandle( &ServerCredHandle );
}
if (ClientCredAllocated) {
FreeCredentialsHandle( &ClientCredHandle );
}
//
// Final Cleanup
//
if ( NegotiateBuffer.pvBuffer != NULL ) {
(VOID) LocalFree( NegotiateBuffer.pvBuffer );
}
if ( ChallengeBuffer.pvBuffer != NULL ) {
(VOID) LocalFree( ChallengeBuffer.pvBuffer );
}
if ( AuthenticateBuffer.pvBuffer != NULL ) {
(VOID) LocalFree( AuthenticateBuffer.pvBuffer );
}
return(SecStatus);
} // ValidatePassword