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.

1096 lines
45 KiB

  1. /****************************************************************************/
  2. // adcsapi.cpp
  3. //
  4. // RDP top-level component API functions.
  5. //
  6. // Copyright (C) Microsoft Corp., PictureTel 1992-1997
  7. // Copyright (C) 1997-2000 Microsoft Corporation
  8. /****************************************************************************/
  9. #include <precomp.h>
  10. #pragma hdrstop
  11. #define TRC_FILE "adcsapi"
  12. #include <randlib.h>
  13. #include <as_conf.hpp>
  14. #include <asmapi.h>
  15. /****************************************************************************/
  16. /* API FUNCTION: DCS_Init */
  17. /* */
  18. /* Initializes DCS. */
  19. /* */
  20. /* PARAMETERS: */
  21. /* pTSWd - TShare WD handle */
  22. /* pSMHandle - SM handle */
  23. /* */
  24. /* RETURNS: */
  25. /* TRUE if DCS successfully initialized, FALSE otherwise. */
  26. /****************************************************************************/
  27. BOOL RDPCALL SHCLASS DCS_Init(PTSHARE_WD pTSWd, PVOID pSMHandle)
  28. {
  29. BOOL rc = FALSE;
  30. unsigned retCode;
  31. TS_GENERAL_CAPABILITYSET GeneralCaps;
  32. long arcUpdateIntervalSeconds;
  33. UINT32 drawGdipSupportLevel;
  34. NTSTATUS Status;
  35. DC_BEGIN_FN("DCS_Init");
  36. TRC_ALT((TB, "Initializing Core!"));
  37. #define DC_INIT_DATA
  38. #include <adcsdata.c>
  39. #undef DC_INIT_DATA
  40. dcsInitialized = TRUE;
  41. // Read the registry key for the draw gdiplus support control
  42. COM_OpenRegistry(pTSWd, WINSTATION_INI_SECTION_NAME);
  43. Status = COMReadEntry(pTSWd, L"DrawGdiplusSupportLevel", (PVOID)&drawGdipSupportLevel, sizeof(INT32),
  44. REG_DWORD);
  45. if (Status != STATUS_SUCCESS) {
  46. /********************************************************************/
  47. /* We failed to read the value - copy in the default */
  48. /********************************************************************/
  49. TRC_ERR((TB, "Failed to read int32. Using default."));
  50. drawGdipSupportLevel = TS_DRAW_GDIPLUS_DEFAULT;
  51. }
  52. else {
  53. TRC_NRM((TB, "Read from registry, gdipSupportLevel is %d", drawGdipSupportLevel));
  54. }
  55. COM_CloseRegistry(pTSWd);
  56. /************************************************************************/
  57. /* Open registry here. Apart from SM_Init, all registry reads should */
  58. /* be done from this function or its children. We close the key at the */
  59. /* end of this function. */
  60. /************************************************************************/
  61. COM_OpenRegistry(pTSWd, DCS_INI_SECTION_NAME);
  62. /************************************************************************/
  63. /* Initialize individual modules. */
  64. /************************************************************************/
  65. TRC_DBG((TB, "Initializing components..."));
  66. // we can't do any registry reading on this csrss thread,
  67. // it'll cause deadlock in the system
  68. arcUpdateIntervalSeconds = DCS_ARC_UPDATE_INTERVAL_DFLT;
  69. //
  70. // Units specified are in seconds, convert to 100ns count
  71. //
  72. dcsMinArcUpdateInterval.QuadPart =
  73. (LONGLONG)DCS_TIME_ONE_SECOND * (ULONGLONG)arcUpdateIntervalSeconds;
  74. TRC_NRM((TB,"Set ARC update interval to %d seconds",
  75. arcUpdateIntervalSeconds));
  76. /************************************************************************/
  77. // Share Controller - must go first
  78. /************************************************************************/
  79. if (SC_Init(pSMHandle)) {
  80. // Capabilities Coordinator. Must be before all components which
  81. // register capabilities structures.
  82. CPC_Init();
  83. // Register the SC's capabilities. This is required because SC is
  84. // initialized before CPC, so cannot register its capabilities in
  85. // SC_Init().
  86. SC_SetCapabilities();
  87. }
  88. else {
  89. TRC_ERR((TB, "SC Initialization failed"));
  90. DC_QUIT;
  91. }
  92. /************************************************************************/
  93. /* Register the general capabilities structure. */
  94. /************************************************************************/
  95. GeneralCaps.capabilitySetType = TS_CAPSETTYPE_GENERAL;
  96. GeneralCaps.osMajorType = TS_OSMAJORTYPE_WINDOWS;
  97. GeneralCaps.osMinorType = TS_OSMINORTYPE_WINDOWS_NT;
  98. GeneralCaps.protocolVersion = TS_CAPS_PROTOCOLVERSION;
  99. /************************************************************************/
  100. /* Mark the old DOS 6 compression field as unsupported. */
  101. /************************************************************************/
  102. GeneralCaps.pad2octetsA = 0;
  103. GeneralCaps.generalCompressionTypes = 0;
  104. // Server supports no BC header and fast-path output, returning long credentials
  105. // and sending the autoreconnect cookie
  106. // Also supports receiving safer encrypted data from the client (better salted
  107. // checksum)
  108. //
  109. GeneralCaps.extraFlags = TS_EXTRA_NO_BITMAP_COMPRESSION_HDR |
  110. TS_FASTPATH_OUTPUT_SUPPORTED | TS_LONG_CREDENTIALS_SUPPORTED |
  111. TS_AUTORECONNECT_COOKIE_SUPPORTED |
  112. TS_ENC_SECURE_CHECKSUM;
  113. /************************************************************************/
  114. /* We don't support remote machines changing their capabilities during */
  115. /* a call */
  116. /************************************************************************/
  117. GeneralCaps.updateCapabilityFlag = TS_CAPSFLAG_UNSUPPORTED;
  118. /************************************************************************/
  119. /* We don't support unshare requests from remote parties */
  120. /************************************************************************/
  121. GeneralCaps.remoteUnshareFlag = TS_CAPSFLAG_UNSUPPORTED;
  122. /************************************************************************/
  123. /* Now do the extension caps - these don't fit in the level 1 caps. */
  124. /************************************************************************/
  125. GeneralCaps.generalCompressionLevel = 0;
  126. /************************************************************************/
  127. /* We can receive a TS_REFRESH_RECT_PDU */
  128. /************************************************************************/
  129. GeneralCaps.refreshRectSupport = TS_CAPSFLAG_SUPPORTED;
  130. /************************************************************************/
  131. /* We can receive a TS_SUPPRESS_OUTPUT_PDU */
  132. /************************************************************************/
  133. GeneralCaps.suppressOutputSupport = TS_CAPSFLAG_SUPPORTED;
  134. CPC_RegisterCapabilities((PTS_CAPABILITYHEADER)&GeneralCaps,
  135. sizeof(TS_GENERAL_CAPABILITYSET));
  136. //
  137. // Register virtual channel capabilities
  138. //
  139. TS_VIRTUALCHANNEL_CAPABILITYSET VcCaps;
  140. VcCaps.capabilitySetType = TS_CAPSETTYPE_VIRTUALCHANNEL;
  141. VcCaps.lengthCapability = sizeof(TS_VIRTUALCHANNEL_CAPABILITYSET);
  142. //Indicate support for 8K VC compression (from client->server)
  143. //I.e server understands compressed channels
  144. VcCaps.vccaps1 = TS_VCCAPS_COMPRESSION_8K;
  145. CPC_RegisterCapabilities((PTS_CAPABILITYHEADER)&VcCaps,
  146. sizeof(TS_VIRTUALCHANNEL_CAPABILITYSET));
  147. TS_DRAW_GDIPLUS_CAPABILITYSET DrawGdipCaps;
  148. DrawGdipCaps.capabilitySetType = TS_CAPSETTYPE_DRAWGDIPLUS;
  149. DrawGdipCaps.lengthCapability = sizeof(TS_DRAW_GDIPLUS_CAPABILITYSET);
  150. DrawGdipCaps.drawGdiplusSupportLevel = drawGdipSupportLevel;
  151. DrawGdipCaps.drawGdiplusCacheLevel = TS_DRAW_GDIPLUS_CACHE_LEVEL_ONE;
  152. CPC_RegisterCapabilities((PTS_CAPABILITYHEADER)&DrawGdipCaps,
  153. sizeof(TS_DRAW_GDIPLUS_CAPABILITYSET));
  154. USR_Init();
  155. CA_Init();
  156. PM_Init();
  157. SBC_Init();
  158. BC_Init();
  159. CM_Init();
  160. IM_Init();
  161. SSI_Init();
  162. SCH_Init();
  163. TRC_NRM((TB, "** All successfully initialized **"));
  164. rc = TRUE;
  165. DC_EXIT_POINT:
  166. /************************************************************************/
  167. /* Close the registry key that we opened earlier. */
  168. /************************************************************************/
  169. COM_CloseRegistry(pTSWd);
  170. DC_END_FN();
  171. return rc;
  172. }
  173. /****************************************************************************/
  174. /* API FUNCTION: DCS_Term */
  175. /* */
  176. /* Terminates DCS. */
  177. /****************************************************************************/
  178. void RDPCALL SHCLASS DCS_Term()
  179. {
  180. DC_BEGIN_FN("DCS_Term");
  181. if (!dcsInitialized) {
  182. TRC_ERR((TB,"DCS_Term() called when we have not been initialized"));
  183. }
  184. SBC_Term();
  185. PM_Term();
  186. CA_Term();
  187. BC_Term();
  188. CM_Term();
  189. IM_Term();
  190. SSI_Term();
  191. SCH_Term();
  192. CPC_Term();
  193. USR_Term();
  194. SC_Term();
  195. dcsInitialized = FALSE;
  196. TRC_NRM((TB, "BYE!"));
  197. DC_END_FN();
  198. }
  199. /****************************************************************************/
  200. /* API FUNCTION: DCS_TimeToDoStuff */
  201. /* */
  202. /* This function is called to send updates etc in the correct order. */
  203. /* */
  204. /* PARAMETERS: IN - pOutputIn - input from TShareDD */
  205. /* OUT - pSchCurrentMode - current Scheduler mode */
  206. /* */
  207. /* RETURNS: Millisecs to set the timer for (-1 means infinite). */
  208. /****************************************************************************/
  209. /* Scheduling is the responsibility of the WDW, DD and SCH components. */
  210. /* These ensure that DCS_TimeToDoStuff() gets called. The Scheduler is in */
  211. /* one of three states: asleep, normal or turbo. When it is asleep, this */
  212. /* function is not called. When it is in normal mode, this function is */
  213. /* called at least once, but the scheduler is a lazy guy, so will fall */
  214. /* asleep again unless you keep prodding him. In turbo mode this function */
  215. /* is called repeatedly and rapidly, but only for a relatively short time, */
  216. /* after which the scheduler falls back into normal mode, and from there */
  217. /* falls asleep. */
  218. /* */
  219. /* Hence when a component realises it has some processing to do later, */
  220. /* which is called from DCS_TimeToDoStuff(), it calls */
  221. /* SCH_ContinueScheduling(SCH_MODE_NORMAL) which guarantees that this */
  222. /* function will be called at least one more time. If the component wants */
  223. /* DCS_TimeToDoStuff() to be called again, it must make another call to */
  224. /* SCH_ContinueScheduling(), which prods the Scheduler again. */
  225. /* */
  226. /* The objective is to only keep the scheduler awake when it is really */
  227. /* necessary. */
  228. /****************************************************************************/
  229. NTSTATUS RDPCALL SHCLASS DCS_TimeToDoStuff(PTSHARE_DD_OUTPUT_IN pOutputIn,
  230. PUINT32 pSchCurrentMode,
  231. PINT32 pNextTimer)
  232. {
  233. INT32 timeToSet;
  234. ULARGE_INTEGER sysTime;
  235. UINT32 sysTimeLowPart;
  236. NTSTATUS status = STATUS_SUCCESS;
  237. DC_BEGIN_FN("DCS_TimeToDoStuff");
  238. #ifdef DC_DEBUG
  239. /************************************************************************/
  240. /* Update trace config in shared memory. */
  241. /************************************************************************/
  242. TRC_MaybeCopyConfig(m_pTSWd, &(m_pShm->trc));
  243. #endif
  244. // Determine if we should do anything based on:
  245. // 1. SCH determining that this is the time to do something.
  246. // 2. We are in a share.
  247. if (SCH_ShouldWeDoStuff(pOutputIn->forceSend) && SC_InShare()) {
  248. PDU_PACKAGE_INFO pkgInfo = {0};
  249. // We check for the need to send a cursor-moved packet, by comparing
  250. // the current mouse position to the last known position at the last
  251. // mouse packet, only a few times a second, to reduce the traffic for
  252. // shadow clients.
  253. KeQuerySystemTime((PLARGE_INTEGER)&sysTime);
  254. sysTimeLowPart = sysTime.LowPart;
  255. if ((sysTimeLowPart - dcsLastMiscTime) > DCS_MISC_PERIOD) {
  256. dcsLastMiscTime = sysTimeLowPart;
  257. IM_CheckUpdateCursor(&pkgInfo, sysTimeLowPart);
  258. }
  259. //
  260. // Check if the ARC cookie needs to be updated
  261. //
  262. if (scEnablePeriodicArcUpdate &&
  263. scUseAutoReconnect &&
  264. ((sysTime.QuadPart - dcsLastArcUpdateTime.QuadPart) > dcsMinArcUpdateInterval.QuadPart)) {
  265. dcsLastArcUpdateTime = sysTime;
  266. DCS_UpdateAutoReconnectCookie();
  267. }
  268. // Try to send updates now.
  269. TRC_DBG((TB, "Send updates"));
  270. //
  271. // *** Keep the code path but still return status code ***
  272. //
  273. status = UP_SendUpdates(pOutputIn->pFrameBuf, pOutputIn->frameBufWidth,
  274. &pkgInfo);
  275. // Call the cursor manager to decide if a new cursor needs to be
  276. // sent to the remote system.
  277. CM_Periodic(&pkgInfo);
  278. // Flush any remaining data in the package.
  279. SC_FlushPackage(&pkgInfo);
  280. }
  281. /************************************************************************/
  282. /* Check whether we have any pending callbacks. */
  283. /************************************************************************/
  284. if (dcsCallbackTimerPending)
  285. DCS_UpdateShm();
  286. /************************************************************************/
  287. /* Find out the timer period to set */
  288. /************************************************************************/
  289. *pNextTimer = SCH_EndOfDoingStuff(pSchCurrentMode);
  290. DC_END_FN();
  291. return status;
  292. }
  293. /****************************************************************************/
  294. /* DCS_DiscardAllOutput */
  295. /* */
  296. /* This routine will discard accumulated orders, screen data, and any */
  297. /* pending shadow data. It is currently only called when the WD is dead */
  298. /* to prevent the DD from looping during shadow termination, or when a */
  299. /* disconnect or terminate is occuring. */
  300. /****************************************************************************/
  301. void RDPCALL SHCLASS DCS_DiscardAllOutput()
  302. {
  303. RECTL sdaRect[BA_MAX_ACCUMULATED_RECTS];
  304. unsigned cRects;
  305. // Blow the order heap, screen data, and clear any shadow data.
  306. OA_ResetOrderList();
  307. BA_GetBounds(sdaRect, &cRects);
  308. if (m_pTSWd->pShadowInfo != NULL)
  309. {
  310. m_pTSWd->pShadowInfo->messageSize = 0;
  311. #ifdef DC_HICOLOR
  312. m_pTSWd->pShadowInfo->messageSizeEx = 0;
  313. #endif
  314. }
  315. }
  316. /****************************************************************************/
  317. /* Name: DCS_ReceivedShurdownRequestPDU */
  318. /* */
  319. /* Purpose: Handles ShutdownRequestPDU. */
  320. /* */
  321. /* Params: personID: originator of the PDU */
  322. /* pPDU: the PDU */
  323. /* */
  324. /* Operation: See embedded comments for each PDU type */
  325. /* */
  326. /* Note that since a ShutdownRequestPDU is not really directed at a */
  327. /* particular component, DCS_ReceivedPacket is intended as a generic */
  328. /* received packet handler, and it therefore takes a generic 2nd parameter */
  329. /****************************************************************************/
  330. void RDPCALL SHCLASS DCS_ReceivedShutdownRequestPDU(
  331. PTS_SHAREDATAHEADER pDataPDU,
  332. unsigned DataLength,
  333. NETPERSONID personID)
  334. {
  335. UINT32 packetSize;
  336. PTS_SHUTDOWN_DENIED_PDU pResponsePDU;
  337. DC_BEGIN_FN("DCS_ReceivedPacket");
  338. if (dcsUserLoggedOn) {
  339. TRC_NRM((TB, "User logged on - deny shutdown request"));
  340. packetSize = sizeof(TS_SHUTDOWN_DENIED_PDU);
  341. if (STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pResponsePDU, packetSize)) {
  342. pResponsePDU->shareDataHeader.pduType2 =
  343. TS_PDUTYPE2_SHUTDOWN_DENIED;
  344. // The way in which this packet is handled in a multi-party
  345. // call is not yet clear. We could send a directed or
  346. // broadcast reponse to the client(s). I've chosen
  347. // broadcast.
  348. SC_SendData((PTS_SHAREDATAHEADER)pResponsePDU, packetSize,
  349. packetSize, PROT_PRIO_MISC, 0);
  350. }
  351. else {
  352. TRC_ALT((TB,"Failed to allocate packet for "
  353. "TS_SHUTDOWN_DENIED_PDU"));
  354. }
  355. }
  356. else {
  357. TRC_NRM((TB, "User not logged on - disconnect"));
  358. WDW_Disconnect(m_pTSWd);
  359. }
  360. DC_END_FN();
  361. } /* DCS_ReceivedPacket */
  362. /****************************************************************************
  363. DCS_UpdateAutoReconnectCookie
  364. Updates the autoreconnection cookie and sends it to the client
  365. *****************************************************************************/
  366. BOOL RDPCALL SHCLASS DCS_UpdateAutoReconnectCookie()
  367. {
  368. BOOL fRet = FALSE;
  369. ARC_SC_PRIVATE_PACKET arcSCPkt;
  370. DC_BEGIN_FN("DCS_UpdateAutoReconnectCookie");
  371. arcSCPkt.cbLen = sizeof(ARC_SC_PRIVATE_PACKET);
  372. arcSCPkt.LogonId = m_pTSWd->arcReconnectSessionID;
  373. arcSCPkt.Version = 1;
  374. if (NewGenRandom(NULL,
  375. NULL,
  376. arcSCPkt.ArcRandomBits,
  377. sizeof(arcSCPkt.ArcRandomBits))) {
  378. #ifdef ARC_INSTRUMENT_RDPWD
  379. LPDWORD pdwArcRandom = (LPDWORD)arcSCPkt.ArcRandomBits;
  380. KdPrint(("ARC-RDPWD:Sending arc for SID:%d - random: 0x%x,0x%x,0x%x,0x%x\n",
  381. arcSCPkt.LogonId,
  382. pdwArcRandom[0],pdwArcRandom[1],pdwArcRandom[2],pdwArcRandom[3]));
  383. #endif
  384. //
  385. // Try to send the updated packet and if it succeeds
  386. //
  387. if (DCS_SendAutoReconnectCookie(&arcSCPkt)) {
  388. //
  389. // Update the locally stored ARC cookie even though
  390. // all we know is that we attempted to send it
  391. // i.e. if the client link drops before it recvs the
  392. // cookie then it won't be able to ARC.
  393. //
  394. memcpy(m_pTSWd->arcCookie, arcSCPkt.ArcRandomBits,
  395. ARC_SC_SECURITY_TOKEN_LEN);
  396. m_pTSWd->arcTokenValid = TRUE;
  397. #ifdef ARC_INSTRUMENT_RDPWD
  398. KdPrint(("ARC-RDPWD:ACTUALLY SENT ARC for SID:%d\n", arcSCPkt.LogonId));
  399. #endif
  400. fRet = TRUE;
  401. }
  402. else {
  403. #ifdef ARC_INSTRUMENT_RDPWD
  404. KdPrint(("ARC-RDPWD:Failed to send new ARC for SID:%d\n", arcSCPkt.LogonId));
  405. #endif
  406. }
  407. }
  408. DC_END_FN();
  409. return fRet;
  410. }
  411. BOOL RDPCALL SHCLASS DCS_FlushAutoReconnectCookie()
  412. {
  413. memset(m_pTSWd->arcCookie, 0, ARC_SC_SECURITY_TOKEN_LEN);
  414. m_pTSWd->arcTokenValid = FALSE;
  415. return TRUE;
  416. }
  417. /****************************************************************************
  418. DCS_SendAutoReconnectCookie
  419. Sends a autoreconnect cookie tot the client
  420. *****************************************************************************/
  421. BOOL RDPCALL SHCLASS DCS_SendAutoReconnectCookie(
  422. PARC_SC_PRIVATE_PACKET pArcSCPkt)
  423. {
  424. BOOL fRet = FALSE;
  425. PTS_SAVE_SESSION_INFO_PDU pInfoPDU = NULL;
  426. PTS_LOGON_INFO_EXTENDED pLogonInfoExPkt = NULL;
  427. UINT32 cbLogonInfoExLen = sizeof(TS_SAVE_SESSION_INFO_PDU) +
  428. sizeof(ARC_SC_PRIVATE_PACKET) +
  429. sizeof(TSUINT32);
  430. TSUINT32 cbAutoReconnectInfoLen = sizeof(ARC_SC_PRIVATE_PACKET);
  431. TSUINT32 cbWrittenLen = 0;
  432. DC_BEGIN_FN("DCS_SendAutoReconnectCookie");
  433. //
  434. //Send down the autoreconnect cookie
  435. //
  436. if (scUseAutoReconnect) {
  437. if ( STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pInfoPDU,
  438. cbLogonInfoExLen)) {
  439. // Zero out the structure and set basic header info.
  440. memset(pInfoPDU, 0, cbLogonInfoExLen);
  441. pInfoPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SAVE_SESSION_INFO;
  442. pInfoPDU->data.InfoType = TS_INFOTYPE_LOGON_EXTENDED_INFO;
  443. // Now fill up the rest of the packet
  444. pLogonInfoExPkt = &pInfoPDU->data.Info.LogonInfoEx;
  445. pLogonInfoExPkt->Length = sizeof(TS_LOGON_INFO_EXTENDED) +
  446. sizeof(ARC_SC_PRIVATE_PACKET) +
  447. sizeof(TSUINT32);
  448. //
  449. // For now the only info we pass down is
  450. // the autoreconnect cookie
  451. //
  452. pLogonInfoExPkt->Flags = LOGON_EX_AUTORECONNECTCOOKIE;
  453. //Copy in the fields
  454. //Autoreconnect field length
  455. PBYTE pBuf = (PBYTE)(pLogonInfoExPkt+1);
  456. memcpy(pBuf, &cbAutoReconnectInfoLen, sizeof(TSUINT32));
  457. pBuf += sizeof(TSUINT32);
  458. cbWrittenLen += sizeof(TSUINT32);
  459. //Autoreconnect cookie
  460. memcpy(pBuf, pArcSCPkt, cbAutoReconnectInfoLen);
  461. pBuf += cbAutoReconnectInfoLen;
  462. cbWrittenLen += cbAutoReconnectInfoLen;
  463. TRC_ASSERT(cbWrittenLen + sizeof(TS_LOGON_INFO_EXTENDED) <=
  464. pLogonInfoExPkt->Length,
  465. (TB,"Wrote to much data to packet"));
  466. fRet = SC_SendData((PTS_SHAREDATAHEADER)pInfoPDU,
  467. cbLogonInfoExLen,
  468. cbLogonInfoExLen,
  469. PROT_PRIO_UPDATES, 0);
  470. } else {
  471. TRC_ALT((TB, "Failed to alloc pkt for "
  472. "PTS_SAVE_SESSION_INFO_PDU"));
  473. }
  474. }
  475. DC_END_FN();
  476. return fRet;
  477. }
  478. /****************************************************************************/
  479. /* Name: DCS_UserLoggedOn */
  480. /* */
  481. /* Purpose: Notify that a user has logged on */
  482. /****************************************************************************/
  483. void RDPCALL SHCLASS DCS_UserLoggedOn(PLOGONINFO pLogonInfo)
  484. {
  485. PTS_SAVE_SESSION_INFO_PDU pInfoPDU;
  486. DC_BEGIN_FN("DCS_UserLoggedOn");
  487. // This can get called before we're initialised in the console remoting
  488. // case. Since in that case the class data hasn't been initialized, we
  489. // can't use dcsInitialized to check whether we're inited or not. We
  490. //must use the non-class variable TSWd->shareClassInit.
  491. if (m_pTSWd->shareClassInit) {
  492. // Note that a user has successfully logged on
  493. dcsUserLoggedOn = TRUE;
  494. m_pTSWd->sessionId = pLogonInfo->SessionId;
  495. // If a different domain/username has been selected for a non-
  496. // autologon session, then send the new values back to the client to
  497. // be cached for future use
  498. if (!(m_pTSWd->pInfoPkt->flags & RNS_INFO_AUTOLOGON) &&
  499. (m_pTSWd->pInfoPkt->flags & RNS_INFO_LOGONNOTIFY ||
  500. (wcscmp((const PWCHAR)(pLogonInfo->Domain),
  501. (const PWCHAR)(m_pTSWd->pInfoPkt->Domain)) ||
  502. wcscmp((const PWCHAR)(pLogonInfo->UserName),
  503. (const PWCHAR)(m_pTSWd->pInfoPkt->UserName))))) {
  504. // Get a buffer.
  505. // The buffer size and how it is going to be filled depends on the client's
  506. // capability to accept Long Credentials on return. Pre-Whistler Clients dont
  507. // support Long Credentials
  508. if (scUseLongCredentials == FALSE) {
  509. // Pre Whistler Client - has no capability for accepting long credentials
  510. if ( STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pInfoPDU, sizeof(TS_SAVE_SESSION_INFO_PDU)) ) {
  511. // Zero out the structure and set basic header info.
  512. memset(pInfoPDU, 0, sizeof(TS_SAVE_SESSION_INFO_PDU));
  513. pInfoPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SAVE_SESSION_INFO;
  514. // Now fill up the rest of the packet
  515. pInfoPDU->data.InfoType = TS_INFOTYPE_LOGON;
  516. // Fill in the Domain info.
  517. pInfoPDU->data.Info.LogonInfo.cbDomain =
  518. (wcslen((const PWCHAR)(pLogonInfo->Domain)) + 1) *
  519. sizeof(WCHAR);
  520. memcpy(pInfoPDU->data.Info.LogonInfo.Domain,
  521. pLogonInfo->Domain,
  522. pInfoPDU->data.Info.LogonInfo.cbDomain);
  523. // Fill in the UserName info.
  524. // In case the fDontDisplayLastUserName is set we should
  525. // not send back the username for caching.
  526. pInfoPDU->data.Info.LogonInfo.cbUserName =
  527. (m_pTSWd->fDontDisplayLastUserName) ? 0 :
  528. (wcslen((const PWCHAR)(pLogonInfo->UserName)) + 1) *
  529. sizeof(WCHAR);
  530. memcpy(pInfoPDU->data.Info.LogonInfo.UserName,
  531. pLogonInfo->UserName,
  532. pInfoPDU->data.Info.LogonInfo.cbUserName);
  533. // Fill in the Session Id info.
  534. pInfoPDU->data.Info.LogonInfo.SessionId =
  535. pLogonInfo->SessionId;
  536. // Send it
  537. SC_SendData((PTS_SHAREDATAHEADER)pInfoPDU,
  538. sizeof(TS_SAVE_SESSION_INFO_PDU),
  539. sizeof(TS_SAVE_SESSION_INFO_PDU),
  540. PROT_PRIO_UPDATES, 0);
  541. } else {
  542. TRC_ALT((TB, "Failed to alloc pkt for "
  543. "PTS_SAVE_SESSION_INFO_PDU"));
  544. }
  545. } else {
  546. // Client CAN accept long Credentials
  547. TSUINT32 DomainLen, UserNameLen, DataLen ;
  548. DomainLen = (wcslen((const PWCHAR)(pLogonInfo->Domain)) + 1) * sizeof(WCHAR);
  549. // In case fDontDisplayLastUserName is set we won't send the user name
  550. UserNameLen = (m_pTSWd->fDontDisplayLastUserName) ? 0 :
  551. (wcslen((const PWCHAR)(pLogonInfo->UserName)) + 1) * sizeof(WCHAR);
  552. // Compute the length of the data u r sending
  553. DataLen = sizeof(TS_SAVE_SESSION_INFO_PDU) + DomainLen + UserNameLen ;
  554. TRC_DBG((TB, "DCS_UserLoggedOn : DomainLength allocated = %ul", DomainLen));
  555. TRC_DBG((TB, "DCS_UserLoggedOn : UserNameLength allocated = %ul", UserNameLen));
  556. if ( STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pInfoPDU, DataLen) ) {
  557. // Zero out the structure and set basic header info.
  558. memset(pInfoPDU, 0, DataLen);
  559. pInfoPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SAVE_SESSION_INFO;
  560. // Now fill up the rest of the packet
  561. pInfoPDU->data.InfoType = TS_INFOTYPE_LOGON_LONG;
  562. pInfoPDU->data.Info.LogonInfoVersionTwo.Version = SAVE_SESSION_PDU_VERSION_ONE ;
  563. pInfoPDU->data.Info.LogonInfoVersionTwo.Size = sizeof(TS_LOGON_INFO_VERSION_2) ;
  564. // Fill in the Session Id info.
  565. pInfoPDU->data.Info.LogonInfoVersionTwo.SessionId =
  566. pLogonInfo->SessionId;
  567. // Fill in the Domain info.
  568. pInfoPDU->data.Info.LogonInfoVersionTwo.cbDomain = DomainLen ;
  569. // Fill in the UserName info.
  570. pInfoPDU->data.Info.LogonInfoVersionTwo.cbUserName = UserNameLen ;
  571. memcpy((PBYTE)(pInfoPDU + 1),
  572. pLogonInfo->Domain,
  573. DomainLen);
  574. // Note that in case the fDontDisplayLastUserName is TRUE
  575. // the UserNameLen is 0 so we won't copy anything.
  576. memcpy((PBYTE)(pInfoPDU + 1) + DomainLen,
  577. pLogonInfo->UserName,
  578. UserNameLen);
  579. // Send it
  580. SC_SendData((PTS_SHAREDATAHEADER)pInfoPDU,
  581. DataLen,
  582. DataLen,
  583. PROT_PRIO_UPDATES, 0);
  584. } else {
  585. TRC_ALT((TB, "Failed to alloc pkt for "
  586. "PTS_SAVE_SESSION_INFO_PDU"));
  587. }
  588. } // Client can accept long credentials
  589. }
  590. else
  591. {
  592. //Send back a plain logon notification (without session update
  593. //information)
  594. //because the ActiveX control needs to expose an
  595. //OnLoginComplete event. Older clients (e.g 2195)
  596. //will just ignore this PDU
  597. if ( STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pInfoPDU,
  598. sizeof(TS_SAVE_SESSION_INFO_PDU)) ) {
  599. // Zero out the structure and set basic header info.
  600. memset(pInfoPDU, 0, sizeof(TS_SAVE_SESSION_INFO_PDU));
  601. pInfoPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SAVE_SESSION_INFO;
  602. // Now fill up the rest of the packet
  603. pInfoPDU->data.InfoType = TS_INFOTYPE_LOGON_PLAINNOTIFY;
  604. // Nothing else is needed
  605. // Send it
  606. //
  607. SC_SendData((PTS_SHAREDATAHEADER)pInfoPDU,
  608. sizeof(TS_SAVE_SESSION_INFO_PDU),
  609. sizeof(TS_SAVE_SESSION_INFO_PDU),
  610. PROT_PRIO_UPDATES, 0);
  611. } else {
  612. TRC_ALT((TB, "Failed to alloc pkt for "
  613. "PTS_SAVE_SESSION_INFO_PDU"));
  614. }
  615. }
  616. pInfoPDU = NULL;
  617. if (pLogonInfo->Flags & LI_USE_AUTORECONNECT) {
  618. if (scUseAutoReconnect) {
  619. //
  620. //Send down the autoreconnect cookie
  621. //
  622. m_pTSWd->arcReconnectSessionID = pLogonInfo->SessionId;
  623. if (DCS_UpdateAutoReconnectCookie()) {
  624. //
  625. // Record the update time to prevent a double-update
  626. // in DCS_TimeToDoStuff
  627. //
  628. KeQuerySystemTime((PLARGE_INTEGER)&dcsLastArcUpdateTime);
  629. scEnablePeriodicArcUpdate = TRUE;
  630. }
  631. }
  632. else {
  633. DCS_FlushAutoReconnectCookie();
  634. scEnablePeriodicArcUpdate = FALSE;
  635. }
  636. }
  637. } else {
  638. TRC_ALT((TB, "Called before init"));
  639. }
  640. DC_END_FN();
  641. } /* DCS_UserLoggedOn */
  642. /****************************************************************************/
  643. /* Name: DCS_WDWKeyboardSetIndicators */
  644. /* */
  645. /* Purpose: Notify that keyboard indicators have changed */
  646. /****************************************************************************/
  647. void RDPCALL SHCLASS DCS_WDWKeyboardSetIndicators(void)
  648. {
  649. PTS_SET_KEYBOARD_INDICATORS_PDU pKeyPDU;
  650. DC_BEGIN_FN("DCS_WDWKeyboardSetIndicators");
  651. if ((_RNS_MAJOR_VERSION(m_pTSWd->version) > 8) ||
  652. (_RNS_MINOR_VERSION(m_pTSWd->version) >= 1))
  653. {
  654. // Get a buffer.
  655. if ( STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pKeyPDU,
  656. sizeof(TS_SET_KEYBOARD_INDICATORS_PDU)) )
  657. {
  658. // Zero out the structure and set basic header info.
  659. memset(pKeyPDU, 0, sizeof(TS_SET_KEYBOARD_INDICATORS_PDU));
  660. pKeyPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SET_KEYBOARD_INDICATORS;
  661. pKeyPDU->UnitId = m_pTSWd->KeyboardIndicators.UnitId;
  662. pKeyPDU->LedFlags = m_pTSWd->KeyboardIndicators.LedFlags;
  663. // Send it.
  664. SC_SendData((PTS_SHAREDATAHEADER)pKeyPDU,
  665. sizeof(TS_SET_KEYBOARD_INDICATORS_PDU),
  666. sizeof(TS_SET_KEYBOARD_INDICATORS_PDU),
  667. PROT_PRIO_UPDATES, 0);
  668. }
  669. else {
  670. TRC_ALT((TB, "Failed to alloc pkt for PTS_SET_KEYBOARD_INDICATORS_PDU"));
  671. }
  672. }
  673. DC_END_FN();
  674. } /* DCS_WDWKeyboardSetIndicators */
  675. /****************************************************************************/
  676. /* Name: DCS_WDWKeyboardSetImeStatus */
  677. /* */
  678. /* Purpose: Notify that ime status have changed */
  679. /****************************************************************************/
  680. void RDPCALL SHCLASS DCS_WDWKeyboardSetImeStatus(void)
  681. {
  682. PTS_SET_KEYBOARD_IME_STATUS_PDU pImePDU;
  683. DC_BEGIN_FN("DCS_WDWKeyboardSetImeStatus");
  684. if ((_RNS_MAJOR_VERSION(m_pTSWd->version) > 8) ||
  685. (_RNS_MINOR_VERSION(m_pTSWd->version) >= 2))
  686. {
  687. // Get a buffer.
  688. if ( STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pImePDU,
  689. sizeof(TS_SET_KEYBOARD_IME_STATUS_PDU)) )
  690. {
  691. // Zero out the structure and set basic header info.
  692. memset(pImePDU, 0, sizeof(TS_SET_KEYBOARD_IME_STATUS_PDU));
  693. pImePDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SET_KEYBOARD_IME_STATUS;
  694. pImePDU->UnitId = m_pTSWd->KeyboardImeStatus.UnitId;
  695. pImePDU->ImeOpen = m_pTSWd->KeyboardImeStatus.ImeOpen;
  696. pImePDU->ImeConvMode = m_pTSWd->KeyboardImeStatus.ImeConvMode;
  697. // Send it.
  698. SC_SendData((PTS_SHAREDATAHEADER)pImePDU,
  699. sizeof(TS_SET_KEYBOARD_IME_STATUS_PDU),
  700. sizeof(TS_SET_KEYBOARD_IME_STATUS_PDU),
  701. PROT_PRIO_UPDATES, 0);
  702. }
  703. else {
  704. TRC_ERR((TB, "Failed to alloc pkt for PTS_SET_KEYBOARD_IME_STATUS_PDU"));
  705. }
  706. }
  707. DC_END_FN();
  708. } /* DCS_WDWKeyboardSetImeStatus */
  709. /****************************************************************************/
  710. /* Name: DCS_TriggerUpdateShmCallback */
  711. /* */
  712. /* Purpose: Triggers a callback to the XX_UpdateShm functions on the */
  713. /* correct WinStation context. */
  714. /****************************************************************************/
  715. void RDPCALL SHCLASS DCS_TriggerUpdateShmCallback(void)
  716. {
  717. DC_BEGIN_FN("DCS_TriggerUpdateShmCallback");
  718. if (!dcsUpdateShmPending)
  719. {
  720. TRC_NRM((TB, "Trigger timer for UpdateShm"));
  721. dcsUpdateShmPending = TRUE;
  722. if (!dcsCallbackTimerPending)
  723. {
  724. WDW_StartRITTimer(m_pTSWd, 0);
  725. dcsCallbackTimerPending = TRUE;
  726. }
  727. }
  728. DC_END_FN();
  729. } /* DCS_TriggerUpdateShmCallback */
  730. /****************************************************************************/
  731. /* Name: DCS_TriggerCBDataReady */
  732. /* */
  733. /* Purpose: Triggers a call to the clipboard data ready function in the */
  734. /* correct WinStation context. */
  735. /****************************************************************************/
  736. void RDPCALL SHCLASS DCS_TriggerCBDataReady(void)
  737. {
  738. DC_BEGIN_FN("DCS_TriggerCBDataReady");
  739. TRC_NRM((TB, "Trigger timer for CBDataReady"));
  740. if (!dcsCallbackTimerPending)
  741. WDW_StartRITTimer(m_pTSWd, 10); // @@@ try 10ms delay
  742. DC_END_FN();
  743. } /* DCS_TriggerCBDataReady */
  744. /****************************************************************************/
  745. /* Name: DCS_UpdateShm */
  746. /* */
  747. /* Purpose: Update SHM */
  748. /* */
  749. /* Operation: Guaranteed to be called in a context where m_pShm is valid. */
  750. /****************************************************************************/
  751. void RDPCALL SHCLASS DCS_UpdateShm(void)
  752. {
  753. DC_BEGIN_FN("DCS_UpdateShm");
  754. TRC_NRM((TB, "Check for specific wake-up calls."));
  755. if (dcsUpdateShmPending)
  756. {
  757. TRC_NRM((TB, "Call UpdateShm calls"));
  758. // A Global flag indicating shm updates for all components
  759. m_pShm->fShmUpdate = TRUE;
  760. SSI_UpdateShm();
  761. SBC_UpdateShm();
  762. BA_UpdateShm();
  763. OA_UpdateShm();
  764. OE_UpdateShm();
  765. CM_UpdateShm();
  766. SCH_UpdateShm();
  767. SC_UpdateShm();
  768. dcsUpdateShmPending = FALSE;
  769. }
  770. dcsCallbackTimerPending = FALSE;
  771. DC_END_FN();
  772. } /* DCS_UpdateShm */
  773. /****************************************************************************/
  774. /* Name: DCS_SendErrorInfo */
  775. /* */
  776. /* Purpose: Sends last error information to the client so that it can */
  777. /* Display meaningful error messages to users about disconnects */
  778. /****************************************************************************/
  779. void RDPCALL SHCLASS DCS_SendErrorInfo(TSUINT32 errInfo)
  780. {
  781. PTS_SET_ERROR_INFO_PDU pErrorPDU = NULL;
  782. PTS_SHAREDATAHEADER pHdr = NULL;
  783. DC_BEGIN_FN("DCS_SendErrorInfo");
  784. TRC_ASSERT(m_pTSWd->bSupportErrorInfoPDU,
  785. (TB,"DCS_SendErrorInfo called but client doesn't"
  786. "support errorinfo PDU"));
  787. //Send a PDU to the client to indicate the last error state
  788. //this is analogous to win32's SetLastError() the PDU doesn't
  789. //trigger a disconnect. The normal code path to disconnect
  790. //is unchanged so we don't worry about affecting compatability with
  791. //older clients
  792. if ( STATUS_SUCCESS == SM_AllocBuffer( m_pTSWd->pSmInfo,
  793. (PPVOID) &pErrorPDU,
  794. sizeof(TS_SET_ERROR_INFO_PDU),
  795. FALSE, //never wait for an error packet
  796. FALSE) )
  797. {
  798. // Zero out the structure and set basic header info.
  799. memset(pErrorPDU, 0, sizeof(TS_SET_ERROR_INFO_PDU));
  800. //
  801. // First set the share data header info
  802. //
  803. pHdr = (PTS_SHAREDATAHEADER)pErrorPDU;
  804. pHdr->shareControlHeader.pduType = TS_PDUTYPE_DATAPDU |
  805. TS_PROTOCOL_VERSION;
  806. pHdr->shareControlHeader.pduSource = 0; //user id may not be
  807. //available yet
  808. pHdr->shareControlHeader.totalLength = sizeof(TS_SET_ERROR_INFO_PDU);
  809. pHdr->shareID = 0;
  810. pHdr->streamID = (BYTE)PROT_PRIO_UPDATES;
  811. pHdr->uncompressedLength = (UINT16)sizeof(TS_SET_ERROR_INFO_PDU);
  812. pHdr->generalCompressedType = 0;
  813. pHdr->generalCompressedLength = 0;
  814. m_pTSWd->pProtocolStatus->Output.CompressedBytes +=
  815. sizeof(TS_SET_ERROR_INFO_PDU);
  816. //
  817. // Error pdu specific info
  818. //
  819. pErrorPDU->shareDataHeader.pduType2 =
  820. TS_PDUTYPE2_SET_ERROR_INFO_PDU;
  821. pErrorPDU->errorInfo = errInfo;
  822. TRC_NRM((TB,"Sending ErrorInfo PDU for err:%d", errInfo));
  823. // Send it
  824. if(!SM_SendData( m_pTSWd->pSmInfo,
  825. pErrorPDU,
  826. sizeof(TS_SET_ERROR_INFO_PDU),
  827. 0, 0, FALSE, RNS_SEC_ENCRYPT, FALSE))
  828. {
  829. TRC_ERR((TB, "Failed to SM_SendData for "
  830. "TS_SET_ERROR_INFO_PDU"));
  831. }
  832. }
  833. else
  834. {
  835. TRC_ALT((TB, "Failed to alloc pkt for "
  836. "TS_SET_ERROR_INFO_PDU"));
  837. }
  838. DC_END_FN();
  839. }
  840. /****************************************************************************/
  841. /* Name: DCS_SendAutoReconnectStatus
  842. /*
  843. /* Purpose: Sends autoreconnect status info to the client
  844. /* (e.g. that autoreconnect failed so the client should go back to
  845. /* displaying output so the user can enter cred at winlogon)
  846. /*
  847. /* Params:
  848. /*
  849. /*
  850. /****************************************************************************/
  851. void RDPCALL SHCLASS DCS_SendAutoReconnectStatus(TSUINT32 arcStatus)
  852. {
  853. PTS_AUTORECONNECT_STATUS_PDU pArcStatus = NULL;
  854. PTS_SHAREDATAHEADER pHdr = NULL;
  855. DC_BEGIN_FN("DCS_SendErrorInfo");
  856. TRC_ASSERT(scUseAutoReconnect,
  857. (TB,"DCS_SendAutoReconnectStatus called but client doesn't"
  858. "support autoreconnect status PDU"));
  859. if ( STATUS_SUCCESS == SM_AllocBuffer( m_pTSWd->pSmInfo,
  860. (PPVOID) &pArcStatus,
  861. sizeof(TS_AUTORECONNECT_STATUS_PDU),
  862. FALSE, //never wait for an error packet
  863. FALSE) )
  864. {
  865. // Zero out the structure and set basic header info.
  866. memset(pArcStatus, 0, sizeof(TS_AUTORECONNECT_STATUS_PDU));
  867. //
  868. // First set the share data header info
  869. //
  870. pHdr = (PTS_SHAREDATAHEADER)pArcStatus;
  871. pHdr->shareControlHeader.pduType = TS_PDUTYPE_DATAPDU |
  872. TS_PROTOCOL_VERSION;
  873. pHdr->shareControlHeader.pduSource = 0; //user id may not be
  874. //available yet
  875. pHdr->shareControlHeader.totalLength =
  876. sizeof(TS_AUTORECONNECT_STATUS_PDU);
  877. pHdr->shareID = scShareID;
  878. pHdr->streamID = (BYTE)PROT_PRIO_UPDATES;
  879. pHdr->uncompressedLength =
  880. (UINT16)sizeof(TS_AUTORECONNECT_STATUS_PDU);
  881. pHdr->generalCompressedType = 0;
  882. pHdr->generalCompressedLength = 0;
  883. m_pTSWd->pProtocolStatus->Output.CompressedBytes +=
  884. sizeof(TS_AUTORECONNECT_STATUS_PDU);
  885. //
  886. // Error pdu specific info
  887. //
  888. pArcStatus->shareDataHeader.pduType2 =
  889. TS_PDUTYPE2_ARC_STATUS_PDU;
  890. pArcStatus->arcStatus = arcStatus;
  891. TRC_NRM((TB,"Sending ArcStatus PDU for status:%d", arcStatus));
  892. // Send it
  893. if(!SM_SendData( m_pTSWd->pSmInfo,
  894. pArcStatus,
  895. sizeof(TS_AUTORECONNECT_STATUS_PDU),
  896. 0, 0, FALSE, RNS_SEC_ENCRYPT, FALSE))
  897. {
  898. TRC_ERR((TB, "Failed to SM_SendData for "
  899. "TS_AUTORECONNECT_STATUS_PDU"));
  900. }
  901. }
  902. else
  903. {
  904. TRC_ALT((TB, "Failed to alloc pkt for "
  905. "TS_AUTORECONNECT_STATUS_PDU"));
  906. }
  907. DC_END_FN();
  908. }