Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3577 lines
100 KiB

  1. //
  2. // uiapi.cpp
  3. //
  4. // UI Class
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. //
  8. #include <adcg.h>
  9. #define TRC_GROUP TRC_GROUP_UI
  10. #define TRC_FILE "uiapi"
  11. #include <atrcapi.h>
  12. #include "wui.h"
  13. #ifdef OS_WINCE
  14. #include <ceconfig.h>
  15. #endif
  16. extern "C"
  17. {
  18. #ifndef OS_WINCE
  19. #include <stdio.h>
  20. #endif // OS_WINCE
  21. }
  22. #include "clx.h"
  23. #include "aco.h"
  24. #include "nl.h"
  25. #include "autil.h"
  26. //
  27. // Debugging globals
  28. // Do not use these values for anything
  29. // but debugging
  30. //
  31. CObjs* g_pTscObjects = (CObjs*)-1;
  32. CUI* g_pUIObject = (CUI*)-1;
  33. LONG g_cUIref = 0;
  34. DWORD g_cUITotalCount = 0;
  35. #define DBG_EXIT_WITHACTIVE_REFS 0x0001
  36. #define DBG_STAT_UI_INIT_CALLED 0x0002
  37. #define DBG_STAT_UI_INIT_RET_PASS 0x0004
  38. #define DBG_STAT_UI_TERM_CALLED 0x0008
  39. #define DBG_STAT_UI_TERM_RETURNED 0x0010
  40. #define DBG_STAT_TERMTSC_SENT 0x0020
  41. #define DBG_STAT_UIREQUESTEDCLOSE_CALLED 0x0040
  42. #define DBG_STAT_UIREQUESTEDCLOSE_RET 0x0080
  43. #define DBG_STAT_UI_INIT_RET_FAIL 0x0100
  44. DWORD g_dwTscCoreDbgStatus = 0;
  45. #define UI_DBG_SETINFO(x) g_dwTscCoreDbgStatus |= x;
  46. CUI::CUI()
  47. {
  48. DC_BEGIN_FN("CUI");
  49. DC_MEMSET(&_UI, 0, sizeof(_UI));
  50. DC_MEMSET(&_drInitData, 0, sizeof(_drInitData));
  51. _Objects._pUiObject = this;
  52. //
  53. // Only used for debugging
  54. //
  55. g_pTscObjects = &_Objects;
  56. g_pUIObject = this;
  57. #ifdef DC_DEBUG
  58. //
  59. // This will dump debug output if there was a problem creating objects
  60. //
  61. _Objects.CheckPointers();
  62. #endif
  63. _pCo = _Objects._pCoObject;
  64. _pUt = _Objects._pUtObject;
  65. _clx = _Objects._pCLXObject;
  66. _pTd = _Objects._pTDObject;
  67. _pIh = _Objects._pIhObject;
  68. _pCd = _Objects._pCdObject;
  69. _pOp = _Objects._pOPObject;
  70. _pUh = _Objects._pUHObject;
  71. _pCChan = _Objects._pChanObject;
  72. #ifdef USE_BBAR
  73. _pBBar = NULL;
  74. _ptBBarLastMousePos.x = -0x0FFF;
  75. _ptBBarLastMousePos.y = -0x0FFF;
  76. _fBBarUnhideTimerActive = TRUE;
  77. #endif
  78. _pHostData = NULL;
  79. _fRecursiveScrollBarMsg = FALSE;
  80. _fRecursiveSizeMsg = FALSE;
  81. #ifndef OS_WINCE
  82. _dwLangBarFlags = 0;
  83. _fLangBarWasHidden = FALSE;
  84. _fIhHasFocus = FALSE;
  85. _pITLBM = NULL;
  86. _fLangBarStateSaved = FALSE;
  87. #endif
  88. _fTerminating = FALSE;
  89. #ifdef DC_DEBUG
  90. //
  91. // Important that these are set very early
  92. // otherwise the failure tables in UT will not be initialized
  93. // and mallocs could fail randomly
  94. //
  95. UI_SetRandomFailureItem(UT_FAILURE_MALLOC, 0);
  96. UI_SetRandomFailureItem(UT_FAILURE_MALLOC_HUGE, 0);
  97. #endif
  98. #ifndef OS_WINCE
  99. _pTaskBarList2 = NULL;
  100. _fQueriedForTaskBarList2 = FALSE;
  101. #endif
  102. _pArcUI = NULL;
  103. InterlockedIncrement(&g_cUIref);
  104. g_cUITotalCount++;
  105. DC_END_FN();
  106. }
  107. CUI::~CUI()
  108. {
  109. DC_BEGIN_FN("~CUI");
  110. if(_UI.pszVChanAddinDlls)
  111. {
  112. UT_Free(_pUt, _UI.pszVChanAddinDlls);
  113. }
  114. InterlockedDecrement(&g_cUIref);
  115. if(_Objects.CheckActiveReferences())
  116. {
  117. UI_DBG_SETINFO(DBG_EXIT_WITHACTIVE_REFS);
  118. TRC_ABORT((TB,_T("!!!!!****Deleting objs with outstanding references")));
  119. }
  120. #ifdef OS_WINCE
  121. UI_SetCompress(FALSE);
  122. #endif
  123. DC_END_FN();
  124. }
  125. //
  126. // API functions
  127. //
  128. //
  129. // Name: UI_Init
  130. //
  131. // Purpose: Creates the Main and Container windows and initializes the
  132. // Core and Component Decoupler
  133. //
  134. // Returns: HRESULT
  135. //
  136. // Params: IN - hInstance - window information
  137. // IN - hprevInstance
  138. //
  139. //
  140. HRESULT DCAPI CUI::UI_Init(HINSTANCE hInstance,
  141. HINSTANCE hPrevInstance,
  142. HINSTANCE hResInstance,
  143. HANDLE hEvtNotifyCoreInit)
  144. {
  145. WNDCLASS mainWindowClass;
  146. WNDCLASS containerWindowClass;
  147. WNDCLASS tmpWndClass;
  148. ATOM registerClassRc;
  149. DWORD dwStyle;
  150. DWORD dwExStyle = 0;
  151. #ifndef OS_WINCE
  152. OSVERSIONINFO osVersionInfo;
  153. #endif
  154. HRESULT hr = E_FAIL;
  155. #if !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
  156. UINT showCmd;
  157. #endif
  158. BOOL fAddedRef = FALSE;
  159. DC_BEGIN_FN("UI_Init");
  160. _fTerminating = FALSE;
  161. if(!_Objects.CheckPointers())
  162. {
  163. TRC_ERR((TB,_T("Objects not all setup")));
  164. hr = E_OUTOFMEMORY;
  165. DC_QUIT;
  166. }
  167. if(!hInstance && !hResInstance)
  168. {
  169. TRC_ERR((TB,_T("Instance pointer not specified")));
  170. hr = E_OUTOFMEMORY;
  171. DC_QUIT;
  172. }
  173. if(UI_IsCoreInitialized())
  174. {
  175. //Don't allow re-entrant core init
  176. //one example of how this can happen
  177. // Connect() method called.
  178. // Core init starts
  179. // Core init times out and fails in control
  180. // Core completes init (and is now initialized)
  181. // Connect() called again
  182. hr = E_FAIL;
  183. DC_QUIT;
  184. }
  185. _Objects.AddObjReference(UI_OBJECT_FLAG);
  186. fAddedRef = TRUE;
  187. UI_DBG_SETINFO(DBG_STAT_UI_INIT_CALLED);
  188. //
  189. // UI initialisation
  190. //
  191. TRC_DBG((TB, _T("UI initialising UT")));
  192. _pUt->UT_Init();
  193. //
  194. // Resources are in the executable. Keep this separate in case the
  195. // resources are moved to a separate DLL: in this case just call
  196. // GetModuleHandle() to get hResDllInstance.
  197. //
  198. _UI.hResDllInstance = hResInstance;
  199. TRC_ASSERT((0 != _UI.hResDllInstance), (TB,_T("Couldn't get res dll handle")));
  200. //
  201. // Initialize External DLL
  202. //
  203. _pUt->InitExternalDll();
  204. //
  205. // Register the class for the Main Window
  206. //
  207. if (!hPrevInstance &&
  208. !GetClassInfo(hInstance, UI_MAIN_CLASS, &tmpWndClass))
  209. {
  210. HICON hIcon= NULL;
  211. #if defined(OS_WIN32) && !defined(OS_WINCE)
  212. if(_UI.szIconFile[0] != 0)
  213. {
  214. hIcon = ExtractIcon(hResInstance, _UI.szIconFile, _UI.iconIndex);
  215. }
  216. if(NULL == hIcon)
  217. {
  218. hIcon = LoadIcon(hResInstance, MAKEINTRESOURCE(UI_IDI_MSTSC_ICON));
  219. }
  220. #else
  221. hIcon = LoadIcon(hResInstance, MAKEINTRESOURCE(UI_IDI_MSTSC_ICON));
  222. #endif
  223. TRC_NRM((TB, _T("Register Main Window class")));
  224. mainWindowClass.style = 0;
  225. mainWindowClass.lpfnWndProc = UIStaticMainWndProc;
  226. mainWindowClass.cbClsExtra = 0;
  227. mainWindowClass.cbWndExtra = sizeof(void*); //store 'this' pointer
  228. mainWindowClass.hInstance = hInstance;
  229. mainWindowClass.hIcon = hIcon;
  230. mainWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  231. mainWindowClass.hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
  232. mainWindowClass.lpszMenuName = NULL;
  233. mainWindowClass.lpszClassName = UI_MAIN_CLASS;
  234. registerClassRc = RegisterClass (&mainWindowClass);
  235. if (registerClassRc == 0)
  236. {
  237. hr = HRESULT_FROM_WIN32(GetLastError());
  238. TRC_ERR((TB,_T("RegisterClass failed: 0x%x"), hr));
  239. DC_QUIT;
  240. }
  241. }
  242. #ifdef OS_WINCE
  243. dwStyle = WS_VSCROLL |
  244. WS_HSCROLL |
  245. WS_CLIPCHILDREN;
  246. #else // OS_WINCE
  247. dwStyle = WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN | WS_SYSMENU;
  248. //
  249. // Main window is child to control main window.
  250. //
  251. dwStyle = dwStyle | WS_CHILD | WS_CLIPSIBLINGS;
  252. #endif // OS_WINCE
  253. //
  254. // Create the main window Initialize the window size from the
  255. // windowPlacement. Will be recalculated to allow for scrollbars or
  256. // fullscreen mode later.
  257. //
  258. // Note that on Win16, the SetWindowPlacement below will cause the
  259. // window to be shown if its position or size are changed (even though
  260. // we explicitly specify SW_HIDE). We avoid this by setting the window
  261. // position on creation to be the same as that set later by
  262. // SetWindowPlacement.
  263. //
  264. _UI.hwndMain = CreateWindow(
  265. UI_MAIN_CLASS, // window class name
  266. _UI.szFullScreenTitle, // window caption
  267. dwStyle, // window style
  268. _UI.windowPlacement.rcNormalPosition.left,
  269. _UI.windowPlacement.rcNormalPosition.top,
  270. _UI.windowPlacement.rcNormalPosition.right -
  271. _UI.windowPlacement.rcNormalPosition.left,
  272. _UI.windowPlacement.rcNormalPosition.bottom -
  273. _UI.windowPlacement.rcNormalPosition.top,
  274. _UI.hWndCntrl, // parent window handle
  275. NULL, // window menu handle
  276. hInstance, // program inst handle
  277. this ); // creation parameters
  278. TRC_NRM((TB, _T("Main Window handle: %p"), _UI.hwndMain));
  279. if (_UI.hwndMain == NULL)
  280. {
  281. hr = HRESULT_FROM_WIN32(GetLastError());
  282. TRC_ERR((TB,_T("CreateWindow failed: 0x%x"), hr));
  283. DC_QUIT;
  284. }
  285. #ifndef OS_WINCE
  286. HMENU hSysMenu = GetSystemMenu( _UI.hwndMain, FALSE);
  287. if(hSysMenu)
  288. {
  289. //
  290. // Always disable the move item on the window menu
  291. // Window menu only appears if the control goes fullscreen
  292. // in the non-container handled fullscreen case.
  293. //
  294. EnableMenuItem((HMENU)hSysMenu, SC_MOVE,
  295. MF_GRAYED | MF_BYCOMMAND);
  296. }
  297. #endif
  298. //
  299. // Register the Container class
  300. //
  301. TRC_DBG((TB, _T("Registering Container window class")));
  302. if (!hPrevInstance &&
  303. !GetClassInfo(hInstance, UI_CONTAINER_CLASS, &tmpWndClass))
  304. {
  305. TRC_NRM((TB, _T("Register class")));
  306. containerWindowClass.style = CS_HREDRAW | CS_VREDRAW;
  307. containerWindowClass.lpfnWndProc = UIStaticContainerWndProc;
  308. containerWindowClass.cbClsExtra = 0;
  309. containerWindowClass.cbWndExtra = sizeof(void*); //store 'this'
  310. containerWindowClass.hInstance = hInstance;
  311. containerWindowClass.hIcon = NULL;
  312. containerWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  313. containerWindowClass.hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
  314. containerWindowClass.lpszMenuName = NULL;
  315. containerWindowClass.lpszClassName = UI_CONTAINER_CLASS;
  316. registerClassRc = RegisterClass(&containerWindowClass);
  317. if (registerClassRc == 0)
  318. {
  319. //
  320. // Failed to register container window so terminate app
  321. //
  322. hr = HRESULT_FROM_WIN32(GetLastError());
  323. TRC_ERR((TB,_T("RegisterClass failed: 0x%x"), hr));
  324. DC_QUIT;
  325. }
  326. }
  327. #ifndef OS_WINCE
  328. osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
  329. dwExStyle = WS_EX_NOPARENTNOTIFY;
  330. if (GetVersionEx(&osVersionInfo) &&
  331. osVersionInfo.dwMajorVersion >= 5)
  332. {
  333. //
  334. // Only allow this style on NT5+ as otherwise the
  335. // create window can fail
  336. //
  337. dwExStyle |= WS_EX_NOINHERITLAYOUT;
  338. }
  339. #else
  340. dwExStyle = 0;
  341. #endif
  342. //
  343. // Create the Container Window
  344. //
  345. TRC_DBG((TB, _T("Creating Container Window")));
  346. _UI.hwndContainer = CreateWindowEx(
  347. dwExStyle,
  348. UI_CONTAINER_CLASS,
  349. NULL,
  350. WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  351. 0,
  352. 0,
  353. _UI.containerSize.width,
  354. _UI.containerSize.height,
  355. _UI.hwndMain,
  356. NULL,
  357. hInstance,
  358. this );
  359. if (_UI.hwndContainer == NULL)
  360. {
  361. //
  362. // Failed to create container window so terminate app
  363. //
  364. TRC_ERR((TB,_T("CreateWindowEx for container failed 0x%x"),
  365. GetLastError()));
  366. hr = HRESULT_FROM_WIN32(GetLastError());
  367. TRC_ERR((TB,_T("CreateWindowEx failed: 0x%x"), hr));
  368. DC_QUIT;
  369. }
  370. #if defined (OS_WINCE)
  371. /********************************************************************/
  372. /* Disable IME */
  373. /* IME is different on 98/NT than on WinCE, on 98/NT one call to */
  374. /* DisableIME is enough for entire process, on WinCE we must call it*/
  375. /* on each window thread that is running to disable it. */
  376. /********************************************************************/
  377. DisableIME(_UI.hwndContainer);
  378. #endif
  379. #if !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
  380. UISetMinMaxPlacement();
  381. showCmd = _UI.windowPlacement.showCmd;
  382. _UI.windowPlacement.showCmd = SW_HIDE;
  383. SetWindowPlacement(_UI.hwndMain, &_UI.windowPlacement);
  384. _UI.windowPlacement.showCmd = showCmd;
  385. #endif // !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
  386. UISmoothScrollingSettingChanged();
  387. #ifndef OS_WINCE
  388. //
  389. // Set up our lovely Cicero interface
  390. //
  391. HRESULT hrLangBar = CoCreateInstance(CLSID_TF_LangBarMgr, NULL,
  392. CLSCTX_INPROC_SERVER, IID_ITfLangBarMgr, (void **)&_pITLBM);
  393. TRC_DBG((TB, _T("CoCreateInstance(CLSID_TF_LangBarMgr) hr= 0x%08xl"), hr));
  394. if (FAILED(hrLangBar))
  395. {
  396. _pITLBM = NULL;
  397. }
  398. #endif
  399. //
  400. // Initialize Core, much of this will happen
  401. // asynchrously. An event will be signaled when core init has completed
  402. //
  403. TRC_DBG((TB, _T("UI Initialising Core")));
  404. _pCo->CO_Init(hInstance, _UI.hwndMain, _UI.hwndContainer);
  405. UI_DBG_SETINFO(DBG_STAT_UI_INIT_RET_PASS);
  406. hr = S_OK;
  407. if (!DuplicateHandle(
  408. GetCurrentProcess(),
  409. hEvtNotifyCoreInit,
  410. GetCurrentProcess(),
  411. &_UI.hEvtNotifyCoreInit,
  412. 0,
  413. FALSE,
  414. DUPLICATE_SAME_ACCESS)) {
  415. hr = HRESULT_FROM_WIN32(GetLastError());
  416. // Hack: Increment the objects reference count as it will be
  417. // released again on UI_TERM
  418. _Objects.AddObjReference(UI_OBJECT_FLAG);
  419. TRC_ERR((TB, _T("Duplicate handle call failed. hr = 0x%x"), hr));
  420. DC_QUIT;
  421. }
  422. DC_EXIT_POINT:
  423. if (FAILED(hr))
  424. {
  425. if (fAddedRef)
  426. {
  427. _Objects.ReleaseObjReference(UI_OBJECT_FLAG);
  428. }
  429. UI_DBG_SETINFO(DBG_STAT_UI_INIT_RET_FAIL);
  430. }
  431. DC_END_FN();
  432. return hr;
  433. }
  434. //
  435. // Name: UI_ResetState
  436. //
  437. // Purpose: Resets all UI state in this component
  438. //
  439. //
  440. // Returns: Nothing
  441. //
  442. // Params: Nothing
  443. //
  444. //
  445. //
  446. DCVOID DCAPI CUI::UI_ResetState()
  447. {
  448. DC_MEMSET(&_UI, 0, sizeof(_UI));
  449. DC_MEMSET(&_drInitData, 0, sizeof(_drInitData));
  450. UIInitializeDefaultSettings();
  451. }
  452. //
  453. // Name: UI_Connect
  454. //
  455. // Purpose: Connects with current settings
  456. //
  457. // Returns: HRESULT
  458. //
  459. // Params: Nothing
  460. //
  461. //
  462. //
  463. HRESULT DCAPI CUI::UI_Connect(CONNECTIONMODE connMode)
  464. {
  465. DC_BEGIN_FN("UI_Connect");
  466. if(!UI_IsCoreInitialized())
  467. {
  468. TRC_ERR((TB,_T("Attempt to connect before core intialize")));
  469. return E_FAIL;
  470. }
  471. //Reset server error state
  472. UI_SetServerErrorInfo( TS_ERRINFO_NOERROR );
  473. //Initialiaze the RDPDR settings struct
  474. //this gets reset on each connection
  475. //rdpdr gets passed down a pointer to the struct
  476. //when it is initialized
  477. UI_InitRdpDrSettings();
  478. //Clean up the load balance redirect state
  479. if (!UI_IsAutoReconnecting()) {
  480. TRC_NRM((TB,_T("Cleaning up LB state")));
  481. UI_CleanupLBState();
  482. }
  483. else {
  484. TRC_NRM((TB,_T("AutoReconnecting don't cleanup lb state")));
  485. }
  486. _fRecursiveSizeMsg = FALSE;
  487. #ifndef OS_WINCE
  488. _fLangBarStateSaved = FALSE;
  489. #endif
  490. InitInputIdleTimer( UI_GetMinsToIdleTimeout() );
  491. _fRecursiveScrollBarMsg = FALSE;
  492. if (UIValidateCurrentParams(connMode))
  493. {
  494. TRC_NRM((TB, _T("Connecting")));
  495. UISetConnectionStatus(UI_STATUS_DISCONNECTED);
  496. _pCo->CO_SetConfigurationValue( CO_CFG_ACCELERATOR_PASSTHROUGH,
  497. _UI.acceleratorCheckState );
  498. _pCo->CO_SetHotkey(&(_UI.hotKey));
  499. _pCo->CO_SetConfigurationValue( CO_CFG_ENCRYPTION,
  500. _UI.encryptionEnabled);
  501. UIShadowBitmapSettingChanged();
  502. #ifdef DC_DEBUG
  503. UI_CoreDebugSettingChanged();
  504. #endif // DC_DEBUG
  505. #ifdef USE_BBAR
  506. if(!_pBBar)
  507. {
  508. _pBBar = new CBBar( _UI.hwndMain,
  509. UI_GetInstanceHandle(),
  510. this,
  511. _UI.fBBarEnabled);
  512. }
  513. if(!_pBBar)
  514. {
  515. TRC_ERR((TB,_T("Alloc for CBBar failed")));
  516. return E_OUTOFMEMORY;
  517. }
  518. _pBBar->SetPinned( _UI.fBBarPinned );
  519. _pBBar->SetShowMinimize(UI_GetBBarShowMinimize());
  520. _pBBar->SetShowRestore(UI_GetBBarShowRestore());
  521. //
  522. // Set the display name here instead of OnConnected so it
  523. // doesn't change w.r.t to redirections (which can change strAddress)
  524. //
  525. _pBBar->SetDisplayedText( _UI.strAddress );
  526. #endif
  527. //
  528. // Errors from the connection are
  529. // signaled by Disconnect's that are fired
  530. // with the appropriate disconnect code
  531. //
  532. UIConnectWithCurrentParams(connMode);
  533. return S_OK;
  534. }
  535. else
  536. {
  537. TRC_ALT((TB, _T("UIValidateCurrentParams failed: not auto-connecting")));
  538. return E_FAIL;
  539. }
  540. DC_END_FN();
  541. }
  542. //
  543. // Name: UI_Term
  544. //
  545. // Purpose: Calls _pCo->CO_Term and CD_Term and destroys the main window
  546. //
  547. // Returns: HRESULT
  548. //
  549. // Params: None
  550. //
  551. //
  552. HRESULT DCAPI CUI::UI_Term(DCVOID)
  553. {
  554. HWND hwndTmp = NULL;
  555. HWND hwndHasFocus = NULL;
  556. DC_BEGIN_FN("UI_Term");
  557. UI_DBG_SETINFO(DBG_STAT_UI_TERM_CALLED);
  558. if(!UI_IsCoreInitialized())
  559. {
  560. return E_FAIL;
  561. }
  562. _fTerminating = TRUE;
  563. #ifdef OS_WINCE
  564. //
  565. // Some device are failing to restore the correct palette when the TSC
  566. // exits. In an attempt to correct this behavior, we'll send the
  567. // necessary message to the shell that will prompt its DefWindowProc to
  568. // re-realize the correct palette. Non WBT only
  569. //
  570. if (g_CEConfig != CE_CONFIG_WBT)
  571. {
  572. hwndTmp = FindWindow(TEXT("DesktopExplorerWindow"), 0);
  573. if(0 != hwndTmp)
  574. {
  575. PostMessage(hwndTmp, WM_QUERYNEWPALETTE, 0, 0);
  576. hwndTmp = 0;
  577. }
  578. }
  579. #endif // OS_WINCE
  580. //
  581. // Here's a problem. - _pCo->CO_Term terminates the SND thread (causes
  582. // call to SND_Term) - SND_Term calls IH_Term - IH_Term calls
  583. // DestroyWindow to destroy the input window - Because the input window
  584. // has the focus, DestroyWindow calls SendMessage to set the focus to
  585. // its parent.
  586. //
  587. // Now we have a deadly embrace: UI thread is waiting for SND thread to
  588. // terminate; SND thread is waiting for UI thread to process
  589. // SendMessage.
  590. //
  591. // The solution is to set the focus to the UI window here, so that the
  592. // input window no longer has the focus when it is destroyed, so that
  593. // DestroyWindow doesn't call SendMessage.
  594. //
  595. // WinCE has the additional problem that it doesn't set the focus to
  596. // another application correctly when mstsc exits. (Something about
  597. // not being able to SendMessage a WM_FOCUS during thread exit). So in
  598. // that case we hide the main window, which removes the need for a
  599. // separate SetFocus call.
  600. //
  601. #ifndef OS_WINCE
  602. //
  603. // Only steal the focus if our IH has it, otherwise
  604. // there is no deadlock above. The main reason for not stealing
  605. // the focus is that in mutli-instance environments e.g the MMC snapin
  606. // stealing focus from another session is a bad thing (especially if the
  607. // session we are stealing the focus from is the one the user is working on)
  608. //
  609. hwndHasFocus = GetFocus();
  610. if(hwndHasFocus &&
  611. (hwndHasFocus == UI_GetInputWndHandle() ||
  612. hwndHasFocus == UI_GetBmpCacheMonitorHandle()))
  613. {
  614. TRC_NRM((TB,_T("Setting focus to main window to prevent deadlock")));
  615. SetFocus(_UI.hwndMain);
  616. }
  617. #else // OS_WINCE
  618. ShowWindow(_UI.hwndMain, SW_HIDE);
  619. #endif // OS_WINCE
  620. ShowWindow(_UI.hwndMain, SW_HIDE);
  621. //
  622. // The next lines appear to Destroy the windows OK. In the past this
  623. // has not been the case. If the process hangs in future then the fix
  624. // is to comment out the DestroyWindows.
  625. //
  626. // Note we null out our copies of the window handle before doing the
  627. // destroy to stop anyone accessing it during the detroy processing.
  628. //
  629. //
  630. // Very important to destory the windows before terminating the core
  631. // to prevent messages from getting processed while we are terminating
  632. //
  633. TRC_NRM((TB, _T("Destroying windows...")));
  634. hwndTmp = _UI.hwndContainer;
  635. _UI.hwndContainer = NULL;
  636. if(hwndTmp)
  637. {
  638. DestroyWindow(hwndTmp);
  639. }
  640. hwndTmp = _UI.hwndMain;
  641. _UI.hwndMain = NULL;
  642. if(hwndTmp)
  643. {
  644. DestroyWindow(hwndTmp);
  645. }
  646. //
  647. // Terminate the Core and Component Decoupler
  648. //
  649. TRC_DBG((TB, _T("UI Terminating Core")));
  650. _pCo->CO_Term();
  651. //
  652. // Free the decompression receive context (if any)
  653. //
  654. if (_UI.pRecvContext2) {
  655. UT_Free(_pUt, _UI.pRecvContext2);
  656. _UI.pRecvContext2 = NULL;
  657. }
  658. //
  659. // Clear and free any autoreconnect cookies
  660. //
  661. UI_SetAutoReconnectCookie(NULL, 0);
  662. TRC_NRM((TB, _T("Destroyed windows")));
  663. UnregisterClass(UI_MAIN_CLASS, UI_GetInstanceHandle());
  664. UnregisterClass(UI_CONTAINER_CLASS, UI_GetInstanceHandle());
  665. //
  666. // Cleanup any timers that are hanging around
  667. //
  668. if( _UI.connectStruct.hConnectionTimer )
  669. {
  670. _pUt->UTDeleteTimer( _UI.connectStruct.hConnectionTimer );
  671. _UI.connectStruct.hConnectionTimer = NULL;
  672. }
  673. if( _UI.connectStruct.hSingleConnectTimer )
  674. {
  675. _pUt->UTDeleteTimer( _UI.connectStruct.hSingleConnectTimer );
  676. _UI.connectStruct.hSingleConnectTimer = NULL;
  677. }
  678. if( _UI.connectStruct.hLicensingTimer )
  679. {
  680. _pUt->UTDeleteTimer( _UI.connectStruct.hLicensingTimer );
  681. _UI.connectStruct.hLicensingTimer = NULL;
  682. }
  683. if (_UI.hDisconnectTimeout)
  684. {
  685. _pUt->UTDeleteTimer( _UI.hDisconnectTimeout );
  686. _UI.hDisconnectTimeout = NULL;
  687. }
  688. //
  689. // Free up BSTRs (if any) used by redirection
  690. //
  691. if (_UI.bstrRedirectionLBInfo)
  692. {
  693. SysFreeString(_UI.bstrRedirectionLBInfo);
  694. _UI.bstrRedirectionLBInfo = NULL;
  695. }
  696. if (_UI.bstrScriptedLBInfo)
  697. {
  698. SysFreeString(_UI.bstrScriptedLBInfo);
  699. _UI.bstrRedirectionLBInfo = NULL;
  700. }
  701. #ifndef OS_WINCE
  702. if (_pITLBM != NULL)
  703. {
  704. _pITLBM->Release();
  705. _pITLBM = NULL;
  706. }
  707. #endif
  708. #ifdef USE_BBAR
  709. if( _pBBar )
  710. {
  711. delete _pBBar;
  712. _pBBar = NULL;
  713. }
  714. #endif
  715. //
  716. // Release our cached interface ptr to the taskbar
  717. //
  718. #ifndef OS_WINCE
  719. if (_pTaskBarList2)
  720. {
  721. _pTaskBarList2->Release();
  722. _pTaskBarList2 = NULL;
  723. }
  724. #endif
  725. //
  726. // Release reference to control parent
  727. //
  728. UI_SetControlInstance(NULL);
  729. //
  730. // Cleanup our state to allow re-initialisation
  731. //
  732. UI_ResetState();
  733. _Objects.ReleaseObjReference(UI_OBJECT_FLAG);
  734. UI_DBG_SETINFO(DBG_STAT_UI_TERM_RETURNED);
  735. DC_END_FN();
  736. return S_OK;
  737. } // UI_Term
  738. //
  739. // Name: UI_FatalError
  740. //
  741. // Purpose: notify control that a fatal error has occurred
  742. //
  743. // Returns: None
  744. //
  745. // Params: IN error - error code
  746. //
  747. //
  748. DCVOID DCAPI CUI::UI_FatalError(DCINT error)
  749. {
  750. DC_BEGIN_FN("UI_FatalError");
  751. TRC_ERR((TB, _T("Fatal Error - code %d"), error));
  752. //
  753. // Notify the control that a fatal error has ocurred
  754. //
  755. SendMessage(_UI.hWndCntrl,WM_TS_FATALERROR,(WPARAM)error,0);
  756. //
  757. // Container should pop up a dialog and give the user
  758. // the choice of exiting or launching a debugger..
  759. // continuing after this point will usually lead to a crash
  760. // as the errors are indeed fatal....
  761. //
  762. DC_END_FN();
  763. return;
  764. } // UI_FatalError
  765. //
  766. // Name: UI_DisplayBitmapCacheWarning
  767. //
  768. // Purpose: Display a bitmap cache warning popup
  769. //
  770. // Returns: None
  771. //
  772. // Params: IN unusedParm
  773. //
  774. //
  775. void DCAPI CUI::UI_DisplayBitmapCacheWarning(ULONG_PTR unusedParm)
  776. {
  777. DC_BEGIN_FN("UI_DisplayBitmapCacheWarning");
  778. DC_IGNORE_PARAMETER(unusedParm);
  779. //
  780. // Notify the control that a warning has ocurred
  781. // pass the warn code for bitmap cache
  782. //
  783. SendMessage(_UI.hWndCntrl,WM_TS_WARNING,
  784. (WPARAM)DC_WARN_BITMAPCACHE_CORRUPTED,0);
  785. DC_END_FN();
  786. } // UI_DisplayBitmapCacheWarning
  787. //Called when the desktop size has changed..e.g in response
  788. //to a shadow.
  789. //pDesktopSize contains the new desktop size
  790. void DCAPI CUI::UI_OnDesktopSizeChange(PDCSIZE pDesktopSize)
  791. {
  792. DC_BEGIN_FN("UI_OnShadowDesktopSizeChange");
  793. TRC_ASSERT(pDesktopSize, (TB,_T("UI_OnShadowDesktopSizeChange received NULL desktop size")));
  794. if(pDesktopSize)
  795. {
  796. if (pDesktopSize->width != _UI.desktopSize.width ||
  797. pDesktopSize->height != _UI.desktopSize.height)
  798. {
  799. UI_SetDesktopSize( pDesktopSize);
  800. #ifdef SMART_SIZING
  801. //
  802. // Notify OP and IH
  803. //
  804. LPARAM newSize = MAKELONG(_UI.mainWindowClientSize.width,
  805. _UI.mainWindowClientSize.height);
  806. UI_NotifyOfDesktopSizeChange( newSize );
  807. #endif
  808. //Notify the control of the change
  809. SendMessage(_UI.hWndCntrl, WM_TS_DESKTOPSIZECHANGE,
  810. (WPARAM)pDesktopSize->width,
  811. (LPARAM)pDesktopSize->height);
  812. }
  813. }
  814. DC_END_FN();
  815. }
  816. //
  817. // Get default langID
  818. //
  819. DCLANGID CUI::UIGetDefaultLangID()
  820. {
  821. #if defined(OS_WIN32)
  822. LANGID LangId;
  823. LangId = GetSystemDefaultLangID();
  824. switch (PRIMARYLANGID(LangId)) {
  825. case LANG_JAPANESE: return DC_LANG_JAPANESE; break;
  826. case LANG_KOREAN: return DC_LANG_KOREAN; break;
  827. case LANG_CHINESE:
  828. switch (SUBLANGID(LangId)) {
  829. case SUBLANG_CHINESE_TRADITIONAL: return DC_LANG_CHINESE_TRADITIONAL; break;
  830. case SUBLANG_CHINESE_SIMPLIFIED: return DC_LANG_CHINESE_SIMPLIFIED; break;
  831. }
  832. }
  833. #else // defined(OS_WIN32)
  834. DCUINT acp;
  835. acp = GetKBCodePage();
  836. switch (acp) {
  837. case 932: return DC_LANG_JAPANESE; break;
  838. case 949: return DC_LANG_KOREAN; break;
  839. case 950: return DC_LANG_CHINESE_TRADITIONAL; break;
  840. case 936: return DC_LANG_CHINESE_SIMPLIFIED; break;
  841. }
  842. #endif // defined(OS_WIN32)
  843. return DC_LANG_UNKNOWN;
  844. }
  845. //
  846. // Get default IME file name
  847. //
  848. DCUINT CUI::UIGetDefaultIMEFileName(PDCTCHAR imeFileName, DCUINT Size)
  849. {
  850. DCTCHAR DefaultIMEStr[MAX_PATH];
  851. DCUINT intRC;
  852. DCUINT stringID = 0;
  853. switch (UIGetDefaultLangID()) {
  854. case DC_LANG_JAPANESE: stringID = UI_IDS_IME_NAME_JPN; break;
  855. case DC_LANG_KOREAN: stringID = UI_IDS_IME_NAME_KOR; break;
  856. case DC_LANG_CHINESE_TRADITIONAL: stringID = UI_IDS_IME_NAME_CHT; break;
  857. case DC_LANG_CHINESE_SIMPLIFIED: stringID = UI_IDS_IME_NAME_CHS; break;
  858. }
  859. if (stringID) {
  860. intRC = LoadString(_UI.hResDllInstance,
  861. stringID,
  862. DefaultIMEStr,
  863. MAX_PATH);
  864. if (intRC) {
  865. if (intRC + 1< Size) {
  866. StringCchCopy(imeFileName, Size, DefaultIMEStr);
  867. return intRC;
  868. }
  869. else {
  870. *imeFileName = _T('\0');
  871. return intRC;
  872. }
  873. }
  874. }
  875. return 0;
  876. }
  877. //
  878. // Get IME Mapping table name
  879. //
  880. DCUINT CUI::UIGetIMEMappingTableName(PDCTCHAR ImeMappingTableName, DCUINT Size)
  881. {
  882. DCUINT len;
  883. PDCTCHAR string = NULL;
  884. switch (UIGetDefaultLangID()) {
  885. case DC_LANG_JAPANESE: string = UTREG_IME_MAPPING_TABLE_JPN; break;
  886. case DC_LANG_KOREAN: string = UTREG_IME_MAPPING_TABLE_KOR; break;
  887. case DC_LANG_CHINESE_TRADITIONAL: string = UTREG_IME_MAPPING_TABLE_CHT; break;
  888. case DC_LANG_CHINESE_SIMPLIFIED: string = UTREG_IME_MAPPING_TABLE_CHS; break;
  889. }
  890. if (string) {
  891. if ( (len=DC_TSTRLEN(string)) < Size - 1) {
  892. StringCchCopy(ImeMappingTableName, Size, string);
  893. return len;
  894. }
  895. else {
  896. *ImeMappingTableName = _T('\0');
  897. return len;
  898. }
  899. }
  900. return 0;
  901. }
  902. //
  903. // Disable IME
  904. //
  905. VOID CUI::DisableIME(HWND hwnd)
  906. {
  907. #if defined(OS_WIN32)
  908. if (_pUt->lpfnImmAssociateContext != NULL)
  909. {
  910. _pUt->lpfnImmAssociateContext(hwnd, (HIMC)NULL);
  911. }
  912. #else // defined(OS_WIN32)
  913. if (_pUt->lpfnWINNLSEnableIME != NULL)
  914. {
  915. _pUt->lpfnWINNLSEnableIME(hwnd, FALSE);
  916. }
  917. #endif // defined(OS_WIN32)
  918. }
  919. //
  920. // Get IME file name
  921. //
  922. VOID CUI::UIGetIMEFileName(PDCTCHAR imeFileName, DCUINT cchSize)
  923. {
  924. HRESULT hr;
  925. DC_BEGIN_FN("UIGetIMEFileName");
  926. #if defined(OS_WIN32)
  927. imeFileName[0] = _T('\0');
  928. #if !defined(OS_WINCE) || defined(OS_WINCE_KEYBOARD_LAYOUT)
  929. {
  930. if (_pUt->UT_ImmGetIMEFileName(CicSubstGetKeyboardLayout(NULL),
  931. imeFileName, cchSize) > 0)
  932. {
  933. /*
  934. * For Win95 issue
  935. * If IME name have contains "$$$.DLL",
  936. * then this is a process IME (i.e EXE type)
  937. */
  938. PDCTCHAR str = DC_TSTRCHR(imeFileName, _T('$'));
  939. if (str != NULL)
  940. {
  941. if (DC_TSTRCMP(str, _T("$$$.DLL")) == 0)
  942. {
  943. UIGetIMEFileName16(imeFileName, cchSize);
  944. }
  945. }
  946. else
  947. {
  948. /*
  949. * For NT3.51-J issue
  950. * If IME name have contains ".EXE",
  951. * then this is a process IME (i.e EXE type)
  952. */
  953. PDCTCHAR str = DC_TSTRCHR(imeFileName, _T('.'));
  954. if (str != NULL)
  955. {
  956. if (DC_TSTRCMP(str, _T(".EXE")) == 0)
  957. {
  958. UIGetIMEFileName16(imeFileName, cchSize);
  959. }
  960. else
  961. {
  962. DCUINT len;
  963. DCTCHAR MappedImeFileName[MAX_PATH];
  964. DCTCHAR ImeMappingTableName[MAX_PATH];
  965. //
  966. // Now look for this key in the [IME Mapping Table] section of
  967. // the client's INI file
  968. //
  969. len = UIGetIMEMappingTableName(ImeMappingTableName,
  970. sizeof(ImeMappingTableName)/sizeof(DCTCHAR));
  971. if (len != 0 &&
  972. len < sizeof(ImeMappingTableName)/sizeof(DCTCHAR)) {
  973. *MappedImeFileName = _T('\0');
  974. _pUt->UT_ReadRegistryString(ImeMappingTableName,
  975. imeFileName,
  976. NULL,
  977. MappedImeFileName,
  978. sizeof(MappedImeFileName)/sizeof(DCTCHAR));
  979. if (*MappedImeFileName) {
  980. hr = StringCchCopy(imeFileName, cchSize,
  981. MappedImeFileName);
  982. }
  983. }
  984. }
  985. }
  986. }
  987. }
  988. }
  989. #else // !defined(OS_WINCE) || defined(OS_WINCE_KEYBOARD_LAYOUT)
  990. UIGetDefaultIMEFileName(imeFileName, Size);
  991. #endif // !defined(OS_WINCE) || defined(OS_WINCE_KEYBOARD_LAYOUT)
  992. #else // defined(OS_WIN32)
  993. UIGetIMEFileName16(imeFileName, Size);
  994. #endif // defined(OS_WIN32)
  995. DC_END_FN();
  996. }
  997. #if !defined(OS_WINCE)
  998. //
  999. // Get IME file name for WINNLS functionality
  1000. //
  1001. VOID CUI::UIGetIMEFileName16(PDCTCHAR imeFileName, DCUINT Size)
  1002. {
  1003. IMEPRO IMEPro;
  1004. DCTCHAR DefaultImeFileName[MAX_PATH];
  1005. DCTCHAR ImeMappingTableName[MAX_PATH];
  1006. DCUINT intRC;
  1007. DC_BEGIN_FN("UIGetIMEFileName16");
  1008. imeFileName[0] = _T('\0');
  1009. {
  1010. if (_pUt->UT_IMPGetIME(NULL, &IMEPro) == 0)
  1011. {
  1012. TRC_ERR((TB, _T("Fatal Error - IMPGetIME returns FALSE")));
  1013. }
  1014. else
  1015. {
  1016. /*
  1017. * Get file name of 8.3 form, if include directory path in IMEPro.szName
  1018. */
  1019. DCTCHAR szBuffer[MAX_PATH];
  1020. PDCTCHAR imeFilePart;
  1021. _pUt->UT_GetFullPathName((PDCTCHAR)IMEPro.szName, sizeof(szBuffer)/sizeof(DCTCHAR),
  1022. szBuffer, &imeFilePart);
  1023. //
  1024. // Now look for this key in the [IME Mapping Table] section of
  1025. // the client's INI file
  1026. //
  1027. intRC = UIGetDefaultIMEFileName(DefaultImeFileName,
  1028. sizeof(DefaultImeFileName)/sizeof(DCTCHAR));
  1029. if (intRC && *DefaultImeFileName) {
  1030. DCUINT len;
  1031. len = UIGetIMEMappingTableName(ImeMappingTableName,
  1032. sizeof(ImeMappingTableName)/sizeof(DCTCHAR));
  1033. if (len != 0 &&
  1034. len < sizeof(ImeMappingTableName)/sizeof(DCTCHAR)) {
  1035. _pUt->UT_ReadRegistryString(ImeMappingTableName,
  1036. imeFilePart,
  1037. DefaultImeFileName,
  1038. imeFileName,
  1039. Size);
  1040. }
  1041. }
  1042. }
  1043. }
  1044. DC_END_FN();
  1045. }
  1046. #endif // !defined(OS_WINCE)
  1047. //
  1048. // Static window procs
  1049. //
  1050. LRESULT CALLBACK CUI::UIStaticMainWndProc (HWND hwnd, UINT message,
  1051. WPARAM wParam, LPARAM lParam)
  1052. {
  1053. CUI* pUI = (CUI*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1054. if(WM_CREATE == message)
  1055. {
  1056. //pull out the this pointer and stuff it in the window class
  1057. LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
  1058. pUI = (CUI*)lpcs->lpCreateParams;
  1059. SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)pUI);
  1060. }
  1061. //
  1062. // Delegate the message to the appropriate instance
  1063. //
  1064. if(pUI)
  1065. {
  1066. return pUI->UIMainWndProc(hwnd, message, wParam, lParam);
  1067. }
  1068. else
  1069. {
  1070. return DefWindowProc(hwnd, message, wParam, lParam);
  1071. }
  1072. }
  1073. LRESULT CALLBACK CUI::UIStaticContainerWndProc (HWND hwnd, UINT message,
  1074. WPARAM wParam, LPARAM lParam)
  1075. {
  1076. CUI* pUI = (CUI*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1077. if(WM_CREATE == message)
  1078. {
  1079. //pull out the this pointer and stuff it in the window class
  1080. LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
  1081. pUI = (CUI*)lpcs->lpCreateParams;
  1082. SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)pUI);
  1083. }
  1084. if(pUI)
  1085. {
  1086. return pUI->UIContainerWndProc(hwnd, message, wParam, lParam);
  1087. }
  1088. else
  1089. {
  1090. return DefWindowProc(hwnd, message, wParam, lParam);
  1091. }
  1092. }
  1093. //
  1094. // Callbacks
  1095. //
  1096. //
  1097. // Name: UI_OnCoreInitialized
  1098. //
  1099. // Purpose: For the CD to inform the UI that the Core has initialized
  1100. //
  1101. DCVOID DCAPI CUI::UI_OnCoreInitialized(ULONG_PTR unused)
  1102. {
  1103. #ifndef OS_WINCE
  1104. BOOL bPrevMenustate;
  1105. #endif // OS_WINCE
  1106. HWND hwndDlgItem = NULL;
  1107. HWND hwndAddress = NULL;
  1108. DC_BEGIN_FN("UI_OnCoreInitialized");
  1109. DC_IGNORE_PARAMETER(unused);
  1110. DC_EXIT_POINT:
  1111. _UI.fOnCoreInitializeEventCalled = TRUE;
  1112. //
  1113. // Notify the IH of the size since there is a small window
  1114. // when the core hasn't been intitialized but we receive
  1115. // the WM_SIZE's that size the control and so the IH
  1116. // would not have received the correct sizes
  1117. //
  1118. ULONG_PTR size = MAKELONG(_UI.mainWindowClientSize.width,
  1119. _UI.mainWindowClientSize.height);
  1120. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  1121. _pIh,
  1122. CD_NOTIFICATION_FUNC(CIH,IH_SetVisibleSize),
  1123. (ULONG_PTR)size);
  1124. DC_END_FN();
  1125. return;
  1126. } // UI_OnCoreInitialised
  1127. //
  1128. // Name: UI_OnInputFocusLost
  1129. //
  1130. // Purpose: When the IH loses the input
  1131. //
  1132. // Returns: Nothing
  1133. //
  1134. // Params: None
  1135. //
  1136. //
  1137. DCVOID DCAPI CUI::UI_OnInputFocusLost(ULONG_PTR unused)
  1138. {
  1139. DC_BEGIN_FN("UI_OnInputFocusLost");
  1140. DC_IGNORE_PARAMETER(unused);
  1141. TRC_DBG((TB, _T("UI_OnInputFocusLost called")));
  1142. if (_fIhHasFocus)
  1143. {
  1144. _fIhHasFocus = FALSE;
  1145. #ifndef OS_WINCE
  1146. if (!UI_IsFullScreen())
  1147. {
  1148. UI_RestoreLangBar();
  1149. }
  1150. #endif
  1151. }
  1152. }
  1153. //
  1154. // Name: UI_OnInputFocusGained
  1155. //
  1156. // Purpose: When the IH gets the input
  1157. //
  1158. // Returns: Nothing
  1159. //
  1160. // Params: None
  1161. //
  1162. //
  1163. DCVOID DCAPI CUI::UI_OnInputFocusGained(ULONG_PTR unused)
  1164. {
  1165. DC_BEGIN_FN("UI_OnInputFocusGained");
  1166. DC_IGNORE_PARAMETER(unused);
  1167. TRC_DBG((TB, _T("UI_OnInputFocusGained called")));
  1168. TRC_ALT((TB, _T("UI_OnInputFocusGained gain _fIhHas=%d"),_fIhHasFocus));
  1169. if (!_fIhHasFocus)
  1170. {
  1171. _fIhHasFocus = TRUE;
  1172. #ifndef OS_WINCE
  1173. if (!UI_IsFullScreen())
  1174. {
  1175. UI_HideLangBar();
  1176. }
  1177. #endif
  1178. }
  1179. else
  1180. {
  1181. TRC_ERR((TB,_T("OnInputFocusGained called when we already have focus")));
  1182. }
  1183. DC_END_FN();
  1184. }
  1185. //
  1186. // Hides the lang bar if not already hidden
  1187. // saves previous lang bar state
  1188. //
  1189. #ifndef OS_WINCE
  1190. void CUI::UI_HideLangBar()
  1191. {
  1192. DC_BEGIN_FN("UI_HideLangBar");
  1193. if (_pITLBM != NULL)
  1194. {
  1195. HRESULT hr;
  1196. hr = _pITLBM->GetShowFloatingStatus(&_dwLangBarFlags);
  1197. TRC_ALT((TB,_T("Hiding langbar GetShow: 0x%x"), _dwLangBarFlags));
  1198. if (SUCCEEDED(hr))
  1199. {
  1200. _fLangBarStateSaved = TRUE;
  1201. _fLangBarWasHidden = _dwLangBarFlags & TF_SFT_HIDDEN;
  1202. if (!_fLangBarWasHidden)
  1203. {
  1204. hr = _pITLBM->ShowFloating(TF_SFT_HIDDEN);
  1205. if (FAILED(hr))
  1206. {
  1207. TRC_ERR((TB,_T("ShowFloating failed: 0x%x"),
  1208. hr));
  1209. }
  1210. }
  1211. }
  1212. }
  1213. DC_END_FN();
  1214. }
  1215. #endif
  1216. //
  1217. // Restores lang bar state to that set before hiding
  1218. // in UI_HideLangBar
  1219. //
  1220. //
  1221. #ifndef OS_WINCE
  1222. void CUI::UI_RestoreLangBar()
  1223. {
  1224. DC_BEGIN_FN("UI_RestoreLangBar");
  1225. TRC_ALT((TB,_T("Restore _dwLangBarFlags: 0x%x _fWasHid:%d _fSaved:%d"),
  1226. _dwLangBarFlags, _fLangBarWasHidden, _fLangBarStateSaved));
  1227. if (_pITLBM != NULL)
  1228. {
  1229. HRESULT hr;
  1230. if (!_fLangBarWasHidden && _fLangBarStateSaved)
  1231. {
  1232. hr = _pITLBM->ShowFloating(_dwLangBarFlags);
  1233. if (FAILED(hr))
  1234. {
  1235. TRC_ERR((TB,_T("ShowFloating failed: 0x%x"),
  1236. hr));
  1237. }
  1238. }
  1239. }
  1240. DC_END_FN();
  1241. }
  1242. #endif
  1243. //
  1244. // Name: UI_OnConnected
  1245. //
  1246. // Purpose: For the CD to inform the UI of connection success
  1247. // and to enable the disconnect menu item
  1248. //
  1249. // Returns: Nothing
  1250. //
  1251. // Params: None
  1252. //
  1253. //
  1254. DCVOID DCAPI CUI::UI_OnConnected(ULONG_PTR unused)
  1255. {
  1256. BOOL fWasAutoReconnect = FALSE;
  1257. DC_BEGIN_FN("UI_OnConnected");
  1258. DC_IGNORE_PARAMETER(unused);
  1259. TRC_DBG((TB, _T("UI_OnConnected called")));
  1260. //
  1261. // Make sure the shutdown timer isn't hanging around
  1262. //
  1263. if (0 != _UI.shutdownTimer)
  1264. {
  1265. TRC_NRM((TB, _T("Killing shutdown timer")));
  1266. KillTimer(_UI.hwndMain, _UI.shutdownTimer);
  1267. _UI.shutdownTimer = 0;
  1268. }
  1269. //OnConnected can also be called if we are already connected
  1270. //we only want to fire an event to the Ax control on the
  1271. //initial connect action.
  1272. DCBOOL fJustConnected = (_UI.connectionStatus == UI_STATUS_CONNECT_PENDING) ||
  1273. (_UI.connectionStatus == UI_STATUS_PENDING_CONNECTENDPOINT);
  1274. //
  1275. // Notify the CLX test harness of the actual connection
  1276. // address and other interesting ARC/Redirection info
  1277. //
  1278. _clx->CLX_ConnectEx(
  1279. _UI.strAddress,
  1280. UI_IsAutoReconnecting(),
  1281. UI_IsClientRedirected(),
  1282. UI_GetRedirectedLBInfo()
  1283. );
  1284. //
  1285. // Dismiss the autoreconnection dialog if we get
  1286. // connected
  1287. //
  1288. if (_pArcUI) {
  1289. fWasAutoReconnect = TRUE;
  1290. UI_StopAutoReconnectDlg();
  1291. }
  1292. UISetConnectionStatus(UI_STATUS_CONNECTED);
  1293. //
  1294. // Set the disconnection reason - now we are connected, we don't expect
  1295. // a disconnect, unless user-initiated.
  1296. //
  1297. _UI.disconnectReason =
  1298. UI_MAKE_DISCONNECT_ERR(UI_ERR_UNEXPECTED_DISCONNECT);
  1299. //
  1300. // Update the screen mode (do not grab the focus here)
  1301. //
  1302. UIUpdateScreenMode( FALSE );
  1303. //
  1304. // Show the Main Window. Put this here so that the main window is seen
  1305. // only on connection
  1306. //
  1307. ShowWindow(_UI.hwndMain, SW_SHOW);
  1308. UISmoothScrollingSettingChanged();
  1309. //
  1310. // Show the Container Window.
  1311. //
  1312. ShowWindow(_UI.hwndContainer, SW_SHOW);
  1313. #ifdef OS_WINCE
  1314. //
  1315. // WinCE doesn't send a WM_SHOWINDOW to the Container, so do that work
  1316. //
  1317. SetFocus(_UI.hwndContainer);
  1318. #endif
  1319. //
  1320. // Tell the Client extension dll of the connection
  1321. //
  1322. _clx->CLX_OnConnected();
  1323. //
  1324. // On first connection set the fullscreen state
  1325. // note that UI_OnConnected also fires after logon
  1326. // don't reset the fullscreen state as the user may
  1327. // have changed it.
  1328. //
  1329. if (fJustConnected)
  1330. {
  1331. if (UI_GetStartFullScreen())
  1332. {
  1333. if (!UI_IsFullScreen())
  1334. {
  1335. UI_GoFullScreen();
  1336. }
  1337. }
  1338. else
  1339. {
  1340. //
  1341. // If a previous connection left us fullscreen
  1342. // leave fullscreen
  1343. //
  1344. if (UI_IsFullScreen())
  1345. {
  1346. UI_LeaveFullScreen();
  1347. }
  1348. }
  1349. }
  1350. //
  1351. // We're done with the winsock hostname
  1352. // buffer at this point.
  1353. //
  1354. #ifdef OS_WINCE
  1355. if (_pHostData)
  1356. {
  1357. #endif
  1358. LocalFree(_pHostData);
  1359. _pHostData = NULL;
  1360. #ifdef OS_WINCE
  1361. }
  1362. else
  1363. {
  1364. TRC_ERR((TB,_T("_pHostData is NULL")));
  1365. }
  1366. #endif
  1367. #ifdef SMART_SIZING
  1368. //
  1369. // Notify OP and IH
  1370. //
  1371. LPARAM newSize = MAKELONG(_UI.mainWindowClientSize.width,
  1372. _UI.mainWindowClientSize.height);
  1373. UI_NotifyOfDesktopSizeChange( newSize );
  1374. #endif
  1375. //Inform the ActiveX control of the connection
  1376. //so it can fire an event to it's container
  1377. if(IsWindow(_UI.hWndCntrl))
  1378. {
  1379. //
  1380. // Only notify it's a new connection.
  1381. //
  1382. if(fJustConnected)
  1383. {
  1384. SendMessage(_UI.hWndCntrl,WM_TS_CONNECTED,0,0);
  1385. #ifdef USE_BBAR
  1386. if (_pBBar) {
  1387. _pBBar->SetEnabled(_UI.fBBarEnabled);
  1388. _pBBar->SetShowMinimize(UI_GetBBarShowMinimize());
  1389. _pBBar->SetShowRestore(UI_GetBBarShowRestore());
  1390. if (!_pBBar->StartupBBar(_UI.desktopSize.width,
  1391. _UI.desktopSize.height,
  1392. TRUE)) {
  1393. // BBar is a security feature drop link if it can't start
  1394. TRC_ERR((TB,_T("BBar failed to init disconnecting")));
  1395. UIGoDisconnected(_UI.disconnectReason, TRUE);
  1396. }
  1397. }
  1398. #endif
  1399. }
  1400. }
  1401. //
  1402. // Make sure we have the focus after a screen mode toggle
  1403. // and after the container has been notified of the connection
  1404. // (so it has a chance to restore the window if it was minimized)
  1405. // Otherwise we can hit problems because we can't assign focus to
  1406. // the minimized Container then IH window. Also the BBar won't start
  1407. // lowering if we connect in the minimized state.
  1408. //
  1409. if(_UI.fGrabFocusOnConnect)
  1410. {
  1411. HWND hwndPrevFocus;
  1412. TRC_NRM((TB,_T("CONNECT GRAB focus")));
  1413. hwndPrevFocus = SetFocus(_UI.hwndContainer);
  1414. TRC_NRM((TB,_T("SetFocus to container, prev focus 0x%x gle 0x%x"),
  1415. hwndPrevFocus, GetLastError()));
  1416. }
  1417. DC_END_FN();
  1418. return;
  1419. } // UI_OnConnected
  1420. //
  1421. // Name: UI_OnDeactivateAllPDU
  1422. //
  1423. // Purpose: For the CD to inform the UI of DeactivateAllPDU
  1424. //
  1425. //
  1426. // Returns: Nothing
  1427. //
  1428. // Params: reason (unused)
  1429. //
  1430. //
  1431. DCVOID DCAPI CUI::UI_OnDeactivateAllPDU(ULONG_PTR reason)
  1432. {
  1433. DC_BEGIN_FN("UI_OnDeactivateAllPDU");
  1434. TRC_NRM((TB, _T("DeactivateAllPDU received")));
  1435. DC_IGNORE_PARAMETER(reason);
  1436. _UI.disconnectReason = UI_MAKE_DISCONNECT_ERR(UI_ERR_NORMAL_DISCONNECT);
  1437. //
  1438. // Create a timer to ensure that we either get disconnected
  1439. // or reconnected in a reasonable time interval otherwise
  1440. // force a disconnect (Because the user can be left hanging with
  1441. // a disabled client).
  1442. //
  1443. if (_UI.hDisconnectTimeout)
  1444. {
  1445. _pUt->UTDeleteTimer( _UI.hDisconnectTimeout );
  1446. _UI.hDisconnectTimeout = NULL;
  1447. }
  1448. _UI.hDisconnectTimeout = _pUt->UTCreateTimer(
  1449. _UI.hwndMain,
  1450. UI_TIMER_DISCONNECT_TIMERID,
  1451. UI_TOTAL_DISCONNECTION_TIMEOUT);
  1452. if (_UI.hDisconnectTimeout)
  1453. {
  1454. _pUt->UTStartTimer( _UI.hDisconnectTimeout );
  1455. }
  1456. else
  1457. {
  1458. TRC_ERR((TB,_T("Failed to create disconnect timer")));
  1459. }
  1460. DC_END_FN();
  1461. return;
  1462. } // UI_OnDeactivateAllPDU
  1463. //
  1464. // Name: UI_OnDemandActivePDU
  1465. //
  1466. // Purpose: For the CD to inform the UI of DemandActivePDU
  1467. //
  1468. //
  1469. // Returns: Nothing
  1470. //
  1471. // Params: reason (unused)
  1472. //
  1473. //
  1474. DCVOID DCAPI CUI::UI_OnDemandActivePDU(ULONG_PTR reason)
  1475. {
  1476. DCUINT32 sessionId;
  1477. DC_BEGIN_FN("UI_OnDemandActivePDU");
  1478. TRC_NRM((TB, _T("DemandActivePDU received")));
  1479. DC_IGNORE_PARAMETER(reason);
  1480. if (_UI.hDisconnectTimeout )
  1481. {
  1482. _pUt->UTDeleteTimer( _UI.hDisconnectTimeout );
  1483. _UI.hDisconnectTimeout = NULL;
  1484. }
  1485. _UI.disconnectReason =
  1486. UI_MAKE_DISCONNECT_ERR(UI_ERR_UNEXPECTED_DISCONNECT);
  1487. //
  1488. // Notify CLX the reconnected session Id if client reconnects a session
  1489. //
  1490. sessionId = UI_GetSessionId();
  1491. if (sessionId) {
  1492. UI_OnLoginComplete();
  1493. }
  1494. DC_END_FN();
  1495. return;
  1496. } // UI_OnDemandActivePDU
  1497. //
  1498. // UI_OnSecurityExchangeComplete
  1499. //
  1500. // For the SL to notify us that the security exchange has completed
  1501. //
  1502. DCVOID DCAPI CUI::UI_OnSecurityExchangeComplete(ULONG_PTR reason)
  1503. {
  1504. DC_BEGIN_FN("UI_OnSecurityExchangeComplete");
  1505. //
  1506. // stop the single and overall connection timer and start the licensing
  1507. // timer. This has to happen on the UI thread as otherwise there could
  1508. // be a race between the timers popping and the SL directly modifying
  1509. // them (see ntbug9!160001)
  1510. //
  1511. if( _UI.connectStruct.hSingleConnectTimer)
  1512. {
  1513. _pUt->UTStopTimer( _UI.connectStruct.hSingleConnectTimer);
  1514. }
  1515. if( _UI.connectStruct.hConnectionTimer )
  1516. {
  1517. _pUt->UTStopTimer( _UI.connectStruct.hConnectionTimer );
  1518. }
  1519. if( _UI.connectStruct.hLicensingTimer )
  1520. {
  1521. _pUt->UTStartTimer( _UI.connectStruct.hLicensingTimer );
  1522. }
  1523. DC_END_FN();
  1524. }
  1525. //
  1526. // UI_OnLicensingComplete
  1527. //
  1528. // For the SL to notify us that the licensing has completed
  1529. //
  1530. DCVOID DCAPI CUI::UI_OnLicensingComplete(ULONG_PTR reason)
  1531. {
  1532. DC_BEGIN_FN("UI_OnLicensingComplete");
  1533. //
  1534. // stop the licensing timer.
  1535. // This has to happen on the UI thread as otherwise there could
  1536. // be a race between the timers popping and the SL directly modifying
  1537. // them (see ntbug9!160001)
  1538. //
  1539. if( _UI.connectStruct.hLicensingTimer )
  1540. {
  1541. _pUt->UTStopTimer( _UI.connectStruct.hLicensingTimer );
  1542. }
  1543. DC_END_FN();
  1544. }
  1545. //
  1546. // Name: UI_OnDisconnected
  1547. //
  1548. // Purpose: For the CD to inform the UI of disconnection
  1549. //
  1550. void DCAPI CUI::UI_OnDisconnected(ULONG_PTR disconnectID)
  1551. {
  1552. unsigned mainDiscReason;
  1553. DC_BEGIN_FN("UI_OnDisconnected");
  1554. TRC_NRM((TB, _T("Disconnected with Id %#x"), disconnectID));
  1555. //
  1556. // Make sure the shutdown timer isn't hanging around
  1557. //
  1558. if (0 != _UI.shutdownTimer)
  1559. {
  1560. TRC_NRM((TB, _T("Killing shutdown timer")));
  1561. KillTimer(_UI.hwndMain, _UI.shutdownTimer);
  1562. _UI.shutdownTimer = 0;
  1563. }
  1564. if (_UI.hDisconnectTimeout )
  1565. {
  1566. _pUt->UTDeleteTimer( _UI.hDisconnectTimeout );
  1567. _UI.hDisconnectTimeout = NULL;
  1568. }
  1569. //Disable and free any idle input timers
  1570. InitInputIdleTimer(0);
  1571. //
  1572. // Restore the lang bar to it's previous state
  1573. // this is important because we won't always receive
  1574. // an OnFocusLost notification from the IH (e.g if it is
  1575. // in the disabled state when it loses focus)
  1576. //
  1577. #ifndef OS_WINCE
  1578. UI_RestoreLangBar();
  1579. #endif
  1580. //
  1581. // Special case for error handling:
  1582. // if we get disconnected while the connection is still pending
  1583. // with a network error the most likely case is that the server
  1584. // broke the link because (a) connections are disabled or (b)
  1585. // max number of connections exceeded. We can't actually send
  1586. // back status from the server at this early stage in the connection
  1587. // so instead we just make a very educated 'guess' on the client.
  1588. // UI shells should parse this error code and display the likely
  1589. // error cases:
  1590. // Server does not allow connections/max number of connections exceeded
  1591. // Network error
  1592. //
  1593. if (TS_ERRINFO_NOERROR == UI_GetServerErrorInfo() &&
  1594. UI_STATUS_CONNECT_PENDING == _UI.connectionStatus &&
  1595. NL_MAKE_DISCONNECT_ERR(NL_ERR_TDFDCLOSE) == disconnectID)
  1596. {
  1597. TRC_NRM((TB, _T(" Setting error info to TS_ERRINFO_SERVER_DENIED_CONNECTION")));
  1598. if (_UI.fUseFIPS) {
  1599. UI_SetServerErrorInfo( TS_ERRINFO_SERVER_DENIED_CONNECTION_FIPS );
  1600. }
  1601. else {
  1602. UI_SetServerErrorInfo( TS_ERRINFO_SERVER_DENIED_CONNECTION );
  1603. }
  1604. }
  1605. // When server redirection is in progress, we simply to the redirection
  1606. // without translating disconnection codes or anything else.
  1607. if (_UI.DoRedirection) {
  1608. TRC_NRM((TB,_T("DoRedirection set, doing it")));
  1609. //
  1610. // Free the previous connection's host name lookup
  1611. // buffer before continuing.
  1612. //
  1613. if(_pHostData)
  1614. {
  1615. LocalFree(_pHostData);
  1616. _pHostData = NULL;
  1617. }
  1618. UIRedirectConnection();
  1619. }
  1620. else if ((_UI.connectionStatus == UI_STATUS_CONNECT_PENDING) ||
  1621. (_UI.connectionStatus == UI_STATUS_CONNECT_PENDING_DNS)) {
  1622. // Try the next connection. Pass the disconnect code on unless we
  1623. // already have a UI-specific code that we can use. This code will
  1624. // be used if we have tried all the IP addresses.
  1625. TRC_NRM((TB, _T("ConnectPending: try next IP address?")));
  1626. if ((_UI.disconnectReason ==
  1627. UI_MAKE_DISCONNECT_ERR(UI_ERR_UNEXPECTED_DISCONNECT)) ||
  1628. (_UI.disconnectReason ==
  1629. UI_MAKE_DISCONNECT_ERR(UI_ERR_NORMAL_DISCONNECT)) ||
  1630. (NL_GET_MAIN_REASON_CODE(_UI.disconnectReason) !=
  1631. UI_DISCONNECT_ERROR))
  1632. {
  1633. _UI.disconnectReason = disconnectID;
  1634. }
  1635. UITryNextConnection();
  1636. }
  1637. else {
  1638. TRC_NRM((TB, _T("Disconnect id %#x/%#x"),
  1639. _UI.disconnectReason, disconnectID));
  1640. // See if this is due to an 'expected' disconnect - such as a
  1641. // timeout.
  1642. if (_UI.disconnectReason ==
  1643. UI_MAKE_DISCONNECT_ERR(UI_ERR_UNEXPECTED_DISCONNECT)) {
  1644. // Unexpected disconnection - use the code passed in.
  1645. UIGoDisconnected(disconnectID, TRUE);
  1646. }
  1647. else if (_UI.disconnectReason ==
  1648. UI_MAKE_DISCONNECT_ERR(UI_ERR_NORMAL_DISCONNECT)) {
  1649. // Normal disconnection (ie we've received a DeactivateAllPDU).
  1650. // Use the reason code set by MCS if a DPUM has been received.
  1651. // Otherwise, leave it unchanged.
  1652. mainDiscReason = NL_GET_MAIN_REASON_CODE(disconnectID);
  1653. if ((mainDiscReason == NL_DISCONNECT_REMOTE_BY_SERVER) ||
  1654. (mainDiscReason == NL_DISCONNECT_REMOTE_BY_USER))
  1655. UIGoDisconnected(disconnectID, TRUE);
  1656. else
  1657. UIGoDisconnected(_UI.disconnectReason, TRUE);
  1658. }
  1659. else {
  1660. // UI-initiated disconnection - use the UI's code.
  1661. UIGoDisconnected(_UI.disconnectReason, TRUE);
  1662. }
  1663. }
  1664. DC_END_FN();
  1665. } // UI_OnDisconnected
  1666. //
  1667. // Name: UI_OnShutDown
  1668. //
  1669. // Purpose: Shuts down the application if called with success from the
  1670. // core. If the called with failure informs the user to
  1671. // disconnect or log off if they wish to shut down.
  1672. //
  1673. // Params: IN - successID - information on whether server allowed
  1674. // termination
  1675. //
  1676. DCVOID DCAPI CUI::UI_OnShutDown(ULONG_PTR successID)
  1677. {
  1678. DC_BEGIN_FN("UI_OnShutDown");
  1679. if (successID == UI_SHUTDOWN_SUCCESS)
  1680. {
  1681. //
  1682. // If the Core has replied to _pCo->CO_Shutdown(CO_SHUTDOWN) with
  1683. // UI_OnShutdown(UI_SHUTDOWN_SUCCESS) then the UI is free to
  1684. // terminate, so starts the process here.
  1685. //
  1686. //
  1687. // Notify axcontrol of shutdown.
  1688. //
  1689. SendMessage(_UI.hWndCntrl,WM_TERMTSC,0,0);
  1690. UI_DBG_SETINFO(DBG_STAT_TERMTSC_SENT);
  1691. //
  1692. // Must restore the langbar state just as we do in UI_OnDisconnected
  1693. // as in this disconnect path (shutdown) the disconnect notification
  1694. // is fired from the ActiveX layer.
  1695. //
  1696. #ifndef OS_WINCE
  1697. UI_RestoreLangBar();
  1698. #endif
  1699. //
  1700. // Do tail end processing for the disconnection but do not
  1701. // fire the disconnect event, that is handled by TERMTSC
  1702. //
  1703. if (_UI.connectionStatus != UI_STATUS_DISCONNECTED) {
  1704. UIGoDisconnected(_UI.disconnectReason, FALSE);
  1705. }
  1706. }
  1707. else
  1708. {
  1709. //
  1710. // We can kill the shutdown timer here since the server must have
  1711. // responded to our shutdown PDU.
  1712. //
  1713. if (0 != _UI.shutdownTimer)
  1714. {
  1715. TRC_NRM((TB, _T("Killing shutdown timer")));
  1716. KillTimer(_UI.hwndMain, _UI.shutdownTimer);
  1717. _UI.shutdownTimer = 0;
  1718. }
  1719. //
  1720. // If successID is not UI_SHUTDOWN_SUCCESS then the UI has been
  1721. // denied shutdown by the server (e.g the user has logged in so
  1722. // we need to prompt him if it's Ok to continue shutdown).
  1723. // Fire an event to the shell to ask the user if it is OK to
  1724. // proceed with the close
  1725. //
  1726. TRC_NRM((TB,_T("Firing WM_TS_ASKCONFIRMCLOSE")));
  1727. BOOL bOkToClose = TRUE;
  1728. SendMessage( _UI.hWndCntrl, WM_TS_ASKCONFIRMCLOSE,
  1729. (WPARAM)&bOkToClose, 0 );
  1730. if( bOkToClose)
  1731. {
  1732. TRC_NRM((TB,_T("User OK'd close request")));
  1733. _pCo->CO_Shutdown(CO_DISCONNECT_AND_EXIT);
  1734. }
  1735. else
  1736. {
  1737. TRC_NRM((TB,_T("User denied close request")));
  1738. }
  1739. }
  1740. DC_END_FN();
  1741. } // UI_OnShutDown
  1742. //
  1743. // Name: UI_UpdateSessionInfo
  1744. //
  1745. // Purpose: Updates the registry with the latest session info.
  1746. //
  1747. // Params: IN - pDomain Domain
  1748. // cbDomain Length of pDomain (in bytes)
  1749. // pUserName UserName
  1750. // cbUsername Length of pUserName (in bytes)
  1751. //
  1752. DCVOID DCAPI CUI::UI_UpdateSessionInfo(PDCWCHAR pDomain,
  1753. DCUINT cbDomain,
  1754. PDCWCHAR pUserName,
  1755. DCUINT cbUsername,
  1756. DCUINT32 SessionId)
  1757. {
  1758. UNREFERENCED_PARAMETER(cbUsername);
  1759. UNREFERENCED_PARAMETER(cbDomain);
  1760. DC_BEGIN_FN("UI_UpdateSessionInfo");
  1761. //
  1762. // Update the UT variables
  1763. //
  1764. UI_SetDomain(pDomain);
  1765. UI_SetUserName(pUserName);
  1766. UI_SetSessionId(SessionId);
  1767. UI_OnLoginComplete();
  1768. DC_EXIT_POINT:
  1769. DC_END_FN();
  1770. }
  1771. //
  1772. // Name: UI_GoFullScreen
  1773. //
  1774. DCVOID CUI::UI_GoFullScreen(DCVOID)
  1775. {
  1776. DWORD dwWebCtrlStyle;
  1777. DC_BEGIN_FN("UI_GoFullScreen");
  1778. //
  1779. // Before going fullscreen restore
  1780. // the lang bar to it's previous state
  1781. // since the system will take care of hiding
  1782. // it with it's built in fullscreen detection
  1783. //
  1784. #ifndef OS_WINCE
  1785. if (!UI_IsFullScreen())
  1786. {
  1787. UI_RestoreLangBar();
  1788. }
  1789. #endif
  1790. if(_UI.fContainerHandlesFullScreenToggle)
  1791. {
  1792. //
  1793. // FullScreen is handled by the container
  1794. // notify the control to fire an event
  1795. //
  1796. //Notify activeX control of screen mode change
  1797. if(IsWindow(_UI.hWndCntrl))
  1798. {
  1799. //
  1800. // wparam = 1 means go fullscreen
  1801. //
  1802. _UI.fContainerInFullScreen = TRUE;
  1803. SendMessage( _UI.hWndCntrl, WM_TS_REQUESTFULLSCREEN, (WPARAM)1, 0);
  1804. UIUpdateScreenMode( TRUE );
  1805. }
  1806. }
  1807. else
  1808. {
  1809. //
  1810. // Control handles fullscreen
  1811. //
  1812. dwWebCtrlStyle = GetWindowLong(_UI.hwndMain, GWL_STYLE);
  1813. if(!dwWebCtrlStyle)
  1814. {
  1815. TRC_ABORT((TB, _T("GetWindowLong failed")));
  1816. DC_QUIT;
  1817. }
  1818. //
  1819. // Going to real full screen mode
  1820. //
  1821. dwWebCtrlStyle &= ~WS_CHILD;
  1822. dwWebCtrlStyle |= WS_POPUP;
  1823. _UI.fControlIsFullScreen = TRUE;
  1824. SetParent(_UI.hwndMain, NULL);
  1825. if(!SetWindowLong(_UI.hwndMain, GWL_STYLE, dwWebCtrlStyle))
  1826. {
  1827. TRC_ABORT((TB, _T("SetWindowLong failed for webctrl")));
  1828. }
  1829. UIUpdateScreenMode( TRUE );
  1830. TRC_ASSERT(IsWindow(_UI.hWndCntrl), (TB, _T("hWndCntrl is NULL")));
  1831. #ifndef OS_WINCE
  1832. //Notify the shell that we've gone fullscreen
  1833. CUT::NotifyShellOfFullScreen( _UI.hwndMain,
  1834. TRUE,
  1835. &_pTaskBarList2,
  1836. &_fQueriedForTaskBarList2 );
  1837. #endif
  1838. //Notify activeX control of screen mode change
  1839. if(IsWindow(_UI.hWndCntrl))
  1840. {
  1841. SendMessage( _UI.hWndCntrl, WM_TS_GONEFULLSCREEN, 0, 0);
  1842. }
  1843. }
  1844. if(UI_IsFullScreen())
  1845. {
  1846. _pIh->IH_NotifyEnterFullScreen();
  1847. #ifdef USE_BBAR
  1848. if(_pBBar)
  1849. {
  1850. _pBBar->OnNotifyEnterFullScreen();
  1851. }
  1852. #endif
  1853. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  1854. // When the fullscreen window size is smaller than the desktop size
  1855. // we don't disable shadow bitmap
  1856. if ((_UI.mainWindowClientSize.width >= _UI.desktopSize.width) &&
  1857. (_UI.mainWindowClientSize.height >= _UI.desktopSize.height))
  1858. {
  1859. _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT,
  1860. _pUh,
  1861. CD_NOTIFICATION_FUNC(CUH,UH_DisableShadowBitmap),
  1862. NULL);
  1863. }
  1864. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  1865. }
  1866. DC_EXIT_POINT:
  1867. DC_END_FN();
  1868. }
  1869. //
  1870. // Name: UI_LeaveFullScreen
  1871. //
  1872. DCVOID CUI::UI_LeaveFullScreen(DCVOID)
  1873. {
  1874. DWORD dwWebCtrlStyle;
  1875. DC_BEGIN_FN("UI_LeaveFullScreen");
  1876. if(_UI.fContainerHandlesFullScreenToggle)
  1877. {
  1878. //
  1879. // FullScreen is handled by the container
  1880. // notify the control to fire an event
  1881. //
  1882. //Notify activeX control of screen mode change
  1883. if(IsWindow(_UI.hWndCntrl))
  1884. {
  1885. //
  1886. // wparam = 1 means go fullscreen
  1887. //
  1888. _UI.fContainerInFullScreen = FALSE;
  1889. SendMessage( _UI.hWndCntrl, WM_TS_REQUESTFULLSCREEN, (WPARAM)0, 0);
  1890. UIUpdateScreenMode( TRUE );
  1891. }
  1892. }
  1893. else
  1894. {
  1895. dwWebCtrlStyle = GetWindowLong(_UI.hwndMain, GWL_STYLE);
  1896. if(!dwWebCtrlStyle)
  1897. {
  1898. TRC_ABORT((TB, _T("GetWindowLong failed for webctrl")));
  1899. DC_QUIT;
  1900. }
  1901. //
  1902. // Leaving real full screen mode
  1903. //
  1904. dwWebCtrlStyle &= ~WS_POPUP;
  1905. dwWebCtrlStyle |= WS_CHILD;
  1906. _UI.fControlIsFullScreen = FALSE;
  1907. SetParent(_UI.hwndMain, _UI.hWndCntrl);
  1908. if(!SetWindowLong(_UI.hwndMain, GWL_STYLE, dwWebCtrlStyle))
  1909. {
  1910. TRC_ABORT((TB, _T("SetWindowLong failed for webctrl")));
  1911. }
  1912. //ActiveX control is always in 'Full screen mode'
  1913. UIUpdateScreenMode( TRUE );
  1914. TRC_ASSERT(IsWindow(_UI.hWndCntrl),(TB, _T("hWndCntrl is NULL")));
  1915. #ifndef OS_WINCE
  1916. //Notify the shell that we've left fullscreen
  1917. CUT::NotifyShellOfFullScreen( _UI.hwndMain,
  1918. FALSE,
  1919. &_pTaskBarList2,
  1920. &_fQueriedForTaskBarList2 );
  1921. #endif
  1922. //Notify activeX control of screen mode change
  1923. if(IsWindow(_UI.hWndCntrl))
  1924. {
  1925. SendMessage( _UI.hWndCntrl, WM_TS_LEFTFULLSCREEN, 0, 0);
  1926. }
  1927. }
  1928. if(!UI_IsFullScreen())
  1929. {
  1930. //Notify IH
  1931. _pIh->IH_NotifyLeaveFullScreen();
  1932. #ifdef USE_BBAR
  1933. if(_pBBar)
  1934. {
  1935. _pBBar->OnNotifyLeaveFullScreen();
  1936. }
  1937. #endif
  1938. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  1939. // When leaving fullscreen, enable the use of shadow bitmap
  1940. _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT,
  1941. _pUh,
  1942. CD_NOTIFICATION_FUNC(CUH,UH_EnableShadowBitmap),
  1943. NULL);
  1944. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  1945. //
  1946. // After leaving fullscreen we need to handle
  1947. // hiding the langbar if the IH has the focus
  1948. //
  1949. #ifndef OS_WINCE
  1950. if (_fIhHasFocus)
  1951. {
  1952. UI_HideLangBar();
  1953. }
  1954. #endif
  1955. }
  1956. DC_EXIT_POINT:
  1957. DC_END_FN();
  1958. }
  1959. //
  1960. // Name: UI_ToggleFullScreenMode
  1961. //
  1962. // Purpose: Toggle web ctrl/full screen mode
  1963. //
  1964. DCVOID CUI::UI_ToggleFullScreenMode(DCVOID)
  1965. {
  1966. DC_BEGIN_FN("UI_ToggleFullScreenMode");
  1967. if(UI_IsFullScreen())
  1968. {
  1969. UI_LeaveFullScreen();
  1970. }
  1971. else
  1972. {
  1973. UI_GoFullScreen();
  1974. }
  1975. DC_END_FN();
  1976. } // UI_ToggleFullScreenMode
  1977. //
  1978. // Name: UI_IsFullScreen
  1979. //
  1980. // Purpose: Returns true if we are in fullscreen mode
  1981. // (for both container and control handled fullscreen)
  1982. //
  1983. DCBOOL CUI::UI_IsFullScreen()
  1984. {
  1985. return _UI.fContainerHandlesFullScreenToggle ?
  1986. _UI.fContainerInFullScreen : _UI.fControlIsFullScreen;
  1987. }
  1988. #ifdef DC_DEBUG
  1989. //
  1990. // Name: UI_CoreDebugSettingChanged
  1991. //
  1992. // Purpose: Performs necessary actions when any of the Core debug
  1993. // setings are updated.
  1994. //
  1995. void DCINTERNAL CUI::UI_CoreDebugSettingChanged()
  1996. {
  1997. unsigned configFlags;
  1998. DC_BEGIN_FN("UICoreDebugSettingChanged");
  1999. if (!_UI.coreInitialized)
  2000. return;
  2001. configFlags = 0;
  2002. if (_UI.hatchBitmapPDUData)
  2003. configFlags |= CO_CFG_FLAG_HATCH_BITMAP_PDU_DATA;
  2004. if (_UI.hatchIndexPDUData)
  2005. configFlags |= CO_CFG_FLAG_HATCH_INDEX_PDU_DATA;
  2006. if (_UI.hatchSSBOrderData)
  2007. configFlags |= CO_CFG_FLAG_HATCH_SSB_ORDER_DATA;
  2008. if (_UI.hatchMemBltOrderData)
  2009. configFlags |= CO_CFG_FLAG_HATCH_MEMBLT_ORDER_DATA;
  2010. if (_UI.labelMemBltOrders)
  2011. configFlags |= CO_CFG_FLAG_LABEL_MEMBLT_ORDERS;
  2012. if (_UI.bitmapCacheMonitor)
  2013. configFlags |= CO_CFG_FLAG_BITMAP_CACHE_MONITOR;
  2014. _pCo->CO_SetConfigurationValue(CO_CFG_DEBUG_SETTINGS, configFlags);
  2015. DC_END_FN();
  2016. }
  2017. //
  2018. // Name: UI_SetRandomFailureItem
  2019. //
  2020. // Purpose: Sets the percentage failure of a specified function
  2021. //
  2022. // Params: IN - itemID - identifies the function
  2023. // IN - percent - the new percentage failure
  2024. //
  2025. void DCAPI CUI::UI_SetRandomFailureItem(unsigned itemID, int percent)
  2026. {
  2027. DC_BEGIN_FN("UI_SetRandomFailureItem");
  2028. _pUt->UT_SetRandomFailureItem(itemID, percent);
  2029. DC_END_FN();
  2030. } // UI_SetRandomFailureItem
  2031. //
  2032. // Name: UI_GetRandomFailureItem
  2033. //
  2034. // Purpose: Gets the percentage failure for a specified function
  2035. //
  2036. // Returns: The percentage
  2037. //
  2038. // Params: IN - itemID - identifies the function
  2039. //
  2040. int DCAPI CUI::UI_GetRandomFailureItem(unsigned itemID)
  2041. {
  2042. DC_BEGIN_FN("UI_GetRandomFailureItem");
  2043. DC_END_FN();
  2044. return _pUt->UT_GetRandomFailureItem(itemID);
  2045. } // UI_GetRandomFailureItem
  2046. //
  2047. // Name: UI_SetNetworkThroughput
  2048. //
  2049. // Purpose: Set the network throughput in bytes per second
  2050. //
  2051. // Params: IN - bytesPerSec to set for the maximum network throughput
  2052. //
  2053. void DCAPI CUI::UI_SetNetworkThroughput(unsigned bytesPerSec)
  2054. {
  2055. DC_BEGIN_FN("UI_SetNetworkThroughput");
  2056. TRC_ASSERT(((bytesPerSec <= 50000)),
  2057. (TB,_T("bytesPerSec is out of range")));
  2058. _pTd->NL_SetNetworkThroughput(bytesPerSec);
  2059. DC_END_FN();
  2060. } // UI_SetNetworkThroughput
  2061. //
  2062. // Name: UI_GetNetworkThroughput
  2063. //
  2064. // Purpose: Gets the percentage failure for a specified function
  2065. //
  2066. unsigned DCAPI CUI::UI_GetNetworkThroughput()
  2067. {
  2068. DC_BEGIN_FN("UI_GetNetworkThroughput");
  2069. DC_END_FN();
  2070. return _pTd->NL_GetNetworkThroughput();
  2071. } // UI_GetNetworkThroughput
  2072. #endif // DC_DEBUG
  2073. //
  2074. // Set the list of virtual channel plugins to load
  2075. //
  2076. BOOL DCAPI CUI::UI_SetVChanAddinList(TCHAR *szVChanAddins)
  2077. {
  2078. DC_BEGIN_FN("UI_SetVChanAddinList");
  2079. if(_UI.pszVChanAddinDlls)
  2080. {
  2081. //If previously set, free
  2082. UT_Free(_pUt, _UI.pszVChanAddinDlls);
  2083. }
  2084. if(!szVChanAddins || szVChanAddins[0] == 0)
  2085. {
  2086. _UI.pszVChanAddinDlls = NULL;
  2087. return TRUE;
  2088. }
  2089. else
  2090. {
  2091. DCUINT len = DC_TSTRLEN(szVChanAddins);
  2092. _UI.pszVChanAddinDlls = (PDCTCHAR)UT_Malloc(_pUt, (len +1) * sizeof(DCTCHAR));
  2093. if(_UI.pszVChanAddinDlls)
  2094. {
  2095. StringCchCopy(_UI.pszVChanAddinDlls, len+1, szVChanAddins);
  2096. }
  2097. else
  2098. {
  2099. return FALSE;
  2100. }
  2101. }
  2102. DC_END_FN();
  2103. return TRUE;
  2104. }
  2105. //
  2106. // Set the load balance info
  2107. //
  2108. BOOL DCAPI CUI::UI_SetLBInfo(PBYTE pLBInfo, unsigned LBInfoSize)
  2109. {
  2110. DC_BEGIN_FN("UI_SetLBInfo");
  2111. if(_UI.bstrScriptedLBInfo)
  2112. {
  2113. //If previously set, free
  2114. SysFreeString(_UI.bstrScriptedLBInfo);
  2115. }
  2116. if(!pLBInfo)
  2117. {
  2118. _UI.bstrScriptedLBInfo = NULL;
  2119. return TRUE;
  2120. }
  2121. else
  2122. {
  2123. _UI.bstrScriptedLBInfo= SysAllocStringByteLen((LPCSTR)pLBInfo, LBInfoSize);
  2124. if (_UI.bstrScriptedLBInfo == NULL)
  2125. {
  2126. return FALSE;
  2127. }
  2128. }
  2129. DC_END_FN();
  2130. return TRUE;
  2131. }
  2132. //
  2133. // Name: UI_SetCompress
  2134. //
  2135. void DCAPI CUI::UI_SetCompress(BOOL fCompress)
  2136. {
  2137. DC_BEGIN_FN("UI_SetCompress");
  2138. TRC_NRM((TB, _T("Setting _UI.fCompress to %d"), fCompress));
  2139. _UI.fCompress = fCompress;
  2140. //
  2141. // If compression is enabled, then allocate a receive context
  2142. //
  2143. if (fCompress && !_UI.pRecvContext2)
  2144. {
  2145. _UI.pRecvContext2 = (RecvContext2_64K *)
  2146. UT_Malloc(_pUt,sizeof(RecvContext2_64K));
  2147. if (_UI.pRecvContext2)
  2148. {
  2149. _UI.pRecvContext2->cbSize = sizeof(RecvContext2_64K);
  2150. initrecvcontext(&_UI.Context1,
  2151. (RecvContext2_Generic*)_UI.pRecvContext2,
  2152. PACKET_COMPR_TYPE_64K);
  2153. }
  2154. else
  2155. _UI.fCompress = FALSE;
  2156. }
  2157. else if (!fCompress && _UI.pRecvContext2)
  2158. {
  2159. UT_Free(_pUt, _UI.pRecvContext2);
  2160. _UI.pRecvContext2 = NULL;
  2161. }
  2162. DC_END_FN();
  2163. } // UI_SetCompress
  2164. //
  2165. // Name: UI_GetCompress
  2166. //
  2167. BOOL DCAPI CUI::UI_GetCompress()
  2168. {
  2169. DC_BEGIN_FN("UI_GetCompress");
  2170. DC_END_FN();
  2171. return _UI.fCompress;
  2172. } // UI_GetCompress
  2173. DCUINT CUI::UI_GetAudioRedirectionMode()
  2174. {
  2175. return _UI.audioRedirectionMode;
  2176. }
  2177. VOID CUI::UI_SetAudioRedirectionMode(DCUINT audioMode)
  2178. {
  2179. DC_BEGIN_FN("UI_SetAudioRedirectionMode");
  2180. TRC_ASSERT((audioMode == UTREG_UI_AUDIO_MODE_REDIRECT ||
  2181. audioMode == UTREG_UI_AUDIO_MODE_PLAY_ON_SERVER ||
  2182. audioMode == UTREG_UI_AUDIO_MODE_NONE),
  2183. (TB,_T("Invalid audio mode passed to UI_SetAudioRedirectionMode")));
  2184. _UI.audioRedirectionMode = audioMode;
  2185. DC_END_FN();
  2186. }
  2187. BOOL CUI::UI_GetDriveRedirectionEnabled()
  2188. {
  2189. return _UI.fEnableDriveRedirection;
  2190. }
  2191. VOID CUI::UI_SetDriveRedirectionEnabled(BOOL fEnable)
  2192. {
  2193. _UI.fEnableDriveRedirection = fEnable;
  2194. }
  2195. BOOL CUI::UI_GetPrinterRedirectionEnabled()
  2196. {
  2197. return _UI.fEnablePrinterRedirection;
  2198. }
  2199. VOID CUI::UI_SetPrinterRedirectionEnabled(BOOL fEnable)
  2200. {
  2201. _UI.fEnablePrinterRedirection = fEnable;
  2202. }
  2203. BOOL CUI::UI_GetPortRedirectionEnabled()
  2204. {
  2205. return _UI.fEnablePortRedirection;
  2206. }
  2207. VOID CUI::UI_SetPortRedirectionEnabled(BOOL fEnable)
  2208. {
  2209. _UI.fEnablePortRedirection = fEnable;
  2210. }
  2211. BOOL CUI::UI_GetSCardRedirectionEnabled()
  2212. {
  2213. return _UI.fEnableSCardRedirection;
  2214. }
  2215. VOID CUI::UI_SetSCardRedirectionEnabled(BOOL fEnable)
  2216. {
  2217. _UI.fEnableSCardRedirection = fEnable;
  2218. }
  2219. VOID CUI::UI_OnDeviceChange(WPARAM wParam, LPARAM lParam)
  2220. {
  2221. DEVICE_PARAMS DeviceParams;
  2222. DC_BEGIN_FN("UI_OnDeviceChange");
  2223. if (_fTerminating) {
  2224. DC_QUIT;
  2225. }
  2226. DeviceParams.wParam = wParam;
  2227. DeviceParams.lParam = lParam;
  2228. DeviceParams.deviceObj = _drInitData.pUpdateDeviceObj;
  2229. if (_drInitData.pUpdateDeviceObj != NULL) {
  2230. _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT,
  2231. _pCChan,
  2232. CD_NOTIFICATION_FUNC(CChan, OnDeviceChange),
  2233. (ULONG_PTR)(PVOID)(&DeviceParams));
  2234. }
  2235. DC_EXIT_POINT:
  2236. DC_END_FN();
  2237. }
  2238. //Initialize the rdpdr settings struct for this connection
  2239. //these settings get passed down to the rdpdr plugin
  2240. void CUI::UI_InitRdpDrSettings()
  2241. {
  2242. DC_BEGIN_FN("UI_InitRdpDrSettings");
  2243. // Need to reset the data only when necessary
  2244. _drInitData.fEnableRedirectedAudio = FALSE;
  2245. _drInitData.fEnableRedirectDrives = FALSE;
  2246. _drInitData.fEnableRedirectPorts = FALSE;
  2247. _drInitData.fEnableRedirectPrinters = FALSE;
  2248. _drInitData.fEnableRedirectedAudio = UI_GetAudioRedirectionMode() ==
  2249. UTREG_UI_AUDIO_MODE_REDIRECT;
  2250. _drInitData.fEnableRedirectDrives = UI_GetDriveRedirectionEnabled();
  2251. _drInitData.fEnableRedirectPrinters = UI_GetPrinterRedirectionEnabled();
  2252. _drInitData.fEnableRedirectPorts = UI_GetPortRedirectionEnabled();
  2253. _drInitData.fEnableSCardRedirection = UI_GetSCardRedirectionEnabled();
  2254. memset(_drInitData.szLocalPrintingDocName, 0,
  2255. sizeof(_drInitData.szLocalPrintingDocName));
  2256. if(!LoadString(_UI.hResDllInstance,
  2257. IDS_RDPDR_PRINT_LOCALDOCNAME,
  2258. _drInitData.szLocalPrintingDocName,
  2259. SIZECHAR(_drInitData.szLocalPrintingDocName))) {
  2260. TRC_ERR((TB,_T("LoadString IDS_RDPDR_PRINT_LOCALDOCNAME failed")));
  2261. }
  2262. memset(_drInitData.szClipCleanTempDirString, 0,
  2263. sizeof(_drInitData.szClipCleanTempDirString));
  2264. if(!LoadString(_UI.hResDllInstance,
  2265. IDS_RDPDR_CLIP_CLEANTEMPDIR,
  2266. _drInitData.szClipCleanTempDirString,
  2267. SIZECHAR(_drInitData.szClipCleanTempDirString))) {
  2268. TRC_ERR((TB,_T("LoadString IDS_RDPDR_CLIP_CLEANTEMPDIR failed")));
  2269. }
  2270. memset(_drInitData.szClipPasteInfoString, 0,
  2271. sizeof(_drInitData.szClipPasteInfoString));
  2272. if(!LoadString(_UI.hResDllInstance,
  2273. IDS_RDPDR_CLIP_PASTEINFO,
  2274. _drInitData.szClipPasteInfoString,
  2275. SIZECHAR(_drInitData.szClipPasteInfoString))) {
  2276. TRC_ERR((TB,_T("LoadString IDS_RDPDR_CLIP_PASTEINFO failed")));
  2277. }
  2278. DC_END_FN();
  2279. }
  2280. // Clean up the LB redirect state. The load balancing cookie stuff needs to
  2281. // know when it's in the middle of a redirection.
  2282. void CUI::UI_CleanupLBState()
  2283. {
  2284. if (_UI.bstrRedirectionLBInfo)
  2285. {
  2286. SysFreeString(_UI.bstrRedirectionLBInfo);
  2287. _UI.bstrRedirectionLBInfo = NULL;
  2288. }
  2289. _UI.ClientIsRedirected = FALSE;
  2290. }
  2291. //
  2292. // Trigger a user initiated disconnection
  2293. //
  2294. // Params: discReason - disconnect reason to set
  2295. // default is NL_DISCONNECT_LOCAL
  2296. //
  2297. BOOL CUI::UI_UserInitiatedDisconnect(UINT discReason)
  2298. {
  2299. DC_BEGIN_FN("UI_UserInitiatedDisconnect");
  2300. if(UI_STATUS_DISCONNECTED == _UI.connectionStatus ||
  2301. UI_STATUS_INITIALIZING == _UI.connectionStatus)
  2302. {
  2303. return FALSE;
  2304. }
  2305. else
  2306. {
  2307. _UI.disconnectReason = discReason;
  2308. UIInitiateDisconnection();
  2309. return TRUE;
  2310. }
  2311. DC_END_FN();
  2312. }
  2313. //
  2314. // Notify the activeX layer that core init has completed
  2315. //
  2316. BOOL CUI::UI_NotifyAxLayerCoreInit()
  2317. {
  2318. DC_BEGIN_FN("UI_NotifyAxLayerCoreInit");
  2319. if(_UI.hEvtNotifyCoreInit)
  2320. {
  2321. BOOL bRet = SetEvent(_UI.hEvtNotifyCoreInit);
  2322. // We can now close the handle to the event. This will not affect the
  2323. // waiting UI thread as hEvtNotifyCoreInit was duplicated and will
  2324. // only be destroyed if the reference count becomes zero.
  2325. CloseHandle(_UI.hEvtNotifyCoreInit);
  2326. _UI.hEvtNotifyCoreInit = NULL;
  2327. if(bRet)
  2328. {
  2329. return TRUE;
  2330. }
  2331. else
  2332. {
  2333. TRC_ABORT((TB,_T("SetEvent _UI.hEvtNotifyCoreInit failed, err: %d"),
  2334. GetLastError()));
  2335. return FALSE;
  2336. }
  2337. }
  2338. else
  2339. {
  2340. return FALSE;
  2341. }
  2342. DC_END_FN();
  2343. }
  2344. HWND CUI::UI_GetInputWndHandle()
  2345. {
  2346. DC_BEGIN_FN("UI_GetInputWndHandle");
  2347. if(_pIh)
  2348. {
  2349. return _pIh->IH_GetInputHandlerWindow();
  2350. }
  2351. else
  2352. {
  2353. return NULL;
  2354. }
  2355. DC_END_FN();
  2356. }
  2357. HWND CUI::UI_GetBmpCacheMonitorHandle()
  2358. {
  2359. DC_BEGIN_FN("UI_GetBmpCacheMonitorHandle");
  2360. #ifdef DC_DEBUG
  2361. if(_pUh)
  2362. {
  2363. return _pUh->UH_GetBitmapCacheMonHwnd();
  2364. }
  2365. else
  2366. {
  2367. return NULL;
  2368. }
  2369. #else
  2370. //Free build has no cache monitor
  2371. return NULL;
  2372. #endif
  2373. DC_END_FN();
  2374. }
  2375. //
  2376. // Injects vKeys to the IH
  2377. //
  2378. BOOL CUI::UI_InjectVKeys(/*[in]*/ LONG numKeys,
  2379. /*[in]*/ short* pfArrayKeyUp,
  2380. /*[in]*/ LONG* plKeyData)
  2381. {
  2382. BOOL fRet = FALSE;
  2383. IH_INJECT_VKEYS_REQUEST ihrp;
  2384. DC_BEGIN_FN("UI_InjectVKeys");
  2385. if (_fTerminating) {
  2386. DC_QUIT;
  2387. }
  2388. if(UI_STATUS_CONNECTED == _UI.connectionStatus)
  2389. {
  2390. //Build a request packet and decouple the work
  2391. //to the IH. We use a sync decouple so there is
  2392. //no need to make copies of the array params
  2393. ihrp.numKeys = numKeys;
  2394. ihrp.pfArrayKeyUp = pfArrayKeyUp;
  2395. ihrp.plKeyData = plKeyData;
  2396. ihrp.fReturnStatus = FALSE;
  2397. _pCd->CD_DecoupleSyncNotification(CD_SND_COMPONENT,
  2398. _pIh,
  2399. CD_NOTIFICATION_FUNC(CIH, IH_InjectMultipleVKeys),
  2400. (ULONG_PTR)&ihrp);
  2401. fRet = ihrp.fReturnStatus;
  2402. }
  2403. else
  2404. {
  2405. fRet = FALSE;
  2406. }
  2407. DC_EXIT_POINT:
  2408. DC_END_FN();
  2409. return fRet;
  2410. }
  2411. BOOL CUI::UI_SetMinsToIdleTimeout(LONG minsToTimeout)
  2412. {
  2413. DC_BEGIN_FN("UI_SetMinsToIdleTimeout");
  2414. //Timers will be initialized at connection time
  2415. //see InitInputIdleTimer
  2416. if(minsToTimeout < MAX_MINS_TOIDLETIMEOUT)
  2417. {
  2418. _UI.minsToIdleTimeout = minsToTimeout;
  2419. }
  2420. DC_END_FN();
  2421. return TRUE;
  2422. }
  2423. LONG CUI::UI_GetMinsToIdleTimeout()
  2424. {
  2425. DC_BEGIN_FN("UI_SetMinsToIdleTimeout");
  2426. DC_END_FN();
  2427. return _UI.minsToIdleTimeout;
  2428. }
  2429. DCVOID DCAPI CUI::UI_SetServerErrorInfo(ULONG_PTR errInfo)
  2430. {
  2431. DC_BEGIN_FN("UI_SetServerErrorInfo");
  2432. TRC_NRM((TB,_T("SetServerErrorInfo prev:0x%x new:0x%x"),
  2433. _UI.lastServerErrorInfo, errInfo));
  2434. _UI.lastServerErrorInfo = errInfo;
  2435. DC_END_FN();
  2436. }
  2437. UINT32 CUI::UI_GetServerErrorInfo()
  2438. {
  2439. DC_BEGIN_FN("UI_GetServerErrorInfo");
  2440. DC_END_FN();
  2441. return _UI.lastServerErrorInfo;
  2442. }
  2443. //
  2444. // Sets the disconnect reason. Can be called by the CD
  2445. // from other threads
  2446. //
  2447. void CUI::UI_SetDisconnectReason(ULONG_PTR reason)
  2448. {
  2449. DC_BEGIN_FN("UI_SetDisconnectReason");
  2450. _UI.disconnectReason = (DCUINT) reason;
  2451. DC_END_FN();
  2452. }
  2453. #ifdef USE_BBAR
  2454. void CUI::UI_OnBBarHotzoneTimerFired(ULONG_PTR unused)
  2455. {
  2456. DC_BEGIN_FN("UI_OnBBarHotzoneTimerFired");
  2457. if (_pBBar) {
  2458. _pBBar->OnBBarHotzoneFired();
  2459. }
  2460. DC_END_FN();
  2461. }
  2462. //
  2463. // Requests a minimize, this only works in fullscreen
  2464. // If we're in container handled fullscreen then the
  2465. // request is dispatched to the container but there
  2466. // is no way to know if it was actually serviced.
  2467. //
  2468. // If we're in control handled fullscreen then
  2469. // just minimize the fullscreen window ourselves
  2470. //
  2471. BOOL CUI::UI_RequestMinimize()
  2472. {
  2473. DC_BEGIN_FN("UI_RequestMinimize");
  2474. if(UI_IsFullScreen())
  2475. {
  2476. if(_UI.fContainerHandlesFullScreenToggle)
  2477. {
  2478. //Dispatch a request to the control so
  2479. //it can fire an event requesting minimze
  2480. TRC_ASSERT( IsWindow(_UI.hWndCntrl),
  2481. (TB,_T("_UI.hWndCntrl is bad 0x%x"),
  2482. _UI.hWndCntrl));
  2483. if( IsWindow( _UI.hWndCntrl) )
  2484. {
  2485. SendMessage( _UI.hWndCntrl,
  2486. WM_TS_REQUESTMINIMIZE,
  2487. 0, 0 );
  2488. }
  2489. //
  2490. // No way to know if container actually did
  2491. // what we asked, but it doesn't matter
  2492. //
  2493. return TRUE;
  2494. }
  2495. else
  2496. {
  2497. //
  2498. // This minimizes but does not destroy the window
  2499. //
  2500. #ifndef OS_WINCE
  2501. return CloseWindow(_UI.hwndMain);
  2502. #else
  2503. ShowWindow(_UI.hwndMain, SW_MINIMIZE);
  2504. return TRUE;
  2505. #endif
  2506. }
  2507. }
  2508. else
  2509. {
  2510. TRC_NRM((TB,_T("Not fullscreen minimize denied")));
  2511. return FALSE;
  2512. }
  2513. DC_END_FN();
  2514. }
  2515. #endif
  2516. int CUI::UI_BppToColorDepthID(int bpp)
  2517. {
  2518. int colorDepthID = CO_BITSPERPEL8;
  2519. DC_BEGIN_FN("UI_BppToColorDepthID");
  2520. switch (bpp)
  2521. {
  2522. case 8:
  2523. {
  2524. colorDepthID = CO_BITSPERPEL8;
  2525. }
  2526. break;
  2527. case 15:
  2528. {
  2529. colorDepthID = CO_BITSPERPEL15;
  2530. }
  2531. break;
  2532. case 16:
  2533. {
  2534. colorDepthID = CO_BITSPERPEL16;
  2535. }
  2536. break;
  2537. case 24:
  2538. case 32:
  2539. {
  2540. colorDepthID = CO_BITSPERPEL24;
  2541. }
  2542. break;
  2543. case 4:
  2544. default:
  2545. {
  2546. TRC_ERR((TB, _T("color depth %u unsupported - default to 8"),
  2547. bpp));
  2548. colorDepthID = CO_BITSPERPEL8;
  2549. }
  2550. break;
  2551. }
  2552. DC_END_FN();
  2553. return colorDepthID;
  2554. }
  2555. int CUI::UI_GetScreenBpp()
  2556. {
  2557. HDC hdc;
  2558. int screenBpp;
  2559. DC_BEGIN_FN("UI_GetScreenBpp");
  2560. hdc = GetDC(NULL);
  2561. if(hdc)
  2562. {
  2563. screenBpp = GetDeviceCaps(hdc, BITSPIXEL);
  2564. TRC_NRM((TB, _T("HDC %p has %u bpp"), hdc, screenBpp));
  2565. ReleaseDC(NULL, hdc);
  2566. }
  2567. DC_END_FN();
  2568. return screenBpp;
  2569. }
  2570. #ifdef SMART_SIZING
  2571. //
  2572. // Name: UI_SetSmartSizing
  2573. //
  2574. // Purpose: Save the fSmartSizing flag
  2575. //
  2576. // Params: IN fSmartSizing
  2577. //
  2578. HRESULT DCAPI CUI::UI_SetSmartSizing(BOOL fSmartSizing)
  2579. {
  2580. HWND hwndOp;
  2581. HRESULT hr = S_OK;
  2582. DC_BEGIN_FN("UI_SetSmartSizing");
  2583. TRC_NRM((TB, _T("Setting _UI.fSmartSizing to %d"), fSmartSizing));
  2584. _UI.fSmartSizing = fSmartSizing;
  2585. _UI.scrollPos.x = 0;
  2586. _UI.scrollPos.y = 0;
  2587. UIRecalculateScrollbars();
  2588. UIMoveContainerWindow();
  2589. if (_pOp) {
  2590. hwndOp = _pOp->OP_GetOutputWindowHandle();
  2591. if (hwndOp)
  2592. {
  2593. InvalidateRect(hwndOp, NULL, FALSE);
  2594. }
  2595. }
  2596. else {
  2597. hr = E_OUTOFMEMORY;
  2598. }
  2599. DC_END_FN();
  2600. return hr;
  2601. } // UI_SetSmartSizing
  2602. #endif // SMART_SIZING
  2603. BOOL CUI::UI_UserRequestedClose()
  2604. {
  2605. BOOL fRet = FALSE;
  2606. DC_BEGIN_FN("UI_UserRequestedClose");
  2607. UI_DBG_SETINFO(DBG_STAT_UIREQUESTEDCLOSE_CALLED);
  2608. //
  2609. // Call _pCo->CO_Shutdown.
  2610. //
  2611. if (UI_STATUS_CONNECTED == _UI.connectionStatus)
  2612. {
  2613. //
  2614. // Since we're connected we will start a timer in case the
  2615. // server gets stuck and doesn't process our shutdown PDU.
  2616. //
  2617. if (0 == _UI.shutdownTimer)
  2618. {
  2619. TRC_NRM((TB, _T("Setting shutdown timer is set for %u seconds"),
  2620. _UI.shutdownTimeout));
  2621. _UI.shutdownTimer = SetTimer(_UI.hwndMain,
  2622. UI_TIMER_SHUTDOWN,
  2623. 1000 * _UI.shutdownTimeout,
  2624. NULL);
  2625. if (_UI.shutdownTimer)
  2626. {
  2627. fRet = TRUE;
  2628. }
  2629. else
  2630. {
  2631. //
  2632. // This is a shame. If the server doesn't do
  2633. // anything with our shutdown PDU we'll wait
  2634. // forever. Report this as a failure so that the shell
  2635. // has an oppurtunity to do an immediate close
  2636. //
  2637. fRet = FALSE;
  2638. TRC_ERR((TB, _T("Failed to set shutdown timeout")));
  2639. }
  2640. }
  2641. else
  2642. {
  2643. TRC_NRM((TB, _T("Shutdown timer already set - leave it")));
  2644. fRet = TRUE;
  2645. }
  2646. }
  2647. else
  2648. {
  2649. fRet = TRUE;
  2650. }
  2651. _pCo->CO_Shutdown( CO_SHUTDOWN);
  2652. UI_DBG_SETINFO(DBG_STAT_UIREQUESTEDCLOSE_RET);
  2653. DC_END_FN();
  2654. return fRet;
  2655. }
  2656. //
  2657. // Notification that login has completed
  2658. // forward on to control (which fires an event)
  2659. // and CLX for debugging/test
  2660. //
  2661. void CUI::UI_OnLoginComplete()
  2662. {
  2663. DCUINT32 sessionId;
  2664. DC_BEGIN_FN("UI_OnLoginComplete");
  2665. sessionId = UI_GetSessionId();
  2666. _clx->CLX_ClxEvent(CLX_EVENT_LOGON, sessionId);
  2667. //Notify the control of the login event
  2668. SendMessage(_UI.hWndCntrl, WM_TS_LOGINCOMPLETE, 0, 0);
  2669. _pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT,
  2670. _pOp,
  2671. CD_NOTIFICATION_FUNC(COP,OP_DimWindow),
  2672. (ULONG_PTR)FALSE);
  2673. DC_END_FN();
  2674. }
  2675. #ifdef OS_WINCE
  2676. #define LOGONID_NONE -1
  2677. #endif
  2678. /****************************************************************************/
  2679. /* Name: UI_GetLocalSessionId */
  2680. /* */
  2681. /* Purpose: Retrieves the session id where the client is running. */
  2682. /****************************************************************************/
  2683. BOOL CUI::UI_GetLocalSessionId(PDCUINT32 pSessionId)
  2684. {
  2685. BOOL rc = FALSE;
  2686. DWORD dwSessionId = RNS_INFO_INVALID_SESSION_ID;
  2687. DC_BEGIN_FN("UI_GetLocalSessionId");
  2688. #ifndef OS_WINCE
  2689. HMODULE hmodule;
  2690. typedef BOOL (FNPROCESSID_TO_SESSIONID)(DWORD, DWORD*);
  2691. FNPROCESSID_TO_SESSIONID *pfnProcessIdToSessionId;
  2692. // get the handle to kernel32.dll library
  2693. hmodule = LoadLibrary(TEXT("KERNEL32.DLL"));
  2694. if (hmodule != NULL) {
  2695. rc = TRUE;
  2696. // get the proc address for ProcessIdToSessionId
  2697. pfnProcessIdToSessionId = (FNPROCESSID_TO_SESSIONID *)GetProcAddress(
  2698. hmodule, "ProcessIdToSessionId");
  2699. // get the session id
  2700. if (pfnProcessIdToSessionId != NULL) {
  2701. // We found the feature ProcessIdToSessionId.
  2702. // See if TS is really enabled on this machine
  2703. // (test valid only on Win2K and above).
  2704. if (UIIsTSOnWin2KOrGreater()) {
  2705. (*pfnProcessIdToSessionId) (GetCurrentProcessId(), &dwSessionId);
  2706. }
  2707. }
  2708. FreeLibrary(hmodule);
  2709. }
  2710. #endif //OS_WINCE
  2711. *((PDCUINT32_UA)pSessionId) = dwSessionId;
  2712. DC_END_FN()
  2713. return rc;
  2714. }
  2715. #ifdef USE_BBAR
  2716. VOID CUI::UI_SetBBarPinned(BOOL b)
  2717. {
  2718. DC_BEGIN_FN("UI_SetBBarPinned");
  2719. _UI.fBBarPinned = b;
  2720. if (_pBBar) {
  2721. _pBBar->SetPinned(b);
  2722. }
  2723. DC_END_FN();
  2724. }
  2725. BOOL CUI::UI_GetBBarPinned()
  2726. {
  2727. DC_BEGIN_FN("UI_GetBBarPinned");
  2728. if (_pBBar) {
  2729. return _pBBar->IsPinned();
  2730. }
  2731. else {
  2732. return _UI.fBBarPinned;
  2733. }
  2734. DC_END_FN();
  2735. }
  2736. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  2737. DCVOID CUI::UI_OnNotifyBBarRectChange(RECT *prect)
  2738. {
  2739. if(UI_IsCoreInitialized())
  2740. _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT,
  2741. _pUh,
  2742. CD_NOTIFICATION_FUNC(CUH,UH_SetBBarRect),
  2743. (ULONG_PTR)prect);
  2744. }
  2745. DCVOID CUI::UI_OnNotifyBBarVisibleChange(int BBarVisible)
  2746. {
  2747. if(UI_IsCoreInitialized())
  2748. _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT,
  2749. _pUh,
  2750. CD_NOTIFICATION_FUNC(CUH, UH_SetBBarVisible),
  2751. (ULONG_PTR)BBarVisible);
  2752. }
  2753. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  2754. #endif //USE_BBAR
  2755. VOID CUI::UI_SetControlInstance(IUnknown* pUnkControl)
  2756. {
  2757. DC_BEGIN_FN("UI_SetControlInstance");
  2758. if (_UI.pUnkAxControlInstance) {
  2759. _UI.pUnkAxControlInstance->Release();
  2760. }
  2761. _UI.pUnkAxControlInstance = pUnkControl;
  2762. if (_UI.pUnkAxControlInstance) {
  2763. _UI.pUnkAxControlInstance->AddRef();
  2764. }
  2765. DC_END_FN();
  2766. }
  2767. IUnknown* CUI::UI_GetControlInstance()
  2768. {
  2769. DC_BEGIN_FN("UI_GetControlInstance");
  2770. if (_UI.pUnkAxControlInstance) {
  2771. _UI.pUnkAxControlInstance->AddRef();
  2772. }
  2773. DC_END_FN();
  2774. return _UI.pUnkAxControlInstance;
  2775. }
  2776. //
  2777. // Sets the autoreconnect cookie replacing existing
  2778. // Params:
  2779. // pCookie - new cookie, clear existing if NULL
  2780. // cbLen - new cookie length
  2781. // Returns status (e.g FALSE if failed)
  2782. //
  2783. BOOL CUI::UI_SetAutoReconnectCookie(PBYTE pCookie, ULONG cbLen)
  2784. {
  2785. BOOL fRet = TRUE;
  2786. DC_BEGIN_FN("UI_SetAutoReconnectCookie");
  2787. if (_UI.pAutoReconnectCookie)
  2788. {
  2789. //For security wipe the cookie
  2790. memset(_UI.pAutoReconnectCookie, 0, _UI.cbAutoReconnectCookieLen);
  2791. //Free existing cookie
  2792. LocalFree(_UI.pAutoReconnectCookie);
  2793. _UI.pAutoReconnectCookie = NULL;
  2794. _UI.cbAutoReconnectCookieLen = 0;
  2795. }
  2796. if (pCookie && cbLen)
  2797. {
  2798. _UI.pAutoReconnectCookie = (PBYTE)LocalAlloc(LPTR,
  2799. cbLen);
  2800. if (_UI.pAutoReconnectCookie)
  2801. {
  2802. memcpy(_UI.pAutoReconnectCookie,
  2803. pCookie,
  2804. cbLen);
  2805. #ifdef INSTRUMENT_ARC
  2806. PARC_SC_PRIVATE_PACKET pArcSCPkt = (PARC_SC_PRIVATE_PACKET)
  2807. _UI.pAutoReconnectCookie;
  2808. LPDWORD pdwArcBits = (LPDWORD)pArcSCPkt->ArcRandomBits;
  2809. KdPrint(("ARC-Client:RECEIVED ARC for SID:%d"
  2810. "RAND: 0x%x,0x%x,0x%x,0x%x\n",
  2811. pArcSCPkt->LogonId,
  2812. pdwArcBits[0],pdwArcBits[1],
  2813. pdwArcBits[2],pdwArcBits[3]));
  2814. #endif
  2815. _UI.cbAutoReconnectCookieLen = cbLen;
  2816. }
  2817. else
  2818. {
  2819. TRC_ERR((TB,_T("LocalAlloc failed for autoreconnect cookie")));
  2820. fRet = FALSE;
  2821. }
  2822. }
  2823. DC_END_FN();
  2824. return fRet;
  2825. }
  2826. //
  2827. // Returns TRUE if the client has the ability to autoreconnect
  2828. //
  2829. BOOL CUI::UI_CanAutoReconnect()
  2830. {
  2831. BOOL fCanARC = FALSE;
  2832. DC_BEGIN_FN("UI_CanAutoReconnect");
  2833. if (UI_GetEnableAutoReconnect() &&
  2834. UI_GetAutoReconnectCookieLen() &&
  2835. UI_GetAutoReconnectCookie())
  2836. {
  2837. fCanARC = TRUE;
  2838. }
  2839. DC_END_FN();
  2840. return fCanARC;
  2841. }
  2842. BOOL CUI::UI_StartAutoReconnectDlg()
  2843. {
  2844. BOOL fRet = FALSE;
  2845. DC_BEGIN_FN("UI_StartAutoReconnectDlg");
  2846. TRC_ASSERT(_pArcUI == NULL,
  2847. (TB,_T("_pArcUI is already set. Clobbering!")));
  2848. //
  2849. // Startup the ARC UI
  2850. //
  2851. #ifdef ARC_MINIMAL_UI
  2852. _pArcUI = new CAutoReconnectPlainUI(_UI.hwndMain,
  2853. _UI.hInstance,
  2854. this);
  2855. #else
  2856. _pArcUI = new CAutoReconnectDlg(_UI.hwndMain,
  2857. _UI.hInstance,
  2858. this);
  2859. #endif
  2860. if (_pArcUI) {
  2861. if (_pArcUI->StartModeless()) {
  2862. _pArcUI->ShowTopMost();
  2863. //
  2864. // Start dimming the OP
  2865. //
  2866. if (_pOp) {
  2867. _pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT,
  2868. _pOp,
  2869. CD_NOTIFICATION_FUNC(COP,OP_DimWindow),
  2870. (ULONG_PTR)TRUE);
  2871. }
  2872. #ifdef USE_BBAR
  2873. //
  2874. // In fullscreen mode lower and lock the bbar
  2875. //
  2876. if (UI_IsFullScreen() && _pBBar && _pBBar->GetEnabled()) {
  2877. _pBBar->StartLowerBBar();
  2878. _pBBar->SetLocked(TRUE);
  2879. }
  2880. #endif
  2881. }
  2882. else {
  2883. TRC_ERR((TB,_T("Arc dlg failed to start modeless")));
  2884. }
  2885. }
  2886. fRet = (_pArcUI != NULL);
  2887. DC_END_FN();
  2888. return fRet;
  2889. }
  2890. BOOL CUI::UI_StopAutoReconnectDlg()
  2891. {
  2892. DC_BEGIN_FN("UI_StopAutoReconnectDlg");
  2893. if (_pArcUI) {
  2894. _pArcUI->Destroy();
  2895. delete _pArcUI;
  2896. _pArcUI = NULL;
  2897. }
  2898. #ifdef USE_BBAR
  2899. //
  2900. // Force the bbar unlocked
  2901. //
  2902. if (_pBBar) {
  2903. _pBBar->SetLocked(FALSE);
  2904. }
  2905. #endif
  2906. DC_END_FN();
  2907. return TRUE;
  2908. }
  2909. //
  2910. // Notification that we are autoreconnecting
  2911. //
  2912. // This is the intenal core event that is fired before
  2913. // the activex layer fires one out to the outside world
  2914. // Params:
  2915. // discReason - disconnection reason
  2916. // attemptCount - number of tries so far
  2917. // maxAttemptCount - total number of times to try
  2918. // pfContinueArc - OUT param set to FALSE to stop ARC'ing
  2919. //
  2920. VOID
  2921. CUI::UI_OnAutoReconnecting(
  2922. LONG discReason,
  2923. LONG attemptCount,
  2924. LONG maxAttemptCount,
  2925. BOOL* pfContinueArc)
  2926. {
  2927. DC_BEGIN_FN("UI_OnAutoReconnecing");
  2928. if (1 == attemptCount) {
  2929. TRC_NRM((TB,_T("Trying to start ARC dlg. Attempt count is 1")));
  2930. UI_StartAutoReconnectDlg();
  2931. }
  2932. //
  2933. // If the arc dialog is up just pass it the event
  2934. //
  2935. if (_pArcUI) {
  2936. _pArcUI->OnNotifyAutoReconnecting(discReason,
  2937. attemptCount,
  2938. maxAttemptCount,
  2939. pfContinueArc);
  2940. }
  2941. else {
  2942. //
  2943. // If no ARC dialog then don't stop ARC'ing
  2944. //
  2945. *pfContinueArc = TRUE;
  2946. }
  2947. DC_END_FN();
  2948. }
  2949. //
  2950. // Received autoreconenct status from the server
  2951. //
  2952. VOID
  2953. CUI::UI_OnReceivedArcStatus(LONG arcStatus)
  2954. {
  2955. DC_BEGIN_FN("UI_OnReceivedArcStatus");
  2956. TRC_NRM((TB,_T("arcStatus: 0x%x"), arcStatus));
  2957. //
  2958. // This is our signal to undim the OP and go back to normal
  2959. // painting because ARC failed and we are sitting at winlogon
  2960. //
  2961. //
  2962. // All events are signals that autoreconnect has stopped
  2963. //
  2964. UI_OnAutoReconnectStopped();
  2965. DC_END_FN();
  2966. }
  2967. VOID
  2968. CUI::UI_OnAutoReconnectStopped()
  2969. {
  2970. DC_BEGIN_FN("UI_OnAutoReconnectStopped");
  2971. if (_pArcUI) {
  2972. UI_StopAutoReconnectDlg();
  2973. }
  2974. if (_pCd && _pOp) {
  2975. _pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT,
  2976. _pOp,
  2977. CD_NOTIFICATION_FUNC(COP,OP_DimWindow),
  2978. (ULONG_PTR)FALSE);
  2979. }
  2980. DC_END_FN();
  2981. }
  2982. /****************************************************************************/
  2983. // SetServerRedirectionInfo
  2984. //
  2985. // Used on receipt of a TS_SERVER_REDIRECT_PDU to store the info needed to
  2986. // redirect the client to a new server. Sets the DoRedirection flag as well
  2987. // to indicate these data members are set and ready for use. Also sets the
  2988. // ClientIsRedirected flag, which is longer-lived than the DoRedirection
  2989. // flag and is used to send the correct cookie when redirected.
  2990. /****************************************************************************/
  2991. HRESULT
  2992. CUI::UI_SetServerRedirectionInfo(
  2993. UINT32 SessionID,
  2994. LPTSTR pszServerAddress,
  2995. PBYTE LBInfo,
  2996. unsigned LBInfoSize,
  2997. BOOL fNeedRedirect
  2998. )
  2999. {
  3000. HRESULT hr = E_FAIL;
  3001. DC_BEGIN_FN("UI_SetServerRedirectionInfo");
  3002. _UI.RedirectionSessionID = SessionID;
  3003. //
  3004. // We were redirected so set the flag
  3005. //
  3006. _UI.ClientIsRedirected = TRUE;
  3007. TRC_NRM((TB,_T("Set server redir info: sid:%d addr:%s lpinfo: %p")
  3008. _T("lbsize: %d fRedir:%d"),
  3009. SessionID, pszServerAddress, LBInfo,
  3010. LBInfoSize, fNeedRedirect));
  3011. if (pszServerAddress) {
  3012. hr = StringCchCopy(_UI.RedirectionServerAddress,
  3013. SIZE_TCHARS(_UI.RedirectionServerAddress),
  3014. pszServerAddress);
  3015. if (SUCCEEDED(hr)) {
  3016. _UI.DoRedirection = fNeedRedirect;
  3017. if (LBInfoSize > 0) {
  3018. _UI.bstrRedirectionLBInfo = SysAllocStringByteLen(
  3019. (LPCSTR)LBInfo, LBInfoSize);
  3020. if (_UI.bstrRedirectionLBInfo == NULL)
  3021. {
  3022. hr = E_OUTOFMEMORY;
  3023. TRC_ERR((TB,
  3024. _T("RDP_SERVER_REDIRECTION_PACKET, failed to set the LB info")));
  3025. }
  3026. }
  3027. }
  3028. }
  3029. else {
  3030. hr = E_INVALIDARG;
  3031. }
  3032. DC_END_FN();
  3033. return hr;
  3034. }