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.

354 lines
13 KiB

  1. /****************************************************************************/
  2. // aupapi.cpp
  3. //
  4. // RDP Update Packager functions.
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <precomp.h>
  9. #pragma hdrstop
  10. #define TRC_FILE "aupapi"
  11. #include <as_conf.hpp>
  12. /****************************************************************************/
  13. // UP_Init
  14. /****************************************************************************/
  15. void RDPCALL SHCLASS UP_Init(void)
  16. {
  17. DC_BEGIN_FN("UP_Init");
  18. #define DC_INIT_DATA
  19. #include <aupdata.c>
  20. #undef DC_INIT_DATA
  21. DC_END_FN();
  22. }
  23. /****************************************************************************/
  24. // UP_ReceivedPacket
  25. //
  26. // Handles TS_SUPPRESS_OUTPUT_PDU.
  27. /****************************************************************************/
  28. void RDPCALL SHCLASS UP_ReceivedPacket(
  29. PTS_SUPPRESS_OUTPUT_PDU pSupOutPDU,
  30. unsigned DataLength,
  31. LOCALPERSONID personID)
  32. {
  33. NTSTATUS Status;
  34. ICA_CHANNEL_COMMAND Cmd;
  35. DC_BEGIN_FN("UP_ReceivedPacket");
  36. DC_IGNORE_PARAMETER(personID);
  37. if (DataLength >= (sizeof(TS_SUPPRESS_OUTPUT_PDU) -
  38. sizeof(TS_RECTANGLE16) +
  39. pSupOutPDU->numberOfRectangles * sizeof(TS_RECTANGLE16))) {
  40. // Don't suppress output if we are being shadowed
  41. if ((pSupOutPDU->numberOfRectangles == TS_QUIET_FULL_SUPPRESSION) &&
  42. (m_pTSWd->shadowState == SHADOW_NONE)) {
  43. TRC_NRM((TB, "Turning frame buffer updates OFF"));
  44. Cmd.Header.Command = ICA_COMMAND_STOP_SCREEN_UPDATES;
  45. Status = IcaChannelInput(m_pTSWd->pContext, Channel_Command, 0,
  46. NULL, (unsigned char *)&Cmd, sizeof(ICA_CHANNEL_COMMAND));
  47. TRC_DBG((TB, "Issued StopUpdates, status %lu", Status));
  48. }
  49. else {
  50. if (pSupOutPDU->numberOfRectangles <= TS_MAX_INCLUDED_RECTS) {
  51. // Any other value means we send all output.
  52. TRC_NRM((TB, "Turning screen buffer updates ON with full "
  53. "repaint"));
  54. Cmd.Header.Command = ICA_COMMAND_REDRAW_SCREEN;
  55. Status = IcaChannelInput(m_pTSWd->pContext, Channel_Command,
  56. 0, NULL, (unsigned char *)&Cmd,
  57. sizeof(ICA_CHANNEL_COMMAND));
  58. TRC_DBG((TB, "Issued RedrawScreen, status %lu", Status));
  59. }
  60. else {
  61. TRC_ERR((TB,"Too many rectangles in PDU, disconnecting"));
  62. goto BadPDU;
  63. }
  64. }
  65. }
  66. else {
  67. TRC_ERR((TB,"Data length %u too short for suppress-output PDU header",
  68. DataLength));
  69. goto BadPDU;
  70. }
  71. DC_END_FN();
  72. return;
  73. // Error handling.
  74. BadPDU:
  75. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_BadSupressOutputPDU,
  76. (BYTE *)pSupOutPDU, DataLength);
  77. DC_END_FN();
  78. } /* UP_ReceivedPacket */
  79. /****************************************************************************/
  80. // UP_SendUpdates
  81. //
  82. // Tries to send orders and bitmap data.
  83. /****************************************************************************/
  84. NTSTATUS RDPCALL SHCLASS UP_SendUpdates(
  85. BYTE *pFrameBuf,
  86. UINT32 frameBufWidth,
  87. PPDU_PACKAGE_INFO pPkgInfo)
  88. {
  89. BOOL ordersToSend;
  90. BOOL sdaToSend;
  91. NTSTATUS status = STATUS_SUCCESS;
  92. DC_BEGIN_FN("UP_SendUpdates");
  93. TRC_DBG((TB, "New set of updates"));
  94. ordersToSend = (OA_GetTotalOrderListBytes() > 0);
  95. sdaToSend = SDG_ScreenDataIsWaiting();
  96. // If we actually have updates to send then try to send a sync token.
  97. // If there is work to do on entry, then set a reschedule.
  98. if (ordersToSend || sdaToSend) {
  99. SCH_ContinueScheduling(SCH_MODE_NORMAL);
  100. TRC_NRM((TB, "Updates waiting %d:%d", ordersToSend, sdaToSend));
  101. // Normal case is no sync required. Only send updates if sync token
  102. // has been sent.
  103. if (!upfSyncTokenRequired || UPSendSyncToken(pPkgInfo)) {
  104. // There is no outstanding sync token waiting to be sent, so we
  105. // can send the orders and screen data updates.
  106. // Send accumulated orders. If this call fails (probably out
  107. // of memory) then don't send any other updates - we'll try
  108. // sending the whole lot later. The orders MUST be sent before
  109. // the screen data.
  110. #ifdef DC_HICOLOR
  111. // test for hi color will avoid call into PM
  112. if ((m_pTSWd->desktopBpp > 8) ||
  113. PM_MaybeSendPalettePacket(pPkgInfo))
  114. #else
  115. if (PM_MaybeSendPalettePacket(pPkgInfo))
  116. #endif
  117. {
  118. status = UPSendOrders(pPkgInfo);
  119. // Since it may take multiple output flushes to send all the
  120. // orders during a shadow operation, we only want to send
  121. // screen data once all the orders are gone.
  122. //
  123. // STATUS_IO_TIMEOUT means disconnected client, no reason to send
  124. // screen data
  125. //
  126. if (OA_GetTotalOrderListBytes() == 0) {
  127. if (sdaToSend) {
  128. TRC_NRM((TB, "Sending SD"));
  129. SDG_SendScreenDataArea(pFrameBuf,
  130. frameBufWidth,
  131. pPkgInfo);
  132. }
  133. }
  134. }
  135. }
  136. }
  137. DC_END_FN();
  138. return status;
  139. }
  140. /****************************************************************************/
  141. // UP_SyncNow
  142. //
  143. // Called when a sync operation is required.
  144. /****************************************************************************/
  145. void RDPCALL SHCLASS UP_SyncNow(BOOLEAN bShadowSync)
  146. {
  147. DC_BEGIN_FN("UP_SyncNow");
  148. // Indicate that a sync token is required. We will only actually send
  149. // the token if we get updates to send.
  150. upfSyncTokenRequired = TRUE;
  151. // Call all the XXX_SyncUpdatesNow routines.
  152. // On a shadow synchronization, the DD will have already performed this
  153. // work. Skip it to avoid an unnecessary DD kick.
  154. if (!bShadowSync) {
  155. BA_SyncUpdatesNow();
  156. OA_SyncUpdatesNow();
  157. SBC_SyncUpdatesNow();
  158. SSI_SyncUpdatesNow();
  159. }
  160. DC_END_FN();
  161. }
  162. /****************************************************************************/
  163. // UPSendSyncToken
  164. //
  165. // Sends SynchronizePDU. Returns nonzero on success.
  166. /****************************************************************************/
  167. BOOL RDPCALL SHCLASS UPSendSyncToken(PPDU_PACKAGE_INFO pPkgInfo)
  168. {
  169. DC_BEGIN_FN("UP_SendSyncToken");
  170. // The sync is handled in different ways depending on whether we're using
  171. // fast-path output.
  172. if (scUseFastPathOutput) {
  173. BYTE *pPackageSpace;
  174. // For the fast-path case, we send a zero-byte fast-path update PDU
  175. // (just the header with size field = 0).
  176. pPackageSpace = SC_GetSpaceInPackage(pPkgInfo,
  177. scUpdatePDUHeaderSpace);
  178. if (pPackageSpace != NULL) {
  179. pPackageSpace[0] = TS_UPDATETYPE_SYNCHRONIZE |
  180. scCompressionUsedValue;
  181. SC_AddToPackage(pPkgInfo, scUpdatePDUHeaderSpace, TRUE);
  182. upfSyncTokenRequired = FALSE;
  183. }
  184. else {
  185. // Try again later.
  186. TRC_NRM((TB,"Failed sync packet alloc"));
  187. }
  188. }
  189. else {
  190. TS_UPDATE_SYNCHRONIZE_PDU UNALIGNED *pUpdateSyncPDU;
  191. // For the normal case we send a full TS_UPDATE_SYNCHRONIZE_PDU.
  192. pUpdateSyncPDU = (TS_UPDATE_SYNCHRONIZE_PDU UNALIGNED *)
  193. SC_GetSpaceInPackage(pPkgInfo,
  194. sizeof(TS_UPDATE_SYNCHRONIZE_PDU));
  195. if (pUpdateSyncPDU != NULL) {
  196. // Fill in the packet contents.
  197. pUpdateSyncPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_UPDATE;
  198. pUpdateSyncPDU->updateType = TS_UPDATETYPE_SYNCHRONIZE;
  199. SC_AddToPackage(pPkgInfo, sizeof(TS_UPDATE_SYNCHRONIZE_PDU),
  200. TRUE);
  201. upfSyncTokenRequired = FALSE;
  202. }
  203. else {
  204. // Try again later.
  205. TRC_NRM((TB, "failed to allocate sync packet"));
  206. }
  207. }
  208. DC_END_FN();
  209. return (!upfSyncTokenRequired);
  210. }
  211. /****************************************************************************/
  212. /* Name: UP_SendBeep */
  213. /* */
  214. /* Purpose: Send a beep PDU to the client */
  215. /* */
  216. /* Returns: TRUE = success; FALSE = failed to alloc packet */
  217. /* */
  218. /* Params: IN duration - length of beep in ms */
  219. /* IN frequency - frequency of beep in Hz */
  220. /* */
  221. /* Operation: Alloc a beep packet, fill it in and send it. */
  222. /****************************************************************************/
  223. BOOL RDPCALL SHCLASS UP_SendBeep(UINT32 duration, UINT32 frequency)
  224. {
  225. BOOL rc = TRUE;
  226. DC_BEGIN_FN("UP_SendBeep");
  227. PTS_PLAY_SOUND_PDU pBeepPDU;
  228. /************************************************************************/
  229. // If caps say we're not allowed to send this beep, then we jump
  230. // out. The return code is still TRUE since nothing actually went
  231. // wrong.
  232. /************************************************************************/
  233. if (upCanSendBeep) {
  234. /********************************************************************/
  235. // Get a buffer and send the beep.
  236. /********************************************************************/
  237. if ( STATUS_SUCCESS == SC_AllocBuffer((PPVOID)&pBeepPDU, sizeof(TS_PLAY_SOUND_PDU)) ) {
  238. // Fill in the PDU
  239. pBeepPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_PLAY_SOUND;
  240. pBeepPDU->data.duration = duration;
  241. pBeepPDU->data.frequency = frequency;
  242. rc = SC_SendData((PTS_SHAREDATAHEADER)pBeepPDU,
  243. sizeof(TS_PLAY_SOUND_PDU),
  244. sizeof(TS_PLAY_SOUND_PDU),
  245. PROT_PRIO_UPDATES,
  246. 0);
  247. }
  248. else {
  249. TRC_ALT((TB, "Failed to allocate packet for TS_PLAY_SOUND_PDU"));
  250. rc = FALSE;
  251. }
  252. }
  253. DC_END_FN();
  254. return rc;
  255. } /* UP_SendBeep */
  256. /****************************************************************************/
  257. /* Name: UP_PartyJoiningShare */
  258. /* */
  259. /* Purpose: Handles update of sound caps when party joins share */
  260. /* */
  261. /* Returns: TRUE - party can join */
  262. /* FALSE - party can't join */
  263. /* */
  264. /* Params: locPersonID - local ID of person trying to join */
  265. /* oldShareSize - old share size */
  266. /****************************************************************************/
  267. BOOL RDPCALL SHCLASS UP_PartyJoiningShare(
  268. LOCALPERSONID locPersonID,
  269. unsigned oldShareSize)
  270. {
  271. DC_BEGIN_FN("UP_PartyJoiningShare");
  272. DC_IGNORE_PARAMETER(oldShareSize);
  273. if (SC_LOCAL_PERSON_ID != locPersonID) {
  274. // Assume we can send beeps. UPEnumSoundCaps will then turn beeps off
  275. // if a party doesn't support them.
  276. upCanSendBeep = TRUE;
  277. CPC_EnumerateCapabilities(TS_CAPSETTYPE_SOUND, NULL, UPEnumSoundCaps);
  278. TRC_NRM((TB, "Beeps are now %s", upCanSendBeep ? "ENABLED" :
  279. "DISABLED"));
  280. UP_UpdateHeaderSize();
  281. }
  282. DC_END_FN();
  283. return TRUE;
  284. } /* UP_PartyJoiningShare */
  285. /****************************************************************************/
  286. /* Name: UP_PartyLeftShare */
  287. /* */
  288. /* Params: personID - local ID of person leaving */
  289. /* newShareSize - new share size */
  290. /****************************************************************************/
  291. void RDPCALL SHCLASS UP_PartyLeftShare(
  292. LOCALPERSONID personID,
  293. unsigned newShareSize)
  294. {
  295. DC_BEGIN_FN("UP_PartyLeftShare");
  296. // We always just want to reenumerate the caps and reset variables.
  297. UP_PartyJoiningShare(personID, newShareSize);
  298. DC_END_FN();
  299. } /* UP_PartyLeftShare */