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.

534 lines
12 KiB

  1. // MstscMhst.cpp : Implementation of CMstscMhst
  2. // Multi host control for TS activeX control.
  3. // contains multiple instances of the activeX control. Used by the MMC control
  4. // Copyright(C) Microsoft Corporation 2000
  5. // nadima
  6. #include "stdafx.h"
  7. #include "multihst.h"
  8. //Pos/width of sessions that are not active
  9. #define X_POS_DISABLED -10
  10. #define Y_POS_DISABLED -10
  11. #define X_WIDTH_DISABLED 5
  12. #define Y_WIDTH_DISABLED 5
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CMstscMhst
  15. /*
  16. *Function Name:Add
  17. *
  18. *Parameters: (out) ppMstsc pointer to newly added TS control
  19. *
  20. *Description: Add's a new TS ActiveX control to the multihost
  21. *
  22. *Returns: HRESULT
  23. *
  24. */
  25. STDMETHODIMP CMstscMhst::Add(IMsRdpClient** ppMstsc)
  26. {
  27. if (::IsWindow(m_hWnd))
  28. {
  29. CAxWindow* pAxWnd = new CAxWindow();
  30. ATLASSERT(pAxWnd);
  31. if (!pAxWnd)
  32. {
  33. return E_OUTOFMEMORY;
  34. }
  35. RECT rc;
  36. GetClientRect(&rc);
  37. //
  38. // Window is created invisible and disabled...
  39. // Must be made with active client for it to become enabled and visible
  40. //
  41. if (!pAxWnd->Create( m_hWnd, rc, MSTSC_CONTROL_GUID,
  42. WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
  43. 0))
  44. {
  45. delete pAxWnd;
  46. return E_FAIL;
  47. }
  48. CComPtr<IMsRdpClient> tsClientPtr;
  49. if (FAILED(pAxWnd->QueryControl( &tsClientPtr)))
  50. {
  51. delete pAxWnd;
  52. return E_FAIL;
  53. }
  54. //
  55. // Store the pointer to the control
  56. //
  57. m_coll.push_back( pAxWnd);
  58. //If no MSTSC windows are active then make this first
  59. //one the active window
  60. if (!m_pActiveWindow)
  61. {
  62. SwitchCurrentActiveClient( pAxWnd);
  63. }
  64. if (ppMstsc)
  65. {
  66. //
  67. // return the pointer, Detach does not decrement the ref count
  68. // so we still hold a reference to the control from the QueryControl
  69. // that is the +1 refcount needed to pass the pointer as an out
  70. // parameter.
  71. //
  72. *ppMstsc = (IMsRdpClient*)tsClientPtr.Detach();
  73. }
  74. return S_OK;
  75. }
  76. else
  77. {
  78. return E_FAIL;
  79. }
  80. }
  81. /*
  82. *Function Name:get_Item
  83. *
  84. *Parameters: (in) Index (index of the item to return)
  85. * (out) ppMstsc pointer to the TS control returned
  86. *
  87. *Description: returns the TS control at a particular index
  88. *
  89. *Returns: HRESULT
  90. *
  91. */
  92. STDMETHODIMP CMstscMhst::get_Item(long Index, IMsRdpClient** ppMstsc)
  93. {
  94. if (Index <0 || Index >= m_coll.size())
  95. {
  96. ATLASSERT(Index > 0 && Index < m_coll.size());
  97. return E_INVALIDARG;
  98. }
  99. if (!ppMstsc)
  100. {
  101. return E_INVALIDARG;
  102. }
  103. //Return the interface pointer associated
  104. //with the AxWindow container
  105. CAxWindow* pAxWnd = m_coll[Index];
  106. if (!pAxWnd)
  107. {
  108. return E_FAIL;
  109. }
  110. CComPtr<IMsRdpClient> tsClientPtr;
  111. if (FAILED(pAxWnd->QueryControl( &tsClientPtr)))
  112. {
  113. delete pAxWnd;
  114. return E_FAIL;
  115. }
  116. //
  117. // Return the pointer to the ts control. Detach does not
  118. // decrement the AddRef from QueryControl so the refcount is
  119. // correctly incremented by one for the out parameter
  120. //
  121. *ppMstsc = (IMsRdpClient*)tsClientPtr.Detach();
  122. return S_OK;
  123. }
  124. /*
  125. *Function Name:get_Count
  126. *
  127. *Parameters: (out) pCount
  128. *
  129. *Description: returns number of items in the collection
  130. *
  131. *Returns: HRESULT
  132. *
  133. */
  134. STDMETHODIMP CMstscMhst::get_Count(long* pCount)
  135. {
  136. if (!pCount)
  137. {
  138. return E_INVALIDARG;
  139. }
  140. *pCount = m_coll.size();
  141. return S_OK;
  142. }
  143. /*
  144. *Function Name:put_ActiveClientIndex
  145. *
  146. *Parameters: (in) ClientIndex
  147. *
  148. *Description: sets the active client by Index
  149. *
  150. *Returns: HRESULT
  151. *
  152. */
  153. STDMETHODIMP CMstscMhst::put_ActiveClientIndex(long ClientIndex)
  154. {
  155. if (ClientIndex < 0 || ClientIndex >= m_coll.size())
  156. {
  157. return E_INVALIDARG;
  158. }
  159. CAxWindow* pNewClientWnd = m_coll[ClientIndex];
  160. if (!pNewClientWnd)
  161. {
  162. return E_FAIL;
  163. }
  164. if (SwitchCurrentActiveClient(pNewClientWnd))
  165. {
  166. m_ActiveClientIndex = ClientIndex;
  167. return S_OK;
  168. }
  169. else
  170. {
  171. return E_FAIL;
  172. }
  173. }
  174. /*
  175. *Function Name:get_ActiveClient
  176. *
  177. *Parameters: (out) ppMstsc pointer to active client
  178. *
  179. *Description: returns the ActiveClient
  180. *
  181. *Returns: HRESULT
  182. *
  183. */
  184. STDMETHODIMP CMstscMhst::get_ActiveClient(IMsRdpClient** ppMstsc)
  185. {
  186. if (!ppMstsc)
  187. {
  188. return E_INVALIDARG;
  189. }
  190. if (!m_pActiveWindow)
  191. {
  192. *ppMstsc = NULL;
  193. return S_OK;
  194. }
  195. CComPtr<IMsRdpClient> tsClientPtr;
  196. if (FAILED(m_pActiveWindow->QueryControl( &tsClientPtr)))
  197. {
  198. return E_FAIL;
  199. }
  200. //
  201. // Detach keeps the +1 ref from QueryControl
  202. //
  203. *ppMstsc = (IMsRdpClient*)tsClientPtr.Detach();
  204. return S_OK;
  205. }
  206. /*
  207. *Function Name:put_ActiveClient
  208. *
  209. *Parameters: ppMstsc
  210. *
  211. *Description: sets the active client given a pointer to
  212. * to the client instance
  213. *
  214. *Returns: HRESULT
  215. *
  216. */
  217. STDMETHODIMP CMstscMhst::put_ActiveClient(IMsRdpClient* ppMstsc)
  218. {
  219. CAxWindow* pAxWnd = NULL;
  220. //find AxWindow that hosts this client
  221. //in the collection
  222. std::vector<CAxWindow*>::iterator iter;
  223. for (iter = m_coll.begin(); iter != m_coll.end(); iter++)
  224. {
  225. CComPtr<IMsRdpClient> tsClientPtr;
  226. HRESULT hr = (*iter)->QueryControl( &tsClientPtr);
  227. if (FAILED(hr))
  228. {
  229. return hr;
  230. }
  231. if (tsClientPtr == ppMstsc)
  232. {
  233. pAxWnd = *iter;
  234. break;
  235. }
  236. }
  237. if (!pAxWnd)
  238. {
  239. //We were given a control reference that could not be found
  240. return E_INVALIDARG;
  241. }
  242. if (!SwitchCurrentActiveClient(pAxWnd))
  243. {
  244. return E_FAIL;
  245. }
  246. return S_OK;
  247. }
  248. /*
  249. *Function Name:SwitchCurrentActiveClient
  250. *
  251. *Parameters: (in) newHostWindow - AxWindow that will become
  252. * the active window
  253. *
  254. *Description: sets the active client given a pointer to
  255. * to the client instance
  256. *
  257. *Returns: success flag
  258. *
  259. */
  260. BOOL CMstscMhst::SwitchCurrentActiveClient(CAxWindow* newHostWindow)
  261. {
  262. //Switch the current active client window
  263. if (!newHostWindow)
  264. {
  265. return FALSE;
  266. }
  267. m_pActiveWindow = newHostWindow;
  268. //
  269. // Make sure the window is sized properly
  270. //
  271. RECT rcClient;
  272. GetClientRect(&rcClient);
  273. m_pActiveWindow->MoveWindow(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
  274. m_pActiveWindow->SetFocus();
  275. //
  276. // This window is made the active child window by brining
  277. // it to the top of the Z-order of child windows
  278. //
  279. newHostWindow->BringWindowToTop();
  280. return TRUE;
  281. }
  282. /*
  283. *Function Name:RemoveIndex
  284. *
  285. *Parameters: ClientIndex
  286. *
  287. *Description: removes a client by index
  288. *
  289. *Returns: HRESULT
  290. *
  291. */
  292. STDMETHODIMP CMstscMhst::RemoveIndex(long ClientIndex)
  293. {
  294. HRESULT hr;
  295. CComPtr<IMsRdpClient> tsClientPtr;
  296. hr = get_Item(ClientIndex, (IMsRdpClient**) (&tsClientPtr));
  297. if (FAILED(hr))
  298. {
  299. return hr;
  300. }
  301. //Pass in interface pointer without addref'ing
  302. hr = Remove( (IMsRdpClient*)tsClientPtr);
  303. return hr;
  304. }
  305. /*
  306. *Function Name:Remove
  307. *
  308. *Parameters: (in) ppMsts client to remove
  309. *
  310. *Description: removes a client from the collection
  311. *
  312. *Returns: HRESULT
  313. *
  314. */
  315. STDMETHODIMP CMstscMhst::Remove(IMsRdpClient* ppMstsc)
  316. {
  317. //Look for the ax window container and if found delete it
  318. //also, remove the entry from the collection
  319. //find AxWindow that hosts this client
  320. CAxWindow* pAxWnd = NULL;
  321. std::vector<CAxWindow*>::iterator iter;
  322. for (iter = m_coll.begin(); iter != m_coll.end(); iter++)
  323. {
  324. CComPtr<IMsRdpClient> tsClientPtr;
  325. HRESULT hr = (*iter)->QueryControl( &tsClientPtr);
  326. if (FAILED(hr))
  327. {
  328. return hr;
  329. }
  330. if (tsClientPtr == ppMstsc)
  331. {
  332. pAxWnd = *iter;
  333. break;
  334. }
  335. }
  336. if (!pAxWnd)
  337. {
  338. //We were given a control reference that could not be found
  339. return E_INVALIDARG;
  340. }
  341. m_coll.erase(iter);
  342. return DeleteAxContainerWnd(pAxWnd);
  343. }
  344. /*
  345. *Function Name:DeleteAxContainerWnd
  346. *
  347. *Parameters: (in) pAxWnd CAxWindow to delete
  348. *
  349. *Description: deletes an activeX container window
  350. *
  351. *Returns: HRESULT
  352. *
  353. */
  354. HRESULT CMstscMhst::DeleteAxContainerWnd(CAxWindow* pAxWnd)
  355. {
  356. if (!pAxWnd)
  357. {
  358. return E_FAIL;
  359. }
  360. if (m_pActiveWindow == pAxWnd)
  361. {
  362. m_pActiveWindow = NULL;
  363. }
  364. if (!pAxWnd->DestroyWindow())
  365. {
  366. return E_FAIL;
  367. }
  368. delete pAxWnd;
  369. return S_OK;
  370. }
  371. //
  372. // OnCreate Handler
  373. //
  374. LRESULT CMstscMhst::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  375. {
  376. ::SetWindowLong(m_hWnd, GWL_STYLE,
  377. ::GetWindowLong(m_hWnd, GWL_STYLE) | WS_CLIPCHILDREN);
  378. if (!AtlAxWinInit())
  379. {
  380. return -1;
  381. }
  382. return 0;
  383. }
  384. /*
  385. *Function Name:OnDestroy
  386. *
  387. *Parameters:
  388. *
  389. *Description: handler for WM_DESTROY
  390. *
  391. *Returns:
  392. *
  393. */
  394. LRESULT CMstscMhst::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  395. {
  396. m_pActiveWindow = NULL;
  397. if (!AtlAxWinTerm())
  398. {
  399. return -1;
  400. }
  401. //
  402. // Delete everything in the collection
  403. //
  404. std::vector<CAxWindow*>::iterator iter;
  405. for (iter = m_coll.begin(); iter != m_coll.end(); iter++)
  406. {
  407. //
  408. // This frees any remaining controls
  409. //
  410. DeleteAxContainerWnd(*iter);
  411. }
  412. //
  413. // Erase the CAxWindow items in the collection
  414. //
  415. m_coll.erase(m_coll.begin(), m_coll.end());
  416. return 0;
  417. }
  418. /**PROC+*********************************************************************/
  419. /* Name: OnFrameWindowActivate */
  420. /* */
  421. /* Purpose: Override IOleInPlaceActiveObject::OnFrameWindowActivate */
  422. /* to set the focus on the core container window when the control */
  423. /* gets activated */
  424. /* */
  425. /**PROC-*********************************************************************/
  426. STDMETHODIMP CMstscMhst::OnFrameWindowActivate(BOOL fActivate )
  427. {
  428. if (fActivate && IsWindow() && m_pActiveWindow)
  429. {
  430. m_pActiveWindow->SetFocus();
  431. }
  432. return S_OK;
  433. }
  434. LRESULT CMstscMhst::OnGotFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  435. {
  436. ATLTRACE("CMstscMhst::OnGotFocus");
  437. if (m_pActiveWindow)
  438. {
  439. m_pActiveWindow->SetFocus();
  440. }
  441. return 0;
  442. }
  443. LRESULT CMstscMhst::OnLostFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  444. {
  445. ATLTRACE("CMstscMhst::OnLostFocus");
  446. return 0;
  447. }
  448. LRESULT CMstscMhst::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  449. {
  450. RECT rcClient;
  451. if (m_pActiveWindow)
  452. {
  453. GetClientRect(&rcClient);
  454. m_pActiveWindow->MoveWindow(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
  455. }
  456. return 0;
  457. }