You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
454 lines
16 KiB
454 lines
16 KiB
/********************************************************************
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
RemoteConnectionData.cpp
|
|
|
|
Abstract:
|
|
SAFRemoteConnectionData Object
|
|
|
|
Revision History:
|
|
KalyaninN created 09/29/'00
|
|
|
|
********************************************************************/
|
|
|
|
// RemoteConnectionData.cpp : Implementation of CSAFRemoteConnectionData
|
|
|
|
#include "stdafx.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSAFRemoteConnectionData
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// construction / destruction
|
|
|
|
// **************************************************************************
|
|
CSAFRemoteConnectionData::CSAFRemoteConnectionData()
|
|
{
|
|
m_NumSessions = 0; // long m_NumSessions;
|
|
m_SessionInfoTable = NULL; // SSessionInfoItem* m_SessionInfoTable;
|
|
// CComBSTR m_bstrServerName;
|
|
}
|
|
|
|
// **************************************************************************
|
|
CSAFRemoteConnectionData::~CSAFRemoteConnectionData()
|
|
{
|
|
Cleanup();
|
|
}
|
|
|
|
// **************************************************************************
|
|
|
|
// **************************************************************************
|
|
void CSAFRemoteConnectionData::Cleanup()
|
|
{
|
|
delete [] m_SessionInfoTable; m_SessionInfoTable = NULL;
|
|
}
|
|
|
|
HRESULT CSAFRemoteConnectionData::InitUserSessionsInfo( /*[in]*/ BSTR bstrServerName )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::InitUserSessionsInfo" );
|
|
|
|
HRESULT hr;
|
|
MPC::Impersonation imp;
|
|
CComPtr<IPCHService> svc;
|
|
COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
|
|
MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
|
|
CComPtr<IPCHCollection> pColl;
|
|
CComQIPtr<ISAFSession> pSession;
|
|
SSessionInfoItem* ptr;
|
|
int i;
|
|
|
|
|
|
m_bstrServerName = bstrServerName;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize ());
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
|
|
|
|
// Connect to the Server represented by bstrServerName.
|
|
si.pwszName = (LPWSTR)m_bstrServerName;
|
|
qi.pIID = &IID_IPCHService;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
|
|
svc.Attach( (IPCHService*)qi.pItf );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, svc->RemoteUserSessionInfo( &pColl ));
|
|
|
|
|
|
//Transfer the contents of the collection to the internal member structure.
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->get_Count( &m_NumSessions));
|
|
|
|
// Allocate Memory for the Session Info Table.
|
|
__MPC_EXIT_IF_ALLOC_FAILS(hr, m_SessionInfoTable, new SSessionInfoItem[m_NumSessions]);
|
|
|
|
for(i=0, ptr=m_SessionInfoTable; i<(int)m_NumSessions; i++, ptr++)
|
|
{
|
|
CComVariant cvVarSession;
|
|
|
|
//
|
|
// Get the item
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->get_Item( i+1, &cvVarSession ));
|
|
if(cvVarSession.vt != VT_DISPATCH) continue;
|
|
|
|
pSession = cvVarSession.pdispVal;
|
|
|
|
//
|
|
// Read the data from the Session Item Object.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_SessionID ( &(ptr->dwSessionID ) ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_SessionState( &(ptr->wtsConnectState) ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_UserName ( &(ptr->bstrUser ) ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_DomainName ( &(ptr->bstrDomain ) ));
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CSAFRemoteConnectionData::Populate( /*[in]*/ CPCHCollection* pColl )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::Populate" );
|
|
|
|
static const DWORD c_dwTSSessionID = 65536; // This is the session that TS uses to Listen.
|
|
|
|
HRESULT hr;
|
|
SessionStateEnum wtsConnectState;
|
|
WINSTATIONINFORMATIONW WSInfo;
|
|
PWTS_SESSION_INFOW pSessionInfo = NULL;
|
|
PWTS_SESSION_INFOW ptr;
|
|
DWORD dwSessions;
|
|
DWORD dwPos;
|
|
BOOL fSucc;
|
|
BOOL fIsHelpAssistant;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_NOTNULL(pColl);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
|
|
//
|
|
// Start with WTSEnumerateSessions,
|
|
// get all sessions whether active or not,
|
|
// get sessions for all logonIDs,
|
|
// then use WinStationQueryInformation to get the logged on users username, domainname
|
|
//
|
|
if(!::WTSEnumerateSessionsW( WTS_CURRENT_SERVER_HANDLE, /*dwReserved*/0, /*dwVersion*/1, &pSessionInfo, &dwSessions ) || !pSessionInfo)
|
|
{
|
|
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError());
|
|
}
|
|
|
|
for(dwPos=0, ptr=pSessionInfo; dwPos < dwSessions; dwPos++, ptr++)
|
|
{
|
|
DWORD dwCurrentSessionID = ptr->SessionId;
|
|
DWORD dwRetSize;
|
|
|
|
::ZeroMemory( &WSInfo, sizeof(WSInfo) );
|
|
|
|
// Do not include the session that TS uses to listen, with SessionID 65536 and SessionState pchListen
|
|
if(dwCurrentSessionID == c_dwTSSessionID) continue;
|
|
|
|
// Do not include the disconnected sessions.
|
|
if(ptr->State == WTSDisconnected) continue;
|
|
|
|
// Do not include the idle sessions. Fix for bug 363824.
|
|
if(ptr->State == WTSIdle) continue;
|
|
|
|
// Exclude the Help Assistant account. This can get included only when there are two instances of Unsolicited RA.
|
|
// When the first instance, shadows the session and the second instance enumerates the sessions, "Help Assistant Session"
|
|
// is included in the second.
|
|
|
|
fIsHelpAssistant = WinStationIsHelpAssistantSession(SERVERNAME_CURRENT, dwCurrentSessionID);
|
|
|
|
if(fIsHelpAssistant)
|
|
continue;
|
|
|
|
fSucc = WinStationQueryInformationW( SERVERNAME_CURRENT, dwCurrentSessionID, WinStationInformation, &WSInfo, sizeof(WSInfo), &dwRetSize );
|
|
|
|
if(!fSucc)
|
|
continue;
|
|
|
|
// Bug 454497 - Do not include blank user names.
|
|
if((StrCmpI(WSInfo.UserName, L"") == 0))
|
|
continue;
|
|
|
|
// Fill up the SessionInfoTable with details.
|
|
switch(ptr->State)
|
|
{
|
|
case WTSActive : wtsConnectState = pchActive; break;
|
|
case WTSConnected : wtsConnectState = pchConnected; break;
|
|
case WTSConnectQuery: wtsConnectState = pchConnectQuery; break;
|
|
case WTSShadow : wtsConnectState = pchShadow; break;
|
|
case WTSListen : wtsConnectState = pchListen; break;
|
|
case WTSReset : wtsConnectState = pchReset; break;
|
|
case WTSDown : wtsConnectState = pchDown; break;
|
|
case WTSInit : wtsConnectState = pchInit; break;
|
|
default : wtsConnectState = pchStateInvalid; break;
|
|
}
|
|
|
|
{
|
|
CComPtr<CSAFSession> pItem;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
|
|
|
|
pItem->put_SessionID ( dwCurrentSessionID );
|
|
pItem->put_UserName ( WSInfo.UserName );
|
|
pItem->put_DomainName ( WSInfo.Domain );
|
|
pItem->put_SessionState( wtsConnectState );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
/* free the memory we asked for */
|
|
if(pSessionInfo) ::WTSFreeMemory( pSessionInfo );
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSAFRemoteConnectionData Methods
|
|
|
|
STDMETHODIMP CSAFRemoteConnectionData::Users( /*[out,retval]*/ IPCHCollection* *ppUsers )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::Users" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHCollection> pColl;
|
|
BSTR bstrPrevUser = NULL;
|
|
BSTR bstrPrevDomain = NULL;
|
|
SSessionInfoItem* ptr;
|
|
int i;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(ppUsers,NULL);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
|
|
|
|
// Each user can be logged to multiple sessions,
|
|
// so there will be repeated usernames with different session IDs
|
|
// in the Session Table. While returning the users in the collection,
|
|
// remove the duplicate username entries.
|
|
for(i=0, ptr = m_SessionInfoTable; i<(int)m_NumSessions; i++, ptr++)
|
|
{
|
|
BSTR bstrUser = ptr->bstrUser;
|
|
BSTR bstrDomain = ptr->bstrDomain;
|
|
|
|
/*if(MPC::StrICmp( ptr->bstrUser , bstrPrevUser ) != 0 &&
|
|
MPC::StrICmp( ptr->bstrDomain, bstrPrevDomain ) != 0 )
|
|
*/
|
|
if(MPC::StrICmp( ptr->bstrDomain, bstrPrevDomain )== 0)
|
|
{
|
|
if(MPC::StrICmp( ptr->bstrUser, bstrPrevUser )== 0)
|
|
{
|
|
// Do Not Include this session.
|
|
}
|
|
else
|
|
{
|
|
CComPtr<CSAFUser> pItem;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_UserName ( bstrUser ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_DomainName( bstrDomain ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
|
|
|
|
bstrPrevUser = bstrUser;
|
|
bstrPrevDomain = bstrDomain;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
CComPtr<CSAFUser> pItem;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_UserName ( bstrUser ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_DomainName( bstrDomain ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
|
|
|
|
bstrPrevUser = bstrUser;
|
|
bstrPrevDomain = bstrDomain;
|
|
}
|
|
}
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppUsers ));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP CSAFRemoteConnectionData::Sessions( /*[in,optional]*/ VARIANT vUser ,
|
|
/*[in,optional]*/ VARIANT vDomain ,
|
|
/*[out,retval ]*/ IPCHCollection* *ppSessions )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::Sessions" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHCollection> pColl;
|
|
SSessionInfoItem* ptr;
|
|
int i;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(ppSessions,NULL);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
|
|
|
|
for(i=0, ptr = m_SessionInfoTable; i<(int)m_NumSessions; i++, ptr++)
|
|
{
|
|
if((vUser .vt != VT_BSTR || MPC::StrICmp( vUser .bstrVal, ptr->bstrUser ) != 0) &&
|
|
(vDomain.vt != VT_BSTR || MPC::StrICmp( vDomain.bstrVal, ptr->bstrDomain ) != 0) )
|
|
{
|
|
CComPtr<CSAFSession> pItem;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
|
|
|
|
pItem->put_UserName ( ptr->bstrUser );
|
|
pItem->put_DomainName ( ptr->bstrDomain );
|
|
pItem->put_SessionID ( ptr->dwSessionID );
|
|
pItem->put_SessionState( ptr->wtsConnectState );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
|
|
}
|
|
}
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppSessions ));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP CSAFRemoteConnectionData::ConnectionParms( /*[in ]*/ BSTR bstrServerName ,
|
|
/*[in ]*/ BSTR bstrUserName ,
|
|
/*[in ]*/ BSTR bstrDomainName ,
|
|
/*[in ]*/ long lSessionID ,
|
|
/*[in ]*/ BSTR bstrUserHelpBlob ,
|
|
/*[out]*/ BSTR *bstrConnectionString )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::ConnectionParms" );
|
|
|
|
HRESULT hr;
|
|
MPC::Impersonation imp;
|
|
CComPtr<IPCHService> svc;
|
|
COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
|
|
MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(bstrConnectionString,NULL);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize ());
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
|
|
|
|
// Connect to the Server represented by bstrServerName.
|
|
si.pwszName = (LPWSTR)bstrServerName;
|
|
qi.pIID = &IID_IPCHService;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
|
|
svc.Attach( (IPCHService*)qi.pItf );
|
|
|
|
// Invoke the method on the IPCHService that invokes the Salem API on the Remote Server.
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, svc->RemoteConnectionParms( bstrUserName, bstrDomainName, lSessionID, bstrUserHelpBlob, bstrConnectionString ));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
// Bug 456403
|
|
|
|
STDMETHODIMP CSAFRemoteConnectionData::ModemConnected( /*[in ]*/ BSTR bstrServerName ,
|
|
/*[out]*/ VARIANT_BOOL *fModemConnected )
|
|
{
|
|
|
|
__HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::ModemConnected" );
|
|
|
|
HRESULT hr;
|
|
MPC::Impersonation imp;
|
|
CComPtr<IPCHService> svc;
|
|
COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
|
|
MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
|
|
|
|
CComPtr<IDispatch> pDisp;
|
|
DISPID dispid;
|
|
LPWSTR szMember = L"RemoteModemConnected";
|
|
|
|
VARIANT varResult;
|
|
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(fModemConnected,VARIANT_FALSE);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize ());
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
|
|
|
|
// Connect to the Server represented by bstrServerName.
|
|
si.pwszName = (LPWSTR)bstrServerName;
|
|
qi.pIID = &IID_IPCHService;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
|
|
svc.Attach( (IPCHService*)qi.pItf );
|
|
|
|
|
|
// Invoke the method on the server(IPCHService interface) that detects for a Modem.
|
|
// Since the original version of RemoteConnectionData object does not have this method,
|
|
// we need to check if the object supports this method or not before calling this
|
|
// method on the server end i.e. check the IPCHService interface by calling the invoke method.
|
|
|
|
// This can be done via IDispatch.
|
|
|
|
// Get the IDispatch pointer of the IPCHService interface
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, svc->QueryInterface(IID_IDispatch, (void **)&pDisp));
|
|
|
|
|
|
// pDisp is an IDispatch pointer to the IPCHService interface
|
|
// Get the ID of the ModemConnected property.
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->GetIDsOfNames(IID_NULL, &szMember, 1,LOCALE_USER_DEFAULT, &dispid));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
|
|
&dispparamsNoArgs, &varResult, NULL, NULL));
|
|
|
|
// Assign the value from varResult to fModemConnected
|
|
*fModemConnected = varResult.boolVal;
|
|
|
|
hr = S_OK;
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
|
|
}
|