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.

859 lines
26 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WDIB.C
  8. * DIB.DRV support
  9. *
  10. * History:
  11. * 28-Apr-1994 Sudeep Bharati
  12. * Created.
  13. *
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include "wowgdip.h"
  18. #include "wdib.h"
  19. #include "memapi.h"
  20. MODNAME(wdib.c);
  21. #define CJSCAN(width,planes,bits) ((((width)*(planes)*(bits)+31) & ~31) / 8)
  22. #define ABS(X) (((X) < 0 ) ? -(X) : (X))
  23. BOOL W32CheckDibColorIndices(LPBITMAPINFOHEADER lpbmi);
  24. // VGA colors
  25. RGBQUAD rgbVGA[] = {
  26. // Blue Green Red
  27. 0x00, 0x00, 0x00, 0, // 0 ; black
  28. 0x00, 0x00, 0x80, 0, // 1 ; dark red
  29. 0x00, 0x80, 0x00, 0, // 2 ; dark green
  30. 0x00, 0x80, 0x80, 0, // 3 ; mustard
  31. 0x80, 0x00, 0x00, 0, // 4 ; dark blue
  32. 0x80, 0x00, 0x80, 0, // 5 ; purple
  33. 0x80, 0x80, 0x00, 0, // 6 ; dark turquoise
  34. 0xc0, 0xc0, 0xc0, 0, // 7 ; gray
  35. 0x80, 0x80, 0x80, 0, // 8 ; dark gray
  36. 0x00, 0x00, 0xff, 0, // 9 ; red
  37. 0x00, 0xff, 0x00, 0, // a ; green
  38. 0x00, 0xff, 0xff, 0, // b ; yellow
  39. 0xff, 0x00, 0x00, 0, // c ; blue
  40. 0xff, 0x00, 0xff, 0, // d ; magenta
  41. 0xff, 0xff, 0x00, 0, // e ; cyan
  42. 0xff, 0xff, 0xff, 0 // f ; white
  43. };
  44. RGBQUAD rgb4[] = {
  45. 0xc0, 0xdc, 0xc0, 0, // 8
  46. 0xf0, 0xca, 0xa6, 0, // 9
  47. 0xf0, 0xfb, 0xff, 0, // 246
  48. 0xa4, 0xa0, 0xa0, 0 // 247
  49. };
  50. PDIBINFO pDibInfoHead = NULL;
  51. PDIBSECTIONINFO pDibSectionInfoHead = NULL;
  52. HDC W32HandleDibDrv (PVPVOID vpbmi16)
  53. {
  54. HDC hdcMem = NULL;
  55. HBITMAP hbm = NULL;
  56. PVOID pvBits, pvIntelBits;
  57. STACKBMI32 bmi32;
  58. LPBITMAPINFO lpbmi32;
  59. DWORD dwClrUsed,nSize,nAlignmentSpace;
  60. PBITMAPINFOHEADER16 pbmi16;
  61. INT nbmiSize,nBytesWritten;
  62. HANDLE hfile=NULL,hsec=NULL;
  63. ULONG RetVal,OriginalSelLimit,ulSelectorLimit,OriginalFlags;
  64. PARM16 Parm16;
  65. CHAR pchTempFile[MAX_PATH];
  66. BOOL bRet = FALSE;
  67. PVPVOID vpBase16 = (PVPVOID) ((ULONG) vpbmi16 & 0xffff0000);
  68. if ((hdcMem = W32FindAndLockDibInfo((USHORT)HIWORD(vpbmi16))) != (HDC)NULL) {
  69. return hdcMem;
  70. }
  71. // First create a memory device context compatible to
  72. // the app's current screen
  73. if ((hdcMem = CreateCompatibleDC (NULL)) == NULL) {
  74. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateCompatibleDC failed\n"));
  75. return NULL;
  76. }
  77. // Copy bmi16 to bmi32. DIB.DRV only supports DIB_RGB_COLORS
  78. lpbmi32 = CopyBMI16ToBMI32(
  79. vpbmi16,
  80. (LPBITMAPINFO)&bmi32,
  81. (WORD) DIB_RGB_COLORS);
  82. // this hack for Director 4.0 does essentially what WFW does
  83. // if this bitmap is 0 sized, just return an hDC for something simple
  84. if(bmi32.bmiHeader.biSizeImage == 0 &&
  85. (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_DIBDRVIMAGESIZEZERO)) {
  86. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv:Zero biSizeImage, returning memory DC!\n"));
  87. return hdcMem;
  88. }
  89. try {
  90. // Copy the whole thing into a temp file. First get a temp file name
  91. if ((nSize = DPM_GetTempPath (MAX_PATH, pchTempFile)) == 0 ||
  92. nSize >= MAX_PATH)
  93. goto hdd_err;
  94. if (DPM_GetTempFileName (pchTempFile,
  95. "DIB",
  96. 0,
  97. pchTempFile) == 0)
  98. goto hdd_err;
  99. if ((hfile = DPM_CreateFile (pchTempFile,
  100. GENERIC_READ | GENERIC_WRITE,
  101. FILE_SHARE_WRITE,
  102. NULL,
  103. CREATE_ALWAYS,
  104. (FILE_ATTRIBUTE_NORMAL |
  105. FILE_ATTRIBUTE_TEMPORARY |
  106. FILE_FLAG_DELETE_ON_CLOSE),
  107. NULL)) == INVALID_HANDLE_VALUE) {
  108. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateFile failed\n"));
  109. goto hdd_err;
  110. }
  111. // call back to get the size of the global object
  112. // associated with vpbmi16
  113. Parm16.WndProc.wParam = HIWORD(vpbmi16);
  114. CallBack16(RET_GETDIBSIZE,
  115. &Parm16,
  116. 0,
  117. (PVPVOID)&ulSelectorLimit);
  118. Parm16.WndProc.wParam = HIWORD(vpbmi16);
  119. if (ulSelectorLimit == 0xffffffff || ulSelectorLimit == 0) {
  120. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv Invalid Selector %x\n",HIWORD(vpbmi16)));
  121. goto hdd_err;
  122. }
  123. ulSelectorLimit++;
  124. OriginalSelLimit = ulSelectorLimit;
  125. CallBack16(RET_GETDIBFLAGS,
  126. &Parm16,
  127. 0,
  128. (PVPVOID)&OriginalFlags);
  129. if (OriginalFlags == 0x4) { //GA_DGROUP
  130. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv GA_DGROUP Not Handled\n"));
  131. goto hdd_err;
  132. }
  133. GETVDMPTR(vpBase16, ulSelectorLimit, pbmi16);
  134. nbmiSize = GetBMI16Size(vpbmi16, (WORD) DIB_RGB_COLORS, &dwClrUsed);
  135. // Under NT CreateDIBSection will fail if the offset to the bits
  136. // is not dword aligned. So we may have to add some space at the top
  137. // of the section to get the offset correctly aligned.
  138. nAlignmentSpace = (nbmiSize+LOWORD(vpbmi16)) % 4;
  139. if (nAlignmentSpace) {
  140. if (DPM_WriteFile (hfile,
  141. pbmi16,
  142. nAlignmentSpace,
  143. &nBytesWritten,
  144. NULL) == FALSE ||
  145. nBytesWritten != (INT) nAlignmentSpace)
  146. goto hdd_err;
  147. }
  148. //
  149. // detect a clinical case of bitedit screwing around dib.drv
  150. //
  151. // code below is using dib macros declared in wdib.h
  152. // namely:
  153. // DibNumColors - yields max number of colors in dib
  154. // DibColors - yields pointer to a dib color table
  155. //
  156. // Function W32CheckDibColorIndices checks to see if DIB color
  157. // table looks like a number (defined usually by biClrImportant)
  158. // of WORD indices in a sequential order (0, 1, 2, ...)
  159. // if this is the case, app is trying to use undocumented feature
  160. // of DIB.DRV that turns color matching off in this case.
  161. // Since we cannot enforce that rule, we approximate it by filling
  162. // color table by a number of known (and always same) entries
  163. // When blitting occurs, no color matching will be performed (when
  164. // both target and destination are of this very nature).
  165. // For no reason at all we fill color table with vga colors.
  166. // Sequential indices could have worked just as well.
  167. //
  168. // Modifications are made to memory pointed to by lpbmi32
  169. if (W32CheckDibColorIndices((LPBITMAPINFOHEADER)lpbmi32)) {
  170. BYTE i;
  171. INT nColors;
  172. LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpbmi32;
  173. LPRGBQUAD lprgbq = (LPRGBQUAD)DibColors(lpbmi);
  174. nColors = DibNumColors(lpbmi);
  175. lpbmi->biClrImportant = nColors;
  176. switch (lpbmi->biBitCount) {
  177. case 1:
  178. lprgbq[0] = rgbVGA[0];
  179. lprgbq[1] = rgbVGA[0x0f];
  180. break;
  181. case 4:
  182. RtlCopyMemory(lprgbq, rgbVGA, sizeof(rgbVGA));
  183. break;
  184. case 8:
  185. RtlCopyMemory(lprgbq, rgbVGA, 8*sizeof(RGBQUAD));
  186. RtlCopyMemory(lprgbq+248, rgbVGA+8, 8*sizeof(RGBQUAD));
  187. RtlCopyMemory(lprgbq+8, rgb4, 2*sizeof(RGBQUAD));
  188. RtlCopyMemory(lprgbq+246, rgb4+2, 2*sizeof(RGBQUAD));
  189. for (i = 10; i < 246; ++i) {
  190. lprgbq[i].rgbBlue = i;
  191. lprgbq[i].rgbGreen= 0;
  192. lprgbq[i].rgbRed = 0;
  193. lprgbq[i].rgbReserved = 0;
  194. }
  195. break;
  196. default: // this should never happen
  197. break;
  198. }
  199. }
  200. if (DPM_WriteFile (hfile,
  201. pbmi16,
  202. ulSelectorLimit,
  203. &nBytesWritten,
  204. NULL) == FALSE || nBytesWritten != (INT) ulSelectorLimit)
  205. goto hdd_err;
  206. if (ulSelectorLimit < 64*1024) {
  207. if (DPM_SetFilePointer (hfile,
  208. 64*1024+nAlignmentSpace,
  209. NULL,
  210. FILE_BEGIN) == -1)
  211. goto hdd_err;
  212. if (DPM_SetEndOfFile (hfile) == FALSE)
  213. goto hdd_err;
  214. ulSelectorLimit = 64*1024;
  215. }
  216. if ((hsec = CreateFileMapping (hfile,
  217. NULL,
  218. PAGE_READWRITE | SEC_COMMIT,
  219. 0,
  220. ulSelectorLimit+nAlignmentSpace,
  221. NULL)) == NULL) {
  222. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateFileMapping Failed\n"));
  223. goto hdd_err;
  224. }
  225. // Now create the DIB section
  226. if ((hbm = CreateDIBSection (hdcMem,
  227. lpbmi32,
  228. DIB_RGB_COLORS,
  229. &pvBits,
  230. hsec,
  231. nAlignmentSpace + LOWORD(vpbmi16) + nbmiSize
  232. )) == NULL) {
  233. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateDibSection Failed\n"));
  234. goto hdd_err;
  235. }
  236. FREEVDMPTR(pbmi16);
  237. if((pvBits = MapViewOfFile(hsec,
  238. FILE_MAP_WRITE,
  239. 0,
  240. 0,
  241. ulSelectorLimit+nAlignmentSpace)) == NULL) {
  242. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv MapViewOfFile Failed\n"));
  243. goto hdd_err;
  244. }
  245. pvBits = (PVOID) ((ULONG)pvBits + nAlignmentSpace);
  246. SelectObject (hdcMem, hbm);
  247. GdiSetBatchLimit(1);
  248. #ifndef i386
  249. if (!NT_SUCCESS(VdmAddVirtualMemory((ULONG)pvBits,
  250. (ULONG)ulSelectorLimit,
  251. (PULONG)&pvIntelBits))) {
  252. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv VdmAddVirtualMemory failed\n"));
  253. goto hdd_err;
  254. }
  255. // On risc platforms, the intel base + the intel linear address
  256. // of the DIB section is not equal to the DIB section's process
  257. // address. This is because of the VdmAddVirtualMemory call
  258. // above. So here we zap the correct address into the flataddress
  259. // array.
  260. if (!VdmAddDescriptorMapping(HIWORD(vpbmi16),
  261. (USHORT) ((ulSelectorLimit+65535)/65536),
  262. (ULONG) pvIntelBits,
  263. (ULONG) pvBits)) {
  264. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv VdmAddDescriptorMapping failed\n"));
  265. goto hdd_err;
  266. }
  267. #else
  268. pvIntelBits = pvBits;
  269. #endif
  270. // Finally set the selectors to the new DIB
  271. Parm16.WndProc.wParam = HIWORD(vpbmi16);
  272. Parm16.WndProc.lParam = (LONG)pvIntelBits;
  273. Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT
  274. Parm16.WndProc.hwnd = 1; // set so it's not randomly 0
  275. CallBack16(RET_SETDIBSEL,
  276. &Parm16,
  277. 0,
  278. (PVPVOID)&RetVal);
  279. if (!RetVal) {
  280. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv Callback set_sel_for_dib failed\n"));
  281. goto hdd_err;
  282. }
  283. // Store all the relevant information so that DeleteDC could
  284. // free all the resources later.
  285. if (W32AddDibInfo(hdcMem,
  286. hfile,
  287. hsec,
  288. nAlignmentSpace,
  289. pvBits,
  290. pvIntelBits,
  291. hbm,
  292. OriginalSelLimit,
  293. (USHORT)OriginalFlags,
  294. (USHORT)((HIWORD(vpbmi16)))) == FALSE)
  295. goto hdd_err;
  296. // Finally spit out the dump for debugging
  297. LOGDEBUG(6,("\t\tWOW::W32HandleDibDrv hdc=%04x nAlignment=%04x\n\t\tNewDib=%x OldDib=%04x:%04x DibSize=%x DibFlags=%x\n",hdcMem,nAlignmentSpace,pvBits,HIWORD(vpbmi16),LOWORD(vpbmi16),OriginalSelLimit,(USHORT)OriginalFlags));
  298. bRet = TRUE;
  299. hdd_err:;
  300. }
  301. finally {
  302. if (!bRet) {
  303. if (hdcMem) {
  304. DeleteDC (hdcMem);
  305. hdcMem = NULL;
  306. }
  307. if (hfile)
  308. DPM_CloseHandle (hfile);
  309. if (hsec)
  310. CloseHandle (hsec);
  311. if (hbm)
  312. CloseHandle (hbm);
  313. }
  314. }
  315. return hdcMem;
  316. }
  317. BOOL W32AddDibInfo (
  318. HDC hdcMem,
  319. HANDLE hfile,
  320. HANDLE hsec,
  321. ULONG nalignment,
  322. PVOID newdib,
  323. PVOID newIntelDib,
  324. HBITMAP hbm,
  325. ULONG dibsize,
  326. USHORT originaldibflags,
  327. USHORT originaldibsel
  328. )
  329. {
  330. PDIBINFO pdi;
  331. if ((pdi = malloc_w (sizeof (DIBINFO))) == NULL)
  332. return FALSE;
  333. pdi->di_hdc = hdcMem;
  334. pdi->di_hfile = hfile;
  335. pdi->di_hsec = hsec;
  336. pdi->di_nalignment = nalignment;
  337. pdi->di_newdib = newdib;
  338. pdi->di_newIntelDib = newIntelDib;
  339. pdi->di_hbm = hbm;
  340. pdi->di_dibsize = dibsize;
  341. pdi->di_originaldibsel = originaldibsel;
  342. pdi->di_originaldibflags = originaldibflags;
  343. pdi->di_next = pDibInfoHead;
  344. pdi->di_lockcount = 1;
  345. pDibInfoHead = pdi;
  346. return TRUE;
  347. }
  348. BOOL W32FreeDibInfoHandle(PDIBINFO pdi, PDIBINFO pdiLast)
  349. {
  350. if (W32RestoreOldDib (pdi) == 0) {
  351. LOGDEBUG(LOG_ALWAYS,("\nWOW::W32RestoreDib failed\n"));
  352. return FALSE;
  353. }
  354. #ifndef i386
  355. VdmRemoveVirtualMemory((ULONG)pdi->di_newIntelDib);
  356. #endif
  357. UnmapViewOfFile ((LPVOID)((ULONG)pdi->di_newdib - pdi->di_nalignment));
  358. DeleteObject (pdi->di_hbm);
  359. CloseHandle (pdi->di_hsec);
  360. DPM_CloseHandle (pdi->di_hfile);
  361. DeleteDC(pdi->di_hdc);
  362. W32FreeDibInfo (pdi, pdiLast);
  363. return TRUE;
  364. }
  365. BOOL W32CheckAndFreeDibInfo (HDC hdc)
  366. {
  367. PDIBINFO pdi = pDibInfoHead,pdiLast=NULL;
  368. while (pdi) {
  369. if (pdi->di_hdc == hdc){
  370. if (--pdi->di_lockcount) {
  371. //
  372. // This must be a releasedc within a nested call to createdc.
  373. // Just return, as this should be released again later.
  374. //
  375. LOGDEBUG(LOG_ALWAYS, ("\nW32CheckAndFreeDibInfo: lockcount!=0\n"));
  376. return TRUE;
  377. }
  378. return W32FreeDibInfoHandle(pdi, pdiLast);
  379. }
  380. pdiLast = pdi;
  381. pdi = pdi->di_next;
  382. }
  383. return FALSE;
  384. }
  385. VOID W32FreeDibInfo (PDIBINFO pdiCur, PDIBINFO pdiLast)
  386. {
  387. if (pdiLast == NULL)
  388. pDibInfoHead = pdiCur->di_next;
  389. else
  390. pdiLast->di_next = pdiCur->di_next;
  391. free_w (pdiCur);
  392. }
  393. ULONG W32RestoreOldDib (PDIBINFO pdi)
  394. {
  395. PARM16 Parm16;
  396. ULONG retval;
  397. // callback to allocate memory and copy the dib from dib section
  398. Parm16.WndProc.wParam = pdi->di_originaldibsel;
  399. Parm16.WndProc.lParam = (LONG) (pdi->di_newdib);
  400. Parm16.WndProc.wMsg = pdi->di_originaldibflags;
  401. CallBack16(RET_FREEDIBSEL,
  402. &Parm16,
  403. 0,
  404. (PVPVOID)&retval);
  405. return retval;
  406. }
  407. HDC W32FindAndLockDibInfo (USHORT sel)
  408. {
  409. PDIBINFO pdi = pDibInfoHead;
  410. while (pdi) {
  411. if (pdi->di_originaldibsel == sel){
  412. pdi->di_lockcount++;
  413. return (pdi->di_hdc);
  414. }
  415. pdi = pdi->di_next;
  416. }
  417. return (HDC) NULL;
  418. }
  419. //
  420. // This function is called from krnl386 if GlobalReAlloc or GlobalFree is
  421. // trying to operate on memory which we suspect is dib-mapped. It finds
  422. // dib by original selector and restores it, thus allowing respective function
  423. // to succeede. Bitedit is the app that does globalrealloc before DeleteDC
  424. //
  425. //
  426. ULONG FASTCALL WK32FindAndReleaseDib(PVDMFRAME pvf)
  427. {
  428. USHORT sel;
  429. PFINDANDRELEASEDIB16 parg;
  430. PDIBINFO pdi;
  431. PDIBINFO pdiLast = NULL;
  432. // get the argument pointer, see wowkrnl.h
  433. GETARGPTR(pvf, sizeof(*parg), parg);
  434. // get selector from the handle
  435. sel = parg->hdib | (USHORT)0x01; // "convert to sel"
  436. // find this said sel in the dibinfo
  437. pdi = pDibInfoHead;
  438. while (pdi) {
  439. if (pdi->di_originaldibsel == sel) {
  440. // found ! this is what we are releasing or reallocating
  441. LOGDEBUG(LOG_ALWAYS, ("\nWOW: In FindAndReleaseDIB function %d\n", (DWORD)parg->wFunId));
  442. // see if we need to nuke...
  443. if (--pdi->di_lockcount) {
  444. // the problem with lock count...
  445. LOGDEBUG(LOG_ALWAYS, ("\nWOW: FindAndReleaseDib failed (lock count!)\n"));
  446. return FALSE;
  447. }
  448. return W32FreeDibInfoHandle(pdi, pdiLast);
  449. }
  450. pdiLast = pdi;
  451. pdi = pdi->di_next;
  452. }
  453. return FALSE;
  454. }
  455. BOOL W32CheckDibColorIndices(LPBITMAPINFOHEADER lpbmi)
  456. {
  457. WORD i, nColors;
  458. LPWORD lpw = (LPWORD)DibColors(lpbmi);
  459. nColors = DibNumColors(lpbmi);
  460. if (lpbmi->biClrImportant) {
  461. nColors = min(nColors, (WORD)lpbmi->biClrImportant);
  462. }
  463. for (i = 0; i < nColors; ++i) {
  464. if (*lpw++ != i) {
  465. return FALSE;
  466. }
  467. }
  468. LOGDEBUG(LOG_ALWAYS, ("\nUndocumented Dib.Drv behaviour used\n"));
  469. return TRUE;
  470. }
  471. /******************************Public*Routine******************************\
  472. * DIBSection specific calls
  473. *
  474. * History:
  475. * 04-May-1994 -by- Eric Kutter [erick]
  476. * Wrote it.
  477. \**************************************************************************/
  478. ULONG cjBitmapBitsSize(CONST BITMAPINFO *pbmi)
  479. {
  480. // Check for PM-style DIB
  481. if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  482. {
  483. LPBITMAPCOREINFO pbmci;
  484. pbmci = (LPBITMAPCOREINFO)pbmi;
  485. return(CJSCAN(pbmci->bmciHeader.bcWidth,pbmci->bmciHeader.bcPlanes,
  486. pbmci->bmciHeader.bcBitCount) *
  487. pbmci->bmciHeader.bcHeight);
  488. }
  489. // not a core header
  490. if ((pbmi->bmiHeader.biCompression == BI_RGB) ||
  491. (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
  492. {
  493. return(CJSCAN(pbmi->bmiHeader.biWidth,pbmi->bmiHeader.biPlanes,
  494. pbmi->bmiHeader.biBitCount) *
  495. ABS(pbmi->bmiHeader.biHeight));
  496. }
  497. else
  498. {
  499. return(pbmi->bmiHeader.biSizeImage);
  500. }
  501. }
  502. ULONG FASTCALL WG32CreateDIBSection(PVDMFRAME pFrame)
  503. {
  504. ULONG ul = 0;
  505. STACKBMI32 bmi32;
  506. LPBITMAPINFO lpbmi32;
  507. HBITMAP hbm32;
  508. PVOID pv16, pvBits, pvIntelBits;
  509. PVPVOID vpbmi16;
  510. PVOID pvBits32;
  511. DWORD dwArg16;
  512. register PCREATEDIBSECTION16 parg16;
  513. GETARGPTR(pFrame, sizeof(CREATEDIBSECTION16), parg16);
  514. // this is performance hack so we don't generate extra code
  515. dwArg16 = FETCHDWORD(parg16->f4); // do it once here
  516. pv16 = (PVOID)GetPModeVDMPointer(dwArg16, sizeof(DWORD)); // aligned here!
  517. WOW32ASSERTMSG(((parg16->f5 == 0) && (parg16->f6 == 0)),
  518. ("WOW:WG32CreateDIBSection, hSection/dwOffset non-null\n"));
  519. vpbmi16 = (PVPVOID)FETCHDWORD(parg16->f2);
  520. lpbmi32 = CopyBMI16ToBMI32(vpbmi16,
  521. (LPBITMAPINFO)&bmi32,
  522. FETCHWORD(parg16->f3));
  523. hbm32 = CreateDIBSection(HDC32(parg16->f1),
  524. lpbmi32,
  525. WORD32(parg16->f3),
  526. &pvBits,
  527. NULL,
  528. 0);
  529. if (hbm32 != 0)
  530. {
  531. PARM16 Parm16;
  532. PDIBSECTIONINFO pdi;
  533. ULONG ulSelectorLimit;
  534. ulSelectorLimit = (ULONG)cjBitmapBitsSize(lpbmi32);
  535. #ifndef i386
  536. if (!NT_SUCCESS(VdmAddVirtualMemory((ULONG)pvBits,
  537. ulSelectorLimit,
  538. (PULONG)&pvIntelBits))) {
  539. LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection VdmAddVirtualMemory failed\n"));
  540. goto cds_err;
  541. }
  542. #else
  543. pvIntelBits = pvBits;
  544. #endif
  545. // Create a selector array for the bits backed by pvIntelBits
  546. Parm16.WndProc.wParam = (WORD)-1; // -1 => allocate selectors
  547. Parm16.WndProc.lParam = (LONG) pvIntelBits; // backing pointer
  548. Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT
  549. Parm16.WndProc.hwnd = (WORD)((ulSelectorLimit+65535)/65536);// selector count
  550. CallBack16(RET_SETDIBSEL,
  551. &Parm16,
  552. 0,
  553. (PVPVOID)&pvBits32);
  554. // 16:16 pointer is still valid as call above makes no difference
  555. if (pv16 != NULL) {
  556. *(UNALIGNED PVOID*)pv16 = pvBits32;
  557. }
  558. if (pvBits32 == NULL) {
  559. LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection, Callback set_sel_for_dib failed\n"));
  560. goto cds_err;
  561. }
  562. #ifndef i386
  563. // okay, that was successful - map the descriptors properly
  564. if (!VdmAddDescriptorMapping(HIWORD(pvBits32),
  565. (USHORT) ((ulSelectorLimit+65535)/65536),
  566. (ULONG) pvIntelBits,
  567. (ULONG) pvBits)) {
  568. LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection VdmAddDescriptorMapping failed\n"));
  569. goto cds_err;
  570. }
  571. #endif
  572. LOGDEBUG(LOG_ALWAYS, ("\nWOW:CreateDIBSection: [16:16 %x] [Intel %x] [Flat %x]\n",
  573. pvBits32, pvIntelBits, pvBits));
  574. ul = GETHBITMAP16(hbm32);
  575. // Add it to the list used for cleanup at DeleteObject time.
  576. if ((pdi = malloc_w (sizeof (DIBSECTIONINFO))) != NULL) {
  577. pdi->di_hbm = hbm32;
  578. pdi->di_pv16 = pvBits32;
  579. #ifndef i386
  580. pdi->di_newIntelDib = pvIntelBits;
  581. #endif
  582. pdi->di_next = pDibSectionInfoHead;
  583. pDibSectionInfoHead = pdi;
  584. // need to turn batching off since a DIBSECTION means the app can
  585. // also draw on the bitmap and we need synchronization.
  586. GdiSetBatchLimit(1);
  587. goto cds_ok;
  588. }
  589. else {
  590. // Failure, free the selector array
  591. Parm16.WndProc.wParam = (WORD)-1; // -1 => allocate/free
  592. Parm16.WndProc.lParam = (LONG) pvBits32; // pointer
  593. Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT
  594. Parm16.WndProc.hwnd = 0; // 0 => free
  595. CallBack16(RET_SETDIBSEL,
  596. &Parm16,
  597. 0,
  598. (PVPVOID)&ul);
  599. #ifndef i386
  600. VdmRemoveVirtualMemory((ULONG)pvIntelBits);
  601. #endif
  602. }
  603. }
  604. else {
  605. LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection, CreateDibSection Failed\n"));
  606. }
  607. cds_err:
  608. if (hbm32 != 0) {
  609. DeleteObject(hbm32);
  610. DeleteWOWGdiHandle(hbm32, (HAND16)LOWORD(ul));
  611. }
  612. LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection returning failure\n"));
  613. ul = 0;
  614. cds_ok:
  615. WOW32APIWARN(ul, "CreateDIBSection");
  616. FREEMISCPTR(pv16);
  617. FREEARGPTR(parg16);
  618. return(ul);
  619. }
  620. ULONG FASTCALL WG32GetDIBColorTable(PVDMFRAME pFrame)
  621. {
  622. ULONG ul = 0;
  623. RGBQUAD * prgb;
  624. register PGETDIBCOLORTABLE16 parg16;
  625. GETARGPTR(pFrame, sizeof(GETDIBCOLORTABLE16), parg16);
  626. GETMISCPTR(parg16->f4,prgb);
  627. ul = (ULONG)GetDIBColorTable(HDC32(parg16->f1),
  628. parg16->f2,
  629. parg16->f3,
  630. prgb);
  631. WOW32APIWARN(ul, "GetDIBColorTable");
  632. if (ul)
  633. FLUSHVDMPTR(parg16->f4,sizeof(RGBQUAD) * ul,prgb);
  634. FREEMISCPTR(prgb);
  635. FREEARGPTR(parg16);
  636. return(ul);
  637. }
  638. ULONG FASTCALL WG32SetDIBColorTable(PVDMFRAME pFrame)
  639. {
  640. ULONG ul = 0;
  641. RGBQUAD * prgb;
  642. register PSETDIBCOLORTABLE16 parg16;
  643. GETARGPTR(pFrame, sizeof(SETDIBCOLORTABLE16), parg16);
  644. GETMISCPTR(parg16->f4,prgb);
  645. ul = (ULONG)SetDIBColorTable(HDC32(parg16->f1),
  646. parg16->f2,
  647. parg16->f3,
  648. prgb);
  649. WOW32APIWARN(ul, "SetDIBColorTable");
  650. FREEMISCPTR(prgb);
  651. FREEARGPTR(parg16);
  652. return(ul);
  653. }
  654. // DIBSection routines
  655. BOOL W32CheckAndFreeDibSectionInfo (HBITMAP hbm)
  656. {
  657. PDIBSECTIONINFO pdi = pDibSectionInfoHead,pdiLast=NULL;
  658. while (pdi) {
  659. if (pdi->di_hbm == hbm){
  660. PARM16 Parm16;
  661. ULONG ulRet;
  662. // need to free the selector array for the memory
  663. Parm16.WndProc.wParam = (WORD)-1; // selector, -1 == allocate/free
  664. Parm16.WndProc.lParam = (LONG) pdi->di_pv16; // pointer
  665. Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT
  666. Parm16.WndProc.hwnd = 0; // selector count, 0 == free
  667. CallBack16(RET_SETDIBSEL,
  668. &Parm16,
  669. 0,
  670. (PVPVOID)&ulRet);
  671. #ifndef i386
  672. VdmRemoveVirtualMemory((ULONG)pdi->di_newIntelDib);
  673. #endif
  674. if (pdiLast == NULL)
  675. pDibSectionInfoHead = pdi->di_next;
  676. else
  677. pdiLast->di_next = pdi->di_next;
  678. // now delete the object
  679. DeleteObject (pdi->di_hbm);
  680. free_w(pdi);
  681. return TRUE;
  682. }
  683. pdiLast = pdi;
  684. pdi = pdi->di_next;
  685. }
  686. return FALSE;
  687. }