|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
Rcontrol Main
Abstract:
This includes WinMain and the WndProc for the system tray icon.
Author:
Marc Reyhner 7/5/2000
--*/
#include "stdafx.h"
#include <initguid.h>
#ifdef TRC_FILE
#undef TRC_FILE
#endif
#define TRC_FILE "rcm"
#include "rcontrol.h"
#include "resource.h"
#include "exception.h"
#include "DirectPlayConnection.h"
#include "RemoteDesktopClientSession.h"
#include "RemoteDesktopServer.h"
#include "RemoteDesktopServerEventSink.h"
// This is the message that will will get when someone does something to the
// taskbar icon.
#define WM_SYSICONMESSAGE (WM_USER + 1)
//
//
//
#define MUTEX_NAME (TEXT("Local\\MICROSOFT_SALEM_IM_MUTEX"))
// This is a pointer to our instance so that we can pass it off to some
// of the menu functions.
HINSTANCE g_hInstance;
// This is the structure for setting parameters for the taskbar icon. We keep one copy
// of it around that we can pass in to Shell_NotifyIcon
NOTIFYICONDATA g_iconData;
// This is a global pointer to the direct play connection so that
// the server can close the DP connection on connect.
CDirectPlayConnection *g_DpConnection;
// This helper function lauches the executable for the gui passing it the
// connection parameters on the command line.
static VOID LaunchClient( HINSTANCE hInstance, BSTR parms );
// This helper function runs the system tray icon if this is a server.
static VOID DoSystemTray( );
// This is the WndProc for the taskbar icon
static LRESULT CALLBACK SysTrayWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
INT WINAPI WinMain( IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN INT nShowCmd) /*++
Routine Description:
The entry point for the application. This figures out if we are a server or client and then behaves accordingly.
Arguments:
hInstance - The instance for this application.
hPrevInstance - Previous instance, should be NULL
lpCmdLine - Command line for the application.
nShowCmd - Flags for how to show the application.
Return value:
INT - The return code for the application.
--*/ { HANDLE lpMutex = NULL; DWORD error; BSTR serverParms, clientParms; DC_BEGIN_FN("WinMain");
serverParms = NULL; clientParms = NULL; g_hInstance = hInstance; CoInitialize(NULL); try { CDirectPlayConnection connection; g_DpConnection = &connection; connection.ConnectToRemoteApplication(); if (connection.IsServer()) { // we are a server
CRemoteDesktopServer server; CRemoteDesktopServerEventSink sink; HRESULT hr;
lpMutex = CreateMutex(NULL,TRUE,MUTEX_NAME); if (!lpMutex) { throw CException(IDS_INITERRORMUTEX); } error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { throw CException(IDS_INITALREADYEXISTS); } serverParms = server.StartListening(); hr = server.EventSinkAdvise(&sink); if (hr != S_OK) { throw CException(IDS_ADVISEERROR); } connection.SendConnectionParameters(serverParms); DoSystemTray(); try { server.StopListening(); } catch (CException e) { TRC_ERR((TB,TEXT("Caught Exception: %s"),e.GetErrorStr())); // We are shutting down so just suppress the error.
} CloseHandle(lpMutex); } else { // we are the client
clientParms = connection.ReceiveConnectionParameters(); connection.DisconnectRemoteApplication(); LaunchClient(hInstance,clientParms); } } catch (CException e) { TCHAR dlgTitle[MAX_STR_LEN]; TRC_ERR((TB,TEXT("Caught Exception: %s"),e.GetErrorStr())); LoadStringSimple(IDS_ERRORDDLGTITLE,dlgTitle); MessageBox(NULL,e.GetErrorStr(),dlgTitle,MB_OK|MB_ICONERROR); } if (clientParms) { delete clientParms; }
CoUninitialize();
DC_END_FN(); return 0; }
static VOID LaunchClient( IN OUT HINSTANCE hInstance, IN BSTR parms )
/*++
Routine Description:
This starts (and does) the client GUI side of the application. DoClientSession will not returne until the client GUI is totally done.
Arguments:
hInstance - The instance for this application
parms - The connection parameters for connecting to the server.
Return value: None
--*/ { DC_BEGIN_FN("LaunchClient");
CRemoteDesktopClientSession clientSession(hInstance); clientSession.DoClientSession(parms);
DC_END_FN(); }
static VOID DoSystemTray( ) /*++
Routine Description:
This creates the system tray and enters the event loop until the a WM_QUIT message is generated.
Arguments:
None
Return value:
None
--*/ { MSG msg; WNDCLASS wndClass; ATOM className; HWND hWnd; TCHAR tipText[MAX_STR_LEN];
DC_BEGIN_FN("DoSystemTray");
wndClass.style = 0; wndClass.lpfnWndProc = SysTrayWndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = g_hInstance; wndClass.hIcon = NULL; wndClass.hCursor = NULL; wndClass.hbrBackground = NULL; wndClass.lpszMenuName = NULL; // This is an internal name so we don't need to localize this.
wndClass.lpszClassName = TEXT("SysTrayWindowClass"); className = RegisterClass(&wndClass); hWnd = CreateWindow((LPCTSTR)className,TEXT(""),0,0,0,0,0,/*HWND_MESSAGE*/0,NULL,NULL,NULL); if (hWnd == NULL) { throw "Failed to create system tray icon."; }
g_iconData.cbSize = sizeof(g_iconData); g_iconData.hIcon = ::LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_TRAYICON)); g_iconData.hWnd = hWnd; LoadStringSimple(IDS_TRAYTOOLTIPDISCONNECTED,tipText); // The buffer is only 128 chars.
_tcsncpy(g_iconData.szTip,tipText,128 - 1); g_iconData.uCallbackMessage = WM_SYSICONMESSAGE; g_iconData.uFlags = NIF_ICON|NIF_MESSAGE |NIF_TIP; g_iconData.uID = 0; g_iconData.uVersion = NOTIFYICON_VERSION;
Shell_NotifyIcon(NIM_ADD,&g_iconData); g_iconData.uFlags = 0; Shell_NotifyIcon(NIM_SETVERSION,&g_iconData); // Do our message loop.
while (GetMessage(&msg, (HWND) NULL, 0, 0)>0) { TranslateMessage(&msg); DispatchMessage(&msg); } Shell_NotifyIcon(NIM_DELETE,&g_iconData); DC_END_FN(); }
static LRESULT CALLBACK SysTrayWndProc( IN HWND hWnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
/*++
Routine Description:
Callback for our taskbar icon. This handles all the window messages related to the icon.
Arguments:
hWnd - Window the message is for
uMsg - The message code
wParam - First message flag
lParam - Second message flag
Return value: LRESULT - The result of processing the message
--*/ { // This is the window message for when the taskbar
// is recreated. We will just initialize it once on
// WM_CREATE
static UINT g_wmTaskbarCreated = 0; // This is the code we will return. We will initialize it to 1.
LRESULT result = 1;
DC_BEGIN_FN("SysTrayWndProc"); // If the taskbar is recreates (i.e. explorer crashed) it will
// give us this message. When that happens we want to re-create
// the taskbar icon.
if (uMsg == g_wmTaskbarCreated) { g_iconData.uFlags = NIF_ICON|NIF_MESSAGE |NIF_TIP; Shell_NotifyIcon(NIM_ADD,&g_iconData); g_iconData.uFlags = 0; Shell_NotifyIcon(NIM_SETVERSION,&g_iconData); DC_END_FN(); return 0; } switch (uMsg) { case WM_CREATE: g_wmTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated")); if (!g_wmTaskbarCreated) { result = -1; } else { result = 0; } case WM_SYSICONMESSAGE: switch (lParam) { case WM_CONTEXTMENU: POINT pos; HMENU hMenu, hSubmenu; GetCursorPos(&pos); hMenu = LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_TRAYMENU)); hSubmenu = GetSubMenu(hMenu,0); SetForegroundWindow(hWnd); TrackPopupMenu(hSubmenu,TPM_VERNEGANIMATION,pos.x,pos.y,0,hWnd,NULL); // this also destroys the submenu
DestroyMenu(hMenu); g_iconData.uFlags = 0; Shell_NotifyIcon(NIM_SETFOCUS,&g_iconData); result = 0; break; case WM_LBUTTONDOWN: PostMessage(hWnd,WM_COMMAND,ID_QUIT,NULL); result = 0; break; default: // Any other messages we will ignore
result = 0; } break; case WM_COMMAND: switch (wParam) { case ID_QUIT: TCHAR dlgText[MAX_STR_LEN], dlgTitle[MAX_STR_LEN]; LoadStringSimple(IDS_TRAYEXITDLGTEXT,dlgText); LoadStringSimple(IDS_TRAYEXITDLGTITLE,dlgTitle); if (IDYES == MessageBox(hWnd,dlgText,dlgTitle,MB_YESNO)) { PostQuitMessage(0); } result = 0; break; } break; default: // We don't understand this message so do the default.
result = DefWindowProc(hWnd,uMsg,wParam,lParam); } DC_END_FN(); return result; }
INT LoadStringSimple( IN UINT uID, OUT LPTSTR lpBuffer )
/*++
Routine Description:
This will load the given string from the applications string table. If it is longer than MAX_STR_LEN it is truncated. lpBuffer should be at least MAX_STR_LEN characters long. If the string does not exist we return 0 and set the buffer to IDS_STRINGMISSING, if that failes then we set it to the hard coded STR_RES_MISSING.
Arguments:
uID - Id of the resource to load.
lpBuffer - Buffer of MAX_STR_LEN to hold the string
Return value: 0 - String resource could not be loaded.
postive integer - length of the string loaded.
--*/ { INT length; DC_BEGIN_FN("LoadStringSimple");
length = LoadString(g_hInstance,uID,lpBuffer,MAX_STR_LEN); if (length == 0) { length = LoadString(g_hInstance,IDS_STRINGMISSING,lpBuffer,MAX_STR_LEN); if (length == 0) { _tcscpy(lpBuffer,STR_RES_MISSING); } length = 0; }
DC_END_FN(); return length; }
|