Source code of Windows XP (NT5)
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.

1526 lines
39 KiB

  1. #include "precomp.h"
  2. //
  3. // PM.CPP
  4. // Palette Manager
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_CORE
  9. //
  10. //
  11. // PALETTE MANAGER (PM) OVERVIEW
  12. //
  13. // Palette Manager is responsible for sending palette packets. A palette
  14. // packet:
  15. //
  16. // (1) indicates the colors being used on the host machine - and therefore
  17. // specifies which colors the remote machine should use if it can choose
  18. // (e.g. by selecting and realizing the given colors into the display
  19. // hardware). [A palette packet may not contain the exact colors being
  20. // used on the host if the protocol bpp is different from the host bpp].
  21. //
  22. // (2) specifies the colors which correspond to the values in bitmap
  23. // (screen) data i.e. the values in 4bpp and 8bpp bitmap data are indices
  24. // into the table of colors sent in the palette packet.
  25. //
  26. //
  27. // (1) affects order replay and (2) affects screen data replay, so a
  28. // correct palette packet must be sent (by calling
  29. // PM_MaybeSendPalettePacket) before a batch of updates are sent.
  30. //
  31. // Palette Manager also handles incoming palette packets from other parties
  32. // in the conference and creates corresponding local palettes which the
  33. // Update Receiver can query and use when processing updates.
  34. //
  35. // When a new palette packet is sent (e.g. due to the System Palette
  36. // changing), all shared areas of the screen will be retransmitted in due
  37. // course. A receiving Palette Manager therefore does not have to (and
  38. // should not attempt to) convert any updates/bitmaps that have been
  39. // received prior to the arrival of the new palette packet.
  40. //
  41. //
  42. //
  43. // PM strategy when network packets cannot be allocated.
  44. //
  45. // PM_MaybeSendPalettePacket returns a boolean indicating whether it has
  46. // succesfully sent a palette packet. The USR will only send updates if
  47. // the corresponding palette packet is successfully sent.
  48. //
  49. //
  50. const COLORREF s_apmGreyRGB[PM_GREY_COUNT] =
  51. {
  52. PM_GREY1,
  53. PM_GREY2,
  54. PM_GREY3,
  55. PM_GREY4,
  56. PM_GREY5
  57. };
  58. //
  59. // PM_PartyLeftShare()
  60. //
  61. void ASShare::PM_PartyLeftShare(ASPerson * pasPerson)
  62. {
  63. DebugEntry(ASShare::PM_PartyLeftShare);
  64. ValidatePerson(pasPerson);
  65. if (pasPerson->cpcCaps.general.version >= CAPS_VERSION_30)
  66. {
  67. // This should be cleared already!
  68. ASSERT(!pasPerson->pmcColorTable);
  69. ASSERT(!pasPerson->apmColorTable);
  70. ASSERT(!pasPerson->pmPalette);
  71. }
  72. else
  73. {
  74. TRACE_OUT(("PM_PartyLeftShare: Freeing pm data for 2.x node [%d]",
  75. pasPerson->mcsID));
  76. PMFreeIncoming(pasPerson);
  77. }
  78. //
  79. // NOTE: In 2.1, we didn't renegotiate the outgoing cache size when
  80. // somebody left. So we don't now either (this is all 2.x compat stuff
  81. // anyway).
  82. //
  83. DebugExitVOID(ASShare::PM_PartyLeftShare);
  84. }
  85. //
  86. // PM_RecalcCaps()
  87. //
  88. // This calculates the PM hosting caps when
  89. // * we start to host
  90. // * we're hosting and somebody joins the share
  91. // * we're hosting and somebody leaves the share
  92. //
  93. // This can GO AWAY WHEN 2.x COMPAT IS GONE -- no more min() of cache size
  94. //
  95. void ASShare::PM_RecalcCaps(BOOL fJoiner)
  96. {
  97. ASPerson * pasT;
  98. DebugEntry(ASShare::PM_RecalcCaps);
  99. if (!m_pHost || !fJoiner)
  100. {
  101. //
  102. // Nothing to do if we're not hosting. And also, if somebody has
  103. // left, no recalculation -- 2.x didn't.
  104. //
  105. DC_QUIT;
  106. }
  107. ValidatePerson(m_pasLocal);
  108. //
  109. // NOTE:
  110. // The default size is 6 palettes cached. The result is going to be
  111. // <= that number. There's no point in recreating the cache, it's
  112. // so small.
  113. //
  114. m_pHost->m_pmNumTxCacheEntries = m_pasLocal->cpcCaps.palette.capsColorTableCacheSize;
  115. if (m_scShareVersion < CAPS_VERSION_30)
  116. {
  117. TRACE_OUT(("In share with 2.x nodes, must recalc PM caps"));
  118. for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
  119. {
  120. m_pHost->m_pmNumTxCacheEntries = min(m_pHost->m_pmNumTxCacheEntries,
  121. pasT->cpcCaps.palette.capsColorTableCacheSize);
  122. }
  123. TRACE_OUT(("Recalced PM caps: Tx Cache size %d",
  124. m_pHost->m_pmNumTxCacheEntries));
  125. }
  126. DC_EXIT_POINT:
  127. DebugExitVOID(ASShare::PM_Recalccaps);
  128. }
  129. //
  130. // PM_HostStarting()
  131. //
  132. // Called when we start to host; sets up color palette stuff and creates
  133. // outgoing palette cache
  134. //
  135. BOOL ASHost::PM_HostStarting(void)
  136. {
  137. BOOL rc = FALSE;
  138. TSHR_COLOR localPalColors[PM_NUM_8BPP_PAL_ENTRIES];
  139. DebugEntry(ASHost::PM_HostStarting);
  140. //
  141. // Get palette caps. NOTE PM_RecalcCaps must be called AFTER
  142. // USR_RecalcCaps(), because that updates m_usrSendingBPP.
  143. //
  144. if (g_usrPalettized)
  145. {
  146. ASSERT(g_usrScreenBPP <= 8);
  147. ZeroMemory(localPalColors, sizeof(localPalColors));
  148. //
  149. // Now create the Local Palette.
  150. //
  151. if (!m_pShare->PM_CreatePalette(COLORS_FOR_BPP(g_usrScreenBPP),
  152. localPalColors, &m_pmTxPalette))
  153. {
  154. ERROR_OUT(( "Failed to create Local Palette"));
  155. DC_QUIT;
  156. }
  157. }
  158. else
  159. {
  160. m_pmTxPalette = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  161. PMGetGrays();
  162. }
  163. //
  164. // With NM 3.0, why not just create a receive cache the size that
  165. // the host specifies in his caps?
  166. //
  167. // So I did that. For back compat, OUTGOING caches use the min size.
  168. // When we only have to be compatible with NM 3.0 and up, we won't
  169. // have to do this min stuff.
  170. //
  171. // Note similar code in CM, SSI, and SBC
  172. //
  173. // Figure out how many outgoing entries we can actually use
  174. m_pShare->PM_RecalcCaps(TRUE);
  175. //
  176. // Create the PM color table cache with a single eviction
  177. // category.
  178. //
  179. if (!CH_CreateCache(&m_pmTxCacheHandle, TSHR_PM_CACHE_ENTRIES,
  180. 1, 0, PMCacheCallback))
  181. {
  182. ERROR_OUT(("Could not create PM cache"));
  183. DC_QUIT;
  184. }
  185. rc = TRUE;
  186. DC_EXIT_POINT:
  187. DebugExitBOOL(ASHost::PM_HostStarting, rc);
  188. return(rc);
  189. }
  190. //
  191. // PM_HostEnded()
  192. //
  193. // We free resources created when we started to host
  194. //
  195. void ASHost::PM_HostEnded(void)
  196. {
  197. DebugEntry(ASHost::PM_HostEnded);
  198. if (m_pmTxPalette)
  199. {
  200. m_pShare->PM_DeletePalette(m_pmTxPalette);
  201. m_pmTxPalette = NULL;
  202. }
  203. if (m_pmTxCacheHandle)
  204. {
  205. CH_DestroyCache(m_pmTxCacheHandle);
  206. m_pmTxCacheHandle = 0;
  207. m_pmNumTxCacheEntries = 0;
  208. }
  209. DebugExitVOID(ASHost::PM_HostEnded);
  210. }
  211. //
  212. // PM_ViewStarting()
  213. //
  214. // For 3.0 nodes, we create the PM cache each time they start hosting
  215. // For 2.x nodes, we create the PM cache once and use it until they leave
  216. // the share.
  217. //
  218. BOOL ASShare::PM_ViewStarting(ASPerson * pasPerson)
  219. {
  220. BOOL rc = FALSE;
  221. DebugEntry(ASShare::PM_ViewStarting);
  222. ValidatePerson(pasPerson);
  223. if (pasPerson->pmcColorTable != 0)
  224. {
  225. ASSERT(pasPerson->apmColorTable != NULL);
  226. ASSERT(pasPerson->pmPalette != NULL);
  227. ASSERT(pasPerson->cpcCaps.general.version < CAPS_VERSION_30);
  228. TRACE_OUT(("PM_ViewStarting Reusing pm data for 2.x node [%d]",
  229. pasPerson->mcsID));
  230. rc = TRUE;
  231. DC_QUIT;
  232. }
  233. //
  234. // In normal operation, we will receive a palette packet from the host
  235. // before any updates, which we use to create the correct palette for
  236. // this host.
  237. //
  238. // However, in some back-level calls we may not receive a palette
  239. // packet before the first updates, so we initialize this host's
  240. // palette to the default palette to allow us to generate some sort
  241. // of output.
  242. //
  243. pasPerson->pmPalette = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  244. //
  245. // Allocate color table cache memory based on the negotiated options
  246. // Space needed is (n)x256xRGBQUAD where n is the number of color
  247. // tables the conference supports.
  248. //
  249. pasPerson->pmcColorTable = pasPerson->cpcCaps.palette.capsColorTableCacheSize;
  250. if (!pasPerson->pmcColorTable)
  251. {
  252. WARNING_OUT(("PM_ViewStarting: person [%d] has no palette cache size",
  253. pasPerson->cpcCaps.palette.capsColorTableCacheSize));
  254. rc = TRUE;
  255. DC_QUIT;
  256. }
  257. pasPerson->apmColorTable = new COLORTABLECACHE[pasPerson->pmcColorTable];
  258. if (!pasPerson->apmColorTable)
  259. {
  260. ERROR_OUT(( "Failed to get memory for PM color table cache"));
  261. DC_QUIT;
  262. }
  263. ZeroMemory(pasPerson->apmColorTable, pasPerson->pmcColorTable * sizeof(COLORTABLECACHE));
  264. rc = TRUE;
  265. DC_EXIT_POINT:
  266. DebugExitBOOL(ASShare::PM_ViewStarting, rc);
  267. return(rc);
  268. }
  269. //
  270. // PM_ViewEnded()
  271. //
  272. void ASShare::PM_ViewEnded(ASPerson * pasPerson)
  273. {
  274. DebugEntry(ASShare::PM_ViewEnded);
  275. ValidatePerson(pasPerson);
  276. //
  277. // For 3.0 nodes, we can free the palette cache; 3.0 senders clear theirs
  278. // every time they host.
  279. // For 2.x nodes, we must keep it around while they are in the share since
  280. // they use it across sharing/unsharing/sharing again.
  281. //
  282. if (pasPerson->cpcCaps.general.version >= CAPS_VERSION_30)
  283. {
  284. PMFreeIncoming(pasPerson);
  285. }
  286. else
  287. {
  288. TRACE_OUT(("PM_PartyViewEnded: Keeping pm data for 2.x node [%d]",
  289. pasPerson->mcsID));
  290. }
  291. DebugExitVOID(ASShare::PM_PartyViewEnded);
  292. }
  293. //
  294. // PMFreeIncoming()
  295. //
  296. void ASShare::PMFreeIncoming(ASPerson * pasPerson)
  297. {
  298. DebugEntry(ASShare::PMFreeIncoming);
  299. //
  300. // Free the color table cache
  301. //
  302. pasPerson->pmcColorTable = 0;
  303. if (pasPerson->apmColorTable)
  304. {
  305. delete[] pasPerson->apmColorTable;
  306. pasPerson->apmColorTable = NULL;
  307. }
  308. if (pasPerson->pmPalette != NULL)
  309. {
  310. //
  311. // Free this host's palette. and set it to NULL so that we can tell
  312. // that this host has left the share.
  313. //
  314. PM_DeletePalette(pasPerson->pmPalette);
  315. pasPerson->pmPalette = NULL;
  316. }
  317. DebugExitVOID(ASShare::PMFreeIncoming);
  318. }
  319. //
  320. // PM_MaybeSendPalettePacket()
  321. //
  322. BOOL ASHost::PM_MaybeSendPalettePacket(void)
  323. {
  324. BOOL rc = TRUE;
  325. DebugEntry(ASHost::PM_MaybeSendPalettePacket);
  326. if (m_pmMustSendPalette)
  327. {
  328. ASSERT(m_usrSendingBPP <= 8);
  329. //
  330. // Ensure that our palette colors are up to date before we send the
  331. // palette packet.
  332. //
  333. if (g_usrPalettized)
  334. {
  335. PMUpdateSystemPaletteColors();
  336. }
  337. PMUpdateTxPaletteColors();
  338. }
  339. else if (g_usrPalettized)
  340. {
  341. ASSERT(m_usrSendingBPP <= 8);
  342. //
  343. // If the System Palette has changed then we may need to send
  344. // another palette packet.
  345. //
  346. if (PMUpdateSystemPaletteColors())
  347. {
  348. //
  349. // The System Palette has changed, but we only need to send
  350. // another palette packet if the palette colors have changed.
  351. //
  352. TRACE_OUT(( "System Palette changed"));
  353. if (PMUpdateTxPaletteColors())
  354. {
  355. TRACE_OUT(( "Tx Palette changed"));
  356. m_pmMustSendPalette = TRUE;
  357. }
  358. }
  359. }
  360. if (m_pmMustSendPalette)
  361. {
  362. ASSERT(m_usrSendingBPP <= 8);
  363. TRACE_OUT(( "Send palette packet"));
  364. rc = PMSendPalettePacket(m_apmTxPaletteColors, COLORS_FOR_BPP(m_usrSendingBPP));
  365. if (rc)
  366. {
  367. m_pmMustSendPalette = FALSE;
  368. }
  369. }
  370. DebugExitBOOL(ASHost::PM_MaybeSendPalettePacket, rc);
  371. return(rc);
  372. }
  373. //
  374. // PM_ReceivedPacket
  375. //
  376. void ASShare::PM_ReceivedPacket
  377. (
  378. ASPerson * pasPerson,
  379. PS20DATAPACKET pPacket
  380. )
  381. {
  382. PPMPACKET pPMPacket;
  383. HPALETTE newPalette = NULL;
  384. DebugEntry(ASShare::PM_ReceivedPacket);
  385. ValidateView(pasPerson);
  386. pPMPacket = (PPMPACKET)pPacket;
  387. //
  388. // Create a new palette from the received packet.
  389. //
  390. // We cannot just update the current palette colors (using
  391. // SetPaletteEntries) because Windows does not handle the repainting
  392. // of other local Palette Manager apps correctly (it does not
  393. // broadcast the WM_PALETTE.. messages as the palette mapping does
  394. // not change).
  395. //
  396. if (PM_CreatePalette(pPMPacket->numColors, pPMPacket->aColors,
  397. &newPalette))
  398. {
  399. PM_DeletePalette(pasPerson->pmPalette);
  400. pasPerson->pmPalette = newPalette;
  401. TRACE_OUT(( "Created new palette 0x%08x from packet", newPalette));
  402. }
  403. else
  404. {
  405. WARNING_OUT(( "Failed to create palette. person(%u) numColors(%u)",
  406. pasPerson, pPMPacket->numColors));
  407. }
  408. DebugExitVOID(ASShare::PM_ReceivedPacket);
  409. }
  410. //
  411. // PM_SyncOutgoing()
  412. //
  413. void ASHost::PM_SyncOutgoing(void)
  414. {
  415. DebugEntry(ASHost::PM_SyncOutgoing);
  416. //
  417. // Ensure we send a palette to the remote PM next time we are called.
  418. //
  419. if (m_usrSendingBPP <= 8)
  420. {
  421. m_pmMustSendPalette = TRUE;
  422. //
  423. // The sync discards any as-yet-unsent accumulated orders. Since these
  424. // orders may include color table cache orders, clear the cache.
  425. //
  426. ASSERT(m_pmTxCacheHandle);
  427. CH_ClearCache(m_pmTxCacheHandle);
  428. }
  429. DebugExitVOID(ASHost::PM_SyncOutgoing);
  430. }
  431. //
  432. // PM_CacheTxColorTable
  433. //
  434. BOOL ASHost::PM_CacheTxColorTable
  435. (
  436. LPUINT pIndex,
  437. LPBOOL pCacheChanged,
  438. UINT cColors,
  439. LPTSHR_RGBQUAD pColors
  440. )
  441. {
  442. BOOL rc = FALSE;
  443. UINT cacheIndex = 0;
  444. UINT i = 0;
  445. PCOLORTABLECACHE pEntry = NULL;
  446. COLORTABLECACHE newEntry = { 0 };
  447. DebugEntry(ASHost::PM_CacheTxColorTable);
  448. ASSERT(m_usrSendingBPP <= 8);
  449. ASSERT(m_pmTxCacheHandle);
  450. TRACE_OUT(( "Caching table of %u colors", cColors));
  451. //
  452. // Create the data we want to cache. It may be that there is already
  453. // an entry in the cache for this set of colors, but we still need to
  454. // create a cache entry in local memory so we can search the cache to
  455. // find out.
  456. //
  457. ZeroMemory(&newEntry, sizeof(COLORTABLECACHE));
  458. newEntry.inUse = TRUE;
  459. newEntry.cColors = cColors;
  460. memcpy(&newEntry.colors, pColors, cColors * sizeof(TSHR_RGBQUAD));
  461. //
  462. // Check to see if the table is already cached. (No hint or eviction
  463. // category.)
  464. //
  465. if (CH_SearchCache(m_pmTxCacheHandle, (LPBYTE)(&newEntry),
  466. sizeof(COLORTABLECACHE), 0, &cacheIndex ))
  467. {
  468. TRACE_OUT(( "Found existing entry at %u",cacheIndex));
  469. *pIndex = cacheIndex;
  470. *pCacheChanged = FALSE;
  471. rc = TRUE;
  472. DC_QUIT;
  473. }
  474. //
  475. // Find a free cache entry
  476. //
  477. // We arrange that our transmit cache is always one greater than the
  478. // negotiated cache size so that we should never fail to find a free
  479. // array entry. Once we have fully populated our Tx cache we will
  480. // always find the free entry as the one last given back to us by CH.
  481. // Note the scan to <= m_pmNumTxCacheEntries is NOT a mistake.
  482. //
  483. if (m_pmNextTxCacheEntry != NULL)
  484. {
  485. pEntry = m_pmNextTxCacheEntry;
  486. m_pmNextTxCacheEntry = NULL;
  487. }
  488. else
  489. {
  490. for (i = 0; i <= m_pmNumTxCacheEntries; i++)
  491. {
  492. if (!m_apmTxCache[i].inUse)
  493. {
  494. break;
  495. }
  496. }
  497. //
  498. // We should never run out of free entries, but cope with it
  499. //
  500. if (i > m_pmNumTxCacheEntries)
  501. {
  502. ERROR_OUT(( "All PM cache entries in use"));
  503. rc = FALSE;
  504. DC_QUIT;
  505. }
  506. pEntry = m_apmTxCache + i;
  507. }
  508. //
  509. // Set up the color table in the free entry we just found
  510. //
  511. memcpy(pEntry, &newEntry, sizeof(COLORTABLECACHE));
  512. //
  513. // Add the new entry to the cache
  514. // We do not use hints or eviction so set to 0
  515. //
  516. cacheIndex = CH_CacheData(m_pmTxCacheHandle, (LPBYTE)pEntry,
  517. sizeof(COLORTABLECACHE), 0 );
  518. TRACE_OUT(( "Color table 0x%08x cached at index %u", pEntry, cacheIndex));
  519. *pIndex = cacheIndex;
  520. *pCacheChanged = TRUE;
  521. rc = TRUE;
  522. DC_EXIT_POINT:
  523. DebugExitDWORD(ASHost::PM_CacheTxColorTable, rc);
  524. return(rc);
  525. }
  526. //
  527. // PM_CacheRxColorTable
  528. //
  529. BOOL ASShare::PM_CacheRxColorTable
  530. (
  531. ASPerson * pasPerson,
  532. UINT index,
  533. UINT cColors,
  534. LPTSHR_RGBQUAD pColors
  535. )
  536. {
  537. BOOL rc = FALSE;
  538. PCOLORTABLECACHE pColorTable;
  539. DebugEntry(ASShare::PM_CacheRxColorTable);
  540. ValidatePerson(pasPerson);
  541. pColorTable = pasPerson->apmColorTable;
  542. TRACE_OUT(( "Person [%d] color table rx cache 0x%08x cache %u, %u colors",
  543. pasPerson->mcsID, pColorTable, index, cColors));
  544. if (pColorTable == NULL)
  545. {
  546. ERROR_OUT(( "Asked to cache when no cache allocated"));
  547. DC_QUIT;
  548. }
  549. //
  550. // The index must be within the currently negotiated cache limits
  551. //
  552. if (index > pasPerson->pmcColorTable)
  553. {
  554. ERROR_OUT(( "Invalid color table index %u",index));
  555. DC_QUIT;
  556. }
  557. //
  558. // Set up the color table entry
  559. //
  560. pColorTable[index].inUse = TRUE;
  561. pColorTable[index].cColors = cColors;
  562. memcpy(pColorTable[index].colors, pColors, cColors * sizeof(TSHR_RGBQUAD));
  563. rc = TRUE;
  564. DC_EXIT_POINT:
  565. DebugExitDWORD(ASShare::PM_CacheRxColorTable, rc);
  566. return(rc);
  567. }
  568. //
  569. // PMSendPalettePacket
  570. //
  571. // DESCRIPTION:
  572. //
  573. // Sends a palette packet containing the given colors.
  574. //
  575. // PARAMETERS:
  576. //
  577. // pColorTable - pointer to an array of TSHR_RGBQUAD colors to be sent in the
  578. // palette packet.
  579. //
  580. // numColors - the number of entries in the TSHR_RGBQUAD array
  581. //
  582. // RETURNS: TRUE if the palette packet is sent, FALSE otherwise
  583. //
  584. //
  585. BOOL ASHost::PMSendPalettePacket
  586. (
  587. LPTSHR_RGBQUAD pColorTable,
  588. UINT numColors
  589. )
  590. {
  591. PPMPACKET pPMPacket;
  592. UINT sizePkt;
  593. UINT i;
  594. BOOL rc = FALSE;
  595. #ifdef _DEBUG
  596. UINT sentSize;
  597. #endif // _DEBUG
  598. DebugEntry(ASHost::PMSendPalettePacket);
  599. //
  600. // Send a palette packet.
  601. //
  602. // First calculate the packet size.
  603. //
  604. sizePkt = sizeof(PMPACKET) + (numColors - 1) * sizeof(TSHR_COLOR);
  605. pPMPacket = (PPMPACKET)m_pShare->SC_AllocPkt(PROT_STR_UPDATES, g_s20BroadcastID, sizePkt);
  606. if (!pPMPacket)
  607. {
  608. WARNING_OUT(("Failed to alloc PM packet, size %u", sizePkt));
  609. DC_QUIT;
  610. }
  611. //
  612. // Fill in the packet contents.
  613. //
  614. pPMPacket->header.header.data.dataType = DT_UP;
  615. pPMPacket->header.updateType = UPD_PALETTE;
  616. //
  617. // Convert the TSHR_RGBQUADs in the color table to TSHR_COLORs as we copy
  618. // them into the packet.
  619. //
  620. pPMPacket->numColors = numColors;
  621. for (i = 0; i < numColors; i++)
  622. {
  623. //
  624. // Convert each RGBQuad entry in the color table to a DCColor.
  625. //
  626. TSHR_RGBQUAD_TO_TSHR_COLOR(pColorTable[i],
  627. pPMPacket->aColors[i]);
  628. }
  629. //
  630. // Now send the packet to the remote application.
  631. //
  632. if (m_pShare->m_scfViewSelf)
  633. m_pShare->PM_ReceivedPacket(m_pShare->m_pasLocal, &(pPMPacket->header.header));
  634. #ifdef _DEBUG
  635. sentSize =
  636. #endif // _DEBUG
  637. m_pShare->DCS_CompressAndSendPacket(PROT_STR_UPDATES, g_s20BroadcastID,
  638. &(pPMPacket->header.header), sizePkt);
  639. TRACE_OUT(("PM packet size: %08d, sent %08d", sizePkt, sentSize));
  640. rc = TRUE;
  641. DC_EXIT_POINT:
  642. DebugExitDWORD(ASHost::PMSendPalettePacket, rc);
  643. return(rc);
  644. }
  645. //
  646. // FUNCTION: PMCacheCallback
  647. //
  648. // DESCRIPTION:
  649. //
  650. // Cursor Manager's Cache Manager callback function. Called whenever an
  651. // entry is removed from the cache to allow us to free up the object.
  652. //
  653. // PARAMETERS:
  654. //
  655. // hCache - cache handle
  656. //
  657. // event - the cache event that has occured
  658. //
  659. // iCacheEntry - index of the cache entry that the event is affecting
  660. //
  661. // pData - pointer to the cache data associated with the given cache entry
  662. //
  663. // cbDataSize - size in bytes of the cached data
  664. //
  665. // RETURNS: Nothing
  666. //
  667. //
  668. void PMCacheCallback
  669. (
  670. ASHost * pHost,
  671. PCHCACHE pCache,
  672. UINT iCacheEntry,
  673. LPBYTE pData
  674. )
  675. {
  676. DebugEntry(PMCacheCallback);
  677. //
  678. // Release the cache entry for reuse
  679. //
  680. TRACE_OUT(( "Releasing cache entry %d at 0x%08x",
  681. iCacheEntry, pData));
  682. pHost->m_pmNextTxCacheEntry = (PCOLORTABLECACHE)pData;
  683. pHost->m_pmNextTxCacheEntry->inUse = FALSE;
  684. //
  685. // Let SBC know that the cache entry has been released
  686. //
  687. pHost->SBC_PMCacheEntryRemoved(iCacheEntry);
  688. DebugExitVOID(PMCacheCallback);
  689. }
  690. //
  691. // PM_GetSystemPaletteEntries
  692. //
  693. void ASHost::PM_GetSystemPaletteEntries(LPTSHR_RGBQUAD pColors)
  694. {
  695. UINT i;
  696. DebugEntry(ASHost::PM_GetSystemPaletteEntries);
  697. PMUpdateSystemPaletteColors();
  698. for (i = 0; i < PM_NUM_8BPP_PAL_ENTRIES; i++)
  699. {
  700. pColors[i].rgbRed = m_apmCurrentSystemPaletteEntries[i].peRed;
  701. pColors[i].rgbGreen = m_apmCurrentSystemPaletteEntries[i].peGreen;
  702. pColors[i].rgbBlue = m_apmCurrentSystemPaletteEntries[i].peBlue;
  703. pColors[i].rgbReserved = 0;
  704. }
  705. //
  706. // This function in its current form always returns TRUE - it is always
  707. // able to obtain the system colors.
  708. //
  709. DebugExitVOID(ASHost::PM_GetSystemPaletteEntries);
  710. }
  711. //
  712. // PM_GetLocalPalette()
  713. //
  714. HPALETTE ASHost::PM_GetLocalPalette(void)
  715. {
  716. //
  717. // Ensure the palette is up to date
  718. //
  719. if (g_usrPalettized)
  720. {
  721. PMUpdateSystemPaletteColors();
  722. }
  723. //
  724. // Return the handle to the Local Palette.
  725. //
  726. return(m_pmTxPalette);
  727. }
  728. //
  729. // PM_GetColorTable
  730. //
  731. void ASShare::PM_GetColorTable
  732. (
  733. ASPerson * pasPerson,
  734. UINT index,
  735. LPUINT pcColors,
  736. LPTSHR_RGBQUAD pColors
  737. )
  738. {
  739. PCOLORTABLECACHE pColorTable;
  740. DebugEntry(ASShare::PM_GetColorTable);
  741. ValidatePerson(pasPerson);
  742. ASSERT(pasPerson->apmColorTable);
  743. pColorTable = &(pasPerson->apmColorTable[index]);
  744. TRACE_OUT(( "Color table requested for [%d], table ptr 0x%08x index %d",
  745. pasPerson->mcsID, pColorTable,index));
  746. if (!pColorTable->inUse)
  747. {
  748. ERROR_OUT(( "Asked for PM cache entry %hu when cache not yet in use",
  749. index));
  750. DC_QUIT;
  751. }
  752. //
  753. // Copy the colors into the structure we have been passed
  754. //
  755. *pcColors = pColorTable->cColors;
  756. memcpy( pColors,
  757. pColorTable->colors,
  758. sizeof(TSHR_RGBQUAD) * pColorTable->cColors );
  759. TRACE_OUT(( "Returning %u colors",*pcColors));
  760. DC_EXIT_POINT:
  761. DebugExitVOID(ASShare::PM_GetColorTable);
  762. }
  763. //
  764. // PMADJUSTBUGGEDCOLOR()
  765. //
  766. // Macro used to tweak an 8 bit palette entry that the Win95 16 bit
  767. // driver returns incorrectly
  768. //
  769. #define PMADJUSTBUGGEDCOLOR(pColor) \
  770. if ( ((pColor)->rgbBlue != 0x00) && \
  771. ((pColor)->rgbBlue != 0xFF) ) \
  772. { \
  773. (pColor)->rgbBlue += 0x40; \
  774. } \
  775. \
  776. if ( ((pColor)->rgbGreen != 0x00) && \
  777. ((pColor)->rgbGreen != 0xFF) ) \
  778. { \
  779. (pColor)->rgbGreen += 0x20; \
  780. } \
  781. \
  782. if ( ((pColor)->rgbRed != 0x00) && \
  783. ((pColor)->rgbRed != 0xFF) ) \
  784. { \
  785. (pColor)->rgbRed += 0x20; \
  786. }
  787. //
  788. // PMGetGrays()
  789. //
  790. // Gets display driver specific versions of gray RGBs
  791. //
  792. void ASHost::PMGetGrays(void)
  793. {
  794. HBITMAP hOldBitmap = NULL;
  795. BITMAPINFO_ours bitmapInfo;
  796. BYTE bitmapBuffer[16];
  797. UINT i;
  798. DebugEntry(ASHost::PMGetGrays);
  799. //
  800. // Initialise the bitmapinfo local structure header contents. This
  801. // structure will be used in the GetDIBits calls.
  802. //
  803. m_pShare->USR_InitDIBitmapHeader((BITMAPINFOHEADER *)&bitmapInfo, 8);
  804. bitmapInfo.bmiHeader.biWidth = 16;
  805. bitmapInfo.bmiHeader.biHeight = 1;
  806. //
  807. // Select the bitmap into the work DC
  808. //
  809. hOldBitmap = SelectBitmap(m_usrWorkDC, m_pShare->m_usrBmp16);
  810. if (hOldBitmap == NULL)
  811. {
  812. ERROR_OUT(( "Failed to select bitmap. hp(%08lX) hbmp(%08lX)",
  813. m_usrWorkDC, m_pShare->m_usrBmp16 ));
  814. DC_QUIT;
  815. }
  816. //
  817. // Use the real GDI to set each bit to each supplied color.
  818. //
  819. for (i = PM_GREY_COUNT; i-- != 0; )
  820. {
  821. SetPixel(m_usrWorkDC, i, 0, s_apmGreyRGB[i]);
  822. }
  823. //
  824. // Because this function is only used for true color scenarios we do
  825. // not need to select a palette into our compatible DC. We just need
  826. // to get the bits.
  827. //
  828. if (!GetDIBits(m_usrWorkDC, m_pShare->m_usrBmp16, 0, 1, &bitmapBuffer,
  829. (BITMAPINFO *)&bitmapInfo, DIB_RGB_COLORS ))
  830. {
  831. ERROR_OUT(( "GetDIBits failed. hp(%x) hbmp(%x)",
  832. m_usrWorkDC, m_pShare->m_usrBmp16));
  833. DC_QUIT;
  834. }
  835. //
  836. // Check if we need to adjust the palette colors for the 16 bit driver
  837. // bug.
  838. //
  839. m_pmBuggedDriver = ((g_usrScreenBPP > 8) &&
  840. (bitmapInfo.bmiColors[1].rgbRed == 0) &&
  841. (bitmapInfo.bmiColors[1].rgbGreen == 0) &&
  842. (bitmapInfo.bmiColors[1].rgbBlue == 0x40));
  843. //
  844. // Extract the RGBs returned by the display driver with the sending bpp
  845. // DIB.
  846. //
  847. for (i = PM_GREY_COUNT; i-- != 0; )
  848. {
  849. //
  850. // Extract the RGB from the color table
  851. //
  852. m_apmDDGreyRGB[i] = *((LPTSHR_RGBQUAD)(&bitmapInfo.bmiColors[bitmapBuffer[i]]));
  853. //
  854. // Adjust the palette colors for the 16 bit driver bug, if needed.
  855. //
  856. if (m_pmBuggedDriver)
  857. {
  858. TRACE_OUT(( "Adjusting for bugged driver"));
  859. PMADJUSTBUGGEDCOLOR(&m_apmDDGreyRGB[i]);
  860. }
  861. }
  862. DC_EXIT_POINT:
  863. //
  864. // clean up
  865. //
  866. if (hOldBitmap != NULL)
  867. {
  868. SelectBitmap(m_usrWorkDC, hOldBitmap);
  869. }
  870. DebugExitVOID(ASHost::PMGetGrays);
  871. }
  872. //
  873. // FUNCTION: PMUpdateSystemPaletteColors
  874. //
  875. // DESCRIPTION:
  876. //
  877. // Determines whether the colors in the System Palette have changed since
  878. // the last time this function was called and if so, updates the supplied
  879. // palette so that it contains the same colors as the System Palette.
  880. //
  881. // The first time that this function is called after PM_Init the System
  882. // Palette colors will be returned and the function will return TRUE.
  883. //
  884. // PARAMETERS:
  885. //
  886. // shadowSystemPalette - handle of the palette to be updated with the
  887. // current System Palette colors
  888. //
  889. // RETURNS: TRUE if the System Palette has changed since the last call,
  890. // FALSE otherwise.
  891. //
  892. //
  893. BOOL ASHost::PMUpdateSystemPaletteColors(void)
  894. {
  895. BOOL rc = FALSE;
  896. PALETTEENTRY systemPaletteEntries[PM_NUM_8BPP_PAL_ENTRIES];
  897. HDC hdcScreen = NULL;
  898. UINT cbSystemPaletteEntries;
  899. int irgb, crgb, crgbFixed;
  900. DebugEntry(ASHost::PMUpdateSystemPaletteColors);
  901. ASSERT(g_usrPalettized);
  902. ASSERT(g_usrScreenBPP <= 8);
  903. ASSERT(m_usrSendingBPP <= 8);
  904. //
  905. // Don't bother with all this stuff if the system palette has not
  906. // changed at all. We track notifications to our UI to detect
  907. // palette changes.
  908. //
  909. if (!g_asSharedMemory->pmPaletteChanged)
  910. {
  911. DC_QUIT;
  912. }
  913. hdcScreen = GetDC(NULL);
  914. if (!hdcScreen)
  915. {
  916. WARNING_OUT(( "GetDC failed"));
  917. DC_QUIT;
  918. }
  919. if (GetSystemPaletteEntries(hdcScreen, 0, COLORS_FOR_BPP(g_usrScreenBPP),
  920. systemPaletteEntries) != (UINT)COLORS_FOR_BPP(g_usrScreenBPP))
  921. {
  922. WARNING_OUT(( "GetSystemPaletteEntries failed"));
  923. DC_QUIT;
  924. }
  925. //
  926. // Now that we have succesfully queried the system palette, we can
  927. // reset our flag.
  928. //
  929. g_asSharedMemory->pmPaletteChanged = FALSE;
  930. cbSystemPaletteEntries = COLORS_FOR_BPP(g_usrScreenBPP) * sizeof(PALETTEENTRY);
  931. //
  932. // See if the System Palette has changed from the last time we queried.
  933. //
  934. if (!memcmp(systemPaletteEntries, m_apmCurrentSystemPaletteEntries,
  935. cbSystemPaletteEntries ))
  936. {
  937. //
  938. // The System Palette has not changed
  939. //
  940. TRACE_OUT(( "System palette has NOT changed"));
  941. rc = TRUE;
  942. DC_QUIT;
  943. }
  944. //
  945. // Take a copy of the new System Palette.
  946. //
  947. memcpy(m_apmCurrentSystemPaletteEntries, systemPaletteEntries, cbSystemPaletteEntries );
  948. //
  949. // Update the current local paleete.
  950. //
  951. // NOTE FOR WIN95:
  952. // We need to add PC_NOCOLLAPSE to non-system palette entries.
  953. //
  954. if (g_asWin95)
  955. {
  956. if (GetSystemPaletteUse(hdcScreen) == SYSPAL_STATIC)
  957. crgbFixed = GetDeviceCaps(hdcScreen, NUMRESERVED) / 2;
  958. else
  959. crgbFixed = 1;
  960. crgb = COLORS_FOR_BPP(g_usrScreenBPP) - crgbFixed;
  961. for (irgb = crgbFixed; irgb < crgb; irgb++)
  962. {
  963. systemPaletteEntries[irgb].peFlags = PC_NOCOLLAPSE;
  964. }
  965. }
  966. SetPaletteEntries(m_pmTxPalette, 0, COLORS_FOR_BPP(g_usrScreenBPP),
  967. systemPaletteEntries );
  968. m_pmMustSendPalette = TRUE;
  969. //
  970. // SFR0407: The system palette has changed so re-fetch our set of RGBs
  971. // which the driver returns on an 8-bit GetDIBits for greys.
  972. //
  973. PMGetGrays();
  974. rc = TRUE;
  975. DC_EXIT_POINT:
  976. if (hdcScreen)
  977. {
  978. ReleaseDC(NULL, hdcScreen);
  979. }
  980. DebugExitBOOL(ASHost::PMUpdateSystemPaletteColors, rc);
  981. return(rc);
  982. }
  983. //
  984. // FUNCTION: PMUpdateTxPaletteColors
  985. //
  986. // DESCRIPTION:
  987. //
  988. // Returns the colors that make up the current Tx Palette (the palette that
  989. // is SENT from the local machine). These are not necessarily the colors
  990. // in the local machine's palette, because the local machine's bpp and the
  991. // protocol bpp may be different (e.g. on an 8bpp machine talking at 4bpp
  992. // the Tx Palette has 16 entries).
  993. //
  994. // PARAMETERS:
  995. //
  996. // pColorTable - pointer to an array of RGBQUADs which is filled with the
  997. // colors that make up the current Tx Palette.
  998. //
  999. // RETURNS: TRUE if successful, FALSE otherwise.
  1000. //
  1001. //
  1002. BOOL ASHost::PMUpdateTxPaletteColors(void)
  1003. {
  1004. UINT i;
  1005. UINT j;
  1006. BOOL rc = FALSE;
  1007. HDC hdcMem = NULL;
  1008. HBITMAP hbmpDummy = NULL;
  1009. HPALETTE hpalOld = NULL;
  1010. BITMAPINFO_ours pmBitmapInfo;
  1011. DebugEntry(ASHost::PMUpdateTxPaletteColors);
  1012. //
  1013. // Returns the values returned by a GetDIBits call with the
  1014. // m_pmTxPalette selected.
  1015. //
  1016. ASSERT(m_usrSendingBPP <= 8);
  1017. //
  1018. // If we are at 8bpp locally, and sending at 8bpp, then the TxPalette
  1019. // is simply the system palette.
  1020. //
  1021. if ((g_usrScreenBPP == 8) && (m_usrSendingBPP == 8))
  1022. {
  1023. PM_GetSystemPaletteEntries(pmBitmapInfo.bmiColors);
  1024. }
  1025. else
  1026. {
  1027. hdcMem = CreateCompatibleDC(NULL);
  1028. if (!hdcMem)
  1029. {
  1030. ERROR_OUT(("PMUpdateTxPaletteColors: couldn't create memory DC"));
  1031. DC_QUIT;
  1032. }
  1033. hpalOld = SelectPalette(hdcMem, m_pmTxPalette, TRUE);
  1034. RealizePalette(hdcMem);
  1035. #define DUMMY_WIDTH 8
  1036. #define DUMMY_HEIGHT 8
  1037. hbmpDummy = CreateBitmap(DUMMY_WIDTH, DUMMY_HEIGHT, 1,
  1038. g_usrScreenBPP, NULL);
  1039. if (hbmpDummy == NULL)
  1040. {
  1041. ERROR_OUT(( "Failed to create bitmap"));
  1042. DC_QUIT;
  1043. }
  1044. //
  1045. // Set up the structure required by GetDIBits.
  1046. //
  1047. pmBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1048. pmBitmapInfo.bmiHeader.biWidth = DUMMY_WIDTH;
  1049. pmBitmapInfo.bmiHeader.biHeight = DUMMY_HEIGHT;
  1050. pmBitmapInfo.bmiHeader.biPlanes = 1;
  1051. pmBitmapInfo.bmiHeader.biBitCount = (WORD)m_usrSendingBPP;
  1052. pmBitmapInfo.bmiHeader.biCompression = BI_RGB;
  1053. pmBitmapInfo.bmiHeader.biSizeImage = 0;
  1054. pmBitmapInfo.bmiHeader.biXPelsPerMeter = 10000;
  1055. pmBitmapInfo.bmiHeader.biYPelsPerMeter = 10000;
  1056. pmBitmapInfo.bmiHeader.biClrUsed = 0;
  1057. pmBitmapInfo.bmiHeader.biClrImportant = 0;
  1058. if (0 == GetDIBits( hdcMem,
  1059. hbmpDummy,
  1060. 0,
  1061. DUMMY_HEIGHT,
  1062. NULL,
  1063. (LPBITMAPINFO)&pmBitmapInfo.bmiHeader,
  1064. DIB_RGB_COLORS ))
  1065. {
  1066. WARNING_OUT(( "GetDIBits failed hdc(%x) hbmp(%x)",
  1067. HandleToUlong(hdcMem),
  1068. HandleToUlong(hbmpDummy)));
  1069. DC_QUIT;
  1070. }
  1071. SelectPalette(hdcMem, hpalOld, TRUE);
  1072. PM_AdjustColorsForBuggedDisplayDrivers(
  1073. (LPTSHR_RGBQUAD)pmBitmapInfo.bmiColors,
  1074. COLORS_FOR_BPP(m_usrSendingBPP));
  1075. //
  1076. // This doesn't work for VGA.
  1077. //
  1078. if (g_usrScreenBPP > 4)
  1079. {
  1080. //
  1081. // Check the new color table for any occurrences of the dodgy-grey
  1082. // RGBs which the display driver returns (getDIBits at 8bpp can
  1083. // return RGBs with unequal R, G and B for a supplied RGB with
  1084. // equal components, causing poor quality output).
  1085. //
  1086. for (i = COLORS_FOR_BPP(m_usrSendingBPP); i-- != 0;)
  1087. {
  1088. for ( j = 0; j < PM_GREY_COUNT; j++ )
  1089. {
  1090. if (!memcmp(&pmBitmapInfo.bmiColors[i],
  1091. &m_apmDDGreyRGB[j],
  1092. sizeof(pmBitmapInfo.bmiColors[i])) )
  1093. {
  1094. //
  1095. // Found a dodgy grey in the color table, so replace
  1096. // with a "good" grey, ie one with equal R, G and B.
  1097. //
  1098. pmBitmapInfo.bmiColors[i].rgbRed =
  1099. GetRValue(s_apmGreyRGB[j]);
  1100. pmBitmapInfo.bmiColors[i].rgbGreen =
  1101. GetGValue(s_apmGreyRGB[j]);
  1102. pmBitmapInfo.bmiColors[i].rgbBlue =
  1103. GetBValue(s_apmGreyRGB[j]);
  1104. TRACE_OUT(( "match our grey %#x", s_apmGreyRGB[j]));
  1105. break;
  1106. }
  1107. }
  1108. }
  1109. }
  1110. }
  1111. //
  1112. // If the colors have changed then return TRUE and copy the new color
  1113. // table back, else return FALSE.
  1114. //
  1115. if (!memcmp(m_apmTxPaletteColors, pmBitmapInfo.bmiColors,
  1116. COLORS_FOR_BPP(m_usrSendingBPP) * sizeof(RGBQUAD) ))
  1117. {
  1118. rc = FALSE;
  1119. }
  1120. else
  1121. {
  1122. memcpy(m_apmTxPaletteColors, pmBitmapInfo.bmiColors,
  1123. COLORS_FOR_BPP(m_usrSendingBPP) * sizeof(RGBQUAD) );
  1124. rc = TRUE;
  1125. }
  1126. DC_EXIT_POINT:
  1127. if (hbmpDummy != NULL)
  1128. {
  1129. DeleteBitmap(hbmpDummy);
  1130. }
  1131. if (hdcMem != NULL)
  1132. {
  1133. DeleteDC(hdcMem);
  1134. }
  1135. DebugExitDWORD(ASHost::PMUpdateTxPaletteColors, rc);
  1136. return(rc);
  1137. }
  1138. //
  1139. // FUNCTION: PMCreatePalette
  1140. //
  1141. // DESCRIPTION:
  1142. //
  1143. // Creates a new palette using the given colors.
  1144. //
  1145. // PARAMETERS:
  1146. //
  1147. // cEntries - number of entries in the pNewEntries array
  1148. //
  1149. // pNewEntries - pointer to a TSHR_COLOR array containing the new palette
  1150. // entries
  1151. //
  1152. // phPal - pointer to a HPALETTE variable that receives the new palette
  1153. // handle.
  1154. //
  1155. //
  1156. // RETURNS - TRUE if successful, FALSE otherwise.
  1157. //
  1158. //
  1159. BOOL ASShare::PM_CreatePalette
  1160. (
  1161. UINT cEntries,
  1162. LPTSHR_COLOR pNewEntries,
  1163. HPALETTE * phPal
  1164. )
  1165. {
  1166. UINT i;
  1167. BYTE pmLogPaletteBuffer[sizeof(LOGPALETTE) + (PM_NUM_8BPP_PAL_ENTRIES-1)*sizeof(PALETTEENTRY)];
  1168. LPLOGPALETTE pLogPalette;
  1169. BOOL rc = FALSE;
  1170. DebugEntry(ASShare::PM_CreatePalette);
  1171. ASSERT(cEntries <= PM_NUM_8BPP_PAL_ENTRIES);
  1172. //
  1173. // Set up a palette structure.
  1174. //
  1175. pLogPalette = (LPLOGPALETTE)pmLogPaletteBuffer;
  1176. // This is a random windows constant
  1177. pLogPalette->palVersion = 0x300;
  1178. pLogPalette->palNumEntries = (WORD)cEntries;
  1179. //
  1180. // This palette packet contains an array of TSHR_COLOR structures which
  1181. // contains 3 fields (RGB). We have to convert each of these
  1182. // structures to a PALETTEENTRY structure which has the same 3 fields
  1183. // (RGB) plus some flags.
  1184. //
  1185. for (i = 0; i < cEntries; i++)
  1186. {
  1187. TSHR_COLOR_TO_PALETTEENTRY( pNewEntries[i],
  1188. pLogPalette->palPalEntry[i] );
  1189. }
  1190. //
  1191. // Create the palette.
  1192. //
  1193. *phPal = CreatePalette(pLogPalette);
  1194. //
  1195. // Return TRUE if the palette was created.
  1196. //
  1197. rc = (*phPal != NULL);
  1198. DebugExitDWORD(ASShare::PM_CreatePalette, rc);
  1199. return(rc);
  1200. }
  1201. //
  1202. // FUNCTION: PM_AdjustColorsForBuggedDisplayDrivers
  1203. //
  1204. // DESCRIPTION:
  1205. //
  1206. // Adjusts the supplied color table if necessary to take account of display
  1207. // driver bugs.
  1208. //
  1209. // PARAMETERS:
  1210. //
  1211. // pColors - pointer to the color table (an array of RGBQUADs)
  1212. //
  1213. // cColors - number of colors in the supplied color table
  1214. //
  1215. // RETURNS: Nothing.
  1216. //
  1217. //
  1218. // NOTE: There is similar code in NormalizeRGB below (although not similar
  1219. // enough to macro it.) If you change this code you should probably do
  1220. // the same there.)
  1221. //
  1222. void ASHost::PM_AdjustColorsForBuggedDisplayDrivers
  1223. (
  1224. LPTSHR_RGBQUAD pColors,
  1225. UINT cColors
  1226. )
  1227. {
  1228. LPTSHR_RGBQUAD pColor;
  1229. UINT i;
  1230. DebugEntry(ASHost::PM_AdjustColorsForBuggedDisplayDrivers);
  1231. //
  1232. // The Win95 16bpp display drivers return wrong colors when querying at
  1233. // 8bpp. The palette depends on the driver itself (5-6-5, 6-5-5, 5-6-5,
  1234. // or 5-5-5). Only when R, G, and B have the same # of bits are we
  1235. // going to end up with an even distribution.
  1236. //
  1237. // Detect this case and try to adjust the colors.
  1238. //
  1239. m_pmBuggedDriver = ((g_usrScreenBPP > 8) &&
  1240. (pColors[1].rgbRed == 0) &&
  1241. (pColors[1].rgbGreen == 0) &&
  1242. (pColors[1].rgbBlue == 0x40));
  1243. if (m_pmBuggedDriver)
  1244. {
  1245. TRACE_OUT(( "Adjusting for bugged driver"));
  1246. pColor = pColors;
  1247. for (i = 0; i < cColors; i++)
  1248. {
  1249. PMADJUSTBUGGEDCOLOR(pColor);
  1250. pColor++;
  1251. }
  1252. }
  1253. DebugExitVOID(ASHost::PM_AdjustColorsForBuggedDisplayDrivers);
  1254. }
  1255. //
  1256. // FUNCTION: PM_DeletePalette
  1257. //
  1258. // DESCRIPTION:
  1259. //
  1260. // Deletes the given palette, if it is not the default palette.
  1261. //
  1262. // PARAMETERS:
  1263. //
  1264. // palette - palette to be deleted
  1265. //
  1266. // RETURNS: Nothing.
  1267. //
  1268. //
  1269. void ASShare::PM_DeletePalette(HPALETTE palette)
  1270. {
  1271. DebugEntry(ASShare::PM_DeletePalette);
  1272. if ((palette != NULL) &&
  1273. (palette != (HPALETTE)GetStockObject(DEFAULT_PALETTE)))
  1274. {
  1275. DeletePalette(palette);
  1276. }
  1277. DebugExitVOID(ASShare::PM_DeletePalette);
  1278. }
  1279.