Leaked source code of windows server 2003
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

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. RemoteConnectionData.cpp
  5. Abstract:
  6. SAFRemoteConnectionData Object
  7. Revision History:
  8. KalyaninN created 09/29/'00
  9. ********************************************************************/
  10. // RemoteConnectionData.cpp : Implementation of CSAFRemoteConnectionData
  11. #include "stdafx.h"
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CSAFRemoteConnectionData
  14. /////////////////////////////////////////////////////////////////////////////
  15. // construction / destruction
  16. // **************************************************************************
  17. CSAFRemoteConnectionData::CSAFRemoteConnectionData()
  18. {
  19. m_NumSessions = 0; // long m_NumSessions;
  20. m_SessionInfoTable = NULL; // SSessionInfoItem* m_SessionInfoTable;
  21. // CComBSTR m_bstrServerName;
  22. }
  23. // **************************************************************************
  24. CSAFRemoteConnectionData::~CSAFRemoteConnectionData()
  25. {
  26. Cleanup();
  27. }
  28. // **************************************************************************
  29. // **************************************************************************
  30. void CSAFRemoteConnectionData::Cleanup()
  31. {
  32. delete [] m_SessionInfoTable; m_SessionInfoTable = NULL;
  33. }
  34. HRESULT CSAFRemoteConnectionData::InitUserSessionsInfo( /*[in]*/ BSTR bstrServerName )
  35. {
  36. __HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::InitUserSessionsInfo" );
  37. HRESULT hr;
  38. MPC::Impersonation imp;
  39. CComPtr<IPCHService> svc;
  40. COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
  41. MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
  42. CComPtr<IPCHCollection> pColl;
  43. CComQIPtr<ISAFSession> pSession;
  44. SSessionInfoItem* ptr;
  45. int i;
  46. m_bstrServerName = bstrServerName;
  47. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize ());
  48. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
  49. // Connect to the Server represented by bstrServerName.
  50. si.pwszName = (LPWSTR)m_bstrServerName;
  51. qi.pIID = &IID_IPCHService;
  52. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
  53. __MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
  54. svc.Attach( (IPCHService*)qi.pItf );
  55. __MPC_EXIT_IF_METHOD_FAILS(hr, svc->RemoteUserSessionInfo( &pColl ));
  56. //Transfer the contents of the collection to the internal member structure.
  57. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->get_Count( &m_NumSessions));
  58. // Allocate Memory for the Session Info Table.
  59. __MPC_EXIT_IF_ALLOC_FAILS(hr, m_SessionInfoTable, new SSessionInfoItem[m_NumSessions]);
  60. for(i=0, ptr=m_SessionInfoTable; i<(int)m_NumSessions; i++, ptr++)
  61. {
  62. CComVariant cvVarSession;
  63. //
  64. // Get the item
  65. //
  66. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->get_Item( i+1, &cvVarSession ));
  67. if(cvVarSession.vt != VT_DISPATCH) continue;
  68. pSession = cvVarSession.pdispVal;
  69. //
  70. // Read the data from the Session Item Object.
  71. //
  72. __MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_SessionID ( &(ptr->dwSessionID ) ));
  73. __MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_SessionState( &(ptr->wtsConnectState) ));
  74. __MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_UserName ( &(ptr->bstrUser ) ));
  75. __MPC_EXIT_IF_METHOD_FAILS(hr, pSession->get_DomainName ( &(ptr->bstrDomain ) ));
  76. }
  77. hr = S_OK;
  78. __HCP_FUNC_CLEANUP;
  79. __HCP_FUNC_EXIT(hr);
  80. }
  81. HRESULT CSAFRemoteConnectionData::Populate( /*[in]*/ CPCHCollection* pColl )
  82. {
  83. __HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::Populate" );
  84. static const DWORD c_dwTSSessionID = 65536; // This is the session that TS uses to Listen.
  85. HRESULT hr;
  86. SessionStateEnum wtsConnectState;
  87. WINSTATIONINFORMATIONW WSInfo;
  88. PWTS_SESSION_INFOW pSessionInfo = NULL;
  89. PWTS_SESSION_INFOW ptr;
  90. DWORD dwSessions;
  91. DWORD dwPos;
  92. BOOL fSucc;
  93. BOOL fIsHelpAssistant;
  94. __MPC_PARAMCHECK_BEGIN(hr)
  95. __MPC_PARAMCHECK_NOTNULL(pColl);
  96. __MPC_PARAMCHECK_END();
  97. //
  98. // Start with WTSEnumerateSessions,
  99. // get all sessions whether active or not,
  100. // get sessions for all logonIDs,
  101. // then use WinStationQueryInformation to get the logged on users username, domainname
  102. //
  103. if(!::WTSEnumerateSessionsW( WTS_CURRENT_SERVER_HANDLE, /*dwReserved*/0, /*dwVersion*/1, &pSessionInfo, &dwSessions ) || !pSessionInfo)
  104. {
  105. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError());
  106. }
  107. for(dwPos=0, ptr=pSessionInfo; dwPos < dwSessions; dwPos++, ptr++)
  108. {
  109. DWORD dwCurrentSessionID = ptr->SessionId;
  110. DWORD dwRetSize;
  111. ::ZeroMemory( &WSInfo, sizeof(WSInfo) );
  112. // Do not include the session that TS uses to listen, with SessionID 65536 and SessionState pchListen
  113. if(dwCurrentSessionID == c_dwTSSessionID) continue;
  114. // Do not include the disconnected sessions.
  115. if(ptr->State == WTSDisconnected) continue;
  116. // Do not include the idle sessions. Fix for bug 363824.
  117. if(ptr->State == WTSIdle) continue;
  118. // Exclude the Help Assistant account. This can get included only when there are two instances of Unsolicited RA.
  119. // When the first instance, shadows the session and the second instance enumerates the sessions, "Help Assistant Session"
  120. // is included in the second.
  121. fIsHelpAssistant = WinStationIsHelpAssistantSession(SERVERNAME_CURRENT, dwCurrentSessionID);
  122. if(fIsHelpAssistant)
  123. continue;
  124. fSucc = WinStationQueryInformationW( SERVERNAME_CURRENT, dwCurrentSessionID, WinStationInformation, &WSInfo, sizeof(WSInfo), &dwRetSize );
  125. if(!fSucc)
  126. continue;
  127. // Bug 454497 - Do not include blank user names.
  128. if((StrCmpI(WSInfo.UserName, L"") == 0))
  129. continue;
  130. // Fill up the SessionInfoTable with details.
  131. switch(ptr->State)
  132. {
  133. case WTSActive : wtsConnectState = pchActive; break;
  134. case WTSConnected : wtsConnectState = pchConnected; break;
  135. case WTSConnectQuery: wtsConnectState = pchConnectQuery; break;
  136. case WTSShadow : wtsConnectState = pchShadow; break;
  137. case WTSListen : wtsConnectState = pchListen; break;
  138. case WTSReset : wtsConnectState = pchReset; break;
  139. case WTSDown : wtsConnectState = pchDown; break;
  140. case WTSInit : wtsConnectState = pchInit; break;
  141. default : wtsConnectState = pchStateInvalid; break;
  142. }
  143. {
  144. CComPtr<CSAFSession> pItem;
  145. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
  146. pItem->put_SessionID ( dwCurrentSessionID );
  147. pItem->put_UserName ( WSInfo.UserName );
  148. pItem->put_DomainName ( WSInfo.Domain );
  149. pItem->put_SessionState( wtsConnectState );
  150. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
  151. }
  152. }
  153. hr = S_OK;
  154. __HCP_FUNC_CLEANUP;
  155. /* free the memory we asked for */
  156. if(pSessionInfo) ::WTSFreeMemory( pSessionInfo );
  157. __HCP_FUNC_EXIT(hr);
  158. }
  159. /////////////////////////////////////////////////////////////////////////////
  160. // CSAFRemoteConnectionData Methods
  161. STDMETHODIMP CSAFRemoteConnectionData::Users( /*[out,retval]*/ IPCHCollection* *ppUsers )
  162. {
  163. __HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::Users" );
  164. HRESULT hr;
  165. CComPtr<CPCHCollection> pColl;
  166. BSTR bstrPrevUser = NULL;
  167. BSTR bstrPrevDomain = NULL;
  168. SSessionInfoItem* ptr;
  169. int i;
  170. __MPC_PARAMCHECK_BEGIN(hr)
  171. __MPC_PARAMCHECK_POINTER_AND_SET(ppUsers,NULL);
  172. __MPC_PARAMCHECK_END();
  173. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
  174. // Each user can be logged to multiple sessions,
  175. // so there will be repeated usernames with different session IDs
  176. // in the Session Table. While returning the users in the collection,
  177. // remove the duplicate username entries.
  178. for(i=0, ptr = m_SessionInfoTable; i<(int)m_NumSessions; i++, ptr++)
  179. {
  180. BSTR bstrUser = ptr->bstrUser;
  181. BSTR bstrDomain = ptr->bstrDomain;
  182. /*if(MPC::StrICmp( ptr->bstrUser , bstrPrevUser ) != 0 &&
  183. MPC::StrICmp( ptr->bstrDomain, bstrPrevDomain ) != 0 )
  184. */
  185. if(MPC::StrICmp( ptr->bstrDomain, bstrPrevDomain )== 0)
  186. {
  187. if(MPC::StrICmp( ptr->bstrUser, bstrPrevUser )== 0)
  188. {
  189. // Do Not Include this session.
  190. }
  191. else
  192. {
  193. CComPtr<CSAFUser> pItem;
  194. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
  195. __MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_UserName ( bstrUser ));
  196. __MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_DomainName( bstrDomain ));
  197. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
  198. bstrPrevUser = bstrUser;
  199. bstrPrevDomain = bstrDomain;
  200. }
  201. }
  202. else
  203. {
  204. CComPtr<CSAFUser> pItem;
  205. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
  206. __MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_UserName ( bstrUser ));
  207. __MPC_EXIT_IF_METHOD_FAILS(hr, pItem->put_DomainName( bstrDomain ));
  208. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
  209. bstrPrevUser = bstrUser;
  210. bstrPrevDomain = bstrDomain;
  211. }
  212. }
  213. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppUsers ));
  214. hr = S_OK;
  215. __HCP_FUNC_CLEANUP;
  216. __HCP_FUNC_EXIT(hr);
  217. }
  218. STDMETHODIMP CSAFRemoteConnectionData::Sessions( /*[in,optional]*/ VARIANT vUser ,
  219. /*[in,optional]*/ VARIANT vDomain ,
  220. /*[out,retval ]*/ IPCHCollection* *ppSessions )
  221. {
  222. __HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::Sessions" );
  223. HRESULT hr;
  224. CComPtr<CPCHCollection> pColl;
  225. SSessionInfoItem* ptr;
  226. int i;
  227. __MPC_PARAMCHECK_BEGIN(hr)
  228. __MPC_PARAMCHECK_POINTER_AND_SET(ppSessions,NULL);
  229. __MPC_PARAMCHECK_END();
  230. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
  231. for(i=0, ptr = m_SessionInfoTable; i<(int)m_NumSessions; i++, ptr++)
  232. {
  233. if((vUser .vt != VT_BSTR || MPC::StrICmp( vUser .bstrVal, ptr->bstrUser ) != 0) &&
  234. (vDomain.vt != VT_BSTR || MPC::StrICmp( vDomain.bstrVal, ptr->bstrDomain ) != 0) )
  235. {
  236. CComPtr<CSAFSession> pItem;
  237. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pItem ));
  238. pItem->put_UserName ( ptr->bstrUser );
  239. pItem->put_DomainName ( ptr->bstrDomain );
  240. pItem->put_SessionID ( ptr->dwSessionID );
  241. pItem->put_SessionState( ptr->wtsConnectState );
  242. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pItem ));
  243. }
  244. }
  245. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppSessions ));
  246. hr = S_OK;
  247. __HCP_FUNC_CLEANUP;
  248. __HCP_FUNC_EXIT(hr);
  249. }
  250. STDMETHODIMP CSAFRemoteConnectionData::ConnectionParms( /*[in ]*/ BSTR bstrServerName ,
  251. /*[in ]*/ BSTR bstrUserName ,
  252. /*[in ]*/ BSTR bstrDomainName ,
  253. /*[in ]*/ long lSessionID ,
  254. /*[in ]*/ BSTR bstrUserHelpBlob ,
  255. /*[out]*/ BSTR *bstrConnectionString )
  256. {
  257. __HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::ConnectionParms" );
  258. HRESULT hr;
  259. MPC::Impersonation imp;
  260. CComPtr<IPCHService> svc;
  261. COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
  262. MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
  263. __MPC_PARAMCHECK_BEGIN(hr)
  264. __MPC_PARAMCHECK_POINTER_AND_SET(bstrConnectionString,NULL);
  265. __MPC_PARAMCHECK_END();
  266. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize ());
  267. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
  268. // Connect to the Server represented by bstrServerName.
  269. si.pwszName = (LPWSTR)bstrServerName;
  270. qi.pIID = &IID_IPCHService;
  271. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
  272. __MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
  273. svc.Attach( (IPCHService*)qi.pItf );
  274. // Invoke the method on the IPCHService that invokes the Salem API on the Remote Server.
  275. __MPC_EXIT_IF_METHOD_FAILS(hr, svc->RemoteConnectionParms( bstrUserName, bstrDomainName, lSessionID, bstrUserHelpBlob, bstrConnectionString ));
  276. hr = S_OK;
  277. __HCP_FUNC_CLEANUP;
  278. __HCP_FUNC_EXIT(hr);
  279. }
  280. // Bug 456403
  281. STDMETHODIMP CSAFRemoteConnectionData::ModemConnected( /*[in ]*/ BSTR bstrServerName ,
  282. /*[out]*/ VARIANT_BOOL *fModemConnected )
  283. {
  284. __HCP_FUNC_ENTRY( "CSAFRemoteConnectionData::ModemConnected" );
  285. HRESULT hr;
  286. MPC::Impersonation imp;
  287. CComPtr<IPCHService> svc;
  288. COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
  289. MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
  290. CComPtr<IDispatch> pDisp;
  291. DISPID dispid;
  292. LPWSTR szMember = L"RemoteModemConnected";
  293. VARIANT varResult;
  294. DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  295. __MPC_PARAMCHECK_BEGIN(hr)
  296. __MPC_PARAMCHECK_POINTER_AND_SET(fModemConnected,VARIANT_FALSE);
  297. __MPC_PARAMCHECK_END();
  298. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize ());
  299. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
  300. // Connect to the Server represented by bstrServerName.
  301. si.pwszName = (LPWSTR)bstrServerName;
  302. qi.pIID = &IID_IPCHService;
  303. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
  304. __MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
  305. svc.Attach( (IPCHService*)qi.pItf );
  306. // Invoke the method on the server(IPCHService interface) that detects for a Modem.
  307. // Since the original version of RemoteConnectionData object does not have this method,
  308. // we need to check if the object supports this method or not before calling this
  309. // method on the server end i.e. check the IPCHService interface by calling the invoke method.
  310. // This can be done via IDispatch.
  311. // Get the IDispatch pointer of the IPCHService interface
  312. __MPC_EXIT_IF_METHOD_FAILS(hr, svc->QueryInterface(IID_IDispatch, (void **)&pDisp));
  313. // pDisp is an IDispatch pointer to the IPCHService interface
  314. // Get the ID of the ModemConnected property.
  315. __MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->GetIDsOfNames(IID_NULL, &szMember, 1,LOCALE_USER_DEFAULT, &dispid));
  316. __MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  317. &dispparamsNoArgs, &varResult, NULL, NULL));
  318. // Assign the value from varResult to fModemConnected
  319. *fModemConnected = varResult.boolVal;
  320. hr = S_OK;
  321. __HCP_FUNC_CLEANUP;
  322. __HCP_FUNC_EXIT(hr);
  323. }