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.

2994 lines
85 KiB

  1. /*----------------------------------------------------------------------------*\
  2. * GDIHELP.C - GDI TOOLHELP
  3. *
  4. * a bunch of GDI utility functions that are usefull for walking
  5. * all GDI objects and dinking with them.
  6. *
  7. * ToddLa
  8. *
  9. \*----------------------------------------------------------------------------*/
  10. #ifdef IS_16
  11. #define DIRECT_DRAW
  12. #endif
  13. #ifdef DIRECT_DRAW
  14. #include "ddraw16.h"
  15. #else
  16. #include <windows.h>
  17. #include "gdihelp.h"
  18. #include "dibeng.inc"
  19. #ifdef DEBUG
  20. #include <toolhelp.h>
  21. #endif
  22. #endif
  23. /*----------------------------------------------------------------------------*\
  24. \*----------------------------------------------------------------------------*/
  25. #undef DPF
  26. #ifdef DEBUG
  27. static void CDECL DPF(char *sz, ...)
  28. {
  29. char ach[128];
  30. lstrcpy(ach,"QuickRes: ");
  31. wvsprintf(ach+10, sz, (LPVOID)(&sz+1));
  32. #ifdef DIRECT_DRAW
  33. dprintf(2, ach);
  34. #else
  35. lstrcat(ach, "\r\n");
  36. OutputDebugString(ach);
  37. #endif
  38. }
  39. static void NEAR PASCAL __Assert(char *exp, char *file, int line)
  40. {
  41. DPF("Assert(%s) failed at %s line %d.", (LPSTR)exp, (LPSTR)file, line);
  42. DebugBreak();
  43. }
  44. #define Assert(exp) ( (exp) ? (void)0 : __Assert(#exp,__FILE__,__LINE__) )
  45. #else
  46. #define Assert(f)
  47. #define DPF ; / ## /
  48. #endif
  49. /*----------------------------------------------------------------------------*\
  50. \*----------------------------------------------------------------------------*/
  51. extern HMODULE WINAPI GetExePtr(HANDLE h);
  52. extern HANDLE WINAPI SetObjectOwner(HGDIOBJ, HANDLE);
  53. extern BOOL WINAPI MakeObjectPrivate(HANDLE hObj, BOOL bPrivate);
  54. extern int WINAPI GDISelectPalette(HDC, HPALETTE, BOOL);
  55. #define PresDC(hdc) GetSystemPaletteUse(hdc)
  56. void SaveDCFix(HGDIOBJ h, LPARAM lParam);
  57. void SaveDCReSelectObjects(HGDIOBJ h, LPARAM lParam);
  58. void ReRealizeObject(HGDIOBJ h, LPARAM lParam);
  59. void ReSelectObjects(HGDIOBJ h, LPARAM lParam);
  60. typedef struct {
  61. BITMAPINFOHEADER bi;
  62. DWORD ct[16];
  63. } DIB4;
  64. typedef struct {
  65. BITMAPINFOHEADER bi;
  66. DWORD ct[256];
  67. } DIB8;
  68. typedef struct {
  69. HGDIOBJ h;
  70. UINT type;
  71. } GDIOBJECT, NEAR *GDIOBJECTLIST;
  72. GDIOBJECTLIST GdiObjectList;
  73. WORD GetW(HGDIOBJ h, UINT off);
  74. WORD SetW(HGDIOBJ h, UINT off, WORD w);
  75. /*----------------------------------------------------------------------------*\
  76. * StockBitmap
  77. * return the stock 1x1x1 bitmap, windows should have a GetStockObject for
  78. * this but it does not.
  79. \*----------------------------------------------------------------------------*/
  80. HBITMAP StockBitmap()
  81. {
  82. HBITMAP hbm = CreateBitmap(0,0,1,1,NULL);
  83. SetObjectOwner(hbm, 0);
  84. return hbm;
  85. }
  86. /*----------------------------------------------------------------------------*\
  87. * SafeSelectObject
  88. *
  89. * call SelectObject, but make sure USER does not RIP because we are using
  90. * a DC without calling GetDC.
  91. \*----------------------------------------------------------------------------*/
  92. HGDIOBJ SafeSelectObject(HDC hdc, HGDIOBJ h)
  93. {
  94. UINT hf;
  95. // this prevents USER from RIPing because we are using
  96. // DCs in the cache without calling GetDC()
  97. hf = SetHookFlags(hdc, DCHF_VALIDATEVISRGN);
  98. h = SelectObject(hdc, h);
  99. SetHookFlags(hdc, hf);
  100. return h;
  101. }
  102. /*----------------------------------------------------------------------------*\
  103. * IsMemoryDC
  104. *
  105. * return TRUE if the passed DC is a memory DC. we do this seeing if we
  106. * can select the stock bitmap into it.
  107. \*----------------------------------------------------------------------------*/
  108. BOOL IsMemoryDC(HDC hdc)
  109. {
  110. HBITMAP hbm;
  111. if (hbm = (HBITMAP)SafeSelectObject(hdc, StockBitmap()))
  112. SafeSelectObject(hdc, hbm);
  113. return hbm != NULL;
  114. }
  115. /*----------------------------------------------------------------------------*\
  116. * IsScreenDC
  117. *
  118. * return TRUE for a non-memory DC
  119. \*----------------------------------------------------------------------------*/
  120. BOOL IsScreenDC(HDC hdc)
  121. {
  122. return (!IsMemoryDC(hdc) && GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY);
  123. }
  124. /*----------------------------------------------------------------------------*\
  125. * GetObjectOwner
  126. * return the owner of a GDI object
  127. \*----------------------------------------------------------------------------*/
  128. HANDLE GetObjectOwner(HGDIOBJ h)
  129. {
  130. HANDLE owner;
  131. owner = SetObjectOwner(h, 0);
  132. SetObjectOwner(h, owner);
  133. return owner;
  134. }
  135. /*----------------------------------------------------------------------------*\
  136. \*----------------------------------------------------------------------------*/
  137. BOOL IsObjectPrivate(HGDIOBJ h)
  138. {
  139. BOOL IsPrivate;
  140. IsPrivate = MakeObjectPrivate(h, 0);
  141. MakeObjectPrivate(h, IsPrivate);
  142. return IsPrivate;
  143. }
  144. /*----------------------------------------------------------------------------*\
  145. \*----------------------------------------------------------------------------*/
  146. BOOL IsObjectStock(HGDIOBJ h)
  147. {
  148. int n;
  149. for (n=0; n<=17; n++)
  150. if (GetStockObject(n) == h)
  151. return TRUE;
  152. if (StockBitmap() == h)
  153. return TRUE;
  154. return FALSE;
  155. }
  156. /*----------------------------------------------------------------------------*\
  157. \*----------------------------------------------------------------------------*/
  158. #pragma optimize("", off)
  159. UINT GetGdiDS()
  160. {
  161. UINT result;
  162. IsGDIObject((HGDIOBJ)1);
  163. _asm mov ax,es
  164. _asm mov result,ax
  165. #ifdef DEBUG
  166. {
  167. SYSHEAPINFO shi = {sizeof(shi)};
  168. SystemHeapInfo(&shi);
  169. Assert((UINT)shi.hGDISegment == result);
  170. }
  171. #endif
  172. return result;
  173. }
  174. #pragma optimize("", on)
  175. /*----------------------------------------------------------------------------*\
  176. \*----------------------------------------------------------------------------*/
  177. GDIOBJECTLIST BuildGdiObjectList(void)
  178. {
  179. int i;
  180. int count;
  181. GDIOBJECTLIST list;
  182. UINT type;
  183. UINT hgdi = GetGdiDS();
  184. #ifdef DEBUG
  185. UINT ObjHist[OBJ_MAX+1];
  186. for (i=0; i<=OBJ_MAX; i++) ObjHist[i] = 0;
  187. #endif
  188. DPF("BEGIN BuildGdiObjectList...");
  189. i=0;
  190. count=0;
  191. list=NULL;
  192. again:
  193. {
  194. WORD FAR *pw;
  195. UINT cnt;
  196. HANDLE h;
  197. // get pointer to local heap info (stored at offset 6 in DGROUP)
  198. pw = MAKELP(hgdi, 6);
  199. pw = MAKELP(hgdi, *pw);
  200. // get pointer to first handle table (stored at offset 0x14 in HeapInfo)
  201. pw = MAKELP(hgdi, pw[0x14/2]);
  202. //
  203. // a handle table starts with a WORD count of entries, followed
  204. // by the entries (each is a DWORD) last WORD is a pointer to
  205. // the next handle table or 0.
  206. //
  207. // each handle entry is a WORD ptr, followed by flags (WORD)
  208. // the HIBYTE of the flags is realy the lock count.
  209. // if the flags are 0xFFFF the handle is free.
  210. // for the GDI heap if 0x10 is set in the flags the
  211. // handle is a GDI object handle.
  212. //
  213. while (OFFSETOF(pw) != 0)
  214. {
  215. cnt = *pw++; // get handle table count
  216. while (cnt-- > 0)
  217. {
  218. h = (HANDLE)OFFSETOF(pw);
  219. // is the handle free? yes skip
  220. if (pw[1] != 0xFFFF)
  221. {
  222. // is the handle a GDI object?
  223. if (pw[1] & 0x0010)
  224. {
  225. type = (UINT)IsGDIObject(h);
  226. if (type)
  227. {
  228. if (list)
  229. {
  230. Assert(i >= 0 && i < count);
  231. list[i].h = (HGDIOBJ)h;
  232. list[i].type = type;
  233. i++;
  234. }
  235. else
  236. {
  237. count++;
  238. #ifdef DEBUG
  239. Assert(type > 0 && type <= OBJ_MAX);
  240. ObjHist[type]++;
  241. #endif
  242. }
  243. }
  244. }
  245. // not a gdi object, might be a SaveDC
  246. else
  247. {
  248. if ((UINT)IsGDIObject(h) == OBJ_DC)
  249. {
  250. if (list)
  251. {
  252. Assert(i >= 0 && i < count);
  253. list[i].h = (HGDIOBJ)h;
  254. list[i].type = OBJ_SAVEDC;
  255. i++;
  256. }
  257. else
  258. {
  259. count++;
  260. #ifdef DEBUG
  261. ObjHist[OBJ_SAVEDC]++;
  262. #endif
  263. }
  264. }
  265. }
  266. }
  267. pw += 2; // next handle
  268. }
  269. // get next handle table.
  270. pw = MAKELP(hgdi,*pw);
  271. }
  272. }
  273. if (list == NULL)
  274. {
  275. list = (GDIOBJECTLIST)LocalAlloc(LPTR, sizeof(GDIOBJECT) * (count+1));
  276. if (list == NULL)
  277. {
  278. Assert(0);
  279. return NULL;
  280. }
  281. goto again;
  282. }
  283. Assert(i == count);
  284. list[i].h = NULL; // NULL terminate list
  285. list[i].type = 0; // NULL terminate list
  286. DPF("END BuildGdiObjectList %d objects.", count);
  287. DPF(" DC: %d", ObjHist[OBJ_DC]);
  288. DPF(" SaveDC: %d", ObjHist[OBJ_SAVEDC]);
  289. DPF(" Bitmap: %d", ObjHist[OBJ_BITMAP]);
  290. DPF(" Pen: %d", ObjHist[OBJ_PEN]);
  291. DPF(" Palette:%d", ObjHist[OBJ_PALETTE]);
  292. DPF(" Brush: %d", ObjHist[OBJ_BRUSH]);
  293. DPF(" Total: %d", count);
  294. return list;
  295. }
  296. /*----------------------------------------------------------------------------*\
  297. \*----------------------------------------------------------------------------*/
  298. BOOL BeginGdiSnapshot(void)
  299. {
  300. if (GdiObjectList != NULL)
  301. return TRUE;
  302. GdiObjectList = BuildGdiObjectList();
  303. return GdiObjectList != NULL;
  304. }
  305. /*----------------------------------------------------------------------------*\
  306. \*----------------------------------------------------------------------------*/
  307. void EndGdiSnapshot(void)
  308. {
  309. if (GdiObjectList != NULL)
  310. {
  311. LocalFree((HLOCAL)GdiObjectList);
  312. GdiObjectList = NULL;
  313. }
  314. }
  315. /*----------------------------------------------------------------------------*\
  316. \*----------------------------------------------------------------------------*/
  317. void EnumGdiObjects(UINT type, EnumGdiObjectsCallback callback, LPARAM lParam)
  318. {
  319. int i;
  320. Assert(GdiObjectList != NULL);
  321. if (GdiObjectList == NULL)
  322. return;
  323. for (i=0; GdiObjectList[i].h; i++)
  324. {
  325. if (GdiObjectList[i].type == type)
  326. {
  327. (*callback)(GdiObjectList[i].h, lParam);
  328. }
  329. }
  330. }
  331. #ifdef DEBUG
  332. /*----------------------------------------------------------------------------*\
  333. \*----------------------------------------------------------------------------*/
  334. LPCSTR GetObjectOwnerName(HGDIOBJ hgdi)
  335. {
  336. int i;
  337. HMODULE hModule;
  338. HANDLE h = GetObjectOwner(hgdi);
  339. static char ach[80];
  340. if (h == 0)
  341. return "System";
  342. else if (h == (HANDLE)1)
  343. return "Orphan";
  344. else if (hModule = (HMODULE)GetExePtr(h))
  345. {
  346. GetModuleFileName(hModule, ach, sizeof(ach));
  347. for (i=lstrlen(ach); i>0 && ach[i-1]!='\\'; i--)
  348. ;
  349. return ach+i;
  350. }
  351. else
  352. {
  353. wsprintf(ach, "#%04X", h);
  354. return ach;
  355. }
  356. }
  357. #endif
  358. /*----------------------------------------------------------------------------*\
  359. \*----------------------------------------------------------------------------*/
  360. HBITMAP CurrentBitmap(HDC hdc)
  361. {
  362. HBITMAP hbm;
  363. if (hbm = SafeSelectObject(hdc, StockBitmap()))
  364. SafeSelectObject(hdc, hbm);
  365. return hbm;
  366. }
  367. /*----------------------------------------------------------------------------*\
  368. \*----------------------------------------------------------------------------*/
  369. HBRUSH CurrentBrush(HDC hdc)
  370. {
  371. HBRUSH hbr;
  372. if (hbr = SafeSelectObject(hdc, GetStockObject(BLACK_BRUSH)))
  373. SafeSelectObject(hdc, hbr);
  374. return hbr;
  375. }
  376. /*----------------------------------------------------------------------------*\
  377. \*----------------------------------------------------------------------------*/
  378. HPEN CurrentPen(HDC hdc)
  379. {
  380. HPEN pen;
  381. if (pen = SafeSelectObject(hdc, GetStockObject(BLACK_PEN)))
  382. SafeSelectObject(hdc, pen);
  383. return pen;
  384. }
  385. /*----------------------------------------------------------------------------*\
  386. \*----------------------------------------------------------------------------*/
  387. HPALETTE CurrentPalette(HDC hdc)
  388. {
  389. HPALETTE hpal;
  390. if (hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE))
  391. SelectPalette(hdc, hpal, FALSE);
  392. return hpal;
  393. }
  394. /*----------------------------------------------------------------------------*\
  395. \*----------------------------------------------------------------------------*/
  396. HDC GetBitmapDC(HBITMAP hbm)
  397. {
  398. int i;
  399. HDC hdc;
  400. HBITMAP hbmT;
  401. Assert(GdiObjectList != NULL);
  402. hdc = CreateCompatibleDC(NULL);
  403. hbmT = SelectObject(hdc, hbm);
  404. DeleteDC(hdc);
  405. //
  406. // if we can select this bitmap into a memDC, it is not selected.
  407. // into any other DC
  408. //
  409. if (hbmT != NULL)
  410. return NULL;
  411. if (GdiObjectList == NULL)
  412. return NULL;
  413. for (i=0; GdiObjectList[i].h; i++)
  414. {
  415. if (GdiObjectList[i].type == OBJ_DC)
  416. {
  417. if (CurrentBitmap((HDC)GdiObjectList[i].h) == hbm)
  418. return GdiObjectList[i].h;
  419. }
  420. }
  421. return NULL;
  422. }
  423. /*----------------------------------------------------------------------------*\
  424. * GetObjectPalette
  425. \*----------------------------------------------------------------------------*/
  426. HPALETTE GetObjectPalette(HGDIOBJ h)
  427. {
  428. HANDLE owner = GetObjectOwner(h);
  429. HPALETTE hpal;
  430. HPALETTE hpal20=NULL;
  431. HPALETTE hpal256=NULL;
  432. HPALETTE hpalDef = GetStockObject(DEFAULT_PALETTE);
  433. int i;
  434. int count20;
  435. int count256;
  436. Assert(GdiObjectList != NULL);
  437. //
  438. // look at all the palettes owned by the app
  439. // mabey if we are lucky there will only be one.
  440. //
  441. for (i=count20=count256=0; GdiObjectList[i].h; i++)
  442. {
  443. if (GdiObjectList[i].type == OBJ_PALETTE)
  444. {
  445. hpal=(HPALETTE)GdiObjectList[i].h;
  446. if (hpal == hpalDef)
  447. continue;
  448. if (GetObjectOwner(hpal) == owner)
  449. {
  450. int n = 0;
  451. GetObject(hpal, sizeof(n), &n);
  452. if (n > 20)
  453. {
  454. count256++;
  455. hpal256 = hpal;
  456. }
  457. else
  458. {
  459. count20++;
  460. hpal20 = hpal;
  461. }
  462. }
  463. }
  464. }
  465. if (count256 == 1)
  466. {
  467. DPF("got palette (%04X) because app (%s) only has one palette", hpal256, GetObjectOwnerName(h));
  468. return hpal256;
  469. }
  470. if (count256 == 2 && count20 == 0)
  471. {
  472. DPF("got palette (%04X) because app (%s) only has two palettes", hpal256, GetObjectOwnerName(h));
  473. return hpal256;
  474. }
  475. if (count20 == 1 && count256 == 0)
  476. {
  477. DPF("got palette (%04X) because app (%s) only has one palette", hpal20, GetObjectOwnerName(h));
  478. return hpal20;
  479. }
  480. if (count20 == 0 && count256 == 0)
  481. {
  482. DPF("no palette for (%04X) because app (%s) has none.", h, GetObjectOwnerName(h));
  483. return GetStockObject(DEFAULT_PALETTE);
  484. }
  485. DPF("**** cant find palette for (%04X) ****", h);
  486. return NULL;
  487. }
  488. /*----------------------------------------------------------------------------*\
  489. * GetBitmapPalette
  490. *
  491. * try to find out the palette that the given DDB uses, this is done be a series
  492. * of hacks and it only works some of the time.
  493. *
  494. \*----------------------------------------------------------------------------*/
  495. HPALETTE GetBitmapPalette(HBITMAP hbm)
  496. {
  497. BITMAP bm;
  498. DWORD dw;
  499. HDC hdc;
  500. HPALETTE hpal;
  501. HPALETTE hpalClip=NULL;
  502. HBITMAP hbmClip=NULL;
  503. Assert(GdiObjectList != NULL);
  504. //
  505. // get the bitmap info, if it is not a bitmap palette is NULL
  506. //
  507. if (GetObject(hbm, sizeof(bm), &bm) == 0)
  508. return NULL;
  509. //
  510. // DIBSections dont have or need palettes
  511. //
  512. if (bm.bmBits != NULL)
  513. return NULL;
  514. //
  515. // 8 bit DDBs are the only bitmaps that care about palettes
  516. //
  517. if (bm.bmBitsPixel != 8 || bm.bmPlanes != 1)
  518. return NULL;
  519. //
  520. // with a new DIBENG it will give us the palette
  521. // in the bitmap dimension, what a hack
  522. //
  523. dw = GetBitmapDimension(hbm);
  524. if (dw && IsGDIObject((HGDIOBJ)HIWORD(dw)) == OBJ_PALETTE &&
  525. HIWORD(dw) != (UINT)GetStockObject(DEFAULT_PALETTE))
  526. {
  527. DPF("got palette (%04X) from the DIBENG", HIWORD(dw), hbm);
  528. return (HPALETTE)HIWORD(dw);
  529. }
  530. //
  531. // if the bitmap is on the clipboard we know what palette to use
  532. //
  533. if (IsClipboardFormatAvailable(CF_PALETTE))
  534. {
  535. if (OpenClipboard(NULL))
  536. {
  537. hpalClip = GetClipboardData(CF_PALETTE);
  538. hbmClip = GetClipboardData(CF_BITMAP);
  539. CloseClipboard();
  540. }
  541. if (hbm == hbmClip)
  542. {
  543. DPF("got palette (%04X) from the clipboard", hpalClip);
  544. return hpalClip;
  545. }
  546. }
  547. //
  548. // try to find a palette by looking at palettes owned by the app.
  549. //
  550. hpal = GetObjectPalette(hbm);
  551. //
  552. // we can figure out the palette of the app, return it
  553. //
  554. if (hpal)
  555. {
  556. if (hpal == GetStockObject(DEFAULT_PALETTE))
  557. return NULL;
  558. else
  559. return hpal;
  560. }
  561. //
  562. // if the bitmap is selected into a memoryDC check to see if
  563. // the memoryDC has a palette.
  564. //
  565. if ((hdc = GetBitmapDC(hbm)) && (hpal = CurrentPalette(hdc)))
  566. {
  567. if (hpal != GetStockObject(DEFAULT_PALETTE))
  568. {
  569. DPF("got palette (%04X) from memDC (%04X)", hpal, hdc);
  570. return hpal;
  571. }
  572. }
  573. DPF("**** cant find palette for bitmap (%04X) ****", hbm);
  574. return NULL;
  575. }
  576. /*----------------------------------------------------------------------------*\
  577. * ConvertDDBtoDS
  578. *
  579. * converts a DDB to a DIBSection
  580. * the conversion is done in place so the handle does not change.
  581. \*----------------------------------------------------------------------------*/
  582. HBITMAP ConvertDDBtoDS(HBITMAP hbm)
  583. {
  584. BITMAP bm;
  585. HBITMAP hbmT;
  586. HDC hdc;
  587. HDC hdcSel;
  588. HPALETTE hpal;
  589. LPVOID lpBits;
  590. HANDLE owner;
  591. BOOL IsPrivate;
  592. int i;
  593. DWORD size;
  594. DIB8 dib;
  595. UINT SelCount;
  596. DWORD dw;
  597. if (GetObject(hbm, sizeof(bm), &bm) == 0)
  598. return NULL;
  599. if (bm.bmBits)
  600. return NULL;
  601. if (bm.bmPlanes == 1 && bm.bmBitsPixel == 1)
  602. return NULL;
  603. dw = GetBitmapDimension(hbm);
  604. owner = GetObjectOwner(hbm);
  605. // if (owner == 0)
  606. // return NULL;
  607. hpal = GetBitmapPalette(hbm);
  608. hdc = GetDC(NULL);
  609. if (hpal)
  610. {
  611. SelectPalette(hdc, hpal, TRUE);
  612. RealizePalette(hdc);
  613. }
  614. dib.bi.biSize = sizeof(BITMAPINFOHEADER);
  615. dib.bi.biBitCount = 0;
  616. GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO)&dib.bi, DIB_RGB_COLORS);
  617. GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO)&dib.bi, DIB_RGB_COLORS);
  618. dib.bi.biXPelsPerMeter = 0x42424242; // special flag marking a DDB
  619. dib.bi.biHeight = -bm.bmHeight; // top-down DIB
  620. if (hpal)
  621. SelectPalette(hdc, (HPALETTE)GetStockObject(DEFAULT_PALETTE), TRUE);
  622. // we dont have a palette, best guess is the system palette
  623. if (hpal == NULL && (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE))
  624. {
  625. DPF("Converting DDB(%04X) to DS for %s (using syspal)", hbm, GetObjectOwnerName(hbm));
  626. GetSystemPaletteEntries(hdc, 0, 256, (LPPALETTEENTRY)dib.ct);
  627. for (i=0; i<256; i++)
  628. dib.ct[i] = RGB(GetBValue(dib.ct[i]), GetGValue(dib.ct[i]), GetRValue(dib.ct[i]));
  629. }
  630. else if (hpal)
  631. {
  632. DPF("Converting DDB(%04X) to DS for %s, using palette (%04X)", hbm, GetObjectOwnerName(hbm), hpal);
  633. }
  634. else
  635. {
  636. DPF("Converting DDB(%04X) to DS for %s", hbm, GetObjectOwnerName(hbm));
  637. }
  638. ReleaseDC(NULL, hdc);
  639. size = (DWORD)bm.bmWidthBytes * bm.bmHeight;
  640. lpBits = GlobalAllocPtr(GHND, size);
  641. Assert(lpBits != NULL);
  642. if (lpBits == NULL)
  643. return NULL;
  644. GetBitmapBits(hbm, size, lpBits);
  645. IsPrivate = MakeObjectPrivate(hbm, FALSE);
  646. hdcSel = GetBitmapDC(hbm);
  647. if (hdcSel)
  648. SelectObject(hdcSel, StockBitmap());
  649. SelCount = GetW(hbm, 16);
  650. if (SelCount != 0)
  651. {
  652. DPF("***** bitmap %04X select count is %d, must be in a SaveDC block!", hbm, SelCount);
  653. SetW(hbm, 16, 0);
  654. }
  655. DeleteBitmap(hbm);
  656. if (IsGDIObject(hbm))
  657. {
  658. DPF("***** UNABLE TO DELETE bitmap %04X *****", hbm);
  659. Assert(0);
  660. }
  661. else
  662. {
  663. hbmT = CreateDIBSection(NULL, (LPBITMAPINFO)&dib.bi, DIB_RGB_COLORS, NULL, NULL, 0);
  664. Assert(hbmT == hbm);
  665. SetBitmapBits(hbm, size, lpBits);
  666. }
  667. GlobalFreePtr(lpBits);
  668. if (SelCount)
  669. SetW(hbm, 16, SelCount);
  670. SetObjectOwner(hbm, owner);
  671. MakeObjectPrivate(hbm, IsPrivate);
  672. if (hdcSel)
  673. SelectObject(hdcSel, hbm);
  674. SetBitmapDimension(hbm, LOWORD(dw), HIWORD(dw));
  675. return hbm;
  676. }
  677. /*----------------------------------------------------------------------------*\
  678. * Convert DStoDDB
  679. *
  680. * convert a DIBSection back to a DDB, we only do this if the DIBSection
  681. * came from a DDB (ConvertDDBtoDS puts a magic value in biXPelsPerMeter)
  682. * the conversion is done in place so the handle does not change.
  683. \*----------------------------------------------------------------------------*/
  684. HBITMAP ConvertDStoDDB(HBITMAP hbm, BOOL fForceConvert)
  685. {
  686. struct {
  687. BITMAP bm;
  688. BITMAPINFOHEADER bi;
  689. DWORD ct[256];
  690. } ds;
  691. HDC hdcSel;
  692. HDC hdc;
  693. HBITMAP hbmT;
  694. HANDLE owner;
  695. BOOL IsPrivate;
  696. LPVOID lpBits;
  697. DWORD size;
  698. int planes,bpp,rc;
  699. UINT SelCount;
  700. DWORD dw;
  701. hdc = GetDC(NULL);
  702. bpp = GetDeviceCaps(hdc, BITSPIXEL);
  703. planes = GetDeviceCaps(hdc, PLANES);
  704. rc = GetDeviceCaps(hdc, RASTERCAPS);
  705. ReleaseDC(NULL, hdc);
  706. if (GetObject(hbm, sizeof(ds), &ds) == 0)
  707. return NULL;
  708. if (ds.bm.bmBits == NULL)
  709. return NULL;
  710. if (ds.bm.bmBitsPixel == 1)
  711. return NULL;
  712. if (ds.bi.biXPelsPerMeter != 0x42424242)
  713. return NULL;
  714. if (ds.bi.biHeight >= 0)
  715. return NULL;
  716. //
  717. // HACK we want to convert bitmaps that are exactly 8x8
  718. // back to DDBs always. Win95 GDI does not support
  719. // Creating a pattern brush from a DIBSection so
  720. // we must do this.
  721. //
  722. if (ds.bm.bmWidth == 8 && ds.bm.bmHeight == 8)
  723. {
  724. DPF("Converting 8x8 DS(%04X) back to DDB for %s", hbm, GetObjectOwnerName(hbm));
  725. fForceConvert = TRUE;
  726. }
  727. //
  728. // unless force convert is TRUE we only want to be here in 8bpp mode.
  729. //
  730. if (!fForceConvert && !(rc & RC_PALETTE))
  731. return NULL;
  732. if (!fForceConvert && (ds.bm.bmPlanes != planes || ds.bm.bmBitsPixel != bpp))
  733. return NULL;
  734. dw = GetBitmapDimension(hbm);
  735. owner = GetObjectOwner(hbm);
  736. // if (owner == 0)
  737. // return NULL;
  738. DPF("Converting DS(%04X) %dx%dx%d to DDB for %s", hbm, ds.bm.bmWidth, ds.bm.bmHeight, ds.bm.bmBitsPixel, GetObjectOwnerName(hbm));
  739. hdcSel = GetBitmapDC(hbm);
  740. size = (DWORD)ds.bm.bmWidthBytes * ds.bm.bmHeight;
  741. lpBits = GlobalAllocPtr(GHND, size);
  742. Assert(lpBits != NULL);
  743. if (lpBits == NULL)
  744. return NULL;
  745. IsPrivate = MakeObjectPrivate(hbm, FALSE);
  746. if (hdcSel)
  747. SelectObject(hdcSel, StockBitmap());
  748. hdc = GetDC(NULL);
  749. if (ds.bm.bmPlanes == planes && ds.bm.bmBitsPixel == bpp)
  750. GetBitmapBits(hbm, size, lpBits);
  751. else
  752. GetDIBits(hdc, hbm, 0, ds.bm.bmHeight, lpBits, (LPBITMAPINFO)&ds.bi, DIB_RGB_COLORS);
  753. SelCount = GetW(hbm, 16);
  754. if (SelCount != 0)
  755. {
  756. DPF("bitmap %04X select count is %d, must be in a SaveDC block!", hbm, SelCount);
  757. SetW(hbm, 16, 0);
  758. }
  759. DeleteBitmap(hbm);
  760. if (IsGDIObject(hbm))
  761. {
  762. DPF("***** UNABLE TO DELETE bitmap %04X *****", hbm);
  763. Assert(0);
  764. }
  765. else
  766. {
  767. hbmT = CreateCompatibleBitmap(hdc,ds.bm.bmWidth,ds.bm.bmHeight);
  768. Assert(hbmT == hbm);
  769. if (ds.bm.bmPlanes == planes && ds.bm.bmBitsPixel == bpp)
  770. SetBitmapBits(hbm, size, lpBits);
  771. else
  772. SetDIBits(hdc, hbm, 0, ds.bm.bmHeight, lpBits, (LPBITMAPINFO)&ds.bi, DIB_RGB_COLORS);
  773. }
  774. ReleaseDC(NULL, hdc);
  775. GlobalFreePtr(lpBits);
  776. if (SelCount)
  777. SetW(hbm, 16, SelCount);
  778. SetObjectOwner(hbm, owner);
  779. MakeObjectPrivate(hbm, IsPrivate);
  780. if (hdcSel)
  781. SelectObject(hdcSel, hbm);
  782. SetBitmapDimension(hbm, LOWORD(dw), HIWORD(dw));
  783. return hbm;
  784. }
  785. /*----------------------------------------------------------------------------*\
  786. \*----------------------------------------------------------------------------*/
  787. void FlushGdiXlatCache()
  788. {
  789. DIB8 dib;
  790. HDC hdc;
  791. HBITMAP hbm;
  792. if (hbm = CreateBitmap(1,1,1,1,NULL))
  793. {
  794. if (hdc = CreateCompatibleDC(NULL))
  795. {
  796. SelectBitmap(hdc, hbm);
  797. dib.bi.biSize = sizeof(BITMAPINFOHEADER);
  798. dib.bi.biWidth = 1;
  799. dib.bi.biHeight = 1;
  800. dib.bi.biPlanes = 1;
  801. dib.bi.biCompression = 0;
  802. dib.bi.biSizeImage = 0;
  803. dib.bi.biXPelsPerMeter = 0;
  804. dib.bi.biYPelsPerMeter = 0;
  805. dib.bi.biClrUsed = 2;
  806. dib.bi.biClrImportant = 0;
  807. dib.ct[0] = RGB(1,1,1);
  808. dib.ct[2] = RGB(2,2,2);
  809. for (dib.bi.biBitCount = 1;
  810. dib.bi.biBitCount <= 8;
  811. dib.bi.biBitCount = (dib.bi.biBitCount + 4) & ~1)
  812. {
  813. SetDIBits(hdc, hbm, 0, 1, (LPVOID)&dib.bi,
  814. (LPBITMAPINFO)&dib.bi, DIB_PAL_COLORS);
  815. }
  816. DeleteDC(hdc);
  817. }
  818. DeleteBitmap(hbm);
  819. }
  820. }
  821. /*----------------------------------------------------------------------------*\
  822. \*----------------------------------------------------------------------------*/
  823. void ReSelectObjects(HGDIOBJ h, LPARAM lParam)
  824. {
  825. COLORREF rgb;
  826. UINT hf;
  827. HDC hdc = (HDC)h;
  828. ////DPF("ReSelecting objects for DC %04X", h);
  829. // this prevents USER from RIPing because we are using
  830. // DCs in the cache without calling GetDC()
  831. hf = SetHookFlags(hdc, DCHF_VALIDATEVISRGN);
  832. SelectObject(hdc, SelectObject(hdc, GetStockObject(BLACK_BRUSH)));
  833. SelectObject(hdc, SelectObject(hdc, GetStockObject(BLACK_PEN)));
  834. GDISelectPalette(hdc, GDISelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE), TRUE);
  835. rgb = GetTextColor(hdc);
  836. SetTextColor(hdc, rgb ^ 0xFFFFFF);
  837. SetTextColor(hdc, rgb);
  838. rgb = GetBkColor(hdc);
  839. SetBkColor(hdc, rgb ^ 0xFFFFFF);
  840. SetBkColor(hdc, rgb);
  841. SetHookFlags(hdc, hf);
  842. }
  843. /////////////////////////////////////////////////////////////////////////////
  844. //
  845. // ReRealizeObjects
  846. //
  847. // calls ReRealizeObject for every pen/brush in the system, this makes sure
  848. // all pens/brushs will be rerealized next time they are used.
  849. //
  850. // call ReSelectObjects() to make sure the current pen/brush/text colors
  851. // are correct in all DCs
  852. //
  853. /////////////////////////////////////////////////////////////////////////////
  854. void ReRealizeObjects()
  855. {
  856. BeginGdiSnapshot();
  857. FlushGdiXlatCache();
  858. EnumGdiObjects(OBJ_BRUSH, ReRealizeObject, 0);
  859. EnumGdiObjects(OBJ_PEN, ReRealizeObject, 0);
  860. EnumGdiObjects(OBJ_DC, ReSelectObjects, 0);
  861. EnumGdiObjects(OBJ_SAVEDC,SaveDCFix, 0);
  862. EnumGdiObjects(OBJ_SAVEDC,SaveDCReSelectObjects, 0);
  863. EndGdiSnapshot();
  864. }
  865. /////////////////////////////////////////////////////////////////////////////
  866. //
  867. // ConvertObjects
  868. //
  869. // convert all DDBs to DIBSections
  870. // convert all color pattern brush's to DIBPattern brushs
  871. // convert all 8bpp icons to 4bpp icons.
  872. //
  873. /////////////////////////////////////////////////////////////////////////////
  874. void ConvertBitmapCB(HGDIOBJ h, LPARAM lParam)
  875. {
  876. ConvertDDBtoDS(h);
  877. }
  878. void ConvertBrushCB(HGDIOBJ h, LPARAM lParam)
  879. {
  880. ConvertPatternBrush(h);
  881. }
  882. void ConvertObjects()
  883. {
  884. BeginGdiSnapshot();
  885. EnumGdiObjects(OBJ_BITMAP, ConvertBitmapCB, 0);
  886. EnumGdiObjects(OBJ_BRUSH, ConvertBrushCB, 0);
  887. EndGdiSnapshot();
  888. }
  889. /////////////////////////////////////////////////////////////////////////////
  890. //
  891. // ConvertBitmapsBack
  892. //
  893. // convert all DIBSections to DDBs
  894. //
  895. /////////////////////////////////////////////////////////////////////////////
  896. void ConvertBitmapBackCB(HGDIOBJ h, LPARAM lParam)
  897. {
  898. ConvertDStoDDB(h, (BOOL)lParam);
  899. }
  900. void ConvertBitmapsBack(BOOL fForceConvert)
  901. {
  902. BeginGdiSnapshot();
  903. EnumGdiObjects(OBJ_BITMAP, ConvertBitmapBackCB, fForceConvert);
  904. EndGdiSnapshot();
  905. }
  906. /////////////////////////////////////////////////////////////////////////////
  907. /////////////////////////////////////////////////////////////////////////////
  908. // BEGIN EVIL
  909. //
  910. // the next few functions mess directly with GDI code/data
  911. //
  912. /////////////////////////////////////////////////////////////////////////////
  913. /////////////////////////////////////////////////////////////////////////////
  914. /*----------------------------------------------------------------------------*\
  915. \*----------------------------------------------------------------------------*/
  916. LPWORD LockObj(HGDIOBJ h, UINT off)
  917. {
  918. WORD FAR *pw;
  919. UINT hGDI = GetGdiDS();
  920. pw = MAKELP(hGDI, h);
  921. if (IsBadReadPtr(pw, 2))
  922. return NULL;
  923. pw = MAKELP(hGDI, *pw + off);
  924. if (IsBadReadPtr(pw, 2))
  925. return NULL;
  926. return pw;
  927. }
  928. /*----------------------------------------------------------------------------*\
  929. \*----------------------------------------------------------------------------*/
  930. WORD GetW(HGDIOBJ h, UINT off)
  931. {
  932. WORD FAR *pw;
  933. if (pw = LockObj(h, off))
  934. return *pw;
  935. else
  936. return 0;
  937. }
  938. /*----------------------------------------------------------------------------*\
  939. \*----------------------------------------------------------------------------*/
  940. WORD SetW(HGDIOBJ h, UINT off, WORD w)
  941. {
  942. WORD FAR *pw;
  943. WORD ret = 0;
  944. if (pw = LockObj(h, off))
  945. {
  946. ret = *pw;
  947. *pw = w;
  948. }
  949. return ret;
  950. }
  951. /*----------------------------------------------------------------------------*\
  952. * ReRealizeObject
  953. *
  954. * delete all physical objects associated with the given GDI object
  955. * this will guarentee the next time the brush/pen is selected we will
  956. * have the device driver rerealize the object.
  957. *
  958. * there are a few ways to do this....
  959. *
  960. * method #1
  961. * call SetSolidBrush()
  962. * this only works for private/solid(not stock) brushes, not pens
  963. * we need to save/restore the stock object bit.
  964. * we need to save/restore the private bit.
  965. *
  966. * method #2
  967. * delete the object and recreate it getting the same handle
  968. * we need to patch the SelCount because we cant delete a selected obj
  969. * we need to save/restore the stock object bit.
  970. * we need to save/restore the private bit.
  971. * we need to save/restore the owner.
  972. *
  973. * method #3
  974. * create a temp object, move the physchain from the given object
  975. * to the new object, delete the temp object.
  976. * we need to patch phys chain of the objects.
  977. *
  978. * after deleting all the physical objects ReSelectObjects() should be
  979. * called to clean up all the objects currently selected in all DCs
  980. *
  981. * SaveDCs are a pain in the neck, ReSelectObjects() does not deal with
  982. * the SaveDC blocks floating around GDIs heap. we need to fix this
  983. * in the general case, the system savedc's just have the white_brush
  984. * and black_pen.
  985. *
  986. * currently using method #3
  987. *
  988. \*----------------------------------------------------------------------------*/
  989. void ReRealizeObject(HGDIOBJ h, LPARAM lParam)
  990. {
  991. HGDIOBJ hTemp;
  992. UINT type;
  993. type = IsGDIObject(h);
  994. //
  995. // if the object does not have a physchain we have no work to do!
  996. //
  997. if (GetW(h, 0) == 0)
  998. return;
  999. //
  1000. // create a temp pen/brush so we can delete it and trick
  1001. // GDI into disposing all the phys objects.
  1002. //
  1003. if (type == OBJ_BRUSH)
  1004. hTemp = CreateSolidBrush(RGB(1,1,1));
  1005. else if (type == OBJ_PEN)
  1006. hTemp = CreatePen(PS_SOLID, 0, RGB(1,1,1));
  1007. else
  1008. return;
  1009. Assert(hTemp != NULL);
  1010. Assert(GetW(hTemp, 0) == 0);
  1011. if (type == OBJ_BRUSH)
  1012. DPF("ReRealize Brush %04X for %s", h, GetObjectOwnerName(h));
  1013. else
  1014. DPF("ReRealize Pen %04X for %s", h, GetObjectOwnerName(h));
  1015. //
  1016. // copy the phys chain from the passed in object to the
  1017. // temp object then call DeleteObject to free them.
  1018. //
  1019. SetW(hTemp, 0, GetW(h, 0));
  1020. SetW(h, 0, 0);
  1021. DeleteObject(hTemp);
  1022. return;
  1023. }
  1024. /*----------------------------------------------------------------------------*\
  1025. * ConvertPatternBrush
  1026. *
  1027. * convert a BS_PATTERN brush to a BS_DIBPATTERN brush.
  1028. * we only convert non-mono pattern brushes
  1029. \*----------------------------------------------------------------------------*/
  1030. HBRUSH ConvertPatternBrush(HBRUSH hbr)
  1031. {
  1032. LOGBRUSH lb;
  1033. HBITMAP hbm;
  1034. COLORREF c0, c1;
  1035. HDC hdc;
  1036. if (GetObject(hbr, sizeof(lb), &lb) == 0)
  1037. return NULL;
  1038. if (lb.lbStyle != BS_PATTERN)
  1039. return NULL;
  1040. hdc = GetDC(NULL);
  1041. hbm = CreateCompatibleBitmap(hdc, 8, 8);
  1042. ReleaseDC(NULL, hdc);
  1043. hdc = CreateCompatibleDC(NULL);
  1044. SelectObject(hdc, hbm);
  1045. SelectObject(hdc, hbr);
  1046. SetTextColor(hdc, 0x000000);
  1047. SetBkColor(hdc, 0x000000);
  1048. PatBlt(hdc, 0, 0, 8, 8, PATCOPY);
  1049. c0 = GetPixel(hdc, 0, 0);
  1050. SetTextColor(hdc, 0xFFFFFF);
  1051. SetBkColor(hdc, 0xFFFFFF);
  1052. PatBlt(hdc, 0, 0, 8, 8, PATCOPY);
  1053. c1 = GetPixel(hdc, 0, 0);
  1054. //
  1055. // if the brush is a mono pattern brush dont convert it
  1056. //
  1057. if (c0 == c1)
  1058. {
  1059. HANDLE h;
  1060. LPBITMAPINFOHEADER lpbi;
  1061. HBRUSH hbrT;
  1062. HANDLE owner;
  1063. BOOL IsPrivate;
  1064. WORD Flags;
  1065. HPALETTE hpal=NULL;
  1066. if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  1067. {
  1068. hpal = GetObjectPalette(hbr);
  1069. if (hpal == GetStockObject(DEFAULT_PALETTE))
  1070. hpal = NULL;
  1071. }
  1072. if (hpal)
  1073. {
  1074. SelectPalette(hdc, hpal, TRUE);
  1075. RealizePalette(hdc);
  1076. PatBlt(hdc, 0, 0, 8, 8, PATCOPY);
  1077. DPF("Converting pattern brush %04X for %s (using hpal=%04X)", hbr, GetObjectOwnerName(hbr), hpal);
  1078. }
  1079. else
  1080. {
  1081. DPF("Converting pattern brush %04X for %s", hbr, GetObjectOwnerName(hbr));
  1082. }
  1083. h = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + 256*4 + 8*8*4);
  1084. Assert(h != NULL);
  1085. if (h == NULL)
  1086. return hbr;
  1087. lpbi = (LPBITMAPINFOHEADER)GlobalLock(h);
  1088. lpbi->biSize = sizeof(BITMAPINFOHEADER);
  1089. lpbi->biBitCount = 0;
  1090. GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
  1091. if (lpbi->biClrUsed == 0 && lpbi->biCompression == BI_BITFIELDS)
  1092. lpbi->biClrUsed = 3;
  1093. if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
  1094. lpbi->biClrUsed = (1 << lpbi->biBitCount);
  1095. GetDIBits(hdc, hbm, 0, (int)lpbi->biHeight,
  1096. (LPBYTE)lpbi + lpbi->biSize + lpbi->biClrUsed*sizeof(RGBQUAD),
  1097. (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
  1098. owner = SetObjectOwner(hbr, 0);
  1099. IsPrivate = MakeObjectPrivate(hbr, FALSE);
  1100. Flags = SetW(hbr, 10, 0);
  1101. DeleteObject(hbr);
  1102. if (IsGDIObject(hbr))
  1103. {
  1104. DPF("***** UNABLE TO DELETE brush %04X *****", hbr);
  1105. Assert(0);
  1106. }
  1107. else
  1108. {
  1109. hbrT = CreateDIBPatternBrush(h, DIB_RGB_COLORS);
  1110. Assert(hbrT == hbr);
  1111. }
  1112. GlobalFree(h);
  1113. SetW(hbr, 10, Flags);
  1114. MakeObjectPrivate(hbr, IsPrivate);
  1115. SetObjectOwner(hbr, owner);
  1116. if (hpal)
  1117. {
  1118. SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE);
  1119. }
  1120. }
  1121. DeleteDC(hdc);
  1122. DeleteObject(hbm);
  1123. return hbr;
  1124. }
  1125. /////////////////////////////////////////////////////////////////////////////
  1126. /////////////////////////////////////////////////////////////////////////////
  1127. LPVOID GetPDevice(HDC hdc)
  1128. {
  1129. DWORD FAR *pdw;
  1130. Assert(IsGDIObject(hdc) == OBJ_DC);
  1131. if (IsGDIObject(hdc) != OBJ_DC)
  1132. return NULL;
  1133. PresDC(hdc);
  1134. if (pdw = (DWORD FAR *)LockObj(hdc, 0x30))
  1135. return (LPVOID)*pdw;
  1136. else
  1137. return NULL;
  1138. ////return MAKELP(GetW(hdc, 0x32), GetW(hdc, 0x30));
  1139. }
  1140. /*----------------------------------------------------------------------------*\
  1141. *
  1142. * get the "internal" version of a GDI api
  1143. * we need to do this so we can call GDI APIs like SelectObject and
  1144. * SetTextColor on SaveDC blocks.
  1145. *
  1146. * we only need to do this on SaveDC blocks, not every DC
  1147. *
  1148. * the code must look like this or we fail:
  1149. *
  1150. * RealProc:
  1151. * .....
  1152. * JMP #### <== Internal version of RealProc
  1153. * mov dh,80 (optinal)
  1154. * RETF NumParams
  1155. * NextProc:
  1156. *
  1157. \*----------------------------------------------------------------------------*/
  1158. FARPROC GetInternalProc(FARPROC RealProc, FARPROC NextProc, UINT NumParams)
  1159. {
  1160. LPBYTE pb = (LPBYTE)NextProc;
  1161. if ((DWORD)NextProc == 0 ||
  1162. (DWORD)RealProc == 0 ||
  1163. LOWORD(RealProc) <= 6 ||
  1164. (DWORD)NextProc <= (DWORD)RealProc ||
  1165. ((DWORD)NextProc - (DWORD)RealProc) > 80)
  1166. {
  1167. Assert(0);
  1168. return RealProc;
  1169. }
  1170. if (pb[-6] == 0xE9 && pb[-3] == 0xCA && pb[-2] == NumParams && pb[-1] == 0x00)
  1171. {
  1172. return (FARPROC)MAKELP(SELECTOROF(pb), OFFSETOF(pb)-3+*(WORD FAR *)(pb-5));
  1173. }
  1174. if (pb[-8] == 0xE9 && pb[-5] == 0xB6 && pb[-4] == 0x80 &&
  1175. pb[-3] == 0xCA && pb[-2] == NumParams && pb[-1] == 0x00)
  1176. {
  1177. return (FARPROC)MAKELP(SELECTOROF(pb), OFFSETOF(pb)-5+*(WORD FAR *)(pb-7));
  1178. }
  1179. Assert(0);
  1180. return RealProc;
  1181. }
  1182. /*----------------------------------------------------------------------------*\
  1183. \*----------------------------------------------------------------------------*/
  1184. #define DCisMem 0x01 // DC is to a memory bitmap
  1185. #define DCisDisplay 0x02 // DC is to the screen device
  1186. #define DC_DIB 0x80
  1187. #define BITMAP_DIB 0x04
  1188. #define ChkDispPal 0x0200
  1189. BOOL IsValidSaveDC(HGDIOBJ h)
  1190. {
  1191. HBITMAP hbm;
  1192. DIBENGINE FAR * pde;
  1193. UINT dcFlags;
  1194. if (IsGDIObject(h) != OBJ_DC)
  1195. {
  1196. DPF("*** invalid SaveDC (%04X)", h);
  1197. return FALSE;
  1198. }
  1199. dcFlags = GetW(h, 0x0E);
  1200. if (!(dcFlags & DCisDisplay))
  1201. {
  1202. DPF("*** SaveDC (%04X) not a display DC", h);
  1203. return FALSE;
  1204. }
  1205. hbm = (HBITMAP)GetW(h, 0x1E);
  1206. if (IsGDIObject(hbm) != OBJ_BITMAP)
  1207. {
  1208. DPF("*** SaveDC (%04X) has invalid bitmap (%04X)", h, hbm);
  1209. return FALSE;
  1210. }
  1211. pde = (DIBENGINE FAR *)MAKELP(GetW(h, 0x32), GetW(h, 0x30));
  1212. if (IsBadReadPtr(pde, sizeof(DIBENGINE)))
  1213. {
  1214. DPF("*** SaveDC (%04X) has bad lpPDevice (%04X:%04X)", h, HIWORD(pde), LOWORD(pde));
  1215. return FALSE;
  1216. }
  1217. if (pde->deType != TYPE_DIBENG)
  1218. {
  1219. DPF("*** SaveDC (%04X) not a DIBENG PDevice (%04X:%04X)", h, HIWORD(pde), LOWORD(pde));
  1220. return FALSE;
  1221. }
  1222. return TRUE;
  1223. }
  1224. /*----------------------------------------------------------------------------*\
  1225. \*----------------------------------------------------------------------------*/
  1226. void SaveDCReSelectObjects(HGDIOBJ h, LPARAM lParam)
  1227. {
  1228. COLORREF rgb;
  1229. HDC hdc = (HDC)h;
  1230. static HGDIOBJ (WINAPI *ISelectObject)(HDC hdc, HGDIOBJ h);
  1231. static COLORREF (WINAPI *ISetTextColor)(HDC hdc, COLORREF rgb);
  1232. static COLORREF (WINAPI *ISetBkColor)(HDC hdc, COLORREF rgb);
  1233. if (ISelectObject == NULL)
  1234. {
  1235. (FARPROC)ISelectObject = GetInternalProc((FARPROC)SelectObject, (FARPROC)SetTextColor, 4);
  1236. (FARPROC)ISetTextColor = GetInternalProc((FARPROC)SetTextColor, (FARPROC)SetBkColor, 6);
  1237. (FARPROC)ISetBkColor = GetInternalProc((FARPROC)SetBkColor, (FARPROC)SetBkMode, 6);
  1238. }
  1239. if (IsValidSaveDC(h))
  1240. {
  1241. DPF("ReSelecting objects for SaveDC %04X", h);
  1242. ISelectObject(hdc, ISelectObject(hdc, GetStockObject(BLACK_BRUSH)));
  1243. ISelectObject(hdc, ISelectObject(hdc, GetStockObject(BLACK_PEN)));
  1244. rgb = ISetTextColor(hdc, 0x000000);
  1245. ISetTextColor(hdc, 0xFFFFFF);
  1246. ISetTextColor(hdc, rgb);
  1247. rgb = ISetBkColor(hdc, 0x000000);
  1248. ISetBkColor(hdc, 0xFFFFFF);
  1249. ISetBkColor(hdc, rgb);
  1250. }
  1251. }
  1252. /*----------------------------------------------------------------------------*\
  1253. *
  1254. * SaveDCFix
  1255. *
  1256. * make sure the dcPlanes and dcBitsPixel are patched right in SaveDC blocks.
  1257. *
  1258. \*----------------------------------------------------------------------------*/
  1259. void SaveDCFix(HGDIOBJ h, LPARAM lParam)
  1260. {
  1261. HBITMAP hbm;
  1262. DIBENGINE FAR * pde;
  1263. UINT dcFlags;
  1264. UINT dcPlanesBitsPixel;
  1265. UINT dePlanesBitsPixel;
  1266. if (!IsValidSaveDC(h))
  1267. {
  1268. return;
  1269. }
  1270. dcPlanesBitsPixel = GetW(h, 0x9C);
  1271. dcFlags = GetW(h, 0x0E);
  1272. if (dcPlanesBitsPixel == 0x0101)
  1273. {
  1274. DPF("not Patching dcBitsPixel for SaveDC %04X (mono)", h);
  1275. return;
  1276. }
  1277. if (LOBYTE(dcPlanesBitsPixel) != 1)
  1278. {
  1279. DPF("not Patching dcBitsPixel for SaveDC %04X (planes!=1)", h);
  1280. Assert(0);
  1281. return;
  1282. }
  1283. if (dcFlags & ChkDispPal)
  1284. {
  1285. DPF("clearing ChkDispPal flag for SaveDC %04X", h);
  1286. SetW(h, 0x0E, dcFlags & ~ChkDispPal);
  1287. }
  1288. if ((dcFlags & DCisMem) && (hbm = (HBITMAP)GetW(h, 0x1E)) != StockBitmap())
  1289. {
  1290. HDC hdcSel;
  1291. HDC hdc;
  1292. hdcSel = GetBitmapDC(hbm);
  1293. if (hdcSel)
  1294. {
  1295. DPF("*******************************************");
  1296. DPF("*** SaveDC (%04X) has non-stock bitmap. ***", h);
  1297. DPF("*******************************************");
  1298. hdc = hdcSel;
  1299. }
  1300. else
  1301. {
  1302. DPF("**********************************************");
  1303. DPF("*** SaveDC (%04X) has non-selected bitmap. ***", h);
  1304. DPF("*** restoring bitmap to STOCK bitmap. ***");
  1305. DPF("**********************************************");
  1306. hdc = CreateCompatibleDC(NULL);
  1307. }
  1308. //
  1309. // copy over the important stuff from the RealDC to the SaveDC
  1310. //
  1311. if (hdc)
  1312. {
  1313. PresDC(hdc);
  1314. SetW(h, 0x0F, GetW(hdc, 0x0F)); // DCFlags2
  1315. SetW(h, 0x26, GetW(hdc, 0x26)); // hPDeviceBlock
  1316. SetW(h, 0x38, GetW(hdc, 0x38)); // pPDeviceBlock
  1317. SetW(h, 0x22, GetW(hdc, 0x22)); // hLDevice
  1318. SetW(h, 0x34, GetW(hdc, 0x34)); // pLDevice
  1319. SetW(h, 0x16, GetW(hdc, 0x16)); // hPDevice
  1320. SetW(h, 0x30, GetW(hdc, 0x30)); // lpPDevice.off
  1321. SetW(h, 0x32, GetW(hdc, 0x32)); // lpPDevice.sel
  1322. SetW(h, 0x36, GetW(hdc, 0x36)); // hBitBits
  1323. SetW(h, 0x9C, GetW(hdc, 0x9C)); // dcPlanes + dcBitsPixel
  1324. }
  1325. if (hdc && hdcSel == NULL)
  1326. {
  1327. DeleteDC(hdc);
  1328. }
  1329. return;
  1330. #if 0 // broken code
  1331. SetW(h, 0x30, 0); // lpPDevice.off
  1332. SetW(h, 0x32, GetW(hbm, 0x0E)); // lpPDevice.sel
  1333. SetW(h, 0x36, GetW(hbm, 0x0E)); // hBitBits
  1334. w = GetW(h, 0x0F); // DCFlags2
  1335. if (GetW(hbm, 0x1E) & BITMAP_DIB) // bmFlags
  1336. w |= DC_DIB;
  1337. else
  1338. w &= ~DC_DIB;
  1339. SetW(h, 0x0F, w); // DCFlags2
  1340. #endif
  1341. }
  1342. pde = (DIBENGINE FAR *)MAKELP(GetW(h, 0x32), GetW(h, 0x30));
  1343. Assert(!IsBadReadPtr(pde, sizeof(DIBENGINE)) && pde->deType == TYPE_DIBENG);
  1344. dePlanesBitsPixel = *(WORD FAR *)&pde->dePlanes;
  1345. if (dePlanesBitsPixel != dcPlanesBitsPixel)
  1346. {
  1347. DPF("Patching dcBitsPixel for SaveDC %04X %04X=>%04X", h, dcPlanesBitsPixel, dePlanesBitsPixel);
  1348. SetW(h,0x9C,dePlanesBitsPixel);
  1349. }
  1350. }
  1351. /////////////////////////////////////////////////////////////////////////////
  1352. /////////////////////////////////////////////////////////////////////////////
  1353. // END EVIL
  1354. /////////////////////////////////////////////////////////////////////////////
  1355. /////////////////////////////////////////////////////////////////////////////
  1356. #ifdef DIRECT_DRAW
  1357. #undef DPF
  1358. #ifdef DEBUG
  1359. #define DPF DPF2
  1360. static void CDECL DPF2(char *sz, ...)
  1361. {
  1362. char ach[128];
  1363. wvsprintf(ach, sz, (LPVOID)(&sz+1));
  1364. #ifdef DIRECT_DRAW
  1365. dprintf(2, ach);
  1366. #else
  1367. lstrcat(ach, "\r\n");
  1368. OutputDebugString(ach);
  1369. #endif
  1370. }
  1371. static void CDECL DPF5(char *sz, ...)
  1372. {
  1373. char ach[128];
  1374. wvsprintf(ach, sz, (LPVOID)(&sz+1));
  1375. #ifdef DIRECT_DRAW
  1376. dprintf(5, ach);
  1377. #else
  1378. lstrcat(ach, "\r\n");
  1379. OutputDebugString(ach);
  1380. #endif
  1381. }
  1382. static void CDECL DPF7(char *sz, ...)
  1383. {
  1384. char ach[128];
  1385. wvsprintf(ach, sz, (LPVOID)(&sz+1));
  1386. #ifdef DIRECT_DRAW
  1387. dprintf(7, ach);
  1388. #else
  1389. lstrcat(ach, "\r\n");
  1390. OutputDebugString(ach);
  1391. #endif
  1392. }
  1393. #else
  1394. #define DPF ; / ## /
  1395. #define DPF5 ; / ## /
  1396. #define DPF7 ; / ## /
  1397. #endif
  1398. // Utility for dumping information about ColorTables
  1399. #ifdef DEBUG_PAL
  1400. void DPF_PALETTE( BITMAPINFO *pbmi )
  1401. {
  1402. DWORD i;
  1403. DWORD *prgb = (DWORD *)(((BYTE *)pbmi)+pbmi->bmiHeader.biSize);
  1404. DWORD cEntries = pbmi->bmiHeader.biClrUsed;
  1405. if (pbmi->bmiHeader.biBitCount > 8)
  1406. return;
  1407. if (cEntries == 0)
  1408. cEntries = 1 << (pbmi->bmiHeader.biBitCount);
  1409. DPF7("Dumping Color table (0xFFRRGGBB) with %d entries", cEntries);
  1410. for (i = 0; i < cEntries; i++)
  1411. {
  1412. DPF7("0x%lx", prgb[i]);
  1413. }
  1414. }
  1415. #else
  1416. #define DPF_PALETTE(x)
  1417. #endif
  1418. // Utility for Dumping information about Bitmap Infos
  1419. #ifdef DEBUG_BMI
  1420. void DPF_PBMI( BITMAPINFO * pbmi )
  1421. {
  1422. char *szT;
  1423. DPF5("Dumping a BitmapInfo struct");
  1424. DPF5("\t\tdeBitmapInfo->bmiHeader.biSize = %ld",pbmi->bmiHeader.biSize);
  1425. DPF5("\t\tdeBitmapInfo->bmiHeader.biWidth = %ld",pbmi->bmiHeader.biWidth);
  1426. DPF5("\t\tdeBitmapInfo->bmiHeader.biHeight = %ld",pbmi->bmiHeader.biHeight);
  1427. DPF5("\t\tdeBitmapInfo->bmiHeader.biPlanes = %d",pbmi->bmiHeader.biPlanes);
  1428. DPF5("\t\tdeBitmapInfo->bmiHeader.biBitCount = %d",pbmi->bmiHeader.biBitCount);
  1429. szT = ((pbmi->bmiHeader.biCompression == BI_RGB) ? "BI_RGB" : "**UNKNOWN**");
  1430. DPF5("\t\tdeBitmapInfo->bmiHeader.biCompression = 0x%lx(%s)",pbmi->bmiHeader.biCompression, szT);
  1431. DPF5("\t\tdeBitmapInfo->bmiHeader.biSizeImage = %ld",pbmi->bmiHeader.biSizeImage);
  1432. DPF5("\t\tdeBitmapInfo->bmiHeader.biXPelsPerMeter = 0x%lx",pbmi->bmiHeader.biXPelsPerMeter);
  1433. DPF5("\t\tdeBitmapInfo->bmiHeader.biYPelsPerMeter = 0x%lx",pbmi->bmiHeader.biYPelsPerMeter);
  1434. DPF5("\t\tdeBitmapInfo->bmiHeader.biClrUsed = %ld",pbmi->bmiHeader.biClrUsed);
  1435. DPF5("\t\tdeBitmapInfo->bmiHeader.biClrImportant = %ld",pbmi->bmiHeader.biClrImportant);
  1436. DPF_PALETTE(pbmi);
  1437. }
  1438. #else
  1439. #define DPF_PBMI(x)
  1440. #endif
  1441. // Utility for Dumping information about PDEs
  1442. #ifdef DEBUG_PDE
  1443. void DPF_PDE( DIBENGINE *pde )
  1444. {
  1445. DPF5("Dumping a DIBENGINE struct.");
  1446. DPF5("\tdeType = 0x%x(%s)",pde->deType,(pde->deType == TYPE_DIBENG ? "TYPE_DIBENG" : "**UNKNOWN**"));
  1447. DPF5("\tdeWidth = %d",pde->deWidth);
  1448. DPF5("\tdeHeight = %d",pde->deHeight);
  1449. DPF5("\tdeWidthBytes = %d",pde->deWidthBytes);
  1450. DPF5("\tdePlanes = %d",pde->dePlanes);
  1451. DPF5("\tdeBitsPixel = %d",pde->deBitsPixel);
  1452. DPF5("\tdeReserved1 = 0x%lx",pde->deReserved1);
  1453. DPF5("\tdeDeltaScan = %ld",pde->deDeltaScan);
  1454. DPF5("\tdelpPDevice = 0x%x",pde->delpPDevice);
  1455. DPF5("\tdeBitsOffset = 0x%lx",pde->deBitsOffset);
  1456. DPF5("\tdeBitsSelector = 0x%x",pde->deBitsSelector);
  1457. DPF5("\tdeFlags = 0x%x(%s)",pde->deFlags,(pde->deFlags == SELECTEDDIB ? "SELECTEDDIB" : "**UNKNOWN**"));
  1458. DPF5("\tdeVersion = %d(%s)",pde->deVersion,(pde->deVersion == VER_DIBENG ? "VER_DIBENG" : "**UNKNOWN**"));
  1459. DPF5("\tdeBeginAccess = 0x%x",pde->deBeginAccess);
  1460. DPF5("\tdeEndAccess = 0x%x",pde->deEndAccess);
  1461. DPF5("\tdeDriverReserved = 0x%lx",pde->deDriverReserved);
  1462. DPF_PBMI(pde->deBitmapInfo);
  1463. }
  1464. #else
  1465. #define DPF_PDE(x)
  1466. #endif
  1467. /////////////////////////////////////////////////////////////////////////////
  1468. //
  1469. // DC stuff
  1470. //
  1471. /////////////////////////////////////////////////////////////////////////////
  1472. DIBENGINE FAR *pdeDisplay;
  1473. UINT FlatSel;
  1474. static HRGN hVisRgn;
  1475. static HDC hdcCache;
  1476. static BOOL bCache565;
  1477. static int in_use;
  1478. static int save_level;
  1479. static DWORD cacheBPP;
  1480. extern HINSTANCE hInstApp;
  1481. extern void FAR PASCAL SelectVisRgn(HDC, HRGN);
  1482. extern HDC FAR PASCAL GetDCState(HDC);
  1483. extern void FAR PASCAL SetDCState(HDC,HDC);
  1484. BOOL DPMISetSelectorLimit(UINT selector, DWORD dwLimit);
  1485. extern DWORD PASCAL MapLS( LPVOID ); // flat -> 16:16
  1486. extern void PASCAL UnMapLS( DWORD ); // unmap 16:16
  1487. /////////////////////////////////////////////////////////////////////////////
  1488. //
  1489. // SetDC
  1490. // NOTE: all calls to SetDC must be matched with SetDC(hdc,0,0,0);
  1491. //
  1492. /////////////////////////////////////////////////////////////////////////////
  1493. BOOL NEAR PASCAL SetDC(HDC hdc, HDC hdcDevice, LPDDSURFACEDESC pddsd, LPPALETTEENTRY lpPalette)
  1494. {
  1495. DIBENGINE FAR *pde;
  1496. int width;
  1497. int height;
  1498. int bpp;
  1499. UINT flags;
  1500. DWORD p16Surface;
  1501. pde = GetPDevice(hdc);
  1502. if (pde == NULL)
  1503. return FALSE;
  1504. Assert(pde->deType == 0x5250);
  1505. Assert(pdeDisplay && pdeDisplay->deType == 0x5250);
  1506. if (pddsd == 0)
  1507. {
  1508. pde->deFlags |= BUSY;
  1509. pde->deBitsOffset = 0;
  1510. pde->deBitsSelector = 0;
  1511. if( pde->deBitmapInfo->bmiHeader.biXPelsPerMeter == 0 )
  1512. {
  1513. DPF("SetDC NULL called on a DC that was never cooked by DDraw.");
  1514. Assert(0);
  1515. return TRUE;
  1516. }
  1517. // This code "should be done" but it causes
  1518. // us to SelectVisRgn more often then necessary (and more
  1519. // often than we did in DX1-4). This is safer.
  1520. // pde->deBitmapInfo->bmiHeader.biWidth = 1;
  1521. // pde->deBitmapInfo->bmiHeader.biHeight = -1;
  1522. // pde->deBitmapInfo->bmiHeader.biSizeImage = 4;
  1523. // We need to unmap the selector we allocated below
  1524. Assert(pde->deReserved1 != 0);
  1525. UnMapLS(pde->deReserved1);
  1526. // Basically, we just want to restore the flags
  1527. // to what they were when we got DC originally
  1528. DPF5("Restore pde->deReserved1 to 0x%lx", pde->deBitmapInfo->bmiHeader.biXPelsPerMeter);
  1529. pde->deReserved1 = pde->deBitmapInfo->bmiHeader.biXPelsPerMeter;
  1530. pde->deBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
  1531. Assert(pde->deReserved1 != 0);
  1532. pde->deBitsSelector = (WORD)((DWORD)pde->deReserved1 >> 16);
  1533. return TRUE;
  1534. }
  1535. // Allocate a selector
  1536. p16Surface = MapLS(pddsd->lpSurface);
  1537. if( !p16Surface )
  1538. {
  1539. DPF("Couldn't allocate selector; Out of selectors.");
  1540. return FALSE;
  1541. }
  1542. if( (WORD)p16Surface != 0 )
  1543. {
  1544. DPF("MapLS didn't return a 16:0 pointer!");
  1545. Assert(0);
  1546. return FALSE;
  1547. }
  1548. // Set the selector limit for this chunk of memory
  1549. Assert(pddsd->dwHeight > 0);
  1550. Assert(pddsd->lPitch > 0);
  1551. if( !DPMISetSelectorLimit( (UINT)(p16Surface>>16), (pddsd->dwHeight*pddsd->lPitch) - 1 ) )
  1552. {
  1553. DPF("Couldn't update selector; Out of selectors.");
  1554. UnMapLS(p16Surface);
  1555. return FALSE;
  1556. }
  1557. DPF5("SetDC: Details of PDE from initial hdc.");
  1558. DPF_PDE(pde);
  1559. width = (int)pddsd->dwWidth,
  1560. height = (int)pddsd->dwHeight,
  1561. bpp = (int)pddsd->ddpfPixelFormat.dwRGBBitCount,
  1562. flags = (UINT)pddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ? FIVE6FIVE : 0;
  1563. pde->deFlags &= ~BUSY;
  1564. // Also, make sure we set all if any banked bits are set in the driver
  1565. // to encourage the DIBENG to avoid screen to screen blts (which are apparently buggy).
  1566. // Only do this for BankSwitched VRAM surfaces.
  1567. // ATTENTION: MULTIMON pdeDisplay is the primary; we should check
  1568. // the hdcDevice instead
  1569. if ((pddsd->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  1570. (pdeDisplay->deFlags & (NON64KBANK|BANKEDVRAM|BANKEDSCAN)))
  1571. {
  1572. pde->deFlags |= (NON64KBANK|BANKEDVRAM|BANKEDSCAN);
  1573. }
  1574. else
  1575. {
  1576. pde->deFlags &= ~(NON64KBANK|BANKEDVRAM|BANKEDSCAN);
  1577. }
  1578. pde->deDeltaScan = (DWORD)pddsd->lPitch;
  1579. pde->deWidthBytes = (WORD)pddsd->lPitch;
  1580. // We use the selector we just allocated instead of the
  1581. // flatsel + offset because it is a little safer if
  1582. // something bad happens and someone goes off the end.
  1583. pde->deBitsOffset = 0;
  1584. pde->deBitsSelector = (WORD)(p16Surface >> 16);
  1585. pde->deBitmapInfo->bmiHeader.biXPelsPerMeter = pde->deReserved1;
  1586. pde->deReserved1 = (DWORD)p16Surface;
  1587. //
  1588. // for a 8bit surface we want to color table to be the same as the
  1589. // display (so it acts like a DDB not a DIB)
  1590. //
  1591. // For non-8bit surfaces; we don't need to do anything w.r.t. color table.
  1592. //
  1593. if (bpp == 8)
  1594. {
  1595. DWORD FAR *pdw;
  1596. int i;
  1597. RGBQUAD rgbT = {0,0,0,0};
  1598. // Use our palette if it is explicitly set on the surface
  1599. if (lpPalette)
  1600. {
  1601. DPF( "Need a DC for an 8 bit surface with palette" );
  1602. Assert(pde->deBitmapInfo->bmiHeader.biBitCount == (DWORD)bpp);
  1603. // We use Pitch instead of Width because the "pitch" of
  1604. // dibsection is assumed to be the width rounded up to the next
  1605. // DWORD
  1606. pde->deBitmapInfo->bmiHeader.biWidth = (DWORD)pddsd->lPitch;
  1607. pde->deBitmapInfo->bmiHeader.biHeight = -height; // negative height for top-down DIB
  1608. pde->deBitmapInfo->bmiHeader.biSizeImage = 0;
  1609. pde->deBitmapInfo->bmiHeader.biClrImportant = 256;
  1610. // We call this because it sets a magic number which
  1611. // has the effect of resetting any cached color translation
  1612. // tables that GDI may have set up for us.
  1613. SetDIBColorTable(hdc, 0, 1, &rgbT);
  1614. pdw = (DWORD FAR *)pde->deBitmapInfo;
  1615. pdw = (DWORD FAR *)((BYTE FAR *)pdw + pdw[0]); // + biSize
  1616. for (i=0; i<256; i++)
  1617. pdw[i] = RGB(lpPalette[i].peBlue,lpPalette[i].peGreen,lpPalette[i].peRed);
  1618. }
  1619. else
  1620. {
  1621. DWORD FAR *pdwSrc;
  1622. DIBENGINE FAR *pdeDevice;
  1623. if (hdcDevice)
  1624. pdeDevice = GetPDevice(hdcDevice);
  1625. else
  1626. pdeDevice = pdeDisplay;
  1627. // This needs to be checked sooner.
  1628. Assert(pdeDevice && pdeDevice->deType == 0x5250);
  1629. Assert(pdeDevice->deBitsPixel == 8);
  1630. // In DX5, we will just modify our own bitmap info
  1631. // by copying the colors from the primary. In DX3, we
  1632. // pointed out bitmap info to the primary's; but that
  1633. // relies on the potentially bad assumption that our bitmap
  1634. // info will have a shorter life span to the primary's mode.
  1635. //
  1636. // It also doesn't work because the biWidth/biHeight fields
  1637. // of the device's primary don't match our own width/height
  1638. //
  1639. pdwSrc = (DWORD FAR *)(pdeDevice->deBitmapInfo);
  1640. pdwSrc = (DWORD FAR *)((BYTE FAR *)pdwSrc + pdwSrc[0]); // + biSize
  1641. pdw = (DWORD FAR *)pde->deBitmapInfo;
  1642. pdw = (DWORD FAR *)((BYTE FAR *)pdw + pdw[0]); // + biSize
  1643. // We call this because it sets a magic number which
  1644. // has the effect of resetting any cached color translation
  1645. // tables that GDI may have set up for us.
  1646. SetDIBColorTable(hdc, 0, 1, &rgbT);
  1647. // Copy all the colors to our color table
  1648. // We also clear all the special flags in our copy
  1649. for (i=0; i<256; i++)
  1650. pdw[i] = (pdwSrc[i] & 0x00FFFFFF);
  1651. // Fixup the rest of the bitmapinfo
  1652. // We use Pitch instead of Width because the "pitch" of
  1653. // dibsection is assumed to be the width rounded up to the next
  1654. // DWORD
  1655. pde->deBitmapInfo->bmiHeader.biWidth = (DWORD)pddsd->lPitch;
  1656. pde->deBitmapInfo->bmiHeader.biHeight = -height; // negative height for top-down DIB
  1657. pde->deBitmapInfo->bmiHeader.biSizeImage = 0;
  1658. pde->deBitmapInfo->bmiHeader.biClrImportant = 256;
  1659. }
  1660. }
  1661. else
  1662. {
  1663. // We need to convert Pitch into the number of whole
  1664. // pixels per scanline. There may be round-down errors
  1665. // however, since GDI assumes that Pitches must be multiples
  1666. // of 4; they round-up.
  1667. DWORD pitch = (DWORD)pddsd->lPitch;
  1668. if (bpp == 16)
  1669. pitch = pitch / 2;
  1670. else if (bpp == 24)
  1671. pitch = pitch / 3;
  1672. else if (bpp == 32)
  1673. pitch = pitch / 4;
  1674. else if (bpp == 4)
  1675. pitch = pitch * 2;
  1676. else if (bpp == 2)
  1677. pitch = pitch * 4;
  1678. else if (bpp == 1)
  1679. pitch = pitch * 8;
  1680. else
  1681. Assert(0); // unexpected bpp
  1682. pde->deBitmapInfo->bmiHeader.biWidth = pitch;
  1683. pde->deBitmapInfo->bmiHeader.biHeight = -height; // negative height for top-down DIB
  1684. pde->deBitmapInfo->bmiHeader.biSizeImage = 0;
  1685. Assert(pde->deBitmapInfo->bmiHeader.biBitCount == (DWORD)bpp);
  1686. }
  1687. //
  1688. // if the width/height of the dc has changed we need to set
  1689. // a new vis region
  1690. //
  1691. if (width != (int)pde->deWidth || height != (int)pde->deHeight)
  1692. {
  1693. pde->deWidth = width;
  1694. pde->deHeight = height;
  1695. SetRectRgn(hVisRgn, 0, 0, width, height);
  1696. SelectVisRgn(hdc, hVisRgn);
  1697. }
  1698. //
  1699. // when the bpp changes dont forget to fix up the deFlags
  1700. // and ReSelect all the objects so they match the new bitdepth
  1701. //
  1702. if (pde->deBitsPixel != bpp || ((pde->deFlags ^ flags) & FIVE6FIVE))
  1703. {
  1704. if (flags & FIVE6FIVE)
  1705. pde->deFlags |= FIVE6FIVE;
  1706. else
  1707. pde->deFlags &= ~FIVE6FIVE;
  1708. pde->deBitsPixel = bpp;
  1709. ReSelectObjects(hdc, 0);
  1710. }
  1711. DPF5("SetDC: Details of PDE returned.");
  1712. DPF_PDE(pde);
  1713. return TRUE;
  1714. }
  1715. /////////////////////////////////////////////////////////////////////////////
  1716. //
  1717. // AllocFlatSel
  1718. //
  1719. /////////////////////////////////////////////////////////////////////////////
  1720. #pragma optimize("", off)
  1721. UINT NEAR PASCAL AllocFlatSel()
  1722. {
  1723. if (FlatSel != 0)
  1724. return FlatSel;
  1725. FlatSel = AllocSelector(SELECTOROF((LPVOID)&FlatSel));
  1726. if (FlatSel == 0)
  1727. return 0;
  1728. SetSelectorBase(FlatSel, 0);
  1729. // SetSelectorLimit(FlatSel, -1);
  1730. _asm mov ax,0008h ; DPMI set limit
  1731. _asm mov bx,FlatSel
  1732. _asm mov dx,-1
  1733. _asm mov cx,-1
  1734. _asm int 31h
  1735. return FlatSel;
  1736. }
  1737. BOOL DPMISetSelectorLimit(UINT selector, DWORD dwLimit)
  1738. {
  1739. BOOL bRetVal=TRUE;
  1740. // If the limit is >= 1MB, we need to make the limit a mulitple
  1741. // of the page size or DPMISetSelectorLimit will fail.
  1742. if( dwLimit >= 0x100000 )
  1743. dwLimit |= 0x0FFF;
  1744. __asm
  1745. {
  1746. mov ax, 0008h
  1747. mov bx, selector
  1748. mov cx, word ptr [dwLimit+2]
  1749. mov dx, word ptr [dwLimit]
  1750. int 31h
  1751. jnc success
  1752. mov bRetVal, FALSE
  1753. success:
  1754. }
  1755. return bRetVal;
  1756. }
  1757. #pragma optimize("", on)
  1758. /////////////////////////////////////////////////////////////////////////////
  1759. //
  1760. // InitDC
  1761. //
  1762. /////////////////////////////////////////////////////////////////////////////
  1763. BOOL NEAR PASCAL InitDC(void)
  1764. {
  1765. HDC hdc;
  1766. UINT rc;
  1767. DIBENGINE FAR *pde;
  1768. if (pdeDisplay != NULL)
  1769. {
  1770. return TRUE;
  1771. }
  1772. //
  1773. // get the PDevice of the display we are going to need to copy
  1774. // some info
  1775. //
  1776. if (pdeDisplay == NULL)
  1777. {
  1778. hdc = GetDC(NULL);
  1779. rc = GetDeviceCaps(hdc, CAPS1);
  1780. pde = GetPDevice(hdc);
  1781. ReleaseDC(NULL, hdc);
  1782. if (!(rc & C1_DIBENGINE) ||
  1783. IsBadReadPtr(pde, 2) || pde->deType != 0x5250 ||
  1784. GetProfileInt("DirectDraw", "DisableGetDC", 0))
  1785. {
  1786. DPF("DD16_GetDC: GetDC is disabled");
  1787. return FALSE;
  1788. }
  1789. pdeDisplay = pde;
  1790. }
  1791. if (FlatSel == 0)
  1792. {
  1793. AllocFlatSel();
  1794. }
  1795. if (hVisRgn == NULL)
  1796. {
  1797. hVisRgn = CreateRectRgn(0,0,0,0);
  1798. SetObjectOwner(hVisRgn, hInstApp);
  1799. }
  1800. return TRUE;
  1801. }
  1802. /////////////////////////////////////////////////////////////////////////////
  1803. //
  1804. // MakeDC
  1805. //
  1806. /////////////////////////////////////////////////////////////////////////////
  1807. HDC NEAR PASCAL MakeDC(DWORD bpp, BOOL f565)
  1808. {
  1809. HDC hdc;
  1810. HBITMAP hbm;
  1811. DIBENGINE FAR *pde;
  1812. DIB8 BitmapInfo = {sizeof(BITMAPINFOHEADER), 1, -1, 1, 8, BI_RGB, 0, 0, 0, 0, 0};
  1813. if (pdeDisplay == NULL)
  1814. return NULL;
  1815. hdc = GetDC(NULL);
  1816. if (bpp == 8)
  1817. {
  1818. BitmapInfo.ct[0] = RGB(0,0,0);
  1819. BitmapInfo.ct[255] = RGB(255, 255, 255);
  1820. }
  1821. else if (bpp == 16)
  1822. {
  1823. if (f565)
  1824. {
  1825. BitmapInfo.bi.biCompression = BI_BITFIELDS;
  1826. BitmapInfo.ct[0] = 0xf800;
  1827. BitmapInfo.ct[1] = 0x07e0;
  1828. BitmapInfo.ct[2] = 0x001f;
  1829. }
  1830. }
  1831. BitmapInfo.bi.biBitCount = (UINT)bpp;
  1832. hbm = CreateDIBSection(hdc, (BITMAPINFO FAR *)&BitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0);
  1833. ReleaseDC(NULL, hdc);
  1834. if (hbm == NULL)
  1835. return NULL;
  1836. hdc = CreateCompatibleDC(NULL);
  1837. SelectObject(hdc, hbm);
  1838. pde = GetPDevice(hdc);
  1839. if (IsBadReadPtr(pde, 2) || pde->deType != 0x5250)
  1840. {
  1841. DeleteDC(hdc);
  1842. DeleteObject(hbm);
  1843. return NULL;
  1844. }
  1845. //
  1846. // ok we have the following:
  1847. //
  1848. // pde --> DIBSECTION (DIBENGINE)
  1849. // pdeDisplay --> DISPLAY PDevice (DIBENGINE)
  1850. //
  1851. // make the DIBSECTION be compatible with the display
  1852. // set the following fields from the DISPLAY PDevice:
  1853. //
  1854. // deBitsPixel
  1855. // deFlags (FIVE6FIVE, PALETTIZED, MINIDRIVER, ...)
  1856. // deBitmapInfo
  1857. //
  1858. pde->deBeginAccess = 0;
  1859. pde->deEndAccess = 0;
  1860. // deDriverReserved has three states
  1861. // 0 - Do Not Cache a translation table
  1862. // 1 - Translation table is same as Screen
  1863. // >1 - Unique ID indicating state of palette (to indicate when cached translation table is out of date)
  1864. //
  1865. // For 24 and 32bpp, it never makes sense to cache a translation table
  1866. // because no translation table is built for our surface as the destination.
  1867. // Win95 Gold DIBEngine has a bug which screws up when doing 8-to-24/32 blts
  1868. // because it incorrectly tries to cache the table. So we set deDriverReserved
  1869. // to 0 for 24/32 bpp.
  1870. //
  1871. // We have been setting deDriverReserved to 1; but we probably should not
  1872. // be doing this anymore; we should be leaving it alone which means
  1873. // that it gets the unique number given to each dibsection.
  1874. //
  1875. if (bpp == 16 || bpp == 24 || bpp == 32)
  1876. pde->deDriverReserved = 0;
  1877. else
  1878. pde->deDriverReserved = 1; // ID for the screen
  1879. pde->deBitsPixel = 0; // set SetDC will see it has changed
  1880. // pde->deFlags = pdeDisplay->deFlags;
  1881. // pde->deFlags &= ~(VRAM|NOT_FRAMEBUFFER|NON64KBANK|BANKEDVRAM|BANKEDSCAN|PALETTE_XLAT);
  1882. // pde->deFlags |= OFFSCREEN;
  1883. // pde->deFlags |= MINIDRIVER; need to clear SELECTEDDIB
  1884. // if the main display is banked, make the DCs banked because they
  1885. //may be used for video memory
  1886. //
  1887. // ATTENTION we should only do this for video memory
  1888. // surfaces not memory surfaces. move this code to SetDC
  1889. // Also, make sure we set all if any banked bits are set in the driver
  1890. // to encourage the DIBENG to avoid screen to screen blts (which are apparently buggy).
  1891. //
  1892. if(pdeDisplay->deFlags & (NON64KBANK|BANKEDVRAM|BANKEDSCAN))
  1893. {
  1894. pde->deFlags |= (NON64KBANK|BANKEDVRAM|BANKEDSCAN);
  1895. }
  1896. // This bit should only ever be used in conjunction with VRAM
  1897. // setting it can confuses drivers (such as the 765) into thinking that
  1898. // the surface is in VRAM when it is not.
  1899. // pde->deFlags |= OFFSCREEN;
  1900. pde->deFlags |= BUSY;
  1901. SetObjectOwner(hdc, hInstApp);
  1902. SetObjectOwner(hbm, hInstApp);
  1903. return hdc;
  1904. }
  1905. /////////////////////////////////////////////////////////////////////////////
  1906. //
  1907. // FreeDC
  1908. //
  1909. /////////////////////////////////////////////////////////////////////////////
  1910. BOOL NEAR PASCAL FreeDC(HDC hdc)
  1911. {
  1912. if (hdc)
  1913. {
  1914. HBITMAP hbm;
  1915. hbm = SelectObject(hdc, StockBitmap());
  1916. DeleteDC(hdc);
  1917. DeleteObject(hbm);
  1918. }
  1919. return TRUE;
  1920. }
  1921. /////////////////////////////////////////////////////////////////////////////
  1922. //
  1923. // DD16_MakeObjectPrivate
  1924. // This function makes sure that no DC that we need is
  1925. // freed until we want it to be freed.
  1926. //
  1927. /////////////////////////////////////////////////////////////////////////////
  1928. WORD DDAPI DD16_MakeObjectPrivate(HDC hdc, BOOL fPrivate)
  1929. {
  1930. BOOL fState;
  1931. // Assert that parameter is good
  1932. Assert(IsGDIObject(hdc) == OBJ_DC);
  1933. fState = MakeObjectPrivate(hdc, fPrivate);
  1934. if (fState)
  1935. {
  1936. return 1;
  1937. }
  1938. else
  1939. {
  1940. return 0;
  1941. }
  1942. }
  1943. /////////////////////////////////////////////////////////////////////////////
  1944. //
  1945. // DD16_GetDC
  1946. //
  1947. /////////////////////////////////////////////////////////////////////////////
  1948. HDC DDAPI DD16_GetDC(HDC hdcDevice, LPDDSURFACEDESC pddsd, LPPALETTEENTRY lpPalette)
  1949. {
  1950. HDC hdc;
  1951. BOOL f565;
  1952. // Assert that parameter is good
  1953. Assert(IsGDIObject(hdcDevice) == OBJ_DC);
  1954. // must be a RGB format surface!
  1955. //
  1956. if (!(pddsd->ddpfPixelFormat.dwFlags & DDPF_RGB))
  1957. {
  1958. DPF("DD16_GetDC: must be a RGB surface");
  1959. return NULL;
  1960. }
  1961. //
  1962. // if the surface is 8bpp the display must also be 8bpp because we
  1963. // share the color table. (Multi-mon: make sure we check the right display.)
  1964. //
  1965. // If a palette is explicitly passed in, then we won't need
  1966. // the device's pde.
  1967. //
  1968. if( pddsd->ddpfPixelFormat.dwRGBBitCount == 8 && lpPalette == NULL )
  1969. {
  1970. DIBENGINE FAR *pdeDevice;
  1971. if( hdcDevice )
  1972. pdeDevice = GetPDevice( hdcDevice );
  1973. else
  1974. pdeDevice = pdeDisplay;
  1975. // 3DFx isn't a real device DC
  1976. if (pdeDevice->deType != 0x5250)
  1977. {
  1978. DPF("Can't get DC on an 8bpp surface without a palette for this device");
  1979. return NULL;
  1980. }
  1981. if (pdeDevice->deBitsPixel != 8 )
  1982. {
  1983. DPF("Can't get DC on an 8bpp surface without a palette when primary is not at 8bpp");
  1984. return NULL;
  1985. }
  1986. }
  1987. #ifdef DEBUG
  1988. //
  1989. // we assume the pixel format is not wacky
  1990. //
  1991. if (pddsd->ddpfPixelFormat.dwRGBBitCount == 8 )
  1992. {
  1993. /*
  1994. * The Permedia driver actually reports bit masks for their 8bit palettized mode, so
  1995. * we shouldn't assert here (as we used to) if any masks are non-zero.
  1996. */
  1997. if ( ( pddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) ==0 )
  1998. {
  1999. DPF("Getting a DC on a non-palettized 8bit surface!");
  2000. Assert(0);
  2001. }
  2002. }
  2003. else if ( pddsd->ddpfPixelFormat.dwRGBBitCount == 4 ||
  2004. pddsd->ddpfPixelFormat.dwRGBBitCount == 1)
  2005. {
  2006. /*
  2007. * Assume these are OK
  2008. */
  2009. }
  2010. else if (pddsd->ddpfPixelFormat.dwRGBBitCount == 16)
  2011. {
  2012. if (pddsd->ddpfPixelFormat.dwRBitMask == 0xf800 &&
  2013. pddsd->ddpfPixelFormat.dwGBitMask == 0x07e0 &&
  2014. pddsd->ddpfPixelFormat.dwBBitMask == 0x001f)
  2015. {
  2016. // 565
  2017. }
  2018. else if (
  2019. pddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 &&
  2020. pddsd->ddpfPixelFormat.dwGBitMask == 0x03e0 &&
  2021. pddsd->ddpfPixelFormat.dwBBitMask == 0x001f)
  2022. {
  2023. // 555
  2024. }
  2025. else
  2026. {
  2027. DPF("DD16_GetDC: not 555 or 565");
  2028. Assert(0);
  2029. }
  2030. }
  2031. else if (pddsd->ddpfPixelFormat.dwRGBBitCount == 24 )
  2032. {
  2033. if (pddsd->ddpfPixelFormat.dwBBitMask == 0x0000FF &&
  2034. pddsd->ddpfPixelFormat.dwGBitMask == 0x00FF00 &&
  2035. pddsd->ddpfPixelFormat.dwRBitMask == 0xFF0000)
  2036. {
  2037. // 888 BGR
  2038. }
  2039. else
  2040. {
  2041. DPF("DD16_GetDC: invalid bit masks");
  2042. Assert(0);
  2043. }
  2044. }
  2045. else if(pddsd->ddpfPixelFormat.dwRGBBitCount == 32)
  2046. {
  2047. if (pddsd->ddpfPixelFormat.dwRBitMask == 0xFF0000 &&
  2048. pddsd->ddpfPixelFormat.dwGBitMask == 0x00FF00 &&
  2049. pddsd->ddpfPixelFormat.dwBBitMask == 0x0000FF)
  2050. {
  2051. // 888 RGB -- standard 32-bit format
  2052. }
  2053. else
  2054. {
  2055. DPF("DD16_GetDC: invalid bit masks");
  2056. Assert(0);
  2057. }
  2058. }
  2059. else
  2060. {
  2061. DPF("DD16_GetDC: invalid bit depth");
  2062. Assert(0);
  2063. }
  2064. #endif
  2065. // is this a 565?
  2066. f565 = FALSE;
  2067. if (pddsd->ddpfPixelFormat.dwRGBBitCount == 16 &&
  2068. pddsd->ddpfPixelFormat.dwRBitMask == 0xf800)
  2069. f565 = TRUE;
  2070. //
  2071. // use the cacheDC if it is free, else make a new one.
  2072. //
  2073. if( in_use || ( pddsd->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
  2074. {
  2075. hdc = MakeDC( pddsd->ddpfPixelFormat.dwRGBBitCount, f565 );
  2076. }
  2077. else
  2078. {
  2079. if (cacheBPP != pddsd->ddpfPixelFormat.dwRGBBitCount || bCache565 != f565 )
  2080. {
  2081. FreeDC(hdcCache);
  2082. hdcCache = MakeDC(pddsd->ddpfPixelFormat.dwRGBBitCount, f565);
  2083. cacheBPP = pddsd->ddpfPixelFormat.dwRGBBitCount;
  2084. bCache565 = f565;
  2085. }
  2086. hdc = hdcCache;
  2087. in_use++;
  2088. }
  2089. //
  2090. // now set the right bits pointer.
  2091. //
  2092. if (hdc)
  2093. {
  2094. BOOL fSuccess;
  2095. // Set the DC with the right information based
  2096. // on the surface. If a palette is passed in
  2097. // then set that palette into the DC.
  2098. fSuccess = SetDC(hdc, hdcDevice, pddsd, lpPalette);
  2099. if( !fSuccess )
  2100. {
  2101. DPF("SetDC Failed");
  2102. // We need to clean up; but we
  2103. // can't call ReleaseDC because our dc is only
  2104. // half-cooked.
  2105. if (hdc == hdcCache)
  2106. {
  2107. Assert(in_use == 1);
  2108. in_use = 0;
  2109. }
  2110. else
  2111. {
  2112. FreeDC(hdc);
  2113. }
  2114. return NULL;
  2115. }
  2116. }
  2117. if (hdc && hdc == hdcCache)
  2118. {
  2119. save_level = SaveDC(hdc);
  2120. }
  2121. return hdc;
  2122. }
  2123. /////////////////////////////////////////////////////////////////////////////
  2124. //
  2125. // DD16_ReleaseDC
  2126. //
  2127. /////////////////////////////////////////////////////////////////////////////
  2128. void DDAPI DD16_ReleaseDC(HDC hdc)
  2129. {
  2130. if (hdc == NULL)
  2131. return;
  2132. if (hdc == hdcCache)
  2133. {
  2134. RestoreDC(hdc, save_level);
  2135. SetDC(hdc, NULL, NULL, NULL);
  2136. Assert(in_use == 1);
  2137. in_use = 0;
  2138. }
  2139. else
  2140. {
  2141. SetDC(hdc, NULL, NULL, NULL);
  2142. FreeDC(hdc);
  2143. }
  2144. }
  2145. /////////////////////////////////////////////////////////////////////////////
  2146. //
  2147. // DD16_SafeMode
  2148. //
  2149. // dynamic safe mode
  2150. //
  2151. /////////////////////////////////////////////////////////////////////////////
  2152. BOOL DDAPI DD16_SafeMode(HDC hdc, BOOL fSafeMode)
  2153. {
  2154. extern void PatchDisplay(int oem, BOOL patch); // dynares.c
  2155. int i;
  2156. for (i=0; i<35; i++)
  2157. {
  2158. PatchDisplay(i, fSafeMode);
  2159. }
  2160. return TRUE;
  2161. }
  2162. /////////////////////////////////////////////////////////////////////////////
  2163. //
  2164. // DD16_Exclude
  2165. // DD16_Unexclude
  2166. //
  2167. // call the exclude or unexclude callbacks in the display driver
  2168. //
  2169. /////////////////////////////////////////////////////////////////////////////
  2170. typedef void (FAR PASCAL *BEGINACCESSPROC)(LPVOID lpPDevice, int left, int top, int right, int bottom, WORD flags);
  2171. typedef void (FAR PASCAL *ENDACCESSPROC)(LPVOID lpPDevice, WORD flags);
  2172. void DDAPI DD16_Exclude(DWORD dwPDevice, RECTL FAR *prcl)
  2173. {
  2174. DIBENGINE FAR *pde = (DIBENGINE FAR *)dwPDevice;
  2175. Assert(pde && pde->deType == 0x5250);
  2176. Assert(prcl != NULL);
  2177. Assert(pde->deFlags & BUSY);
  2178. if (pde->deBeginAccess)
  2179. {
  2180. BEGINACCESSPROC OEMBeginAccess = (BEGINACCESSPROC)pde->deBeginAccess;
  2181. //
  2182. // when DirectDraw calls us it has already taken the BUSY bit
  2183. // but BUSY needs to be clear for the cursor to be excluded.
  2184. // so release the BUSY bit while we call the driver, this is
  2185. // a ok thing to do because we have the Win16Lock.
  2186. //
  2187. pde->deFlags &= ~BUSY;
  2188. OEMBeginAccess(pde, (int)prcl->left, (int)prcl->top,
  2189. (int)prcl->right, (int)prcl->bottom, CURSOREXCLUDE);
  2190. pde->deFlags |= BUSY;
  2191. }
  2192. }
  2193. void DDAPI DD16_Unexclude(DWORD dwPDevice)
  2194. {
  2195. DIBENGINE FAR *pde = (DIBENGINE FAR *)dwPDevice;
  2196. Assert(pde && pde->deType == 0x5250);
  2197. if (pde->deEndAccess)
  2198. {
  2199. ENDACCESSPROC OEMEndAccess = (ENDACCESSPROC)pde->deEndAccess;
  2200. OEMEndAccess(pde, CURSOREXCLUDE);
  2201. }
  2202. }
  2203. /*
  2204. * DD16_AttemptGamma
  2205. *
  2206. * Total HACK! The GetDeviceGammaRamp call can attempt to call a NULL
  2207. * entry. Since we can't fix Win95, instead we look at the entry that
  2208. * it will call and suggest that they don't call it if it's NULL.
  2209. */
  2210. BOOL DDAPI DD16_AttemptGamma( HDC hdc )
  2211. {
  2212. WORD wLDevice;
  2213. WORD FAR *pw;
  2214. UINT hGDI = GetGdiDS();
  2215. wLDevice = GetW(hdc, 0x34);
  2216. if( wLDevice != 0 )
  2217. {
  2218. pw = MAKELP(hGDI, wLDevice);
  2219. if (!IsBadReadPtr(pw, 0x80))
  2220. {
  2221. pw = MAKELP(hGDI, wLDevice + 0x7C);
  2222. if (*pw != NULL)
  2223. {
  2224. return TRUE;
  2225. }
  2226. }
  2227. }
  2228. return FALSE;
  2229. } /* DD16_AttemptGamma */
  2230. /*
  2231. * DD16_IsDeviceBusy
  2232. *
  2233. * Determines if the device represented by the HDC is
  2234. * busy or not.
  2235. */
  2236. BOOL DDAPI DD16_IsDeviceBusy( HDC hdc )
  2237. {
  2238. DIBENGINE FAR *pde;
  2239. pde = GetPDevice(hdc);
  2240. if(pde == NULL)
  2241. return FALSE;
  2242. Assert(pde->deType==0x5250);
  2243. return pde->deFlags & BUSY;
  2244. } /* DD16_IsDeviceBusy */
  2245. /////////////////////////////////////////////////////////////////////////////
  2246. //
  2247. // DD16_Stretch
  2248. //
  2249. // call the DIBENG to do a stretch.
  2250. //
  2251. /////////////////////////////////////////////////////////////////////////////
  2252. extern int FAR PASCAL DIB_Stretch(
  2253. DIBENGINE FAR *dst, int, int, int, int,
  2254. DIBENGINE FAR *src, int, int, int, int,
  2255. DWORD Rop, LPVOID lpPBrush, LPVOID lpDrawMode, LPRECT lpClip);
  2256. extern int FAR PASCAL DIB_BitBlt(
  2257. DIBENGINE FAR *dst, int xD, int yD,
  2258. DIBENGINE FAR *src, int xS, int yS, int w, int h,
  2259. DWORD Rop, LPVOID lpPBrush, LPVOID lpDrawMode);
  2260. typedef struct {
  2261. short int Rop2;
  2262. short int bkMode;
  2263. unsigned long int bkColor;
  2264. unsigned long int TextColor;
  2265. short int TBreakExtra;
  2266. short int BreakExtra;
  2267. short int BreakErr;
  2268. short int BreakRem;
  2269. short int BreakCount;
  2270. short int CharExtra;
  2271. unsigned long int LbkColor;
  2272. unsigned long int LTextColor;
  2273. DWORD ICMCXform;
  2274. short StretchBltMode;
  2275. DWORD eMiterLimit;
  2276. } DRAWMODE;
  2277. int DDAPI DD16_Stretch(DWORD DstPtr, int DstPitch, UINT DstBPP, int DstX, int DstY, int DstDX, int DstDY,
  2278. DWORD SrcPtr, int SrcPitch, UINT SrcBPP, int SrcX, int SrcY, int SrcDX, int SrcDY)//, long Rop3)
  2279. {
  2280. DIBENGINE src;
  2281. DIBENGINE dst;
  2282. DRAWMODE dm;
  2283. RECT rc;
  2284. static DIB8 bmiStretch = {sizeof(BITMAPINFOHEADER), 1, -1, 1, 8, BI_RGB, 0, 0, 0, 0, 0};
  2285. //
  2286. // make sure we have a flat sel
  2287. //
  2288. if (FlatSel == 0)
  2289. return -1;
  2290. // Set the bitdepth on the bitmapinfo
  2291. Assert( DstBPP == SrcBPP );
  2292. bmiStretch.bi.biBitCount = DstBPP;
  2293. //
  2294. // setup source DIBENG
  2295. //
  2296. if (SrcPtr)
  2297. {
  2298. src.deType = TYPE_DIBENG;
  2299. src.deWidth = 10000;
  2300. src.deHeight = 10000;
  2301. src.deWidthBytes = SrcPitch;
  2302. src.dePlanes = 1;
  2303. src.deBitsPixel = SrcBPP;
  2304. src.deReserved1 = 0;
  2305. src.deDeltaScan = SrcPitch;
  2306. src.delpPDevice = NULL;
  2307. src.deBitsOffset = SrcPtr;
  2308. src.deBitsSelector = FlatSel;
  2309. src.deFlags = SELECTEDDIB;
  2310. src.deVersion = VER_DIBENG;
  2311. src.deBitmapInfo = (BITMAPINFO *)&bmiStretch;
  2312. src.deBeginAccess = 0;
  2313. src.deEndAccess = 0;
  2314. src.deDriverReserved= 0;
  2315. }
  2316. //
  2317. // setup dest DIBENG
  2318. //
  2319. dst.deType = TYPE_DIBENG;
  2320. dst.deWidth = 10000;
  2321. dst.deHeight = 10000;
  2322. dst.deWidthBytes = DstPitch;
  2323. dst.dePlanes = 1;
  2324. dst.deBitsPixel = DstBPP;
  2325. dst.deReserved1 = 0;
  2326. dst.deDeltaScan = DstPitch;
  2327. dst.delpPDevice = NULL;
  2328. dst.deBitsOffset = DstPtr;
  2329. dst.deBitsSelector = FlatSel;
  2330. dst.deFlags = SELECTEDDIB;
  2331. dst.deVersion = VER_DIBENG;
  2332. dst.deBitmapInfo = (BITMAPINFO *)&bmiStretch;
  2333. dst.deBeginAccess = 0;
  2334. dst.deEndAccess = 0;
  2335. dst.deDriverReserved = 0;
  2336. //
  2337. // this memory *might* be in VRAM so setup things to
  2338. // work right.
  2339. //
  2340. // ATTENTION we should only do this for video memory
  2341. // surfaces not memory surfaces.
  2342. // If any are set, set all the bits to force the DIBENG to
  2343. // not do a screen to screen blit (which apparently has a bug).
  2344. //
  2345. if (pdeDisplay && (pdeDisplay->deFlags & (NON64KBANK|BANKEDVRAM|BANKEDSCAN)))
  2346. {
  2347. dst.deFlags |= (NON64KBANK|BANKEDVRAM|BANKEDSCAN);
  2348. src.deFlags |= (NON64KBANK|BANKEDVRAM|BANKEDSCAN);
  2349. }
  2350. //
  2351. // now call the DIBENG
  2352. //
  2353. if(SrcPtr == (DWORD)NULL)
  2354. {
  2355. DPF("Blitting from Primary with HDC unsupported!");
  2356. return FALSE;
  2357. }
  2358. else if ((DstDX == SrcDX) && (DstDY == SrcDY))
  2359. {
  2360. //DPF("Calling DIB_BitBlt");
  2361. // NOTE: If the source and destination video memory pointers
  2362. // are the same then we simply pass the destination
  2363. // DIBENG for the source as this is how the blt code spots
  2364. // the fact that the source and destination surfaces are
  2365. // the same and so takes the necessary action to handle
  2366. // overlapping surfaces
  2367. #ifdef DEBUG
  2368. if( DstPtr == SrcPtr)
  2369. {
  2370. Assert(DstPitch == SrcPitch);
  2371. Assert(DstBPP == SrcBPP);
  2372. }
  2373. #endif
  2374. return DIB_BitBlt(&dst, DstX, DstY,
  2375. (DstPtr == SrcPtr) ? &dst : &src,
  2376. SrcX, SrcY, SrcDX, SrcDY, SRCCOPY, // Rop3,
  2377. NULL, &dm);
  2378. }
  2379. else
  2380. {
  2381. rc.left = DstX;
  2382. rc.top = DstY;
  2383. rc.right = DstX + DstDX;
  2384. rc.bottom = DstY + DstDY;
  2385. dm.StretchBltMode = STRETCH_DELETESCANS;
  2386. /* DPF("Calling DIB_StretchBlt with:");
  2387. DPF("\tdst.deType = 0x%x(%s)",dst.deType,(dst.deType == TYPE_DIBENG ? "TYPE_DIBENG" : "**UNKNOWN**"));
  2388. DPF("\tdst.deWidth = %d",dst.deWidth);
  2389. DPF("\tdst.deHeight = %d",dst.deHeight);
  2390. DPF("\tdst.deWidthBytes = %d",dst.deWidthBytes);
  2391. DPF("\tdst.dePlanes = %d",dst.dePlanes);
  2392. DPF("\tdst.deBitsPixel = %d",dst.deBitsPixel);
  2393. DPF("\tdst.deReserved1 = %ld",dst.deReserved1);
  2394. DPF("\tdst.deDeltaScan = %ld",dst.deDeltaScan);
  2395. DPF("\tdst.delpPDevice = 0x%x",dst.delpPDevice);
  2396. DPF("\tdst.deBitsOffset = 0x%x",dst.deBitsOffset);
  2397. DPF("\tdst.deBitsSelector = 0x%x",dst.deBitsSelector);
  2398. DPF("\tdst.deFlags = 0x%x(%s)",dst.deFlags,(dst.deFlags == SELECTEDDIB ? "SELECTEDDIB" : "**UNKNOWN**"));
  2399. DPF("\tdst.deVersion = %d(%s)",dst.deVersion,(dst.deVersion == VER_DIBENG ? "VER_DIBENG" : "**UNKNOWN**"));
  2400. DPF("\t\tdst.deBitmapInfo->bmiHeader.biSize = %ld",dst.deBitmapInfo->bmiHeader.biSize);
  2401. DPF("\t\tdst.deBitmapInfo->bmiHeader.biWidth = %ld",dst.deBitmapInfo->bmiHeader.biWidth);
  2402. DPF("\t\tdst.deBitmapInfo->bmiHeader.biHeight = %ld",dst.deBitmapInfo->bmiHeader.biHeight);
  2403. DPF("\t\tdst.deBitmapInfo->bmiHeader.biPlanes = %d",dst.deBitmapInfo->bmiHeader.biPlanes);
  2404. DPF("\t\tdst.deBitmapInfo->bmiHeader.biBitCount = %d",dst.deBitmapInfo->bmiHeader.biBitCount);
  2405. DPF("\t\tdst.deBitmapInfo->bmiHeader.biCompression = 0x%x(%s)",dst.deBitmapInfo->bmiHeader.biCompression,((dst.deBitmapInfo->bmiHeader.biCompression == BI_RGB) ? "BI_RGB" : "**UNKNOWN**"));
  2406. DPF("\t\tdst.deBitmapInfo->bmiHeader.biSizeImage = %ld",dst.deBitmapInfo->bmiHeader.biSizeImage);
  2407. DPF("\t\tdst.deBitmapInfo->bmiHeader.biXPelsPerMeter = %ld",dst.deBitmapInfo->bmiHeader.biXPelsPerMeter);
  2408. DPF("\t\tdst.deBitmapInfo->bmiHeader.biYPelsPerMeter = %ld",dst.deBitmapInfo->bmiHeader.biYPelsPerMeter);
  2409. DPF("\t\tdst.deBitmapInfo->bmiHeader.biClrUsed = %ld",dst.deBitmapInfo->bmiHeader.biClrUsed);
  2410. DPF("\t\tdst.deBitmapInfo->bmiHeader.biClrImportant = %ld",dst.deBitmapInfo->bmiHeader.biClrImportant);
  2411. DPF("\tdst.deBeginAccess = 0x%x",dst.deBeginAccess);
  2412. DPF("\tdst.deEndAccess = 0x%x",dst.deEndAccess);
  2413. DPF("\tdst.deDriverReserved = 0x%x",dst.deDriverReserved);
  2414. DPF("");
  2415. DPF("\tDstX = %d",DstX);
  2416. DPF("\tDstY = %d",DstY);
  2417. DPF("\tDstDX = %d",DstDX);
  2418. DPF("\tDstDY = %d",DstDY);
  2419. DPF("");
  2420. DPF("\tsrc.deType = 0x%x(%s)",src.deType,(src.deType == TYPE_DIBENG ? "TYPE_DIBENG" : "**UNKNOWN**"));
  2421. DPF("\tsrc.deWidth = %d",src.deWidth);
  2422. DPF("\tsrc.deHeight = %d",src.deHeight);
  2423. DPF("\tsrc.deWidthBytes = %d",src.deWidthBytes);
  2424. DPF("\tsrc.dePlanes = %d",src.dePlanes);
  2425. DPF("\tsrc.deBitsPixel = %d",src.deBitsPixel);
  2426. DPF("\tsrc.deReserved1 = %ld",src.deReserved1);
  2427. DPF("\tsrc.deDeltaScan = %ld",src.deDeltaScan);
  2428. DPF("\tsrc.delpPDevice = 0x%x",src.delpPDevice);
  2429. DPF("\tsrc.deBitsOffset = 0x%x",src.deBitsOffset);
  2430. DPF("\tsrc.deBitsSelector = 0x%x",src.deBitsSelector);
  2431. DPF("\tsrc.deFlags = 0x%x(%s)",src.deFlags,(src.deFlags == SELECTEDDIB ? "SELECTEDDIB" : "**UNKNOWN**"));
  2432. DPF("\tsrc.deVersion = %d(%s)",src.deVersion,(src.deVersion == VER_DIBENG ? "VER_DIBENG" : "**UNKNOWN**"));
  2433. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biSize = %ld",src.deBitmapInfo->bmiHeader.biSize);
  2434. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biWidth = %ld",src.deBitmapInfo->bmiHeader.biWidth);
  2435. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biHeight = %ld",src.deBitmapInfo->bmiHeader.biHeight);
  2436. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biPlanes = %d",src.deBitmapInfo->bmiHeader.biPlanes);
  2437. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biBitCount = %d",src.deBitmapInfo->bmiHeader.biBitCount);
  2438. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biCompression = 0x%x(%s)",src.deBitmapInfo->bmiHeader.biCompression,((src.deBitmapInfo->bmiHeader.biCompression == BI_RGB) ? "BI_RGB" : "**UNKNOWN**"));
  2439. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biSizeImage = %ld",src.deBitmapInfo->bmiHeader.biSizeImage);
  2440. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biXPelsPerMeter = %ld",src.deBitmapInfo->bmiHeader.biXPelsPerMeter);
  2441. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biYPelsPerMeter = %ld",src.deBitmapInfo->bmiHeader.biYPelsPerMeter);
  2442. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biClrUsed = %ld",src.deBitmapInfo->bmiHeader.biClrUsed);
  2443. DPF("\t\tsrc.deBitmapInfo->bmiHeader.biClrImportant = %ld",src.deBitmapInfo->bmiHeader.biClrImportant);
  2444. DPF("\tsrc.deBeginAccess = 0x%x",src.deBeginAccess);
  2445. DPF("\tsrc.deEndAccess = 0x%x",src.deEndAccess);
  2446. DPF("\tsrc.deDriverReserved = 0x%x",src.deDriverReserved);
  2447. DPF("");
  2448. DPF("\tSrcX = %d",SrcX);
  2449. DPF("\tSrcY = %d",SrcY);
  2450. DPF("\tSrcDX = %d",SrcDX);
  2451. DPF("\tSrcDY = %d",SrcDY);
  2452. DPF("");
  2453. DPF("\tdm.StretchBltMode = STRETCH_DELETESCANS");
  2454. DPF("");
  2455. DPF("\trc.left = %d",rc.left);
  2456. DPF("\trc.top = %d",rc.top);
  2457. DPF("\trc.right = %d",rc.right);
  2458. DPF("\trc.bottom = %d",rc.bottom);
  2459. DPF("");
  2460. */
  2461. return DIB_Stretch(&dst, DstX, DstY, DstDX, DstDY,
  2462. &src, SrcX, SrcY, SrcDX, SrcDY, SRCCOPY, // Rop3,
  2463. NULL, &dm, &rc);
  2464. }
  2465. }
  2466. /////////////////////////////////////////////////////////////////////////////
  2467. /////////////////////////////////////////////////////////////////////////////
  2468. void GdiHelpCleanUp()
  2469. {
  2470. if (FlatSel)
  2471. {
  2472. SetSelectorLimit(FlatSel, 0);
  2473. FreeSelector(FlatSel);
  2474. FlatSel = 0;
  2475. }
  2476. if (hdcCache)
  2477. {
  2478. FreeDC(hdcCache);
  2479. hdcCache = NULL;
  2480. }
  2481. if (hVisRgn)
  2482. {
  2483. DeleteObject(hVisRgn);
  2484. hVisRgn = NULL;
  2485. }
  2486. if (pdeDisplay)
  2487. {
  2488. pdeDisplay = NULL;
  2489. }
  2490. }
  2491. /////////////////////////////////////////////////////////////////////////////
  2492. /////////////////////////////////////////////////////////////////////////////
  2493. BOOL GdiHelpInit()
  2494. {
  2495. InitDC();
  2496. return FlatSel!=NULL && pdeDisplay!=NULL;
  2497. }
  2498. #endif // DirectDraw