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.

978 lines
28 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Contains miscellaneous engine helper functions.
  8. *
  9. * Revision History:
  10. *
  11. * 12/13/1998 andrewgo
  12. * Created it.
  13. *
  14. \**************************************************************************/
  15. #include "precomp.hpp"
  16. /**************************************************************************\
  17. *
  18. * Function Description:
  19. *
  20. * The kernel32.dll function InterlockedCompareExchange does not exist
  21. * on Win95, so we use this one instead when running on that platform.
  22. * Unfortunately, Win95 can run on 386 machines, which don't have the
  23. * cmpxchg instruction, so we have to roll it ourselves.
  24. *
  25. * Arguments:
  26. *
  27. *
  28. * Return Value:
  29. *
  30. * NONE
  31. *
  32. * History:
  33. *
  34. * 12/08/1998 andrewgo
  35. * Created it.
  36. *
  37. \**************************************************************************/
  38. LONG
  39. WINAPI
  40. InterlockedCompareExchangeWin95(
  41. IN OUT PLONG destination,
  42. IN LONG exchange,
  43. IN LONG comperand
  44. )
  45. {
  46. #if defined(_X86_)
  47. _asm cli // Disable interrupts to guarantee atomicity
  48. LONG initialValue = *destination;
  49. if (initialValue == comperand)
  50. {
  51. *destination = exchange;
  52. }
  53. _asm sti // Re-enable interrupts
  54. return(initialValue);
  55. #else
  56. return(0);
  57. #endif
  58. }
  59. /**************************************************************************\
  60. *
  61. * Function Description:
  62. *
  63. * The InterlockedIncrement function in Win95 returns only a positive
  64. * result if the value is positive, but not necessarily the resulting value.
  65. * This differs from WinNT semantics which always returns the incremented
  66. * value.
  67. *
  68. * Arguments:
  69. *
  70. * [IN] lpAddend - Pointer to value to increment
  71. *
  72. * Return Value:
  73. *
  74. * NONE
  75. *
  76. * History:
  77. *
  78. * 7/23/1999 ericvan
  79. * Created it.
  80. *
  81. \**************************************************************************/
  82. LONG
  83. WINAPI
  84. InterlockedIncrementWin95(
  85. IN LPLONG lpAddend
  86. )
  87. {
  88. #if defined(_X86_)
  89. _asm cli // Disable interrupts to guarantee atomicity
  90. *lpAddend += 1;
  91. LONG value = *lpAddend;
  92. _asm sti // Re-enable interrupts
  93. return(value);
  94. #else
  95. return(0);
  96. #endif
  97. }
  98. /**************************************************************************\
  99. *
  100. * Function Description:
  101. *
  102. * The InterlockedDecrement function in Win95 returns only a positive
  103. * result if the value is positive, but not necessarily the resulting value.
  104. * This differs from WinNT semantics which always returns the incremented
  105. * value.
  106. *
  107. * Arguments:
  108. *
  109. * [IN] lpAddend - Pointer to value to increment
  110. *
  111. * Return Value:
  112. *
  113. * NONE
  114. *
  115. * History:
  116. *
  117. * 7/23/1999 ericvan
  118. * Created it.
  119. *
  120. \**************************************************************************/
  121. LONG
  122. WINAPI
  123. InterlockedDecrementWin95(
  124. IN LPLONG lpAddend
  125. )
  126. {
  127. #if defined(_X86_)
  128. _asm cli // Disable interrupts to guarantee atomicity
  129. *lpAddend -= 1;
  130. LONG value = *lpAddend;
  131. _asm sti // Re-enable interrupts
  132. return(value);
  133. #else
  134. return(0);
  135. #endif
  136. }
  137. /**************************************************************************\
  138. *
  139. * Function Description:
  140. *
  141. * Given a DC to an enhanced metafile, this function determines whether
  142. * the DC is actually a printer DC or a true metafile DC.
  143. *
  144. * After spending a day pouring over the Win9x GDI code, I could find
  145. * no fool-proof API accessible method of determining whether a metafile
  146. * DC is a printer DC or not. We could potentially crack the DC handle
  147. * to get the DCTYPE structure and look at flPrinting to see if
  148. * PR_EMF_SPOOL is set, but the various flavors of Win9x have different
  149. * DCTYPE structures (including Far East differences).
  150. *
  151. * The only exploitable difference is the fact that Win9x doesn't allow
  152. * escapes down to the associated device for true metafile DCs, but does
  153. * for metafile print DCs. We check for the support of QUERYESCSUPPORT,
  154. * which according to the DDK all drivers are required to support, but
  155. * theoretically there are some that might not (so this method isn't
  156. * foolproof).
  157. *
  158. * Note that this function works only on Win9x, as on NT escapes are
  159. * allowed down to the printer at record time even for true metafile DCs.
  160. *
  161. * Arguments:
  162. *
  163. * [IN] hdc - Handle to an EMF DC
  164. *
  165. * Return Value:
  166. *
  167. * TRUE - The DC is guaranteed to be a printer DC
  168. * FALSE - The DC is 99% likely to be a true metafile (there's about a 1%
  169. * change that the DC is a true printer DC
  170. *
  171. * History:
  172. *
  173. * 10/6/1999 andrewgo
  174. * Created it.
  175. *
  176. \**************************************************************************/
  177. BOOL
  178. APIENTRY
  179. GdiIsMetaPrintDCWin9x(
  180. HDC hdc
  181. )
  182. {
  183. BOOL isPrint = FALSE;
  184. // Our check won't work for OBJ_DC or OBJ_MEMDC types:
  185. ASSERT(GetDCType(hdc) == OBJ_ENHMETADC);
  186. // Make sure we don't get any false positives from metafiles associated
  187. // with a display:
  188. int deviceCaps = GetDeviceCaps(hdc, TECHNOLOGY);
  189. if ((deviceCaps == DT_RASPRINTER) || (deviceCaps == DT_PLOTTER))
  190. {
  191. // Check to see if QUERYESCSUPPORT is supported by the driver
  192. // (if it is, that tells us everything we need to know!)
  193. DWORD queryEscape = QUERYESCSUPPORT;
  194. isPrint = (ExtEscape(hdc,
  195. QUERYESCSUPPORT,
  196. sizeof(queryEscape),
  197. (CHAR*) &queryEscape,
  198. 0,
  199. NULL) > 0);
  200. if (!isPrint)
  201. {
  202. // SETCOPYCOUNT is the most commonly supported printer escape,
  203. // which we check in addition to QUERYESCSUPPORT because I'm a
  204. // little paranoid that drivers might forget to say they support
  205. // the QUERYESCSUPPORT function when called by QUERYESCSUPPORT.
  206. DWORD setCopyCount = SETCOPYCOUNT;
  207. isPrint = (ExtEscape(hdc,
  208. QUERYESCSUPPORT,
  209. sizeof(setCopyCount),
  210. (CHAR*) &setCopyCount,
  211. 0,
  212. NULL) > 0);
  213. }
  214. }
  215. return(isPrint);
  216. }
  217. //
  218. // 32 bit ANSI X3.66 CRC checksum table - polynomial 0xedb88320
  219. //
  220. // Copyright (C) 1986 Gary S. Brown. You may use this program, or
  221. // code or tables extracted from it, as desired without restriction.
  222. //
  223. static const UINT32 Crc32Table[] =
  224. {
  225. 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
  226. 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
  227. 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
  228. 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
  229. 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
  230. 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
  231. 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
  232. 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
  233. 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
  234. 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
  235. 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
  236. 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
  237. 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
  238. 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
  239. 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  240. 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
  241. 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
  242. 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
  243. 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
  244. 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
  245. 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
  246. 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
  247. 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
  248. 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
  249. 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
  250. 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
  251. 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
  252. 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
  253. 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
  254. 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
  255. 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
  256. 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
  257. };
  258. /**************************************************************************\
  259. *
  260. * Function Description:
  261. *
  262. * Compute the 32-bit CRC checksum on a buffer of data
  263. *
  264. * Arguments:
  265. *
  266. * buf - Points to the data buffer to be checksumed
  267. * size - Size of the data buffer, in bytes
  268. * checksum - Initial checksum value
  269. *
  270. * Return Value:
  271. *
  272. * Resulting checksum value
  273. *
  274. \**************************************************************************/
  275. UINT32
  276. Crc32(
  277. IN const VOID* buf,
  278. IN UINT size,
  279. IN UINT32 checksum
  280. )
  281. {
  282. const BYTE* p = (const BYTE*) buf;
  283. while (size--)
  284. {
  285. checksum = Crc32Table[(checksum ^ *p++) & 0xff] ^ (checksum >> 8);
  286. }
  287. return checksum;
  288. }
  289. /**************************************************************************\
  290. *
  291. * Function Description:
  292. *
  293. * Convert a floating-point coordinate bounds to an integer pixel bounds.
  294. *
  295. * Since we're converting bounds from float to int, we have to make sure
  296. * that the bounds are still encompassing of the object. So we have to take
  297. * the floor of the left and top values, even though the rasterizer takes
  298. * the ceiling. The reason for this is that the rasterizer uses 28.4 fixed
  299. * point. So a number like 52.001 converts to 52.0 in 28.4, so the ceiling
  300. * in the rasterizer would be 52, whereas the ceiling of the original number
  301. * is 53, but if we return 53 here, then we would be incorrect. It's better
  302. * to be too big here sometimes and still have all-encompassing bounds, than
  303. * to be right most of the time, but have too small a bounds the other times.
  304. *
  305. * The other caveat is that we need to calculate the bounds assuming the
  306. * result will be used for antialiasing (the bounds antialiased fills are
  307. * bigger than the bounds for aliased fills).
  308. *
  309. * NOTE: This conversion implicitly assumes that a fill is done on the
  310. * figure vertices. Nominal-width lines REQUIRE the caller to
  311. * have increased all the dimensions by 1/2 before calling!
  312. *
  313. * Arguments:
  314. *
  315. * Return Value:
  316. *
  317. * Ok for success, ValueOverflow if the boundsF would overflow the
  318. * integer size. rect is always initialized - for ValueOverflow, its
  319. * set to zero.
  320. *
  321. \**************************************************************************/
  322. #define INT_BOUNDS_MAX 1073741823
  323. #define INT_BOUNDS_MIN -1073741824
  324. GpStatus
  325. BoundsFToRect(
  326. const GpRectF *boundsF,
  327. GpRect *rect // Lower-right exclusive
  328. )
  329. {
  330. // If you're wondering what the "+1" is doing below, read the
  331. // above comment and remember that we're calculating the bounds
  332. // assuming antialiased fills.
  333. //
  334. // The tightest bound for an antialiased fill would truly be:
  335. //
  336. // [round(min - epsilon), round(max + epsilon) + 1)
  337. //
  338. // Where 'epsilon' is the epsilon for rounding to our internal
  339. // 28.4 rasterization precision, which is 1/32 of a pixel,
  340. // and [left, right) is exclusive of the right pixel.
  341. //
  342. // We skip the 'round' and 'epsilon' business by using 'floor'
  343. // and 'ceiling':
  344. GpStatus status = Ok;
  345. if(boundsF->X >= INT_BOUNDS_MIN && boundsF->X <= INT_BOUNDS_MAX)
  346. {
  347. rect->X = GpFloor(boundsF->X);
  348. }
  349. else
  350. {
  351. status = ValueOverflow;
  352. }
  353. if((status == Ok) && (boundsF->Y >= INT_BOUNDS_MIN) &&
  354. (boundsF->Y <= INT_BOUNDS_MAX))
  355. {
  356. rect->Y = GpFloor(boundsF->Y);
  357. }
  358. else
  359. {
  360. status = ValueOverflow;
  361. }
  362. if((status == Ok) && (boundsF->Width >= 0) &&
  363. (boundsF->Width <= INT_BOUNDS_MAX))
  364. {
  365. rect->Width = GpCeiling(boundsF->GetRight()) - rect->X + 1;
  366. }
  367. else
  368. {
  369. status = ValueOverflow;
  370. }
  371. if((status == Ok) && (boundsF->Height >= 0) &&
  372. (boundsF->Height <= INT_BOUNDS_MAX))
  373. {
  374. rect->Height = GpCeiling(boundsF->GetBottom()) - rect->Y + 1;
  375. }
  376. else
  377. {
  378. status = ValueOverflow;
  379. }
  380. if(status != Ok)
  381. {
  382. // Make sure the rect is always initialized.
  383. // Also this makes the ASSERT below valid.
  384. rect->Width = 0;
  385. rect->Height = 0;
  386. rect->X = 0;
  387. rect->Y = 0;
  388. }
  389. // Don't forget that 'Width' and 'Height' are effectively
  390. // lower-right exclusive. That is, if (x, y) are (1, 1) and
  391. // (width, height) are (2, 2), then the object is 2 pixels by
  392. // 2 pixels in size, and does not touch any pixels in column
  393. // 3 or row 3:
  394. ASSERT((rect->Width >= 0) && (rect->Height >= 0));
  395. return status;
  396. }
  397. /**************************************************************************\
  398. *
  399. * Function Description:
  400. *
  401. * This seems to be some sort of unit conversion function.
  402. *
  403. * Arguments:
  404. *
  405. * Return Value:
  406. *
  407. \**************************************************************************/
  408. REAL GetDeviceWidth(REAL width, GpUnit unit, REAL dpi)
  409. {
  410. // UnitWorld cannot be used for this method.
  411. // UnitDisplay is device-dependent and cannot be used as a pen width unit
  412. ASSERT((unit != UnitWorld) && (unit != UnitDisplay));
  413. REAL deviceWidth = width;
  414. switch (unit)
  415. {
  416. case UnitPoint: // Each unit represents 1/72 inch.
  417. deviceWidth *= dpi / 72.0f;
  418. break;
  419. case UnitInch: // Each unit represents 1 inch.
  420. deviceWidth *= dpi;
  421. break;
  422. case UnitDocument: // Each unit represents 1/300 inch.
  423. deviceWidth *= dpi / 300.0f;
  424. break;
  425. case UnitMillimeter: // Each unit represents 1 millimeter.
  426. // One Millimeter is 0.03937 inches
  427. // One Inch is 25.4 millimeters
  428. deviceWidth *= dpi / 25.4f;
  429. break;
  430. default: // this should not happen, if it does assume
  431. // UnitPixel.
  432. ASSERT(0);
  433. // FALLTHRU
  434. case UnitPixel: // Each unit represents one device pixel.
  435. break;
  436. }
  437. return deviceWidth;
  438. }
  439. /**************************************************************************\
  440. *
  441. * Function Description:
  442. *
  443. * Given two coordinates defining opposite corners of a rectangle, this
  444. * routine transforms the rectangle according to the specified transform
  445. * and computes the resulting integer bounds, taking into account the
  446. * possibility of non-scaling transforms.
  447. *
  448. * Note that it operates entirely in floating point, and as such takes
  449. * no account of rasterization rules, pen width, etc.
  450. *
  451. * Arguments:
  452. *
  453. * [IN] matrix - Transform to be applied (or NULL)
  454. * [IN] x0, y0, x1, y1 - 2 points defining the bounds (they don't have
  455. * to be well ordered)
  456. * [OUT] bounds - Resulting (apparently floating point) bounds
  457. *
  458. * Return Value:
  459. *
  460. * NONE
  461. *
  462. * History:
  463. *
  464. * 12/08/1998 andrewgo
  465. * Created it.
  466. *
  467. \**************************************************************************/
  468. VOID
  469. TransformBounds(
  470. const GpMatrix *matrix,
  471. REAL left,
  472. REAL top,
  473. REAL right,
  474. REAL bottom,
  475. GpRectF *bounds
  476. )
  477. {
  478. // Note that we don't have to order the points before the transform
  479. // (in part because the transform may flip the points anyways):
  480. if (matrix && !matrix->IsIdentity())
  481. {
  482. GpPointF vertex[4];
  483. vertex[0].X = left;
  484. vertex[0].Y = top;
  485. vertex[1].X = right;
  486. vertex[1].Y = bottom;
  487. // If the transform is a simple scaling transform, life is a little
  488. // easier:
  489. if (matrix->IsTranslateScale())
  490. {
  491. matrix->Transform(vertex, 2);
  492. // We arrange the code here a little so that we don't take a
  493. // jump on the common case, where the transform is non-flipping:
  494. left = vertex[1].X;
  495. right = vertex[0].X;
  496. if (left > right)
  497. {
  498. left = vertex[0].X;
  499. right = vertex[1].X;
  500. }
  501. top = vertex[1].Y;
  502. bottom = vertex[0].Y;
  503. if (top > bottom)
  504. {
  505. top = vertex[0].Y;
  506. bottom = vertex[1].Y;
  507. }
  508. }
  509. else
  510. {
  511. // Ugh, the result is not a rectangle in device space (it might be
  512. // a parallelogram, for example). Consequently, we have to look at
  513. // the bounds of all the vertices:
  514. vertex[2].X = left;
  515. vertex[2].Y = bottom;
  516. vertex[3].X = right;
  517. vertex[3].Y = top;
  518. matrix->Transform(vertex, 4);
  519. left = right = vertex[0].X;
  520. top = bottom = vertex[0].Y;
  521. for (INT i = 1; i < 4; i++)
  522. {
  523. if (left > vertex[i].X)
  524. left = vertex[i].X;
  525. if (right < vertex[i].X)
  526. right = vertex[i].X;
  527. if (top > vertex[i].Y)
  528. top = vertex[i].Y;
  529. if (bottom < vertex[i].Y)
  530. bottom = vertex[i].Y;
  531. }
  532. ASSERT((left <= right) && (top <= bottom));
  533. }
  534. }
  535. bounds->X = left;
  536. bounds->Y = top;
  537. //!!! Watch out for underflow.
  538. if(right - left > CPLX_EPSILON)
  539. bounds->Width = right - left;
  540. else
  541. bounds->Width = 0;
  542. if(bottom - top > CPLX_EPSILON)
  543. bounds->Height = bottom - top;
  544. else
  545. bounds->Height = 0;
  546. }
  547. /**************************************************************************\
  548. *
  549. * Function Description:
  550. *
  551. * Checks if the current semaphore object is locked. This is moved into
  552. * a C++ file because of the dependency on globals.hpp. On Win9x this
  553. * function always returns TRUE.
  554. *
  555. * Arguments:
  556. *
  557. * NONE
  558. *
  559. * Return Value:
  560. *
  561. * BOOL
  562. *
  563. * History:
  564. *
  565. * 1/27/1999 ericvan Moved from engine.hpp
  566. *
  567. \**************************************************************************/
  568. BOOL
  569. GpSemaphore::IsLocked(
  570. VOID
  571. )
  572. {
  573. ASSERT(Initialized);
  574. if (Globals::IsNt)
  575. {
  576. return(((RTL_CRITICAL_SECTION*) &CriticalSection)->LockCount != -1);
  577. }
  578. else
  579. {
  580. return TRUE; // No way to do this on Win95
  581. }
  582. }
  583. /**************************************************************************\
  584. *
  585. * Function Description:
  586. *
  587. * Checks if the current semaphore object is locked by current thread.
  588. * This is moved into a C++ file because of the dependency on globals.hpp.
  589. * On Win9x this function always returns TRUE.
  590. *
  591. * Arguments:
  592. *
  593. * NONE
  594. *
  595. * Return Value:
  596. *
  597. * BOOL
  598. *
  599. * History:
  600. *
  601. * 1/27/1999 ericvan Moved from engine.hpp
  602. *
  603. \**************************************************************************/
  604. BOOL
  605. GpSemaphore::IsLockedByCurrentThread(
  606. VOID
  607. )
  608. {
  609. ASSERT(Initialized);
  610. if (Globals::IsNt)
  611. {
  612. return(((RTL_CRITICAL_SECTION*) &CriticalSection)->OwningThread ==
  613. (HANDLE) (DWORD_PTR) GetCurrentThreadId());
  614. }
  615. else
  616. {
  617. return TRUE; // No way to do this on Win9x
  618. }
  619. }
  620. /**************************************************************************\
  621. *
  622. * Function Description:
  623. *
  624. * Uninitializes the critical section object.
  625. * This is moved into a C++ file because of the dependency on globals.hpp.
  626. * On Win9x this function skips the IsLocked() check.
  627. *
  628. * Arguments:
  629. *
  630. * NONE
  631. *
  632. * Return Value:
  633. *
  634. * BOOL
  635. *
  636. * History:
  637. *
  638. * 1/27/1999 ericvan Moved from engine.hpp
  639. *
  640. \**************************************************************************/
  641. VOID
  642. GpSemaphore::Uninitialize(
  643. VOID
  644. )
  645. {
  646. #ifdef DBG
  647. if (Globals::IsNt)
  648. {
  649. ASSERTMSG(!IsLocked(), ("Semaphore can't be locked when deleted"));
  650. }
  651. #endif
  652. if (Initialized)
  653. {
  654. DeleteCriticalSection(&CriticalSection);
  655. Initialized = FALSE;
  656. }
  657. }
  658. #if defined(_X86_)
  659. /**************************************************************************\
  660. *
  661. * Function Description:
  662. *
  663. * This is a common function used by GetObjectTypeInternal and GetDCType.
  664. * It should not be called elsewhere.
  665. *
  666. * NOTE: On Windows 9x, two GDI objects may have the same handle value, if
  667. * one is OBJ_METAFILE and the other is anything else. In this case
  668. * of colliding object handles, GetObjectType will always return
  669. * OBJ_METAFILE. This function temporarily invalidates the metafile
  670. * so GetObjectType will skip that check and return the type of the
  671. * colliding object. If no colliding object is found, or if OBJ_*DC
  672. * is returned, this function returns 0. OBJ_*DC objects may not be
  673. * "present" (available in 16-bit) sometimes, and so the wrong value
  674. * can be returned since GetObjectType does not make such a DC
  675. * "present".
  676. *
  677. * Arguments:
  678. *
  679. * [IN] handle - GDI object handle (not when expecting OBJ_METAFILE)
  680. *
  681. * Return Value:
  682. *
  683. * GDI object type identifier on success or 0 on failure
  684. *
  685. * History:
  686. *
  687. * 01/25/2001 johnstep
  688. * Created it.
  689. *
  690. \**************************************************************************/
  691. static
  692. DWORD
  693. GetObjectTypeWin9x(
  694. IN HGDIOBJ handle
  695. )
  696. {
  697. // Disable interrupts around this code to prevent other threads from
  698. // attempting to access this object, in case this is a collision, which
  699. // means we must modify the metafile object directly via the selector.
  700. __asm cli
  701. DWORD type = GetObjectType(handle);
  702. // If there are 2 objects with the same handle, one being an OBJ_METAFILE
  703. // and the other not, OBJ_METAFILE is always returned. Since the caller
  704. // is not interested in a metafile, do a hack here to skip the metafile
  705. // check and find the type of the colliding object, if any.
  706. if (type == OBJ_METAFILE)
  707. {
  708. // The first WORD of a metafile must contain 1 or 2, and we wouldn't
  709. // be here if it didn't. This macro will toggle a higher bit in the
  710. // first word to defeat the metafile check, allowing us to proceed to
  711. // the normal object check.
  712. #define XOR_METAFILE_BIT(selector)\
  713. __asm push gs\
  714. __asm mov gs, word ptr selector\
  715. __asm xor word ptr gs:[0], 8\
  716. __asm pop gs
  717. XOR_METAFILE_BIT(handle);
  718. type = GetObjectType(handle);
  719. XOR_METAFILE_BIT(handle);
  720. }
  721. // Make sure to reenable interrupts before returning.
  722. __asm sti
  723. return type;
  724. }
  725. #endif
  726. /**************************************************************************\
  727. *
  728. * Function Description:
  729. *
  730. * This is a workaround for a serious bug in Windows 9x GetObjectType
  731. * implementation. This function correctly returns the object type for the
  732. * given handle, unless it's an OBJ_*DC or OBJ_METAFILE. For those types,
  733. * it shouldn't crash, but it will intermittently return 0 instead of the
  734. * correct type.
  735. *
  736. * For OBJ_*DC types, use GetDCType. You can validate an OBJ_METAFILE with
  737. * IsValidMetaFile, but you need to expect it to be a metafile handle. If
  738. * you don't know which of the 3 classes your handle falls into, you'll
  739. * need to expand on these workaround functions.
  740. *
  741. * NOTE: On Windows 9x, two GDI objects may have the same handle value, if
  742. * one is OBJ_METAFILE and the other is anything else. In this case
  743. * of colliding object handles, GetObjectType will always return
  744. * OBJ_METAFILE. This function temporarily invalidates the metafile
  745. * so GetObjectType will skip that check and return the type of the
  746. * colliding object. If no colliding object is found, or if OBJ_*DC
  747. * is returned, this function returns 0. OBJ_*DC objects may not be
  748. * "present" (available in 16-bit) sometimes, and so the wrong value
  749. * can be returned since GetObjectType does not make such a DC
  750. * "present".
  751. *
  752. * Arguments:
  753. *
  754. * [IN] handle - GDI object handle (not to verify for OBJ_METAFILE)
  755. *
  756. * Return Value:
  757. *
  758. * GDI object type identifier on success or 0 on failure
  759. *
  760. * History:
  761. *
  762. * 01/25/2001 johnstep
  763. * Created it.
  764. *
  765. \**************************************************************************/
  766. DWORD
  767. GetObjectTypeInternal(
  768. IN HGDIOBJ handle
  769. )
  770. {
  771. #if defined(_X86_)
  772. if (!Globals::IsNt)
  773. {
  774. DWORD type = GetObjectTypeWin9x(handle);
  775. switch (type)
  776. {
  777. case OBJ_DC:
  778. case OBJ_METADC:
  779. case OBJ_MEMDC:
  780. case OBJ_ENHMETADC:
  781. type = 0;
  782. break;
  783. }
  784. return type;
  785. }
  786. #else
  787. // We assume that this issue only matters on x86.
  788. ASSERT(Globals::IsNt);
  789. #endif
  790. return GetObjectType(handle);
  791. }
  792. /**************************************************************************\
  793. *
  794. * Function Description:
  795. *
  796. * GetObjectType on Win9x is unreliable when dealing with DC objects. It
  797. * is possible to get a bogus value (or potentially even lead to
  798. * instability in GDI) when a DC is not "present", which means its 16-bit
  799. * data has been "swapped out" into 32-bit. Most GDI functions handle
  800. * this, but GetObjectType does not. We call GetPixel to attempt to make
  801. * the DC present before calling GetObjectType.
  802. *
  803. * Arguments:
  804. *
  805. * [IN] hdc - DC handle
  806. *
  807. * Return Value:
  808. *
  809. * DC object type identifier on success or 0 on failure
  810. *
  811. * History:
  812. *
  813. * 01/31/2001 johnstep
  814. * Created it.
  815. *
  816. \**************************************************************************/
  817. DWORD
  818. GetDCType(
  819. IN HDC hdc
  820. )
  821. {
  822. #if defined(_X86_)
  823. if (!Globals::IsNt)
  824. {
  825. // Force the DC present here before attempting to inquire the type.
  826. GetPixel(hdc, 0, 0);
  827. DWORD type = GetObjectTypeWin9x(hdc);
  828. switch (type)
  829. {
  830. case OBJ_DC:
  831. case OBJ_METADC:
  832. case OBJ_MEMDC:
  833. case OBJ_ENHMETADC:
  834. break;
  835. default:
  836. // We got an unexpected object type, so return 0 to indicate
  837. // failure.
  838. type = 0;
  839. }
  840. return type;
  841. }
  842. #else
  843. // We assume that this issue only matters on x86.
  844. ASSERT(Globals::IsNt);
  845. #endif
  846. return GetObjectType(hdc);
  847. }