windows-nt/Source/XPSP1/NT/termsrv/remdsk/msngr/remotedesktopclientsession.cpp
2020-09-26 16:20:57 +08:00

603 lines
11 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
RemoteDesktopClientSession
Abstract:
RemoteDesktopClientSession manages the client side GUI for the application
hostiving the Salem ActiveX control.
Author:
Marc Reyhner 7/11/2000
--*/
#include "stdafx.h"
#ifdef TRC_FILE
#undef TRC_FILE
#endif
#define TRC_FILE "rcrdcs"
#include "RemoteDesktopClientSession.h"
#include "RemoteDesktopClientEventSink.h"
#include "resource.h"
#include "exception.h"
//
// The guid for the ActiveX control we are creating the child window for.
//
#define REMOTEDESKTOPHOST_TEXTGUID TEXT("{299BE050-E83E-4DB7-A7DA-D86FDEBFE6D0}")
CRemoteDesktopClientSession::CRemoteDesktopClientSession(
IN OUT HINSTANCE hInstance
)
/*++
Routine Description:
The only thing the constructor does is to save hInstance and to
set gm_Session to be this class.
Arguments:
hInstance - The instance for this module.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::CRemoteDesktopClientSession");
m_hWnd = NULL;
m_hRdcHostWnd = NULL;
m_RemDeskClient = NULL;
m_Sink = NULL;
m_hInstance = hInstance;
DC_END_FN();
}
CRemoteDesktopClientSession::~CRemoteDesktopClientSession(
)
/*++
Routine Description:
We just NULL the gm_Session pointer here since everything else
was already cleaned up.
Arguments:
None.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::~CRemoteDesktopClientSession");
DC_END_FN();
}
VOID
CRemoteDesktopClientSession::DoClientSession(
IN BSTR parms
)
/*++
Routine Description:
Here we start and manage the entire client GUI.
Arguments:
parms - The string needed for Salem to connect to the remote server.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::DoClientSession");
HRESULT hr;
ATOM atom;
TCHAR wndTitle[MAX_STR_LEN];
HICON wndIcon = (HICON)LoadImage(m_hInstance,MAKEINTRESOURCE(IDI_TRAYICON),
IMAGE_ICON,0,0,0);
WNDCLASS wndClass = { CS_PARENTDC, _WindowProc, 0, 0, m_hInstance, wndIcon, NULL,
(HBRUSH)COLOR_WINDOWFRAME,MAKEINTRESOURCE(IDR_CLIENTMENU),TEXT("RdcWndClass") };
AtlAxWinInit();
atom = RegisterClass(&wndClass);
if (!atom) {
TRC_ERR((TB,TEXT("Error registering window class for main frame.")));
goto FAILURE;
}
LoadStringSimple(IDS_CLIENTWNDTITLE,wndTitle);
m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,(LPCTSTR)atom,wndTitle,
WS_VISIBLE|WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
50,50,690,530,NULL,NULL,m_hInstance,this);
if (!m_hWnd) {
TRC_ERR((TB,TEXT("Error creating main frame.")));
goto FAILURE;
}
SetForegroundWindow(m_hWnd);
m_Sink = new CRemoteDesktopClientEventSink(this);
if (!m_Sink) {
TRC_ERR((TB,TEXT("Error creating client event sink.")));
goto FAILURE;
}
hr = m_Sink->DispEventAdvise(m_RemDeskClient);
if (hr != S_OK) {
goto FAILURE;
}
hr = m_RemDeskClient->put_ConnectParms(parms);
if (hr != S_OK) {
goto FAILURE;
}
hr = m_RemDeskClient->ConnectToServer(NULL);
if (hr != S_OK) {
goto FAILURE;
}
DoMessageLoop();
delete m_Sink;
m_Sink = NULL;
DestroyIcon(wndIcon);
DC_END_FN();
return;
FAILURE:
throw CException(IDS_CLIENTERRORCREATE);
}
LRESULT CALLBACK
CRemoteDesktopClientSession::_WindowProc(
IN OUT HWND hWnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
The window proc calls the appropriate message handler for the messages
that we care about.
Arguments:
hWnd - The window the message is for.
uMsg - The message.
wParam - WPARAM for the message.
lParam - LPARAM for the message.
Return value:
LRESULT - The message specific return code. See MSDN for details.
--*/
{
LRESULT retValue = 0;
CRemoteDesktopClientSession *session;
DC_BEGIN_FN("CRemoteDesktopClientSession::_WindowProc");
if (uMsg != WM_CREATE) {
session = (CRemoteDesktopClientSession*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
}
switch (uMsg) {
case WM_CREATE:
session = (CRemoteDesktopClientSession*)
((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hWnd,GWLP_USERDATA,(long)session);
retValue = session->OnCreate(hWnd);
break;
case WM_COMMAND:
if (session) {
retValue = session->OnCommand(wParam,lParam);
}
break;
case WM_DESTROY:
if (session) {
session->OnDestroy();
}
break;
case WM_SETFOCUS:
if (session) {
session->OnSetFocus();
}
break;
case WM_SIZE:
if (session) {
session->OnSize(LOWORD(lParam),HIWORD(lParam));
}
break;
default:
retValue = DefWindowProc(hWnd,uMsg,wParam,lParam);
}
DC_END_FN();
return retValue;
}
VOID
CRemoteDesktopClientSession::DoMessageLoop(
)
/*++
Routine Description:
This runs through your normal event loop until we get a WM_QUIT.
Any dialogs that messages should be caught for need to be inserted
into this function.
Arguments:
None.
Return value:
None.
--*/
{
MSG msg;
DC_BEGIN_FN("CRemoteDesktopClientSession::DoMessageLoop");
while (GetMessage(&msg,NULL,0,0)>0) {
if (!m_AboutDlg.DialogMessage(&msg) && !m_ApprovalDlg.DialogMessage(&msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DC_END_FN();
}
LRESULT
CRemoteDesktopClientSession::OnCreate(
IN OUT HWND hWnd
)
/*++
Routine Description:
When the window is being created we create the child window and get a pointer
to the IRemoteDesktopClient for the control. If there is a problem we return
-1 and the window is not created.
Arguments:
hWnd - The window being created.
Return value:
0 - The window was created correctly.
-1 - There was an error creating the window.
--*/
{
HRESULT hr;
IUnknown *pUnk = NULL;
ISAFRemoteDesktopClientHost *remClientHost = NULL;
DC_BEGIN_FN("CRemoteDesktopClientSession::OnCreate");
m_hRdcHostWnd = CreateWindow(TEXT("AtlAxWin"),REMOTEDESKTOPHOST_TEXTGUID,
WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE,0,0,0,0,hWnd,NULL,m_hInstance,NULL);
if (!m_hRdcHostWnd) {
TRC_ERR((TB,TEXT("Error creating Salem window.")));
goto FAILURE;
}
hr = AtlAxGetControl(m_hRdcHostWnd,&pUnk);
if (hr != S_OK) {
TRC_ERR((TB,TEXT("Error getting IUnknown from salem window.")));
goto FAILURE;
}
hr = pUnk->QueryInterface(__uuidof(ISAFRemoteDesktopClientHost),(LPVOID*)&remClientHost);
if (hr != S_OK) {
TRC_ERR((TB,TEXT("Error getting IRemoteDesktopClientHost from Salem control.")));
goto FAILURE;
}
pUnk->Release();
pUnk = NULL;
hr = remClientHost->GetRemoteDesktopClient(&m_RemDeskClient);
if (hr != S_OK) {
TRC_ERR((TB,TEXT("Error gettin IRemoteDesktopClient from host.")));
goto FAILURE;
}
remClientHost->Release();
remClientHost = NULL;
DC_END_FN();
return 0;
FAILURE:
if (m_hRdcHostWnd) {
DestroyWindow(m_hRdcHostWnd);
m_hRdcHostWnd = NULL;
}
if (pUnk) {
pUnk->Release();
pUnk = NULL;
}
if (remClientHost) {
remClientHost->Release();
remClientHost = NULL;
}
return -1;
}
VOID
CRemoteDesktopClientSession::OnSize(
IN WORD width,
IN WORD height
)
/*++
Routine Description:
We keep the child window the same as our new size.
Arguments:
None.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::OnSize");
SetWindowPos(m_hRdcHostWnd,NULL,0,0,width,height,SWP_NOZORDER);
DC_END_FN();
}
VOID
CRemoteDesktopClientSession::ConnectRemoteDesktop(
)
/*++
Routine Description:
We initiate a request to control the remote desktop and pop up the
approval warning dialog.
Arguments:
None.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::ConnectRemoteDesktop");
m_RemDeskClient->ConnectRemoteDesktop();
m_ApprovalDlg.m_rObj = this;
m_ApprovalDlg.Create(m_hInstance,IDD_APPROVALWAIT,m_hWnd);
DC_END_FN();
}
VOID
CRemoteDesktopClientSession::OnAbout(
)
/*++
Routine Description:
We either create or bring to the foreground the about box.
Arguments:
None.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::OnAbout");
if (m_AboutDlg.IsCreated()) {
m_AboutDlg.Activate();
} else {
m_AboutDlg.Create(m_hInstance,IDD_ABOUT,m_hWnd);
}
DC_END_FN();
}
LRESULT
CRemoteDesktopClientSession::OnCommand(
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
When the window is destroyed we disconnect from the remote host and then
send a quit message to exit the event loop.
Arguments:
wParam - The command which was triggered.
lParam - The control the command came from.
Return value:
0 - We handled the command.
1 - We did not handle the command.
--*/
{
LRESULT retValue = 0;
DC_BEGIN_FN("CRemoteDesktopClientSession::OnCommand");
switch (wParam) {
case ID_EXIT:
DestroyWindow(m_hWnd);
break;
case ID_ABOUT:
OnAbout();
break;
default:
retValue = 1;
}
DC_END_FN();
return retValue;
}
VOID
CRemoteDesktopClientSession::OnDestroy(
)
/*++
Routine Description:
When the window is destroyed we disconnect from the remote host and then
send a quit message to exit the event loop.
Arguments:
None.
Return value:
None.
--*/
{
BOOL isConnected;
HRESULT hr;
DC_BEGIN_FN("CRemoteDesktopClientSession::OnDestroy");
if(m_RemDeskClient) {
hr = m_RemDeskClient->get_IsRemoteDesktopConnected(&isConnected);
if (hr == S_OK && isConnected) {
m_RemDeskClient->DisconnectRemoteDesktop();
}
m_RemDeskClient->DisconnectFromServer();
}
PostQuitMessage(0);
DC_END_FN();
}
VOID
CRemoteDesktopClientSession::ShowRemdeskControl(
)
/*++
Routine Description:
This makes our child window visible.
Arguments:
None.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::ShowRemdeskControl");
ShowWindow(m_hRdcHostWnd,SW_SHOW);
DC_END_FN();
}
VOID
CRemoteDesktopClientSession::OnSetFocus(
)
/*++
Routine Description:
When we get focus we pass it off to our child window.
Arguments:
None.
Return value:
None.
--*/
{
DC_BEGIN_FN("CRemoteDesktopClientSession::OnSetFocus");
SetFocus(m_hRdcHostWnd);
DC_END_FN();
}