603 lines
11 KiB
C++
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();
|
||
|
}
|