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.

287 lines
8.8 KiB

  1. //*****************************************************************************
  2. //
  3. // DC Cacheing -
  4. //
  5. // Support for misbehaved apps - which continue to use a DC that has been
  6. // Released. Well the problem is WIN30 allows it, so we need to be
  7. // compatible.
  8. //
  9. //
  10. // 03-Feb-92 NanduriR Created.
  11. //
  12. //*****************************************************************************
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. MODNAME(wreldc.c);
  16. BOOL GdiCleanCacheDC (HDC hdc16);
  17. //*****************************************************************************
  18. // count of currently cached DCs so that we can quickly check whether any
  19. // ReleasedDCs are pending.
  20. //
  21. //*****************************************************************************
  22. INT iReleasedDCs = 0;
  23. //*****************************************************************************
  24. // The head of the linked list of the DCs Info.
  25. //
  26. //*****************************************************************************
  27. LPDCCACHE lpDCCache = NULL;
  28. //*****************************************************************************
  29. // ReleaseCachedDCs -
  30. // ReleaseDC's a cached DC if it meets the 'search criterion'.
  31. // The Search flag indicates which input arguments will be used.
  32. // Unused arguments can be NULL or pure garbage.
  33. //
  34. // NOTE: this does not free the memory that has been allocated for
  35. // the list.
  36. //
  37. // We reset the flag 'flState' and thus will be able to
  38. // reuse the structure.
  39. //
  40. // Returns TRUE
  41. //*****************************************************************************
  42. BOOL ReleaseCachedDCs(HAND16 htask16, HAND16 hwnd16, HAND16 hdc16,
  43. HWND hwnd32, UINT flSearch)
  44. {
  45. HAND16 hdcTemp;
  46. LPDCCACHE lpT;
  47. UNREFERENCED_PARAMETER(hdc16);
  48. if (iReleasedDCs) {
  49. for (lpT = lpDCCache; lpT != NULL; lpT = lpT->lpNext) {
  50. if (!(lpT->flState & DCCACHE_STATE_RELPENDING))
  51. continue;
  52. hdcTemp = (HAND16)NULL;
  53. if (flSearch & SRCHDC_TASK16_HWND16) {
  54. if (lpT->htask16 == htask16 &&
  55. lpT->hwnd16 == hwnd16)
  56. hdcTemp = lpT->hdc16;
  57. }
  58. else if (flSearch & SRCHDC_TASK16) {
  59. if (lpT->htask16 == htask16)
  60. hdcTemp = lpT->hdc16;
  61. }
  62. else {
  63. LOGDEBUG(0, ("ReleaseCachedDCs:Invalid Search Flag\n"));
  64. }
  65. if (hdcTemp) {
  66. if (ReleaseDC(lpT->hwnd32, HDC32(hdcTemp))) {
  67. LOGDEBUG(6,
  68. ("ReleaseCachedDCs: success hdc16 %04x - count %04x\n",
  69. hdcTemp, (iReleasedDCs-1)));
  70. }
  71. else {
  72. LOGDEBUG(7, ("ReleaseCachedDCs: FAILED hdc16 %04x\n",
  73. hdcTemp));
  74. }
  75. // reset the state evenif ReleaseDC failed
  76. lpT->flState = 0;
  77. if (!(--iReleasedDCs))
  78. break;
  79. }
  80. }
  81. }
  82. return TRUE;
  83. }
  84. //*****************************************************************************
  85. // FreeCachedDCs -
  86. // ReleaseDC's a cached DC - Normally called during taskexit.
  87. //
  88. // NOTE: this does not free the memory that has been allocated for
  89. // the list.
  90. //
  91. // We reset the flag 'flState' and thus will be able to
  92. // reuse the structure.
  93. //
  94. // Returns TRUE
  95. //*****************************************************************************
  96. BOOL FreeCachedDCs(HAND16 htask16)
  97. {
  98. HAND16 hdcTemp;
  99. LPDCCACHE lpT;
  100. for (lpT = lpDCCache; lpT != NULL; lpT = lpT->lpNext) {
  101. if ((lpT->flState & DCCACHE_STATE_INUSE) &&
  102. lpT->htask16 == htask16) {
  103. hdcTemp = lpT->hdc16;
  104. if (lpT->flState & DCCACHE_STATE_RELPENDING) {
  105. if (ReleaseDC(lpT->hwnd32, HDC32(hdcTemp))) {
  106. LOGDEBUG(6,
  107. ("FreeCachedDCs: success hdc16 %04x - task %04x\n",
  108. hdcTemp, htask16));
  109. }
  110. else {
  111. LOGDEBUG(7, ("FreeCachedDCs: FAILED hdc16 %04x - task %04x\n",
  112. hdcTemp, htask16));
  113. }
  114. WOW32ASSERT(iReleasedDCs != 0);
  115. --iReleasedDCs;
  116. }
  117. lpT->flState = 0;
  118. }
  119. }
  120. return TRUE;
  121. }
  122. //*****************************************************************************
  123. // StoredDC -
  124. //
  125. // Initializes a DCCACHE structure with appropriate values.
  126. // Uses an empty slot in the linked list if available else
  127. // allocates a new one and adds to the head of the list.
  128. //
  129. // Returns TRUE on success, FALSE on failure
  130. //*****************************************************************************
  131. BOOL StoreDC(HAND16 htask16, HAND16 hwnd16, HAND16 hdc16)
  132. {
  133. HAND16 hdcTemp = (HAND16)NULL;
  134. LPDCCACHE lpT, lpNew;
  135. // Check for an 'inuse' slot that will match the one that will be created
  136. // or check for an empty slot.
  137. //
  138. // An existing 'inuse' slot may match the one that's being created if
  139. // an app makes multiple calls to GetDC(hwnd) without an intervening
  140. // ReleaseDC. eg. MathCad.
  141. // - Nanduri
  142. lpNew = (LPDCCACHE)NULL;
  143. for (lpT = lpDCCache; lpT != NULL; lpT = lpT->lpNext) {
  144. if (lpT->flState & DCCACHE_STATE_INUSE) {
  145. if (lpT->hdc16 == hdc16) {
  146. if (lpT->hwnd16 == hwnd16 &&
  147. lpT->htask16 == htask16 ) {
  148. LOGDEBUG(6, ("WOW:An identical second GetDC call without ReleaseDC\n"));
  149. }
  150. else {
  151. LOGDEBUG(6, ("WOW:New DC 0x%04x exists - replacing old cache\n", hdc16));
  152. }
  153. if (lpT->flState & DCCACHE_STATE_RELPENDING) {
  154. WOW32ASSERT(iReleasedDCs != 0);
  155. --iReleasedDCs;
  156. }
  157. lpNew = lpT;
  158. break;
  159. }
  160. }
  161. else {
  162. if (!lpNew)
  163. lpNew = lpT;
  164. }
  165. }
  166. lpT = lpNew;
  167. if (lpT == NULL) {
  168. lpT = (LPDCCACHE)malloc_w_small(sizeof(DCCACHE));
  169. if (lpT) {
  170. lpT->lpNext = lpDCCache;
  171. lpDCCache = lpT;
  172. }
  173. else {
  174. LOGDEBUG(0, ("StoreDC: malloc_w_small for cache failed\n"));
  175. }
  176. }
  177. if (lpT != NULL) {
  178. lpT->flState = DCCACHE_STATE_INUSE;
  179. lpT->htask16 = htask16;
  180. lpT->hwnd16 = hwnd16;
  181. lpT->hdc16 = hdc16;
  182. lpT->hwnd32 = HWND32(hwnd16);
  183. LOGDEBUG(6, ("StoreDC: Added hdc %04x\n",hdc16));
  184. return TRUE;
  185. }
  186. else
  187. return FALSE;
  188. }
  189. //*****************************************************************************
  190. // CacheReleasedDC -
  191. //
  192. // Increments iReleasedDCs to indicate that a ReleaseDC is pending.
  193. //
  194. // Increments the iReleasedDC only if there was a corresponding GetDC.
  195. // i.e, only if the DC exists in the DCcache;
  196. //
  197. // This is to handle the scenrio below:
  198. // hdc = BeginPaint(hwnd,..);
  199. // ReleaseDC(hwnd, hdc);
  200. // EndPaint(hwnd, ..);
  201. //
  202. //
  203. // Returns TRUE on success, FALSE on failure
  204. //*****************************************************************************
  205. BOOL CacheReleasedDC(HAND16 htask16, HAND16 hwnd16, HAND16 hdc16)
  206. {
  207. HAND16 hdcTemp = (HAND16)NULL;
  208. LPDCCACHE lpT;
  209. for (lpT = lpDCCache; lpT != NULL; lpT = lpT->lpNext) {
  210. if ((lpT->flState & DCCACHE_STATE_INUSE) &&
  211. lpT->htask16 == htask16 &&
  212. lpT->hwnd16 == hwnd16 &&
  213. lpT->hdc16 == hdc16 ) {
  214. // the app might do releasedc twice on the same dc by mistake
  215. if (!(lpT->flState & DCCACHE_STATE_RELPENDING)) {
  216. lpT->flState |= DCCACHE_STATE_RELPENDING;
  217. iReleasedDCs++;
  218. }
  219. LOGDEBUG(6, ("CachedReleasedDC: Pending hdc %04x - count %04x\n",
  220. hdc16, iReleasedDCs));
  221. GdiCleanCacheDC (HDC32(hdc16));
  222. // Fix apps that draw then do lots
  223. // of disk activity, usually they do
  224. // a releaseDC. This flush will syncronize
  225. // the drawing with the beginning of the
  226. // disk activity. Bug #9704 PackRats install program draws text too late
  227. GdiFlush();
  228. return TRUE;
  229. }
  230. }
  231. return FALSE;
  232. }