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.

759 lines
33 KiB

  1. /****************************************************************************/
  2. /* acmapi.cpp */
  3. /* */
  4. /* Cursor Manager API functions. */
  5. /* */
  6. /* Copyright(c) Microsoft, PictureTel 1992-1997 */
  7. /* Copyright(c) Microsoft 1997-1999 */
  8. /****************************************************************************/
  9. #include <precomp.h>
  10. #pragma hdrstop
  11. #define TRC_FILE "acmapi"
  12. #include <as_conf.hpp>
  13. /****************************************************************************/
  14. /* CM_Init */
  15. /****************************************************************************/
  16. void RDPCALL SHCLASS CM_Init(void)
  17. {
  18. TS_POINTER_CAPABILITYSET PtrCaps;
  19. DC_BEGIN_FN("CM_Init");
  20. #define DC_INIT_DATA
  21. #include <acmdata.c>
  22. #undef DC_INIT_DATA
  23. /************************************************************************/
  24. /* Set up the CM capabilities. */
  25. /************************************************************************/
  26. PtrCaps.capabilitySetType = TS_CAPSETTYPE_POINTER;
  27. PtrCaps.colorPointerFlag = TRUE;
  28. PtrCaps.colorPointerCacheSize = CM_DEFAULT_RX_CACHE_ENTRIES;
  29. PtrCaps.pointerCacheSize = CM_DEFAULT_RX_CACHE_ENTRIES;
  30. CPC_RegisterCapabilities((PTS_CAPABILITYHEADER)&PtrCaps,
  31. sizeof(TS_POINTER_CAPABILITYSET));
  32. TRC_NRM((TB, "CM initialized"));
  33. DC_END_FN();
  34. }
  35. /****************************************************************************/
  36. /* CM_UpdateShm(..) */
  37. /* */
  38. /* Updates CM Shared Memory. */
  39. /****************************************************************************/
  40. void RDPCALL SHCLASS CM_UpdateShm(void)
  41. {
  42. DC_BEGIN_FN("CM_UpdateShm");
  43. TRC_NRM((TB, "Update CM"));
  44. /************************************************************************/
  45. /* Setup the cache size to use */
  46. /************************************************************************/
  47. m_pShm->cm.cmCacheSize = cmNewTxCacheSize;
  48. m_pShm->cm.cmNativeColor = cmSendNativeColorDepth;
  49. #ifdef DC_HICOLOR
  50. /************************************************************************/
  51. /* Do we support any-bpp cursors? */
  52. /************************************************************************/
  53. m_pShm->cm.cmSendAnyColor = (m_pTSWd->supportedBpps != 0);
  54. #endif
  55. DC_END_FN();
  56. }
  57. /****************************************************************************/
  58. /* CM_PartyJoiningShare() */
  59. /* */
  60. /* Called when a new party is joining the share. */
  61. /* */
  62. /* PARAMETERS: */
  63. /* */
  64. /* locPersonID - local person ID of remote person joining the share. */
  65. /* */
  66. /* oldShareSize - the number of the parties which were in the share (ie */
  67. /* excludes the joining party). */
  68. /* */
  69. /* RETURNS: TRUE if the party can join the share. */
  70. /* FALSE if the party can NOT join the share. */
  71. /****************************************************************************/
  72. BOOL RDPCALL SHCLASS CM_PartyJoiningShare(
  73. LOCALPERSONID locPersonID,
  74. unsigned oldShareSize)
  75. {
  76. BOOL rc = TRUE;
  77. DC_BEGIN_FN("CM_PartyJoiningShare");
  78. /************************************************************************/
  79. /* Allow ourself to be added to the share, but do nothing else. */
  80. /************************************************************************/
  81. if (locPersonID == SC_LOCAL_PERSON_ID) {
  82. TRC_DBG((TB, "Added ourself {%u} to the share", locPersonID));
  83. }
  84. else {
  85. // Flag that we must send a cursor shape update.
  86. cmNeedToSendCursorShape = TRUE;
  87. // Set cache size before enumerating capabilities.
  88. TRC_NRM((TB, "Default cache size: %u", CM_DEFAULT_TX_CACHE_ENTRIES));
  89. cmNewTxCacheSize = CM_DEFAULT_TX_CACHE_ENTRIES;
  90. cmSendNativeColorDepth = FALSE;
  91. TRC_NRM((TB, "Native color depth support is %s",
  92. cmSendNativeColorDepth ? "ON" : "OFF"));
  93. // Do capability renegotiation.
  94. CPC_EnumerateCapabilities(TS_CAPSETTYPE_POINTER, NULL, CMEnumCMCaps);
  95. // Check that the negotiated cache size is non-zero - the protocol
  96. // assumes this
  97. TRC_NRM((TB, "Negotiated cache size: %u", NULL, cmNewTxCacheSize));
  98. if (cmNewTxCacheSize == 0) {
  99. // This is a protocol error - log it
  100. TRC_ERR((TB, "Negotiated cache size is zero"));
  101. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_NoCursorCache, NULL, 0);
  102. rc = FALSE;
  103. }
  104. else {
  105. // Trigger an IOCTL from the DD so we have the right context to
  106. // update the shared memory.
  107. DCS_TriggerUpdateShmCallback();
  108. }
  109. }
  110. DC_END_FN();
  111. return rc;
  112. }
  113. /****************************************************************************/
  114. /* FUNCTION: CMEnumCMCaps */
  115. /* */
  116. /* CM callback function for CPC capabilities enumeration. */
  117. /* */
  118. /* PARAMETERS: */
  119. /* personID - ID of this person */
  120. /* pCapabilities - pointer to this person's cursor capabilites */
  121. /****************************************************************************/
  122. void RDPCALL SHCLASS CMEnumCMCaps(
  123. LOCALPERSONID locPersonID,
  124. UINT_PTR UserData,
  125. PTS_CAPABILITYHEADER pCapabilities)
  126. {
  127. PTS_POINTER_CAPABILITYSET pPointerCaps;
  128. BOOL fSupportsColorCursors;
  129. unsigned cCursorCacheSize;
  130. DC_BEGIN_FN("CMEnumCMCaps");
  131. DC_IGNORE_PARAMETER(UserData);
  132. pPointerCaps = (PTS_POINTER_CAPABILITYSET)pCapabilities;
  133. /************************************************************************/
  134. /* If the person does not have any cursor capabilites we still get */
  135. /* called, but the sizeOfCapabilities field is zero. */
  136. /************************************************************************/
  137. if (pPointerCaps->lengthCapability < FIELDOFFSET(
  138. TS_POINTER_CAPABILITYSET, pointerCacheSize))
  139. {
  140. TRC_NRM((TB, "Person[0x%x] No cursor caps", locPersonID));
  141. cCursorCacheSize = 0;
  142. fSupportsColorCursors = FALSE;
  143. }
  144. else if (pPointerCaps->lengthCapability == FIELDOFFSET(
  145. TS_POINTER_CAPABILITYSET, pointerCacheSize))
  146. {
  147. TRC_NRM((TB,
  148. "Old style Person[0x%x] capsID(%u) size(%u) ccrs(%u) CacheSize(%u)",
  149. locPersonID,
  150. pPointerCaps->capabilitySetType,
  151. pPointerCaps->lengthCapability,
  152. pPointerCaps->colorPointerFlag,
  153. pPointerCaps->colorPointerCacheSize));
  154. cCursorCacheSize = pPointerCaps->colorPointerCacheSize;
  155. fSupportsColorCursors = pPointerCaps->colorPointerFlag;
  156. }
  157. else
  158. {
  159. TRC_NRM((TB,
  160. "New style Person[0x%x] capsID(%u) size(%u) ccrs(%u) CacheSize(%u)",
  161. locPersonID,
  162. pPointerCaps->capabilitySetType,
  163. pPointerCaps->lengthCapability,
  164. pPointerCaps->colorPointerFlag,
  165. pPointerCaps->pointerCacheSize));
  166. cCursorCacheSize = pPointerCaps->pointerCacheSize;
  167. fSupportsColorCursors = pPointerCaps->colorPointerFlag;
  168. cmSendNativeColorDepth = TRUE;
  169. }
  170. TRC_ASSERT((fSupportsColorCursors), (TB, "Mono protocol not supported"));
  171. cmNewTxCacheSize = min(cmNewTxCacheSize, cCursorCacheSize);
  172. DC_END_FN();
  173. }
  174. /****************************************************************************/
  175. /* FUNCTION: CM_SendCursorMovedPacket */
  176. /* */
  177. /* Called to try and send a cursor moved packet either from */
  178. /* CM_SendCursorMovedPacket or CM_Periodic. */
  179. /****************************************************************************/
  180. void RDPCALL SHCLASS CM_SendCursorMovedPacket(PPDU_PACKAGE_INFO pPkgInfo)
  181. {
  182. unsigned packetSize;
  183. BYTE *pPackageSpace;
  184. TS_POINTER_PDU_DATA UNALIGNED *pPointerPDU;
  185. DC_BEGIN_FN("CMSendCursorMovedPacket");
  186. TRC_ASSERT((m_pShm), (TB,"NULL m_pShm"));
  187. // Work out how much space we need for a cursor packet.
  188. if (scUseFastPathOutput)
  189. packetSize = scUpdatePDUHeaderSpace + sizeof(TS_POINT16);
  190. else
  191. packetSize = scUpdatePDUHeaderSpace +
  192. FIELDOFFSET(TS_POINTER_PDU_DATA, pointerData.pointerPosition) +
  193. FIELDSIZE(TS_POINTER_PDU_DATA, pointerData.pointerPosition);
  194. pPackageSpace = SC_GetSpaceInPackage(pPkgInfo, packetSize);
  195. if (NULL != pPackageSpace) {
  196. TS_POINT16 UNALIGNED *pPoint;
  197. // Fill in the packet.
  198. if (scUseFastPathOutput) {
  199. pPackageSpace[0] = TS_UPDATETYPE_MOUSEPTR_POSITION |
  200. scCompressionUsedValue;
  201. pPoint = (TS_POINT16 UNALIGNED *)(pPackageSpace +
  202. scUpdatePDUHeaderSpace);
  203. }
  204. else {
  205. ((TS_POINTER_PDU UNALIGNED *)pPackageSpace)->shareDataHeader.
  206. pduType2 = TS_PDUTYPE2_POINTER;
  207. pPointerPDU = (TS_POINTER_PDU_DATA UNALIGNED *)(pPackageSpace +
  208. scUpdatePDUHeaderSpace);
  209. pPointerPDU->messageType = TS_PTRMSGTYPE_POSITION;
  210. pPoint = &pPointerPDU->pointerData.pointerPosition;
  211. }
  212. pPoint->x = (UINT16)m_pShm->cm.cmCursorPos.x;
  213. pPoint->y = (UINT16)m_pShm->cm.cmCursorPos.y;
  214. SC_AddToPackage(pPkgInfo, packetSize, FALSE);
  215. TRC_NRM((TB, "Send cursor move (%d,%d)", m_pShm->cm.cmCursorPos.x,
  216. m_pShm->cm.cmCursorPos.y));
  217. }
  218. else {
  219. TRC_ERR((TB, "couldn't get space in package"));
  220. }
  221. DC_END_FN();
  222. }
  223. /****************************************************************************/
  224. /* FUNCTION: CMSendCursorShape */
  225. /* */
  226. /* Sends a packet containing the given cursor shape (bitmap). If the */
  227. /* same shape is located in the cache then a cached cursor packet is sent. */
  228. /* */
  229. /* PARAMETERS: */
  230. /* pCursorShape - pointer to the cursor shape */
  231. /* cbCursorDataSize - pointer to the cursor data size */
  232. /* */
  233. /* RETURNS: TRUE if successful, FALSE otherwise. */
  234. /****************************************************************************/
  235. BOOL RDPCALL SHCLASS CMSendCursorShape(PPDU_PACKAGE_INFO pPkgInfo)
  236. {
  237. BOOL rc = TRUE;
  238. PCM_CURSORSHAPE pCursorShape;
  239. unsigned cbCursorDataSize;
  240. DC_BEGIN_FN("CMSendCursorShape");
  241. TRC_ASSERT((m_pShm), (TB,"NULL m_pShm"));
  242. /************************************************************************/
  243. /* check for a cached cursor */
  244. /************************************************************************/
  245. if (m_pShm->cm.cmCacheHit)
  246. {
  247. TRC_NRM((TB, "Cursor in cache: iEntry(%u)", m_pShm->cm.cmCacheEntry));
  248. if (CMSendCachedCursor(m_pShm->cm.cmCacheEntry, pPkgInfo))
  249. {
  250. /****************************************************************/
  251. /* Indicate to the DD that we got the new cursor and return */
  252. /* success. */
  253. /****************************************************************/
  254. m_pShm->cm.cmBitsWaiting = FALSE;
  255. }
  256. else
  257. {
  258. TRC_ALT((TB, "Failed to send definition"));
  259. rc = FALSE;
  260. }
  261. }
  262. else
  263. {
  264. /********************************************************************/
  265. /* wasn't cached - get the bits and send them */
  266. /********************************************************************/
  267. if (CMGetCursorShape(&pCursorShape, &cbCursorDataSize))
  268. {
  269. if (!CM_CURSOR_IS_NULL(pCursorShape))
  270. {
  271. TRC_NRM((TB, "Send new cursor: pShape(%p), iEntry(%u)",
  272. pCursorShape, m_pShm->cm.cmCacheEntry));
  273. if (CMSendColorBitmapCursor(pCursorShape,
  274. m_pShm->cm.cmCacheEntry, pPkgInfo))
  275. {
  276. /********************************************************/
  277. /* Indicate to the DD that we got the new cursor and */
  278. /* return success. */
  279. /********************************************************/
  280. m_pShm->cm.cmBitsWaiting = FALSE;
  281. }
  282. else
  283. {
  284. TRC_ALT((TB, "Failed to send cursor"));
  285. rc = FALSE;
  286. }
  287. }
  288. else
  289. {
  290. /************************************************************/
  291. /* If this is a Null pointer, send the relevant packet. We */
  292. /* return FALSE here so that we will attempt to re-send the */
  293. /* cursor on the next CM_Periodic(). */
  294. /************************************************************/
  295. TRC_NRM((TB, "Send Null cursor"));
  296. CMSendSystemCursor(TS_SYSPTR_NULL, pPkgInfo);
  297. rc = FALSE;
  298. }
  299. }
  300. }
  301. DC_END_FN();
  302. return rc;
  303. }
  304. /****************************************************************************/
  305. /* FUNCTION: CMSendCachedCursor */
  306. /* */
  307. /* Sends a packet containing the given cache entry id. */
  308. /* */
  309. /* PARAMETERS: */
  310. /* iCacheEntry - cache index */
  311. /* */
  312. /* RETURNS: TRUE if packet sent, FALSE otherwise. */
  313. /****************************************************************************/
  314. BOOL RDPCALL SHCLASS CMSendCachedCursor(unsigned iCacheEntry,
  315. PPDU_PACKAGE_INFO pPkgInfo)
  316. {
  317. BOOL rc = TRUE;
  318. BYTE *pPackageSpace;
  319. TS_POINTER_PDU_DATA UNALIGNED *pPointerPDU;
  320. unsigned cbPacketSize;
  321. DC_BEGIN_FN("CMSendCachedCursor");
  322. TRC_NRM((TB, "Send cached cursor(%u)", iCacheEntry));
  323. // See how much space we need.
  324. if (scUseFastPathOutput)
  325. cbPacketSize = scUpdatePDUHeaderSpace + sizeof(TSUINT16);
  326. else
  327. cbPacketSize = scUpdatePDUHeaderSpace +
  328. FIELDOFFSET(TS_POINTER_PDU_DATA,
  329. pointerData.cachedPointerIndex) +
  330. FIELDSIZE(TS_POINTER_PDU_DATA,
  331. pointerData.cachedPointerIndex);
  332. pPackageSpace = SC_GetSpaceInPackage(pPkgInfo, cbPacketSize);
  333. if (NULL != pPackageSpace) {
  334. TSUINT16 UNALIGNED *pIndex;
  335. // Fill in the packet.
  336. if (scUseFastPathOutput) {
  337. pPackageSpace[0] = TS_UPDATETYPE_MOUSEPTR_CACHED |
  338. scCompressionUsedValue;
  339. pIndex = (TSUINT16 UNALIGNED *)(pPackageSpace +
  340. scUpdatePDUHeaderSpace);
  341. }
  342. else {
  343. ((TS_POINTER_PDU UNALIGNED *)pPackageSpace)->shareDataHeader.
  344. pduType2 = TS_PDUTYPE2_POINTER;
  345. pPointerPDU = (TS_POINTER_PDU_DATA UNALIGNED *)
  346. (pPackageSpace + scUpdatePDUHeaderSpace);
  347. pPointerPDU->messageType = TS_PTRMSGTYPE_CACHED;
  348. pIndex = &pPointerPDU->pointerData.cachedPointerIndex;
  349. }
  350. *pIndex = (TSUINT16)iCacheEntry;
  351. SC_AddToPackage(pPkgInfo, cbPacketSize, TRUE);
  352. }
  353. else
  354. {
  355. TRC_ERR((TB, "couldn't get space in package"));
  356. rc = FALSE;
  357. }
  358. DC_END_FN();
  359. return rc;
  360. }
  361. /****************************************************************************/
  362. /* FUNCTION: CMSendSystemCursor */
  363. /* */
  364. /* Sends a packet containing the given system cursor IDC. */
  365. /* */
  366. /* PARAMETERS: */
  367. /* cursorIDC - the IDC of the system cursor to send */
  368. /* */
  369. /* RETURNS: TRUE if successful, FALSE otherwise. */
  370. /****************************************************************************/
  371. BOOL RDPCALL SHCLASS CMSendSystemCursor(UINT32 cursorIDC,
  372. PPDU_PACKAGE_INFO pPkgInfo)
  373. {
  374. BOOL rc = TRUE;
  375. unsigned cbPacketSize;
  376. BYTE *pPackageSpace;
  377. TS_POINTER_PDU_DATA UNALIGNED *pPointerPDU;
  378. DC_BEGIN_FN("CMSendSystemCursor");
  379. // The cursor is one of the system cursors. Work out how big a packet
  380. // we need.
  381. if (scUseFastPathOutput)
  382. cbPacketSize = scUpdatePDUHeaderSpace;
  383. else
  384. cbPacketSize = scUpdatePDUHeaderSpace +
  385. FIELDOFFSET(TS_POINTER_PDU_DATA,
  386. pointerData.systemPointerType) +
  387. FIELDSIZE(TS_POINTER_PDU_DATA,
  388. pointerData.systemPointerType);
  389. pPackageSpace = SC_GetSpaceInPackage(pPkgInfo, cbPacketSize);
  390. if (NULL != pPackageSpace) {
  391. // Fill in the packet.
  392. if (scUseFastPathOutput) {
  393. TRC_ASSERT((cursorIDC == TS_SYSPTR_NULL ||
  394. cursorIDC == TS_SYSPTR_DEFAULT),
  395. (TB,"Unrecognized cursorIDC=%u", cursorIDC));
  396. pPackageSpace[0] = (cursorIDC == TS_SYSPTR_NULL ?
  397. TS_UPDATETYPE_MOUSEPTR_SYSTEM_NULL :
  398. TS_UPDATETYPE_MOUSEPTR_SYSTEM_DEFAULT) |
  399. scCompressionUsedValue;
  400. }
  401. else {
  402. ((TS_POINTER_PDU UNALIGNED *)pPackageSpace)->shareDataHeader.
  403. pduType2 = TS_PDUTYPE2_POINTER;
  404. pPointerPDU = (TS_POINTER_PDU_DATA UNALIGNED *)(pPackageSpace +
  405. scUpdatePDUHeaderSpace);
  406. pPointerPDU->messageType = TS_PTRMSGTYPE_SYSTEM;
  407. pPointerPDU->pointerData.systemPointerType = (UINT16)cursorIDC;
  408. }
  409. TRC_NRM((TB, "Send UINT16 %ld", cursorIDC));
  410. SC_AddToPackage(pPkgInfo, cbPacketSize, TRUE);
  411. }
  412. else
  413. {
  414. TRC_ERR((TB, "couldn't get space in package"));
  415. rc = FALSE;
  416. }
  417. DC_END_FN();
  418. return rc;
  419. }
  420. /****************************************************************************/
  421. /* FUNCTION: CMSendColorBitmapCursor */
  422. /* */
  423. /* Sends a given cursor as a color bitmap. */
  424. /* */
  425. /* PARAMETERS: */
  426. /* pCursor - pointer to the cursor shape */
  427. /* iCacheEntry - cache index to store in the transmitted packet */
  428. /* */
  429. /* RETURNS: TRUE if packet sent, FALSE otherwise */
  430. /****************************************************************************/
  431. BOOL RDPCALL SHCLASS CMSendColorBitmapCursor(
  432. PCM_CURSORSHAPE pCursor,
  433. unsigned iCacheEntry,
  434. PPDU_PACKAGE_INFO pPkgInfo)
  435. {
  436. unsigned cbPacketSize;
  437. BYTE *pPackageSpace;
  438. TS_POINTER_PDU_DATA UNALIGNED *pPointerPDU;
  439. BOOL rc = TRUE;
  440. unsigned cbANDMaskSize;
  441. unsigned cbXORBitmapSize;
  442. unsigned cbColorCursorSize;
  443. TS_COLORPOINTERATTRIBUTE UNALIGNED *pColAttr;
  444. DC_BEGIN_FN("CMSendColorBitmapCursor");
  445. /************************************************************************/
  446. /* Calculate the color cursor size in bytes -- both AND and XOR fields. */
  447. /************************************************************************/
  448. cbANDMaskSize = CURSOR_AND_MASK_SIZE(pCursor);
  449. cbXORBitmapSize = CURSOR_XOR_BITMAP_SIZE(pCursor);
  450. cbColorCursorSize = cbANDMaskSize + cbXORBitmapSize;
  451. // How big is a cursor packet?
  452. if (cmSendNativeColorDepth) {
  453. // New protocol.
  454. if (scUseFastPathOutput)
  455. cbPacketSize = scUpdatePDUHeaderSpace +
  456. sizeof(TS_POINTERATTRIBUTE) + cbColorCursorSize;
  457. else
  458. cbPacketSize = scUpdatePDUHeaderSpace +
  459. (unsigned)FIELDOFFSET(TS_POINTER_PDU_DATA,
  460. pointerData.pointerAttribute.colorPtrAttr.
  461. colorPointerData[0]) + cbColorCursorSize;
  462. }
  463. else {
  464. // old protocol - hard coded 24 bpp
  465. if (scUseFastPathOutput)
  466. cbPacketSize = scUpdatePDUHeaderSpace +
  467. sizeof(TS_COLORPOINTERATTRIBUTE) + cbColorCursorSize;
  468. else
  469. cbPacketSize = scUpdatePDUHeaderSpace +
  470. (unsigned)FIELDOFFSET(TS_POINTER_PDU_DATA,
  471. pointerData.colorPointerAttribute.colorPointerData[0]) +
  472. cbColorCursorSize;
  473. }
  474. pPackageSpace = SC_GetSpaceInPackage(pPkgInfo, cbPacketSize);
  475. if (NULL != pPackageSpace) {
  476. // Fill in the packet.
  477. if (scUseFastPathOutput) {
  478. if (cmSendNativeColorDepth) {
  479. TS_POINTERATTRIBUTE UNALIGNED *pAttr;
  480. // New protocol.
  481. pPackageSpace[0] = TS_UPDATETYPE_MOUSEPTR_POINTER |
  482. scCompressionUsedValue;
  483. pAttr = (TS_POINTERATTRIBUTE UNALIGNED *)(pPackageSpace +
  484. scUpdatePDUHeaderSpace);
  485. pAttr->XORBpp = pCursor->hdr.cBitsPerPel;
  486. pColAttr = &pAttr->colorPtrAttr;
  487. }
  488. else {
  489. // Old protocol.
  490. pPackageSpace[0] = TS_UPDATETYPE_MOUSEPTR_COLOR |
  491. scCompressionUsedValue;
  492. pColAttr = (TS_COLORPOINTERATTRIBUTE UNALIGNED *)
  493. (pPackageSpace + scUpdatePDUHeaderSpace);
  494. }
  495. }
  496. else {
  497. ((TS_POINTER_PDU UNALIGNED *)pPackageSpace)->shareDataHeader.
  498. pduType2 = TS_PDUTYPE2_POINTER;
  499. pPointerPDU = (TS_POINTER_PDU_DATA UNALIGNED *)(pPackageSpace +
  500. scUpdatePDUHeaderSpace);
  501. if (cmSendNativeColorDepth) {
  502. // new protocol
  503. pPointerPDU->messageType = TS_PTRMSGTYPE_POINTER;
  504. pPointerPDU->pointerData.pointerAttribute.XORBpp =
  505. pCursor->hdr.cBitsPerPel;
  506. pColAttr = &(pPointerPDU->pointerData.pointerAttribute.
  507. colorPtrAttr);
  508. }
  509. else {
  510. // old protocol - hard coded 24 bpp
  511. pPointerPDU->messageType = TS_PTRMSGTYPE_COLOR;
  512. pColAttr = &(pPointerPDU->pointerData.colorPointerAttribute);
  513. }
  514. }
  515. pColAttr->cacheIndex = (TSUINT16)iCacheEntry;
  516. // Now set up the details
  517. CMGetColorCursorDetails(
  518. pCursor,
  519. &(pColAttr->width),
  520. &(pColAttr->height),
  521. (PUINT16_UA)&(pColAttr->hotSpot.x),
  522. (PUINT16_UA)&(pColAttr->hotSpot.y),
  523. &(pColAttr->colorPointerData[0]) + cbXORBitmapSize,
  524. &(pColAttr->lengthANDMask),
  525. &(pColAttr->colorPointerData[0]),
  526. &(pColAttr->lengthXORMask));
  527. // sanity checks
  528. TRC_ASSERT((pColAttr->lengthANDMask == cbANDMaskSize),
  529. (TB, "AND mask size differs: %u, %u",
  530. pColAttr->lengthANDMask,
  531. cbANDMaskSize));
  532. TRC_ASSERT((pColAttr->lengthXORMask == cbXORBitmapSize),
  533. (TB, "XOR bitmap size differs: %u, %u",
  534. pColAttr->lengthXORMask,
  535. cbXORBitmapSize));
  536. TRC_NRM((TB,
  537. "Color cursor id %u cx:%u cy:%u xhs:%u yhs:%u cbAND:%u cbXOR:%u",
  538. pColAttr->cacheIndex,
  539. pColAttr->width,
  540. pColAttr->height,
  541. pColAttr->hotSpot.x,
  542. pColAttr->hotSpot.y,
  543. pColAttr->lengthANDMask,
  544. pColAttr->lengthXORMask));
  545. // Add it to the package.
  546. SC_AddToPackage(pPkgInfo, cbPacketSize, TRUE);
  547. }
  548. else
  549. {
  550. TRC_ERR((TB, "couldn't get space in package"));
  551. rc = FALSE;
  552. }
  553. DC_END_FN();
  554. return rc;
  555. }
  556. /****************************************************************************/
  557. /* FUNCTION: CMGetColorCursorDetails */
  558. /* */
  559. /* Returns details of a cursor at 24bpp, given a CM_CURSORSHAPE structure. */
  560. /* */
  561. /* PARAMETERS: */
  562. /* pCursor - pointer to a CM_CURSORSHAPE structure from which this function */
  563. /* extracts the details */
  564. /* pcxWidth - pointer to a UINT16 variable that receives the cursor width */
  565. /* in pixels */
  566. /* pcyHeight - pointer to a UINT16 variable that receives the cursor */
  567. /* height in pixels */
  568. /* pxHotSpot - pointer to a UINT16 variable that receives the cursor */
  569. /* hotspot x coordinate */
  570. /* pyHotSpot - pointer to a UINT16 variable that receives the cursor */
  571. /* hotspot y coordinate */
  572. /* pANDMask - pointer to a buffer that receives the cursor AND mask */
  573. /* pcbANDMask - pointer to a UINT16 variable that receives the size in */
  574. /* bytes of the cursor AND mask */
  575. /* pXORBitmap - pointer to a buffer that receives the cursor XOR bitmap at */
  576. /* 24bpp */
  577. /* pcbXORBitmap - pointer to a UINT16 variable that receives the size in */
  578. /* bytes of the cursor XOR bitmap */
  579. /****************************************************************************/
  580. void RDPCALL SHCLASS CMGetColorCursorDetails(
  581. PCM_CURSORSHAPE pCursor,
  582. PUINT16_UA pcxWidth,
  583. PUINT16_UA pcyHeight,
  584. PUINT16_UA pxHotSpot,
  585. PUINT16_UA pyHotSpot,
  586. PBYTE pANDMask,
  587. PUINT16_UA pcbANDMask,
  588. PBYTE pXORBitmap,
  589. PUINT16_UA pcbXORBitmap)
  590. {
  591. unsigned cbANDMaskSize;
  592. unsigned cbXORBitmapSize;
  593. unsigned cbXORBitmapRowWidth;
  594. unsigned cbANDMaskRowWidth;
  595. unsigned cbSrcRowOffset;
  596. unsigned cbDstRowOffset;
  597. unsigned y;
  598. PCM_CURSORSHAPEHDR pCursorHdr;
  599. DC_BEGIN_FN("CMGetColorCursorDetails");
  600. TRC_ASSERT((pCursor != NULL),(TB,"NULL pCursor not allowed!"));
  601. pCursorHdr = &(pCursor->hdr);
  602. /************************************************************************/
  603. /* Copy the cursor size and hotspot coords. */
  604. /************************************************************************/
  605. *pcxWidth = pCursorHdr->cx;
  606. *pcyHeight = pCursorHdr->cy;
  607. *pxHotSpot = (UINT16)pCursorHdr->ptHotSpot.x;
  608. *pyHotSpot = (UINT16)pCursorHdr->ptHotSpot.y;
  609. TRC_NRM((TB, "cx(%u) cy(%u) cbWidth %d planes(%u) bpp(%u)",
  610. pCursorHdr->cx,
  611. pCursorHdr->cy,
  612. pCursorHdr->cbMaskRowWidth,
  613. pCursorHdr->cPlanes,
  614. pCursorHdr->cBitsPerPel));
  615. cbANDMaskSize = CURSOR_AND_MASK_SIZE(pCursor);
  616. cbXORBitmapSize = CURSOR_XOR_BITMAP_SIZE(pCursor);
  617. /************************************************************************/
  618. /* Copy the AND mask - this is always mono. */
  619. /* */
  620. /* The AND mask is currently in top-down format (the top row of the */
  621. /* bitmap comes first). */
  622. /* */
  623. /* The protocol sends bitmaps in Device Independent format, which is */
  624. /* bottom-up. We therefore have to flip the rows as we copy the mask. */
  625. /************************************************************************/
  626. cbANDMaskRowWidth = pCursorHdr->cbMaskRowWidth;
  627. cbSrcRowOffset = 0;
  628. cbDstRowOffset = cbANDMaskRowWidth * (pCursorHdr->cy-1);
  629. for (y = 0; y < pCursorHdr->cy; y++)
  630. {
  631. memcpy( pANDMask + cbDstRowOffset,
  632. pCursor->Masks + cbSrcRowOffset,
  633. cbANDMaskRowWidth );
  634. cbSrcRowOffset += cbANDMaskRowWidth;
  635. cbDstRowOffset -= cbANDMaskRowWidth;
  636. }
  637. /************************************************************************/
  638. /* Copy the XOR mask a row at a time. It starts at the end of the AND */
  639. /* mask in the source data */
  640. /************************************************************************/
  641. cbXORBitmapRowWidth = CURSOR_DIB_BITS_SIZE(pCursor->hdr.cx, 1,
  642. pCursor->hdr.cBitsPerPel);
  643. cbSrcRowOffset = cbANDMaskSize;
  644. cbDstRowOffset = cbXORBitmapRowWidth * (pCursorHdr->cy-1);
  645. for (y = 0; y < pCursorHdr->cy; y++)
  646. {
  647. memcpy( pXORBitmap + cbDstRowOffset,
  648. pCursor->Masks + cbSrcRowOffset,
  649. cbXORBitmapRowWidth );
  650. cbSrcRowOffset += pCursorHdr->cbColorRowWidth;
  651. cbDstRowOffset -= cbXORBitmapRowWidth;
  652. }
  653. TRC_NRM((TB, "XOR data len %d", cbXORBitmapSize ));
  654. TRC_DATA_NRM("XOR data", pXORBitmap, cbXORBitmapSize);
  655. *pcbANDMask = (UINT16) CURSOR_AND_MASK_SIZE(pCursor);
  656. *pcbXORBitmap = (UINT16) CURSOR_XOR_BITMAP_SIZE(pCursor);
  657. DC_END_FN();
  658. }