diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/wow32/wdib.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/mvdm/wow32/wdib.c')
-rw-r--r-- | private/mvdm/wow32/wdib.c | 859 |
1 files changed, 859 insertions, 0 deletions
diff --git a/private/mvdm/wow32/wdib.c b/private/mvdm/wow32/wdib.c new file mode 100644 index 000000000..6cdececf3 --- /dev/null +++ b/private/mvdm/wow32/wdib.c @@ -0,0 +1,859 @@ +/*++ + * + * WOW v1.0 + * + * Copyright (c) 1991, Microsoft Corporation + * + * WDIB.C + * DIB.DRV support + * + * History: + * 28-Apr-1994 Sudeep Bharati + * Created. + * +--*/ + + +#include "precomp.h" +#pragma hdrstop +#include "wowgdip.h" +#include "wdib.h" +#include "memapi.h" + +MODNAME(wdib.c); + +#define CJSCAN(width,planes,bits) ((((width)*(planes)*(bits)+31) & ~31) / 8) +#define ABS(X) (((X) < 0 ) ? -(X) : (X)) + +BOOL W32CheckDibColorIndices(LPBITMAPINFOHEADER lpbmi); + +// VGA colors +RGBQUAD rgbVGA[] = { +// Blue Green Red + 0x00, 0x00, 0x00, 0, // 0 ; black + 0x00, 0x00, 0x80, 0, // 1 ; dark red + 0x00, 0x80, 0x00, 0, // 2 ; dark green + 0x00, 0x80, 0x80, 0, // 3 ; mustard + 0x80, 0x00, 0x00, 0, // 4 ; dark blue + 0x80, 0x00, 0x80, 0, // 5 ; purple + 0x80, 0x80, 0x00, 0, // 6 ; dark turquoise + 0xc0, 0xc0, 0xc0, 0, // 7 ; gray + 0x80, 0x80, 0x80, 0, // 8 ; dark gray + 0x00, 0x00, 0xff, 0, // 9 ; red + 0x00, 0xff, 0x00, 0, // a ; green + 0x00, 0xff, 0xff, 0, // b ; yellow + 0xff, 0x00, 0x00, 0, // c ; blue + 0xff, 0x00, 0xff, 0, // d ; magenta + 0xff, 0xff, 0x00, 0, // e ; cyan + 0xff, 0xff, 0xff, 0 // f ; white +}; + +RGBQUAD rgb4[] = { + 0xc0, 0xdc, 0xc0, 0, // 8 + 0xf0, 0xca, 0xa6, 0, // 9 + 0xf0, 0xfb, 0xff, 0, // 246 + 0xa4, 0xa0, 0xa0, 0 // 247 +}; + + + +PDIBINFO pDibInfoHead = NULL; +PDIBSECTIONINFO pDibSectionInfoHead = NULL; + +HDC W32HandleDibDrv (PVPVOID vpbmi16) +{ + HDC hdcMem = NULL; + HBITMAP hbm = NULL; + PVOID pvBits, pvIntelBits; + STACKBMI32 bmi32; + LPBITMAPINFO lpbmi32; + DWORD dwClrUsed,nSize,nAlignmentSpace; + PBITMAPINFOHEADER16 pbmi16; + INT nbmiSize,nBytesWritten; + HANDLE hfile=NULL,hsec=NULL; + ULONG RetVal,OriginalSelLimit,SelectorLimit,OriginalFlags; + PARM16 Parm16; + CHAR pchTempFile[MAX_PATH]; + BOOL bRet = FALSE; + PVPVOID vpBase16 = (PVPVOID) ((ULONG) vpbmi16 & 0xffff0000); + + if ((hdcMem = W32FindAndLockDibInfo((USHORT)HIWORD(vpbmi16))) != (HDC)NULL) { + return hdcMem; + } + + // First create a memory device context compatible to + // the app's current screen + if ((hdcMem = CreateCompatibleDC (NULL)) == NULL) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateCompatibleDC failed\n")); + return NULL; + } + + // Copy bmi16 to bmi32. DIB.DRV only supports DIB_RGB_COLORS + lpbmi32 = CopyBMI16ToBMI32( + vpbmi16, + (LPBITMAPINFO)&bmi32, + (WORD) DIB_RGB_COLORS); + + // this hack for Director 4.0 does essentially what WFW does + // if this bitmap is 0 sized, just return an hDC for something simple + if(bmi32.bmiHeader.biSizeImage == 0 && + (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_DIBDRVIMAGESIZEZERO)) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv:Zero biSizeImage, returning memory DC!\n")); + return hdcMem; + } + + try { + + // Copy the wholething into a temp file. First get a temp file name + if ((nSize = GetTempPath (MAX_PATH, pchTempFile)) == 0 || + nSize >= MAX_PATH) + goto hdd_err; + + if (GetTempFileName (pchTempFile, + "DIB", + 0, + pchTempFile) == 0) + goto hdd_err; + + if ((hfile = CreateFile (pchTempFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + (FILE_ATTRIBUTE_NORMAL | + FILE_ATTRIBUTE_TEMPORARY | + FILE_FLAG_DELETE_ON_CLOSE), + NULL)) == INVALID_HANDLE_VALUE) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateFile failed\n")); + goto hdd_err; + } + + // call back to get the size of the global object + // associated with vpbmi16 + Parm16.WndProc.wParam = HIWORD(vpbmi16); + + CallBack16(RET_GETDIBSIZE, + &Parm16, + 0, + (PVPVOID)&SelectorLimit); + + Parm16.WndProc.wParam = HIWORD(vpbmi16); + + if (SelectorLimit == 0xffffffff || SelectorLimit == 0) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv Invalid Selector %x\n",HIWORD(vpbmi16))); + goto hdd_err; + } + + SelectorLimit++; + + OriginalSelLimit = SelectorLimit; + + CallBack16(RET_GETDIBFLAGS, + &Parm16, + 0, + (PVPVOID)&OriginalFlags); + + if (OriginalFlags == 0x4) { //GA_DGROUP + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv GA_DGROUP Not Handled\n")); + goto hdd_err; + } + + GETVDMPTR(vpBase16, SelectorLimit, pbmi16); + + nbmiSize = GetBMI16Size(vpbmi16, (WORD) DIB_RGB_COLORS, &dwClrUsed); + + // Under NT CreateDIBSection will fail if the offset to the bits + // is not dword aligned. So we may have to add some space at the top + // of the section to get the offset correctly aligned. + + nAlignmentSpace = (nbmiSize+LOWORD(vpbmi16)) % 4; + + if (nAlignmentSpace) { + if (WriteFile (hfile, + pbmi16, + nAlignmentSpace, + &nBytesWritten, + NULL) == FALSE || + nBytesWritten != (INT) nAlignmentSpace) + goto hdd_err; + } + + // + // detect a clinical case of bitedit screwing around dib.drv + // + // code below is using dib macros declared in wdib.h + // namely: + // DibNumColors - yields max number of colors in dib + // DibColors - yields pointer to a dib color table + // + // Function W32CheckDibColorIndices checks to see if DIB color + // table looks like a number (defined usually by biClrImportant) + // of WORD indices in a sequential order (0, 1, 2, ...) + // if this is the case, app is trying to use undocumented feature + // of DIB.DRV that turns color matching off in this case. + // Since we cannot enforce that rule, we approximate it by filling + // color table by a number of known (and always same) entries + // When blitting occurs, no color matching will be performed (when + // both target and destination are of this very nature). + // For no reason at all we fill color table with vga colors. + // Sequential indices could have worked just as well. + // + // Modifications are made to memory pointed to by lpbmi32 + + if (W32CheckDibColorIndices((LPBITMAPINFOHEADER)lpbmi32)) { + INT i, nColors; + LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpbmi32; + LPRGBQUAD lprgbq = (LPRGBQUAD)DibColors(lpbmi); + + nColors = DibNumColors(lpbmi); + lpbmi->biClrImportant = nColors; + + switch (lpbmi->biBitCount) { + case 1: + lprgbq[0] = rgbVGA[0]; + lprgbq[1] = rgbVGA[0x0f]; + break; + + case 4: + RtlCopyMemory(lprgbq, rgbVGA, sizeof(rgbVGA)); + break; + + case 8: + RtlCopyMemory(lprgbq, rgbVGA, 8*sizeof(RGBQUAD)); + RtlCopyMemory(lprgbq+248, rgbVGA+8, 8*sizeof(RGBQUAD)); + RtlCopyMemory(lprgbq+8, rgb4, 2*sizeof(RGBQUAD)); + RtlCopyMemory(lprgbq+246, rgb4+2, 2*sizeof(RGBQUAD)); + for (i = 10; i < 246; ++i) { + lprgbq[i].rgbBlue = i; + lprgbq[i].rgbGreen= 0; + lprgbq[i].rgbRed = 0; + lprgbq[i].rgbReserved = 0; + } + break; + + default: // this should never happen + break; + } + } + + if (WriteFile (hfile, + pbmi16, + SelectorLimit, + &nBytesWritten, + NULL) == FALSE || nBytesWritten != (INT) SelectorLimit) + goto hdd_err; + + if (SelectorLimit < 64*1024) { + if (SetFilePointer (hfile, + 64*1024+nAlignmentSpace, + NULL, + FILE_BEGIN) == -1) + goto hdd_err; + + if (SetEndOfFile (hfile) == FALSE) + goto hdd_err; + + SelectorLimit = 64*1024; + } + + if ((hsec = CreateFileMapping (hfile, + NULL, + PAGE_READWRITE | SEC_COMMIT, + 0, + SelectorLimit+nAlignmentSpace, + NULL)) == NULL) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateFileMapping Failed\n")); + goto hdd_err; + } + + // Now create the DIB section + if ((hbm = CreateDIBSection (hdcMem, + lpbmi32, + DIB_RGB_COLORS, + &pvBits, + hsec, + nAlignmentSpace + LOWORD(vpbmi16) + nbmiSize + )) == NULL) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateDibSection Failed\n")); + goto hdd_err; + } + + FREEVDMPTR(pbmi16); + + if((pvBits = MapViewOfFile(hsec, + FILE_MAP_WRITE, + 0, + 0, + SelectorLimit+nAlignmentSpace)) == NULL) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv MapViewOfFile Failed\n")); + goto hdd_err; + } + + pvBits = (PVOID) ((ULONG)pvBits + nAlignmentSpace); + + SelectObject (hdcMem, hbm); + + GdiSetBatchLimit(1); + +#ifndef i386 + if (!NT_SUCCESS(VdmAddVirtualMemory((ULONG)pvBits, + (ULONG)SelectorLimit, + (PULONG)&pvIntelBits))) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv VdmAddVirtualMemory failed\n")); + goto hdd_err; + } + + // On risc platforms, the intel base + the intel linear address + // of the DIB section is not equal to the DIB section's process + // address. This is because of the VdmAddVirtualMemory call + // above. So here we zap the correct address into the flataddress + // array. + if (!VdmAddDescriptorMapping(HIWORD(vpbmi16), + (USHORT) ((SelectorLimit+65535)/65536), + (ULONG) pvIntelBits, + (ULONG) pvBits)) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv VdmAddDescriptorMapping failed\n")); + goto hdd_err; + } + +#else + pvIntelBits = pvBits; +#endif + + // Finally set the selectors to the new DIB + Parm16.WndProc.wParam = HIWORD(vpbmi16); + Parm16.WndProc.lParam = (LONG)pvIntelBits; + Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT + Parm16.WndProc.hwnd = 1; // set so it's not randomly 0 + + CallBack16(RET_SETDIBSEL, + &Parm16, + 0, + (PVPVOID)&RetVal); + + if (!RetVal) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv Callback set_sel_for_dib failed\n")); + goto hdd_err; + } + + + // Store all the relevant information so that DeleteDC could + // free all the resources later. + if (W32AddDibInfo(hdcMem, + hfile, + hsec, + nAlignmentSpace, + pvBits, + pvIntelBits, + hbm, + OriginalSelLimit, + (USHORT)OriginalFlags, + (USHORT)((HIWORD(vpbmi16)))) == FALSE) + goto hdd_err; + + + // Finally spit out the dump for debugging + 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)); + + bRet = TRUE; +hdd_err:; + } + finally { + if (!bRet) { + + if (hdcMem) { + DeleteDC (hdcMem); + hdcMem = NULL; + } + if (hfile) + CloseHandle (hfile); + + if (hsec) + CloseHandle (hsec); + + if (hbm) + CloseHandle (hbm); + } + } + return hdcMem; +} + + +BOOL W32AddDibInfo ( + HDC hdcMem, + HANDLE hfile, + HANDLE hsec, + ULONG nalignment, + PVOID newdib, + PVOID newIntelDib, + HBITMAP hbm, + ULONG dibsize, + USHORT originaldibflags, + USHORT originaldibsel + ) +{ + PDIBINFO pdi; + + if ((pdi = malloc_w (sizeof (DIBINFO))) == NULL) + return FALSE; + + pdi->di_hdc = hdcMem; + pdi->di_hfile = hfile; + pdi->di_hsec = hsec; + pdi->di_nalignment = nalignment; + pdi->di_newdib = newdib; + pdi->di_newIntelDib = newIntelDib; + pdi->di_hbm = hbm; + pdi->di_dibsize = dibsize; + pdi->di_originaldibsel = originaldibsel; + pdi->di_originaldibflags = originaldibflags; + pdi->di_next = pDibInfoHead; + pdi->di_lockcount = 1; + pDibInfoHead = pdi; + + return TRUE; +} + +BOOL W32FreeDibInfoHandle(PDIBINFO pdi, PDIBINFO pdiLast) +{ + if (W32RestoreOldDib (pdi) == 0) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::W32RestoreDib failed\n")); + return FALSE; + } +#ifndef i386 + VdmRemoveVirtualMemory((ULONG)pdi->di_newIntelDib); +#endif + UnmapViewOfFile ((LPVOID)((ULONG)pdi->di_newdib - pdi->di_nalignment)); + + DeleteObject (pdi->di_hbm); + CloseHandle (pdi->di_hsec); + CloseHandle (pdi->di_hfile); + + DeleteDC(pdi->di_hdc); + W32FreeDibInfo (pdi, pdiLast); + + return TRUE; +} + + +BOOL W32CheckAndFreeDibInfo (HDC hdc) +{ + PDIBINFO pdi = pDibInfoHead,pdiLast=NULL; + + while (pdi) { + if (pdi->di_hdc == hdc){ + + if (--pdi->di_lockcount) { + // + // This must be a releasedc within a nested call to createdc. + // Just return, as this should be released again later. + // + LOGDEBUG(LOG_ALWAYS, ("\nW32CheckAndFreeDibInfo: lockcount!=0\n")); + return TRUE; + } + + return W32FreeDibInfoHandle(pdi, pdiLast); + } + pdiLast = pdi; + pdi = pdi->di_next; + } + + return FALSE; +} + +VOID W32FreeDibInfo (PDIBINFO pdiCur, PDIBINFO pdiLast) +{ + if (pdiLast == NULL) + pDibInfoHead = pdiCur->di_next; + else + pdiLast->di_next = pdiCur->di_next; + + free_w (pdiCur); +} + +ULONG W32RestoreOldDib (PDIBINFO pdi) +{ + PARM16 Parm16; + ULONG retval; + + // callback to allocate memory and copy the dib from dib section + + Parm16.WndProc.wParam = pdi->di_originaldibsel; + Parm16.WndProc.lParam = (LONG) (pdi->di_newdib); + Parm16.WndProc.wMsg = pdi->di_originaldibflags; + + CallBack16(RET_FREEDIBSEL, + &Parm16, + 0, + (PVPVOID)&retval); + + return retval; +} + + +HDC W32FindAndLockDibInfo (USHORT sel) +{ + PDIBINFO pdi = pDibInfoHead; + + while (pdi) { + + if (pdi->di_originaldibsel == sel){ + pdi->di_lockcount++; + return (pdi->di_hdc); + + } + pdi = pdi->di_next; + + } + return (HDC) NULL; +} + +// +// This function is called from krnl386 if GlobalReAlloc or GlobalFree is +// trying to operate on memory which we suspect is dib-mapped. It finds +// dib by original selector and restores it, thus allowing respective function +// to succeede. Bitedit is the app that does globalrealloc before DeleteDC +// +// + +ULONG FASTCALL WK32FindAndReleaseDib(PVDMFRAME pvf) +{ + USHORT sel; + PFINDANDRELEASEDIB16 parg; + PDIBINFO pdi; + PDIBINFO pdiLast = NULL; + + // get the argument pointer, see wowkrnl.h + GETARGPTR(pvf, sizeof(*parg), parg); + + // get selector from the handle + sel = parg->hdib | (USHORT)0x01; // "convert to sel" + + // find this said sel in the dibinfo + pdi = pDibInfoHead; + while (pdi) { + if (pdi->di_originaldibsel == sel) { + + // found ! this is what we are releasing or reallocating + LOGDEBUG(LOG_ALWAYS, ("\nWOW: In FindAndReleaseDIB function %d\n", (DWORD)parg->wFunId)); + + // see if we need to nuke... + if (--pdi->di_lockcount) { + // the problem with lock count... + LOGDEBUG(LOG_ALWAYS, ("\nWOW: FindAndReleaseDib failed (lock count!)\n")); + return FALSE; + } + + return W32FreeDibInfoHandle(pdi, pdiLast); + } + + pdiLast = pdi; + pdi = pdi->di_next; + } + + return FALSE; +} + + +BOOL W32CheckDibColorIndices(LPBITMAPINFOHEADER lpbmi) +{ + WORD i, nColors; + LPWORD lpw = (LPWORD)DibColors(lpbmi); + + nColors = DibNumColors(lpbmi); + if (lpbmi->biClrImportant) { + nColors = min(nColors, (WORD)lpbmi->biClrImportant); + } + + for (i = 0; i < nColors; ++i) { + if (*lpw++ != i) { + return FALSE; + } + } + + LOGDEBUG(LOG_ALWAYS, ("\nUndocumented Dib.Drv behaviour used\n")); + + return TRUE; +} + +/******************************Public*Routine******************************\ +* DIBSection specific calls +* +* History: +* 04-May-1994 -by- Eric Kutter [erick] +* Wrote it. +\**************************************************************************/ + +ULONG cjBitmapBitsSize(CONST BITMAPINFO *pbmi) +{ +// Check for PM-style DIB + + if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + LPBITMAPCOREINFO pbmci; + pbmci = (LPBITMAPCOREINFO)pbmi; + return(CJSCAN(pbmci->bmciHeader.bcWidth,pbmci->bmciHeader.bcPlanes, + pbmci->bmciHeader.bcBitCount) * + pbmci->bmciHeader.bcHeight); + } + +// not a core header + + if ((pbmi->bmiHeader.biCompression == BI_RGB) || + (pbmi->bmiHeader.biCompression == BI_BITFIELDS)) + { + return(CJSCAN(pbmi->bmiHeader.biWidth,pbmi->bmiHeader.biPlanes, + pbmi->bmiHeader.biBitCount) * + ABS(pbmi->bmiHeader.biHeight)); + } + else + { + return(pbmi->bmiHeader.biSizeImage); + } +} + +ULONG FASTCALL WG32CreateDIBSection(PVDMFRAME pFrame) +{ + ULONG ul = 0; + STACKBMI32 bmi32; + LPBITMAPINFO lpbmi32; + HBITMAP hbm32; + PVOID pv16, pvBits, pvIntelBits; + PVPVOID vpbmi16; + PVOID pvBits32; + DWORD dwArg16; + + register PCREATEDIBSECTION16 parg16; + + GETARGPTR(pFrame, sizeof(CREATEDIBSECTION16), parg16); + + // this is performance hack so we don't generate extra code + dwArg16 = FETCHDWORD(parg16->f4); // do it once here + pv16 = (PVOID)GetPModeVDMPointer(dwArg16, sizeof(DWORD)); // aligned here! + + WOW32ASSERTMSG(((parg16->f5 == 0) && (parg16->f6 == 0)), + ("WOW:WG32CreateDIBSection, hSection/dwOffset non-null\n")); + + vpbmi16 = (PVPVOID)FETCHDWORD(parg16->f2); + lpbmi32 = CopyBMI16ToBMI32(vpbmi16, + (LPBITMAPINFO)&bmi32, + FETCHWORD(parg16->f3)); + + hbm32 = CreateDIBSection(HDC32(parg16->f1), + lpbmi32, + WORD32(parg16->f3), + &pvBits, + NULL, + 0); + + if (hbm32 != 0) + { + PARM16 Parm16; + PDIBSECTIONINFO pdi; + ULONG SelectorLimit; + + SelectorLimit = (ULONG)cjBitmapBitsSize(lpbmi32); +#ifndef i386 + if (!NT_SUCCESS(VdmAddVirtualMemory((ULONG)pvBits, + SelectorLimit, + (PULONG)&pvIntelBits))) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection VdmAddVirtualMemory failed\n")); + goto cds_err; + } + +#else + pvIntelBits = pvBits; +#endif + + // Create a selector array for the bits backed by pvIntelBits + + Parm16.WndProc.wParam = (WORD)-1; // -1 => allocate selectors + Parm16.WndProc.lParam = (LONG) pvIntelBits; // backing pointer + Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT + Parm16.WndProc.hwnd = (WORD)((SelectorLimit+65535)/65536);// selector count + + CallBack16(RET_SETDIBSEL, + &Parm16, + 0, + (PVPVOID)&pvBits32); + + // 16:16 pointer is still valid as call above makes no difference + if (pv16 != NULL) { + *(UNALIGNED PVOID*)pv16 = pvBits32; + } + + if (pvBits32 == NULL) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection, Callback set_sel_for_dib failed\n")); + goto cds_err; + } + +#ifndef i386 + // okay, that was successful - map the descriptors properly + + if (!VdmAddDescriptorMapping(HIWORD(pvBits32), + (USHORT) ((SelectorLimit+65535)/65536), + (ULONG) pvIntelBits, + (ULONG) pvBits)) { + LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection VdmAddDescriptorMapping failed\n")); + goto cds_err; + } +#endif + + LOGDEBUG(LOG_ALWAYS, ("\nWOW:CreateDIBSection: [16:16 %x] [Intel %x] [Flat %x]\n", + pvBits32, pvIntelBits, pvBits)); + + ul = GETHBITMAP16(hbm32); + + // Add it to the list used for cleanup at DeleteObject time. + + if ((pdi = malloc_w (sizeof (DIBSECTIONINFO))) != NULL) { + pdi->di_hbm = (HBITMAP)(HAND16)hbm32; + pdi->di_pv16 = pvBits32; +#ifndef i386 + pdi->di_newIntelDib = pvIntelBits; +#endif + pdi->di_next = pDibSectionInfoHead; + pDibSectionInfoHead = pdi; + + // need to turn batching off since a DIBSECTION means the app can + // also draw on the bitmap and we need synchronization. + + GdiSetBatchLimit(1); + + goto cds_ok; + } + else { + // Failure, free the selector array + + Parm16.WndProc.wParam = (WORD)-1; // -1 => allocate/free + Parm16.WndProc.lParam = (LONG) pvBits32; // pointer + Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT + Parm16.WndProc.hwnd = 0; // 0 => free + + CallBack16(RET_SETDIBSEL, + &Parm16, + 0, + (PVPVOID)&ul); +#ifndef i386 + VdmRemoveVirtualMemory((ULONG)pvIntelBits); +#endif + + } + } + else { + LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection, CreateDibSection Failed\n")); + } + +cds_err: + + if (hbm32 != 0) { + DeleteObject(hbm32); + } + LOGDEBUG(LOG_ALWAYS,("\nWOW::WG32CreateDibSection returning failure\n")); + ul = 0; + +cds_ok: + WOW32APIWARN(ul, "CreateDIBSection"); + + FREEMISCPTR(pv16); + FREEARGPTR(parg16); + + return(ul); +} + +ULONG FASTCALL WG32GetDIBColorTable(PVDMFRAME pFrame) +{ + ULONG ul = 0; + RGBQUAD * prgb; + + register PGETDIBCOLORTABLE16 parg16; + + GETARGPTR(pFrame, sizeof(GETDIBCOLORTABLE16), parg16); + GETMISCPTR(parg16->f4,prgb); + + ul = (ULONG)GetDIBColorTable(HDC32(parg16->f1), + parg16->f2, + parg16->f3, + prgb); + + WOW32APIWARN(ul, "GetDIBColorTable"); + + if (ul) + FLUSHVDMPTR(parg16->f4,sizeof(RGBQUAD) * ul,prgb); + + FREEMISCPTR(prgb); + FREEARGPTR(parg16); + + return(ul); +} + +ULONG FASTCALL WG32SetDIBColorTable(PVDMFRAME pFrame) +{ + ULONG ul = 0; + RGBQUAD * prgb; + + register PSETDIBCOLORTABLE16 parg16; + + GETARGPTR(pFrame, sizeof(SETDIBCOLORTABLE16), parg16); + GETMISCPTR(parg16->f4,prgb); + + ul = (ULONG)SetDIBColorTable(HDC32(parg16->f1), + parg16->f2, + parg16->f3, + prgb); + + WOW32APIWARN(ul, "SetDIBColorTable"); + + FREEMISCPTR(prgb); + FREEARGPTR(parg16); + + return(ul); +} + + +// DIBSection routines + +BOOL W32CheckAndFreeDibSectionInfo (HBITMAP hbm) +{ + PDIBSECTIONINFO pdi = pDibSectionInfoHead,pdiLast=NULL; + + while (pdi) { + if (pdi->di_hbm == hbm){ + + PARM16 Parm16; + ULONG ulRet; + + // need to free the selector array for the memory + + Parm16.WndProc.wParam = (WORD)-1; // selector, -1 == allocate/free + Parm16.WndProc.lParam = (LONG) pdi->di_pv16; // pointer + Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT + Parm16.WndProc.hwnd = 0; // selector count, 0 == free + + CallBack16(RET_SETDIBSEL, + &Parm16, + 0, + (PVPVOID)&ulRet); +#ifndef i386 + VdmRemoveVirtualMemory((ULONG)pdi->di_newIntelDib); +#endif + + if (pdiLast == NULL) + pDibSectionInfoHead = pdi->di_next; + else + pdiLast->di_next = pdi->di_next; + + // now delete the object + + DeleteObject (pdi->di_hbm); + + free_w(pdi); + + return TRUE; + } + pdiLast = pdi; + pdi = pdi->di_next; + } + return FALSE; +} + |