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.

1911 lines
76 KiB

  1. /****************************************************************************/
  2. // aco.cpp
  3. //
  4. // Core class.
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. #define TRC_GROUP TRC_GROUP_CORE
  10. #define TRC_FILE "aco"
  11. #define TSC_HR_FILEID TSC_HR_ACO_CPP
  12. #include <atrcapi.h>
  13. #include "aco.h"
  14. // Order important
  15. #include "wui.h"
  16. #include "cd.h"
  17. #include "cc.h"
  18. #include "snd.h"
  19. #include "ih.h"
  20. #include "uh.h"
  21. #include "sl.h"
  22. #include "op.h"
  23. #include "rcv.h"
  24. #include "cm.h"
  25. #include "sp.h"
  26. #include "or.h"
  27. #include "autil.h"
  28. #ifdef OS_WINCE
  29. #include <ceconfig.h>
  30. #endif
  31. extern "C"
  32. VOID WINAPI CO_StaticInit(HINSTANCE hInstance)
  33. {
  34. CIH::IH_StaticInit(hInstance);
  35. }
  36. extern "C"
  37. VOID WINAPI CO_StaticTerm()
  38. {
  39. CIH::IH_StaticTerm();
  40. }
  41. CCO::CCO(CObjs* objs)
  42. {
  43. _pClientObjects = objs;
  44. _fCOInitComplete = FALSE;
  45. }
  46. CCO::~CCO()
  47. {
  48. }
  49. //
  50. // API functions
  51. //
  52. /****************************************************************************/
  53. /* Name: CO_Init */
  54. /* */
  55. /* Purpose: Core Initialization */
  56. /* */
  57. /* Params: IN hInstance - the instance handle */
  58. /* IN hwndMain - the handle of the main window */
  59. /* IN hwndContainer - the handle of the container window */
  60. /****************************************************************************/
  61. void DCAPI CCO::CO_Init(HINSTANCE hInstance, HWND hwndMain, HWND hwndContainer)
  62. {
  63. DC_BEGIN_FN("CO_Init");
  64. TRC_ASSERT(_pClientObjects, (TB,_T("_pClientObjects is NULL")));
  65. _pClientObjects->AddObjReference(CO_OBJECT_FLAG);
  66. //Setup local object pointers
  67. _pUt = _pClientObjects->_pUtObject;
  68. _pUi = _pClientObjects->_pUiObject;
  69. _pSl = _pClientObjects->_pSlObject;
  70. _pUh = _pClientObjects->_pUHObject;
  71. _pRcv = _pClientObjects->_pRcvObject;
  72. _pCd = _pClientObjects->_pCdObject;
  73. _pSnd = _pClientObjects->_pSndObject;
  74. _pCc = _pClientObjects->_pCcObject;
  75. _pIh = _pClientObjects->_pIhObject;
  76. _pOr = _pClientObjects->_pOrObject;
  77. _pSp = _pClientObjects->_pSPObject;
  78. _pOp = _pClientObjects->_pOPObject;
  79. _pCm = _pClientObjects->_pCMObject;
  80. _pClx = _pClientObjects->_pCLXObject;
  81. DC_MEMSET(&_CO, 0, sizeof(_CO));
  82. memset(m_disconnectHRs, 0, sizeof(m_disconnectHRs));
  83. m_disconnectHRIndex = 0;
  84. /************************************************************************/
  85. /* Set UT instance handle */
  86. /************************************************************************/
  87. TRC_NRM((TB, _T("CO setting Instance handle in UT to %p"), hInstance));
  88. _pUi->UI_SetInstanceHandle(hInstance);
  89. _pUt->UT_SetInstanceHandle(hInstance);
  90. /************************************************************************/
  91. /* Set UT Main Window handle. */
  92. /************************************************************************/
  93. TRC_NRM((TB, _T("CO setting Main Window handle in UT to %p"), hwndMain));
  94. _pUi->UI_SetUIMainWindow(hwndMain);
  95. /************************************************************************/
  96. /* Set UT Container Window handle. */
  97. /************************************************************************/
  98. TRC_NRM((TB, _T("CO setting Container Window handle in UT to %p"),
  99. hwndContainer));
  100. _pUi->UI_SetUIContainerWindow(hwndContainer);
  101. //
  102. // Initialize the component decoupler and register the UI (as we are
  103. // running on the UI thread here). CD_Init must be called after
  104. // setting UT.hInstance.
  105. //
  106. _pCd->CD_Init();
  107. _pCd->CD_RegisterComponent(CD_UI_COMPONENT);
  108. COSubclassUIWindows();
  109. // Start the sender thread
  110. _pUt->UT_StartThread(CSND::SND_StaticMain, &_CO.sendThreadID, _pSnd);
  111. _fCOInitComplete = TRUE;
  112. DC_END_FN();
  113. } /* CO_Init */
  114. /****************************************************************************/
  115. /* Name: CO_Term */
  116. /* */
  117. /* Purpose: Core Termination */
  118. /****************************************************************************/
  119. void DCAPI CCO::CO_Term()
  120. {
  121. DC_BEGIN_FN("CO_Term");
  122. if(_fCOInitComplete)
  123. {
  124. // Deregister from the component decoupler
  125. _pCd->CD_UnregisterComponent(CD_UI_COMPONENT);
  126. #ifdef OS_WIN32
  127. // We're on Win32 so terminate the Sender Thread.
  128. // We're called on the UI thread so PUMP messages while
  129. // waiting for the thread to get destroyed
  130. //
  131. //
  132. // Pump messages while waiting since this is the UI thread
  133. //
  134. _pUt->UT_DestroyThread(_CO.sendThreadID, TRUE);
  135. #else
  136. // We're on Win16 so just call SND_Term directly.
  137. SND_Term();
  138. #endif
  139. _pCd->CD_Term();
  140. _pClientObjects->ReleaseObjReference(CO_OBJECT_FLAG);
  141. }
  142. else
  143. {
  144. TRC_DBG((TB,_T("Skipping CO_Term because _fCOInitComplete is false")));
  145. }
  146. DC_END_FN();
  147. } /* CO_Term */
  148. /****************************************************************************/
  149. /* Name: CO_Connect */
  150. /* */
  151. /* Purpose: Connect to an RNS */
  152. /* */
  153. /* Params: IN pConnectStruct - connection information */
  154. /****************************************************************************/
  155. void DCAPI CCO::CO_Connect(PCONNECTSTRUCT pConnectStruct)
  156. {
  157. DC_BEGIN_FN("CO_Connect");
  158. /************************************************************************/
  159. /* Check that the core is initialized. */
  160. /************************************************************************/
  161. TRC_ASSERT((_pUi->UI_IsCoreInitialized()), (TB, _T("Core not initialized")));
  162. /************************************************************************/
  163. /* Call CC with a Connect event */
  164. /************************************************************************/
  165. _pCd->CD_DecoupleNotification(CD_SND_COMPONENT,
  166. _pCc,
  167. CD_NOTIFICATION_FUNC(CCC,CC_Connect),
  168. pConnectStruct,
  169. sizeof(CONNECTSTRUCT));
  170. DC_END_FN();
  171. } /* CO_Connect */
  172. /****************************************************************************/
  173. /* Name: CO_Disconnect */
  174. /* */
  175. /* Purpose: Disconnect */
  176. /* */
  177. /* Operation: call the Call Controller FSM */
  178. /****************************************************************************/
  179. void DCAPI CCO::CO_Disconnect(void)
  180. {
  181. DC_BEGIN_FN("CO_Disconnect");
  182. // Check that the core is initialized.
  183. TRC_ASSERT((_pUi->UI_IsCoreInitialized()), (TB, _T("Core not initialized")));
  184. // Call CC with a Disconnect event.
  185. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT, _pCc,
  186. CD_NOTIFICATION_FUNC(CCC,CC_Event),
  187. (ULONG_PTR) CC_EVT_API_DISCONNECT);
  188. DC_END_FN();
  189. } /* CO_Disconnect */
  190. /****************************************************************************/
  191. /* Name: CO_Shutdown */
  192. /* */
  193. /* Purpose: Shutdown the client */
  194. /* */
  195. /* Params: IN shutdownCode - what kind of shutdown is required. */
  196. /* */
  197. /* Operation: call the Call Controller FSM */
  198. /****************************************************************************/
  199. void DCAPI CCO::CO_Shutdown(unsigned shutdownCode)
  200. {
  201. DC_BEGIN_FN("CO_Shutdown");
  202. //Prevent race by ensuring CO init is complete
  203. if(_fCOInitComplete)
  204. {
  205. // Check that the core is initialized.
  206. if (!_pUi->UI_IsCoreInitialized())
  207. {
  208. //
  209. // Trace and then fake-up a call to UI_OnShutdown to pretend to the
  210. // UI that the shutdown completed successfully.
  211. //
  212. TRC_NRM((TB,_T("Core NOT initialized")));
  213. _pUi->UI_OnShutDown(UI_SHUTDOWN_SUCCESS);
  214. DC_QUIT;
  215. }
  216. switch (shutdownCode)
  217. {
  218. case CO_DISCONNECT_AND_EXIT:
  219. {
  220. TRC_DBG((TB, _T("Shutdown type: disconnect and exit")));
  221. // Call CC with a Shutdown event
  222. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  223. _pCc,
  224. CD_NOTIFICATION_FUNC(CCC,CC_Event),
  225. (ULONG_PTR) CC_EVT_API_DISCONNECTANDEXIT);
  226. }
  227. break;
  228. case CO_SHUTDOWN:
  229. {
  230. TRC_DBG((TB, _T("Shutdown type: shutdown")));
  231. // Call CC with a Shutdown event
  232. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  233. _pCc,
  234. CD_NOTIFICATION_FUNC(CCC,CC_Event),
  235. (ULONG_PTR) CC_EVT_API_SHUTDOWN);
  236. }
  237. break;
  238. default:
  239. {
  240. TRC_ABORT((TB, _T("Illegal shutdown code")));
  241. }
  242. break;
  243. }
  244. }
  245. DC_EXIT_POINT:
  246. DC_END_FN();
  247. } /* CO_Shutdown */
  248. /****************************************************************************/
  249. /* Name: CO_OnSaveSessionInfoPDU */
  250. /* */
  251. /* Purpose: Process Save Session PDU */
  252. /* */
  253. /* Params: pInfoPDU - Ptr to PTS_SAVE_SESSION_INFO_PDU */
  254. /****************************************************************************/
  255. // SECURITY - the size of the packet has been checked only to be sure there is
  256. // enough data to read the PTS_SAVE_SESSION_INFO_PDU_DATA.InfoType field
  257. HRESULT DCAPI CCO::CO_OnSaveSessionInfoPDU(
  258. PTS_SAVE_SESSION_INFO_PDU_DATA pInfoPDU,
  259. DCUINT dataLength)
  260. {
  261. HRESULT hr = S_OK;
  262. UINT32 sessionId;
  263. TSUINT8 UserNameGot[TS_MAX_USERNAME_LENGTH];
  264. TSUINT8 DomainNameGot[TS_MAX_DOMAIN_LENGTH];
  265. TSUINT32 DomainLength, UserNameLength;
  266. TSUINT16 VersionGot;
  267. DCUINT packetSize;
  268. DC_BEGIN_FN("CO_OnSaveSessionInfoPDU");
  269. switch (pInfoPDU->InfoType) {
  270. case TS_INFOTYPE_LOGON:
  271. {
  272. TRC_NRM((TB, _T("Logon PDU")));
  273. packetSize = FIELDOFFSET(TS_SAVE_SESSION_INFO_PDU_DATA, Info) +
  274. sizeof(TS_LOGON_INFO);
  275. if (packetSize >= dataLength)
  276. sessionId = pInfoPDU->Info.LogonInfo.SessionId;
  277. else if (packetSize - FIELDSIZE(TS_LOGON_INFO, SessionId) >=
  278. dataLength) {
  279. // NT4 servers did not send the session ID so default to zero
  280. // if there is no data.
  281. sessionId = 0;
  282. }
  283. else {
  284. TRC_ABORT((TB,_T("bad TS_SAVE_SESSION_INFO_PDU_DATA; size %u"),
  285. dataLength ));
  286. hr = E_TSC_CORE_LENGTH;
  287. DC_QUIT;
  288. }
  289. TRC_ALT((TB, _T("Session ID is: %ld"), sessionId));
  290. if (pInfoPDU->Info.LogonInfo.cbDomain > TS_MAX_DOMAIN_LENGTH_OLD ||
  291. pInfoPDU->Info.LogonInfo.cbUserName > TS_MAX_USERNAME_LENGTH ) {
  292. TRC_ABORT(( TB, _T("Invalid TS_INFOTYPE_LOGON; cbDomain %u ")
  293. _T("cbUserName %u"),
  294. pInfoPDU->Info.LogonInfo.cbDomain,
  295. pInfoPDU->Info.LogonInfo.cbUserName));
  296. hr = E_TSC_CORE_LENGTH;
  297. DC_QUIT;
  298. }
  299. _pUi->UI_UpdateSessionInfo((PDCWCHAR)(pInfoPDU->Info.LogonInfo.Domain),
  300. (DCUINT) (pInfoPDU->Info.LogonInfo.cbDomain),
  301. (PDCWCHAR)(pInfoPDU->Info.LogonInfo.UserName),
  302. (DCUINT) (pInfoPDU->Info.LogonInfo.cbUserName),
  303. sessionId);
  304. }
  305. break;
  306. case TS_INFOTYPE_LOGON_LONG:
  307. {
  308. TRC_NRM((TB, _T("Logon PDU")));
  309. VersionGot = pInfoPDU->Info.LogonInfoVersionTwo.Version ;
  310. DomainLength = pInfoPDU->Info.LogonInfoVersionTwo.cbDomain ;
  311. UserNameLength = pInfoPDU->Info.LogonInfoVersionTwo.cbUserName ;
  312. if ((FIELDOFFSET( TS_SAVE_SESSION_INFO_PDU_DATA, Info) +
  313. sizeof(TS_LOGON_INFO_VERSION_2) + DomainLength + UserNameLength
  314. > dataLength) ||
  315. (DomainLength > TS_MAX_DOMAIN_LENGTH) ||
  316. (UserNameLength > TS_MAX_USERNAME_LENGTH))
  317. {
  318. TRC_ABORT(( TB, _T("Invalid TS_INFOTYPE_LOGON_LONG; cbDomain ")
  319. _T("%u cbUserName %u"), DomainLength, UserNameLength));
  320. hr = E_TSC_CORE_LENGTH;
  321. DC_QUIT;
  322. }
  323. // Get the sessionId
  324. sessionId = pInfoPDU->Info.LogonInfoVersionTwo.SessionId;
  325. TRC_ALT((TB, _T("Session ID is: %ld"), sessionId));
  326. // Parse out the Domain and UserName from the pInfoPDU
  327. memset( DomainNameGot, 0, TS_MAX_DOMAIN_LENGTH);
  328. memset( UserNameGot, 0, TS_MAX_USERNAME_LENGTH);
  329. memcpy( DomainNameGot,
  330. (PBYTE)(pInfoPDU + 1),
  331. DomainLength) ;
  332. memcpy(UserNameGot,
  333. (PBYTE)(pInfoPDU + 1) + DomainLength,
  334. UserNameLength) ;
  335. _pUi->UI_UpdateSessionInfo((PDCWCHAR)(DomainNameGot),
  336. (DCUINT) (DomainLength),
  337. (PDCWCHAR)(UserNameGot),
  338. (DCUINT) (UserNameLength),
  339. sessionId);
  340. }
  341. break;
  342. case TS_INFOTYPE_LOGON_PLAINNOTIFY:
  343. {
  344. //Notify of login event
  345. _pUi->UI_OnLoginComplete();
  346. }
  347. break;
  348. case TS_INFOTYPE_LOGON_EXTENDED_INFO:
  349. {
  350. TRC_NRM((TB,_T("Received TS_INFOTYPE_LOGON_EXTENDED_INFO")));
  351. TS_LOGON_INFO_EXTENDED UNALIGNED* pLogonInfoExPkt =
  352. (TS_LOGON_INFO_EXTENDED UNALIGNED*)&pInfoPDU->Info.LogonInfoEx;
  353. if (FIELDOFFSET(TS_SAVE_SESSION_INFO_PDU_DATA, Info) +
  354. pLogonInfoExPkt->Length > dataLength) {
  355. TRC_ABORT(( TB, _T("Invalid TS_INFOTYPE_LOGON_EXTENDED_INFO")
  356. _T("[expected %u got %u]"),
  357. sizeof(TS_SAVE_SESSION_INFO_PDU_DATA) -
  358. FIELDSIZE(TS_SAVE_SESSION_INFO_PDU_DATA, Info) +
  359. pLogonInfoExPkt->Length, dataLength));
  360. hr = E_TSC_CORE_LENGTH;
  361. DC_QUIT;
  362. }
  363. PBYTE pBuf = (PBYTE)(pLogonInfoExPkt + 1);
  364. if (pLogonInfoExPkt &&
  365. pLogonInfoExPkt->Flags & LOGON_EX_AUTORECONNECTCOOKIE)
  366. {
  367. //
  368. // Autoreconnect cookie is present
  369. //
  370. ULONG cbAutoReconnectSize = *((ULONG UNALIGNED *)(pBuf));
  371. PBYTE pAutoReconnectCookie = (PBYTE)(pBuf) + sizeof(ULONG);
  372. pBuf += cbAutoReconnectSize + sizeof(ULONG);
  373. if (cbAutoReconnectSize > TS_MAX_AUTORECONNECT_LEN) {
  374. TRC_ABORT(( TB, _T("TS_INFOTYPE_LOGON_EXTENDED_INFO")
  375. _T("autoreconnect wrong size; [got %u]"),
  376. cbAutoReconnectSize));
  377. hr = E_TSC_CORE_LENGTH;
  378. DC_QUIT;
  379. }
  380. CHECK_READ_N_BYTES( pAutoReconnectCookie, (PBYTE)pInfoPDU + dataLength,
  381. cbAutoReconnectSize, hr,
  382. (TB,_T("TS_INFOTYPE_LOGON_EXTENDED_INFO")
  383. _T("autoreconnect wrong size; [got %u]"),
  384. cbAutoReconnectSize));
  385. TRC_ALT((TB,_T("Received autoreconnect cookie - size: %d"),
  386. cbAutoReconnectSize));
  387. //
  388. // Store the autoreconnect cookie. It will be used
  389. // if we get disconnected unexpectedly to allow a
  390. // fast reconnect to the server.
  391. //
  392. _pUi->UI_SetAutoReconnectCookie(pAutoReconnectCookie,
  393. cbAutoReconnectSize);
  394. }
  395. }
  396. break;
  397. default:
  398. {
  399. TRC_ERR((TB, _T("Unexpected Save Session Info PDU type: %u"),
  400. (DCUINT)pInfoPDU->InfoType));
  401. }
  402. break;
  403. }
  404. DC_EXIT_POINT:
  405. DC_END_FN();
  406. return hr;
  407. } /* CO_OnSaveSessionInfoPDU */
  408. /****************************************************************************/
  409. /* Name: CO_OnSetKeyboardIndicatorsPDU */
  410. /* */
  411. /* Purpose: Process the TS_SET_KEYBOARD_INDICATORS_PDU */
  412. /* */
  413. /* Params: pKeyPDU - Ptr to TS_SET_KEYBOARD_INDICATORS_PDU */
  414. /****************************************************************************/
  415. HRESULT DCAPI CCO::CO_OnSetKeyboardIndicatorsPDU(
  416. PTS_SET_KEYBOARD_INDICATORS_PDU pKeyPDU, DCUINT dataLen)
  417. {
  418. DC_BEGIN_FN("CO_OnSetKeyboardIndicatorsPDU");
  419. DC_IGNORE_PARAMETER(dataLen);
  420. _pIh->IH_UpdateKeyboardIndicators(pKeyPDU->UnitId, pKeyPDU->LedFlags);
  421. DC_END_FN();
  422. return S_OK;
  423. } /* CO_OnSetKeyboardIndicatorsPDU */
  424. /****************************************************************************/
  425. /* Name: CO_SetConfigurationValue */
  426. /* */
  427. /* Purpose: Sets a given configuration setting to a given value */
  428. /* */
  429. /* Params: configItem - the configuration item to change */
  430. /* configValue - the new value of the configuration item */
  431. /* (see acoapi.h for valid values) */
  432. /****************************************************************************/
  433. void DCAPI CCO::CO_SetConfigurationValue(
  434. unsigned configItem,
  435. unsigned configValue)
  436. {
  437. DC_BEGIN_FN("CO_SetConfigurationValue");
  438. TRC_ASSERT((_pUi->UI_IsCoreInitialized()), (TB, _T("Core not initialized")));
  439. switch (configItem) {
  440. case CO_CFG_ACCELERATOR_PASSTHROUGH:
  441. {
  442. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  443. _pIh,
  444. CD_NOTIFICATION_FUNC(CIH,IH_SetAcceleratorPassthrough),
  445. (ULONG_PTR) configValue);
  446. }
  447. break;
  448. case CO_CFG_ENCRYPTION:
  449. {
  450. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  451. _pSl,
  452. CD_NOTIFICATION_FUNC(CSL,SL_EnableEncryption),
  453. (ULONG_PTR) configValue);
  454. }
  455. break;
  456. #ifdef DC_DEBUG
  457. case CO_CFG_DEBUG_SETTINGS:
  458. {
  459. _pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT,
  460. _pUh,
  461. CD_NOTIFICATION_FUNC(CUH,UH_ChangeDebugSettings),
  462. (ULONG_PTR) configValue);
  463. }
  464. break;
  465. #endif /* DC_DEBUG */
  466. default:
  467. {
  468. TRC_ABORT((TB, _T("Invalid configItem: %u"), configItem));
  469. }
  470. break;
  471. }
  472. DC_END_FN();
  473. } /* CO_SetConfigurationValue */
  474. /****************************************************************************/
  475. /* Name: CO_SetHotkey */
  476. /* */
  477. /* Purpose: call the function with the given data */
  478. /****************************************************************************/
  479. void DCAPI CCO::CO_SetHotkey(PDCHOTKEY pHotkey)
  480. {
  481. _pCd->CD_DecoupleNotification(CD_SND_COMPONENT,
  482. _pIh,
  483. CD_NOTIFICATION_FUNC(CIH,IH_SetHotkey),
  484. &pHotkey,
  485. sizeof(PDCHOTKEY));
  486. }
  487. #ifdef DC_DEBUG
  488. /****************************************************************************/
  489. /* Name: CO_GetRandomFailureItem */
  490. /* */
  491. /* Purpose: Simple wrapper to _pUt->UT_GetRandomFailureItem */
  492. /* */
  493. /* Returns: % times item currently fails */
  494. /* */
  495. /* Params: ItemID - IN - requested item */
  496. /****************************************************************************/
  497. int DCAPI CCO::CO_GetRandomFailureItem(unsigned itemID)
  498. {
  499. DC_BEGIN_FN("CO_GetRandomFailureItem");
  500. DC_END_FN();
  501. return _pUt->UT_GetRandomFailureItem(itemID);
  502. } /* CO_GetRandomFailureItem */
  503. /****************************************************************************/
  504. /* Name: CO_SetRandomFailureItem */
  505. /* */
  506. /* Purpose: Simple wrapper for _pUi->UI_SetRandomFailureItem */
  507. /* */
  508. /* Params: See _pUi->UI_SetRandomFailureItem */
  509. /****************************************************************************/
  510. void DCAPI CCO::CO_SetRandomFailureItem(unsigned itemID, int percent)
  511. {
  512. DC_BEGIN_FN("CO_SetRandomFailureItem");
  513. _pUt->UT_SetRandomFailureItem(itemID, percent);
  514. DC_END_FN();
  515. } /* CO_SetRandomFailureItem */
  516. #endif /* DC_DEBUG */
  517. /****************************************************************************/
  518. /* Name: COContainerWindowSubclassProc */
  519. /* */
  520. /* Purpose: Subclass procedure for the UI Container Window */
  521. /****************************************************************************/
  522. LRESULT CALLBACK CCO::COContainerWindowSubclassProc( HWND hwnd,
  523. UINT message,
  524. WPARAM wParam,
  525. LPARAM lParam )
  526. {
  527. LRESULT rc = 0;
  528. POINT newPos;
  529. DC_BEGIN_FN("COContainerWindowSubclassProc");
  530. switch (message)
  531. {
  532. case WM_SETFOCUS:
  533. {
  534. //
  535. // Note, the code here used to use CallWindowProc.
  536. // this has been changed to use a direct call.
  537. // If there is ever a need for Unicode/ANSI conversions
  538. // then change the direct calls to the window proc
  539. // to use CallWindowProc
  540. //
  541. rc =_pUi->UIContainerWndProc( hwnd, message, wParam, lParam);
  542. if (rc) {
  543. SetFocus(_pIh->IH_GetInputHandlerWindow());
  544. }
  545. }
  546. break;
  547. case WM_MOVE:
  548. {
  549. /****************************************************************/
  550. /* Tell IH about the new window position. */
  551. /* Take care with sign extension here. */
  552. /****************************************************************/
  553. newPos.x = (DCINT)((DCINT16)LOWORD(lParam));
  554. newPos.y = (DCINT)((DCINT16)HIWORD(lParam));
  555. TRC_DBG((TB, _T("Move to %d,%d"), newPos.x, newPos.y));
  556. _pCd->CD_DecoupleNotification(CD_SND_COMPONENT,
  557. _pIh,
  558. CD_NOTIFICATION_FUNC(CIH,IH_SetVisiblePos),
  559. &newPos,
  560. sizeof(newPos));
  561. rc = _pUi->UIContainerWndProc( hwnd, message, wParam, lParam);
  562. }
  563. break;
  564. default:
  565. {
  566. rc =_pUi->UIContainerWndProc( hwnd, message, wParam, lParam);
  567. }
  568. break;
  569. }
  570. DC_END_FN();
  571. return rc;
  572. } /* COContainerWindowSubclassProc */
  573. /****************************************************************************/
  574. /* Name: COMainFrameWindowSubclassProc */
  575. /* */
  576. /* Purpose: Subclass procedure for the UI Main Frame Window */
  577. /****************************************************************************/
  578. LRESULT CALLBACK CCO::COMainWindowSubclassProc( HWND hwnd,
  579. UINT message,
  580. WPARAM wParam,
  581. LPARAM lParam )
  582. {
  583. LRESULT rc = 0;
  584. DCSIZE newSize;
  585. DC_BEGIN_FN("COMainWindowSubclassProc");
  586. switch (message) {
  587. case WM_SIZE:
  588. {
  589. /****************************************************************/
  590. /* Tell IH about the new window size. */
  591. /* Take care with sign extension here. */
  592. /****************************************************************/
  593. newSize.width = (DCINT)((DCINT16)LOWORD(lParam));
  594. newSize.height = (DCINT)((DCINT16)HIWORD(lParam));
  595. TRC_DBG((TB, _T("Size now %d,%d"), newSize.width, newSize.height));
  596. switch (wParam)
  597. {
  598. case SIZE_MINIMIZED:
  599. case SIZE_MAXIMIZED:
  600. case SIZE_RESTORED:
  601. {
  602. WPARAM newWindowState = wParam;
  603. //
  604. // This is slightly hack-erific.
  605. // because we're now an ActiveX nested child window
  606. // we don't get a WM_MINIMIZED. But on minimize
  607. // the size becomes 0,0 so fake it.
  608. //
  609. if(!newSize.width && !newSize.height)
  610. {
  611. newWindowState = SIZE_MINIMIZED;
  612. }
  613. /********************************************************/
  614. /* OR interested in these to maybe send */
  615. /* SuppressOutputPDU */
  616. /********************************************************/
  617. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  618. _pOr,
  619. CD_NOTIFICATION_FUNC(COR,OR_SetSuppressOutput),
  620. (UINT) newWindowState);
  621. }
  622. break;
  623. default:
  624. {
  625. /********************************************************/
  626. /* OR not interested in these - do nothing */
  627. /********************************************************/
  628. }
  629. break;
  630. }
  631. rc =_pUi->UIMainWndProc( hwnd, message, wParam, lParam);
  632. }
  633. break;
  634. case WM_PALETTECHANGED:
  635. {
  636. TRC_NRM((TB, _T("WM_PALETTECHANGED")));
  637. /****************************************************************/
  638. /* Note that we are calling this function (which should */
  639. /* logically be called on the receive thread) on the UI thread. */
  640. /* See comment in function description. */
  641. /****************************************************************/
  642. _pOp->OP_PaletteChanged(hwnd, (HWND)wParam);
  643. }
  644. break;
  645. case WM_QUERYNEWPALETTE:
  646. {
  647. TRC_NRM((TB, _T("WM_QUERYNEWPALETTE")));
  648. /****************************************************************/
  649. /* Note that we are calling this function (which should */
  650. /* logically be called on the receive thread) on the UI thread. */
  651. /* See comment in function description. */
  652. /****************************************************************/
  653. rc = _pOp->OP_QueryNewPalette(hwnd);
  654. }
  655. break;
  656. #ifdef OS_WINNT
  657. case WM_ENTERSIZEMOVE:
  658. {
  659. /****************************************************************/
  660. /* Tell IH we're entering Size/Move mode */
  661. /****************************************************************/
  662. TRC_NRM((TB, _T("Enter Size/Move")));
  663. _CO.inSizeMove = TRUE;
  664. _pCd->CD_DecoupleSyncNotification(CD_SND_COMPONENT,
  665. _pIh,
  666. CD_NOTIFICATION_FUNC(CIH,IH_InputEvent),
  667. WM_ENTERSIZEMOVE);
  668. }
  669. break;
  670. case WM_CAPTURECHANGED:
  671. {
  672. if (_CO.inSizeMove)
  673. {
  674. /************************************************************/
  675. /* Tell IH we're leaving size/move mode (Windows doesn't */
  676. /* always send WM_EXITSIZEMOVE, but it does seem to always */
  677. /* send WM_CAPTURECHANGED). */
  678. /************************************************************/
  679. TRC_NRM((TB, _T("Capture Changed when in Size/Move")));
  680. _CO.inSizeMove = FALSE;
  681. _pCd->CD_DecoupleSyncNotification(CD_SND_COMPONENT,
  682. _pIh,
  683. CD_NOTIFICATION_FUNC(CIH,IH_InputEvent),
  684. WM_EXITSIZEMOVE);
  685. }
  686. }
  687. break;
  688. case WM_EXITSIZEMOVE:
  689. {
  690. // Tell IH we're leaving size/move mode.
  691. TRC_NRM((TB, _T("Exit Size/Move")));
  692. _CO.inSizeMove = FALSE;
  693. _pCd->CD_DecoupleSyncNotification(CD_SND_COMPONENT,
  694. _pIh,
  695. CD_NOTIFICATION_FUNC(CIH,IH_InputEvent),
  696. WM_EXITSIZEMOVE);
  697. }
  698. break;
  699. case WM_EXITMENULOOP:
  700. {
  701. // Tell IH we're exiting the system menu handler.
  702. TRC_NRM((TB, _T("Exit menu loop")));
  703. _pCd->CD_DecoupleSyncNotification(CD_SND_COMPONENT,
  704. _pIh,
  705. CD_NOTIFICATION_FUNC(CIH,IH_InputEvent),
  706. WM_EXITMENULOOP);
  707. }
  708. break;
  709. #endif
  710. #ifdef OS_WINCE
  711. // HPC devices do not get WM_SIZE (SIZE_RESTORED) on a maximize,
  712. // but we do get the WM_ACTIVATE message.
  713. case WM_ACTIVATE:
  714. {
  715. if (g_CEConfig != CE_CONFIG_WBT &&
  716. LOWORD(wParam) != WA_INACTIVE)
  717. {
  718. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  719. _pOr,
  720. CD_NOTIFICATION_FUNC(COR,OR_SetSuppressOutput),
  721. SIZE_RESTORED);
  722. }
  723. }
  724. // FALL-THRU
  725. #endif // OS_WINCE
  726. default:
  727. {
  728. rc =_pUi->UIMainWndProc( hwnd, message, wParam, lParam);
  729. }
  730. break;
  731. }
  732. DC_END_FN();
  733. return rc;
  734. } /* COContainerWindowSubclassProc */
  735. LRESULT CALLBACK CCO::COStaticContainerWindowSubclassProc( HWND hwnd,
  736. UINT message,
  737. WPARAM wParam,
  738. LPARAM lParam )
  739. {
  740. // delegate to appropriate instance
  741. CCO* pCO = (CCO*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  742. return pCO->COContainerWindowSubclassProc(hwnd, message, wParam, lParam);
  743. }
  744. LRESULT CALLBACK CCO::COStaticMainWindowSubclassProc( HWND hwnd,
  745. UINT message,
  746. WPARAM wParam,
  747. LPARAM lParam )
  748. {
  749. // delegate to appropriate instance
  750. CCO* pCO = (CCO*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  751. return pCO->COMainWindowSubclassProc(hwnd, message, wParam, lParam);
  752. }
  753. /****************************************************************************/
  754. /* Name: COSubclassUIWindows */
  755. /* */
  756. /* Purpose: Subclasses the UI's Main Frame and Container Windows */
  757. /****************************************************************************/
  758. void DCINTERNAL CCO::COSubclassUIWindows()
  759. {
  760. DC_BEGIN_FN("COSubclassUIWindows");
  761. // Replace the instance pointer with that for the CO object
  762. // when subclassing. Have to do this because CO is not derived from UI
  763. SetWindowLongPtr( _pUi->UI_GetUIMainWindow(), GWLP_USERDATA, (LONG_PTR)this);
  764. SetWindowLongPtr( _pUi->UI_GetUIContainerWindow(), GWLP_USERDATA, (LONG_PTR)this);
  765. _CO.pUIMainWndProc = SubclassWindow( _pUi->UI_GetUIMainWindow(),
  766. COStaticMainWindowSubclassProc );
  767. _CO.pUIContainerWndProc = SubclassWindow( _pUi->UI_GetUIContainerWindow(),
  768. COStaticContainerWindowSubclassProc );
  769. DC_END_FN();
  770. } /* COSubclassUIWindows */
  771. /****************************************************************************/
  772. /* Name: CO_OnInitialized */
  773. /* */
  774. /* Purpose: Handle Initialized notification from SL */
  775. /* */
  776. /* Operation: Initialize the Receiver Thread */
  777. /****************************************************************************/
  778. void DCCALLBACK CCO::CO_OnInitialized()
  779. {
  780. DC_BEGIN_FN("CO_OnInitialized");
  781. // Call RCV_Init to initialize the Core.
  782. _pRcv->RCV_Init();
  783. DC_END_FN();
  784. } /* CO_OnInitialized */
  785. /****************************************************************************/
  786. /* Name: CO_OnTerminating */
  787. /* */
  788. /* Purpose: Handle Terminating notification from SL */
  789. /****************************************************************************/
  790. void DCCALLBACK CCO::CO_OnTerminating()
  791. {
  792. DC_BEGIN_FN("CO_OnTerminating");
  793. // Terminate Core components.
  794. _pRcv->RCV_Term();
  795. DC_END_FN();
  796. } /* CO_OnTerminating */
  797. /****************************************************************************/
  798. /* Name: CO_OnConnected */
  799. /* */
  800. /* Purpose: Handle Connected notification from SL */
  801. /* */
  802. /* Params: IN channelID */
  803. /* IN pUserData */
  804. /* IN userDataLength */
  805. /****************************************************************************/
  806. void DCCALLBACK CCO::CO_OnConnected(
  807. unsigned channelID,
  808. PVOID pUserData,
  809. unsigned userDataLength,
  810. UINT32 serverVersion)
  811. {
  812. DC_BEGIN_FN("CO_OnConnected");
  813. TRC_DBG((TB, _T("Channel %d"), channelID));
  814. DC_IGNORE_PARAMETER(serverVersion);
  815. // Currently there is no Core userdata sent from the Server.
  816. DC_IGNORE_PARAMETER(pUserData);
  817. DC_IGNORE_PARAMETER(userDataLength);
  818. DC_IGNORE_PARAMETER(channelID);
  819. // Pass to CC.
  820. TRC_NRM((TB, _T("Connect OK")));
  821. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  822. _pCc,
  823. CD_NOTIFICATION_FUNC(CCC,CC_Event),
  824. (ULONG_PTR) CC_EVT_API_ONCONNECTOK);
  825. DC_END_FN();
  826. } /* CO_OnConnected */
  827. /****************************************************************************/
  828. /* Name: CO_OnDisconnected */
  829. /* */
  830. /* Purpose: Handle Disconnected notification from SL */
  831. /* */
  832. /* Params: IN result - disconnection reason code */
  833. /****************************************************************************/
  834. void DCCALLBACK CCO::CO_OnDisconnected(unsigned result)
  835. {
  836. DC_BEGIN_FN("CO_OnDisconnected");
  837. DC_IGNORE_PARAMETER(result);
  838. // Pass to CC.
  839. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  840. _pCc,
  841. CD_NOTIFICATION_FUNC(CCC,CC_OnDisconnected),
  842. (ULONG_PTR) result);
  843. DC_END_FN();
  844. } /* CO_OnDisconnected */
  845. #define CO_CHECKPACKETCAST( type, size, hr ) \
  846. if ( (size) < sizeof(type)) { \
  847. TRC_ABORT((TB, _T("Bad ") _T( #type ) _T(" len [expected %u got %u]"), \
  848. sizeof(type), (size) )); \
  849. hr = E_TSC_CORE_LENGTH; \
  850. DC_QUIT; \
  851. }
  852. #define CO_CHECKPACKETCAST_SPECIFC( type, size, expected, hr ) \
  853. if ( (size) < (expected)) { \
  854. TRC_ABORT((TB, _T("Bad ") _T( #type ) _T(" len [expected %u got %u]"), \
  855. (expected), (size) )); \
  856. hr = E_TSC_CORE_LENGTH; \
  857. DC_QUIT; \
  858. }
  859. // This macro is used to see that when a pointer to a TS_SHAREDATAHEADER
  860. // is passed on to a handler, the TS_SHAREDATAHEADER is an uncompressed packet
  861. // If the packet was compressed, then the data after the TS_SHAREDATAHEADER is
  862. // still compressed, and the method we pass this header onto will puke on the
  863. // data, assuming it does not uncompress the data, which no layers above this
  864. // do
  865. #define COPR_MUSTBEUNCOMP( type, pDataHdr, hr ) \
  866. if (pDataHdr->generalCompressedType & PACKET_COMPRESSED) { \
  867. TRC_ABORT((TB, _T( #type ) \
  868. _T(" was unexpectedly compressed"))); \
  869. hr = E_TSC_CORE_UNEXPECTEDCOMP; \
  870. DC_QUIT; \
  871. }
  872. /****************************************************************************/
  873. /* Name: CO_OnPacketReceived */
  874. /* */
  875. /* Purpose: Handle PacketReceived notification from SL */
  876. /* */
  877. /* Params: IN pData - packet received */
  878. /* IN dataLen - length of packet */
  879. /* IN flags - RNS_SEC_ flags */
  880. /* IN channelID - MCS channel on which packet was sent */
  881. /* IN priority - priority of packet */
  882. /****************************************************************************/
  883. HRESULT DCCALLBACK CCO::CO_OnPacketReceived(
  884. PBYTE pData,
  885. unsigned dataLen,
  886. unsigned flags,
  887. unsigned channelID,
  888. unsigned priority)
  889. {
  890. HRESULT hr = S_OK;
  891. PTS_SHARECONTROLHEADER pCtrlHdr;
  892. PTS_SHAREDATAHEADER pDataHdr;
  893. PTS_FLOW_PDU pFlowPDU;
  894. PDCUINT8 pCurrentPDU;
  895. DCUINT currentDataLen;
  896. DCUINT dataBufLen;
  897. #ifdef DC_DEBUG
  898. DCUINT countPDU = 0;
  899. #endif
  900. DCUINT dataRemaining = dataLen;
  901. DC_BEGIN_FN("CO_OnPacketReceived");
  902. DC_IGNORE_PARAMETER(flags);
  903. DC_IGNORE_PARAMETER(priority);
  904. DC_IGNORE_PARAMETER(channelID);
  905. TRC_ASSERT((pData != NULL), (TB, _T("NULL packet")));
  906. TRC_NRM((TB, _T("channelID %#x"), channelID));
  907. TRC_NRM((TB, _T("(fixed) Buffer: %p len %d"), pData, dataLen));
  908. TRC_DATA_DBG("Contents", pData, dataLen);
  909. // Find the first PDU in the packet.
  910. pCurrentPDU = pData;
  911. // And while there are more PDUs in the packet, route each PDU.
  912. while (pCurrentPDU != NULL) {
  913. // Intermediate variable to save in casts!
  914. pCtrlHdr = (PTS_SHARECONTROLHEADER)pCurrentPDU;
  915. // SECURITY: NOTE - it is not safe to read the pduSource
  916. // field of the TS_SHARECONTROLHEADER since we are not
  917. // requiring this data to be there. This is to support
  918. // the TS_PDUTYPE_DEACTIVATEALLPDU which appears smaller
  919. // on win2k
  920. // Be sure there is enough data to read the totalLength
  921. if (dataRemaining < FIELDOFFSET(TS_SHARECONTROLHEADER, pduSource)) {
  922. TRC_ABORT(( TB, _T("dataRemaining %u partial sizeof(TS_")
  923. _T("SHARECONTROLHEADER) %u "), dataRemaining,
  924. FIELDOFFSET(TS_SHARECONTROLHEADER, pduSource)));
  925. hr = E_TSC_CORE_LENGTH;
  926. DC_QUIT;
  927. }
  928. // All PDUs start with the length and PDU type, except FlowPDUs.
  929. if (pCtrlHdr->totalLength != TS_FLOW_MARKER) {
  930. currentDataLen = pCtrlHdr->totalLength;
  931. // Be sure there is enough data for the entire packet
  932. if (dataRemaining < currentDataLen) {
  933. TRC_ABORT(( TB, _T("dataRemaining %u currentDataLen %u"),
  934. dataRemaining, currentDataLen));
  935. hr = E_TSC_CORE_LENGTH;
  936. DC_QUIT;
  937. }
  938. if (sizeof(PTS_SHAREDATAHEADER) <= dataRemaining) {
  939. TRC_NRM((TB, _T("current PDU x%p type %u, type2 %u, data len %u"),
  940. pCurrentPDU,
  941. (pCtrlHdr->pduType) & TS_MASK_PDUTYPE,
  942. ((PTS_SHAREDATAHEADER)pCurrentPDU)->pduType2,
  943. currentDataLen));
  944. }
  945. switch ((pCtrlHdr->pduType) & TS_MASK_PDUTYPE) {
  946. case TS_PDUTYPE_DATAPDU:
  947. {
  948. PDCUINT8 pDataBuf;
  949. TRC_DBG((TB, _T("A Data PDU")));
  950. CO_CHECKPACKETCAST(TS_SHAREDATAHEADER, currentDataLen, hr);
  951. pDataHdr = (PTS_SHAREDATAHEADER)pCurrentPDU;
  952. pDataBuf = pCurrentPDU + sizeof(TS_SHAREDATAHEADER);
  953. dataBufLen = currentDataLen - sizeof(TS_SHAREDATAHEADER);
  954. if (pDataHdr->generalCompressedType & PACKET_COMPRESSED) {
  955. UCHAR *buf;
  956. int bufSize;
  957. if (pDataHdr->generalCompressedType & PACKET_FLUSHED)
  958. initrecvcontext (&_pUi->_UI.Context1,
  959. (RecvContext2_Generic*)_pUi->_UI.pRecvContext2,
  960. PACKET_COMPR_TYPE_64K);
  961. if (decompress(pDataBuf,
  962. pCtrlHdr->totalLength - sizeof(TS_SHAREDATAHEADER),
  963. (pDataHdr->generalCompressedType & PACKET_AT_FRONT),
  964. &buf,
  965. &bufSize,
  966. &_pUi->_UI.Context1,
  967. (RecvContext2_Generic*)_pUi->_UI.pRecvContext2,
  968. (pDataHdr->generalCompressedType &
  969. PACKET_COMPR_TYPE_MASK))) {
  970. pDataBuf = buf;
  971. dataBufLen = bufSize;
  972. }
  973. else {
  974. TRC_ABORT((TB, _T("Decompression FAILURE!!!")));
  975. hr = E_TSC_UI_DECOMPRESSION;
  976. DC_QUIT;
  977. }
  978. }
  979. switch (pDataHdr->pduType2) {
  980. case TS_PDUTYPE2_UPDATE:
  981. CO_CHECKPACKETCAST(TS_UPDATE_HDR_DATA,
  982. dataBufLen, hr);
  983. TRC_DBG((TB, _T("Update PDU")));
  984. hr = _pUh->UH_OnUpdatePDU(
  985. (TS_UPDATE_HDR_DATA UNALIGNED FAR *)
  986. pDataBuf, dataBufLen);
  987. DC_QUIT_ON_FAIL(hr);
  988. break;
  989. case TS_PDUTYPE2_POINTER:
  990. // SECURITY: Only the TS_POINTER_PDU_DATA.messageType needs to be
  991. // read. NT4 servers may not send a TS_POINTER_PDU_DATA.pointerData
  992. CO_CHECKPACKETCAST_SPECIFC(TS_POINTER_PDU_DATA,
  993. dataBufLen, sizeof(TSUINT16), hr);
  994. TRC_DBG((TB, _T("Mouse Pointer PDU")));
  995. hr = _pCm->CM_SlowPathPDU(
  996. (TS_POINTER_PDU_DATA UNALIGNED FAR *)
  997. pDataBuf, dataBufLen);
  998. DC_QUIT_ON_FAIL(hr);
  999. break;
  1000. case TS_PDUTYPE2_FONTMAP:
  1001. case TS_PDUTYPE2_INPUT:
  1002. case TS_PDUTYPE2_UPDATECAPABILITY:
  1003. case TS_PDUTYPE2_DESKTOP_SCROLL:
  1004. case TS_PDUTYPE2_APPLICATION:
  1005. case TS_PDUTYPE2_CONTROL:
  1006. case TS_PDUTYPE2_MEDIATEDCONTROL:
  1007. case TS_PDUTYPE2_REMOTESHARE:
  1008. case TS_PDUTYPE2_SYNCHRONIZE:
  1009. case TS_PDUTYPE2_WINDOWLISTUPDATE:
  1010. case TS_PDUTYPE2_WINDOWACTIVATION:
  1011. TRC_DBG((TB, _T("Ignore pdutype2 %#x"),
  1012. pDataHdr->pduType2));
  1013. break;
  1014. case TS_PDUTYPE2_SHUTDOWN_DENIED:
  1015. TRC_DBG((TB, _T("ShutdownDeniedPDU")));
  1016. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  1017. _pCc,
  1018. CD_NOTIFICATION_FUNC(CCC,CC_Event),
  1019. (ULONG_PTR)CC_EVT_API_ONSHUTDOWNDENIED);
  1020. break;
  1021. case TS_PDUTYPE2_PLAY_SOUND:
  1022. CO_CHECKPACKETCAST(TS_PLAY_SOUND_PDU_DATA,
  1023. dataBufLen, hr);
  1024. TRC_DBG((TB, _T("PlaySoundPDU")));
  1025. hr = _pSp->SP_OnPlaySoundPDU((PTS_PLAY_SOUND_PDU_DATA)
  1026. pDataBuf, dataBufLen);
  1027. DC_QUIT_ON_FAIL(hr);
  1028. break;
  1029. case TS_PDUTYPE2_SAVE_SESSION_INFO:
  1030. //CO_CHECKPACKETCAST(TS_SAVE_SESSION_INFO_PDU_DATA, dataBufLen, hr);
  1031. // SECURITY: TS_SAVE_SESSION_INFO_PDU_DATA may be sent from NT4 with
  1032. // only a TS_SAVE_SESSION_INFO_PDU_DATA.InfoType
  1033. CO_CHECKPACKETCAST_SPECIFC(TS_SAVE_SESSION_INFO_PDU_DATA,
  1034. dataBufLen, sizeof(TSUINT32), hr);
  1035. TRC_DBG((TB, _T("Save Session Info PDU")));
  1036. hr = CO_OnSaveSessionInfoPDU(
  1037. (PTS_SAVE_SESSION_INFO_PDU_DATA)pDataBuf,
  1038. dataBufLen);
  1039. DC_QUIT_ON_FAIL(hr);
  1040. break;
  1041. case TS_PDUTYPE2_SET_KEYBOARD_INDICATORS:
  1042. CO_CHECKPACKETCAST(TS_SET_KEYBOARD_INDICATORS_PDU,
  1043. currentDataLen, hr);
  1044. COPR_MUSTBEUNCOMP(TS_SET_KEYBOARD_INDICATORS_PDU,
  1045. pDataHdr, hr);
  1046. TRC_DBG((TB, _T("TS_PDUTYPE2_SET_KEYBOARD_INDICATORS PDU")));
  1047. hr = CO_OnSetKeyboardIndicatorsPDU
  1048. ((PTS_SET_KEYBOARD_INDICATORS_PDU)pCurrentPDU,
  1049. currentDataLen);
  1050. DC_QUIT_ON_FAIL(hr);
  1051. break;
  1052. case TS_PDUTYPE2_SET_KEYBOARD_IME_STATUS:
  1053. {
  1054. PTS_SET_KEYBOARD_IME_STATUS_PDU pImePDU;
  1055. CO_CHECKPACKETCAST(TS_SET_KEYBOARD_IME_STATUS_PDU,
  1056. currentDataLen, hr);
  1057. COPR_MUSTBEUNCOMP(TS_SET_KEYBOARD_IME_STATUS_PDU,
  1058. pDataHdr, hr);
  1059. TRC_DBG((TB, _T("TS_PDUTYPE2_SET_KEYBOARD_IME_STATUS PDU")));
  1060. pImePDU = (PTS_SET_KEYBOARD_IME_STATUS_PDU)pCurrentPDU;
  1061. _pIh->IH_SetKeyboardImeStatus(pImePDU->ImeOpen,
  1062. pImePDU->ImeConvMode);
  1063. break;
  1064. }
  1065. case TS_PDUTYPE2_SET_ERROR_INFO_PDU:
  1066. {
  1067. PTS_SET_ERROR_INFO_PDU pErrInfoPDU;
  1068. CO_CHECKPACKETCAST(TS_SET_ERROR_INFO_PDU,
  1069. currentDataLen, hr);
  1070. COPR_MUSTBEUNCOMP(TS_SET_ERROR_INFO_PDU,
  1071. pDataHdr, hr);
  1072. TRC_DBG((TB, _T("TS_SET_ERROR_INFO_PDU PDU")));
  1073. pErrInfoPDU = (PTS_SET_ERROR_INFO_PDU)pCurrentPDU;
  1074. _pUi->UI_SetServerErrorInfo(pErrInfoPDU->errorInfo);
  1075. break;
  1076. }
  1077. case TS_PDUTYPE2_ARC_STATUS_PDU:
  1078. {
  1079. PTS_AUTORECONNECT_STATUS_PDU pArcStatusPDU;
  1080. CO_CHECKPACKETCAST(TS_AUTORECONNECT_STATUS_PDU,
  1081. currentDataLen, hr);
  1082. COPR_MUSTBEUNCOMP(TS_AUTORECONNECT_STATUS_PDU,
  1083. pDataHdr, hr);
  1084. TRC_DBG((TB, _T("TS_PDUTYPE2_ARC_STATUS_PDU")));
  1085. pArcStatusPDU = (PTS_AUTORECONNECT_STATUS_PDU)pCurrentPDU;
  1086. _pUi->UI_OnReceivedArcStatus(pArcStatusPDU->arcStatus);
  1087. break;
  1088. }
  1089. default:
  1090. TRC_ABORT((TB, _T("Invalid pduType2 %#x"),
  1091. pDataHdr->pduType2));
  1092. break;
  1093. }
  1094. }
  1095. break;
  1096. case TS_PDUTYPE_DEMANDACTIVEPDU:
  1097. TRC_DBG((TB, _T("DemandActivePDU")));
  1098. CO_CHECKPACKETCAST(TS_DEMAND_ACTIVE_PDU, currentDataLen, hr);
  1099. _pCd->CD_DecoupleNotification(CD_SND_COMPONENT,
  1100. _pCc,
  1101. CD_NOTIFICATION_FUNC(CCC,CC_OnDemandActivePDU),
  1102. pCurrentPDU,
  1103. currentDataLen);
  1104. break;
  1105. case TS_PDUTYPE_DEACTIVATEALLPDU:
  1106. TRC_DBG((TB, _T("DeactivateAllPDU")));
  1107. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT, _pCc,
  1108. CD_NOTIFICATION_FUNC(CCC,CC_Event),
  1109. (ULONG_PTR)CC_EVT_API_ONDEACTIVATEALL);
  1110. break;
  1111. case TS_PDUTYPE_DEACTIVATESELFPDU:
  1112. case TS_PDUTYPE_DEACTIVATEOTHERPDU:
  1113. case TS_PDUTYPE_CONFIRMACTIVEPDU:
  1114. case TS_PDUTYPE_REQUESTACTIVEPDU:
  1115. TRC_ERR((TB, _T("PDU type %x unexpected!"), pCtrlHdr->pduType));
  1116. break;
  1117. default:
  1118. TRC_ABORT((TB, _T("Unrecognized PDU type: %#x"),
  1119. pCtrlHdr->pduType));
  1120. break;
  1121. }
  1122. }
  1123. else {
  1124. TRC_NRM((TB, _T("FlowPDU")));
  1125. pFlowPDU = (PTS_FLOW_PDU)pData;
  1126. switch (pFlowPDU->pduType) {
  1127. case TS_PDUTYPE_FLOWTESTPDU:
  1128. TRC_NRM((TB, _T("FlowTestPDU ignored")));
  1129. break;
  1130. case TS_PDUTYPE_FLOWRESPONSEPDU:
  1131. TRC_NRM((TB, _T("FlowResponsePDU ignored")));
  1132. break;
  1133. default:
  1134. TRC_ABORT((TB, _T("Unknown FlowPDU %#x"), pFlowPDU->pduType));
  1135. break;
  1136. }
  1137. DC_QUIT;
  1138. }
  1139. // Now look for the next PDU in the packet.
  1140. pCurrentPDU += pCtrlHdr->totalLength;
  1141. dataRemaining -= pCtrlHdr->totalLength;
  1142. if ((DCUINT)(pCurrentPDU - pData) >= dataLen) {
  1143. TRC_NRM((TB, _T("Last PDU in packet")));
  1144. pCurrentPDU = NULL;
  1145. }
  1146. #ifdef DC_DEBUG
  1147. countPDU++;
  1148. #endif
  1149. }
  1150. #ifdef DC_DEBUG
  1151. if (countPDU > 1)
  1152. {
  1153. TRC_NRM((TB, _T("*** PDU count %u"), countPDU));
  1154. }
  1155. #endif
  1156. DC_EXIT_POINT:
  1157. if (FAILED(hr) && IMMEDIATE_DISSCONNECT_ON_HR(hr)) {
  1158. TRC_ABORT((TB, _T("Disconnect for security")));
  1159. CO_DropLinkImmediate(SL_ERR_INVALIDPACKETFORMAT, hr);
  1160. }
  1161. DC_END_FN();
  1162. return hr;
  1163. } /* CO_OnPacketReceived */
  1164. /****************************************************************************/
  1165. // CO_OnFastPathOutputReceived
  1166. //
  1167. // Handles fast-path output from the server by dispatching subpackets
  1168. // to the right handler component.
  1169. /****************************************************************************/
  1170. #define DC_QUIT_ON_FAIL_TRC(hr, trc) if (FAILED(hr)) {TRC_ABORT( trc );DC_QUIT;}
  1171. HRESULT DCAPI CCO::CO_OnFastPathOutputReceived(BYTE FAR *pData,
  1172. unsigned DataLen)
  1173. {
  1174. HRESULT hr = S_OK;
  1175. unsigned RawPDUSize;
  1176. unsigned HdrSize;
  1177. unsigned PDUSize;
  1178. BYTE FAR *pPDU;
  1179. DC_BEGIN_FN("CO_OnFastPathOutputReceived");
  1180. // Fast-path output is a series of PDUs packed on byte boundaries.
  1181. while (DataLen) {
  1182. // First byte is header containing the update type and compression-
  1183. // used flag. If compression-used is true the following byte is the
  1184. // compression flags, otherwise it's not present. Final part of
  1185. // header is 2-byte little-endian size field.
  1186. if (*pData & TS_OUTPUT_FASTPATH_COMPRESSION_USED) {
  1187. HdrSize = 4;
  1188. if (HdrSize > DataLen) {
  1189. TRC_ABORT((TB, _T("Bad comp fast path PDU")));
  1190. hr = E_TSC_CORE_LENGTH;
  1191. DC_QUIT;
  1192. }
  1193. RawPDUSize = *((UINT16 UNALIGNED FAR *)(pData + 2));
  1194. // Be sure there is enough size for the header
  1195. if (HdrSize + RawPDUSize > DataLen) {
  1196. TRC_ABORT((TB, _T("Bad comp fast path PDU; [need %u have %u]"),
  1197. HdrSize + RawPDUSize, DataLen));
  1198. hr = E_TSC_CORE_LENGTH;
  1199. DC_QUIT;
  1200. }
  1201. if (pData[1] & PACKET_COMPRESSED) {
  1202. if (pData[1] & PACKET_FLUSHED)
  1203. initrecvcontext (&_pUi->_UI.Context1,
  1204. (RecvContext2_Generic*)_pUi->_UI.pRecvContext2,
  1205. PACKET_COMPR_TYPE_64K);
  1206. if (!decompress(pData + 4, RawPDUSize,
  1207. pData[1] & PACKET_AT_FRONT, &pPDU, (PDCINT) &PDUSize,
  1208. &_pUi->_UI.Context1,
  1209. (RecvContext2_Generic*)_pUi->_UI.pRecvContext2,
  1210. pData[1] & PACKET_COMPR_TYPE_MASK)) {
  1211. TRC_ABORT((TB, _T("Decompression FAILURE!!!")));
  1212. hr = E_TSC_UI_DECOMPRESSION;
  1213. DC_QUIT;
  1214. }
  1215. }
  1216. else {
  1217. pPDU = pData + 4;
  1218. PDUSize = RawPDUSize;
  1219. }
  1220. }
  1221. else {
  1222. // Compression flags not present.
  1223. HdrSize = 3;
  1224. if (HdrSize > DataLen) {
  1225. TRC_ABORT((TB, _T("Bad uncomp fast path PDU; [need %u have %u]"),
  1226. HdrSize, DataLen));
  1227. hr = E_TSC_CORE_LENGTH;
  1228. DC_QUIT;
  1229. }
  1230. PDUSize = RawPDUSize = *((UINT16 UNALIGNED FAR *)(pData + 1));
  1231. pPDU = pData + 3;
  1232. // Be sure there is enough size for the header
  1233. if (HdrSize + RawPDUSize > DataLen) {
  1234. TRC_ABORT((TB, _T("Bad uncomp fast path PDU; [need %u have %u]"),
  1235. HdrSize + RawPDUSize, DataLen));
  1236. hr = E_TSC_CORE_LENGTH;
  1237. DC_QUIT;
  1238. }
  1239. }
  1240. switch (*pData & TS_OUTPUT_FASTPATH_UPDATETYPE_MASK) {
  1241. case TS_UPDATETYPE_ORDERS:
  1242. // Number of orders is in little-endian format in
  1243. // the first two bytes of the PDU area.
  1244. TRC_NRM((TB, _T("Fast-path Order PDU")));
  1245. hr = _pUh->UH_ProcessOrders(*((UINT16 UNALIGNED FAR *)pPDU),
  1246. pPDU + 2, PDUSize);
  1247. DC_QUIT_ON_FAIL_TRC( hr, (TB,_T("UH_ProcessOrders")));
  1248. break;
  1249. case TS_UPDATETYPE_BITMAP:
  1250. // BitmapPDU format unchanged from normal path.
  1251. CO_CHECKPACKETCAST(TS_UPDATE_BITMAP_PDU_DATA, PDUSize, hr);
  1252. TRC_NRM((TB, _T("Bitmap PDU")));
  1253. hr = _pUh->UH_ProcessBitmapPDU(
  1254. (TS_UPDATE_BITMAP_PDU_DATA UNALIGNED FAR *)pPDU,
  1255. PDUSize);
  1256. DC_QUIT_ON_FAIL_TRC( hr, (TB,_T("UH_ProcessBitmapPDU")));
  1257. break;
  1258. case TS_UPDATETYPE_PALETTE:
  1259. CO_CHECKPACKETCAST(TS_UPDATE_PALETTE_PDU_DATA, PDUSize, hr);
  1260. // PalettePDU format unchanged from normal path.
  1261. TRC_NRM((TB, _T("Palette PDU")));
  1262. hr = _pUh->UH_ProcessPalettePDU(
  1263. (TS_UPDATE_PALETTE_PDU_DATA UNALIGNED FAR *)pPDU,
  1264. PDUSize);
  1265. DC_QUIT_ON_FAIL_TRC( hr, (TB,_T("UH_ProcessPalettePDU")));
  1266. break;
  1267. case TS_UPDATETYPE_SYNCHRONIZE:
  1268. TRC_NRM((TB, _T("Sync PDU")));
  1269. break;
  1270. case TS_UPDATETYPE_MOUSEPTR_SYSTEM_NULL:
  1271. TRC_NRM((TB,_T("Mouse null system pointer PDU")));
  1272. _pCm->CM_NullSystemPointerPDU();
  1273. break;
  1274. case TS_UPDATETYPE_MOUSEPTR_SYSTEM_DEFAULT:
  1275. TRC_NRM((TB,_T("Mouse default system pointer PDU")));
  1276. _pCm->CM_DefaultSystemPointerPDU();
  1277. break;
  1278. case TS_UPDATETYPE_MOUSEPTR_MONO:
  1279. CO_CHECKPACKETCAST(TS_MONOPOINTERATTRIBUTE, PDUSize, hr);
  1280. TRC_NRM((TB,_T("Mouse mono pointer PDU")));
  1281. hr = _pCm->CM_MonoPointerPDU(
  1282. (TS_MONOPOINTERATTRIBUTE UNALIGNED FAR *)pPDU,PDUSize);
  1283. DC_QUIT_ON_FAIL_TRC( hr, (TB,_T("CM_MonoPointerPDU")));
  1284. break;
  1285. case TS_UPDATETYPE_MOUSEPTR_POSITION:
  1286. CO_CHECKPACKETCAST(TS_POINT16, PDUSize, hr);
  1287. TRC_NRM((TB,_T("Mouse position PDU")));
  1288. _pCm->CM_PositionPDU((TS_POINT16 UNALIGNED FAR *)pPDU);
  1289. break;
  1290. case TS_UPDATETYPE_MOUSEPTR_COLOR:
  1291. CO_CHECKPACKETCAST(TS_COLORPOINTERATTRIBUTE, PDUSize, hr);
  1292. TRC_NRM((TB,_T("Mouse color pointer PDU")));
  1293. hr = _pCm->CM_ColorPointerPDU(
  1294. (TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *)pPDU,
  1295. PDUSize);
  1296. DC_QUIT_ON_FAIL_TRC( hr, (TB,_T("CM_ColorPointerPDU")));
  1297. break;
  1298. case TS_UPDATETYPE_MOUSEPTR_CACHED:
  1299. CO_CHECKPACKETCAST(TSUINT16, PDUSize, hr);
  1300. TRC_NRM((TB,_T("Mouse cached pointer PDU")));
  1301. _pCm->CM_CachedPointerPDU(*((TSUINT16 UNALIGNED FAR *)pPDU));
  1302. break;
  1303. case TS_UPDATETYPE_MOUSEPTR_POINTER:
  1304. CO_CHECKPACKETCAST(TS_POINTERATTRIBUTE, PDUSize, hr);
  1305. TRC_NRM((TB,_T("Mouse pointer PDU")));
  1306. hr = _pCm->CM_PointerPDU(
  1307. (TS_POINTERATTRIBUTE UNALIGNED FAR *)pPDU, PDUSize);
  1308. DC_QUIT_ON_FAIL_TRC( hr, (TB,_T("CM_PointerPDU")));
  1309. break;
  1310. default:
  1311. TRC_ERR((TB, _T("Unexpected Update PDU type: %u"),
  1312. *pData & TS_OUTPUT_FASTPATH_UPDATETYPE_MASK));
  1313. break;
  1314. }
  1315. pData += HdrSize + RawPDUSize;
  1316. DataLen -= HdrSize + RawPDUSize;
  1317. }
  1318. /************************************************************************/
  1319. /* If there are a large number of PDUs arriving, messages flood the */
  1320. /* Receive Thread's message queue and it is possible for WM_PAINT */
  1321. /* messages to not get processed within a reasonable amount of time */
  1322. /* (as they have the lowest priority). We therefore ensure that */
  1323. /* any outstanding WM_PAINTs are flushed if they have not been */
  1324. /* processed within UH_WORST_CASE_WM_PAINT_PERIOD. */
  1325. /* */
  1326. /* Note that the normal processing of updates does not involve */
  1327. /* WM_PAINT messages - we draw directly to the Output Window. */
  1328. /* WM_PAINTs are only generated by resizing or obscuring/revealing */
  1329. /* an area of the client window. */
  1330. /************************************************************************/
  1331. _pOp->OP_MaybeForcePaint();
  1332. DC_EXIT_POINT:
  1333. if (FAILED(hr) && IMMEDIATE_DISSCONNECT_ON_HR(hr)) {
  1334. TRC_ABORT((TB, _T("Disconnect for security")));
  1335. CO_DropLinkImmediate(SL_ERR_INVALIDPACKETFORMAT, hr);
  1336. }
  1337. DC_END_FN();
  1338. return hr;
  1339. }
  1340. #define CHECK_ULONGLEN_STRING(p, pEnd, str, ulSize, descr) \
  1341. {\
  1342. CHECK_READ_N_BYTES(p, pEnd, sizeof(ULONG), hr, (TB,_T("can not read ") _T( #descr ) _T("size"))) \
  1343. (ulSize) = *((ULONG UNALIGNED *)(p)); \
  1344. (str) = (PBYTE)(p) + sizeof(ULONG); \
  1345. CHECK_READ_N_BYTES(str , pEnd, ulSize, hr, (TB,_T("can not read ") _T( #descr ))) \
  1346. (p) += (ulSize) + sizeof(ULONG); \
  1347. }
  1348. /****************************************************************************/
  1349. // CO_OnServerRedirectionPacket
  1350. //
  1351. // Called from SL on receipt of a server redir packet for load balancing.
  1352. /****************************************************************************/
  1353. HRESULT DCAPI CCO::CO_OnServerRedirectionPacket(
  1354. RDP_SERVER_REDIRECTION_PACKET UNALIGNED *pPkt,
  1355. DCUINT dataLen)
  1356. {
  1357. HRESULT hr = S_OK;
  1358. WCHAR AlignedAddress[TS_MAX_SERVERADDRESS_LENGTH];
  1359. unsigned length;
  1360. PBYTE pEnd = ((BYTE *)pPkt) + pPkt->Length;
  1361. BOOL fNeedRedirect = TRUE;
  1362. DC_BEGIN_FN("CO_OnServerRedirectionPacket");
  1363. TRC_DBG((TB, _T("RDP_SERVER_REDIRECTION_PACKET")));
  1364. //
  1365. // Notify the CLX test harness of the redirection packet
  1366. //
  1367. _pClx->CLX_RedirectNotify(pPkt, dataLen);
  1368. if (dataLen < pPkt->Length) {
  1369. TRC_ABORT(( TB, _T("packet length incorrect")));
  1370. hr = E_TSC_CORE_LENGTH;
  1371. DC_QUIT;
  1372. }
  1373. if (pPkt->Flags & RDP_SEC_REDIRECTION_PKT) {
  1374. // Copy the address to an aligned buffer.
  1375. length = min(pPkt->Length + sizeof(WCHAR) - sizeof(RDP_SERVER_REDIRECTION_PACKET),
  1376. sizeof(AlignedAddress));
  1377. if (length > 0 && length <= sizeof(AlignedAddress)) {
  1378. memcpy(AlignedAddress, pPkt->ServerAddress, length);
  1379. // Set the redir info in UI and disconnect.
  1380. _pUi->UI_SetServerRedirectionInfo(pPkt->SessionID, AlignedAddress,
  1381. NULL, 0, fNeedRedirect);
  1382. }
  1383. }
  1384. else if (pPkt->Flags & RDP_SEC_REDIRECTION_PKT2) {
  1385. RDP_SERVER_REDIRECTION_PACKET_V2 UNALIGNED *pPkt2 =
  1386. (RDP_SERVER_REDIRECTION_PACKET_V2 UNALIGNED*)pPkt;
  1387. PBYTE LBInfo = NULL;
  1388. PBYTE ServerName = NULL;
  1389. PBYTE pBuf = NULL;
  1390. unsigned LBInfoSize = 0;
  1391. unsigned ServerNameSize = 0;
  1392. pBuf = (PBYTE)(pPkt2 + 1);
  1393. if (pPkt2->RedirFlags & TARGET_NET_ADDRESS) {
  1394. CHECK_ULONGLEN_STRING(pBuf, pEnd, ServerName,
  1395. ServerNameSize, TARGET_NET_ADDRESS);
  1396. }
  1397. if (pPkt2->RedirFlags & LOAD_BALANCE_INFO) {
  1398. CHECK_ULONGLEN_STRING(pBuf, pEnd, LBInfo,
  1399. LBInfoSize, LOAD_BALANCE_INFO);
  1400. }
  1401. if (ServerNameSize > 0 && ServerNameSize <= sizeof(AlignedAddress)) {
  1402. memcpy(AlignedAddress, ServerName, ServerNameSize);
  1403. // Set the redir info in UI and disconnect.
  1404. _pUi->UI_SetServerRedirectionInfo(pPkt2->SessionID, AlignedAddress,
  1405. NULL, 0, fNeedRedirect);
  1406. }
  1407. else {
  1408. // Set the redir info in UI and disconnect. That LBInfo is going to
  1409. // be there indicates to XT_SendCR that we are in the middle of
  1410. // a redirect and should use the redirect info instead of scripting
  1411. // or hash-mode cookie.
  1412. _pUi->UI_SetServerRedirectionInfo(pPkt2->SessionID,
  1413. _pUi->_UI.strAddress, LBInfo, LBInfoSize, fNeedRedirect);
  1414. }
  1415. }
  1416. else if (pPkt->Flags & RDP_SEC_REDIRECTION_PKT3) {
  1417. RDP_SERVER_REDIRECTION_PACKET_V3 UNALIGNED *pPkt3 =
  1418. (RDP_SERVER_REDIRECTION_PACKET_V3 UNALIGNED*)pPkt;
  1419. PBYTE LBInfo = NULL;
  1420. PBYTE ServerName = NULL;
  1421. PBYTE pBuf = NULL;
  1422. PBYTE pUserName = NULL;
  1423. PBYTE pDomain = NULL;
  1424. PBYTE pClearPassword = NULL;
  1425. unsigned LBInfoSize = 0;
  1426. unsigned ServerNameSize = 0;
  1427. unsigned UserNameSize = 0;
  1428. unsigned DomainSize = 0;
  1429. unsigned PasswordSize = 0;
  1430. pBuf = (PBYTE)(pPkt3 + 1);
  1431. if (pPkt3->RedirFlags & TARGET_NET_ADDRESS) {
  1432. CHECK_ULONGLEN_STRING(pBuf, pEnd, ServerName,
  1433. ServerNameSize, TARGET_NET_ADDRESS);
  1434. }
  1435. if (pPkt3->RedirFlags & LOAD_BALANCE_INFO) {
  1436. CHECK_ULONGLEN_STRING(pBuf, pEnd, LBInfo,
  1437. LBInfoSize, LOAD_BALANCE_INFO);
  1438. }
  1439. if (pPkt3->RedirFlags & LB_USERNAME) {
  1440. CHECK_ULONGLEN_STRING(pBuf, pEnd, pUserName,
  1441. UserNameSize, LB_USERNAME);
  1442. }
  1443. if (pPkt3->RedirFlags & LB_DOMAIN) {
  1444. CHECK_ULONGLEN_STRING(pBuf, pEnd, pDomain,
  1445. DomainSize, LB_DOMAIN);
  1446. }
  1447. if (pPkt3->RedirFlags & LB_PASSWORD) {
  1448. CHECK_ULONGLEN_STRING(pBuf, pEnd, pClearPassword,
  1449. PasswordSize, LB_PASSWORD);
  1450. }
  1451. if (pPkt3->RedirFlags & LB_SMARTCARD_LOGON) {
  1452. _pUi->UI_SetUseSmartcardLogon(TRUE);
  1453. }
  1454. if ((pPkt3->RedirFlags & LB_NOREDIRECT) != 0) {
  1455. fNeedRedirect = FALSE;
  1456. }
  1457. if (UserNameSize > 0) {
  1458. PBYTE pAlignedUserName = (PBYTE)LocalAlloc(LPTR,
  1459. UserNameSize+sizeof(TCHAR));
  1460. if (pAlignedUserName) {
  1461. memset(pAlignedUserName, 0, UserNameSize+sizeof(TCHAR));
  1462. memcpy(pAlignedUserName, pUserName, UserNameSize);
  1463. if (pPkt3->RedirFlags & LB_DONTSTOREUSERNAME) {
  1464. _pUi->UI_SetRedirectionUserName((LPTSTR)pAlignedUserName);
  1465. } else {
  1466. _pUi->UI_SetUserName((LPTSTR)pAlignedUserName);
  1467. }
  1468. LocalFree(pAlignedUserName);
  1469. }
  1470. }
  1471. if (DomainSize > 0) {
  1472. PBYTE pAlignedDomain = (PBYTE)LocalAlloc(LPTR,
  1473. DomainSize+sizeof(TCHAR));
  1474. if (pAlignedDomain) {
  1475. memset(pAlignedDomain, 0, DomainSize+sizeof(TCHAR));
  1476. memcpy(pAlignedDomain, pDomain, DomainSize);
  1477. _pUi->UI_SetDomain((LPTSTR)pAlignedDomain);
  1478. LocalFree(pAlignedDomain);
  1479. }
  1480. }
  1481. if ((PasswordSize > 0) &&
  1482. ((PasswordSize + sizeof(TCHAR)) <= UI_MAX_PASSWORD_LENGTH)) {
  1483. PBYTE pAlignedClearPass = (PBYTE)LocalAlloc(LPTR,
  1484. UI_MAX_PASSWORD_LENGTH);
  1485. if (pAlignedClearPass) {
  1486. SecureZeroMemory(pAlignedClearPass, UI_MAX_PASSWORD_LENGTH);
  1487. memcpy(pAlignedClearPass, pClearPassword, PasswordSize);
  1488. BYTE Salt[UT_SALT_LENGTH];
  1489. //
  1490. // The password has to be stored in our internal 'obfuscated'
  1491. // format.
  1492. //
  1493. if(TSRNG_GenerateRandomBits(Salt, sizeof(Salt))) {
  1494. //Encrypt the password
  1495. if(EncryptDecryptLocalData50(pAlignedClearPass,
  1496. PasswordSize,
  1497. Salt, sizeof(Salt))) {
  1498. _pUi->UI_SetPassword( pAlignedClearPass );
  1499. _pUi->UI_SetSalt( Salt);
  1500. }
  1501. else {
  1502. TRC_ERR((TB,_T("Error encrytping password")));
  1503. }
  1504. }
  1505. else {
  1506. TRC_ERR((TB,_T("Error generating salt")));
  1507. }
  1508. //
  1509. // For security reasons clear the password field
  1510. //
  1511. SecureZeroMemory(pAlignedClearPass, PasswordSize+sizeof(TCHAR));
  1512. SecureZeroMemory(pClearPassword, PasswordSize);
  1513. LocalFree(pAlignedClearPass);
  1514. //
  1515. // Set the autologon flag
  1516. //
  1517. if (UserNameSize)
  1518. {
  1519. _pUi->_UI.fAutoLogon = TRUE;
  1520. }
  1521. }
  1522. }
  1523. if (ServerNameSize > 0 && ServerNameSize <= sizeof(AlignedAddress)) {
  1524. memcpy(AlignedAddress, ServerName, ServerNameSize);
  1525. // Set the redir info in UI and disconnect.
  1526. _pUi->UI_SetServerRedirectionInfo(pPkt3->SessionID, AlignedAddress,
  1527. NULL, 0, fNeedRedirect);
  1528. }
  1529. else {
  1530. // Set the redir info in UI and disconnect. That LBInfo is going to
  1531. // be there indicates to XT_SendCR that we are in the middle of
  1532. // a redirect and should use the redirect info instead of scripting
  1533. // or hash-mode cookie.
  1534. _pUi->UI_SetServerRedirectionInfo(pPkt3->SessionID,
  1535. _pUi->_UI.strAddress, LBInfo, LBInfoSize, fNeedRedirect);
  1536. }
  1537. }
  1538. else {
  1539. TRC_ERR((TB,_T("Unexpected redirection packet")));
  1540. }
  1541. if (fNeedRedirect) {
  1542. CO_Disconnect();
  1543. }
  1544. DC_EXIT_POINT:
  1545. if (FAILED(hr) && IMMEDIATE_DISSCONNECT_ON_HR(hr)) {
  1546. TRC_ABORT((TB, _T("Disconnect for security")));
  1547. CO_DropLinkImmediate(SL_ERR_INVALIDPACKETFORMAT, hr);
  1548. }
  1549. DC_END_FN();
  1550. return hr;
  1551. }
  1552. /****************************************************************************/
  1553. /* Name: CO_OnBufferAvailable */
  1554. /* */
  1555. /* Purpose: Handle BufferAvailable notification from SL. */
  1556. /****************************************************************************/
  1557. void DCCALLBACK CCO::CO_OnBufferAvailable()
  1558. {
  1559. DC_BEGIN_FN("CO_OnBufferAvailable");
  1560. // Tell the Sender Thread.
  1561. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  1562. _pSnd,
  1563. CD_NOTIFICATION_FUNC(CSND,SND_BufferAvailable),
  1564. (ULONG_PTR) 0);
  1565. DC_END_FN();
  1566. } /* CO_OnBufferAvailable */
  1567. //
  1568. // CO_DropLinkImmediate
  1569. //
  1570. // Purpose: Immediately drops the link without doing a gracefull connection
  1571. // shutdown (i.e. no DPUm is sent and we don't transition to the SND
  1572. // thread at any point before dropping the link). Higher level components
  1573. // will still get all the usual disconnect notifications so they can
  1574. // be properly torn down.
  1575. //
  1576. // This call was added to trigger an immediate disconnect in cases
  1577. // where we detect invalid data that could be due to an attack, it
  1578. // ensures we won't receive any more data after the call returns
  1579. //
  1580. // Params: reason - SL disconnect reason code
  1581. // hrDisconnect - hresult as to why the TSC_CORE wanted to disconnect
  1582. //
  1583. // Returns: HRESULT
  1584. //
  1585. // Thread context: Call on RCV thread
  1586. //
  1587. HRESULT DCINTERNAL CCO::CO_DropLinkImmediate(UINT reason, HRESULT hrDisconnect )
  1588. {
  1589. DC_BEGIN_FN("CO_DropLinkImmediate");
  1590. HRESULT hr = E_FAIL;
  1591. TRC_ASSERT((NULL != _pSl),
  1592. (TB, _T("SL not connected can not drop immediate")));
  1593. if (_pSl) {
  1594. hr = _pSl->SL_DropLinkImmediate(reason);
  1595. }
  1596. COSetDisconnectHR(hrDisconnect);
  1597. DC_END_FN();
  1598. return hr;
  1599. }