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.

1731 lines
76 KiB

  1. /****************************************************************************/
  2. // asbcapi.cpp
  3. //
  4. // Send Bitmap Cache API functions.
  5. //
  6. // Copyright(c) Microsoft, PictureTel 1992-1997
  7. // (C) 1997-2000 Microsoft Corp.
  8. /****************************************************************************/
  9. #include <precomp.h>
  10. #pragma hdrstop
  11. #define TRC_FILE "asbcapi"
  12. #include <as_conf.hpp>
  13. /****************************************************************************/
  14. // SBC_Init(): Initializes the SBC.
  15. //
  16. // Returns: FALSE on failure to initialize.
  17. /****************************************************************************/
  18. void RDPCALL SHCLASS SBC_Init(void)
  19. {
  20. long cachingDisabled;
  21. TS_BITMAPCACHE_CAPABILITYSET_HOSTSUPPORT HostCaps;
  22. DC_BEGIN_FN("SBC_Init");
  23. // This initializes all the global data for this component.
  24. #define DC_INIT_DATA
  25. #include <asbcdata.c>
  26. #undef DC_INIT_DATA
  27. COM_ReadProfInt32(m_pTSWd,
  28. SBC_INI_CACHING_DISABLED,
  29. SBC_DEFAULT_CACHING_DISABLED,
  30. &cachingDisabled);
  31. sbcBitmapCachingEnabled = !(cachingDisabled & SBC_DISABLE_BITMAP_CACHE);
  32. sbcBrushCachingEnabled = !(cachingDisabled & SBC_DISABLE_BRUSH_CACHE);
  33. sbcGlyphCachingEnabled = !(cachingDisabled & SBC_DISABLE_GLYPH_CACHE);
  34. sbcOffscreenCachingEnabled = !(cachingDisabled & SBC_DISABLE_OFFSCREEN_CACHE);
  35. #ifdef DRAW_GDIPLUS
  36. #ifdef DRAW_NINEGRID
  37. sbcDrawNineGridCachingEnabled = !(cachingDisabled & SBC_DISABLE_DRAWNINEGRID_CACHE);
  38. sbcDrawGdiplusEnabled = !(cachingDisabled & SBC_DISABLE_DRAWGDIPLUS_CACHE);
  39. TRC_NRM((TB, "Caches enabled: Bitmap=%u, Brush=%u, Glyph=%u, Offscreen=%u, DNG=%u, GDIP=%u",
  40. sbcBitmapCachingEnabled,
  41. sbcBrushCachingEnabled,
  42. sbcGlyphCachingEnabled,
  43. sbcOffscreenCachingEnabled,
  44. sbcDrawNineGridCachingEnabled,
  45. sbcDrawGdiplusEnabled));
  46. #else
  47. sbcDrawGdiplusEnabled = !(cachingDisabled & SBC_DISABLE_DRAWGDIPLUS_CACHE);
  48. TRC_NRM((TB, "Caches enabled: Bitmap=%u, Brush=%u, Glyph=%u, Offscreen=%u",
  49. sbcBitmapCachingEnabled,
  50. sbcBrushCachingEnabled,
  51. sbcGlyphCachingEnabled,
  52. sbcOffscreenCachingEnabled));
  53. #endif // DRAW_NINEGRID
  54. #else // DRAW_GDIPLUS
  55. #ifdef DRAW_NINEGRID
  56. sbcDrawNineGridCachingEnabled = !(cachingDisabled & SBC_DISABLE_DRAWNINEGRID_CACHE);
  57. TRC_NRM((TB, "Caches enabled: Bitmap=%u, Brush=%u, Glyph=%u, Offscreen=%u, DNG=%u",
  58. sbcBitmapCachingEnabled,
  59. sbcBrushCachingEnabled,
  60. sbcGlyphCachingEnabled,
  61. sbcOffscreenCachingEnabled,
  62. sbcDrawNineGridCachingEnabled));
  63. #else
  64. TRC_NRM((TB, "Caches enabled: Bitmap=%u, Brush=%u, Glyph=%u, Offscreen=%u",
  65. sbcBitmapCachingEnabled,
  66. sbcBrushCachingEnabled,
  67. sbcGlyphCachingEnabled,
  68. sbcOffscreenCachingEnabled));
  69. #endif // DRAW_NINEGRID
  70. #endif // DRAW_GDIPLUS
  71. // The server supports rev2 bitmap caching. Indicate this support with a
  72. // client-to-server capability so the client can respond in kind.
  73. HostCaps.capabilitySetType = TS_CAPSETTYPE_BITMAPCACHE_HOSTSUPPORT;
  74. HostCaps.lengthCapability = sizeof(HostCaps);
  75. HostCaps.CacheVersion = TS_BITMAPCACHE_REV2;
  76. HostCaps.Pad1 = 0;
  77. HostCaps.Pad2 = 0;
  78. CPC_RegisterCapabilities((PTS_CAPABILITYHEADER)&HostCaps,
  79. sizeof(TS_BITMAPCACHE_CAPABILITYSET_HOSTSUPPORT));
  80. TRC_NRM((TB, "SBC initialized OK"));
  81. DC_END_FN();
  82. }
  83. /****************************************************************************/
  84. // SBC_Term(): Terminates the SBC.
  85. /****************************************************************************/
  86. void RDPCALL SHCLASS SBC_Term(void)
  87. {
  88. DC_BEGIN_FN("SBC_Term");
  89. SBC_FreeBitmapKeyDatabase();
  90. DC_END_FN();
  91. }
  92. /****************************************************************************/
  93. // SBC_SyncUpdatesNow: Called to force a sync, which clears all caches.
  94. /****************************************************************************/
  95. void RDPCALL SHCLASS SBC_SyncUpdatesNow(void)
  96. {
  97. DC_BEGIN_FN("SBC_SyncUpdatesNow");
  98. #ifdef DRAW_GDIPLUS
  99. #ifdef DRAW_NINEGRID
  100. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled ||
  101. sbcBrushCachingEnabled || sbcOffscreenCachingEnabled ||
  102. sbcDrawNineGridCachingEnabled || sbcDrawGdiplusEnabled) {
  103. #else
  104. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled ||
  105. sbcBrushCachingEnabled || sbcOffscreenCachingEnabled ||
  106. sbcDrawGdiplusEnabled) {
  107. #endif // DRAW_NINEGRID
  108. #else // DRAW_GDIPLUS
  109. #ifdef DRAW_NINEGRID
  110. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled ||
  111. sbcBrushCachingEnabled || sbcOffscreenCachingEnabled ||
  112. sbcDrawNineGridCachingEnabled) {
  113. #else
  114. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled ||
  115. sbcBrushCachingEnabled || sbcOffscreenCachingEnabled) {
  116. #endif // DRAW_NINEGRID
  117. #endif // DRAW_GDIPLUS
  118. sbcSyncRequired = TRUE;
  119. DCS_TriggerUpdateShmCallback();
  120. }
  121. DC_END_FN();
  122. }
  123. /****************************************************************************/
  124. // SBC_DumpBitmapKeyDatabase
  125. //
  126. // Allocates a key database and fills it in with the current contents of
  127. // the bitmap caches.
  128. /****************************************************************************/
  129. void RDPCALL SHCLASS SBC_DumpBitmapKeyDatabase(BOOLEAN bSaveDatabase)
  130. {
  131. unsigned i, j;
  132. unsigned TotalEntries, CurEntry;
  133. CHNODE *pNode;
  134. DC_BEGIN_FN("SBC_DumpBitmapKeyDatabase");
  135. // If we have a previous database, possibly from the original client
  136. // persistent key upload, destroy it.
  137. SBC_FreeBitmapKeyDatabase();
  138. // Count up the total number of entries we will need if preserving the key
  139. // database. For shadows, this information is always discarded.
  140. TotalEntries = 0;
  141. if (bSaveDatabase) {
  142. for (i = 0; i < m_pShm->sbc.NumBitmapCaches; i++)
  143. if (m_pShm->sbc.bitmapCacheInfo[i].cacheHandle != NULL)
  144. TotalEntries += CH_GetNumEntries(m_pShm->sbc.bitmapCacheInfo[i].
  145. cacheHandle);
  146. }
  147. if (TotalEntries > 0) {
  148. // Allocate the database.
  149. sbcKeyDatabaseSize = sizeof(SBC_BITMAP_CACHE_KEY_INFO) + (TotalEntries - 1) *
  150. sizeof(SBC_MRU_KEY);
  151. sbcKeyDatabase = (SBC_BITMAP_CACHE_KEY_INFO *)COM_Malloc(sbcKeyDatabaseSize);
  152. if (sbcKeyDatabase != NULL) {
  153. sbcKeyDatabase->TotalKeys = TotalEntries;
  154. // Fill in the database from each cache.
  155. CurEntry = 0;
  156. for (i = 0; i < m_pShm->sbc.NumBitmapCaches; i++) {
  157. sbcKeyDatabase->NumKeys[i] = CH_GetNumEntries(m_pShm->sbc.
  158. bitmapCacheInfo[i].cacheHandle);
  159. sbcKeyDatabase->KeyStart[i] = CurEntry;
  160. SBC_DumpMRUList(m_pShm->sbc.bitmapCacheInfo[i].cacheHandle,
  161. &(sbcKeyDatabase->Keys[sbcKeyDatabase->KeyStart[i]]));
  162. CurEntry += sbcKeyDatabase->NumKeys[i];
  163. }
  164. // Fill in remainder of pointers and info with zeros to indicate
  165. // nothing there.
  166. for (; i < TS_BITMAPCACHE_MAX_CELL_CACHES; i++) {
  167. sbcKeyDatabase->NumKeys[i] = 0;
  168. sbcKeyDatabase->KeyStart[i] = 0;
  169. }
  170. }
  171. else {
  172. // Not allocating the database is an error, but not fatal, since
  173. // it just means that the caches will be cleared instead of being
  174. // initialized.
  175. TRC_ERR((TB,"Failed to allocate key database"));
  176. sbcKeyDatabaseSize = 0;
  177. }
  178. }
  179. DC_END_FN();
  180. }
  181. /****************************************************************************/
  182. // SBC_DumpMRUList
  183. //
  184. // Walks a cache MRU list and dumps the keys and indices to an
  185. // SBC_MRU_KEY array.
  186. /****************************************************************************/
  187. void RDPCALL SHCLASS SBC_DumpMRUList(CHCACHEHANDLE hCache, void *pList)
  188. {
  189. CHNODE *pNode;
  190. unsigned CurEntry;
  191. PLIST_ENTRY pCurrentListEntry;
  192. SBC_MRU_KEY *pKeys = (SBC_MRU_KEY *)pList;
  193. PCHCACHEDATA pCacheData;
  194. DC_BEGIN_FN("SBC_DumpMRUList");
  195. pCacheData = (CHCACHEDATA *)hCache;
  196. CurEntry = 0;
  197. pCurrentListEntry = pCacheData->MRUList.Flink;
  198. while (pCurrentListEntry != &pCacheData->MRUList) {
  199. pNode = CONTAINING_RECORD(pCurrentListEntry, CHNODE, MRUList);
  200. pKeys[CurEntry].Key1 = pNode->Key1;
  201. pKeys[CurEntry].Key2 = pNode->Key2;
  202. pKeys[CurEntry].CacheIndex = (unsigned)(pNode - pCacheData->NodeArray);
  203. CurEntry++;
  204. pCurrentListEntry = pCurrentListEntry->Flink;
  205. }
  206. TRC_ASSERT((CurEntry == pCacheData->NumEntries),
  207. (TB,"NumEntries (%u) != # entries in MRU list (%u)",
  208. pCacheData->NumEntries, CurEntry));
  209. DC_END_FN();
  210. }
  211. /****************************************************************************/
  212. // SBC_PartyJoiningShare: Called when a new party is joining the share.
  213. //
  214. // Params:
  215. // locPersonID - local person ID of remote person joining the share.
  216. // oldShareSize - the number of the parties which were in the share (ie
  217. // excludes the joining party).
  218. //
  219. // Returns: TRUE if the party can join the share, FALSE otherwise.
  220. /****************************************************************************/
  221. BOOLEAN RDPCALL SHCLASS SBC_PartyJoiningShare(
  222. LOCALPERSONID locPersonID,
  223. unsigned oldShareSize)
  224. {
  225. DC_BEGIN_FN("SBC_PartyJoiningShare");
  226. DC_IGNORE_PARAMETER(oldShareSize);
  227. TRC_NRM((TB, "[%x] joining share", locPersonID));
  228. #ifdef DRAW_GDIPLUS
  229. #ifdef DRAW_NINEGRID
  230. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  231. sbcOffscreenCachingEnabled || sbcDrawNineGridCachingEnabled || sbcDrawGdiplusEnabled) {
  232. #else
  233. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  234. sbcOffscreenCachingEnabled || sbcDrawGdiplusEnabled) {
  235. #endif // DRAW_NINEGRID
  236. #else // DRAW_GDIPLUS
  237. #ifdef DRAW_NINEGRID
  238. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  239. sbcOffscreenCachingEnabled || sbcDrawNineGridCachingEnabled) {
  240. #else
  241. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  242. sbcOffscreenCachingEnabled) {
  243. #endif // DRAW_NINEGRID
  244. #endif // DRAW_GDIPLUS
  245. // Local server does not require new action.
  246. if (locPersonID != SC_LOCAL_PERSON_ID) {
  247. sbcCachingOn = TRUE;
  248. sbcNewCapsData = TRUE;
  249. // Redetermine the size of the bitmap cache.
  250. if (sbcBitmapCachingEnabled)
  251. SBCRedetermineBitmapCacheSize();
  252. // Redetermine the size of the glyph cache.
  253. if (sbcGlyphCachingEnabled)
  254. SBCRedetermineGlyphCacheSize();
  255. // Redetermine the brush support level
  256. if (sbcBrushCachingEnabled)
  257. SBCRedetermineBrushSupport();
  258. // Redetermine the offscreen support level
  259. if (sbcOffscreenCachingEnabled) {
  260. SBCRedetermineOffscreenSupport();
  261. }
  262. #ifdef DRAW_NINEGRID
  263. // Redetermine the drawninegrid support level
  264. if (sbcDrawNineGridCachingEnabled) {
  265. SBCRedetermineDrawNineGridSupport();
  266. }
  267. #endif
  268. #ifdef DRAW_GDIPLUS
  269. if (sbcDrawGdiplusEnabled) {
  270. SBCRedetermineDrawGdiplusSupport();
  271. }
  272. #endif
  273. // Force a callback on the WinStation context so we can update
  274. // the shared memory.
  275. DCS_TriggerUpdateShmCallback();
  276. }
  277. }
  278. DC_END_FN();
  279. return TRUE;
  280. }
  281. /****************************************************************************/
  282. // SBC_PartyLeftShare(): Called when a party has left the share.
  283. //
  284. // Params:
  285. // locPersonID - local person ID of remote person leaving the share.
  286. // newShareSize - the number of the parties now in the call (ie excludes
  287. // the leaving party).
  288. /****************************************************************************/
  289. void RDPCALL SHCLASS SBC_PartyLeftShare(
  290. LOCALPERSONID locPersonID,
  291. unsigned newShareSize)
  292. {
  293. DC_BEGIN_FN("SBC_PartyLeftShare");
  294. DC_IGNORE_PARAMETER(newShareSize);
  295. TRC_NRM((TB, "[%x] left share", locPersonID));
  296. // Must have active caches
  297. #ifdef DRAW_GDIPLUS
  298. #ifdef DRAW_NINEGRID
  299. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  300. sbcOffscreenCachingEnabled || sbcDrawNineGridCachingEnabled || sbcDrawGdiplusEnabled) {
  301. #else
  302. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  303. sbcOffscreenCachingEnabled || sbcDrawGdiplusEnabled) {
  304. #endif // DRAW_NINEGRID
  305. #else // DRAW_GDIPLUS
  306. #ifdef DRAW_NINEGRID
  307. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  308. sbcOffscreenCachingEnabled || sbcDrawNineGridCachingEnabled) {
  309. #else
  310. if (sbcBitmapCachingEnabled || sbcGlyphCachingEnabled || sbcBrushCachingEnabled ||
  311. sbcOffscreenCachingEnabled) {
  312. #endif // DRAW_NINEGRID
  313. #endif // DRAW_GDIPLUS
  314. // If all people left the share then disable caching.
  315. if (locPersonID == SC_LOCAL_PERSON_ID) {
  316. TRC_NRM((TB, "Disable caching"));
  317. sbcCachingOn = FALSE;
  318. sbcNewCapsData = TRUE;
  319. // Force a callback on the WinStation context so we can update the
  320. // shared memory.
  321. DCS_TriggerUpdateShmCallback();
  322. }
  323. // Else, look thru the capabilities again to see what's possible
  324. else {
  325. sbcCachingOn = TRUE;
  326. sbcNewCapsData = TRUE;
  327. // Redetermine the size of the bitmap cache.
  328. if (sbcBitmapCachingEnabled)
  329. SBCRedetermineBitmapCacheSize();
  330. // Redetermine the size of the glyph cache.
  331. if (sbcGlyphCachingEnabled)
  332. SBCRedetermineGlyphCacheSize();
  333. // Redetermine the brush support level
  334. if (sbcBrushCachingEnabled)
  335. SBCRedetermineBrushSupport();
  336. // Redetermine the offscreen support level
  337. if (sbcOffscreenCachingEnabled) {
  338. SBCRedetermineOffscreenSupport();
  339. }
  340. #ifdef DRAW_NINEGRID
  341. // Redetermine the drawninegrid support level
  342. if (sbcDrawNineGridCachingEnabled) {
  343. SBCRedetermineDrawNineGridSupport();
  344. }
  345. #endif
  346. #ifdef DRAW_GDIPLUS
  347. if (sbcDrawGdiplusEnabled) {
  348. SBCRedetermineDrawGdiplusSupport();
  349. }
  350. #endif
  351. // TODO: Is this really necessary?
  352. DCS_TriggerUpdateShmCallback();
  353. }
  354. }
  355. DC_END_FN();
  356. }
  357. /****************************************************************************/
  358. // SBC_HandlePersistentCacheList(): Handles list of persistent cache keys
  359. // from the client.
  360. /****************************************************************************/
  361. void RDPCALL SHCLASS SBC_HandlePersistentCacheList(
  362. TS_BITMAPCACHE_PERSISTENT_LIST *pPDU,
  363. unsigned DataLength,
  364. LOCALPERSONID LocalID)
  365. {
  366. unsigned i, j, CurEntry;
  367. INT TotalEntries;
  368. DC_BEGIN_FN("SBC_HandlePersistentCacheList");
  369. // Check the packet length against its internal representation, make sure
  370. // it is as long as it needs to be. If not, we either received a buggy
  371. // packet or we're being attacked.
  372. if (DataLength >= (sizeof(TS_BITMAPCACHE_PERSISTENT_LIST) -
  373. sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY))) {
  374. if (pPDU->bFirstPDU) {
  375. // Check that we have not already received persistent key info.
  376. // If we have and we get a new PDU, it is a protocol error.
  377. if (sbcPersistentKeysReceived) {
  378. TRC_ERR((TB,"Persistent key packet received marked FIRST "
  379. "illegally"));
  380. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  381. Log_RDP_PersistentKeyPDUIllegalFIRST,
  382. (PBYTE)pPDU, DataLength);
  383. goto ExitFunc;
  384. }
  385. // Get the total number of entries from the PDU array. Check
  386. // against the negotiated caps and make sure the client is not
  387. // trying to send too many.
  388. TotalEntries = 0;
  389. for (i = 0; i < TS_BITMAPCACHE_MAX_CELL_CACHES; i++) {
  390. TotalEntries += pPDU->TotalEntries[i];
  391. if (pPDU->TotalEntries[i] > sbcCurrentBitmapCaps.
  392. CellCacheInfo[i].NumEntries) {
  393. TRC_ERR((TB,"Persistent key packet received specified "
  394. "more keys (%u) than there are cache entries (%u) "
  395. "for cache %u", pPDU->TotalEntries[i],
  396. sbcCurrentBitmapCaps.CellCacheInfo[i].NumEntries,
  397. i));
  398. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  399. Log_RDP_PersistentKeyPDUTooManyCacheKeys,
  400. (PBYTE)pPDU, DataLength);
  401. goto ExitFunc;
  402. }
  403. }
  404. // Check if we receive 0 keys, in this case, we will just exit the
  405. // function quietly
  406. if (TotalEntries == 0) {
  407. TRC_ERR((TB, "0 persistent key"));
  408. goto ExitFunc;
  409. }
  410. // Check this against the max allowed by the protocol.
  411. if (TotalEntries > TS_BITMAPCACHE_MAX_TOTAL_PERSISTENT_KEYS) {
  412. TRC_ERR((TB,"Client specified %u total keys, beyond %u "
  413. "protocol limit", TotalEntries,
  414. TS_BITMAPCACHE_MAX_TOTAL_PERSISTENT_KEYS));
  415. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  416. Log_RDP_PersistentKeyPDUTooManyTotalKeys,
  417. (PBYTE)pPDU, DataLength);
  418. goto ExitFunc;
  419. }
  420. sbcKeyDatabaseSize = sizeof(SBC_BITMAP_CACHE_KEY_INFO) + (TotalEntries - 1) *
  421. sizeof(SBC_MRU_KEY);
  422. sbcKeyDatabase = (SBC_BITMAP_CACHE_KEY_INFO *)COM_Malloc(sbcKeyDatabaseSize);
  423. if (sbcKeyDatabase == NULL) {
  424. sbcKeyDatabaseSize = 0;
  425. TRC_ERR((TB,"Could not alloc persistent key info"));
  426. goto ExitFunc;
  427. }
  428. // Set up general data and entry pointers within the key array.
  429. CurEntry = 0;
  430. for (i = 0; i < TS_BITMAPCACHE_MAX_CELL_CACHES; i++) {
  431. sbcKeyDatabase->KeyStart[i] = CurEntry;
  432. CurEntry += pPDU->TotalEntries[i];
  433. sbcKeyDatabase->NumKeys[i] = 0;
  434. sbcNumKeysExpected[i] = pPDU->TotalEntries[i];
  435. }
  436. sbcTotalKeysExpected = TotalEntries;
  437. sbcKeyDatabase->TotalKeys = 0;
  438. // Mark that we have received the first-keys packet.
  439. sbcPersistentKeysReceived = TRUE;
  440. }
  441. // If this is not the first PDU but we failed a previous allocation,
  442. // too bad, no persistent keys. This could also happen if the client
  443. // continues sending persistent cache keys after sending the
  444. // TS_BITMAPCACHE_LAST_OVERALL flag that indicates the end of the key
  445. // packet stream.
  446. if (sbcKeyDatabase == NULL)
  447. goto ExitFunc;
  448. // Total the supposed number of keys received in the PDU. Check against
  449. // the PDU size.
  450. TotalEntries = 0;
  451. for (i = 0; i < TS_BITMAPCACHE_MAX_CELL_CACHES; i++)
  452. TotalEntries += pPDU->NumEntries[i];
  453. if (DataLength < (sizeof(TS_BITMAPCACHE_PERSISTENT_LIST) +
  454. (TotalEntries - 1) *
  455. sizeof(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY))) {
  456. TRC_ERR((TB,"Client specified %u keys in this PersistentListPDU, "
  457. "PDU data not long enough", TotalEntries));
  458. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  459. Log_RDP_PersistentKeyPDUBadLength,
  460. (PBYTE)pPDU, DataLength);
  461. goto ExitFunc;
  462. }
  463. // Loop across the caches to check each one.
  464. CurEntry = 0;
  465. for (i = 0; i < TS_BITMAPCACHE_MAX_CELL_CACHES; i++) {
  466. // Make sure that we don't receive more keys than were specified in
  467. // the original PDU.
  468. if ((sbcKeyDatabase->NumKeys[i] + pPDU->NumEntries[i]) <=
  469. sbcNumKeysExpected[i]) {
  470. // Transfer keys into the key list. We set these up for the MRU
  471. // list in the same order received since the client does not
  472. // have any MRU priority info to give us.
  473. for (j = 0; j < pPDU->NumEntries[i]; j++) {
  474. (&(sbcKeyDatabase->Keys[sbcKeyDatabase->KeyStart[i]]))
  475. [sbcKeyDatabase->NumKeys[i] + j].Key1 =
  476. pPDU->Entries[CurEntry].Key1;
  477. (&(sbcKeyDatabase->Keys[sbcKeyDatabase->KeyStart[i]]))
  478. [sbcKeyDatabase->NumKeys[i] + j].Key2 =
  479. pPDU->Entries[CurEntry].Key2;
  480. (&(sbcKeyDatabase->Keys[sbcKeyDatabase->KeyStart[i]]))
  481. [sbcKeyDatabase->NumKeys[i] + j].CacheIndex =
  482. sbcKeyDatabase->NumKeys[i] + j;
  483. CurEntry++;
  484. }
  485. sbcKeyDatabase->NumKeys[i] += pPDU->NumEntries[i];
  486. sbcKeyDatabase->TotalKeys += pPDU->NumEntries[i];
  487. }
  488. else {
  489. TRC_ERR((TB,"Received too many keys in cache %u", i));
  490. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  491. Log_RDP_PersistentKeyPDUTooManyCacheKeys,
  492. (PBYTE)pPDU, DataLength);
  493. goto ExitFunc;
  494. }
  495. }
  496. if (pPDU->bLastPDU) {
  497. // This is an assertion but not fatal -- we simply use what we
  498. // received.
  499. TRC_ASSERT((sbcKeyDatabase->TotalKeys == sbcTotalKeysExpected),
  500. (TB,"Num expected persistent keys does not match sent keys "
  501. "(rec'd=%d, expect=%d)", sbcKeyDatabase->TotalKeys,
  502. sbcTotalKeysExpected));
  503. }
  504. }
  505. else {
  506. TRC_ERR((TB,"Persistent key PDU received but data is not long enough "
  507. "for header, LocalID=%u", LocalID));
  508. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_PersistentKeyPDUBadLength,
  509. (PBYTE)pPDU, DataLength);
  510. }
  511. ExitFunc:
  512. DC_END_FN();
  513. }
  514. /****************************************************************************/
  515. // Returns the persistent key database to the DD and free the local copy
  516. /****************************************************************************/
  517. void RDPCALL SHCLASS SBC_GetBitmapKeyDatabase(unsigned* keyDBSize,
  518. BYTE* pKeyDB)
  519. {
  520. unsigned i, CurEntry;
  521. SBC_BITMAP_CACHE_KEY_INFO* pKeyDatabase;
  522. DC_BEGIN_FN("SBC_GetBitmapKeyDatabase");
  523. // No persistent key database setup
  524. if ( sbcKeyDatabaseSize == 0 || sbcKeyDatabase == NULL) {
  525. TRC_NRM((TB, "Failed to get the key database: dd keysize=%d, wd keysize=%d, keydatabase=%p",
  526. *keyDBSize, sbcKeyDatabaseSize, sbcKeyDatabase));
  527. *keyDBSize = 0;
  528. DC_QUIT;
  529. }
  530. // DD's buffer is too small
  531. if (*keyDBSize < sbcKeyDatabaseSize) {
  532. TRC_NRM((TB, "Failed to get the key database: dd keysize=%d, wd keysize=%d, keydatabase=%p",
  533. *keyDBSize, sbcKeyDatabaseSize, sbcKeyDatabase));
  534. *keyDBSize = sbcKeyDatabaseSize;
  535. DC_QUIT;
  536. }
  537. TRC_NRM((TB, "get bitmapKeyDatabase: copy keys from wd to dd"));
  538. pKeyDatabase = (SBC_BITMAP_CACHE_KEY_INFO*)(pKeyDB);
  539. memcpy(pKeyDatabase, sbcKeyDatabase, sbcKeyDatabaseSize);
  540. *keyDBSize = sbcKeyDatabaseSize;
  541. SBC_FreeBitmapKeyDatabase();
  542. DC_EXIT_POINT:
  543. return;
  544. }
  545. /****************************************************************************/
  546. // Free the key databaes
  547. /****************************************************************************/
  548. void RDPCALL SHCLASS SBC_FreeBitmapKeyDatabase()
  549. {
  550. if (sbcKeyDatabase != NULL) {
  551. COM_Free(sbcKeyDatabase);
  552. sbcKeyDatabase = NULL;
  553. }
  554. sbcKeyDatabaseSize = 0;
  555. }
  556. /****************************************************************************/
  557. // SBC_HandleBitmapCacheErrorPDU: Handles a bitmap cache error PDU.
  558. // Right now this function just checks the length of the PDU to make
  559. // sure it is valid. If not, the server close the client connection
  560. // This function is for future support of error PDU implementation
  561. /****************************************************************************/
  562. void RDPCALL SHCLASS SBC_HandleBitmapCacheErrorPDU(
  563. TS_BITMAPCACHE_ERROR_PDU *pPDU,
  564. unsigned DataLength,
  565. LOCALPERSONID LocalID)
  566. {
  567. unsigned i;
  568. DC_BEGIN_FN("SBC_HandleBitmapCacheErrorPDU");
  569. if (DataLength >= (sizeof(TS_BITMAPCACHE_ERROR_PDU) -
  570. sizeof(TS_BITMAPCACHE_ERROR_INFO))) {
  571. if ((sizeof(TS_BITMAPCACHE_ERROR_PDU) - sizeof(TS_BITMAPCACHE_ERROR_INFO)
  572. + pPDU->NumInfoBlocks * sizeof(TS_BITMAPCACHE_ERROR_INFO))
  573. == DataLength) {
  574. TRC_NRM((TB, "Received a bitmap cache error PDU"));
  575. // update the total number of error pdus received
  576. sbcTotalNumErrorPDUs++;
  577. // For the duration of a session, we will only handle maximum
  578. // MAX_NUM_ERROR_PDU_SEND numbers of error PDUs received.
  579. // This is to avoid bad clients attack the server with error pdu
  580. if (sbcTotalNumErrorPDUs <= MAX_NUM_ERROR_PDU_SEND) {
  581. for (i = 0; i < pPDU->NumInfoBlocks; i++) {
  582. if (pPDU->Info[i].CacheID < sbcCurrentBitmapCaps.NumCellCaches) {
  583. // For now, the server only handles the client clear cache
  584. // request. Server will clear the cache and then issue a screen
  585. // redraw. The server doesn't handle if the client requests to
  586. // resize the cache.
  587. sbcClearCache[pPDU->Info[i].CacheID] = pPDU->Info[i].bFlushCache;
  588. }
  589. }
  590. TRC_DBG((TB, "Issued clear cache to RDPDD"));
  591. // trigger a timer so that when DD gets it, it will clear the cache.
  592. DCS_TriggerUpdateShmCallback();
  593. }
  594. else {
  595. TRC_DBG((TB, "Received more than %d bitmap error pdus.",
  596. MAX_NUM_ERROR_PDU_SEND));
  597. }
  598. }
  599. else {
  600. TRC_ERR((TB,"Bitmap Cache Error PDU received but data Length is wrong, "
  601. "too many or too few info blocks, LocalID=%u", LocalID));
  602. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_BitmapCacheErrorPDUBadLength,
  603. (PBYTE)pPDU, DataLength);
  604. }
  605. }
  606. else {
  607. TRC_ERR((TB,"Bitmap Cache Error PDU received but data is not long enough "
  608. "for header, LocalID=%u", LocalID));
  609. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_BitmapCacheErrorPDUBadLength,
  610. (PBYTE)pPDU, DataLength);
  611. }
  612. DC_END_FN();
  613. }
  614. /****************************************************************************/
  615. // SBC_HandleOffscrCacheErrorPDU: Handles an offscr cache error PDU.
  616. // This function checks the length of the PDU to make
  617. // sure it is valid. If not, the server close the client connection
  618. // When this PDU is received, WD will pass disable offscreen rendering to
  619. // DD and DD will disable the offscreen rendering support and refresh
  620. // the screen
  621. /****************************************************************************/
  622. void RDPCALL SHCLASS SBC_HandleOffscrCacheErrorPDU(
  623. TS_OFFSCRCACHE_ERROR_PDU *pPDU,
  624. unsigned DataLength,
  625. LOCALPERSONID LocalID)
  626. {
  627. DC_BEGIN_FN("SBC_HandleOffscrCacheErrorPDU");
  628. if (DataLength >= sizeof(TS_OFFSCRCACHE_ERROR_PDU)) {
  629. TRC_NRM((TB, "Received an offscreen cache error PDU"));
  630. if (pPDU->flags & TS_FLUSH_AND_DISABLE_OFFSCREEN) {
  631. TRC_DBG((TB, "Issued clear cache to RDPDD"));
  632. sbcDisableOffscreenCaching = TRUE;
  633. // trigger a timer so that when DD gets it, it will disable
  634. // offscreen rendering and refresh the screen
  635. DCS_TriggerUpdateShmCallback();
  636. }
  637. else {
  638. TRC_DBG((TB, "Unsupported flag, just ignore this PDU"));
  639. }
  640. }
  641. else {
  642. TRC_ERR((TB,"Offscr Cache Error PDU received but data is not long enough "
  643. "for header, LocalID=%u", LocalID));
  644. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_BitmapCacheErrorPDUBadLength,
  645. (PBYTE)pPDU, DataLength);
  646. }
  647. DC_END_FN();
  648. }
  649. #ifdef DRAW_NINEGRID
  650. /****************************************************************************/
  651. // SBC_HandleDrawNineGridErrorPDU: Handles a drawninegrid cache error PDU.
  652. // This function checks the length of the PDU to make
  653. // sure it is valid. If not, the server close the client connection
  654. // When this PDU is received, WD will pass disable drawninegrid rendering to
  655. // DD and DD will disable the drawninegrid rendering support and refresh
  656. // the screen
  657. /****************************************************************************/
  658. void RDPCALL SHCLASS SBC_HandleDrawNineGridErrorPDU(
  659. TS_DRAWNINEGRID_ERROR_PDU *pPDU,
  660. unsigned DataLength,
  661. LOCALPERSONID LocalID)
  662. {
  663. DC_BEGIN_FN("SBC_HandleDrawNineGridErrorPDU");
  664. if (DataLength >= sizeof(TS_DRAWNINEGRID_ERROR_PDU)) {
  665. TRC_NRM((TB, "Received an drawninegrid cache error PDU"));
  666. if (pPDU->flags & TS_FLUSH_AND_DISABLE_DRAWNINEGRID) {
  667. TRC_DBG((TB, "Issued clear cache to RDPDD"));
  668. sbcDisableDrawNineGridCaching = TRUE;
  669. // trigger a timer so that when DD gets it, it will disable
  670. // drawninegrid rendering and refresh the screen
  671. DCS_TriggerUpdateShmCallback();
  672. }
  673. else {
  674. TRC_DBG((TB, "Unsupported flag, just ignore this PDU"));
  675. }
  676. }
  677. else {
  678. TRC_ERR((TB,"DrawNineGrid Cache Error PDU received but data is not long enough "
  679. "for header, LocalID=%u", LocalID));
  680. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_BitmapCacheErrorPDUBadLength,
  681. (PBYTE)pPDU, DataLength);
  682. }
  683. DC_END_FN();
  684. }
  685. #endif
  686. #ifdef DRAW_GDIPLUS
  687. void RDPCALL SHCLASS SBC_HandleDrawGdiplusErrorPDU(
  688. TS_DRAWGDIPLUS_ERROR_PDU *pPDU,
  689. unsigned DataLength,
  690. LOCALPERSONID LocalID)
  691. {
  692. DC_BEGIN_FN("SBC_HandleDrawGdiplusErrorPDU");
  693. if (DataLength >= sizeof(TS_DRAWGDIPLUS_ERROR_PDU)) {
  694. TRC_ERR((TB, "Received a drawgdiplus error PDU"));
  695. if (pPDU->flags & TS_FLUSH_AND_DISABLE_DRAWGDIPLUS) {
  696. TRC_DBG((TB, "Issued clear cache to RDPDD"));
  697. sbcDisableDrawGdiplus = TRUE;
  698. // trigger a timer so that when DD gets it, it will disable
  699. // drawninegrid rendering and refresh the screen
  700. DCS_TriggerUpdateShmCallback();
  701. }
  702. else {
  703. TRC_DBG((TB, "Unsupported flag, just ignore this PDU"));
  704. }
  705. }
  706. else {
  707. TRC_ERR((TB,"DrawGdiplus Error PDU received but data is not long enough "
  708. "for header, LocalID=%u", LocalID));
  709. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_BitmapCacheErrorPDUBadLength,
  710. (PBYTE)pPDU, DataLength);
  711. }
  712. DC_END_FN();
  713. }
  714. #endif // DRAW_GDIPLUS
  715. /****************************************************************************/
  716. // SBC_UpdateShm: Called on WinStation context to update the SBC shared
  717. // memory.
  718. /****************************************************************************/
  719. void RDPCALL SHCLASS SBC_UpdateShm(void)
  720. {
  721. unsigned i;
  722. DC_BEGIN_FN("SBC_UpdateShm");
  723. TRC_NRM((TB, "Update SBC shm"));
  724. // Cell bitmap caches.
  725. m_pShm->sbc.NumBitmapCaches = sbcCurrentBitmapCaps.NumCellCaches;
  726. m_pShm->sbc.fClearCache = FALSE;
  727. for (i = 0; i < sbcCurrentBitmapCaps.NumCellCaches; i++) {
  728. m_pShm->sbc.bitmapCacheInfo[i].Info =
  729. sbcCurrentBitmapCaps.CellCacheInfo[i];
  730. // set the clear cache flag for all caches
  731. if (sbcClearCache[i] == TRUE) {
  732. m_pShm->sbc.fClearCache = TRUE;
  733. }
  734. m_pShm->sbc.bitmapCacheInfo[i].fClearCache = sbcClearCache[i];
  735. sbcClearCache[i] = FALSE;
  736. TRC_NRM((TB, "bitmap cell cache(%u) NumEntries(%u) CellSize(%u)",
  737. i, m_pShm->sbc.bitmapCacheInfo[i].Info.NumEntries,
  738. SBC_CellSizeFromCacheID(i)));
  739. }
  740. // Cache bitmap order style.
  741. m_pShm->sbc.bUseRev2CacheBitmapOrder =
  742. ((sbcCurrentBitmapCaps.capabilitySetType >=
  743. TS_BITMAPCACHE_REV2) ? TRUE : FALSE);
  744. // Glyph and glyph fragment caching.
  745. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++) {
  746. m_pShm->sbc.caps.glyphCacheSize[i].cEntries = sbcGlyphCacheSizes[i].cEntries;
  747. m_pShm->sbc.caps.glyphCacheSize[i].cbCellSize = sbcGlyphCacheSizes[i].cbCellSize;
  748. TRC_NRM((TB, "glyph cache(%u) entries(%u) cellSize(%u)", i,
  749. m_pShm->sbc.caps.glyphCacheSize[i].cEntries,
  750. m_pShm->sbc.caps.glyphCacheSize[i].cbCellSize));
  751. }
  752. m_pShm->sbc.caps.fragCacheSize[0].cEntries = sbcFragCacheSizes[0].cEntries;
  753. m_pShm->sbc.caps.fragCacheSize[0].cbCellSize = sbcFragCacheSizes[0].cbCellSize;
  754. m_pShm->sbc.syncRequired = (m_pShm->sbc.syncRequired || sbcSyncRequired) ?
  755. TRUE : FALSE;
  756. sbcSyncRequired = FALSE;
  757. m_pShm->sbc.fCachingEnabled = (sbcCachingOn ? TRUE : FALSE);
  758. m_pShm->sbc.caps.GlyphSupportLevel = sbcGlyphSupportLevel;
  759. m_pShm->sbc.caps.brushSupportLevel = sbcBrushSupportLevel;
  760. m_pShm->sbc.newCapsData = (m_pShm->sbc.newCapsData || sbcNewCapsData) ?
  761. TRUE : FALSE;
  762. sbcNewCapsData = FALSE;
  763. // Offscreen cache
  764. m_pShm->sbc.offscreenCacheInfo.supportLevel = sbcOffscreenCacheInfo.supportLevel;
  765. m_pShm->sbc.offscreenCacheInfo.cacheSize = sbcOffscreenCacheInfo.cacheSize;
  766. m_pShm->sbc.offscreenCacheInfo.cacheEntries = sbcOffscreenCacheInfo.cacheEntries;
  767. m_pShm->sbc.fDisableOffscreen = sbcDisableOffscreenCaching;
  768. #ifdef DRAW_NINEGRID
  769. // DrawNineGrid cache
  770. m_pShm->sbc.drawNineGridCacheInfo.supportLevel = sbcDrawNineGridCacheInfo.supportLevel;
  771. m_pShm->sbc.drawNineGridCacheInfo.cacheSize = sbcDrawNineGridCacheInfo.cacheSize;
  772. m_pShm->sbc.drawNineGridCacheInfo.cacheEntries = sbcDrawNineGridCacheInfo.cacheEntries;
  773. m_pShm->sbc.fDisableDrawNineGrid = sbcDisableDrawNineGridCaching;
  774. #endif
  775. #ifdef DRAW_GDIPLUS
  776. m_pShm->sbc.drawGdiplusInfo.supportLevel = sbcDrawGdiplusInfo.supportLevel;
  777. m_pShm->sbc.drawGdiplusInfo.GdipVersion = sbcDrawGdiplusInfo.GdipVersion;
  778. m_pShm->sbc.drawGdiplusInfo.GdipCacheLevel = sbcDrawGdiplusInfo.GdipCacheLevel;
  779. m_pShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries =
  780. sbcDrawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries;
  781. m_pShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries =
  782. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries;
  783. m_pShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries = sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries;
  784. m_pShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries =
  785. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries;
  786. m_pShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries =
  787. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries;
  788. m_pShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipGraphicsCacheChunkSize =
  789. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipGraphicsCacheChunkSize;
  790. m_pShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipObjectBrushCacheChunkSize =
  791. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectBrushCacheChunkSize;
  792. m_pShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipObjectPenCacheChunkSize =
  793. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectPenCacheChunkSize;
  794. m_pShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipObjectImageAttributesCacheChunkSize =
  795. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectImageAttributesCacheChunkSize;
  796. m_pShm->sbc.drawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheChunkSize =
  797. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheChunkSize;
  798. m_pShm->sbc.drawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheTotalSize =
  799. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheTotalSize;
  800. m_pShm->sbc.drawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheMaxSize =
  801. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheMaxSize;
  802. m_pShm->sbc.fDisableDrawGdiplus = sbcDisableDrawGdiplus;
  803. #endif // DRAW_GDIPLUS
  804. m_pShm->sbc.fAllowCacheWaitingList = sbcCurrentBitmapCaps.bAllowCacheWaitingList;
  805. #ifdef DC_HICOLOR
  806. m_pShm->sbc.clientBitsPerPel = sbcClientBitsPerPel;
  807. #endif
  808. TRC_NRM((TB, "syncRequired(%u) fCachingEnabled(%u) newCapsData(%u)",
  809. m_pShm->sbc.syncRequired,
  810. m_pShm->sbc.fCachingEnabled,
  811. m_pShm->sbc.newCapsData));
  812. DC_END_FN();
  813. }
  814. /****************************************************************************/
  815. // SBCRedetermineBitmapCacheSize: Enumerates all the people in the share and
  816. // redetermines the overall capabilities.
  817. //
  818. // Returns: TRUE if caching should be enabled, FALSE otherwise.
  819. /****************************************************************************/
  820. BOOLEAN RDPCALL SHCLASS SBCRedetermineBitmapCacheSize(void)
  821. {
  822. BOOLEAN rc = TRUE;
  823. unsigned i;
  824. DC_BEGIN_FN("SBCRedetermineBitmapCacheSize");
  825. #ifdef DC_HICOLOR
  826. // Need to update the bpp as this affects the size of the caches
  827. sbcClientBitsPerPel = m_desktopBpp;
  828. #endif
  829. // Set the initial local max/min caps to defaults.
  830. sbcCurrentBitmapCaps = sbcDefaultBitmapCaps;
  831. // First attempt to enumerate rev2 capabilities, if present.
  832. CPC_EnumerateCapabilities(TS_CAPSETTYPE_BITMAPCACHE_REV2, NULL,
  833. SBCEnumBitmapCacheCaps);
  834. // Then enumerate rev1 caps if present.
  835. CPC_EnumerateCapabilities(TS_CAPSETTYPE_BITMAPCACHE, NULL,
  836. SBCEnumBitmapCacheCaps);
  837. // Trace the results and check to see if we negotiated any of the
  838. // cell caches to zero, in which case bitmap caching becomes disabled.
  839. TRC_NRM((TB,"New caps: bPersistentLists=%s, NumCellCaches=%u",
  840. (sbcCurrentBitmapCaps.bPersistentKeysExpected ? "TRUE" : "FALSE"),
  841. sbcCurrentBitmapCaps.NumCellCaches));
  842. if (sbcCurrentBitmapCaps.NumCellCaches > 0) {
  843. for (i = 0; i < sbcCurrentBitmapCaps.NumCellCaches; i++) {
  844. TRC_NRM((TB, " Cell cache %u: Persistent=%s, NumEntries=%u",
  845. i, sbcCurrentBitmapCaps.CellCacheInfo[i].bSendBitmapKeys ?
  846. "TRUE" : "FALSE",
  847. sbcCurrentBitmapCaps.CellCacheInfo[i].NumEntries));
  848. if (sbcCurrentBitmapCaps.CellCacheInfo[i].NumEntries == 0) {
  849. // Set the number of cell caches to zero as a signal for flag-
  850. // setting when the DD calls to get the new caps.
  851. sbcCurrentBitmapCaps.NumCellCaches = 0;
  852. // Return FALSE so that caching is disabled.
  853. TRC_ERR((TB, "Zero NumEntries on cache %u, caching disabled",
  854. i));
  855. rc = FALSE;
  856. break;
  857. }
  858. }
  859. }
  860. else {
  861. // Return FALSE to disable caching.
  862. TRC_ERR((TB,"Zero caches, disabling caching"));
  863. rc = FALSE;
  864. }
  865. DC_END_FN();
  866. return rc;
  867. }
  868. /****************************************************************************/
  869. // SBCEnumBitmapCaps: Callback function passed to CPC_EnumerateCapabilities.
  870. // It will be called with a capability structure for each person in the share
  871. // corresponding to the TS_CAPSETTYPE_BITMAPCACHE and _REV2 capability
  872. // structures.
  873. //
  874. // Params:
  875. // personID - ID of person with these capabilities.
  876. // pProtCaps - pointer to capabilities structure for this person. This
  877. // pointer is only valid within the call to this function.
  878. /****************************************************************************/
  879. void RDPCALL SHCLASS SBCEnumBitmapCacheCaps(
  880. LOCALPERSONID locPersonID,
  881. UINT_PTR UserData,
  882. PTS_CAPABILITYHEADER pCapHdr)
  883. {
  884. unsigned i;
  885. #ifdef DC_HICOLOR
  886. unsigned shadowerBpp;
  887. unsigned scaleNum = 1;
  888. unsigned scaleDenom = 1;
  889. #endif
  890. DC_BEGIN_FN("SBCEnumBitmapCacheCaps");
  891. DC_IGNORE_PARAMETER(UserData);
  892. if (pCapHdr->capabilitySetType == TS_CAPSETTYPE_BITMAPCACHE_REV2) {
  893. TS_BITMAPCACHE_CAPABILITYSET_REV2 *pCaps;
  894. // We can receive a zero size for the capability if we didn't receive
  895. // any rev2 caps from any client.
  896. if (pCapHdr->lengthCapability >=
  897. sizeof(TS_BITMAPCACHE_CAPABILITYSET_REV2)) {
  898. pCaps = (PTS_BITMAPCACHE_CAPABILITYSET_REV2)pCapHdr;
  899. // Cache version defaults to rev2, we don't need to change
  900. // sbcCurrentBitmapCaps.capabilitySetType.
  901. TRC_NRM((TB,"[%ld]: Rec'd REV2 caps, # caches=%d",
  902. locPersonID, pCaps->NumCellCaches));
  903. // Now we look at each capability parameter and take the max or min
  904. // of the local and remote settings, as appropriate.
  905. sbcCurrentBitmapCaps.bPersistentKeysExpected =
  906. pCaps->bPersistentKeysExpected;
  907. sbcCurrentBitmapCaps.bAllowCacheWaitingList =
  908. min(sbcCurrentBitmapCaps.bAllowCacheWaitingList,
  909. pCaps->bAllowCacheWaitingList);
  910. sbcCurrentBitmapCaps.NumCellCaches =
  911. min(pCaps->NumCellCaches, sbcCurrentBitmapCaps.NumCellCaches);
  912. for (i = 0; i < sbcCurrentBitmapCaps.NumCellCaches; i++) {
  913. // If all parties in a share are rev2, and any client wants keys,
  914. // send them.
  915. if (!sbcCurrentBitmapCaps.CellCacheInfo[i].bSendBitmapKeys)
  916. sbcCurrentBitmapCaps.CellCacheInfo[i].bSendBitmapKeys =
  917. pCaps->CellCacheInfo[i].bSendBitmapKeys;
  918. #ifdef DC_HICOLOR
  919. sbcCurrentBitmapCaps.CellCacheInfo[i].NumEntries =
  920. min(((pCaps->CellCacheInfo[i].NumEntries * scaleNum)
  921. / scaleDenom),
  922. sbcCurrentBitmapCaps.CellCacheInfo[i].NumEntries);
  923. #else
  924. sbcCurrentBitmapCaps.CellCacheInfo[i].NumEntries =
  925. min(pCaps->CellCacheInfo[i].NumEntries,
  926. sbcCurrentBitmapCaps.CellCacheInfo[i].NumEntries);
  927. #endif
  928. }
  929. }
  930. else {
  931. TRC_NRM((TB,"[%ld]: No rev2 caps received", locPersonID));
  932. TRC_ASSERT((pCapHdr->lengthCapability == 0),
  933. (TB, "[%ld]: Rev2 capability length (%u) too small",
  934. locPersonID, pCapHdr->lengthCapability));
  935. }
  936. }
  937. else {
  938. TS_BITMAPCACHE_CAPABILITYSET *pOldCaps;
  939. TRC_ASSERT((pCapHdr->capabilitySetType == TS_CAPSETTYPE_BITMAPCACHE),
  940. (TB,"Received caps that are neither rev1 nor rev2!"));
  941. // We can receive a zero size for the capability if we didn't receive
  942. // any rev1 caps from any client.
  943. if (pCapHdr->lengthCapability >=
  944. sizeof(TS_BITMAPCACHE_CAPABILITYSET)) {
  945. // Rev 1 (Hydra 4.0 release) bitmap caching caps. Map to the
  946. // rev2 caps structure, taking min of the cell sizes and numbers
  947. // of entries.
  948. TRC_NRM((TB,"[%ld]: Rec'd REV1 caps", locPersonID));
  949. // We now have to use rev1 protocol to all clients.
  950. sbcCurrentBitmapCaps.capabilitySetType = TS_BITMAPCACHE_REV1;
  951. pOldCaps = (TS_BITMAPCACHE_CAPABILITYSET *)pCapHdr;
  952. sbcCurrentBitmapCaps.bPersistentKeysExpected = FALSE;
  953. sbcCurrentBitmapCaps.bAllowCacheWaitingList = FALSE;
  954. sbcCurrentBitmapCaps.NumCellCaches =
  955. min(3, sbcCurrentBitmapCaps.NumCellCaches);
  956. sbcCurrentBitmapCaps.CellCacheInfo[0].bSendBitmapKeys = FALSE;
  957. if (pOldCaps->Cache1MaximumCellSize == SBC_CellSizeFromCacheID(0)) {
  958. sbcCurrentBitmapCaps.CellCacheInfo[0].NumEntries =
  959. min(pOldCaps->Cache1Entries,
  960. sbcCurrentBitmapCaps.CellCacheInfo[0].NumEntries);
  961. }
  962. else {
  963. // Did not receive the required size from the client. This is
  964. // nonstandard behavior on RDP 4.0, so no problem to disable
  965. // caching. Set the NumEntries to zero to turn off caching.
  966. sbcCurrentBitmapCaps.CellCacheInfo[0].NumEntries = 0;
  967. }
  968. sbcCurrentBitmapCaps.CellCacheInfo[1].bSendBitmapKeys = FALSE;
  969. if (pOldCaps->Cache2MaximumCellSize == SBC_CellSizeFromCacheID(1)) {
  970. sbcCurrentBitmapCaps.CellCacheInfo[1].NumEntries =
  971. min(pOldCaps->Cache2Entries,
  972. sbcCurrentBitmapCaps.CellCacheInfo[1].NumEntries);
  973. }
  974. else {
  975. // Did not receive the required size from the client. This is
  976. // nonstandard behavior on RDP 4.0, so no problem to disable
  977. // caching. Set the NumEntries to zero to turn off caching.
  978. sbcCurrentBitmapCaps.CellCacheInfo[1].NumEntries = 0;
  979. }
  980. sbcCurrentBitmapCaps.CellCacheInfo[2].bSendBitmapKeys = FALSE;
  981. if (pOldCaps->Cache3MaximumCellSize == SBC_CellSizeFromCacheID(2)) {
  982. sbcCurrentBitmapCaps.CellCacheInfo[2].NumEntries =
  983. min(pOldCaps->Cache3Entries,
  984. sbcCurrentBitmapCaps.CellCacheInfo[2].NumEntries);
  985. }
  986. else {
  987. // Did not receive the required size from the client. This is
  988. // nonstandard behavior on RDP 4.0, so no problem to disable
  989. // caching. Set the NumEntries to zero to turn off caching.
  990. sbcCurrentBitmapCaps.CellCacheInfo[2].NumEntries = 0;
  991. }
  992. }
  993. else {
  994. TRC_NRM((TB,"No rev1 caps received"));
  995. TRC_ASSERT((pCapHdr->lengthCapability == 0),
  996. (TB, "Rev1 capability length (%u) too small",
  997. pCapHdr->lengthCapability));
  998. }
  999. }
  1000. DC_END_FN();
  1001. }
  1002. /****************************************************************************/
  1003. /* FUNCTION: SBCRedetermineBrushSupport */
  1004. /* */
  1005. /* Enumerates all the people in the share and redetermines the brush */
  1006. /* support level depending on their and the local receive capabilities. */
  1007. /* */
  1008. /* RETURNS: the share brush support level */
  1009. /****************************************************************************/
  1010. BOOLEAN RDPCALL SHCLASS SBCRedetermineBrushSupport(void)
  1011. {
  1012. unsigned i;
  1013. BOOLEAN rc = TRUE;
  1014. DC_BEGIN_FN("SBCRedetermineBrushSupport");
  1015. /************************************************************************/
  1016. /* Start by setting brush support to the highest supported */
  1017. /************************************************************************/
  1018. sbcBrushSupportLevel = TS_BRUSH_COLOR8x8;
  1019. TRC_NRM((TB, "Initial brush support level: %ld", sbcBrushSupportLevel));
  1020. /************************************************************************/
  1021. /* Enumerate all the brush support capabilities of all the parties. */
  1022. /* Brush support is set to the lowest common denominator. */
  1023. /************************************************************************/
  1024. CPC_EnumerateCapabilities(TS_CAPSETTYPE_BRUSH, NULL, SBCEnumBrushCaps);
  1025. if (sbcBrushSupportLevel == TS_BRUSH_DEFAULT)
  1026. rc = FALSE;
  1027. TRC_NRM((TB, "Enumerated brush support level: %ld", sbcBrushSupportLevel));
  1028. DC_END_FN();
  1029. return rc;
  1030. }
  1031. /****************************************************************************/
  1032. /* FUNCTION: SBCEnumBrushCaps */
  1033. /* */
  1034. /* Function passed to CPC_EnumerateCapabilities. It will be called with a */
  1035. /* capability structure for each person in the share corresponding to the */
  1036. /* TS_CAPSETTYPE_BRUSH capability structure. */
  1037. /* */
  1038. /* PARAMETERS: */
  1039. /* */
  1040. /* personID - ID of person with these capabilities. */
  1041. /* */
  1042. /* pProtCaps - pointer to capabilities structure for this person. This */
  1043. /* pointer is only valid within the call to this function. */
  1044. /****************************************************************************/
  1045. void RDPCALL SHCLASS SBCEnumBrushCaps(
  1046. LOCALPERSONID locPersonID,
  1047. UINT_PTR UserData,
  1048. PTS_CAPABILITYHEADER pCapabilities)
  1049. {
  1050. PTS_BRUSH_CAPABILITYSET pBrushCaps;
  1051. unsigned i;
  1052. DC_BEGIN_FN("SBCEnumBrushCaps");
  1053. DC_IGNORE_PARAMETER(UserData);
  1054. pBrushCaps = (PTS_BRUSH_CAPABILITYSET)pCapabilities;
  1055. /************************************************************************/
  1056. /* Set the brush support level to the lowest common denominator of all */
  1057. /* the parties in the call. */
  1058. /************************************************************************/
  1059. if (pCapabilities->lengthCapability >= sizeof(TS_BRUSH_CAPABILITYSET)) {
  1060. pBrushCaps = (PTS_BRUSH_CAPABILITYSET)pCapabilities;
  1061. TRC_NRM((TB, "Brush Support Level[ID=%u]: %ld", locPersonID,
  1062. pBrushCaps->brushSupportLevel));
  1063. sbcBrushSupportLevel = min(sbcBrushSupportLevel,
  1064. pBrushCaps->brushSupportLevel);
  1065. }
  1066. else {
  1067. sbcBrushSupportLevel = TS_BRUSH_DEFAULT;
  1068. TRC_NRM((TB, "[%ld]: Brush Support Level Unknown", locPersonID));
  1069. }
  1070. TRC_NRM((TB, "[%ld]: Negotiated brush level: %ld", locPersonID,
  1071. sbcBrushSupportLevel));
  1072. DC_END_FN();
  1073. }
  1074. /****************************************************************************/
  1075. /* FUNCTION: SBCEnumOffscreenCaps */
  1076. /* */
  1077. /* Function passed to CPC_EnumerateCapabilities. It will be called with a */
  1078. /* capability structure for each person in the share corresponding to the */
  1079. /* TS_CAPSETTYPE_OFFSCREEN capability structure. */
  1080. /* */
  1081. /* PARAMETERS: */
  1082. /* */
  1083. /* personID - ID of person with these capabilities. */
  1084. /* */
  1085. /* pProtCaps - pointer to capabilities structure for this person. This */
  1086. /* pointer is only valid within the call to this function. */
  1087. /****************************************************************************/
  1088. void RDPCALL SHCLASS SBCEnumOffscreenCaps(
  1089. LOCALPERSONID locPersonID,
  1090. UINT_PTR UserData,
  1091. PTS_CAPABILITYHEADER pCapabilities)
  1092. {
  1093. PTS_OFFSCREEN_CAPABILITYSET pOffscreenCaps;
  1094. DC_BEGIN_FN("SBCEnumOffscreenCaps");
  1095. DC_IGNORE_PARAMETER(UserData);
  1096. pOffscreenCaps = (PTS_OFFSCREEN_CAPABILITYSET)pCapabilities;
  1097. /************************************************************************/
  1098. /* Set the offscr support level to the lowest common denominator of all */
  1099. /* the parties in the call. */
  1100. /************************************************************************/
  1101. if (pCapabilities->lengthCapability >= sizeof(TS_OFFSCREEN_CAPABILITYSET)) {
  1102. pOffscreenCaps = (PTS_OFFSCREEN_CAPABILITYSET)pCapabilities;
  1103. TRC_NRM((TB, "Offscreen Support Level[ID=%u]: %ld", locPersonID,
  1104. pOffscreenCaps->offscreenSupportLevel));
  1105. sbcOffscreenCacheInfo.supportLevel = min(sbcOffscreenCacheInfo.supportLevel,
  1106. pOffscreenCaps->offscreenSupportLevel);
  1107. sbcOffscreenCacheInfo.cacheSize = min(sbcOffscreenCacheInfo.cacheSize,
  1108. pOffscreenCaps->offscreenCacheSize);
  1109. sbcOffscreenCacheInfo.cacheEntries = min(sbcOffscreenCacheInfo.cacheEntries,
  1110. pOffscreenCaps->offscreenCacheEntries);
  1111. }
  1112. else {
  1113. sbcOffscreenCacheInfo.supportLevel = TS_OFFSCREEN_DEFAULT;
  1114. TRC_NRM((TB, "[%ld]: Offscreen Support Level Unknown", locPersonID));
  1115. }
  1116. if (sbcOffscreenCacheInfo.cacheSize == 0 ||
  1117. sbcOffscreenCacheInfo.cacheEntries == 0) {
  1118. sbcOffscreenCacheInfo.supportLevel = TS_OFFSCREEN_DEFAULT;
  1119. }
  1120. TRC_NRM((TB, "[%ld]: Negotiated offscreen level: %ld", locPersonID,
  1121. sbcOffscreenCacheInfo.supportLevel));
  1122. DC_END_FN();
  1123. }
  1124. /****************************************************************************/
  1125. /* FUNCTION: SBCRedetermineOffscreenSupport */
  1126. /* */
  1127. /* Enumerates all the people in the share and redetermines the offscreen */
  1128. /* support level depending on their and the local receive capabilities. */
  1129. /* */
  1130. /* RETURNS: the share offscreen support level */
  1131. /****************************************************************************/
  1132. BOOLEAN RDPCALL SHCLASS SBCRedetermineOffscreenSupport(void)
  1133. {
  1134. unsigned i;
  1135. BOOLEAN rc = TRUE;
  1136. DC_BEGIN_FN("SBCRedetermineOffscreenSupport");
  1137. /************************************************************************/
  1138. /* Start by setting offscreen support to the highest supported */
  1139. /************************************************************************/
  1140. sbcOffscreenCacheInfo.supportLevel = TS_OFFSCREEN_SUPPORTED;
  1141. sbcOffscreenCacheInfo.cacheSize = TS_OFFSCREEN_CACHE_SIZE_SERVER_DEFAULT;
  1142. sbcOffscreenCacheInfo.cacheEntries = TS_OFFSCREEN_CACHE_ENTRIES_DEFAULT;
  1143. TRC_NRM((TB, "Initial offscreen support level: %ld",
  1144. sbcOffscreenCacheInfo.supportLevel));
  1145. /************************************************************************/
  1146. /* Enumerate all the offscr support capabilities of all the parties. */
  1147. /* Offscr support is set to the lowest common denominator. */
  1148. /************************************************************************/
  1149. CPC_EnumerateCapabilities(TS_CAPSETTYPE_OFFSCREENCACHE, NULL,
  1150. SBCEnumOffscreenCaps);
  1151. if (sbcOffscreenCacheInfo.supportLevel == TS_OFFSCREEN_DEFAULT)
  1152. rc = FALSE;
  1153. TRC_NRM((TB, "Enumerated offscreen support level: %ld",
  1154. sbcOffscreenCacheInfo.supportLevel));
  1155. DC_END_FN();
  1156. return rc;
  1157. }
  1158. #ifdef DRAW_NINEGRID
  1159. /****************************************************************************/
  1160. // FUNCTION: SBCEnumDrawNineGridCaps
  1161. //
  1162. // Function passed to CPC_EnumerateCapabilities. It will be called with a
  1163. // capability structure for each person in the share corresponding to the
  1164. // TS_CAPSETTYPE_DRAWNINEGRID capability structure.
  1165. //
  1166. // PARAMETERS:
  1167. //
  1168. // personID - ID of person with these capabilities.
  1169. //
  1170. // pProtCaps - pointer to capabilities structure for this person. This
  1171. // pointer is only valid within the call to this function.
  1172. /****************************************************************************/
  1173. void RDPCALL SHCLASS SBCEnumDrawNineGridCaps(
  1174. LOCALPERSONID locPersonID,
  1175. UINT_PTR UserData,
  1176. PTS_CAPABILITYHEADER pCapabilities)
  1177. {
  1178. PTS_DRAW_NINEGRID_CAPABILITYSET pDrawNineGridCaps;
  1179. DC_BEGIN_FN("SBCEnumDrawNineGridCaps");
  1180. DC_IGNORE_PARAMETER(UserData);
  1181. pDrawNineGridCaps = (PTS_DRAW_NINEGRID_CAPABILITYSET)pCapabilities;
  1182. /************************************************************************/
  1183. // Set the drawninegrid support level to the lowest common denominator of all
  1184. // the parties in the call.
  1185. /************************************************************************/
  1186. if (pCapabilities->lengthCapability >= sizeof(TS_DRAW_NINEGRID_CAPABILITYSET)) {
  1187. pDrawNineGridCaps = (PTS_DRAW_NINEGRID_CAPABILITYSET)pCapabilities;
  1188. TRC_NRM((TB, "DrawNineGrid Support Level[ID=%u]: %ld", locPersonID,
  1189. pDrawNineGridCaps->drawNineGridSupportLevel));
  1190. sbcDrawNineGridCacheInfo.supportLevel = min(sbcDrawNineGridCacheInfo.supportLevel,
  1191. pDrawNineGridCaps->drawNineGridSupportLevel);
  1192. sbcDrawNineGridCacheInfo.cacheSize = min(sbcDrawNineGridCacheInfo.cacheSize,
  1193. pDrawNineGridCaps->drawNineGridCacheSize);
  1194. sbcDrawNineGridCacheInfo.cacheEntries = min(sbcDrawNineGridCacheInfo.cacheEntries,
  1195. pDrawNineGridCaps->drawNineGridCacheEntries);
  1196. }
  1197. else {
  1198. sbcDrawNineGridCacheInfo.supportLevel = TS_DRAW_NINEGRID_DEFAULT;
  1199. TRC_NRM((TB, "[%ld]: DrawNineGrid Support Level Unknown", locPersonID));
  1200. }
  1201. if (sbcDrawNineGridCacheInfo.cacheSize == 0 ||
  1202. sbcDrawNineGridCacheInfo.cacheEntries == 0) {
  1203. sbcDrawNineGridCacheInfo.supportLevel = TS_DRAW_NINEGRID_DEFAULT;
  1204. }
  1205. TRC_NRM((TB, "[%ld]: Negotiated drawninegrid level: %ld", locPersonID,
  1206. sbcDrawNineGridCacheInfo.supportLevel));
  1207. DC_END_FN();
  1208. }
  1209. /****************************************************************************/
  1210. // FUNCTION: SBCRedetermineDrawNineGridSupport
  1211. //
  1212. // Enumerates all the people in the share and redetermines the drawninegrid
  1213. // support level depending on their and the local receive capabilities.
  1214. //
  1215. // RETURNS: the share drawninegrid support level
  1216. /****************************************************************************/
  1217. BOOLEAN RDPCALL SHCLASS SBCRedetermineDrawNineGridSupport(void)
  1218. {
  1219. unsigned i;
  1220. BOOLEAN rc = TRUE;
  1221. DC_BEGIN_FN("SBCRedetermineDrawNineGridSupport");
  1222. /************************************************************************/
  1223. // Start by setting drawninegrid support to the highest supported
  1224. /************************************************************************/
  1225. sbcDrawNineGridCacheInfo.supportLevel = TS_DRAW_NINEGRID_SUPPORTED_REV2;
  1226. sbcDrawNineGridCacheInfo.cacheSize = TS_DRAW_NINEGRID_CACHE_SIZE_DEFAULT;
  1227. sbcDrawNineGridCacheInfo.cacheEntries = TS_DRAW_NINEGRID_CACHE_ENTRIES_DEFAULT;
  1228. TRC_NRM((TB, "Initial DrawNineGrid support level: %ld",
  1229. sbcDrawNineGridCacheInfo.supportLevel));
  1230. /************************************************************************/
  1231. // Enumerate all the DrawNineGrid support capabilities of all the parties.
  1232. // drawninegrid support is set to the lowest common denominator.
  1233. /************************************************************************/
  1234. CPC_EnumerateCapabilities(TS_CAPSETTYPE_DRAWNINEGRIDCACHE, NULL,
  1235. SBCEnumDrawNineGridCaps);
  1236. if (sbcDrawNineGridCacheInfo.supportLevel == TS_DRAW_NINEGRID_DEFAULT)
  1237. rc = FALSE;
  1238. TRC_NRM((TB, "Enumerated drawninegrid support level: %ld",
  1239. sbcDrawNineGridCacheInfo.supportLevel));
  1240. DC_END_FN();
  1241. return rc;
  1242. }
  1243. #endif
  1244. #ifdef DRAW_GDIPLUS
  1245. /****************************************************************************/
  1246. // FUNCTION: SBCEnumDrawGdiplusCaps
  1247. //
  1248. // Function passed to CPC_EnumerateCapabilities. It will be called with a
  1249. // capability structure for each person in the share corresponding to the
  1250. // TS_DRAW_GDIPLUS_CAPABILITYSET capability structure.
  1251. //
  1252. // PARAMETERS:
  1253. //
  1254. // personID - ID of person with these capabilities.
  1255. //
  1256. // pProtCaps - pointer to capabilities structure for this person. This
  1257. // pointer is only valid within the call to this function.
  1258. /****************************************************************************/
  1259. void RDPCALL SHCLASS SBCEnumDrawGdiplusCaps(
  1260. LOCALPERSONID locPersonID,
  1261. UINT_PTR UserData,
  1262. PTS_CAPABILITYHEADER pCapabilities)
  1263. {
  1264. PTS_DRAW_GDIPLUS_CAPABILITYSET pDrawGdiplusCaps;
  1265. DC_BEGIN_FN("SBCEnumDrawGdiplusCaps");
  1266. DC_IGNORE_PARAMETER(UserData);
  1267. pDrawGdiplusCaps = (PTS_DRAW_GDIPLUS_CAPABILITYSET)pCapabilities;
  1268. /************************************************************************/
  1269. // Set the drawgdiplus support level to the lowest common denominator of all
  1270. // the parties in the call.
  1271. /************************************************************************/
  1272. if (pCapabilities->lengthCapability >= sizeof(TS_DRAW_GDIPLUS_CAPABILITYSET)) {
  1273. pDrawGdiplusCaps = (PTS_DRAW_GDIPLUS_CAPABILITYSET)pCapabilities;
  1274. TRC_NRM((TB, "DrawGdiplus Support Level[ID=%u]: %ld", locPersonID,
  1275. pDrawGdiplusCaps->drawGdiplusSupportLevel));
  1276. TRC_NRM((TB, "Gdip version is [ID=%u]: 0x%x, 0x%x", locPersonID,
  1277. pDrawGdiplusCaps->GdipVersion, sbcDrawGdiplusInfo.GdipVersion));
  1278. sbcDrawGdiplusInfo.supportLevel = min(sbcDrawGdiplusInfo.supportLevel,
  1279. pDrawGdiplusCaps->drawGdiplusSupportLevel);
  1280. sbcDrawGdiplusInfo.GdipVersion = min(sbcDrawGdiplusInfo.GdipVersion,
  1281. pDrawGdiplusCaps->GdipVersion);
  1282. sbcDrawGdiplusInfo.GdipCacheLevel = min(sbcDrawGdiplusInfo.GdipCacheLevel,
  1283. pDrawGdiplusCaps->drawGdiplusCacheLevel);
  1284. sbcDrawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries = min(sbcDrawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries,
  1285. pDrawGdiplusCaps->GdipCacheEntries.GdipGraphicsCacheEntries);
  1286. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries = min(sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries,
  1287. pDrawGdiplusCaps->GdipCacheEntries.GdipObjectBrushCacheEntries);
  1288. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries = min(sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries,
  1289. pDrawGdiplusCaps->GdipCacheEntries.GdipObjectPenCacheEntries);
  1290. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries = min(sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries,
  1291. pDrawGdiplusCaps->GdipCacheEntries.GdipObjectImageCacheEntries);
  1292. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries = min(sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries,
  1293. pDrawGdiplusCaps->GdipCacheEntries.GdipObjectImageAttributesCacheEntries);
  1294. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipGraphicsCacheChunkSize = min(sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipGraphicsCacheChunkSize,
  1295. pDrawGdiplusCaps->GdipCacheChunkSize.GdipGraphicsCacheChunkSize);
  1296. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectBrushCacheChunkSize = min(sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectBrushCacheChunkSize,
  1297. pDrawGdiplusCaps->GdipCacheChunkSize.GdipObjectBrushCacheChunkSize);
  1298. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectPenCacheChunkSize = min(sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectPenCacheChunkSize,
  1299. pDrawGdiplusCaps->GdipCacheChunkSize.GdipObjectPenCacheChunkSize);
  1300. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectImageAttributesCacheChunkSize = min(sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectImageAttributesCacheChunkSize,
  1301. pDrawGdiplusCaps->GdipCacheChunkSize.GdipObjectImageAttributesCacheChunkSize);
  1302. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheChunkSize = min(sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheChunkSize,
  1303. pDrawGdiplusCaps->GdipImageCacheProperties.GdipObjectImageCacheChunkSize);
  1304. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheTotalSize = min(sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheTotalSize,
  1305. pDrawGdiplusCaps->GdipImageCacheProperties.GdipObjectImageCacheTotalSize);
  1306. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheMaxSize = min(sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheMaxSize,
  1307. pDrawGdiplusCaps->GdipImageCacheProperties.GdipObjectImageCacheMaxSize);
  1308. }
  1309. else {
  1310. sbcDrawGdiplusInfo.supportLevel = TS_DRAW_GDIPLUS_DEFAULT;
  1311. sbcDrawGdiplusInfo.GdipVersion = TS_GDIPVERSION_DEFAULT;
  1312. TRC_ERR((TB, "[%ld]: DrawGdiplus Support Level Unknown", locPersonID));
  1313. }
  1314. TRC_NRM((TB, "[%ld]: Negotiated drawgdiplus level: %ld", locPersonID,
  1315. sbcDrawGdiplusInfo.supportLevel));
  1316. DC_END_FN();
  1317. }
  1318. BOOLEAN RDPCALL SHCLASS SBCRedetermineDrawGdiplusSupport(void)
  1319. {
  1320. BOOLEAN rc = TRUE;
  1321. DC_BEGIN_FN("SBCRedetermineDrawGdiplusSupport");
  1322. /************************************************************************/
  1323. // Start by setting drawgdiplus support to the highest supported
  1324. /************************************************************************/
  1325. sbcDrawGdiplusInfo.supportLevel = TS_DRAW_GDIPLUS_SUPPORTED;
  1326. sbcDrawGdiplusInfo.GdipVersion = 0xFFFFFFFF;
  1327. sbcDrawGdiplusInfo.GdipCacheLevel = TS_DRAW_GDIPLUS_CACHE_LEVEL_ONE;
  1328. sbcDrawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries = TS_GDIP_GRAPHICS_CACHE_ENTRIES_DEFAULT;
  1329. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries = TS_GDIP_BRUSH_CACHE_ENTRIES_DEFAULT;
  1330. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries = TS_GDIP_PEN_CACHE_ENTRIES_DEFAULT;
  1331. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries = TS_GDIP_IMAGE_CACHE_ENTRIES_DEFAULT;
  1332. sbcDrawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries = TS_GDIP_IMAGEATTRIBUTES_CACHE_ENTRIES_DEFAULT;
  1333. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipGraphicsCacheChunkSize = TS_GDIP_GRAPHICS_CACHE_CHUNK_SIZE_DEFAULT;
  1334. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectBrushCacheChunkSize = TS_GDIP_BRUSH_CACHE_CHUNK_SIZE_DEFAULT;
  1335. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectPenCacheChunkSize = TS_GDIP_PEN_CACHE_CHUNK_SIZE_DEFAULT;
  1336. sbcDrawGdiplusInfo.GdipCacheChunkSize.GdipObjectImageAttributesCacheChunkSize = TS_GDIP_IMAGEATTRIBUTES_CACHE_CHUNK_SIZE_DEFAULT;
  1337. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheChunkSize = TS_GDIP_IMAGE_CACHE_CHUNK_SIZE_DEFAULT;
  1338. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheTotalSize = TS_GDIP_IMAGE_CACHE_TOTAL_SIZE_DEFAULT;
  1339. sbcDrawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheMaxSize = TS_GDIP_IMAGE_CACHE_MAX_SIZE_DEFAULT;
  1340. CPC_EnumerateCapabilities(TS_CAPSETTYPE_DRAWGDIPLUS, NULL,
  1341. SBCEnumDrawGdiplusCaps);
  1342. if (sbcDrawGdiplusInfo.supportLevel == TS_DRAW_GDIPLUS_DEFAULT)
  1343. rc = FALSE;
  1344. TRC_NRM((TB, "Enumerated drawgdiplus support level: %ld",
  1345. sbcDrawGdiplusInfo.supportLevel));
  1346. DC_END_FN();
  1347. return rc;
  1348. }
  1349. #endif // DRAW_GDIPLUS
  1350. /****************************************************************************/
  1351. // SBCRedetermineGlyphCacheSize: Enumerates all the people in the share and
  1352. // redetermines the size of the glyph cache depending on their and the local
  1353. // receive capabilities.
  1354. //
  1355. // Returns: TRUE if glyph caching should be enabled, FALSE otherwise.
  1356. /****************************************************************************/
  1357. BOOLEAN RDPCALL SHCLASS SBCRedetermineGlyphCacheSize(void)
  1358. {
  1359. BOOLEAN rc = TRUE;
  1360. unsigned i;
  1361. DC_BEGIN_FN("SBCRedetermineGlyphCacheSize");
  1362. /************************************************************************/
  1363. /* Enumerate all the glyph cache receive capabilities of all the */
  1364. /* parties. The usable size of the send glyph cache is the minimum of */
  1365. /* all the remote receive caches and the local send cache size. */
  1366. /************************************************************************/
  1367. /************************************************************************/
  1368. /* Start by setting the size of the local send bitmap cache to the */
  1369. /* local default values. We DO need to do this, or we end up */
  1370. /* negotiating our glyph cache down to zero! */
  1371. /************************************************************************/
  1372. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++) {
  1373. sbcGlyphCacheSizes[i].cEntries = sbcMaxGlyphCacheSizes[i].cEntries;
  1374. sbcGlyphCacheSizes[i].cbCellSize = sbcMaxGlyphCacheSizes[i].cbCellSize;
  1375. }
  1376. sbcFragCacheSizes[0].cEntries = sbcMaxFragCacheSizes[0].cEntries;
  1377. sbcFragCacheSizes[0].cbCellSize = sbcMaxFragCacheSizes[0].cbCellSize;
  1378. /************************************************************************/
  1379. /* Now enumerate all the parties in the share and set our send glyph */
  1380. /* sizes appropriately. */
  1381. /************************************************************************/
  1382. CPC_EnumerateCapabilities(TS_CAPSETTYPE_GLYPHCACHE, NULL,
  1383. SBCEnumGlyphCacheCaps);
  1384. if (sbcGlyphSupportLevel == CAPS_GLYPH_SUPPORT_NONE)
  1385. rc = FALSE;
  1386. DC_END_FN();
  1387. return rc;
  1388. }
  1389. /****************************************************************************/
  1390. // SBCEnumGlyphCacheCaps: Function passed to CPC_EnumerateCapabilities. It
  1391. // will be called with a capability structure for each person in the share
  1392. // corresponding to the TS_CAPSETTYPE_BITMAPCACHE capability structure.
  1393. //
  1394. // Params:
  1395. // personID - ID of person with these capabilities.
  1396. // pProtCaps - pointer to capabilities structure for this person. This
  1397. // pointer is only valid within the call to this function.
  1398. /****************************************************************************/
  1399. void CALLBACK SHCLASS SBCEnumGlyphCacheCaps(
  1400. LOCALPERSONID locPersonID,
  1401. UINT_PTR UserData,
  1402. PTS_CAPABILITYHEADER pCapabilities)
  1403. {
  1404. unsigned i;
  1405. PTS_GLYPHCACHE_CAPABILITYSET pGlyphCacheCaps;
  1406. DC_BEGIN_FN("SBCEnumGlyphCacheCaps");
  1407. DC_IGNORE_PARAMETER(UserData);
  1408. if (pCapabilities->lengthCapability >=
  1409. sizeof(TS_GLYPHCACHE_CAPABILITYSET)) {
  1410. pGlyphCacheCaps = (PTS_GLYPHCACHE_CAPABILITYSET)pCapabilities;
  1411. for (i = 0; i<SBC_NUM_GLYPH_CACHES; i++) {
  1412. TRC_NRM((TB, "[%u]: Cache %d: MaximumCellSize(%u) Entries(%u)",
  1413. locPersonID,
  1414. i,
  1415. pGlyphCacheCaps->GlyphCache[i].CacheMaximumCellSize,
  1416. pGlyphCacheCaps->GlyphCache[i].CacheEntries));
  1417. /************************************************************************/
  1418. /* Set the size of the glyph cache to the minimum of its current size */
  1419. /* and this party's receive glyph cache size. */
  1420. /************************************************************************/
  1421. sbcGlyphCacheSizes[i].cEntries =
  1422. min(sbcGlyphCacheSizes[i].cEntries,
  1423. pGlyphCacheCaps->GlyphCache[i].CacheEntries);
  1424. sbcGlyphCacheSizes[i].cbCellSize =
  1425. min(sbcGlyphCacheSizes[i].cbCellSize,
  1426. pGlyphCacheCaps->GlyphCache[i].CacheMaximumCellSize);
  1427. TRC_NRM((TB,
  1428. "[%u]: Negotiated glyph cache %u size: cEntries(%u) cbCellSize(%u)",
  1429. locPersonID,
  1430. i,
  1431. sbcGlyphCacheSizes[i].cEntries,
  1432. sbcGlyphCacheSizes[i].cbCellSize));
  1433. }
  1434. /************************************************************************/
  1435. /* Set the size of the glyph cache to the minimum of its current size */
  1436. /* and this party's receive glyph cache size. */
  1437. /************************************************************************/
  1438. sbcFragCacheSizes[0].cEntries =
  1439. min(sbcFragCacheSizes[0].cEntries,
  1440. pGlyphCacheCaps->FragCache.CacheEntries);
  1441. sbcFragCacheSizes[0].cbCellSize =
  1442. min(sbcFragCacheSizes[0].cbCellSize,
  1443. pGlyphCacheCaps->FragCache.CacheMaximumCellSize);
  1444. /************************************************************************/
  1445. /* Glyph support level */
  1446. /************************************************************************/
  1447. sbcGlyphSupportLevel = min(sbcGlyphSupportLevel,
  1448. pGlyphCacheCaps->GlyphSupportLevel);
  1449. }
  1450. else {
  1451. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++) {
  1452. sbcGlyphCacheSizes[i].cEntries = 0;
  1453. sbcGlyphCacheSizes[i].cbCellSize = 0;
  1454. }
  1455. sbcFragCacheSizes[0].cEntries = 0;
  1456. sbcFragCacheSizes[0].cbCellSize = 0;
  1457. sbcGlyphSupportLevel = CAPS_GLYPH_SUPPORT_NONE;
  1458. }
  1459. DC_END_FN();
  1460. }