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.
3995 lines
126 KiB
3995 lines
126 KiB
//
|
|
// uiint.cpp
|
|
//
|
|
// UI Class internal functions
|
|
//
|
|
// Implements the root object in the rdp client core hierarchy
|
|
// this object owns the top level windows in the core.
|
|
//
|
|
// Copyright (C) 1997-2000 Microsoft Corporation
|
|
//
|
|
|
|
#include <adcg.h>
|
|
#define TRC_GROUP TRC_GROUP_UI
|
|
#define TRC_FILE "wuiint"
|
|
#include <atrcapi.h>
|
|
|
|
#include "wui.h"
|
|
|
|
extern "C"
|
|
{
|
|
#include <aver.h>
|
|
// multi-monitor support
|
|
#ifdef OS_WINNT
|
|
#define COMPILE_MULTIMON_STUBS
|
|
#include <multimon.h>
|
|
#endif // OS_WINNT
|
|
}
|
|
|
|
//
|
|
// Cicero keyboard layout API's
|
|
//
|
|
#ifndef OS_WINCE
|
|
#include "cicsthkl.h"
|
|
#endif
|
|
|
|
#include "sl.h"
|
|
#include "aco.h"
|
|
#include "clx.h"
|
|
#include "autil.h"
|
|
|
|
//
|
|
// Internal functions
|
|
//
|
|
|
|
//
|
|
// draw a solid color rectangle quickly
|
|
//
|
|
VOID near CUI::FastRect(HDC hDC, int x, int y, int cx, int cy)
|
|
{
|
|
RECT rc;
|
|
|
|
rc.left = x;
|
|
rc.right = x+cx;
|
|
rc.top = y;
|
|
rc.bottom = y+cy;
|
|
ExtTextOut(hDC,x,y,ETO_OPAQUE,&rc,NULL,0,NULL);
|
|
}
|
|
|
|
|
|
DWORD near CUI::RGB2BGR(DWORD rgb)
|
|
{
|
|
return RGB(GetBValue(rgb),GetGValue(rgb),GetRValue(rgb));
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UIContainerWndProc
|
|
//
|
|
// Purpose: Handles messages to Container Window
|
|
//
|
|
LRESULT CALLBACK CUI::UIContainerWndProc( HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
LRESULT rc = 0;
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
|
|
DC_BEGIN_FN("UIContainerWndProc");
|
|
|
|
TRC_DBG((TB, _T("msg(%#x)"), message));
|
|
|
|
switch (message)
|
|
{
|
|
case WM_PAINT:
|
|
{
|
|
TRC_DBG((TB, _T("Container WM_PAINT")));
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
|
|
//
|
|
// Do nothing. All UI painting is done by the Main Window.
|
|
//
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
{
|
|
HWND hwndFocus;
|
|
if (_pArcUI) {
|
|
hwndFocus = _pArcUI->GetHwnd();
|
|
TRC_NRM((TB, _T("Passing focus to ARC dlg")));
|
|
SetFocus(hwndFocus);
|
|
}
|
|
else {
|
|
//
|
|
// Flag as not handled so subclass proc does the right thing
|
|
//
|
|
rc = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
rc = DefWindowProc(hwnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return rc;
|
|
} // UIContainerProc
|
|
|
|
|
|
//
|
|
// Name: UIGetMaximizedWindowSize
|
|
//
|
|
// Purpose: Calculates the size to which the main window should be
|
|
// maximized, base on the screen size and the size of window
|
|
// which would have a client area the same size as the
|
|
// container (_UI.maxMainWindowSize).
|
|
//
|
|
DCSIZE DCINTERNAL CUI::UIGetMaximizedWindowSize(DCVOID)
|
|
{
|
|
DCSIZE maximizedSize;
|
|
DCUINT xSize;
|
|
DCUINT ySize;
|
|
|
|
DC_BEGIN_FN("UIGetMaximizedWindowSize");
|
|
|
|
//
|
|
// The maximum size we set a window to is the smaller of:
|
|
// - _UI.maxMainWindowSize
|
|
// - the screen size plus twice the border width (so the borders are
|
|
// not visible).
|
|
// Always call GetSystemMetrics to get the screen size and border
|
|
// width, as these can change dynamically.
|
|
//
|
|
if(!_UI.fControlIsFullScreen)
|
|
{
|
|
xSize = _UI.controlSize.width;
|
|
ySize = _UI.controlSize.height;
|
|
}
|
|
else
|
|
{
|
|
xSize = GetSystemMetrics(SM_CXSCREEN);
|
|
ySize = GetSystemMetrics(SM_CYSCREEN);
|
|
}
|
|
|
|
#ifdef OS_WINCE
|
|
maximizedSize.width = DC_MIN(_UI.maxMainWindowSize.width,xSize);
|
|
|
|
maximizedSize.height = DC_MIN(_UI.maxMainWindowSize.height,ySize);
|
|
|
|
#else // This section NOT OS_WINCE
|
|
maximizedSize.width = DC_MIN(_UI.maxMainWindowSize.width,
|
|
xSize + (2 * GetSystemMetrics(SM_CXFRAME)));
|
|
|
|
maximizedSize.height = DC_MIN(_UI.maxMainWindowSize.height,
|
|
ySize + (2 * GetSystemMetrics(SM_CYFRAME)));
|
|
#endif // OS_WINCE
|
|
|
|
TRC_NRM((TB, _T("Main Window maxSize (%d,%d) maximizedSize (%d,%d) "),
|
|
_UI.maxMainWindowSize.width,
|
|
_UI.maxMainWindowSize.height,
|
|
maximizedSize.width,
|
|
maximizedSize.height));
|
|
|
|
DC_END_FN();
|
|
return maximizedSize;
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UIMainWndProc
|
|
//
|
|
// Purpose: Main Window event handling procedure
|
|
//
|
|
LRESULT CALLBACK CUI::UIMainWndProc( HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
LRESULT rc = 0;
|
|
RECT rect;
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
DCSIZE maximized;
|
|
|
|
DC_BEGIN_FN("UIMainWndProc");
|
|
|
|
TRC_DBG((TB, _T("msg(%#x)"), message));
|
|
|
|
switch (message)
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
TRC_DBG((TB, _T("Main window created and initializing")));
|
|
|
|
//
|
|
// Initialize states
|
|
//
|
|
UISetConnectionStatus(UI_STATUS_INITIALIZING);
|
|
|
|
|
|
TRC_DBG((TB, _T("Setting up container window size")));
|
|
|
|
//
|
|
// In WebUI, Main window is a child window of the ActiveX
|
|
// control window. A WM_SIZE message will be sent to child
|
|
// while CreatWindow. Handler for this message in WinUI is
|
|
// assuming that _UI.hWndMain is already set, but not true
|
|
// the case _UI. So Set _UI.hWndMain while creating the
|
|
// main the main window.
|
|
//
|
|
_UI.hwndMain = hwnd;
|
|
//
|
|
// Set the Container to be as large as the desk top size
|
|
// requested - but no bigger than the control size.
|
|
//
|
|
|
|
if(!_UI.fControlIsFullScreen)
|
|
{
|
|
_UI.containerSize.width =
|
|
DC_MIN(_UI.uiSizeTable[0],
|
|
_UI.controlSize.width);
|
|
|
|
_UI.containerSize.height =
|
|
DC_MIN(_UI.uiSizeTable[1],
|
|
_UI.controlSize.height);
|
|
}
|
|
else
|
|
{
|
|
_UI.containerSize.width =
|
|
DC_MIN(_UI.uiSizeTable[0],
|
|
(DCUINT)GetSystemMetrics(SM_CXSCREEN));
|
|
|
|
_UI.containerSize.height =
|
|
DC_MIN(_UI.uiSizeTable[1],
|
|
(DCUINT)GetSystemMetrics(SM_CYSCREEN));
|
|
}
|
|
|
|
UIRecalcMaxMainWindowSize();
|
|
|
|
//
|
|
// Set Container to be initially positioned at top left of
|
|
// client area
|
|
//
|
|
TRC_DBG((TB, _T("Setting scrollbars to (0,0)")));
|
|
_UI.scrollPos.x = 0;
|
|
_UI.scrollPos.y = 0;
|
|
}
|
|
break;
|
|
|
|
case WM_ACTIVATE:
|
|
{
|
|
TRC_NRM((TB, _T("WM_ACTIVATE")));
|
|
|
|
if ( (DC_GET_WM_ACTIVATE_ACTIVATION(wParam) != WA_INACTIVE) &&
|
|
(_UI.hwndContainer != NULL)) {
|
|
|
|
HWND hwndFocus = NULL;
|
|
|
|
if (_pArcUI) {
|
|
hwndFocus = _pArcUI->GetHwnd();
|
|
TRC_NRM((TB, _T("Passing focus to ARC dlg")));
|
|
|
|
}
|
|
else if (IsWindowVisible(_UI.hwndContainer)) {
|
|
hwndFocus = _UI.hwndContainer;
|
|
TRC_NRM((TB, _T("Passing focus to Container")));
|
|
}
|
|
|
|
if (hwndFocus) {
|
|
SetFocus(hwndFocus);
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
{
|
|
TRC_DBG((TB, _T("WM_KEYDOWN: %u"), wParam));
|
|
if (wParam == _UI.hotKey.fullScreen)
|
|
{
|
|
TRC_DBG((TB, _T("AXCORE Got a full screen VK")));
|
|
if ((GetKeyState(VK_MENU) & (UI_ALT_DOWN_MASK)) != 0)
|
|
{
|
|
TRC_NRM((TB,
|
|
_T("AXCORE Alt down also - Got a Screen Mode Hotkey")));
|
|
//
|
|
// Only do this if we are connected
|
|
//
|
|
if(UI_STATUS_CONNECTED == _UI.connectionStatus)
|
|
{
|
|
//
|
|
// Toggle the ctrl to/from real full screen mode
|
|
//
|
|
UI_ToggleFullScreenMode();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_INITMENUPOPUP:
|
|
{
|
|
//
|
|
// If fullscreen, disable the move item on the system menu
|
|
// we show sys menu so an ICON for the client appears in
|
|
// the taskbar
|
|
//
|
|
HMENU hSysMenu = GetSystemMenu( hwnd, FALSE);
|
|
if(hSysMenu)
|
|
{
|
|
TRC_ERR((TB,(_T("ENABLEMENUITEM....FSCREEN IS %s")),
|
|
UI_IsFullScreen() ? "TRUE" : "FALSE"));
|
|
#ifndef OS_WINCE
|
|
EnableMenuItem((HMENU)hSysMenu, SC_MOVE,
|
|
MF_GRAYED | MF_BYCOMMAND);
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
{
|
|
//
|
|
// Store the new size
|
|
//
|
|
_UI.mainWindowClientSize.width = LOWORD(lParam);
|
|
_UI.mainWindowClientSize.height = HIWORD(lParam);
|
|
|
|
if (UI_IsCoreInitialized()) {
|
|
#ifdef SMART_SIZING
|
|
UI_NotifyOfDesktopSizeChange(lParam);
|
|
#endif // SMART_SIZING
|
|
|
|
_pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
|
|
_pIh,
|
|
CD_NOTIFICATION_FUNC(CIH,IH_SetVisibleSize),
|
|
(ULONG_PTR)lParam);
|
|
}
|
|
|
|
//
|
|
// Notify the ARC dialog
|
|
//
|
|
if (_pArcUI) {
|
|
_pArcUI->OnParentSizePosChange();
|
|
}
|
|
|
|
//
|
|
// Web control is special.. it runs 'full screen' but can and
|
|
// does need to be resized
|
|
//
|
|
if(_UI.fControlIsFullScreen)
|
|
{
|
|
TRC_DBG((TB, _T("Ignoring WM_SIZE while in full-screen mode")));
|
|
DC_QUIT;
|
|
}
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
|
|
//
|
|
// We're non-fullscreen, so keep the window placement structure
|
|
// up-to-date
|
|
//
|
|
GetWindowPlacement(_UI.hwndMain, &_UI.windowPlacement);
|
|
TRC_DBG((TB, _T("Got window placement in WM_SIZE")));
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
|
|
|
|
if (wParam == SIZE_MAXIMIZED)
|
|
{
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
LockWindowUpdate(_UI.hwndMain);
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
|
|
TRC_DBG((TB, _T("Maximize")));
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
|
|
//
|
|
// Override the maximized / minimized positions with our
|
|
// hardcoded valued - required if the maximized window is
|
|
// moved.
|
|
//
|
|
UISetMinMaxPlacement();
|
|
SetWindowPlacement(_UI.hwndMain, &_UI.windowPlacement);
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
|
|
|
|
//
|
|
// We need to be accurate about the maximized window size.
|
|
// It is not possible to use _UI.maxMainWindowSize as this
|
|
// may be greater than screen size, eg server and client
|
|
// are 640x480, container is 640x480 then _UI.maxWindowSize
|
|
// (obtained via AdjustWindowRect in UIRecalcMaxMainWindow)
|
|
// is something like 648x525.
|
|
// Passing this value to SetWindowPos has results which
|
|
// vary with different shells:
|
|
// Win95/NT4.0: the resulting window is 648x488 at -4, -4,
|
|
// ie all the window, except the border, is
|
|
// on-screen
|
|
// Win31/NT3.51: the resulting window is 648x525 at -4, -4,
|
|
// ie the size passed to SetWindowPos, so
|
|
// the bottom 40 pixels are off-screen.
|
|
// To avoid such differences calculate a maximized window
|
|
// size value which takes account of both the physical
|
|
// screen size and the ideal window size.
|
|
//
|
|
UIRecalcMaxMainWindowSize();
|
|
maximized = UIGetMaximizedWindowSize();
|
|
SetWindowPos( _UI.hwndMain,
|
|
NULL,
|
|
0, 0,
|
|
maximized.width,
|
|
maximized.height,
|
|
SWP_NOZORDER | SWP_NOMOVE |
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER );
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
LockWindowUpdate(NULL);
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
}
|
|
|
|
//
|
|
// Set scrollbars correctly.
|
|
//
|
|
|
|
if (!_fRecursiveSizeMsg)
|
|
{
|
|
_fRecursiveSizeMsg = TRUE;
|
|
UIRecalculateScrollbars();
|
|
_fRecursiveSizeMsg = FALSE;
|
|
}
|
|
#ifdef DISABLE_SHADOW_IN_FULLSCREEN
|
|
// When in full-screen mode, the client workstation resolution can change
|
|
// we enable use of shadow bitmap when fullscreen window size is smallerer than desktop size
|
|
// otherwise disable the use of shadow bitmap
|
|
if(UI_IsFullScreen())
|
|
{
|
|
if ((_UI.mainWindowClientSize.width < _UI.desktopSize.width) ||
|
|
(_UI.mainWindowClientSize.height < _UI.desktopSize.height))
|
|
{
|
|
_pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT,
|
|
_pUh,
|
|
CD_NOTIFICATION_FUNC(CUH,UH_EnableShadowBitmap),
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
_pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT,
|
|
_pUh,
|
|
CD_NOTIFICATION_FUNC(CUH,UH_DisableShadowBitmap),
|
|
NULL);
|
|
}
|
|
}
|
|
#endif // DISABLE_SHADOW_IN_FULLSCREEN
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_PAINT:
|
|
{
|
|
//
|
|
// Paint the Main Window
|
|
//
|
|
TRC_DBG((TB, _T("Main Window WM_PAINT")));
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
if (hdc == NULL)
|
|
{
|
|
TRC_SYSTEM_ERROR("BeginPaint failed");
|
|
break;
|
|
}
|
|
|
|
GetClientRect(hwnd, &rect);
|
|
|
|
if ((_UI.connectionStatus == UI_STATUS_CONNECTED))
|
|
{
|
|
//
|
|
// We only paint the main window if it is bigger than the container
|
|
// window. Hierarchy is
|
|
// -Main
|
|
// -Container
|
|
// this can happen even in windowed mode if the control is
|
|
// sized bigger than the required desktop size
|
|
RECT rcContainer;
|
|
GetClientRect( _UI.hwndContainer, &rcContainer);
|
|
if( (rcContainer.right < rect.right) ||
|
|
(rcContainer.bottom < rect.bottom))
|
|
{
|
|
//
|
|
// If we're full screen the paint a black frame around
|
|
// the container..Else paint in the system background color
|
|
//
|
|
if(UI_IsFullScreen())
|
|
{
|
|
PatBlt( hdc,
|
|
rect.left,
|
|
rect.top,
|
|
rect.right - rect.left,
|
|
rect.bottom - rect.top,
|
|
BLACKNESS);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwBackColor = GetSysColor( COLOR_APPWORKSPACE);
|
|
#ifndef OS_WINCE
|
|
HBRUSH hNewBrush = CreateSolidBrush( dwBackColor);
|
|
#else
|
|
HBRUSH hNewBrush = CECreateSolidBrush( dwBackColor);
|
|
#endif
|
|
HBRUSH hOldBrush = (HBRUSH)SelectObject( hdc, hNewBrush);
|
|
|
|
Rectangle( hdc,
|
|
rect.left,
|
|
rect.top,
|
|
rect.right,
|
|
rect.bottom);
|
|
|
|
SelectObject( hdc, hOldBrush);
|
|
#ifndef OS_WINCE
|
|
DeleteObject(hNewBrush);
|
|
#else
|
|
CEDeleteBrush(hNewBrush);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
}
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
break;
|
|
|
|
case WM_VSCROLL:
|
|
{
|
|
DCINT yStart;
|
|
DCBOOL smoothScroll = FALSE;
|
|
|
|
TRC_DBG((TB, _T("Vertical scrolling")));
|
|
|
|
yStart = _UI.scrollPos.y;
|
|
|
|
//
|
|
// Deal with vertical scrolling
|
|
//
|
|
switch (DC_GET_WM_SCROLL_CODE(wParam))
|
|
{
|
|
case SB_TOP:
|
|
{
|
|
_UI.scrollPos.y = 0;
|
|
}
|
|
break;
|
|
|
|
case SB_BOTTOM:
|
|
{
|
|
_UI.scrollPos.y = _UI.scrollMax.y;
|
|
}
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
{
|
|
_UI.scrollPos.y -= UI_SCROLL_LINE_DISTANCE;
|
|
}
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
{
|
|
_UI.scrollPos.y += UI_SCROLL_LINE_DISTANCE;
|
|
}
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
{
|
|
_UI.scrollPos.y -= UI_SCROLL_VERT_PAGE_DISTANCE;
|
|
smoothScroll = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
{
|
|
_UI.scrollPos.y += UI_SCROLL_VERT_PAGE_DISTANCE;
|
|
smoothScroll = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
{
|
|
_UI.scrollPos.y =
|
|
DC_GET_WM_SCROLL_POSITION(wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case SB_ENDSCROLL:
|
|
{
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Move the Container and scrollbars appropriately
|
|
//
|
|
_UI.scrollPos.y = DC_MAX( 0,
|
|
DC_MIN(_UI.scrollPos.y, _UI.scrollMax.y) );
|
|
|
|
//
|
|
// Don't smooth scroll unless specifically configured in the
|
|
// registry.
|
|
//
|
|
if (smoothScroll && _UI.smoothScrolling)
|
|
{
|
|
DCINT y;
|
|
DCINT step;
|
|
DCUINT numSteps;
|
|
DCUINT i;
|
|
|
|
TRC_DBG((TB, _T("Smooth scroll")));
|
|
step = (_UI.scrollPos.y < yStart) ? -UI_SMOOTH_SCROLL_STEP :
|
|
UI_SMOOTH_SCROLL_STEP;
|
|
numSteps = DC_ABS(_UI.scrollPos.y - yStart) /
|
|
UI_SMOOTH_SCROLL_STEP;
|
|
for ( i = 0, y = yStart + step;
|
|
i < numSteps;
|
|
i++, y += step )
|
|
{
|
|
MoveWindow( _UI.hwndContainer,
|
|
-_UI.scrollPos.x,
|
|
-y,
|
|
_UI.containerSize.width,
|
|
_UI.containerSize.height,
|
|
TRUE );
|
|
}
|
|
}
|
|
|
|
UIMoveContainerWindow();
|
|
|
|
SetScrollPos(hwnd, SB_VERT, _UI.scrollPos.y, TRUE);
|
|
}
|
|
break;
|
|
|
|
case WM_HSCROLL:
|
|
{
|
|
DCINT xStart;
|
|
DCBOOL smoothScroll = FALSE;
|
|
|
|
TRC_DBG((TB, _T("Horizontal scrolling")));
|
|
|
|
xStart = _UI.scrollPos.x;
|
|
|
|
//
|
|
// Deal with horizontal scrolling
|
|
//
|
|
switch (DC_GET_WM_SCROLL_CODE(wParam))
|
|
{
|
|
case SB_TOP:
|
|
{
|
|
_UI.scrollPos.x = 0;
|
|
}
|
|
break;
|
|
|
|
case SB_BOTTOM:
|
|
{
|
|
_UI.scrollPos.x = _UI.scrollMax.x;
|
|
}
|
|
break;
|
|
|
|
case SB_LINELEFT:
|
|
{
|
|
_UI.scrollPos.x -= UI_SCROLL_LINE_DISTANCE;
|
|
}
|
|
break;
|
|
|
|
case SB_LINERIGHT:
|
|
{
|
|
_UI.scrollPos.x += UI_SCROLL_LINE_DISTANCE;
|
|
}
|
|
break;
|
|
|
|
case SB_PAGELEFT:
|
|
{
|
|
_UI.scrollPos.x -= UI_SCROLL_HORZ_PAGE_DISTANCE;
|
|
smoothScroll = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SB_PAGERIGHT:
|
|
{
|
|
_UI.scrollPos.x += UI_SCROLL_HORZ_PAGE_DISTANCE;
|
|
smoothScroll = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
{
|
|
_UI.scrollPos.x =
|
|
DC_GET_WM_SCROLL_POSITION(wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case SB_ENDSCROLL:
|
|
{
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Move the Container and scrollbar appropriately
|
|
//
|
|
_UI.scrollPos.x = DC_MAX( 0,
|
|
DC_MIN(_UI.scrollPos.x, _UI.scrollMax.x) );
|
|
|
|
//
|
|
// Don't smooth scroll unless specifically configured in the
|
|
// registry.
|
|
//
|
|
if (smoothScroll && _UI.smoothScrolling)
|
|
{
|
|
DCINT x;
|
|
DCINT step;
|
|
DCUINT numSteps;
|
|
DCUINT i;
|
|
|
|
TRC_DBG((TB, _T("Smooth scroll")));
|
|
step = (_UI.scrollPos.x < xStart) ? -UI_SMOOTH_SCROLL_STEP :
|
|
UI_SMOOTH_SCROLL_STEP;
|
|
numSteps = DC_ABS(_UI.scrollPos.x - xStart) /
|
|
UI_SMOOTH_SCROLL_STEP;
|
|
for ( i = 0, x = xStart + step;
|
|
i < numSteps;
|
|
i++, x += step )
|
|
{
|
|
MoveWindow( _UI.hwndContainer,
|
|
-x,
|
|
-_UI.scrollPos.y,
|
|
_UI.containerSize.width,
|
|
_UI.containerSize.height,
|
|
TRUE );
|
|
}
|
|
}
|
|
|
|
UIMoveContainerWindow();
|
|
|
|
SetScrollPos(hwnd, SB_HORZ, _UI.scrollPos.x, TRUE);
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
//
|
|
// Now switch on the command.
|
|
//
|
|
switch (DC_GET_WM_COMMAND_ID(wParam))
|
|
{
|
|
case UI_IDM_ACCELERATOR_PASSTHROUGH:
|
|
{
|
|
//
|
|
// Toggle the accelerator passthrough menu item
|
|
//
|
|
_UI.acceleratorCheckState = !_UI.acceleratorCheckState;
|
|
|
|
_pCo->CO_SetConfigurationValue( CO_CFG_ACCELERATOR_PASSTHROUGH,
|
|
_UI.acceleratorCheckState );
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_SMOOTHSCROLLING:
|
|
{
|
|
//
|
|
// Toggle the smooth scrolling setting
|
|
//
|
|
_UI.smoothScrolling = !_UI.smoothScrolling;
|
|
|
|
UISmoothScrollingSettingChanged();
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
{
|
|
//
|
|
// Do Nothing
|
|
//
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
{
|
|
rc = DefWindowProc(hwnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
{
|
|
#ifdef USE_BBAR
|
|
//
|
|
// Notify the bbar
|
|
//
|
|
if (_pBBar)
|
|
{
|
|
_pBBar->OnSysColorChange();
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
rc = DefWindowProc(hwnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
{
|
|
UI_UserRequestedClose();
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
{
|
|
TRC_DBG((TB, _T("Timer id %d"), wParam));
|
|
|
|
if (_fTerminating) {
|
|
//
|
|
// Drop any defered processing such as timer messages
|
|
// during termination
|
|
//
|
|
|
|
TRC_ERR((TB,_T("Received timer msg %d while terminating!"),
|
|
wParam));
|
|
break;
|
|
}
|
|
|
|
switch (wParam)
|
|
{
|
|
case UI_TIMER_SHUTDOWN:
|
|
{
|
|
TRC_DBG((TB, _T("Killing shutdown timer")));
|
|
KillTimer(_UI.hwndMain, _UI.shutdownTimer);
|
|
_UI.shutdownTimer = 0;
|
|
if (_UI.connectionStatus == UI_STATUS_CONNECTED)
|
|
{
|
|
//
|
|
// We've tried asking the server if we can shut
|
|
// down but it obviously hasn't responded. We need
|
|
// to be more forceful.
|
|
//
|
|
TRC_ALT((TB, _T("Shutdown timeout: forcing shutdown")));
|
|
_pCo->CO_Shutdown(CO_DISCONNECT_AND_EXIT);
|
|
}
|
|
else
|
|
{
|
|
TRC_ALT((TB, _T("Spare shutdown timeout; conn status %u"),
|
|
_UI.connectionStatus));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_TIMER_SINGLE_CONN:
|
|
{
|
|
TRC_NRM((TB, _T("Single connection timer")));
|
|
|
|
//
|
|
// We no longer need this timer.
|
|
//
|
|
|
|
if( NULL != _UI.connectStruct.hSingleConnectTimer )
|
|
{
|
|
_pUt->UTDeleteTimer( _UI.connectStruct.hSingleConnectTimer );
|
|
TRC_NRM((TB, _T("Kill single connection timer")));
|
|
_UI.connectStruct.hSingleConnectTimer = NULL;
|
|
}
|
|
else
|
|
{
|
|
TRC_ALT((TB,_T("NULL timer handle for hSingleConnectTimer")));
|
|
}
|
|
|
|
if (_UI.connectionStatus == UI_STATUS_CONNECT_PENDING)
|
|
{
|
|
TRC_ALT((TB, _T("Timeout for IP address: try next")));
|
|
|
|
_UI.disconnectReason =
|
|
UI_MAKE_DISCONNECT_ERR(UI_ERR_DISCONNECT_TIMEOUT);
|
|
|
|
//
|
|
// Next connection will be attempted on receiving
|
|
// the OnDisconnected message
|
|
//
|
|
_pCo->CO_Disconnect();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_TIMER_OVERALL_CONN:
|
|
{
|
|
TRC_NRM((TB, _T("Overall connection timer")));
|
|
|
|
if( NULL != _UI.connectStruct.hConnectionTimer )
|
|
{
|
|
_pUt->UTDeleteTimer( _UI.connectStruct.hConnectionTimer );
|
|
_UI.connectStruct.hConnectionTimer = NULL;
|
|
}
|
|
else
|
|
{
|
|
TRC_ALT((TB,_T("NULL timer handle for hConnectionTimer")));
|
|
}
|
|
|
|
if ((_UI.connectionStatus == UI_STATUS_CONNECT_PENDING) ||
|
|
(_UI.connectionStatus == UI_STATUS_CONNECT_PENDING_DNS))
|
|
{
|
|
TRC_ALT((TB, _T("Timeout for connection")));
|
|
|
|
//
|
|
// Disconnect; display the timeout dialog
|
|
//
|
|
_UI.disconnectReason =
|
|
UI_MAKE_DISCONNECT_ERR(UI_ERR_DISCONNECT_TIMEOUT);
|
|
UIInitiateDisconnection();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_TIMER_LICENSING:
|
|
{
|
|
TRC_NRM((TB, _T("Licensing timer")));
|
|
|
|
if( NULL != _UI.connectStruct.hLicensingTimer )
|
|
{
|
|
_pUt->UTDeleteTimer( _UI.connectStruct.hLicensingTimer );
|
|
_UI.connectStruct.hLicensingTimer = NULL;
|
|
}
|
|
else
|
|
{
|
|
TRC_ALT((TB,_T("NULL timer handle for hLicensingTimer")));
|
|
}
|
|
|
|
|
|
TRC_ALT((TB, _T("Timeout for connection")));
|
|
|
|
// Disconnect due to licensing timeout
|
|
_UI.disconnectReason =
|
|
UI_MAKE_DISCONNECT_ERR( UI_ERR_LICENSING_TIMEOUT );
|
|
|
|
UIInitiateDisconnection();
|
|
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Idle input notification timer
|
|
//
|
|
case UI_TIMER_IDLEINPUTTIMEOUT:
|
|
{
|
|
//If no input was received during the idle period
|
|
//then fire an event to the control. Otherwise
|
|
//queue another timer interval. This only matters
|
|
//while we are connected and the timeout is still
|
|
//active
|
|
TRC_NRM((TB,_T("Idle timeout monitoring period elapsed")));
|
|
if(UI_STATUS_CONNECTED == _UI.connectionStatus &&
|
|
UI_GetMinsToIdleTimeout())
|
|
{
|
|
if(!_pIh->IH_GetInputWasSentFlag())
|
|
{
|
|
//Disable the timer. To prevent weird re-entrancy
|
|
//problems. E.g the if the event is fired and script
|
|
//pops a message box then we will be blocked and might
|
|
//receive another timer notification and re-enter
|
|
//this code path. Prevent that by ending the timer
|
|
//before firing the notification, you get a on-shot notify.
|
|
InitInputIdleTimer(0);
|
|
|
|
//Fire event to control.
|
|
SendMessage( _UI.hWndCntrl,
|
|
WM_TS_IDLETIMEOUTNOTIFICATION, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
//Input was sent during monitoring
|
|
//interval. Queue another wait interval
|
|
TRC_ASSERT(_UI.hIdleInputTimer,
|
|
(TB,_T("_UI.hIdleInputTimer is null")));
|
|
_pIh->IH_ResetInputWasSentFlag();
|
|
if(!_pUt->UTStartTimer(_UI.hIdleInputTimer))
|
|
{
|
|
TRC_ERR((TB,_T("InitInputIdleTimer failed")));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
#ifdef USE_BBAR
|
|
case UI_TIMER_BBAR_UNHIDE_TIMERID:
|
|
{
|
|
//
|
|
// This timer elapses when the mouse has hovered
|
|
// for a set amount of time within the dbl click rectangle
|
|
// the next part of the logic determines if the current
|
|
// mouse position is within the bbar hotzone and if so
|
|
// the bbar is lowered.
|
|
//
|
|
KillTimer( hwnd, UI_TIMER_BBAR_UNHIDE_TIMERID );
|
|
TRC_NRM((TB, _T("Timer fired: UI_TIMER_BBAR_UNHIDE_TIMERID")));
|
|
if(_UI.fBBarEnabled)
|
|
{
|
|
POINT pt;
|
|
RECT rc;
|
|
|
|
_ptBBarLastMousePos.x = -0x0fff;
|
|
_ptBBarLastMousePos.y = -0x0fff;
|
|
|
|
GetCursorPos(&pt);
|
|
GetWindowRect( hwnd, &rc);
|
|
rc.bottom = rc.top + IH_BBAR_HOTZONE_HEIGHT;
|
|
//
|
|
// Figure out if the cursor was in the
|
|
// bbar hotzone when the timer elapsed
|
|
//
|
|
if (PtInRect(&rc, pt))
|
|
{
|
|
//
|
|
// Notify that the bbar hotzone timer
|
|
// has elapsed. This may trigger a lowering
|
|
// of the bbar
|
|
//
|
|
UI_OnBBarHotzoneTimerFired(NULL);
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case UI_TIMER_DISCONNECT_TIMERID:
|
|
{
|
|
TRC_NRM((TB, _T("Disconnect timer")));
|
|
|
|
TRC_ASSERT(( NULL != _UI.hDisconnectTimeout ),
|
|
(TB, _T("Unexpected NULL timer")));
|
|
|
|
if (NULL != _UI.hDisconnectTimeout)
|
|
{
|
|
_pUt->UTDeleteTimer( _UI.hDisconnectTimeout );
|
|
_UI.hDisconnectTimeout = NULL;
|
|
}
|
|
|
|
if (UI_STATUS_CONNECTED == _UI.connectionStatus)
|
|
{
|
|
//
|
|
// We've been left hanging too long in the connected
|
|
// but deactivated state
|
|
//
|
|
TRC_ALT((TB, _T("Timeout for not disconnecting in time")));
|
|
_UI.disconnectReason =
|
|
UI_MAKE_DISCONNECT_ERR( UI_ERR_DISCONNECT_TIMEOUT );
|
|
|
|
UIInitiateDisconnection();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
TRC_ABORT((TB, _T("Unexpected UI timer ID %d"), wParam));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_WSA_GETHOSTBYNAME:
|
|
{
|
|
WORD errorWSA;
|
|
|
|
//
|
|
// Drop any defered processing such as DNS lookups
|
|
// during termination
|
|
//
|
|
if (_fTerminating) {
|
|
TRC_ERR((TB, _T("Ignoring UI_WSA_GETHOSTBYNAME during termination")));
|
|
break;
|
|
}
|
|
|
|
TRC_NRM((TB, _T("Got the host address list")));
|
|
|
|
//
|
|
// We've observed some cases in stress where there can be a pending
|
|
// WSA_GETHOSTBYNAME message that gets processed after we disconnect
|
|
// and delete the _pHostData. If that is the case just drop the message
|
|
//
|
|
if (!_pHostData) {
|
|
TRC_ERR((TB,_T("_pHostData is NULL, ignoring UI_WSA_GETHOSTBYNAME")));
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// We've received the result of a WSAAsyncGetHostByName
|
|
// operation. Split the message apart and call the FSM.
|
|
//
|
|
errorWSA = WSAGETASYNCERROR(lParam);
|
|
|
|
if (errorWSA != 0)
|
|
{
|
|
TRC_NRM((TB, _T("GHBN failed:%hu. Trying inet_addr(%s)"),
|
|
errorWSA, _UI.ansiAddress));
|
|
|
|
_UI.hostAddress = inet_addr(_UI.ansiAddress);
|
|
if (_UI.hostAddress != INADDR_NONE)
|
|
{
|
|
//
|
|
// Great, we have an IP address.
|
|
//
|
|
TRC_NRM((TB, _T("%s looks like an IP address:%#lx"),
|
|
_UI.ansiAddress,
|
|
_UI.hostAddress));
|
|
|
|
UITryNextConnection();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Didn't recognise the address. Disconnect and
|
|
// indicate the error event.
|
|
//
|
|
TRC_ALT((TB, _T("GHBN (%hu) and inet_addr() both failed"),
|
|
errorWSA));
|
|
|
|
//
|
|
// Yet another case where we are sure that
|
|
// we are now done with the winsock lookup
|
|
// buffer and can free it.
|
|
//
|
|
if(_pHostData)
|
|
{
|
|
LocalFree(_pHostData);
|
|
_pHostData = NULL;
|
|
}
|
|
UIInitiateDisconnection();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If there are no addresses to try, display the 'bad
|
|
// server name' error.
|
|
//
|
|
UITryNextConnection();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_DESKTOPSIZECHANGE:
|
|
{
|
|
DCUINT visibleScrollBars;
|
|
DCSIZE windowSize;
|
|
DCSIZE newSize;
|
|
#ifndef OS_WINCE
|
|
DCSIZE screenSize;
|
|
#endif
|
|
|
|
#ifdef OS_WINNT
|
|
HMONITOR hMonitor;
|
|
MONITORINFO monInfo;
|
|
RECT screenRect;
|
|
#endif
|
|
|
|
//
|
|
// Handle client window resizing on connection
|
|
//
|
|
newSize.width = LOWORD(lParam);
|
|
newSize.height = HIWORD(lParam);
|
|
TRC_NRM((TB, _T("Got new window size %d x %d"), newSize.width,
|
|
newSize.height ));
|
|
|
|
//
|
|
// Before we do anything with the new size, see if we are
|
|
// currently showing scroll bars.
|
|
//
|
|
GetWindowRect(_UI.hwndMain, &rect);
|
|
windowSize.width = rect.right - rect.left;
|
|
windowSize.height = rect.bottom - rect.top;
|
|
|
|
visibleScrollBars = UICalculateVisibleScrollBars(windowSize.width,
|
|
windowSize.height);
|
|
|
|
//
|
|
// Now update the size of the desktop container
|
|
//
|
|
_UI.containerSize.width = newSize.width;
|
|
_UI.containerSize.height = newSize.height;
|
|
|
|
//
|
|
// Recalculate the new Main Window max size from the new
|
|
// Container Window size
|
|
//
|
|
UIRecalcMaxMainWindowSize();
|
|
|
|
//
|
|
// And resize the container window
|
|
//
|
|
SetWindowPos( _UI.hwndContainer,
|
|
NULL,
|
|
0, 0,
|
|
_UI.containerSize.width,
|
|
_UI.containerSize.height,
|
|
SWP_NOZORDER | SWP_NOMOVE |
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER );
|
|
|
|
#ifndef OS_WINCE
|
|
//
|
|
// Do we need to adjust the window size? Only if
|
|
// 1. we're not in full screen mode
|
|
// 2. we're not maximized
|
|
// 3. we were showing all of the old desktop (ie we had no
|
|
// scroll bars showing
|
|
//
|
|
if (((GetWindowLong(_UI.hwndMain,GWL_STYLE) & WS_MAXIMIZE) == 0) &&
|
|
(visibleScrollBars == 0))
|
|
{
|
|
TRC_NRM((TB, _T("Adjusting window size...")));
|
|
//
|
|
// We adjust the window to display the new desktop size,
|
|
// ensuring that it still fits on the screen. First, find
|
|
// out how big the screen is!
|
|
//
|
|
screenSize.width = GetSystemMetrics(SM_CXSCREEN);
|
|
screenSize.height = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
if(_UI.fControlIsFullScreen)
|
|
{
|
|
#ifdef OS_WINNT
|
|
//
|
|
// For multi monitor systems, we need to find out which
|
|
// monitor the client window is on, and then get the screen
|
|
// size of that monitor
|
|
//
|
|
if (GetSystemMetrics(SM_CMONITORS))
|
|
{
|
|
hMonitor = MonitorFromWindow(_UI.hWndCntrl,
|
|
MONITOR_DEFAULTTONULL);
|
|
if (hMonitor != NULL)
|
|
{
|
|
monInfo.cbSize = sizeof(MONITORINFO);
|
|
if (GetMonitorInfo(hMonitor, &monInfo))
|
|
{
|
|
screenRect = monInfo.rcMonitor;
|
|
screenSize.width = screenRect.right
|
|
- screenRect.left;
|
|
screenSize.height = screenRect.bottom
|
|
- screenRect.top;
|
|
}
|
|
}
|
|
}
|
|
#endif // OS_WINNT
|
|
} // (_UI.fControlIsFullScreen)
|
|
|
|
//
|
|
// Now limit the window size to fit on the screen
|
|
//
|
|
windowSize.width = DC_MIN(_UI.maxMainWindowSize.width,
|
|
screenSize.width);
|
|
windowSize.height = DC_MIN(_UI.maxMainWindowSize.height,
|
|
screenSize.height);
|
|
|
|
SetWindowPos( _UI.hwndMain,
|
|
NULL,
|
|
0, 0,
|
|
windowSize.width,
|
|
windowSize.height,
|
|
SWP_NOZORDER | SWP_NOMOVE |
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER );
|
|
}
|
|
#endif // ndef OS_WINCE
|
|
|
|
//
|
|
// Update the scroll bar settings
|
|
//
|
|
UIRecalculateScrollbars();
|
|
}
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
{
|
|
#ifdef USE_BBAR
|
|
if (UI_IsFullScreen())
|
|
{
|
|
POINT pt;
|
|
GetCursorPos(&pt);
|
|
UISetBBarUnhideTimer( pt.x, pt.y );
|
|
}
|
|
else
|
|
{
|
|
if(_fBBarUnhideTimerActive)
|
|
{
|
|
KillTimer( _UI.hwndMain,
|
|
UI_TIMER_BBAR_UNHIDE_TIMERID );
|
|
_fBBarUnhideTimerActive = FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
// Pass the message on to windows otherwise
|
|
// we get problems with cursors not getting updated
|
|
// over scrollbars
|
|
//
|
|
rc = DefWindowProc(hwnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
rc = DefWindowProc(hwnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return rc;
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UIRecalcMaxMainWindowSize
|
|
//
|
|
// Purpose: Recalculates _UI.maxMainWindowSize given the current Container
|
|
// size and frame style. The maximum main window size is the
|
|
// size of window needed such that the client area is the same
|
|
// size as the container.
|
|
//
|
|
DCVOID DCINTERNAL CUI::UIRecalcMaxMainWindowSize(DCVOID)
|
|
{
|
|
DCSIZE screenSize;
|
|
#ifndef OS_WINCE
|
|
RECT rect;
|
|
#ifdef OS_WIN32
|
|
BOOL errorRc;
|
|
#endif
|
|
#endif
|
|
RECT rcWebCtrl;
|
|
|
|
DC_BEGIN_FN("UIRecalcMaxMainWindowSize");
|
|
|
|
//
|
|
// Get the screen size - this can change, so do it every time we need
|
|
// it.
|
|
//
|
|
if(!_UI.fControlIsFullScreen)
|
|
{
|
|
GetClientRect( _UI.hWndCntrl, &rcWebCtrl);
|
|
screenSize.width = rcWebCtrl.right - rcWebCtrl.left;
|
|
screenSize.height = rcWebCtrl.bottom - rcWebCtrl.top;
|
|
}
|
|
else
|
|
{
|
|
screenSize.width = GetSystemMetrics(SM_CXSCREEN);
|
|
screenSize.height = GetSystemMetrics(SM_CYSCREEN);
|
|
}
|
|
|
|
TRC_NRM((TB, _T("ActiveX control maxSize (%d,%d)"),
|
|
screenSize.width,
|
|
screenSize.height));
|
|
|
|
//
|
|
// If current mode is full screen, then the maximum window size is the
|
|
// same as the screen size - unless the container is larger still,
|
|
// which is possible if we're shadowing a session larger than
|
|
// ourselves.
|
|
//
|
|
// In this case, or if the current mode is not full screen then we want
|
|
// the size of window which is required for a client area of the size
|
|
// of the container. Passing the container size to AdjustWindowRect
|
|
// returns this window size. Such a window may be bigger than the
|
|
// screen, eg server and client are 640x480, container is 640x480.
|
|
// AdjustWindowRect adds on the border, title bar and menu sizes and
|
|
// returns something like 648x525. So, _UI.maxMainWindowSize can only
|
|
// match the actual window size when the client screen is bigger than
|
|
// the server screen or when operating in full screen mode. This means
|
|
// that _UI.maxMainWindowSize should *never* be used to set the window
|
|
// size, eg by passing it to SetWindowPos. It can be used to determine
|
|
// whether scroll bars are required, ie they are needed if the current
|
|
// window size is less than _UI.maxMainWindowSize (in other words,
|
|
// always unless in full screen mode or client screen is larger than
|
|
// server screen).
|
|
//
|
|
// To set the window size, calculate a value based on:
|
|
// - the desired window size given the container size
|
|
// - the size of the client screen.
|
|
//
|
|
|
|
#ifndef OS_WINCE
|
|
if ( _UI.fControlIsFullScreen && (
|
|
(_UI.containerSize.width > screenSize.width) ||
|
|
(_UI.containerSize.height > screenSize.height)))
|
|
{
|
|
//
|
|
// Recalc window size based on container
|
|
//
|
|
rect.left = 0;
|
|
rect.right = _UI.containerSize.width;
|
|
rect.top = 0;
|
|
rect.bottom = _UI.containerSize.height;
|
|
|
|
#ifdef OS_WIN32
|
|
errorRc = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
|
TRC_ASSERT((errorRc != 0), (TB, _T("AdjustWindowRect failed")));
|
|
#else
|
|
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
|
#endif
|
|
|
|
_UI.maxMainWindowSize.width = rect.right - rect.left;
|
|
_UI.maxMainWindowSize.height = rect.bottom - rect.top;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
//
|
|
// Window size is simply the whole screen
|
|
//
|
|
_UI.maxMainWindowSize.width = screenSize.width;
|
|
_UI.maxMainWindowSize.height = screenSize.height;
|
|
}
|
|
TRC_NRM((TB, _T("Main Window maxSize (%d,%d)"),
|
|
_UI.maxMainWindowSize.width,
|
|
_UI.maxMainWindowSize.height));
|
|
|
|
DC_END_FN();
|
|
} // UIRecalcMaxMainWindowSize
|
|
|
|
|
|
//
|
|
// Name: UIConnectWithCurrentParams
|
|
//
|
|
// Purpose: To connect to the host with the current set of parameters and
|
|
// tidy up the main window and container sizes
|
|
//
|
|
DCVOID DCINTERNAL CUI::UIConnectWithCurrentParams(CONNECTIONMODE connMode)
|
|
{
|
|
DCUINT timeout;
|
|
int screenBpp;
|
|
UINT screenColorDepthID;
|
|
HRESULT hr;
|
|
|
|
DC_BEGIN_FN("UIConnectWithCurrentParams");
|
|
|
|
TRC_DBG((TB, _T("UIConnectWithCurrentParams called")));
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
//
|
|
// If we're autoreconnecting and were connected to a cluster replace
|
|
// the server name with the actual IP as we need to hit the same
|
|
// server we were connected to.
|
|
//
|
|
if (UI_IsClientRedirected() &&
|
|
UI_IsAutoReconnecting() &&
|
|
_UI.RedirectionServerAddress[0]
|
|
) {
|
|
TRC_NRM((TB,_T("ARC SD redirect target from %s to %s"),
|
|
_UI.strAddress,
|
|
_UI.RedirectionServerAddress
|
|
));
|
|
hr = StringCchCopy(_UI.strAddress,
|
|
SIZE_TCHARS(_UI.strAddress),
|
|
_UI.RedirectionServerAddress);
|
|
if (FAILED(hr)) {
|
|
TRC_ERR((TB,_T("StringCchCopy for strAddress failed: 0x%x"),hr));
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Set connect watch flag to correctly handle connects
|
|
// that are called in OnDisconnected event handlers
|
|
//
|
|
_UI.fConnectCalledWatch = TRUE;
|
|
|
|
if( connMode != CONNECTIONMODE_INITIATE &&
|
|
connMode != CONNECTIONMODE_CONNECTEDENDPOINT )
|
|
{
|
|
//
|
|
// Invalid connection mode.
|
|
//
|
|
TRC_ERR((TB, _T("Invalid connect mode %d"), connMode));
|
|
_UI.disconnectReason =
|
|
UI_MAKE_DISCONNECT_ERR(UI_ERR_UNEXPECTED_DISCONNECT);
|
|
UIInitiateDisconnection();
|
|
DC_QUIT;
|
|
}
|
|
|
|
//
|
|
// Get x and y ContainerSizes, relies on ordering of desktop size IDs
|
|
//
|
|
_UI.containerSize.width = _UI.uiSizeTable[0];
|
|
_UI.containerSize.height = _UI.uiSizeTable[1];
|
|
|
|
_UI.connectStruct.desktopWidth = (DCUINT16)_UI.containerSize.width;
|
|
_UI.connectStruct.desktopHeight = (DCUINT16)_UI.containerSize.height;
|
|
|
|
//
|
|
// Recalculate the new Main Window max size from the new Container
|
|
// Window size
|
|
//
|
|
UIRecalcMaxMainWindowSize();
|
|
|
|
//
|
|
// Resize the Container Window (but leave it invisible - it will
|
|
// be shown when the connection is made).
|
|
//
|
|
SetWindowPos( _UI.hwndContainer,
|
|
NULL,
|
|
0, 0,
|
|
_UI.containerSize.width,
|
|
_UI.containerSize.height,
|
|
SWP_NOZORDER | SWP_NOMOVE |
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER );
|
|
|
|
TRC_DBG((TB, _T("Filling a connect struct")));
|
|
|
|
screenBpp = UI_GetScreenBpp();
|
|
screenColorDepthID = (UINT)UI_BppToColorDepthID(screenBpp);
|
|
if(screenColorDepthID < _UI.colorDepthID)
|
|
{
|
|
TRC_NRM((TB,_T("Lowering color depth to match screen (from %d to %d)"),
|
|
_UI.colorDepthID, screenColorDepthID));
|
|
_UI.colorDepthID = screenColorDepthID;
|
|
}
|
|
|
|
_UI.connectStruct.colorDepthID = _UI.colorDepthID;
|
|
_UI.connectStruct.transportType = _UI.transportType;
|
|
_UI.connectStruct.sasSequence = _UI.sasSequence;
|
|
|
|
//
|
|
// Read the keyboard layout
|
|
//
|
|
_UI.connectStruct.keyboardLayout = UIGetKeyboardLayout();
|
|
TRC_NRM((TB, _T("keyboard layout %#lx"), _UI.connectStruct.keyboardLayout));
|
|
|
|
//
|
|
// Read the keyboard type.
|
|
// GetKeyboardType(0) is returned keyboard type.
|
|
// GetKeyboardType(1) is returned sub keyboard type.
|
|
// GetKeyboardType(2) is returned number of function keys.
|
|
//
|
|
#if !defined(OS_WINCE)
|
|
_UI.connectStruct.keyboardType = GetKeyboardType(0);
|
|
_UI.connectStruct.keyboardSubType = GetKeyboardType(1);
|
|
_UI.connectStruct.keyboardFunctionKey = GetKeyboardType(2);
|
|
if (_pUt->UT_IsNEC98platform())
|
|
{
|
|
if (UI_GetOsMinorType() == TS_OSMINORTYPE_WINDOWS_95 ||
|
|
UI_GetOsMinorType() == TS_OSMINORTYPE_WINDOWS_31X)
|
|
{
|
|
/*
|
|
* Hiword of "1" is a magic number for handling NEC PC-98 Win9x
|
|
* keyboard layout on the Hydra server.
|
|
*/
|
|
_UI.connectStruct.keyboardSubType = MAKELONG(
|
|
_UI.connectStruct.keyboardSubType, 1);
|
|
}
|
|
else if (UI_GetOsMinorType() == TS_OSMINORTYPE_WINDOWS_NT)
|
|
{
|
|
OSVERSIONINFO osVersionInfo;
|
|
BOOL bRc;
|
|
|
|
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
|
|
bRc = GetVersionEx(&osVersionInfo);
|
|
if (osVersionInfo.dwMajorVersion >= 5)
|
|
{
|
|
/*
|
|
* Hiword of "2" is a magic number for handling NEC PC-98 NT5
|
|
* keyboard layout on the Hydra server.
|
|
*/
|
|
_UI.connectStruct.keyboardSubType = MAKELONG(
|
|
_UI.connectStruct.keyboardSubType, 2);
|
|
}
|
|
}
|
|
}
|
|
else if (_pUt->UT_IsNew106Layout())
|
|
{
|
|
/*
|
|
* Hiword of "1" is a magic number for handling 106 keyboard layout
|
|
* on the Hydra server.
|
|
* Because, Old 106 and New one has the same sub keyboard type.
|
|
*/
|
|
_UI.connectStruct.keyboardSubType = MAKELONG(_UI.connectStruct.keyboardSubType, 1);
|
|
}
|
|
else if (_pUt->UT_IsFujitsuLayout())
|
|
{
|
|
/*
|
|
* Hiword of "2" is a magic number for handling Fujitsu keyboard layout
|
|
* on the Hydra server.
|
|
*/
|
|
_UI.connectStruct.keyboardSubType = MAKELONG(_UI.connectStruct.keyboardSubType, 2);
|
|
}
|
|
#else // !defined(OS_WINCE)
|
|
//
|
|
// WinCE doesn't have GetKeyboardType API.
|
|
// Read the keyboard type/subtype/function keys from values set by
|
|
// control properties
|
|
//
|
|
|
|
_UI.connectStruct.keyboardType = _UI.winceKeyboardType;
|
|
_UI.connectStruct.keyboardSubType = _UI.winceKeyboardSubType;
|
|
_UI.connectStruct.keyboardFunctionKey = _UI.winceKeyboardFunctionKey;
|
|
|
|
#endif // !defined(OS_WINCE)
|
|
TRC_NRM((TB, _T("keyboard type %#lx sub type %#lx func key %#lx"),
|
|
_UI.connectStruct.keyboardType,
|
|
_UI.connectStruct.keyboardSubType,
|
|
_UI.connectStruct.keyboardFunctionKey));
|
|
|
|
|
|
//
|
|
// Read the IME file name.
|
|
//
|
|
UIGetIMEFileName(_UI.connectStruct.imeFileName,
|
|
sizeof(_UI.connectStruct.imeFileName) / sizeof(TCHAR));
|
|
TRC_NRM((TB, _T("IME file name %s"), _UI.connectStruct.imeFileName));
|
|
|
|
//
|
|
// The shadow bitmap flag should already be set.
|
|
// Set the dedicated termianl flag.
|
|
// Then copy the connect flags.
|
|
//
|
|
if (_UI.dedicatedTerminal)
|
|
{
|
|
SET_FLAG(_UI.connectFlags, CO_CONN_FLAG_DEDICATED_TERMINAL);
|
|
}
|
|
else
|
|
{
|
|
CLEAR_FLAG(_UI.connectFlags, CO_CONN_FLAG_DEDICATED_TERMINAL);
|
|
}
|
|
|
|
_UI.connectStruct.connectFlags = _UI.connectFlags;
|
|
|
|
|
|
//
|
|
// And start a connection timeout timer. If one is already running
|
|
// (from a prevous attempt) then restart it.
|
|
//
|
|
|
|
if( _UI.connectStruct.hConnectionTimer )
|
|
{
|
|
_pUt->UTStopTimer( _UI.connectStruct.hConnectionTimer );
|
|
}
|
|
|
|
TRC_NRM((TB, _T("Single connection timeout %u seconds"), _UI.singleTimeout));
|
|
|
|
//
|
|
// Set the licensing phase timeout
|
|
//
|
|
|
|
_UI.licensingTimeout = DEFAULT_LICENSING_TIMEOUT;
|
|
|
|
TRC_NRM((TB, _T("Licensing timeout %u seconds"), _UI.licensingTimeout));
|
|
|
|
UI_SetConnectionMode( connMode );
|
|
|
|
if( connMode == CONNECTIONMODE_INITIATE )
|
|
{
|
|
UISetConnectionStatus(UI_STATUS_CONNECT_PENDING_DNS);
|
|
|
|
timeout = _UI.connectionTimeOut;
|
|
|
|
TRC_NRM((TB, _T("Connection timeout %d seconds"), timeout));
|
|
|
|
if( NULL == _UI.connectStruct.hConnectionTimer )
|
|
{
|
|
_UI.connectStruct.hConnectionTimer = _pUt->UTCreateTimer(
|
|
_UI.hwndMain,
|
|
UI_TIMER_OVERALL_CONN,
|
|
timeout * 1000 );
|
|
}
|
|
|
|
if( NULL == _UI.connectStruct.hConnectionTimer )
|
|
{
|
|
//
|
|
// Cannot connect without a timeout - fail with an error
|
|
//
|
|
TRC_ERR((TB, _T("Failed to create connection timeout timer")));
|
|
_UI.disconnectReason = UI_MAKE_DISCONNECT_ERR(UI_ERR_NOTIMER);
|
|
UIInitiateDisconnection();
|
|
DC_QUIT;
|
|
}
|
|
|
|
if( FALSE == _pUt->UTStartTimer( _UI.connectStruct.hConnectionTimer ) )
|
|
{
|
|
//
|
|
// Cannot connect without a timeout - fail with an error
|
|
//
|
|
TRC_ERR((TB, _T("Failed to start connection timeout timer")));
|
|
_UI.disconnectReason = UI_MAKE_DISCONNECT_ERR(UI_ERR_NOTIMER);
|
|
UIInitiateDisconnection();
|
|
DC_QUIT;
|
|
}
|
|
|
|
_UI.connectStruct.bInitiateConnect = TRUE;
|
|
UIStartDNSLookup();
|
|
}
|
|
else
|
|
{
|
|
// A new state is necessary so when disconnect come in, it won't
|
|
// triggle CUI::UI_OnDisconnected()'s UITryNextConnection()
|
|
// code path.
|
|
UISetConnectionStatus(UI_STATUS_PENDING_CONNECTENDPOINT);
|
|
|
|
// socket already connected, start various timer
|
|
if( NULL == _UI.connectStruct.hSingleConnectTimer )
|
|
{
|
|
_UI.connectStruct.hSingleConnectTimer =
|
|
_pUt->UTCreateTimer(_UI.hwndMain,
|
|
UI_TIMER_SINGLE_CONN,
|
|
_UI.singleTimeout * 1000 );
|
|
}
|
|
|
|
if( NULL == _UI.connectStruct.hSingleConnectTimer )
|
|
{
|
|
TRC_ERR(
|
|
(TB, _T("Failed to create single connection timeout timer")));
|
|
|
|
_UI.disconnectReason = UI_MAKE_DISCONNECT_ERR(UI_ERR_NOTIMER);
|
|
UIInitiateDisconnection();
|
|
DC_QUIT;
|
|
}
|
|
|
|
if( NULL == _UI.connectStruct.hLicensingTimer )
|
|
{
|
|
_UI.connectStruct.hLicensingTimer =
|
|
_pUt->UTCreateTimer(_UI.hwndMain,
|
|
UI_TIMER_LICENSING,
|
|
_UI.licensingTimeout * 1000 );
|
|
}
|
|
|
|
if( NULL == _UI.connectStruct.hLicensingTimer )
|
|
{
|
|
TRC_ERR((TB, _T("Failed to create licensing timeout timer")));
|
|
_UI.disconnectReason = UI_MAKE_DISCONNECT_ERR(UI_ERR_NOTIMER);
|
|
UIInitiateDisconnection();
|
|
DC_QUIT;
|
|
}
|
|
|
|
_UI.connectStruct.bInitiateConnect = FALSE;
|
|
UIStartConnectWithConnectedEndpoint();
|
|
}
|
|
|
|
//Notify the Ax control that we are connecting
|
|
TRC_DBG((TB, _T("Connecting...")));
|
|
SendMessage( _UI.hWndCntrl, WM_TS_CONNECTING, 0, 0);
|
|
|
|
DC_EXIT_POINT:
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
DC_END_FN();
|
|
} // UIConnectWithCurrentParams
|
|
|
|
|
|
//
|
|
// Name: UICalculateVisibleScrollBars
|
|
//
|
|
// Purpose: Calculates whether scrollbars are needed
|
|
//
|
|
// Returns: DCUINT containing flags whether or not the vertical and
|
|
// horizontal scrollbars are needed
|
|
//
|
|
// Params: IN - width and height of frame
|
|
//
|
|
DCUINT DCINTERNAL CUI::UICalculateVisibleScrollBars( DCUINT mainFrameWidth,
|
|
DCUINT mainFrameHeight )
|
|
{
|
|
DCUINT rc;
|
|
DCSIZE screenSize;
|
|
#ifndef OS_WINCE
|
|
RECT rect;
|
|
BOOL errorRc;
|
|
#endif
|
|
|
|
|
|
#ifdef OS_WINNT
|
|
HMONITOR hMonitor;
|
|
MONITORINFO monInfo;
|
|
#endif // OS_WINNT
|
|
|
|
DC_BEGIN_FN("UICalculateVisibleScrollBars");
|
|
|
|
// for multi monitor, need to find which monitor the client window
|
|
// resides, then get the correct screen size of the corresponding
|
|
// monitor
|
|
|
|
// default screen size
|
|
screenSize.height = _UI.containerSize.height;
|
|
screenSize.width = _UI.containerSize.width;
|
|
|
|
if(_UI.fControlIsFullScreen)
|
|
{
|
|
#ifdef OS_WINNT
|
|
if (GetSystemMetrics(SM_CMONITORS)) {
|
|
hMonitor = MonitorFromWindow(_UI.hWndCntrl, MONITOR_DEFAULTTONULL);
|
|
if (hMonitor != NULL) {
|
|
monInfo.cbSize = sizeof(MONITORINFO);
|
|
if (GetMonitorInfo(hMonitor, &monInfo)) {
|
|
screenSize.height = max(screenSize.height,
|
|
(unsigned)(monInfo.rcMonitor.bottom - monInfo.rcMonitor.top));
|
|
screenSize.width = max(screenSize.width,
|
|
(unsigned)(monInfo.rcMonitor.right - monInfo.rcMonitor.left));
|
|
}
|
|
}
|
|
}
|
|
#endif // OS_WINNT
|
|
} // (_UI.fControlIsFullScreen)
|
|
|
|
TRC_DBG((TB, _T("mainFrameWidth = %d"), mainFrameWidth));
|
|
TRC_DBG((TB, _T("mainFrameHeight = %d"), mainFrameHeight));
|
|
|
|
TRC_DBG((TB, _T("ScreenSize.width = %d"), screenSize.width));
|
|
TRC_DBG((TB, _T("ScreenSize.height = %d"), screenSize.height));
|
|
|
|
//
|
|
// Calculate the neccessity for the scrollbars
|
|
//
|
|
#ifdef SMART_SIZING
|
|
if (_UI.fSmartSizing) {
|
|
rc = UI_NO_SCROLLBARS;
|
|
}
|
|
else
|
|
#endif // SMART_SIZING
|
|
if ( (mainFrameWidth >= screenSize.width) &&
|
|
(mainFrameHeight >= screenSize.height) )
|
|
{
|
|
rc = UI_NO_SCROLLBARS;
|
|
}
|
|
else if ( (mainFrameWidth < screenSize.width) &&
|
|
(mainFrameHeight >=
|
|
(screenSize.height + GetSystemMetrics(SM_CYHSCROLL))) )
|
|
{
|
|
rc = UI_BOTTOM_SCROLLBAR;
|
|
}
|
|
else if ( (mainFrameHeight < screenSize.height) &&
|
|
(mainFrameWidth >=
|
|
(screenSize.width + GetSystemMetrics(SM_CXVSCROLL))) )
|
|
{
|
|
rc = UI_RIGHT_SCROLLBAR;
|
|
}
|
|
else
|
|
{
|
|
rc = UI_BOTH_SCROLLBARS;
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
//
|
|
// Check specifically for a main window size that corresponds to a
|
|
// zero-height client area. This special case requires that we disable
|
|
// the right-hand scrollbar, because GetClientArea returns values that
|
|
// indicate it is disabled.
|
|
//
|
|
rect.left = 0;
|
|
rect.right = _UI.containerSize.width;
|
|
rect.top = 0;
|
|
rect.bottom = 0;
|
|
|
|
#ifdef OS_WIN32
|
|
errorRc =
|
|
#endif
|
|
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
|
|
|
#ifdef OS_WIN32
|
|
TRC_ASSERT((errorRc != 0), (TB, _T("AdjustWindowRect failed")));
|
|
#endif
|
|
|
|
TRC_DBG((TB, _T("Zero-height client area => main window height %d"),
|
|
rect.bottom - rect.top));
|
|
|
|
if (mainFrameHeight == (DCUINT)(rect.bottom - rect.top))
|
|
{
|
|
//
|
|
// The client size is zero height - turn off the right scrollbar
|
|
//
|
|
rc &= ~(DCUINT)UI_RIGHT_SCROLLBAR;
|
|
}
|
|
#endif //OS_WINCE
|
|
|
|
DC_END_FN();
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// Name: UIRecalculateScrollbars
|
|
//
|
|
// Purpose: Calculates where to position the Container window within the
|
|
// Main Window
|
|
//
|
|
DCVOID DCINTERNAL CUI::UIRecalculateScrollbars(DCVOID)
|
|
{
|
|
RECT rect;
|
|
RECT clientRect;
|
|
DCBOOL horzScrollBarIsVisible = TRUE;
|
|
DCBOOL vertScrollBarIsVisible = TRUE;
|
|
SCROLLINFO scrollInfo;
|
|
DCSIZE windowSize;
|
|
DCSIZE clientSize;
|
|
DCBOOL needMove = FALSE;
|
|
DCUINT visibleScrollBars;
|
|
#ifdef OS_WINCE
|
|
DCUINT32 style;
|
|
#endif // OS_WINCE
|
|
|
|
DC_BEGIN_FN("UIRecalculateScrollbars");
|
|
|
|
//
|
|
// Get the dimensions of the window. Use this to determine the need
|
|
// for scrolling, rather than using the client rect, as it is constant
|
|
// for a given window size (obviously) while the client area varies as
|
|
// scroll bars appear and disappear. We can use the window size since
|
|
// we previously calculated the window size needed to accomodate the
|
|
// entire container (this is the _UI.maxMainWindowSize). If the current
|
|
// window size is less than _UI.maxMainWindowSize we know that the
|
|
// client area is less than the container size and scroll bars are
|
|
// needed.
|
|
//
|
|
GetWindowRect(_UI.hwndMain, &rect);
|
|
windowSize.width = rect.right - rect.left;
|
|
windowSize.height = rect.bottom - rect.top;
|
|
|
|
if(_UI.fControlIsFullScreen)
|
|
{
|
|
windowSize.width = DC_MIN(windowSize.width,
|
|
(DCUINT)GetSystemMetrics(SM_CXSCREEN));
|
|
windowSize.height = DC_MIN(windowSize.height,
|
|
(DCUINT)GetSystemMetrics(SM_CYSCREEN));
|
|
}
|
|
|
|
//
|
|
// First establish whether scrollbars are needed
|
|
//
|
|
visibleScrollBars = UICalculateVisibleScrollBars(windowSize.width,
|
|
windowSize.height);
|
|
#ifdef OS_WINCE
|
|
//
|
|
// ShowScrollBar is unsupported in WinCE - instead, set the window
|
|
// styles ourself
|
|
//
|
|
style = GetWindowLong( _UI.hwndMain,
|
|
GWL_STYLE );
|
|
|
|
if (visibleScrollBars & UI_BOTTOM_SCROLLBAR)
|
|
{
|
|
style |= WS_HSCROLL;
|
|
}
|
|
else
|
|
{
|
|
style &= ~WS_HSCROLL;
|
|
}
|
|
|
|
if (visibleScrollBars & UI_RIGHT_SCROLLBAR)
|
|
{
|
|
style |= WS_VSCROLL;
|
|
}
|
|
else
|
|
{
|
|
style &= ~WS_VSCROLL;
|
|
}
|
|
|
|
SetWindowLong( _UI.hwndMain,
|
|
GWL_STYLE,
|
|
style );
|
|
|
|
#else
|
|
|
|
_UI.fHorizontalScrollBarVisible = ((visibleScrollBars & UI_BOTTOM_SCROLLBAR) != 0) ?
|
|
TRUE : FALSE;
|
|
ShowScrollBar( _UI.hwndMain,
|
|
SB_HORZ,
|
|
_UI.fHorizontalScrollBarVisible);
|
|
|
|
_UI.fVerticalScrollBarVisible = ((visibleScrollBars & UI_RIGHT_SCROLLBAR) != 0) ?
|
|
TRUE : FALSE;
|
|
ShowScrollBar( _UI.hwndMain,
|
|
SB_VERT,
|
|
_UI.fVerticalScrollBarVisible);
|
|
|
|
#endif // OS_WINCE
|
|
|
|
//
|
|
// Get the client area width and height
|
|
//
|
|
GetClientRect(_UI.hwndMain, &clientRect);
|
|
|
|
clientSize.width = clientRect.right - clientRect.left;
|
|
clientSize.height = clientRect.bottom - clientRect.top;
|
|
|
|
TRC_DBG((TB, _T("Window rect %d,%d %d,%d"), rect.left,
|
|
rect.top,
|
|
rect.right,
|
|
rect.bottom));
|
|
TRC_DBG((TB, _T("Client:= width %d, height %d"),
|
|
clientSize.width, clientSize.height));
|
|
TRC_DBG((TB, _T("Container:= width %d, height %d"),
|
|
_UI.containerSize.width, _UI.containerSize.height));
|
|
_UI.scrollMax.x = _UI.containerSize.width - clientSize.width;
|
|
_UI.scrollMax.y = _UI.containerSize.height - clientSize.height;
|
|
|
|
TRC_NRM((TB, _T("scrollMax (%d,%d)"), _UI.scrollMax.x, _UI.scrollMax.y));
|
|
|
|
//
|
|
// If the Container is larger than the client, adjust the scrollbars
|
|
// appropriately
|
|
//
|
|
if (clientSize.width <= _UI.containerSize.width) {
|
|
if (_UI.scrollPos.x > _UI.scrollMax.x) {
|
|
_UI.scrollPos.x = _UI.scrollMax.x;
|
|
needMove = TRUE;
|
|
} else if (_UI.scrollPos.x < 0) {
|
|
_UI.scrollPos.x = 0;
|
|
needMove = TRUE;
|
|
}
|
|
} else {
|
|
//
|
|
// else put the Container in the middle of the client area
|
|
//
|
|
_UI.scrollPos.x = _UI.scrollMax.x / 2;
|
|
needMove = TRUE;
|
|
}
|
|
|
|
if (clientSize.height <= _UI.containerSize.height) {
|
|
if (_UI.scrollPos.y > _UI.scrollMax.y) {
|
|
_UI.scrollPos.y = _UI.scrollMax.y;
|
|
needMove = TRUE;
|
|
} else if (_UI.scrollPos.y < 0) {
|
|
_UI.scrollPos.y = 0;
|
|
needMove = TRUE;
|
|
}
|
|
} else {
|
|
//
|
|
// else put the Container in the middle of the client area
|
|
//
|
|
_UI.scrollPos.y = _UI.scrollMax.y / 2;
|
|
|
|
needMove = TRUE;
|
|
}
|
|
|
|
if (needMove) {
|
|
UIMoveContainerWindow();
|
|
}
|
|
|
|
TRC_DBG((TB, _T("scrollPos (%d,%d)"), _UI.scrollPos.x, _UI.scrollPos.y));
|
|
|
|
//
|
|
// Common header fields
|
|
//
|
|
scrollInfo.cbSize = sizeof(scrollInfo);
|
|
scrollInfo.fMask = SIF_ALL;
|
|
|
|
if ((visibleScrollBars & UI_BOTTOM_SCROLLBAR) != 0)
|
|
{
|
|
//
|
|
// Set horizontal values
|
|
//
|
|
scrollInfo.nMin = 0;
|
|
scrollInfo.nMax = _UI.containerSize.width - 1;
|
|
scrollInfo.nPage = clientSize.width;
|
|
scrollInfo.nPos = _UI.scrollPos.x;
|
|
|
|
UISetScrollInfo(SB_HORZ,
|
|
&scrollInfo,
|
|
TRUE);
|
|
}
|
|
|
|
if ((visibleScrollBars & UI_RIGHT_SCROLLBAR) != 0)
|
|
{
|
|
//
|
|
// Set vertical values
|
|
//
|
|
scrollInfo.nMin = 0;
|
|
scrollInfo.nMax = _UI.containerSize.height - 1;
|
|
scrollInfo.nPage = clientSize.height;
|
|
scrollInfo.nPos = _UI.scrollPos.y;
|
|
|
|
UISetScrollInfo(SB_VERT,
|
|
&scrollInfo,
|
|
TRUE);
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Name: UIMoveContainerWindow
|
|
//
|
|
// Purpose: Moves the container window to its new position and flags it to
|
|
// be repainted
|
|
//
|
|
DCVOID DCINTERNAL CUI::UIMoveContainerWindow(DCVOID)
|
|
{
|
|
#ifdef OS_WINCE
|
|
RECT rect;
|
|
#endif
|
|
|
|
DC_BEGIN_FN("UIMoveContainerWindow");
|
|
|
|
if(!_UI.hwndContainer)
|
|
{
|
|
#ifdef DEFER_CORE_INIT
|
|
TRC_ASSERT((NULL != _UI.hwndContainer), (TB, _T("_UI.hwndContainer is NULL")));
|
|
#endif
|
|
DC_QUIT;
|
|
}
|
|
|
|
#ifdef OS_WINCE
|
|
//
|
|
// WinCE will do a move even if one isn't required. Stop that here.
|
|
//
|
|
GetWindowRect(_UI.hwndContainer, &rect);
|
|
|
|
if ((rect.left != -_UI.scrollPos.x) ||
|
|
(rect.top != -_UI.scrollPos.y) ||
|
|
((DCUINT)(rect.right - rect.left) != _UI.containerSize.width) ||
|
|
((DCUINT)(rect.bottom - rect.top) != _UI.containerSize.height))
|
|
#endif
|
|
{
|
|
MoveWindow( _UI.hwndContainer,
|
|
-_UI.scrollPos.x,
|
|
-_UI.scrollPos.y,
|
|
_UI.containerSize.width,
|
|
_UI.containerSize.height,
|
|
TRUE );
|
|
}
|
|
|
|
DC_END_FN();
|
|
DC_EXIT_POINT:
|
|
;
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UIUpdateScreenMode
|
|
//
|
|
// Purpose: Updates the window settings after a switch to/from fullscreen
|
|
//
|
|
// Params:
|
|
// fGrabFocus - if true grabs the focus
|
|
//
|
|
DCVOID DCINTERNAL CUI::UIUpdateScreenMode(BOOL fGrabFocus)
|
|
{
|
|
DCUINT32 style;
|
|
LONG wID;
|
|
|
|
// multi-monitor support
|
|
RECT screenRect;
|
|
#ifdef OS_WINNT
|
|
HMONITOR hMonitor;
|
|
MONITORINFO monInfo;
|
|
#endif // OS_WINNT
|
|
|
|
DC_BEGIN_FN("UIUpdateScreenMode");
|
|
|
|
TRC_NRM((TB, _T("Entering Fullscreen mode")));
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
LockWindowUpdate( _UI.hwndMain );
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
|
|
UIRecalcMaxMainWindowSize();
|
|
|
|
//
|
|
// Take away the title bar and borders
|
|
//
|
|
style = GetWindowLong( _UI.hwndMain,
|
|
GWL_STYLE );
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
style &= ~(WS_DLGFRAME |
|
|
WS_THICKFRAME | WS_BORDER |
|
|
WS_MAXIMIZEBOX);
|
|
|
|
#else // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
style &= ~(WS_DLGFRAME | WS_SYSMENU | WS_BORDER);
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
SetWindowLong( _UI.hwndMain,
|
|
GWL_STYLE,
|
|
style );
|
|
|
|
//
|
|
// Set the window ID (to remove the menu titles).
|
|
//
|
|
wID = SetWindowLong( _UI.hwndMain, GWL_ID, 0 );
|
|
|
|
//
|
|
/// Note that two calls to SetWindowPos are required here in order to
|
|
/// adjust the position to allow for frame removal and also to correctly
|
|
// set the Z-ordering.
|
|
//
|
|
|
|
// default screen size
|
|
screenRect.top = 0;
|
|
screenRect.left = 0;
|
|
|
|
//
|
|
// Win32 sets the window size clipped to the physical screen; Win16
|
|
// seems to store the size you set regardless - which is not the
|
|
// behavior we want later on when we query the window size to work out
|
|
// if we need scroll bars
|
|
//
|
|
screenRect.bottom = _UI.maxMainWindowSize.height;
|
|
screenRect.right = _UI.maxMainWindowSize.width;
|
|
|
|
// for multi monitor, need to find which monitor the client window
|
|
// resides, then get the correct screen size of the corresponding
|
|
// monitor
|
|
|
|
if(_UI.fControlIsFullScreen)
|
|
{
|
|
#ifdef OS_WINNT
|
|
if (GetSystemMetrics(SM_CMONITORS)) {
|
|
hMonitor = MonitorFromWindow(_UI.hWndCntrl, MONITOR_DEFAULTTONULL);
|
|
if (hMonitor != NULL) {
|
|
monInfo.cbSize = sizeof(MONITORINFO);
|
|
if (GetMonitorInfo(hMonitor, &monInfo)) {
|
|
screenRect = monInfo.rcMonitor;
|
|
}
|
|
}
|
|
}
|
|
#endif // OS_WINNT
|
|
} //(_UI.fControlIsFullScreen)
|
|
|
|
|
|
//
|
|
// Reposition and size the window with the frame changes, and place at
|
|
// the top of the Z-order (by not setting SWP_NOOWNERZORDER or
|
|
// SWP_NOZORDER and specifying HWND_TOP).
|
|
//
|
|
SetWindowPos( _UI.hwndMain,
|
|
HWND_TOP,
|
|
screenRect.left, screenRect.top,
|
|
screenRect.right - screenRect.left,
|
|
screenRect.bottom - screenRect.top,
|
|
SWP_NOACTIVATE | SWP_FRAMECHANGED );
|
|
|
|
//
|
|
// Reposition the window again - otherwise the fullscreen window is
|
|
// positioned as if it still had borders.
|
|
//
|
|
SetWindowPos( _UI.hwndMain,
|
|
NULL,
|
|
screenRect.left, screenRect.top,
|
|
0, 0,
|
|
SWP_NOZORDER | SWP_NOACTIVATE |
|
|
SWP_NOOWNERZORDER | SWP_NOSIZE );
|
|
|
|
//
|
|
// Reset the container to top left
|
|
//
|
|
_UI.scrollPos.x = 0;
|
|
_UI.scrollPos.y = 0;
|
|
|
|
UIRecalculateScrollbars();
|
|
|
|
UIMoveContainerWindow();
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
LockWindowUpdate( NULL );
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_LOCKWINDOWUPDATE)
|
|
|
|
//
|
|
// Make sure we have the focus after a screen mode toggle
|
|
//
|
|
if(fGrabFocus)
|
|
{
|
|
SetFocus(_UI.hwndContainer);
|
|
}
|
|
|
|
DC_END_FN();
|
|
} // UIUpdateScreenMode
|
|
|
|
|
|
//
|
|
// Name: UIValidateCurrentParams
|
|
//
|
|
// Purpose: To check whether the current connection parameters are valid
|
|
//
|
|
// Returns: TRUE - if the parameters are valid
|
|
// FALSE otherwise
|
|
//
|
|
BOOL DCINTERNAL CUI::UIValidateCurrentParams(CONNECTIONMODE connMode)
|
|
{
|
|
BOOL rc = TRUE;
|
|
unsigned xSize = _UI.controlSize.width;
|
|
unsigned ySize = _UI.controlSize.height;
|
|
|
|
DC_BEGIN_FN("UIValidateCurrentParams");
|
|
|
|
if( CONNECTIONMODE_INITIATE == connMode )
|
|
{
|
|
//
|
|
// If the Address is empty, the params are invalid
|
|
//
|
|
if ((DC_TSTRCMP(_UI.strAddress, _T("")) == 0))
|
|
{
|
|
rc = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure we have a screen big enough for the the remote desktop
|
|
//
|
|
if ((xSize < _UI.uiSizeTable[0]) ||
|
|
(ySize < _UI.uiSizeTable[1]) )
|
|
{
|
|
rc = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return rc;
|
|
} // UIValidateCurrentParams
|
|
|
|
|
|
//
|
|
// Name: UIShadowBitmapSettingChanged
|
|
//
|
|
// Purpose: Performs necessary actions when _UI.shadowBitmapEnabled
|
|
// is updated.
|
|
//
|
|
DCVOID DCINTERNAL CUI::UIShadowBitmapSettingChanged(DCVOID)
|
|
{
|
|
DC_BEGIN_FN("UIShadowBitmapSettingChanged");
|
|
|
|
if (_UI.shadowBitmapEnabled)
|
|
{
|
|
SET_FLAG(_UI.connectFlags, CO_CONN_FLAG_SHADOW_BITMAP_ENABLED);
|
|
}
|
|
else
|
|
{
|
|
CLEAR_FLAG(_UI.connectFlags, CO_CONN_FLAG_SHADOW_BITMAP_ENABLED);
|
|
}
|
|
|
|
DC_END_FN();
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UISmoothScrollingSettingChanged
|
|
//
|
|
// Purpose: Performs necessary actions when _UI.smoothScrolling
|
|
// is updated.
|
|
//
|
|
DCVOID DCINTERNAL CUI::UISmoothScrollingSettingChanged(DCVOID)
|
|
{
|
|
DC_BEGIN_FN("UISmoothScrollingSettingChanged");
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
//
|
|
// Name: UISetScrollInfo
|
|
//
|
|
// Purpose: Sets scroll bar parameters
|
|
//
|
|
// Returns: DC_RC_OK if successful, error code otherwise
|
|
//
|
|
// Params: IN hwnd - handle of window with scroll bar
|
|
// IN scrollBarFlag - type of scroll bar
|
|
// IN pScrollInfo - info to set for the scrollbar
|
|
// IN redraw - TRUE if scrollbar to be redrawn
|
|
//
|
|
unsigned DCINTERNAL CUI::UISetScrollInfo(
|
|
int scrollBarFlag,
|
|
LPSCROLLINFO pScrollInfo,
|
|
BOOL redraw)
|
|
{
|
|
unsigned rc = DC_RC_OK;
|
|
|
|
DC_BEGIN_FN("UISetScrollInfo");
|
|
|
|
//
|
|
// This only works for scroll bar flags indicating horizontal and/or
|
|
// vertical scrollbar.
|
|
//
|
|
TRC_ASSERT((!TEST_FLAG(scrollBarFlag, ~(SB_HORZ | SB_VERT))),
|
|
(TB, _T("Invalid scroll bar flag %#x"), scrollBarFlag));
|
|
|
|
TRC_ASSERT((!IsBadReadPtr(pScrollInfo, sizeof(*pScrollInfo))),
|
|
(TB, _T("Bad scroll info memory %p"), pScrollInfo));
|
|
|
|
//
|
|
// Call the Windows API to set the information.
|
|
//
|
|
SetScrollInfo(_UI.hwndMain,
|
|
scrollBarFlag,
|
|
pScrollInfo,
|
|
redraw);
|
|
DC_END_FN();
|
|
return rc;
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UISetConnectionStatus
|
|
//
|
|
// Purpose: Sets the UI connection status
|
|
//
|
|
DCVOID DCINTERNAL CUI::UISetConnectionStatus(DCUINT status)
|
|
{
|
|
DC_BEGIN_FN("UISetConnectionStatus");
|
|
|
|
if (_UI.connectionStatus == status)
|
|
{
|
|
DC_QUIT;
|
|
}
|
|
|
|
//
|
|
// Store the new connection status.
|
|
//
|
|
TRC_NRM((TB, _T("UI connection status %u->%u"), _UI.connectionStatus, status));
|
|
_UI.connectionStatus = status;
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UIInitializeDefaultSettings
|
|
//
|
|
// Purpose: Initialize connection settings with defaults. This is mainly
|
|
// for advanced settings that can optionally be overwridden by
|
|
// the user
|
|
//
|
|
void DCINTERNAL CUI::UIInitializeDefaultSettings()
|
|
{
|
|
unsigned nRead = 0;
|
|
unsigned i;
|
|
int defaultValue;
|
|
HDC hdc;
|
|
int colorDepthID;
|
|
TCHAR szWPosDflt[] = UTREG_UI_WIN_POS_STR_DFLT;
|
|
HRESULT hr;
|
|
|
|
DC_BEGIN_FN("UIInitializeDefaultSettings");
|
|
|
|
//
|
|
// Get screen mode before creating windows
|
|
//
|
|
_UI.windowPlacement.length = sizeof(_UI.windowPlacement);
|
|
|
|
//
|
|
// Set the maximized / minimized positions to the hardcoded defaults.
|
|
//
|
|
UISetMinMaxPlacement();
|
|
|
|
//
|
|
// Find out the actual display depth
|
|
//
|
|
// Don't worry about these functions failing - if they do, we'll use
|
|
// the default setting, or 8bpp if no registry setting.
|
|
//
|
|
colorDepthID = CO_BITSPERPEL8;
|
|
hdc = GetDC(NULL);
|
|
TRC_ASSERT((NULL != hdc), (TB,_T("Failed to get DC")));
|
|
if(hdc)
|
|
{
|
|
#ifdef DC_HICOLOR
|
|
DCINT screenBpp;
|
|
screenBpp = GetDeviceCaps(hdc, BITSPIXEL);
|
|
TRC_NRM((TB, _T("HDC %p has %u bpp"), hdc, screenBpp));
|
|
//
|
|
// Clamp the default color depth to 16bpp for best perf
|
|
//
|
|
screenBpp = screenBpp > 16 ? 16 : screenBpp;
|
|
colorDepthID = UI_BppToColorDepthID( screenBpp );
|
|
#else
|
|
DCINT numColors = GetDeviceCaps(hdc, NUMCOLORS);
|
|
TRC_NRM((TB, _T("HDC %p, num colors"), hdc, numColors));
|
|
colorDepthID = (numColors == 16) ? CO_BITSPERPEL4 : CO_BITSPERPEL8;
|
|
#endif
|
|
ReleaseDC(NULL, hdc);
|
|
}
|
|
|
|
TRC_NRM((TB, _T("Color depth ID %d"), colorDepthID));
|
|
_UI.colorDepthID = colorDepthID;
|
|
//
|
|
// Read auto connect flag
|
|
//
|
|
TRC_NRM((TB, _T("AutoConnect = %d"), _UI.autoConnectEnabled));
|
|
|
|
//
|
|
// Read the smooth scrolling option
|
|
//
|
|
_UI.smoothScrolling = UTREG_UI_SMOOTH_SCROLL_DFLT;
|
|
|
|
//
|
|
// Read the accelerator check state
|
|
//
|
|
_UI.acceleratorCheckState = UTREG_UI_ACCELERATOR_PASSTHROUGH_ENABLED_DFLT;
|
|
|
|
//
|
|
// Read the Shadow Bitmap option
|
|
//
|
|
#ifndef OS_WINCE
|
|
_UI.shadowBitmapEnabled = UTREG_UI_SHADOW_BITMAP_DFLT;
|
|
#else
|
|
_UI.shadowBitmapEnabled = _pUt->UT_ReadRegistryInt(UTREG_SECTION,
|
|
UTREG_UI_SHADOW_BITMAP,
|
|
UTREG_UI_SHADOW_BITMAP_DFLT);
|
|
#endif
|
|
|
|
_UI.fMaximizeShell = UTREG_UI_MAXIMIZESHELL50_DFLT;
|
|
|
|
//
|
|
// Keyboard hooking mode
|
|
//
|
|
_UI.keyboardHookMode = UTREG_UI_KEYBOARD_HOOK_DFLT;
|
|
|
|
//
|
|
// Audio redirection mode
|
|
//
|
|
_UI.audioRedirectionMode = UTREG_UI_AUDIO_MODE_DFLT;
|
|
|
|
//
|
|
// !WARNING! if you change this default to TRUE revisit the security
|
|
// code that disables drive redirection in response to a reg key
|
|
// in the control's put_RedirectDrives method. It only does the check
|
|
// on the property set to avoid a reg access in the connect path.
|
|
//
|
|
// Drive
|
|
//
|
|
_UI.fEnableDriveRedirection = FALSE; //off by default for security
|
|
|
|
//
|
|
// Printers
|
|
//
|
|
_UI.fEnablePrinterRedirection = FALSE; //off by default for security
|
|
|
|
//
|
|
// COM ports
|
|
//
|
|
_UI.fEnablePortRedirection = FALSE; //off by default for security
|
|
|
|
//
|
|
// Smart card
|
|
//
|
|
_UI.fEnableSCardRedirection = FALSE; //off by default for security
|
|
|
|
//
|
|
// Connect to server console is disabled by default
|
|
//
|
|
UI_SetConnectToServerConsole(FALSE);
|
|
|
|
//
|
|
// Order draw threshold
|
|
//
|
|
_UI.orderDrawThreshold = UTREG_UH_DRAW_THRESHOLD_DFLT;
|
|
_UI.RegBitmapCacheSize = UTREG_UH_TOTAL_BM_CACHE_DFLT;
|
|
_UI.RegBitmapVirtualCache8BppSize = TSC_BITMAPCACHEVIRTUALSIZE_8BPP;
|
|
_UI.RegBitmapVirtualCache16BppSize = TSC_BITMAPCACHEVIRTUALSIZE_16BPP;
|
|
_UI.RegBitmapVirtualCache24BppSize = TSC_BITMAPCACHEVIRTUALSIZE_24BPP;
|
|
|
|
_UI.RegScaleBitmapCachesByBPP = UTREG_UH_SCALE_BM_CACHE_DFLT;
|
|
_UI.PersistCacheFileName[0] = NULL;
|
|
_UI.RegNumBitmapCaches = UTREG_UH_BM_NUM_CELL_CACHES_DFLT;
|
|
|
|
const unsigned ProportionDefault[TS_BITMAPCACHE_MAX_CELL_CACHES] =
|
|
{
|
|
UTREG_UH_BM_CACHE1_PROPORTION_DFLT,
|
|
UTREG_UH_BM_CACHE2_PROPORTION_DFLT,
|
|
UTREG_UH_BM_CACHE3_PROPORTION_DFLT,
|
|
UTREG_UH_BM_CACHE4_PROPORTION_DFLT,
|
|
UTREG_UH_BM_CACHE5_PROPORTION_DFLT,
|
|
};
|
|
#if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
|
|
|
|
const unsigned PersistenceDefault[TS_BITMAPCACHE_MAX_CELL_CACHES] =
|
|
{
|
|
UTREG_UH_BM_CACHE1_PERSISTENCE_DFLT,
|
|
UTREG_UH_BM_CACHE2_PERSISTENCE_DFLT,
|
|
UTREG_UH_BM_CACHE3_PERSISTENCE_DFLT,
|
|
UTREG_UH_BM_CACHE4_PERSISTENCE_DFLT,
|
|
UTREG_UH_BM_CACHE5_PERSISTENCE_DFLT,
|
|
};
|
|
#endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
|
|
|
|
const unsigned MaxEntriesDefault[TS_BITMAPCACHE_MAX_CELL_CACHES] =
|
|
{
|
|
UTREG_UH_BM_CACHE1_MAXENTRIES_DFLT,
|
|
UTREG_UH_BM_CACHE2_MAXENTRIES_DFLT,
|
|
UTREG_UH_BM_CACHE3_MAXENTRIES_DFLT,
|
|
UTREG_UH_BM_CACHE4_MAXENTRIES_DFLT,
|
|
UTREG_UH_BM_CACHE5_MAXENTRIES_DFLT,
|
|
};
|
|
|
|
|
|
for (i = 0; i < TS_BITMAPCACHE_MAX_CELL_CACHES; i++)
|
|
{
|
|
_UI.RegBCProportion[i] = ProportionDefault[i];
|
|
|
|
#if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
|
|
_UI.bSendBitmapKeys[i] = PersistenceDefault[i] ? TRUE: FALSE;
|
|
#endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
|
|
|
|
_UI.RegBCMaxEntries[i] = MaxEntriesDefault[i];
|
|
|
|
if (_UI.RegBCMaxEntries[i] < MaxEntriesDefault[i]) {
|
|
_UI.RegBCMaxEntries[i] = MaxEntriesDefault[i];
|
|
}
|
|
}
|
|
|
|
_UI.GlyphSupportLevel = UTREG_UH_GL_SUPPORT_DFLT;
|
|
|
|
_UI.cbGlyphCacheEntrySize[0] = UTREG_UH_GL_CACHE1_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[1] = UTREG_UH_GL_CACHE2_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[2] = UTREG_UH_GL_CACHE3_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[3] = UTREG_UH_GL_CACHE4_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[4] = UTREG_UH_GL_CACHE5_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[5] = UTREG_UH_GL_CACHE6_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[6] = UTREG_UH_GL_CACHE7_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[7] = UTREG_UH_GL_CACHE8_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[8] = UTREG_UH_GL_CACHE9_CELLSIZE_DFLT;
|
|
_UI.cbGlyphCacheEntrySize[9] = UTREG_UH_GL_CACHE10_CELLSIZE_DFLT;
|
|
|
|
_UI.fragCellSize = UTREG_UH_FG_CELLSIZE_DFLT;
|
|
_UI.brushSupportLevel = UTREG_UH_BRUSH_SUPPORT_DFLT;
|
|
|
|
_UI.maxEventCount = UTREG_IH_MAX_EVENT_COUNT_DFLT;
|
|
_UI.eventsAtOnce = UTREG_IH_NRM_EVENT_COUNT_DFLT;
|
|
_UI.minSendInterval = UTREG_IH_MIN_SEND_INTERVAL_DFLT;
|
|
_UI.keepAliveInterval = UTREG_IH_KEEPALIVE_INTERVAL_DFLT;
|
|
_UI.allowBackgroundInput = UTREG_IH_ALLOWBACKGROUNDINPUT_DFLT;
|
|
|
|
|
|
_UI.shutdownTimeout = UTREG_UI_SHUTDOWN_TIMEOUT_DFLT;
|
|
|
|
#ifdef OS_WINCE
|
|
_UI.winceKeyboardType = UTREG_UI_KEYBOARD_TYPE_DFLT;
|
|
_UI.winceKeyboardSubType = UTREG_UI_KEYBOARD_SUBTYPE_DFLT;
|
|
_UI.winceKeyboardFunctionKey = UTREG_UI_KEYBOARD_FUNCTIONKEY_DFLT;
|
|
#endif
|
|
|
|
_UI.connectionTimeOut = UTREG_UI_OVERALL_CONN_TIMEOUT_DFLT;
|
|
_UI.singleTimeout = UTREG_UI_SINGLE_CONN_TIMEOUT_DFLT;
|
|
hr = StringCchCopy(
|
|
_UI.szKeyBoardLayoutStr,
|
|
SIZE_TCHARS(_UI.szKeyBoardLayoutStr),
|
|
UTREG_UI_KEYBOARD_LAYOUT_DFLT
|
|
);
|
|
TRC_ASSERT(SUCCEEDED(hr),
|
|
(TB,_T("StringCchCopy for keyblayout str failed: 0x%x"), hr));
|
|
|
|
//
|
|
// Read the transport type
|
|
// VER1: Restricted to TCP only.
|
|
//
|
|
_UI.transportType = UTREG_UI_TRANSPORT_TYPE_DFLT;
|
|
if (_UI.transportType != CO_TRANSPORT_TCP)
|
|
{
|
|
TRC_ABORT((TB, _T("Illegal Tansport Type %d configured"),
|
|
_UI.transportType));
|
|
_UI.transportType = UTREG_UI_TRANSPORT_TYPE_DFLT;
|
|
}
|
|
|
|
//
|
|
// SAS sequence
|
|
//
|
|
_UI.sasSequence = UTREG_UI_SAS_SEQUENCE_DFLT;
|
|
if ((_UI.sasSequence != RNS_UD_SAS_DEL) &&
|
|
(_UI.sasSequence != RNS_UD_SAS_NONE))
|
|
{
|
|
TRC_ABORT((TB, _T("Illegal SAS Sequence %#x configured"),_UI.sasSequence));
|
|
_UI.sasSequence = UTREG_UI_SAS_SEQUENCE_DFLT;
|
|
}
|
|
|
|
//
|
|
// encryption enabled flag
|
|
//
|
|
_UI.encryptionEnabled = UTREG_UI_ENCRYPTION_ENABLED_DFLT;
|
|
|
|
//
|
|
// dedicated terminal flag
|
|
//
|
|
_UI.dedicatedTerminal = UTREG_UI_DEDICATED_TERMINAL_DFLT;
|
|
|
|
_UI.MCSPort = UTREG_UI_MCS_PORT_DFLT;
|
|
|
|
//
|
|
// fMouse flag
|
|
//
|
|
_UI.fMouse = UTREG_UI_ENABLE_MOUSE_DFLT;
|
|
|
|
//
|
|
// Read the DisableCtrlAltDel flag
|
|
//
|
|
_UI.fDisableCtrlAltDel = UTREG_UI_DISABLE_CTRLALTDEL_DFLT;
|
|
|
|
#ifdef SMART_SIZING
|
|
//
|
|
// Read the SmartSizing flag
|
|
//
|
|
_UI.fSmartSizing = UTREG_UI_SMARTSIZING_DFLT;
|
|
#endif // SMART_SIZING
|
|
|
|
//
|
|
// Read the EnableWindowsKey flag
|
|
//
|
|
_UI.fEnableWindowsKey = UTREG_UI_ENABLE_WINDOWSKEY_DFLT;
|
|
|
|
//
|
|
// Read the DoubleClickDetect flag
|
|
//
|
|
_UI.fDoubleClickDetect = UTREG_UI_DOUBLECLICK_DETECT_DFLT;
|
|
|
|
//
|
|
// Set screen mode hotkey
|
|
//
|
|
#ifndef OS_WINCE // Only full screen on WinCE
|
|
defaultValue = UTREG_UI_FULL_SCREEN_VK_CODE_DFLT;
|
|
if (_pUt->UT_IsNEC98platform())
|
|
{
|
|
defaultValue = UTREG_UI_FULL_SCREEN_VK_CODE_NEC98_DFLT;
|
|
}
|
|
_UI.hotKey.fullScreen = defaultValue;
|
|
#endif // OS_WINCE
|
|
|
|
//
|
|
// Set the ctrl-esc key to it's default.
|
|
//
|
|
_UI.hotKey.ctrlEsc = UTREG_UI_CTRL_ESC_VK_CODE_DFLT;
|
|
|
|
//
|
|
// Set the alt-esc key to it's default.
|
|
//
|
|
_UI.hotKey.altEsc = UTREG_UI_ALT_ESC_VK_CODE_DFLT;
|
|
|
|
//
|
|
// Set the alt-tab key to it's default.
|
|
//
|
|
_UI.hotKey.altTab = UTREG_UI_ALT_TAB_VK_CODE_DFLT;
|
|
|
|
//
|
|
// Set the alt-shift-tab key to it's default.
|
|
//
|
|
_UI.hotKey.altShifttab = UTREG_UI_ALT_SHFTAB_VK_CODE_DFLT;
|
|
|
|
//
|
|
// Set the alt-space key to it's default.
|
|
//
|
|
_UI.hotKey.altSpace = UTREG_UI_ALT_SPACE_VK_CODE_DFLT;
|
|
|
|
//
|
|
// Set the ctrl-alt-del key to it's default.
|
|
//
|
|
defaultValue = UTREG_UI_CTRL_ALTDELETE_VK_CODE_DFLT;
|
|
if (_pUt->UT_IsNEC98platform())
|
|
{
|
|
defaultValue = UTREG_UI_CTRL_ALTDELETE_VK_CODE_NEC98_DFLT;
|
|
}
|
|
_UI.hotKey.ctlrAltdel = defaultValue;
|
|
|
|
//
|
|
// Read the compression option
|
|
//
|
|
UI_SetCompress(UTREG_UI_COMPRESS_DFLT);
|
|
|
|
#if ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
|
|
_UI.fBitmapPersistence = UTREG_UI_BITMAP_PERSISTENCE_DFLT;
|
|
#else
|
|
_UI.fBitmapPersistence = UTREG_UI_BITMAP_PERSISTENCE_DFLT;
|
|
#endif // ((!defined(OS_WINCE)) || (defined(ENABLE_BMP_CACHING_FOR_WINCE)))
|
|
TRC_NRM((TB, _T("Bitmap Persistence Enabled = %d"), _UI.fBitmapPersistence));
|
|
|
|
#ifdef DC_DEBUG
|
|
//
|
|
// Set the debug options to their defaults
|
|
//
|
|
_UI.hatchBitmapPDUData = UTREG_UI_HATCH_BITMAP_PDU_DATA_DFLT;
|
|
|
|
_UI.hatchSSBOrderData = UTREG_UI_HATCH_SSB_ORDER_DATA_DFLT;
|
|
|
|
_UI.hatchMemBltOrderData = UTREG_UI_HATCH_MEMBLT_ORDER_DATA_DFLT;
|
|
|
|
_UI.labelMemBltOrders = UTREG_UI_LABEL_MEMBLT_ORDERS_DFLT;
|
|
|
|
_UI.bitmapCacheMonitor = UTREG_UI_BITMAP_CACHE_MONITOR_DFLT;
|
|
#endif // DC_DEBUG
|
|
|
|
_UI.coreInitialized = FALSE;
|
|
|
|
OSVERSIONINFO osVersionInfo;
|
|
BOOL bRc;
|
|
|
|
//
|
|
// Set the OS version
|
|
//
|
|
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
|
|
bRc = GetVersionEx(&osVersionInfo);
|
|
|
|
TRC_ASSERT((bRc), (TB,_T("GetVersionEx failed")));
|
|
#ifdef OS_WINCE
|
|
TRC_ASSERT((osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_CE),
|
|
(TB,_T("Unknown os version %d"), osVersionInfo.dwPlatformId));
|
|
#else
|
|
TRC_ASSERT(((osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ||
|
|
(osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)),
|
|
(TB,_T("Unknown os version %d"), osVersionInfo.dwPlatformId));
|
|
|
|
_UI.osMinorType =
|
|
(osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ?
|
|
TS_OSMINORTYPE_WINDOWS_95 : TS_OSMINORTYPE_WINDOWS_NT;
|
|
#endif
|
|
|
|
_UI.fRunningOnPTS = IsRunningOnPTS();
|
|
|
|
#ifdef USE_BBAR
|
|
_UI.fBBarEnabled = TRUE;
|
|
_UI.fBBarPinned = TRUE;
|
|
_UI.fBBarShowMinimizeButton = TRUE;
|
|
_UI.fBBarShowRestoreButton = TRUE;
|
|
#endif
|
|
|
|
_UI.fGrabFocusOnConnect = TRUE;
|
|
//
|
|
// Perf optimization settings (which features to disable)
|
|
// Default is to disable nothing
|
|
//
|
|
_UI.dwPerformanceFlags = TS_PERF_DISABLE_NOTHING;
|
|
|
|
// default to don't notify TS public key
|
|
// currently only RemoteAssistance uses this.
|
|
_UI.fNotifyTSPublicKey = FALSE;
|
|
|
|
//
|
|
// Max number of ARC retries
|
|
//
|
|
UI_SetMaxArcAttempts(MAX_ARC_CONNECTION_ATTEMPTS);
|
|
|
|
//
|
|
// By default allow autoreconnection
|
|
//
|
|
UI_SetEnableAutoReconnect(TRUE);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
//
|
|
// Name: UISetMinMaxPlacement
|
|
//
|
|
// Purpose: Reset the minimized / maximized placement
|
|
// Operation: Allow for the window border width.
|
|
//
|
|
void DCINTERNAL CUI::UISetMinMaxPlacement()
|
|
{
|
|
DC_BEGIN_FN("UISetMinMaxPlacement");
|
|
|
|
//
|
|
// Set the maximized position to the top left - allow for the window
|
|
// frame width.
|
|
//
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
_UI.windowPlacement.ptMaxPosition.x = -GetSystemMetrics(SM_CXFRAME);
|
|
_UI.windowPlacement.ptMaxPosition.y = -GetSystemMetrics(SM_CYFRAME);
|
|
#else // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
_UI.windowPlacement.ptMaxPosition.x = 0;
|
|
_UI.windowPlacement.ptMaxPosition.y = 0;
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
|
|
//
|
|
// Minimized position is 0, 0
|
|
//
|
|
_UI.windowPlacement.ptMinPosition.x = 0;
|
|
_UI.windowPlacement.ptMinPosition.y = 0;
|
|
|
|
DC_END_FN();
|
|
} // UISetMinMaxPlacement
|
|
|
|
|
|
//
|
|
// Name: UIInitiateDisconnection
|
|
//
|
|
// Purpose: Call _pCo->CO_Disconnect, set UI states and menus
|
|
//
|
|
void DCINTERNAL CUI::UIInitiateDisconnection()
|
|
{
|
|
#ifndef OS_WINCE
|
|
int intRC;
|
|
#endif
|
|
|
|
DC_BEGIN_FN("UIInitiateDisconnection");
|
|
|
|
TRC_NRM((TB, _T("Disconnecting...")));
|
|
|
|
if (_UI.connectionStatus != UI_STATUS_CONNECT_PENDING_DNS)
|
|
{
|
|
//
|
|
// Only disconnect if we have issued CO_Connect - not if we are
|
|
// still awaiting the host name lookup.
|
|
//
|
|
TRC_NRM((TB, _T("UI calling _pCo->CO_Disconnect")));
|
|
_pCo->CO_Disconnect();
|
|
}
|
|
else
|
|
{
|
|
if (!UIFreeAsyncDNSBuffer()) {
|
|
if (_pHostData) {
|
|
TRC_ERR((TB,
|
|
_T("Failed to free async dns buffer. Status: %d hghbn: 0x%x"),
|
|
_UI.connectionStatus, _UI.hGHBN));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now indicate that disconnection has completed
|
|
// and fire the event
|
|
//
|
|
UIGoDisconnected(_UI.disconnectReason, TRUE);
|
|
}
|
|
|
|
DC_END_FN();
|
|
} // UIInitiateDisconnection
|
|
|
|
|
|
//
|
|
// Name: UIGetKeyboardLayout
|
|
//
|
|
// Purpose: Get the keyboard layout ID
|
|
//
|
|
// Returns: layout ID
|
|
//
|
|
// Operation: Win16: Read SYSTEM.INI to find the keyboard DLL name. Look
|
|
// this up in the Client INI file to find the keyboard layout ID
|
|
// Win32: use GetKeyboardLayout()
|
|
//
|
|
UINT32 DCINTERNAL CUI::UIGetKeyboardLayout()
|
|
{
|
|
UINT32 layout = RNS_UD_KBD_DEFAULT;
|
|
TCHAR szLayoutStr[UTREG_UI_KEYBOARD_LAYOUT_LEN];
|
|
CHAR kbdName[KL_NAMELENGTH];
|
|
HRESULT hr;
|
|
|
|
DC_BEGIN_FN("UIGetKeyboardLayout");
|
|
|
|
//
|
|
// Read the keyboard type.
|
|
// First look for a registry / ini entry
|
|
//
|
|
hr = StringCchCopy(szLayoutStr,
|
|
SIZE_TCHARS(szLayoutStr),
|
|
_UI.szKeyBoardLayoutStr);
|
|
if (FAILED(hr)) {
|
|
TRC_ERR((TB,_T("StringCchCopy for keyboard layout str failed: 0x%x"),hr));
|
|
DC_QUIT;
|
|
}
|
|
|
|
if (!DC_TSTRCMP(szLayoutStr, UTREG_UI_KEYBOARD_LAYOUT_DFLT))
|
|
{
|
|
//
|
|
// Read the layout - OS dependent method.
|
|
//
|
|
TRC_DBG((TB, _T("No registry setting - determine the layout")));
|
|
|
|
//
|
|
// GetKeyboardLayout does not return the correct information, so
|
|
// use CicSubstGetKeyboardLayout (a Cicero replacement for
|
|
// GetKeyboardLayoutName that can correctly return the physical hKL
|
|
// even when Cicero is active such as with CUAS).
|
|
//
|
|
#ifndef OS_WINCE
|
|
if (!CicSubstGetKeyboardLayout(kbdName))
|
|
#else
|
|
if (!GetKeyboardLayoutName(kbdName))
|
|
#endif
|
|
{
|
|
TRC_ALT((TB, _T("Failed to get keyboard layout name")));
|
|
DC_QUIT;
|
|
}
|
|
hr = StringCchPrintf(szLayoutStr, SIZE_TCHARS(szLayoutStr),
|
|
_T("0x%S"), kbdName);
|
|
}
|
|
|
|
//
|
|
// Convert from hex string to int.
|
|
//
|
|
TRC_DBG((TB, _T("Layout Name %s"), szLayoutStr));
|
|
if (DC_TSSCANF(szLayoutStr, _T("%lx"), &layout) != 1)
|
|
{
|
|
TRC_ALT((TB, _T("Invalid keyboard layout %s"), szLayoutStr));
|
|
layout = RNS_UD_KBD_DEFAULT;
|
|
}
|
|
|
|
/*
|
|
* The HKL of US-Dvorak, US-International on Win95 have a difference to WinNT.
|
|
* This code is swaped HKL value if platform is Win95.
|
|
*/
|
|
if (UI_GetOsMinorType() == TS_OSMINORTYPE_WINDOWS_95 &&
|
|
(layout == 0x00010409 || layout == 0x00020409))
|
|
{
|
|
if (layout == 0x00010409)
|
|
layout = 0x00020409;
|
|
else
|
|
layout = 0x00010409;
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
TRC_NRM((TB, _T("Layout ID %#lx"), layout));
|
|
DC_END_FN();
|
|
return layout;
|
|
} // UIGetKeyboardLayout
|
|
|
|
//
|
|
// Name: UIStartConnectWithConnectedEndpoint
|
|
//
|
|
// Purpose: Connect with a connected socket
|
|
//
|
|
// Params: IN disconnectCode - error code to be displayed if there
|
|
// are no more connections to try.
|
|
//
|
|
// Notes: The disconnectCode is either a timeout, or the ID passed in
|
|
// to UI_OnDisconnected().
|
|
//
|
|
void DCINTERNAL CUI::UIStartConnectWithConnectedEndpoint()
|
|
{
|
|
DC_BEGIN_FN("UIStartConnectWithConnectedEndpoint");
|
|
|
|
//
|
|
// Call CC_Connect via the Component Decoupler
|
|
//
|
|
_UI.disconnectReason =UI_MAKE_DISCONNECT_ERR(UI_ERR_UNEXPECTED_DISCONNECT);
|
|
_pCo->CO_Connect(&_UI.connectStruct);
|
|
|
|
UISetConnectionStatus(UI_STATUS_PENDING_CONNECTENDPOINT);
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
} // UIStartListen
|
|
|
|
|
|
//
|
|
// Name: UITryNextConnection
|
|
//
|
|
// Purpose: Attempt to connect to an IP address
|
|
//
|
|
// Params: IN disconnectCode - error code to be displayed if there
|
|
// are no more connections to try.
|
|
//
|
|
// Notes: The disconnectCode is either a timeout, or the ID passed in
|
|
// to UI_OnDisconnected().
|
|
//
|
|
void DCINTERNAL CUI::UITryNextConnection()
|
|
{
|
|
u_long addr;
|
|
u_long DCPTR pAddr;
|
|
HRESULT hr;
|
|
|
|
DC_BEGIN_FN("UITryNextConnection");
|
|
|
|
addr = _UI.hostAddress;
|
|
|
|
//
|
|
// Stop the single connection timer.
|
|
//
|
|
if( _UI.connectStruct.hSingleConnectTimer )
|
|
{
|
|
_pUt->UTStopTimer( _UI.connectStruct.hSingleConnectTimer );
|
|
}
|
|
|
|
//
|
|
// Check for the DNS case
|
|
//
|
|
if (addr == INADDR_NONE)
|
|
{
|
|
pAddr = (u_long DCPTR)
|
|
((struct hostent DCPTR)_pHostData)->h_addr_list[_UI.addrIndex];
|
|
if (pAddr != NULL)
|
|
{
|
|
addr = *pAddr;
|
|
}
|
|
else
|
|
{
|
|
TRC_NRM((TB, _T("No more addresses in list")));
|
|
addr = 0;
|
|
}
|
|
|
|
TRC_NRM((TB, _T("DNS lookup address [%d] %#lx"), _UI.addrIndex, addr));
|
|
_UI.addrIndex++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Not DNS - just a single address, so set to zero for next time.
|
|
//
|
|
TRC_NRM((TB, _T("Normal address %#lx"), addr));
|
|
_UI.hostAddress = 0;
|
|
}
|
|
|
|
if (addr == 0)
|
|
{
|
|
//
|
|
// Cannot connect - so put up the failure dialog.
|
|
//
|
|
TRC_NRM((TB, _T("No more IP addresses")));
|
|
|
|
//
|
|
// Kill the overall connection timer, as this is the last in the
|
|
// list.
|
|
//
|
|
if( _UI.connectStruct.hConnectionTimer )
|
|
{
|
|
_pUt->UTDeleteTimer( _UI.connectStruct.hConnectionTimer );
|
|
_UI.connectStruct.hConnectionTimer = NULL;
|
|
}
|
|
|
|
UIGoDisconnected(_UI.disconnectReason, TRUE);
|
|
DC_QUIT;
|
|
}
|
|
|
|
DCUINT32 localSessionId;
|
|
UI_GetLocalSessionId( &localSessionId );
|
|
|
|
//
|
|
// Prevent loopback connections to (really session 0)
|
|
// Requirments for loopback are
|
|
// 1) Connecting to same machine client is running on
|
|
// 2) Either of
|
|
// -this is a PTS box
|
|
// -Connect to console (session 0) is set and this _is_ session 0.
|
|
//
|
|
if(((_UI.fRunningOnPTS ||
|
|
(UI_GetConnectToServerConsole() && 0 == localSessionId)) &&
|
|
IsConnectingToOwnAddress(addr)))
|
|
{
|
|
//Disconnect don't allow loopback connects to own console
|
|
_UI.disconnectReason =
|
|
UI_MAKE_DISCONNECT_ERR(UI_ERR_LOOPBACK_CONSOLE_CONNECT);
|
|
UIGoDisconnected(_UI.disconnectReason, TRUE);
|
|
DC_QUIT;
|
|
}
|
|
|
|
//
|
|
// Network Layer currently still uses inet_addr() - so write the
|
|
// address as a dotted xx.xx.xx.xx string
|
|
//
|
|
hr = StringCchPrintf(
|
|
_UI.connectStruct.RNSAddress,
|
|
SIZE_TCHARS(_UI.connectStruct.RNSAddress),
|
|
_T("%ld.%ld.%ld.%ld"),
|
|
addr & 0xFF,
|
|
(addr>>8) & 0xFF,
|
|
(addr>>16) & 0xFF,
|
|
(addr>>24) & 0xFF);
|
|
if (SUCCEEDED(hr)) {
|
|
TRC_NRM((TB, _T(" _pCo->CO_Connect: Try address %#lx = %s"),
|
|
addr, _UI.connectStruct.RNSAddress));
|
|
}
|
|
else {
|
|
TRC_ERR((TB,_T("Unable to sprintf RNSAddress: 0x%x"), hr));
|
|
_UI.disconnectReason =
|
|
UI_MAKE_DISCONNECT_ERR(UI_ERR_GHBNFAILED);
|
|
UIGoDisconnected(_UI.disconnectReason, TRUE);
|
|
DC_QUIT;
|
|
}
|
|
|
|
//
|
|
// create the various timer handles for the connection process
|
|
//
|
|
if( NULL == _UI.connectStruct.hSingleConnectTimer )
|
|
{
|
|
_UI.connectStruct.hSingleConnectTimer = _pUt->UTCreateTimer(
|
|
_UI.hwndMain,
|
|
UI_TIMER_SINGLE_CONN,
|
|
_UI.singleTimeout * 1000 );
|
|
}
|
|
|
|
if( NULL == _UI.connectStruct.hSingleConnectTimer )
|
|
{
|
|
TRC_ERR((TB, _T("Failed to create single connection timeout timer")));
|
|
}
|
|
|
|
if( NULL == _UI.connectStruct.hLicensingTimer )
|
|
{
|
|
_UI.connectStruct.hLicensingTimer = _pUt->UTCreateTimer(
|
|
_UI.hwndMain,
|
|
UI_TIMER_LICENSING,
|
|
_UI.licensingTimeout * 1000 );
|
|
}
|
|
|
|
if( NULL == _UI.connectStruct.hLicensingTimer )
|
|
{
|
|
TRC_ERR((TB, _T("Failed to create licensing timeout timer")));
|
|
}
|
|
|
|
//
|
|
// Call CC_Connect via the Component Decoupler
|
|
//
|
|
_UI.disconnectReason =UI_MAKE_DISCONNECT_ERR(UI_ERR_UNEXPECTED_DISCONNECT);
|
|
_pCo->CO_Connect(&_UI.connectStruct);
|
|
|
|
//
|
|
// start the single connection timer
|
|
//
|
|
|
|
if( _UI.connectStruct.hSingleConnectTimer )
|
|
{
|
|
if( FALSE == _pUt->UTStartTimer( _UI.connectStruct.hSingleConnectTimer ) )
|
|
{
|
|
TRC_ERR((TB, _T("Failed to start single connection timeout timer")));
|
|
}
|
|
}
|
|
|
|
UISetConnectionStatus(UI_STATUS_CONNECT_PENDING);
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
} // UITryNextConnection
|
|
|
|
|
|
//
|
|
// UIRedirectConnection
|
|
//
|
|
// Used for load balancing redirection for force the client to reflect
|
|
// to the target server.
|
|
//
|
|
void DCINTERNAL CUI::UIRedirectConnection()
|
|
{
|
|
HRESULT hr;
|
|
DC_BEGIN_FN("UIRedirectConnection");
|
|
|
|
TRC_ASSERT((_UI.DoRedirection),(TB,_T("DoRedir is not set!")));
|
|
|
|
// Stop the single connection timer.
|
|
if (_UI.connectStruct.hSingleConnectTimer)
|
|
_pUt->UTStopTimer(_UI.connectStruct.hSingleConnectTimer);
|
|
|
|
#ifdef UNICODE
|
|
TRC_NRM((TB,_T("Target address before redirection replacement: %S"),
|
|
_UI.strAddress));
|
|
hr = StringCchCopy(_UI.strAddress,
|
|
SIZE_TCHARS(_UI.strAddress),
|
|
_UI.RedirectionServerAddress);
|
|
if (FAILED(hr)) {
|
|
TRC_ERR((TB,_T("StringCchCopy for strAddress failed: 0x%x"),hr));
|
|
DC_QUIT;
|
|
}
|
|
|
|
#else
|
|
TRC_NRM((TB,_T("Target address before redirection replacement: %s"),
|
|
_UI.strAddress));
|
|
|
|
#ifdef OS_WIN32
|
|
// Translate the Unicode server name to ANSI.
|
|
WideCharToMultiByte(CP_ACP, 0, _UI.RedirectionServerAddress, -1,
|
|
_UI.strAddress, 256, NULL, NULL);
|
|
#else
|
|
{
|
|
// For Win16, need to manually convert Unicode to ANSI.
|
|
int i = 0;
|
|
|
|
while (_UI.RedirectionServerAddress[i]) {
|
|
_UI.strAddress[i] = (BYTE)_UI.RedirectionServerAddress[i];
|
|
i++;
|
|
}
|
|
_UI.strAddress[i] = 0;
|
|
}
|
|
#endif
|
|
|
|
#endif // UNICODE
|
|
|
|
TRC_NRM((TB,_T("Setting redirection server address to %S"),
|
|
_UI.RedirectionServerAddress));
|
|
|
|
// Reset the redirection server string.
|
|
_UI.RedirectionServerAddress[0] = L'\0';
|
|
|
|
// Start the DNS lookup for the server name, and hence the rest of the
|
|
// connection sequence.
|
|
UIStartDNSLookup();
|
|
|
|
DC_EXIT_POINT:
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
//
|
|
// Name: UIStartDNSLookup
|
|
//
|
|
// Purpose: Initiate lookup of the host IP address(es)
|
|
//
|
|
void DCINTERNAL CUI::UIStartDNSLookup()
|
|
{
|
|
UINT32 errorCode;
|
|
|
|
DC_BEGIN_FN("UIStartDNSLookup");
|
|
|
|
UISetConnectionStatus(UI_STATUS_CONNECT_PENDING_DNS);
|
|
|
|
_UI.addrIndex = 0;
|
|
|
|
#ifdef UNICODE
|
|
//
|
|
// WinSock 1.1 only supports ANSI, so we need to convert any Unicode
|
|
// strings at this point.
|
|
//
|
|
if (!WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
_UI.strAddress,
|
|
-1,
|
|
_UI.ansiAddress,
|
|
256,
|
|
NULL,
|
|
NULL))
|
|
{
|
|
//
|
|
// Conversion failed
|
|
//
|
|
TRC_ERR((TB, _T("Failed to convert address to ANSI")));
|
|
|
|
//
|
|
// Generate the error code.
|
|
//
|
|
errorCode = UI_MAKE_DISCONNECT_ERR(UI_ERR_ANSICONVERT);
|
|
|
|
TRC_ASSERT((HIWORD(errorCode) == 0),
|
|
(TB, _T("disconnect reason code unexpectedly using 32 bits")));
|
|
UIGoDisconnected((DCUINT)errorCode, TRUE);
|
|
DC_QUIT;
|
|
}
|
|
|
|
#else
|
|
StringCchCopyA(_UI.ansiAddress, sizeof(_UI.ansiAddress), _UI.strAddress);
|
|
#endif // UNICODE
|
|
|
|
//
|
|
// Check that the address is not the limited broadcast address
|
|
// (255.255.255.255). inet_addr() doesn't distinguish between this and
|
|
// an invalid IP address.
|
|
//
|
|
if (!strcmp(_UI.ansiAddress, "255.255.255.255")) {
|
|
TRC_ALT((TB, _T("Cannot connect to the limited broadcast address")));
|
|
|
|
//
|
|
// Generate the error code.
|
|
//
|
|
errorCode = UI_MAKE_DISCONNECT_ERR(UI_ERR_BADIPADDRESS);
|
|
|
|
TRC_ASSERT((HIWORD(errorCode) == 0),
|
|
(TB, _T("disconnect reason code unexpectedly using 32 bits")));
|
|
UIGoDisconnected((DCUINT)errorCode, TRUE);
|
|
DC_QUIT;
|
|
}
|
|
|
|
//
|
|
// Now determine whether a DNS lookup is required.
|
|
//
|
|
TRC_NRM((TB, _T("ServerAddress:%s"), _UI.ansiAddress));
|
|
|
|
//
|
|
// Check that we have a string.
|
|
//
|
|
TRC_ASSERT((_UI.ansiAddress[0] != '\0'),
|
|
(TB, _T("Empty server address string")));
|
|
|
|
//
|
|
// Set this to a known value. It's used later to decide whether we're
|
|
// using DNS or a straight IP address.
|
|
//
|
|
_UI.hostAddress = INADDR_NONE;
|
|
|
|
|
|
if(NULL == _pHostData)
|
|
{
|
|
//
|
|
// Allocate new buffer
|
|
//
|
|
_pHostData = (PBYTE)LocalAlloc( LPTR, MAXGETHOSTSTRUCT);
|
|
if(_pHostData)
|
|
{
|
|
DC_MEMSET(_pHostData, 0, MAXGETHOSTSTRUCT);
|
|
}
|
|
else
|
|
{
|
|
UI_FatalError(DC_ERR_OUTOFMEMORY);
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Use existing
|
|
//
|
|
|
|
TRC_ERR((TB,_T("_pHostData already allocated!!! Possibly leaking!")));
|
|
}
|
|
|
|
|
|
//
|
|
// Start DNS lookup, assuming this is a server name. If it's an IP
|
|
// address, this call will fail and we'll use inet_addr() instead.
|
|
// This mechanism allows us to specify server names that are
|
|
// all-numeric. inet_addr() interprets a single number as an IP
|
|
// address (see inet_addr() documentation in MSDN).
|
|
//
|
|
TRC_NRM((TB, _T("Doing DNS lookup for '%s'"), _UI.ansiAddress));
|
|
_UI.disconnectReason = UI_MAKE_DISCONNECT_ERR(UI_ERR_GHBNFAILED);
|
|
|
|
_UI.hGHBN = WSAAsyncGetHostByName(_UI.hwndMain,
|
|
UI_WSA_GETHOSTBYNAME,
|
|
_UI.ansiAddress,
|
|
(char*)_pHostData,
|
|
MAXGETHOSTSTRUCT);
|
|
if (_UI.hGHBN == 0)
|
|
{
|
|
//
|
|
// Failed to start the async operation. Free the buffer here
|
|
// an find out what went wrong.
|
|
//
|
|
LocalFree(_pHostData);
|
|
_pHostData = NULL;
|
|
|
|
TRC_ALT((TB, _T("Failed to initiate GetHostByName")));
|
|
UIGoDisconnected(UI_MAKE_DISCONNECT_ERR(UI_ERR_DNSLOOKUPFAILED), TRUE);
|
|
DC_QUIT;
|
|
}
|
|
|
|
//
|
|
// Now just wait for the callback.
|
|
//
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
} // UIStartDNSLookup
|
|
|
|
|
|
//
|
|
// Name: UIGoDisconnected
|
|
//
|
|
// Purpose: Tail processing for disconnection process
|
|
// Does final cleanup, hides connection windows etc
|
|
//
|
|
// Params: IN disconnectID - disconnection error code
|
|
// IN fFireEvent - true to fire a disconnect event
|
|
//
|
|
// Operation: Called from UI_OnDisconnected, or whenever the UI cannot
|
|
// start or continue the connection process.
|
|
//
|
|
void DCINTERNAL CUI::UIGoDisconnected(unsigned disconnectID, BOOL fFireEvent)
|
|
{
|
|
BOOL rc = FALSE;
|
|
|
|
DC_BEGIN_FN("UIGoDisconnected");
|
|
|
|
TRC_NRM((TB, _T("disconnectID %#x"), disconnectID));
|
|
|
|
//
|
|
// make sure that all timers are dead
|
|
//
|
|
if (_UI.connectStruct.hSingleConnectTimer) {
|
|
_pUt->UTDeleteTimer(_UI.connectStruct.hSingleConnectTimer);
|
|
_UI.connectStruct.hSingleConnectTimer = NULL;
|
|
}
|
|
if (_UI.connectStruct.hConnectionTimer) {
|
|
_pUt->UTDeleteTimer(_UI.connectStruct.hConnectionTimer);
|
|
_UI.connectStruct.hConnectionTimer = NULL;
|
|
}
|
|
if(_UI.connectStruct.hLicensingTimer) {
|
|
_pUt->UTDeleteTimer(_UI.connectStruct.hLicensingTimer);
|
|
_UI.connectStruct.hLicensingTimer = NULL;
|
|
}
|
|
|
|
|
|
UI_OnInputFocusLost(0);
|
|
// Tell the Client extension dll of the disconnection
|
|
_clx->CLX_OnDisconnected(disconnectID);
|
|
|
|
//
|
|
// Set watch flag so we can determine if the user tried to connect
|
|
// from the event handler
|
|
//
|
|
_UI.fConnectCalledWatch = FALSE;
|
|
|
|
//
|
|
// Notify Ax control of the disconnection
|
|
//
|
|
if (fFireEvent && IsWindow(_UI.hWndCntrl)) {
|
|
rc = SendMessage(_UI.hWndCntrl,
|
|
WM_TS_DISCONNECTED,
|
|
(WPARAM)disconnectID,
|
|
0);
|
|
|
|
//
|
|
// Bail out immediately AND avoid touching any instance
|
|
// data as we may have been deleted in the event fired
|
|
// to the outside world
|
|
//
|
|
if (!rc) {
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
|
|
|
|
if (!UI_IsAutoReconnecting() && !_UI.fConnectCalledWatch) {
|
|
TRC_NRM((TB,_T("Not autoreconnecting doing tail cleanup!")));
|
|
|
|
UIFinishDisconnection();
|
|
|
|
#ifdef USE_BBAR
|
|
if (_pBBar) {
|
|
_pBBar->KillAndCleanupBBar();
|
|
}
|
|
#endif
|
|
}
|
|
else {
|
|
TRC_NRM((TB,_T("Skipping tail disconnect: arc: %d - conwatch: %d"),
|
|
UI_IsAutoReconnecting(),
|
|
_UI.fConnectCalledWatch));
|
|
}
|
|
|
|
//
|
|
// Reset connect watch flag
|
|
//
|
|
_UI.fConnectCalledWatch = FALSE;
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
} // UIGoDisconnected
|
|
|
|
|
|
//
|
|
// Name: UIFinishDisconnection
|
|
//
|
|
// Purpose: Do final actions for disconnection and put up connection
|
|
// dialog ready for next connection (or just exit if we
|
|
// auto-connected or if we're on WinCE).
|
|
//
|
|
void DCINTERNAL CUI::UIFinishDisconnection()
|
|
{
|
|
DC_BEGIN_FN("UIFinishDisconnection");
|
|
|
|
#ifndef OS_WINCE
|
|
//
|
|
// For WinCE, the connect dialog is not brought up again - we're about
|
|
// to quit.
|
|
//
|
|
if (_UI.connectionStatus == UI_STATUS_CONNECTED)
|
|
{
|
|
TRC_NRM((TB, _T("Hiding main window and bringing up connection dialog")));
|
|
// We do ShowWindow twice for the main window because the first
|
|
// call can be ignored if the main window was maximized.
|
|
ShowWindow(_UI.hwndContainer, SW_HIDE);
|
|
ShowWindow(_UI.hwndMain, SW_HIDE);
|
|
ShowWindow(_UI.hwndMain, SW_HIDE);
|
|
}
|
|
#endif //OS_WINCE
|
|
|
|
if(_pHostData &&
|
|
_UI.connectionStatus != UI_STATUS_CONNECT_PENDING_DNS &&
|
|
_UI.connectionStatus != UI_STATUS_CONNECT_PENDING)
|
|
{
|
|
//
|
|
// We're done with the winsock buffer
|
|
//
|
|
LocalFree(_pHostData);
|
|
_pHostData = NULL;
|
|
}
|
|
else if (_pHostData &&
|
|
_UI.connectionStatus == UI_STATUS_CONNECT_PENDING_DNS) {
|
|
if (!UIFreeAsyncDNSBuffer()) {
|
|
TRC_ERR((TB,
|
|
_T("Failed to free async dns buffer. Status: %d hghbn: 0x%x"),
|
|
_UI.connectionStatus, _UI.hGHBN));
|
|
}
|
|
}
|
|
|
|
|
|
TRC_NRM((TB, _T("Set disconnected state")));
|
|
UISetConnectionStatus(UI_STATUS_DISCONNECTED);
|
|
|
|
DC_END_FN();
|
|
} // UIFinishDisconnection
|
|
|
|
//
|
|
// IsConnectingToOwnAddress
|
|
// return true if this is an attempt to reconnect to our
|
|
// own address.
|
|
// e.g On PTS doing a loopback
|
|
// or on server doing a loopback with /CONSOLE
|
|
//
|
|
BOOL CUI::IsConnectingToOwnAddress(u_long connectAddr)
|
|
{
|
|
DC_BEGIN_FN("IsConnectingToOwnConsole");
|
|
|
|
//
|
|
// Check if this is a loopback connection attempt
|
|
//
|
|
|
|
//32-bit form of 127.0.0.1 addr
|
|
#define LOOPBACK_ADDR ((u_long)0x0100007f)
|
|
|
|
//
|
|
// First the quick check for localhost/127.0.0.1
|
|
//
|
|
if( LOOPBACK_ADDR == connectAddr)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// More extensive check, i.e resolve the local hostname
|
|
//
|
|
|
|
char hostname[(512+1)*sizeof(TCHAR)];
|
|
int err;
|
|
int j;
|
|
struct hostent* phostent;
|
|
|
|
err=gethostname(hostname, sizeof(hostname));
|
|
if (err == 0)
|
|
{
|
|
if ((phostent = gethostbyname(hostname)) !=NULL)
|
|
{
|
|
switch (phostent->h_addrtype)
|
|
{
|
|
case AF_INET:
|
|
j=0;
|
|
while (phostent->h_addr_list[j] != NULL)
|
|
{
|
|
if(!memcmp(&connectAddr,
|
|
phostent->h_addr_list[j],
|
|
sizeof(u_long)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
j++;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CUI::IsRunningOnPTS()
|
|
{
|
|
DC_BEGIN_FN("IsRunningOnPTS");
|
|
|
|
#ifndef OS_WINCE
|
|
if(UI_GetOsMinorType() == TS_OSMINORTYPE_WINDOWS_NT)
|
|
{
|
|
OSVERSIONINFOEX osVer;
|
|
memset(&osVer, 0, sizeof(OSVERSIONINFOEX));
|
|
osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
if(GetVersionEx( (LPOSVERSIONINFO ) &osVer))
|
|
{
|
|
return ((osVer.wProductType == VER_NT_WORKSTATION) &&
|
|
!(osVer.wSuiteMask & VER_SUITE_PERSONAL) &&
|
|
(osVer.wSuiteMask & VER_SUITE_SINGLEUSERTS));
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("GetVersionEx failed: 0x%x"),
|
|
GetLastError()));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//can't be PTS if its not NT
|
|
return FALSE;
|
|
}
|
|
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
//
|
|
// Do the work of initializing or reinitializing
|
|
// the Input idle timers
|
|
//
|
|
BOOL CUI::InitInputIdleTimer(LONG minsToTimeout)
|
|
{
|
|
DC_BEGIN_FN("InitInputIdleTimer");
|
|
|
|
TRC_ASSERT(_UI.hwndMain,
|
|
(TB,_T("InitInputIdleTimer called before main window is up")));
|
|
if(minsToTimeout < MAX_MINS_TOIDLETIMEOUT)
|
|
{
|
|
//Reset the marker indicating if input was sent
|
|
_pIh->IH_ResetInputWasSentFlag();
|
|
|
|
//Reset any existing idle timer
|
|
if(_UI.hIdleInputTimer)
|
|
{
|
|
HANDLE hTimer = _UI.hIdleInputTimer;
|
|
_UI.hIdleInputTimer = NULL;
|
|
_UI.minsToIdleTimeout = 0;
|
|
if(!_pUt->UTDeleteTimer( hTimer ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
if(minsToTimeout)
|
|
{
|
|
_UI.hIdleInputTimer = _pUt->UTCreateTimer(
|
|
_UI.hwndMain,
|
|
UI_TIMER_IDLEINPUTTIMEOUT,
|
|
minsToTimeout * 60 * 1000 );
|
|
if(_UI.hIdleInputTimer)
|
|
{
|
|
if(_pUt->UTStartTimer( _UI.hIdleInputTimer ))
|
|
{
|
|
_UI.minsToIdleTimeout = minsToTimeout;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("UTStartTimer hIdleInputTimer failed")));
|
|
_UI.minsToIdleTimeout = 0;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("UTCreateTimer hIdleInputTimer failed")));
|
|
_UI.minsToIdleTimeout = 0;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//We've reset the timer and no new one
|
|
//was requested
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
#ifdef USE_BBAR
|
|
//
|
|
// Set or update the bbar unhide timer
|
|
// based on the last mouse move
|
|
//
|
|
// Params:
|
|
// x - mouse x pos
|
|
// y - mouse y pos
|
|
//
|
|
VOID CUI::UISetBBarUnhideTimer(LONG x, LONG y)
|
|
{
|
|
DC_BEGIN_FN("IHSetBBarUnhideTimer");
|
|
|
|
TRC_ASSERT(_UI.hwndMain,
|
|
(TB,_T("hwndMain is NULL")));
|
|
|
|
if (_UI.fBBarEnabled && _pBBar && _pBBar->IsRaised())
|
|
{
|
|
LONG dx = x-_ptBBarLastMousePos.x;
|
|
LONG dy = y-_ptBBarLastMousePos.y;
|
|
LONG rr = dx*dx + dy*dy;
|
|
LONG dd = GetSystemMetrics(SM_CXDOUBLECLK) *
|
|
GetSystemMetrics(SM_CYDOUBLECLK);
|
|
|
|
if (rr > dd)
|
|
{
|
|
_fBBarUnhideTimerActive = TRUE;
|
|
SetTimer(_UI.hwndMain,
|
|
UI_TIMER_BBAR_UNHIDE_TIMERID,
|
|
IH_BBAR_UNHIDE_TIMEINTERVAL,
|
|
NULL);
|
|
_ptBBarLastMousePos.x = x;
|
|
_ptBBarLastMousePos.y = y;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(_fBBarUnhideTimerActive)
|
|
{
|
|
KillTimer( _UI.hwndMain,
|
|
UI_TIMER_BBAR_UNHIDE_TIMERID );
|
|
_fBBarUnhideTimerActive = FALSE;
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
#endif //USE_BBAR
|
|
|
|
|
|
#ifndef OS_WINCE
|
|
|
|
|
|
// TS detection code from MSDN and modified.
|
|
/* -------------------------------------------------------------
|
|
Note that the ValidateProductSuite and IsTerminalServices
|
|
functions use ANSI versions of Win32 functions to maintain
|
|
compatibility with Windows 95/98.
|
|
------------------------------------------------------------- */
|
|
/****************************************************************************/
|
|
/* Name: UIIsTSOnWin2KOrGreater */
|
|
/* */
|
|
/* Purpose: This function is called when we know that TS can be enabled */
|
|
/* but we need to see if TS is really enabled. */
|
|
/* It means: */
|
|
/* - not Win2K or above, then it's TS4 */
|
|
/* - Win2K or above: test if TS is installed */
|
|
/****************************************************************************/
|
|
BOOL CUI::UIIsTSOnWin2KOrGreater( VOID )
|
|
{
|
|
BOOL bResult = FALSE;
|
|
DWORD dwVersion;
|
|
OSVERSIONINFOEXA osVersion;
|
|
DWORDLONG dwlCondition = 0;
|
|
HMODULE hmodK32 = NULL;
|
|
HMODULE hmodNtDll = NULL;
|
|
typedef ULONGLONG (WINAPI *PFnVerSetCondition) (ULONGLONG, ULONG, UCHAR);
|
|
typedef BOOL (WINAPI *PFnVerifyVersionA) (POSVERSIONINFOEXA, DWORD, DWORDLONG);
|
|
PFnVerSetCondition pfnVerSetCondition;
|
|
PFnVerifyVersionA pfnVerifyVersionA;
|
|
|
|
dwVersion = GetVersion();
|
|
|
|
// Are we running Windows NT?
|
|
|
|
if (!(dwVersion & 0x80000000))
|
|
{
|
|
// Is it Windows 2000 or greater?
|
|
|
|
if (LOBYTE(LOWORD(dwVersion)) > 4)
|
|
{
|
|
// In Windows 2000, use the VerifyVersionInfo and
|
|
// VerSetConditionMask functions. Don't static link because
|
|
// it won't load on earlier systems.
|
|
|
|
hmodNtDll = GetModuleHandleA( "ntdll.dll" );
|
|
if (hmodNtDll)
|
|
{
|
|
pfnVerSetCondition = (PFnVerSetCondition) GetProcAddress(
|
|
hmodNtDll, "VerSetConditionMask");
|
|
if (pfnVerSetCondition != NULL)
|
|
{
|
|
dwlCondition = (*pfnVerSetCondition) (dwlCondition,
|
|
VER_SUITENAME, VER_OR);
|
|
|
|
// Get a VerifyVersionInfo pointer.
|
|
|
|
hmodK32 = GetModuleHandleA( "KERNEL32.DLL" );
|
|
if (hmodK32 != NULL)
|
|
{
|
|
pfnVerifyVersionA = (PFnVerifyVersionA) GetProcAddress(
|
|
hmodK32, "VerifyVersionInfoA") ;
|
|
if (pfnVerifyVersionA != NULL)
|
|
{
|
|
ZeroMemory(&osVersion, sizeof(osVersion));
|
|
osVersion.dwOSVersionInfoSize = sizeof(osVersion);
|
|
osVersion.wSuiteMask = VER_SUITE_TERMINAL | VER_SUITE_SINGLEUSERTS;
|
|
bResult = (*pfnVerifyVersionA) (&osVersion,
|
|
VER_SUITENAME, dwlCondition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else // This is Windows NT 4.0 or earlier.
|
|
// since we know that TS can be enabled, then it's TS4.
|
|
bResult = TRUE;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
#endif //OS_WINCE
|
|
|
|
#ifdef SMART_SIZING
|
|
//
|
|
// Notify the IH and OP of the desktop size change
|
|
// Params:
|
|
// size - lParam encoded size (LOWORD - width, HIWORD height)
|
|
//
|
|
void CUI::UI_NotifyOfDesktopSizeChange(LPARAM size)
|
|
{
|
|
DC_BEGIN_FN("UI_NotifyOfDesktopSizeChange");
|
|
|
|
//
|
|
// NOTE: Can only use async notifications from the UI thread
|
|
// otherwise the following can happen: SendMessage to
|
|
// another thread dispatches messages, this means that
|
|
// the containing app could receive a message to destroy
|
|
// the control (e.g Salem tests do this). Destroying
|
|
// the control while in a CD call is not a good thing.
|
|
// As we would blow up on return.
|
|
//
|
|
_pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT,
|
|
_pOp,
|
|
CD_NOTIFICATION_FUNC(COP,OP_MainWindowSizeChange),
|
|
(ULONG_PTR)size);
|
|
_pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
|
|
_pIh,
|
|
CD_NOTIFICATION_FUNC(CIH,IH_MainWindowSizeChange),
|
|
(ULONG_PTR)size);
|
|
|
|
DC_END_FN();
|
|
}
|
|
#endif //SMART_SIZING
|
|
|
|
//
|
|
// Free the ASYNC DNS buffer.
|
|
// If there is a pending async operation it is canceled first
|
|
//
|
|
// Returns: TRUE if the buffer was freed (or was already freed)
|
|
//
|
|
BOOL CUI::UIFreeAsyncDNSBuffer()
|
|
{
|
|
BOOL fFreeHostData = FALSE;
|
|
int intRC;
|
|
DC_BEGIN_FN("UIFreeAsyncDNSBuffer");
|
|
|
|
if (_UI.hGHBN) {
|
|
//
|
|
// Cancel the DNS lookup
|
|
//
|
|
TRC_NRM((TB, _T("Cancel DNS lookup")));
|
|
intRC = WSACancelAsyncRequest(_UI.hGHBN);
|
|
|
|
if (intRC == SOCKET_ERROR) {
|
|
TRC_NRM((TB, _T("Failed to cancel async DNS request")));
|
|
|
|
//
|
|
// Can't free the buffer here, because it may still be
|
|
// in use, or the request may have already completed
|
|
// and the completion message may still be in transit
|
|
// in which case the buffer will be freed when we receive
|
|
// the message.
|
|
//
|
|
} else {
|
|
fFreeHostData = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
fFreeHostData = TRUE;
|
|
}
|
|
|
|
if (fFreeHostData) {
|
|
//Succesfully canceled the request
|
|
//Free the buffer passed to winsock
|
|
if(_pHostData)
|
|
{
|
|
LocalFree(_pHostData);
|
|
_pHostData = NULL;
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
return fFreeHostData;
|
|
}
|
|
|