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.

528 lines
11 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. TSRDPRemoteDesktopSession
  5. Abstract:
  6. This is the TS/RDP implementation of the Remote Desktop Session class.
  7. The Remote Desktop Session class defines functions that define
  8. pluggable C++ interface for remote desktop access, by abstracting
  9. the implementation specific details of remote desktop access for the
  10. server-side into the following C++ methods:
  11. Author:
  12. Tad Brockway 02/00
  13. Revision History:
  14. --*/
  15. //#include <RemoteDesktop.h>
  16. #include "stdafx.h"
  17. #ifdef TRC_FILE
  18. #undef TRC_FILE
  19. #endif
  20. #define TRC_FILE "_tsrdss"
  21. #include <RDSHost.h>
  22. #include "TSRDPRemoteDesktopSession.h"
  23. #include "TSRDPServerDataChannelMgr.h"
  24. #include <RemoteDesktopChannels.h>
  25. #include "RemoteDesktopUtils.h"
  26. #include <Sddl.h>
  27. #include <windows.h>
  28. ///////////////////////////////////////////////////////
  29. //
  30. // CTSRDPRemoteDesktopSession Methods
  31. //
  32. CTSRDPRemoteDesktopSession::CTSRDPRemoteDesktopSession() :
  33. m_ChannelMgr(NULL)
  34. /*++
  35. Routine Description:
  36. Constructor
  37. Arguments:
  38. Return Value:
  39. None.
  40. --*/
  41. {
  42. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::CTSRDPRemoteDesktopSession");
  43. DC_END_FN();
  44. }
  45. CTSRDPRemoteDesktopSession::~CTSRDPRemoteDesktopSession()
  46. /*++
  47. Routine Description:
  48. Destructor
  49. Arguments:
  50. Return Value:
  51. None.
  52. --*/
  53. {
  54. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::~CTSRDPRemoteDesktopSession");
  55. Shutdown();
  56. DC_END_FN();
  57. }
  58. HRESULT
  59. CTSRDPRemoteDesktopSession::Initialize(
  60. BSTR connectParms,
  61. CRemoteDesktopServerHost *hostObject,
  62. REMOTE_DESKTOP_SHARING_CLASS sharingClass,
  63. BOOL bEnableCallback,
  64. DWORD timeOut,
  65. BSTR userHelpCreateBlob,
  66. LONG tsSessionID,
  67. BSTR userSID
  68. )
  69. /*++
  70. Routine Description:
  71. The Initialize method prepares the COM object for connection by
  72. the client-side Remote Desktop Host ActiveX Control.
  73. Arguments:
  74. connectParms - If parms are non-NULL, then the session already exists.
  75. Otherwise, a new session should be created.
  76. hostObject - Back pointer to containing RDS Host object.
  77. sharingClass - Level of desktop sharing for a new session.
  78. callbackCLSID - Callback object class ID for a new session.
  79. timeOut - Help session timeout value. 0, if not specified.
  80. userHelpCreateBlob - user specific help session create blob.
  81. tsSessionID - Terminal Services Session ID or -1 if
  82. undefined.
  83. userSID - User SID or "" if undefined.
  84. Return Value:
  85. S_OK on success. Otherwise, an error code is returned.
  86. --*/
  87. {
  88. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::Initialize");
  89. WSADATA wsData;
  90. CComBSTR helpAccountName;
  91. CComBSTR helpSessionID;
  92. HANDLE tokenHandle;
  93. PTOKEN_USER tokenUser = NULL;
  94. HRESULT hr = S_OK;
  95. CComBSTR tmpBstr;
  96. LPTSTR sidStr = NULL;
  97. //
  98. // Make a copy of connect parms.
  99. //
  100. m_ConnectParms = connectParms;
  101. //
  102. // Get our session ID if one is not provided.
  103. //
  104. if (tsSessionID != -1) {
  105. m_SessionID = tsSessionID;
  106. }
  107. else {
  108. if (!ProcessIdToSessionId(GetCurrentProcessId(), &m_SessionID)) {
  109. hr = HRESULT_FROM_WIN32(GetLastError());
  110. TRC_ERR((TB, TEXT("Error fetching session ID: %08X."),
  111. GetLastError()));
  112. goto CLEANUPANDEXIT;
  113. }
  114. }
  115. //
  116. // If we didn't get a SID, use our SID.
  117. //
  118. UINT len = SysStringByteLen(userSID);
  119. if (len == 0) {
  120. hr = FetchOurTokenUser(&tokenUser);
  121. if (hr != S_OK) {
  122. goto CLEANUPANDEXIT;
  123. }
  124. userSID = NULL;
  125. //
  126. // Copy the user SID into a BSTR.
  127. //
  128. if (!ConvertSidToStringSid(tokenUser->User.Sid, &sidStr)) {
  129. hr = HRESULT_FROM_WIN32(GetLastError());
  130. TRC_ERR((TB, L"ConvertSidToStringSid: %08X", hr));
  131. goto CLEANUPANDEXIT;
  132. }
  133. tmpBstr = sidStr;
  134. }
  135. //
  136. // Give the parent class a chance to initialize.
  137. //
  138. hr = CRemoteDesktopSession::Initialize(
  139. connectParms, hostObject,
  140. sharingClass,
  141. bEnableCallback,
  142. timeOut,
  143. userHelpCreateBlob,
  144. m_SessionID,
  145. (userSID != NULL) ? userSID : tmpBstr
  146. );
  147. if (!SUCCEEDED(hr)) {
  148. goto CLEANUPANDEXIT;
  149. }
  150. //
  151. // Instantiate the channel manager object and store in the parent
  152. // class.
  153. //
  154. m_ChannelMgr = new CComObject<CTSRDPServerChannelMgr>();
  155. if (m_ChannelMgr == NULL) {
  156. TRC_ERR((TB, TEXT("Error instantiating channel manager.")));
  157. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  158. goto CLEANUPANDEXIT;
  159. }
  160. m_ChannelMgr->AddRef();
  161. //
  162. // Get the help account name.
  163. //
  164. hr = m_HelpSession->get_AssistantAccountName(&helpAccountName);
  165. if (!SUCCEEDED(hr)) {
  166. TRC_ERR((TB, L"get_AssistantAccountName: %08X", hr));
  167. goto CLEANUPANDEXIT;
  168. }
  169. //
  170. // Get the help session ID.
  171. //
  172. hr = m_HelpSession->get_HelpSessionId(&helpSessionID);
  173. if (!SUCCEEDED(hr)) {
  174. TRC_ERR((TB, L"get_HelpSessionId: %08X", hr));
  175. goto CLEANUPANDEXIT;
  176. }
  177. //
  178. // Initialize the channel mnager
  179. //
  180. hr = m_ChannelMgr->Initialize(this, helpSessionID);
  181. if (hr != S_OK) {
  182. goto CLEANUPANDEXIT;
  183. }
  184. CLEANUPANDEXIT:
  185. if (tokenUser != NULL) {
  186. LocalFree(tokenUser);
  187. }
  188. if( sidStr != NULL ) {
  189. LocalFree( sidStr );
  190. }
  191. SetValid(SUCCEEDED(hr));
  192. DC_END_FN();
  193. return hr;
  194. }
  195. STDMETHODIMP
  196. CTSRDPRemoteDesktopSession::Disconnect()
  197. /*++
  198. Routine Description:
  199. Force a disconnect of the currently connected client,
  200. if one is connected.
  201. Arguments:
  202. Return Value:
  203. S_OK on success. Otherwise, an error code is returned.
  204. --*/
  205. {
  206. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::Disconnect");
  207. if (m_ChannelMgr != NULL) {
  208. m_ChannelMgr->Disconnect();
  209. }
  210. DC_END_FN();
  211. return S_OK;
  212. }
  213. void
  214. CTSRDPRemoteDesktopSession::Shutdown()
  215. /*++
  216. Routine Description:
  217. Final Initialization
  218. Arguments:
  219. Return Value:
  220. S_OK on success. Otherwise, an error code is returned.
  221. --*/
  222. {
  223. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::Shutdown");
  224. //
  225. // Tell the channel manager to stop listening for data so it can
  226. // shut down when its ref count goes to 0. And, decrement its
  227. // ref count.
  228. //
  229. if (m_ChannelMgr != NULL) {
  230. m_ChannelMgr->StopListening();
  231. m_ChannelMgr->Release();
  232. m_ChannelMgr = NULL;
  233. }
  234. DC_END_FN();
  235. }
  236. STDMETHODIMP
  237. CTSRDPRemoteDesktopSession::get_ConnectParms(
  238. OUT BSTR *parms
  239. )
  240. /*++
  241. Routine Description:
  242. Return parms that can be used to connect from the ActiveX client
  243. control.
  244. Arguments:
  245. parms - Parms returned here.
  246. Return Value:
  247. --*/
  248. {
  249. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::get_ConnectParms");
  250. HRESULT hr = S_OK;
  251. //
  252. // If we are not valid, fail.
  253. //
  254. if (!IsValid()) {
  255. hr = E_FAIL;
  256. ASSERT(FALSE);
  257. goto CLEANUPANDEXIT;
  258. }
  259. // Always get latest connect parm again, IP address might
  260. // change
  261. hr = m_HelpSession->get_ConnectParms( parms );
  262. CLEANUPANDEXIT:
  263. DC_END_FN();
  264. return hr;
  265. }
  266. VOID
  267. CTSRDPRemoteDesktopSession::GetSessionName(
  268. CComBSTR &name
  269. )
  270. /*++
  271. Routine Description:
  272. Return a string representation for the session.
  273. Arguments:
  274. Return Value:
  275. --*/
  276. {
  277. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::GetSessionName");
  278. WCHAR buf[256];
  279. ASSERT(IsValid());
  280. wsprintf(buf, L"TSRDP%ld", m_SessionID);
  281. name = buf;
  282. DC_END_FN();
  283. }
  284. VOID
  285. CTSRDPRemoteDesktopSession::GetSessionDescription(
  286. CComBSTR &descr
  287. )
  288. {
  289. GetSessionName(descr);
  290. }
  291. HRESULT
  292. CTSRDPRemoteDesktopSession::FetchOurTokenUser(
  293. PTOKEN_USER *tokenUser
  294. )
  295. /*++
  296. Routine Description:
  297. Fetch our Token User struct.
  298. Arguments:
  299. tokenUser - Returned token user for this thread. Should
  300. be freed using LocalFree.
  301. Return Value:
  302. S_OK on success. An error HRESULT otherwise.
  303. --*/
  304. {
  305. HRESULT hr = S_OK;
  306. ULONG bufferLength;
  307. HANDLE tokenHandle = NULL;
  308. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::FetchOurTokenUser");
  309. *tokenUser = NULL;
  310. //
  311. // Get our process token.
  312. //
  313. if (!OpenProcessToken(
  314. GetCurrentProcess(),
  315. TOKEN_QUERY,
  316. &tokenHandle
  317. )) {
  318. hr = HRESULT_FROM_WIN32(GetLastError());
  319. TRC_ERR((TB, L"OpenThreadToken: %08X", hr));
  320. goto CLEANUPANDEXIT;
  321. }
  322. //
  323. // Fetch our Token User struct.
  324. //
  325. bufferLength = 0;
  326. GetTokenInformation(
  327. tokenHandle,
  328. TokenUser,
  329. NULL,
  330. 0,
  331. &bufferLength
  332. );
  333. if (bufferLength == 0) {
  334. hr = HRESULT_FROM_WIN32(GetLastError());
  335. TRC_ERR((TB, L"OpenThreadToken: %08X", hr));
  336. goto CLEANUPANDEXIT;
  337. }
  338. *tokenUser = (PTOKEN_USER)LocalAlloc(LPTR, bufferLength);
  339. if (*tokenUser == NULL) {
  340. hr = HRESULT_FROM_WIN32(GetLastError());
  341. TRC_ERR((TB, L"LocalAlloc: %08X", GetLastError()));
  342. goto CLEANUPANDEXIT;
  343. }
  344. if (!GetTokenInformation(
  345. tokenHandle,
  346. TokenUser,
  347. *tokenUser,
  348. bufferLength,
  349. &bufferLength
  350. )) {
  351. hr = HRESULT_FROM_WIN32(GetLastError());
  352. LocalFree(*tokenUser);
  353. *tokenUser = NULL;
  354. }
  355. CLEANUPANDEXIT:
  356. if (tokenHandle != NULL) {
  357. CloseHandle(tokenHandle);
  358. }
  359. DC_END_FN();
  360. return hr;
  361. }
  362. HRESULT CTSRDPRemoteDesktopSession::StartListening()
  363. /*++
  364. Routine Description:
  365. Start listening
  366. Should be called everytime the client disconnects and everytime we open
  367. a remote desktop session
  368. This is because the named pipe would have been closed in the disconnect
  369. Return Value:
  370. S_OK on success. An error HRESULT otherwise.
  371. --*/
  372. {
  373. DC_BEGIN_FN("CTSRDPRemoteDesktopSession::StartListening");
  374. HRESULT hr = E_FAIL;
  375. CComBSTR helpAccountName;
  376. //
  377. // Tell the channel manager to start listening
  378. //
  379. if (m_ChannelMgr != NULL) {
  380. //
  381. // Get the help account name.
  382. //
  383. hr = m_HelpSession->get_AssistantAccountName(&helpAccountName);
  384. if (!SUCCEEDED(hr)) {
  385. TRC_ERR((TB, L"get_AssistantAccountName: %08X", hr));
  386. goto CLEANUPANDEXIT;
  387. }
  388. hr = m_ChannelMgr->StartListening(helpAccountName);
  389. }
  390. DC_END_FN();
  391. CLEANUPANDEXIT:
  392. return hr;
  393. }