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