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.

3710 lines
106 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WGDI.C
  8. * WOW32 16-bit GDI API support
  9. *
  10. * History:
  11. * 07-Mar-1991 Jeff Parsons (jeffpar)
  12. * Created.
  13. *
  14. * 09-Apr-1991 NigelT
  15. * Various defines are used here to remove calls to Win32
  16. * features which don't work yet.
  17. *
  18. * 06-June-1992 Chandan Chauhan (ChandanC)
  19. * Fixed BITMAP and DeviceIndependentBitmap (DIB) issues
  20. *
  21. * 22-May-1995 Craig Jones (a-craigj)
  22. * METAFILE NOTE: several 32-bit API's will return TRUE when GDI is in
  23. * "metafile" mode -- however, the POINT struct does not get
  24. * updated by GDI32 even if the API returns successfully so
  25. * we just return TRUE or FALSE as the point coors like W3.1.
  26. *
  27. --*/
  28. #include "precomp.h"
  29. #pragma hdrstop
  30. #include "wowgdip.h"
  31. #include "wdib.h"
  32. #include "stddef.h" // these three are needed to include the
  33. #include "wingdip.h"
  34. // definition of EXTTEXTMETRICS in wingdip.h
  35. // [bodind]
  36. MODNAME(wgdi.c);
  37. #define SETGDIXFORM 4113
  38. #define RESETPAGE 4114
  39. // This must be removed from POSTBETA for sure. ChandanC 3/22/94.
  40. #define IGNORESTARTPGAE 0x7FFFFFFF
  41. #define ADD_MSTT 0x7FFFFFFD
  42. #ifdef FE_SB
  43. // WOWCF_FE_FLW2_PRINTING_PS, Japanese Lotus Freelance printing with PostScript.
  44. // Between Escape( BEGIN_PATH ) and Escape( END_PATH ), select brush object
  45. // with WHITE_BRUSH
  46. BOOL fCmptFLW = FALSE;
  47. #endif // FE_SB
  48. LPDEVMODE GetDefaultDevMode32(LPSTR pszDriver); // Implemented in wspool.c
  49. // Hack for apps which try to be their own printer driver & send form feeds to
  50. // the printer in Escape(PassThrough) calls. This mechanism prevents an
  51. // additional page being spit out of the printer when the app calls EndDoc()
  52. // because GDI32 EndDoc() does an implicit form feed.
  53. typedef struct _FormFeedHack {
  54. struct _FormFeedHack UNALIGNED *next;
  55. HAND16 hTask16;
  56. HDC hdc;
  57. LPBYTE lpBytes;
  58. int cbBytes;
  59. } FORMFEEDHACK;
  60. typedef FORMFEEDHACK UNALIGNED *PFORMFEEDHACK;
  61. PFORMFEEDHACK gpFormFeedHackList = NULL; // start of global formfeed Hack list
  62. LONG HandleFormFeedHack(HDC hdc, LPBYTE lpdata, int cb);
  63. LPBYTE SendFrontEndOfDataStream(HDC hdc, LPBYTE lpData, int *cb, LONG *ul);
  64. void FreeFormFeedHackNode(PFORMFEEDHACK pNode);
  65. void FreeTaskFormFeedHacks(HAND16 hTask16);
  66. void SendFormFeedHack(HDC hdc);
  67. PFORMFEEDHACK FindFormFeedHackNode(HDC hdc);
  68. PFORMFEEDHACK CreateFormFeedHackNode(HDC hdc, int cb, LPBYTE lpData);
  69. void RemoveFormFeedHack(HDC hdc);
  70. ULONG FASTCALL WG32CreateBitmap(PVDMFRAME pFrame)
  71. {
  72. ULONG ul;
  73. register PCREATEBITMAP16 parg16;
  74. LPBYTE lpBitsOriginal;
  75. GETARGPTR(pFrame, sizeof(CREATEBITMAP16), parg16);
  76. GETOPTPTR(parg16->f5, 0, lpBitsOriginal);
  77. ul = GETHBITMAP16(CreateBitmap(INT32(parg16->f1),
  78. INT32(parg16->f2),
  79. LOBYTE(parg16->f3),
  80. LOBYTE(parg16->f4),
  81. lpBitsOriginal));
  82. WOW32APIWARN(ul, "CreateBitmap");
  83. FREEOPTPTR(lpBitsOriginal);
  84. FREEARGPTR(parg16);
  85. RETURN(ul);
  86. }
  87. ULONG FASTCALL WG32CreateBitmapIndirect(PVDMFRAME pFrame)
  88. {
  89. ULONG ul;
  90. register PCREATEBITMAPINDIRECT16 parg16;
  91. PBITMAP16 pbm16;
  92. BITMAP bm;
  93. LPBYTE lp = NULL;
  94. GETARGPTR(pFrame, sizeof(CREATEBITMAPINDIRECT16), parg16);
  95. GETVDMPTR(parg16->f1, sizeof(BITMAP16), pbm16);
  96. GETOPTPTR(pbm16->bmBits, 0, lp);
  97. bm.bmType = (LONG) FETCHSHORT(pbm16->bmType);
  98. bm.bmWidth = (LONG) FETCHSHORT(pbm16->bmWidth);
  99. bm.bmHeight = (LONG) FETCHSHORT(pbm16->bmHeight);
  100. bm.bmWidthBytes = (LONG) FETCHSHORT(pbm16->bmWidthBytes);
  101. bm.bmPlanes = (WORD) pbm16->bmPlanes;
  102. bm.bmBitsPixel = (WORD) pbm16->bmBitsPixel;
  103. bm.bmBits = lp;
  104. ul = GETHBITMAP16(CreateBitmapIndirect(&bm));
  105. WOW32APIWARN(ul, "CreateBitmapIndirect");
  106. FREEOPTPTR(lp);
  107. FREEARGPTR(parg16);
  108. RETURN(ul);
  109. }
  110. ULONG FASTCALL WG32CreateBrushIndirect(PVDMFRAME pFrame)
  111. {
  112. ULONG ul;
  113. LOGBRUSH t1;
  114. HAND16 hMem16;
  115. HANDLE hMem32 = NULL;
  116. LPBYTE lpMem16, lpMem32;
  117. INT cb;
  118. VPVOID vp;
  119. register PCREATEBRUSHINDIRECT16 parg16;
  120. GETARGPTR(pFrame, sizeof(CREATEBRUSHINDIRECT16), parg16);
  121. GETLOGBRUSH16(parg16->f1, &t1);
  122. // some apps don't properly set the style. Make sure it is a valid w3.1 style
  123. if (t1.lbStyle > BS_DIBPATTERN)
  124. t1.lbStyle = BS_SOLID;
  125. if (t1.lbStyle == BS_PATTERN) {
  126. t1.lbStyle = BS_PATTERN8X8;
  127. }
  128. else if (t1.lbStyle == BS_DIBPATTERN) {
  129. hMem16 = (WORD) t1.lbHatch;
  130. if (hMem16) {
  131. vp = RealLockResource16(hMem16, &cb);
  132. if (vp) {
  133. GETMISCPTR(vp, lpMem16);
  134. hMem32 = WOWGLOBALALLOC(GMEM_MOVEABLE, cb);
  135. WOW32ASSERT(hMem32);
  136. if (hMem32) {
  137. lpMem32 = GlobalLock(hMem32);
  138. RtlCopyMemory(lpMem32, lpMem16, cb);
  139. GlobalUnlock(hMem32);
  140. }
  141. GlobalUnlock16(hMem16);
  142. FREEMISCPTR(lpMem16);
  143. }
  144. }
  145. t1.lbHatch = (LONG)hMem32;
  146. }
  147. else if (t1.lbStyle == BS_SOLID)
  148. {
  149. t1.lbColor = COLOR32(t1.lbColor);
  150. }
  151. ul = GETHBRUSH16(CreateBrushIndirect(&t1));
  152. if (hMem32)
  153. {
  154. WOWGLOBALFREE(hMem32);
  155. }
  156. WOW32APIWARN(ul, "CreateBrushIndirect");
  157. FREEARGPTR(parg16);
  158. RETURN(ul);
  159. }
  160. ULONG FASTCALL WG32CreateCompatibleDC(PVDMFRAME pFrame)
  161. {
  162. ULONG ul;
  163. HDC hdc;
  164. register PCREATECOMPATIBLEDC16 parg16;
  165. GETARGPTR(pFrame, sizeof(CREATECOMPATIBLEDC16), parg16);
  166. if ( parg16->f1 ) {
  167. hdc = HDC32(parg16->f1);
  168. if ( hdc == NULL ) {
  169. FREEARGPTR(parg16);
  170. return(0);
  171. }
  172. } else {
  173. hdc = NULL;
  174. }
  175. ul = GETHDC16(CreateCompatibleDC(hdc));
  176. //
  177. // Some apps such as MSWORKS and MS PUBLISHER use some wizard code that accepts
  178. // a hDC or a hWnd as a parameter and attempt to figure out what type of handle
  179. // it is by using the IsWindow() call. Since both handles come from different
  180. // handle spaces they may end up the same value and this wizard code will end
  181. // up writing to the DC for a random window. By ORing in a 1 we ensure that the
  182. // handle types will never share the same value since all hWnds are even. Note
  183. // that this hack is also made in WU32GetDC().
  184. //
  185. // Note that there are some apps that use the lower 2 bits of the hDC for their
  186. // own purposes.
  187. if (ul && CURRENTPTD()->dwWOWCompatFlags & WOWCF_UNIQUEHDCHWND) {
  188. ul = ul | 1;
  189. }
  190. WOW32APIWARN(ul, "CreateCompatibleDC");
  191. FREEARGPTR(parg16);
  192. RETURN(ul);
  193. }
  194. ULONG FASTCALL WG32CreateDC(PVDMFRAME pFrame)
  195. {
  196. ULONG ul = 0;
  197. PSZ psz1 = NULL;
  198. PSZ psz2 = NULL;
  199. PSZ psz3 = NULL;
  200. PSZ pszDib;
  201. LPDEVMODE t4 = NULL;
  202. register PCREATEDC16 parg16;
  203. GETARGPTR(pFrame, sizeof(CREATEDC16), parg16);
  204. if(parg16->f1) {
  205. if(!(psz1 = malloc_w_strcpy_vp16to32(parg16->f1, FALSE, 0)))
  206. goto ExitPath;
  207. }
  208. if(parg16->f2) {
  209. if(!(psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0)))
  210. goto ExitPath;
  211. }
  212. if(parg16->f3) {
  213. if(!(psz3 = malloc_w_strcpy_vp16to32(parg16->f3, FALSE, 0)))
  214. goto ExitPath;
  215. }
  216. // Note: parg16->f4 will usually be a lpDevMode, but it is documented
  217. // that it can also be a lpBitMapInfo if the driver name is "dib.drv"
  218. // test for "dib.drv". Director 4.0 uses "dirdib.drv"
  219. if (psz1 && ((pszDib = WOW32_strstr (psz1, "DIB")) ||
  220. (pszDib = WOW32_strstr (psz1, "dib")))) {
  221. if (WOW32_stricmp (pszDib, "DIB") == 0 ||
  222. WOW32_stricmp (pszDib, "DIB.DRV") == 0) {
  223. ul = GETHDC16(W32HandleDibDrv ((PVPVOID)parg16->f4));
  224. // Note: flat 16:16 ptrs should be considered invalid after this call
  225. }
  226. }
  227. // handle normal non-dib.drv case
  228. else {
  229. if (FETCHDWORD(parg16->f4) == 0L) {
  230. t4 = GetDefaultDevMode32(psz2);
  231. }
  232. else {
  233. t4 = ThunkDevMode16to32(parg16->f4);
  234. }
  235. // this can callback into a 16-bit fax driver!
  236. ul = GETHDC16(CreateDC(psz1, psz2, psz3, t4));
  237. // Note: flat 16:16 ptrs should be considered invalid after this call
  238. FREEARGPTR(parg16);
  239. }
  240. ExitPath:
  241. if(psz1)
  242. free_w(psz1);
  243. if(psz2)
  244. free_w(psz2);
  245. if(psz3)
  246. free_w(psz3);
  247. WOW32APIWARN(ul, "CreateDC");
  248. FREEDEVMODE32(t4);
  249. FREEARGPTR(parg16);
  250. RETURN(ul);
  251. }
  252. ULONG FASTCALL WG32CreateDIBPatternBrush(PVDMFRAME pFrame)
  253. {
  254. ULONG ul = 0;
  255. LPBYTE lpb16;
  256. LOGBRUSH logbr;
  257. register PCREATEDIBPATTERNBRUSH16 parg16;
  258. GETARGPTR(pFrame, sizeof(CREATEDIBPATTERNBRUSH16), parg16);
  259. GETMISCPTR(parg16->f1, lpb16);
  260. logbr.lbStyle = BS_DIBPATTERN8X8;
  261. logbr.lbColor = WORD32(parg16->f2);
  262. logbr.lbHatch = (LONG) lpb16;
  263. ul = GETHBRUSH16(CreateBrushIndirect(&logbr));
  264. WOW32APIWARN(ul, "CreateDIBPatternBrush");
  265. FREEARGPTR(parg16);
  266. RETURN(ul);
  267. }
  268. ULONG FASTCALL WG32CreateDIBitmap(PVDMFRAME pFrame)
  269. {
  270. ULONG ul=0;
  271. LPBYTE lpib4;
  272. BITMAPINFOHEADER bmxh2;
  273. STACKBMI32 bmi32;
  274. LPBITMAPINFOHEADER lpbmih32;
  275. LPBITMAPINFO lpbmi32;
  276. register PCREATEDIBITMAP16 parg16;
  277. GETARGPTR(pFrame, sizeof(CREATEDIBITMAP16), parg16);
  278. GETMISCPTR(parg16->f4, lpib4);
  279. lpbmih32 = CopyBMIH16ToBMIH32((PVPVOID) FETCHDWORD(parg16->f2), &bmxh2);
  280. if (lpbmih32) {
  281. lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f5),
  282. (LPBITMAPINFO)&bmi32,
  283. FETCHWORD(parg16->f6));
  284. // see if we need to adjust the image sze for RLE bitmaps
  285. if(lpbmi32 && lpib4 && (DWORD32(parg16->f3) == CBM_INIT)) {
  286. if((lpbmi32->bmiHeader.biCompression == BI_RLE4) ||
  287. (lpbmi32->bmiHeader.biCompression == BI_RLE8)) {
  288. if(lpbmi32->bmiHeader.biSizeImage == 0) {
  289. lpbmi32->bmiHeader.biSizeImage =
  290. Get_RLE_Compression_Size(lpbmi32->bmiHeader.biCompression,
  291. lpib4,
  292. parg16->f4);
  293. }
  294. }
  295. }
  296. ul = GETHBITMAP16(CreateDIBitmap(HDC32(parg16->f1),
  297. lpbmih32,
  298. DWORD32(parg16->f3),
  299. lpib4,
  300. lpbmi32,
  301. WORD32(parg16->f6) ));
  302. }
  303. WOW32APIWARN(ul, "CreateDIBitmap");
  304. FREEMISCPTR(lpib4);
  305. FREEARGPTR(parg16);
  306. return(ul);
  307. }
  308. ULONG FASTCALL WG32CreateEllipticRgnIndirect(PVDMFRAME pFrame)
  309. {
  310. ULONG ul;
  311. RECT t1;
  312. register PCREATEELLIPTICRGNINDIRECT16 parg16;
  313. GETARGPTR(pFrame, sizeof(CREATEELLIPTICRGNINDIRECT16), parg16);
  314. WOW32VERIFY(GETRECT16(parg16->f1, &t1));
  315. ul = GETHRGN16(CreateEllipticRgnIndirect(&t1));
  316. WOW32APIWARN(ul, "CreateEllipticRgnIndirect");
  317. FREEARGPTR(parg16);
  318. RETURN(ul);
  319. }
  320. ULONG FASTCALL WG32CreateIC(PVDMFRAME pFrame)
  321. {
  322. ULONG ul = 0;
  323. PSZ psz1 = NULL;
  324. PSZ psz2 = NULL;
  325. PSZ psz2t = NULL;
  326. PSZ psz3 = NULL;
  327. LPDEVMODE t4 = NULL;
  328. register PCREATEIC16 parg16;
  329. INT len;
  330. PCHAR pch;
  331. CHAR achDevice[256];
  332. DWORD dw;
  333. GETARGPTR(pFrame, sizeof(CREATEIC16), parg16);
  334. if(parg16->f1) {
  335. if(!(psz1 = malloc_w_strcpy_vp16to32(parg16->f1, FALSE, 0)))
  336. goto ExitPath;
  337. }
  338. if(parg16->f2) {
  339. if(!(psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0)))
  340. goto ExitPath;
  341. }
  342. if(parg16->f3) {
  343. if(!(psz3 = malloc_w_strcpy_vp16to32(parg16->f3, FALSE, 0)))
  344. goto ExitPath;
  345. }
  346. if (FETCHDWORD(parg16->f4) != 0L) {
  347. t4 = ThunkDevMode16to32(parg16->f4);
  348. }
  349. else {
  350. t4 = GetDefaultDevMode32(psz2);
  351. }
  352. // invalidate all flat ptrs to 16:16 memory now!
  353. FREEARGPTR(parg16);
  354. psz2t = psz2;
  355. //
  356. // HACK Alert!
  357. //
  358. // NBI's Legacy comes with a pscript.drv that resides in [AppPath]\cbt
  359. // they call CreateIC() specifying the the path to this file as the driver.
  360. // the app GP faults if the CreateIC returns 0. once they've loaded this
  361. // printer driver, on successive calls to CreateIC() they simply use
  362. // "PSCRIPT" as the driver name and use "PostScript Printer", "FILE:" as
  363. // the other parms.
  364. // let's recognize these driver names and try to replace it with the
  365. // system default printer. if there's no printer installed, a GP fault
  366. // is unavoidable. the app appears to use this pscript.drv only during
  367. // the tutorial, so we're not providing life-support for an app that's
  368. // clinically dead.
  369. //
  370. //
  371. // check for a driver name that ends with "PSCRIPT" and if so,
  372. // check that the device name is "PostScript Printer".
  373. // on NT the driver name should always be "winspool", although it's
  374. // completely ignored.
  375. //
  376. // PageMaker 5.0a calls this with ("pscript","Postscript printer","LPT1:",0)
  377. // when opening calibrat.pt5
  378. len = psz1 ? strlen(psz1) : 0;
  379. if (len >= 7) {
  380. #if 0
  381. static CHAR achPS[] = "PostScript Printer";
  382. #endif
  383. if (!WOW32_stricmp(psz1+len-7, "pscript")
  384. #if 0
  385. // let's see who else thinks they're using a pscript driver
  386. //
  387. && (RtlCompareMemory(achPS, psz2, sizeof(achPS)) == sizeof(achPS))
  388. #endif
  389. ) {
  390. LOGDEBUG(LOG_ALWAYS,("WOW32: CreateIC - detected request for Pscript driver\n"));
  391. dw = GetProfileString("windows", "device", "", achDevice,
  392. sizeof(achDevice));
  393. if (dw) {
  394. psz2t = achDevice;
  395. pch = WOW32_strchr(achDevice, ',');
  396. if (pch) {
  397. *pch = '\0';
  398. }
  399. }
  400. }
  401. }
  402. // this can callback into a 16-bit fax driver!
  403. ul = GETHDC16(CreateIC(psz1, psz2t, psz3, t4));
  404. // Note: flat 16:16 ptrs should be considered invalid after this call
  405. FREEARGPTR(parg16);
  406. ExitPath:
  407. if(psz1)
  408. free_w(psz1);
  409. if(psz2)
  410. free_w(psz2);
  411. if(psz3)
  412. free_w(psz3);
  413. WOW32APIWARN(ul, "CreateIC");
  414. FREEDEVMODE32(t4);
  415. RETURN(ul);
  416. }
  417. ULONG FASTCALL WG32CreatePatternBrush(PVDMFRAME pFrame)
  418. {
  419. ULONG ul;
  420. LOGBRUSH logbr;
  421. register PCREATEPATTERNBRUSH16 parg16;
  422. GETARGPTR(pFrame, sizeof(CREATEPATTERNBRUSH16), parg16);
  423. logbr.lbStyle = BS_PATTERN8X8;
  424. logbr.lbColor = 0;
  425. logbr.lbHatch = (LONG)HBITMAP32(parg16->f1);
  426. ul = GETHBRUSH16(CreateBrushIndirect(&logbr));
  427. WOW32APIWARN(ul, "CreatePatternBrush");
  428. FREEARGPTR(parg16);
  429. RETURN(ul);
  430. }
  431. ULONG FASTCALL WG32CreatePenIndirect(PVDMFRAME pFrame)
  432. {
  433. ULONG ul;
  434. LOGPEN t1;
  435. register PCREATEPENINDIRECT16 parg16;
  436. GETARGPTR(pFrame, sizeof(CREATEPENINDIRECT16), parg16);
  437. GETLOGPEN16(parg16->f1, &t1);
  438. ul = GETHPEN16(CreatePenIndirect(&t1));
  439. WOW32APIWARN(ul, "CreatePenIndirect");
  440. FREEARGPTR(parg16);
  441. RETURN(ul);
  442. }
  443. ULONG FASTCALL WG32CreatePolyPolygonRgn(PVDMFRAME pFrame)
  444. {
  445. ULONG ul = 0;
  446. LPPOINT pPoints;
  447. PINT pPolyCnt;
  448. UINT cpts = 0;
  449. INT ii;
  450. register PCREATEPOLYPOLYGONRGN16 parg16;
  451. INT cInt16;
  452. INT BufferT[256]; // comfortably large array
  453. GETARGPTR(pFrame, sizeof(CREATEPOLYPOLYGONRGN16), parg16);
  454. cInt16 = INT32(parg16->f3);
  455. pPolyCnt = STACKORHEAPALLOC(cInt16 * sizeof(INT), sizeof(BufferT), BufferT);
  456. if (!pPolyCnt) {
  457. FREEARGPTR(parg16);
  458. RETURN(0);
  459. }
  460. getintarray16(parg16->f2, cInt16, pPolyCnt);
  461. for (ii=0; ii < cInt16; ii++)
  462. cpts += pPolyCnt[ii];
  463. pPoints = STACKORHEAPALLOC(cpts * sizeof(POINT),
  464. sizeof(BufferT) - cInt16 * sizeof(INT),
  465. BufferT + cInt16);
  466. if(pPoints) {
  467. getpoint16(parg16->f1, cpts, pPoints);
  468. ul = GETHRGN16(CreatePolyPolygonRgn(pPoints,
  469. pPolyCnt,
  470. INT32(parg16->f3),
  471. INT32(parg16->f4)));
  472. }
  473. WOW32APIWARN(ul, "CreatePolyPolygonRgn");
  474. STACKORHEAPFREE(pPoints, BufferT + cInt16);
  475. STACKORHEAPFREE(pPolyCnt, BufferT);
  476. FREEARGPTR(parg16);
  477. RETURN(ul);
  478. }
  479. ULONG FASTCALL WG32CreatePolygonRgn(PVDMFRAME pFrame)
  480. {
  481. ULONG ul = 0;
  482. LPPOINT t1;
  483. register PCREATEPOLYGONRGN16 parg16;
  484. POINT BufferT[128];
  485. GETARGPTR(pFrame, sizeof(CREATEPOLYGONRGN16), parg16);
  486. t1 = STACKORHEAPALLOC(parg16->f2 * sizeof(POINT), sizeof(BufferT), BufferT);
  487. if(t1) {
  488. getpoint16(parg16->f1, parg16->f2, t1);
  489. ul = GETHRGN16(CreatePolygonRgn(t1, INT32(parg16->f2), INT32(parg16->f3)));
  490. }
  491. WOW32APIWARN(ul, "CreatePolygonRgn");
  492. STACKORHEAPFREE(t1, BufferT);
  493. FREEARGPTR(parg16);
  494. RETURN(ul);
  495. }
  496. ULONG FASTCALL WG32CreateRectRgnIndirect(PVDMFRAME pFrame)
  497. {
  498. ULONG ul;
  499. RECT t1;
  500. register PCREATERECTRGNINDIRECT16 parg16;
  501. GETARGPTR(pFrame, sizeof(CREATERECTRGNINDIRECT16), parg16);
  502. WOW32VERIFY(GETRECT16(parg16->f1, &t1));
  503. ul = GETHRGN16(CreateRectRgnIndirect(&t1));
  504. WOW32APIWARN(ul, "CreateRectRgnIndirect");
  505. FREEARGPTR(parg16);
  506. RETURN(ul);
  507. }
  508. ULONG FASTCALL WG32DPtoLP(PVDMFRAME pFrame)
  509. {
  510. ULONG ul=0;
  511. LPPOINT t2;
  512. register PDPTOLP16 parg16;
  513. POINT BufferT[128];
  514. GETARGPTR(pFrame, sizeof(DPTOLP16), parg16);
  515. t2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
  516. if (t2) {
  517. getpoint16(parg16->f2, parg16->f3, t2);
  518. ul = GETBOOL16(DPtoLP(HDC32(parg16->f1), t2, INT32(parg16->f3)));
  519. PUTPOINTARRAY16(parg16->f2, parg16->f3, t2);
  520. STACKORHEAPFREE(t2, BufferT);
  521. }
  522. FREEARGPTR(parg16);
  523. RETURN(ul);
  524. }
  525. ULONG FASTCALL WG32DeleteDC(PVDMFRAME pFrame)
  526. {
  527. HDC hdc32;
  528. ULONG ul;
  529. register PDELETEDC16 parg16;
  530. GETARGPTR(pFrame, sizeof(DELETEDC16), parg16);
  531. hdc32 = HDC32(parg16->f1);
  532. if ((ul = W32CheckAndFreeDibInfo(hdc32)) == FALSE) {
  533. ul = GETBOOL16(DeleteDC(hdc32));
  534. // update our GDI handle mapping table
  535. if(ul) {
  536. DeleteWOWGdiHandle(hdc32, (HAND16)parg16->f1);
  537. }
  538. }
  539. FREEARGPTR(parg16);
  540. RETURN(ul);
  541. }
  542. ULONG FASTCALL WG32DeleteObject(PVDMFRAME pFrame)
  543. {
  544. ULONG ul;
  545. register PDELETEOBJECT16 parg16;
  546. HGDIOBJ hGdiObj;
  547. GETARGPTR(pFrame, sizeof(DELETEOBJECT16), parg16);
  548. hGdiObj = HOBJ32(parg16->f1);
  549. if ((pDibSectionInfoHead == NULL) ||
  550. (ul = W32CheckAndFreeDibSectionInfo(hGdiObj) == FALSE)) {
  551. ul = GETBOOL16(DeleteObject(hGdiObj));
  552. // update our GDI handle mapping table
  553. if(ul) {
  554. DeleteWOWGdiHandle(hGdiObj, (HAND16)parg16->f1);
  555. }
  556. if (!ul) {
  557. //
  558. // Most apps probably don't care what the return value from
  559. // DeleteObject is, but in any case, in this regard, NT has
  560. // different logic from win31/win95. For example, it appears
  561. // that win95 always returns TRUE when a palette object is
  562. // passed to DeleteObject, even if the palette was not deleted
  563. // (because it was already selected).
  564. //
  565. // Here we try to decide if we should change the return value
  566. // from FALSE to TRUE.
  567. //
  568. // ChessMaster 3000 tries to delete a Palette object that
  569. // is still selected. If it fails, then it puts up a popup.
  570. //
  571. switch(GetObjectType(hGdiObj)) {
  572. case OBJ_PAL:
  573. case OBJ_PEN:
  574. case OBJ_BRUSH:
  575. ul = TRUE;
  576. break;
  577. }
  578. }
  579. }
  580. FREEARGPTR(parg16);
  581. RETURN(ul);
  582. }
  583. // WARNING: This function may cause 16-bit memory movement
  584. INT W32EnumObjFunc(LPSTR lpLogObject, PENUMOBJDATA pEnumObjData)
  585. {
  586. PARM16 Parm16;
  587. INT iReturn;
  588. WOW32ASSERT(pEnumObjData);
  589. switch (pEnumObjData->ObjType) {
  590. case OBJ_BRUSH:
  591. PUTLOGBRUSH16(pEnumObjData->vpObjData, sizeof(LOGBRUSH), (LPLOGBRUSH)lpLogObject);
  592. break;
  593. case OBJ_PEN:
  594. PUTLOGPEN16(pEnumObjData->vpObjData, sizeof(LOGPEN), (LPLOGPEN)lpLogObject);
  595. break;
  596. default:
  597. LOGDEBUG(LOG_ALWAYS,("WOW32 ERROR -- Illegal type %d passes to EnumObj\n",pEnumObjData->ObjType));
  598. return 0;
  599. } // end switch
  600. STOREDWORD(Parm16.EnumObjProc.vpLogObject, pEnumObjData->vpObjData);
  601. STOREDWORD(Parm16.EnumObjProc.vpData, pEnumObjData->dwUserParam);
  602. CallBack16(RET_ENUMOBJPROC, &Parm16, pEnumObjData->vpfnEnumObjProc, (PVPVOID)&iReturn);
  603. return (SHORT)iReturn;
  604. }
  605. ULONG FASTCALL WG32EnumObjects(PVDMFRAME pFrame)
  606. {
  607. ULONG ul = 0;
  608. register PENUMOBJECTS16 parg16;
  609. ENUMOBJDATA EnumObjData;
  610. GETARGPTR(pFrame, sizeof(ENUMOBJECTS16), parg16);
  611. EnumObjData.ObjType = INT32(parg16->f2);
  612. switch(EnumObjData.ObjType) {
  613. case OBJ_BRUSH:
  614. EnumObjData.vpObjData = malloc16(sizeof(LOGBRUSH16));
  615. break;
  616. case OBJ_PEN:
  617. EnumObjData.vpObjData = malloc16(sizeof(LOGPEN16));
  618. break;
  619. default:
  620. LOGDEBUG(LOG_ALWAYS,("WOW32 ERROR -- Illegal type %d passes to EnumObj\n",EnumObjData.ObjType));
  621. EnumObjData.vpObjData = (VPVOID)0;
  622. }
  623. // malloc16 may have caused 16-bit memory movement - invalidate flat ptrs
  624. FREEVDMPTR(pFrame);
  625. FREEARGPTR(parg16);
  626. GETFRAMEPTR(((PTD)CURRENTPTD())->vpStack, pFrame);
  627. GETARGPTR(pFrame, sizeof(ENUMOBJECTS16), parg16);
  628. if( EnumObjData.vpObjData ) {
  629. EnumObjData.vpfnEnumObjProc = DWORD32(parg16->f3);
  630. EnumObjData.dwUserParam = DWORD32(parg16->f4);
  631. ul = (ULONG)(GETINT16(EnumObjects(HDC32(parg16->f1),
  632. (int)INT32(parg16->f2),
  633. (GOBJENUMPROC)W32EnumObjFunc,
  634. (LPARAM)&EnumObjData)));
  635. // 16-bit memory may have moved - invalidate flat pointers
  636. FREEARGPTR(parg16);
  637. FREEVDMPTR(pFrame);
  638. free16(EnumObjData.vpObjData);
  639. }
  640. FREEARGPTR(parg16);
  641. RETURN(ul);
  642. }
  643. /**************************************************************************\
  644. *
  645. \**************************************************************************/
  646. typedef struct _ESCKERNPAIR {
  647. union
  648. {
  649. BYTE each[2];
  650. WORD both;
  651. } kpPair;
  652. SHORT KernAmount;
  653. } ESCKERNPAIR;
  654. /******************************Public*Routine******************************\
  655. * iGetKerningPairsEsc32
  656. *
  657. * History:
  658. * Tue 16-Mar-1993 11:08:36 by Kirk Olynyk [kirko]
  659. * Wrote it.
  660. \**************************************************************************/
  661. int
  662. iGetKerningPairsEsc32(
  663. HDC hdc,
  664. ESCKERNPAIR *pekp
  665. )
  666. {
  667. int i,j;
  668. int n;
  669. ESCKERNPAIR *pekpT, *pekpTOut;
  670. KERNINGPAIR *pkpT;
  671. KERNINGPAIR *pkp = (KERNINGPAIR*) NULL;
  672. if
  673. (
  674. (n = GetKerningPairs(hdc,0,NULL)) &&
  675. (pkp = malloc_w((n * sizeof(KERNINGPAIR)))) &&
  676. (n = (int) GetKerningPairs(hdc, n, pkp))
  677. )
  678. {
  679. n = min(n,512);
  680. //
  681. // load the low byte of each word, Win 3.1 doesn't seem to care about
  682. // the high byte
  683. //
  684. pekpT = pekp;
  685. pekpTOut = pekp + n;
  686. pkpT = pkp;
  687. while (pekpT < pekpTOut)
  688. {
  689. pekpT->kpPair.each[0] = (BYTE) pkpT->wFirst;
  690. pekpT->kpPair.each[1] = (BYTE) pkpT->wSecond;
  691. pekpT->KernAmount = (SHORT) pkpT->iKernAmount;
  692. pekpT += 1;
  693. pkpT += 1;
  694. }
  695. //
  696. // bubble sort word formed by byte pair
  697. //
  698. for (i = 0; i < n - 1; i++)
  699. {
  700. for (j = n-1; j > i; --j)
  701. {
  702. if (pekp[j-1].kpPair.both > pekp[j].kpPair.both)
  703. {
  704. ESCKERNPAIR ekp;
  705. ekp = pekp[j];
  706. pekp[j] = pekp[j-1];
  707. pekp[j] = ekp;
  708. }
  709. }
  710. }
  711. }
  712. if (pkp)
  713. {
  714. free_w(pkp);
  715. }
  716. return(n);
  717. }
  718. // Don;t change this unless you change where it is used as a limit
  719. #define ESC_BUF_SIZE 32
  720. ULONG FASTCALL WG32Escape(PVDMFRAME pFrame)
  721. {
  722. ULONG ul=0;
  723. register PESCAPE16 parg16;
  724. PVOID pin = NULL;
  725. int iMapMode;
  726. CHAR buf[ESC_BUF_SIZE];
  727. HANDLE hdc32;
  728. GETARGPTR(pFrame, sizeof(ESCAPE16), parg16);
  729. GETOPTPTR(parg16->f4, 0, pin);
  730. hdc32 = HDC32(parg16->f1);
  731. switch (INT32(parg16->f2)) {
  732. case GETPHYSPAGESIZE:
  733. case GETPRINTINGOFFSET:
  734. case GETSCALINGFACTOR:
  735. { POINT pt;
  736. ul = GETINT16(Escape(hdc32,
  737. INT32(parg16->f2),
  738. INT32(parg16->f3),
  739. pin,
  740. (LPSTR)&pt));
  741. if (!ul)
  742. {
  743. // if these fail, they are almost certainly doing it on a display dc.
  744. // We will fill the return value in with reasonable values for those
  745. // apps (micrographx draw) that ignore our return values.
  746. // we still return failure.
  747. switch (INT32(parg16->f2))
  748. {
  749. case GETPHYSPAGESIZE:
  750. pt.x = GetDeviceCaps(hdc32,HORZRES);
  751. pt.y = GetDeviceCaps(hdc32,VERTRES);
  752. break;
  753. case GETPRINTINGOFFSET:
  754. pt.x = 0;
  755. pt.y = 0;
  756. break;
  757. default:
  758. break;
  759. }
  760. }
  761. PUTPOINT16(parg16->f5, &pt);
  762. }
  763. break;
  764. case GETCOLORTABLE:
  765. {
  766. PDWORD pdw;
  767. DWORD dw;
  768. INT i;
  769. if (pin) {
  770. i = (INT) FETCHSHORT(*(PSHORT)pin);
  771. } else {
  772. ul = (ULONG)-1;
  773. break;
  774. }
  775. ul = GETINT16(Escape(hdc32,
  776. INT32(parg16->f2),
  777. sizeof(INT),
  778. (LPCSTR)&i,
  779. &dw));
  780. GETVDMPTR(parg16->f5, sizeof(DWORD), pdw);
  781. STOREDWORD ((*pdw), dw);
  782. FREEVDMPTR(pdw);
  783. }
  784. break;
  785. case NEXTBAND:
  786. { RECT rt;
  787. ul = GETINT16(Escape(hdc32,
  788. INT32(parg16->f2),
  789. INT32(parg16->f3),
  790. pin,
  791. (LPSTR)&rt));
  792. PUTRECT16(parg16->f5, &rt);
  793. }
  794. break;
  795. case QUERYESCSUPPORT:
  796. {
  797. INT i;
  798. i = (INT) FETCHWORD((*(PWORD)pin));
  799. switch (i) {
  800. // For Escapes return FALSE for MGX Draw and TRUE for all other apps.
  801. // ChandanC, 27/5/93.
  802. //
  803. case OPENCHANNEL: // 4110
  804. case DOWNLOADHEADER: // 4111
  805. case CLOSECHANNEL: // 4112
  806. case SETGDIXFORM: // 4113
  807. case RESETPAGE: // 4114
  808. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  809. ul = 0;
  810. }
  811. else {
  812. ul = 1;
  813. }
  814. break;
  815. case POSTSCRIPT_PASSTHROUGH: // 4115
  816. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  817. ul = 0;
  818. }
  819. else {
  820. LOGDEBUG(3,("Querying support for escape %x\n",i));
  821. ul = GETINT16(Escape(hdc32,
  822. INT32(parg16->f2),
  823. sizeof(int),
  824. (PVOID)&i,
  825. NULL));
  826. }
  827. break;
  828. case ENCAPSULATED_POSTSCRIPT: // 4116
  829. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  830. ul = 0;
  831. }
  832. else {
  833. LOGDEBUG(3,("Querying support for escape %x\n",i));
  834. ul = GETINT16(DrawEscape(hdc32,
  835. INT32(parg16->f2),
  836. sizeof(int),
  837. (PVOID)&i));
  838. }
  839. break;
  840. case GETEXTENDEDTEXTMETRICS:
  841. case GETPAIRKERNTABLE:
  842. case FLUSHOUTPUT:
  843. ul = 1;
  844. break;
  845. case SETCOPYCOUNT:
  846. case GETCOLORTABLE:
  847. case GETPHYSPAGESIZE:
  848. case GETPRINTINGOFFSET:
  849. case GETSCALINGFACTOR:
  850. case NEXTBAND:
  851. case SETABORTPROC:
  852. case BEGIN_PATH:
  853. case END_PATH:
  854. case CLIP_TO_PATH:
  855. LOGDEBUG(3,("Querying support for escape %x\n",i));
  856. ul = GETINT16(Escape(hdc32,
  857. INT32(parg16->f2),
  858. sizeof(int),
  859. (PVOID)&i,
  860. NULL));
  861. break;
  862. case POSTSCRIPT_DATA:
  863. case POSTSCRIPT_IGNORE:
  864. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  865. ul = 0;
  866. }
  867. else {
  868. LOGDEBUG(3,("Querying support for escape %x\n",i));
  869. ul = GETINT16(Escape(hdc32,
  870. INT32(parg16->f2),
  871. sizeof(int),
  872. (PVOID)&i,
  873. NULL));
  874. }
  875. break;
  876. case GETTECHNOLOGY:
  877. case PASSTHROUGH:
  878. case DOWNLOADFACE:
  879. case GETFACENAME:
  880. case GETDEVICEUNITS:
  881. case EPSPRINTING:
  882. LOGDEBUG(3,("Querying support for escape %x\n",i));
  883. ul = GETINT16(ExtEscape(hdc32,
  884. INT32(parg16->f2),
  885. sizeof(int),
  886. (PVOID)&i,
  887. 0,
  888. NULL));
  889. break;
  890. case DRAWPATTERNRECT:
  891. LOGDEBUG(3,("Querying support for escape %x\n",i));
  892. // some apps just don't do DRAWPATTERNRECT correctly (Excel
  893. // 6.0c, Word 6.0c Access 2.0 #122856). Others can't handle
  894. // the new 32bit DRAWPATTERNRECT struct (AmiPro 3.1
  895. // #107210). We just tell them that it isn't supported and
  896. // force them to figure out the effect on their own.
  897. if(CURRENTPTD()->dwWOWCompatFlagsEx &
  898. WOWCFEX_SAYNO2DRAWPATTERNRECT) {
  899. ul = 0;
  900. break;
  901. }
  902. else {
  903. ul = GETINT16(ExtEscape(hdc32,
  904. INT32(parg16->f2),
  905. sizeof(int),
  906. (PVOID)&i,
  907. 0,
  908. NULL));
  909. break;
  910. }
  911. default:
  912. LOGDEBUG(3,("Querying support for escape %x\n",i));
  913. ul = GETINT16(Escape(hdc32,
  914. INT32(parg16->f2),
  915. sizeof(int),
  916. (PVOID)&i,
  917. NULL));
  918. break;
  919. }
  920. }
  921. break;
  922. case SETABORTPROC:
  923. ((PTDB)SEGPTR(pFrame->wTDB, 0))->TDB_vpfnAbortProc =
  924. FETCHDWORD(parg16->f4);
  925. ul = GETINT16(Escape(hdc32,
  926. INT32(parg16->f2),
  927. 0,
  928. (LPCSTR)W32AbortProc,
  929. NULL));
  930. break;
  931. case GETDEVICEUNITS:
  932. {
  933. PVOID pout;
  934. LONG out[4];
  935. ul = GETINT16(Escape(hdc32,
  936. INT32(parg16->f2),
  937. 0,
  938. NULL,
  939. (LPSTR)out));
  940. if (ul == 1) {
  941. GETOPTPTR(parg16->f5, 0, pout);
  942. RtlCopyMemory(pout, out, sizeof(out));
  943. FREEOPTPTR(pout);
  944. }
  945. }
  946. break;
  947. case GETPAIRKERNTABLE:
  948. {
  949. PVOID pout;
  950. GETOPTPTR(parg16->f5, 0, pout);
  951. ul = GETINT16(iGetKerningPairsEsc32(hdc32, (ESCKERNPAIR*)pout));
  952. FREEOPTPTR(pout);
  953. }
  954. break;
  955. case GETEXTENDEDTEXTMETRICS:
  956. {
  957. PVOID pout;
  958. EXTTEXTMETRIC etm;
  959. if ( (ul = GETINT16(GetETM(hdc32, &etm))) != 0 )
  960. {
  961. GETOPTPTR(parg16->f5, 0, pout);
  962. RtlCopyMemory(pout, &etm, sizeof(EXTTEXTMETRIC));
  963. FREEOPTPTR(pout);
  964. }
  965. }
  966. break;
  967. case OPENCHANNEL: // 4110
  968. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  969. ul = 0;
  970. } else {
  971. DOCINFO16 *pout;
  972. DOCINFO DocInfo;
  973. DocInfo.cbSize = sizeof(DocInfo);
  974. DocInfo.lpszDatatype = "RAW";
  975. DocInfo.fwType = 0;
  976. GETOPTPTR(parg16->f5, 0, pout);
  977. if (pout) {
  978. GETOPTPTR(pout->lpszDocName, 0, DocInfo.lpszDocName);
  979. GETOPTPTR(pout->lpszOutput, 0, DocInfo.lpszOutput);
  980. ul = StartDoc(hdc32, &DocInfo);
  981. FREEOPTPTR(DocInfo.lpszDocName);
  982. FREEOPTPTR(DocInfo.lpszOutput);
  983. } else {
  984. //
  985. // Fifth parameter null, use old (startdoc) format
  986. //
  987. GETOPTPTR(parg16->f4, 0, DocInfo.lpszDocName);
  988. DocInfo.lpszOutput = NULL;
  989. ul = StartDoc(hdc32, &DocInfo);
  990. FREEOPTPTR(DocInfo.lpszDocName);
  991. }
  992. FREEOPTPTR(pout);
  993. }
  994. break;
  995. case DOWNLOADHEADER: // 4111
  996. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  997. ul = 0;
  998. }
  999. else {
  1000. PBYTE pout;
  1001. char ach[64];
  1002. GETOPTPTR(parg16->f5, 0, pout);
  1003. if (pout) {
  1004. ul = GETINT16(ExtEscape(hdc32,
  1005. INT32(parg16->f2),
  1006. 0,
  1007. NULL,
  1008. sizeof(ach),
  1009. ach));
  1010. strcpy (pout, ach);
  1011. }
  1012. else {
  1013. ul = GETINT16(ExtEscape(hdc32,
  1014. INT32(parg16->f2),
  1015. 0,
  1016. NULL,
  1017. 0,
  1018. NULL));
  1019. }
  1020. FREEOPTPTR(pout);
  1021. }
  1022. break;
  1023. case CLOSECHANNEL: // 4112
  1024. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  1025. ul = 0;
  1026. }
  1027. else {
  1028. // send any buffered data streams to the printer before EndDoc
  1029. if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_FORMFEEDHACK) {
  1030. SendFormFeedHack(hdc32);
  1031. }
  1032. ul = EndDoc(hdc32);
  1033. }
  1034. break;
  1035. // This Escape is defined for PageMaker. It is SETGDIXFORM.
  1036. // ChandanC, 24/5/93.
  1037. //
  1038. case SETGDIXFORM: // 4113
  1039. case RESETPAGE: // 4114
  1040. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  1041. ul = 0;
  1042. }
  1043. else {
  1044. ul = 1;
  1045. }
  1046. break;
  1047. case POSTSCRIPT_PASSTHROUGH: // 4115
  1048. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  1049. ul = 0;
  1050. }
  1051. else {
  1052. ul = GETINT16(Escape(hdc32,
  1053. INT32(parg16->f2),
  1054. (FETCHWORD(*(PWORD)pin) + 2),
  1055. (LPCSTR)pin,
  1056. NULL));
  1057. }
  1058. break;
  1059. case ENCAPSULATED_POSTSCRIPT: // 4116
  1060. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  1061. ul = 0;
  1062. }
  1063. else {
  1064. DWORD cb;
  1065. PVOID lpInData32 = NULL;
  1066. lpInData32 = pin;
  1067. cb = FETCHDWORD (*(PDWORD) pin);
  1068. if ((DWORD) pin & 3) {
  1069. if (lpInData32 = (PVOID) malloc_w (cb)) {
  1070. RtlCopyMemory(lpInData32, pin, cb);
  1071. }
  1072. else {
  1073. ul = 0;
  1074. break;
  1075. }
  1076. }
  1077. ul = GETINT16(DrawEscape(hdc32,
  1078. INT32(parg16->f2),
  1079. cb,
  1080. lpInData32));
  1081. if (((DWORD) pin & 3) && (lpInData32)) {
  1082. free_w (lpInData32);
  1083. }
  1084. }
  1085. break;
  1086. case POSTSCRIPT_DATA:
  1087. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  1088. ul = 0;
  1089. LOGDEBUG (LOG_ALWAYS, ("MicroGraphax app using POSTSCRIPT_DATA, contact PingW/ChandanC\n"));
  1090. WOW32ASSERT(FALSE);
  1091. }
  1092. else {
  1093. //
  1094. // XPress needs IGNORESTARTPAGE escape.
  1095. // PingW, ChandanC 3/22/94
  1096. //
  1097. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_NEEDIGNORESTARTPAGE) {
  1098. int l;
  1099. char szBuf[40];
  1100. if ((l = ExtEscape(hdc32,
  1101. GETTECHNOLOGY,
  1102. 0,
  1103. NULL,
  1104. sizeof(szBuf),
  1105. szBuf)) > 0) {
  1106. if (!WOW32_stricmp(szBuf, szPostscript)) {
  1107. l = ExtEscape(hdc32,
  1108. IGNORESTARTPGAE,
  1109. 0,
  1110. NULL,
  1111. 0,
  1112. NULL);
  1113. }
  1114. }
  1115. }
  1116. ul = GETINT16(Escape(hdc32,
  1117. INT32(parg16->f2),
  1118. (FETCHWORD(*(PWORD)pin) + 2),
  1119. (LPCSTR)pin,
  1120. NULL));
  1121. }
  1122. break;
  1123. case POSTSCRIPT_IGNORE:
  1124. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
  1125. ul = 0;
  1126. LOGDEBUG (LOG_ALWAYS, ("MicroGraphax app using POSTSCRIPT_IGNORE, contact PingW/ChandanC\n"));
  1127. WOW32ASSERT(FALSE);
  1128. }
  1129. else {
  1130. ul = GETINT16(Escape(hdc32,
  1131. INT32(parg16->f2),
  1132. INT32(parg16->f3),
  1133. (LPCSTR)pin,
  1134. NULL));
  1135. }
  1136. break;
  1137. case BEGIN_PATH:
  1138. // Some apps set the empty clip region before doing the path escapes,
  1139. // We need to undo that so the drawing APIs between begin and endpath
  1140. // go through to drivers.
  1141. SelectClipRgn(hdc32,NULL);
  1142. // fall through to escape call
  1143. case END_PATH:
  1144. #ifdef FE_SB
  1145. // WOWCF_FE_FLW2_PRINTING_PS,
  1146. // Japanese Lotus Freelance printing with PostScript.
  1147. // Between Escape( BEGIN_PATH ) and Escape( END_PATH ),
  1148. // select brush object with WHITE_BRUSH
  1149. if (GetSystemDefaultLangID() == 0x411 &&
  1150. CURRENTPTD()->dwWOWCompatFlagsFE & WOWCF_FE_FLW2_PRINTING_PS ) {
  1151. if( INT32(parg16->f2) == BEGIN_PATH )
  1152. fCmptFLW = TRUE;
  1153. else
  1154. fCmptFLW = FALSE;
  1155. }
  1156. #endif // FE_SB
  1157. // fall through to escape call
  1158. case CLIP_TO_PATH:
  1159. ul = GETINT16(Escape(hdc32,
  1160. INT32(parg16->f2),
  1161. INT32(parg16->f3),
  1162. (LPCSTR)pin,
  1163. NULL));
  1164. break;
  1165. case PASSTHROUGH:
  1166. // if this is a form feed hack app...
  1167. if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_FORMFEEDHACK) {
  1168. ul = HandleFormFeedHack(hdc32,
  1169. pin,
  1170. FETCHWORD(*(PWORD)pin)); // cb only
  1171. }
  1172. else {
  1173. ul = GETINT16(Escape(hdc32,
  1174. INT32(parg16->f2),
  1175. (FETCHWORD(*(PWORD)pin) + 2),
  1176. (LPCSTR)pin,
  1177. NULL));
  1178. }
  1179. break;
  1180. case FLUSHOUTPUT:
  1181. ul = TRUE;
  1182. break;
  1183. case DOWNLOADFACE:
  1184. {
  1185. WORD InData;
  1186. PWORD lpInData = NULL;
  1187. // PM5 forgot to set there map mode so we do it.
  1188. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
  1189. iMapMode = SetMapMode(hdc32,MM_TWIPS);
  1190. if (pin) {
  1191. InData = FETCHWORD(*(PWORD)pin);
  1192. lpInData = &InData;
  1193. }
  1194. ul = GETINT16(Escape(hdc32,
  1195. INT32(parg16->f2),
  1196. sizeof(USHORT),
  1197. (LPCSTR)lpInData,
  1198. NULL));
  1199. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
  1200. SetMapMode(hdc32,iMapMode);
  1201. }
  1202. break;
  1203. case GETFACENAME:
  1204. {
  1205. int len;
  1206. PSZ pout;
  1207. CHAR ach[60];
  1208. // PM5 forgot to set there map mode so we do it.
  1209. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
  1210. iMapMode = SetMapMode(hdc32,MM_TWIPS);
  1211. GETOPTPTR(parg16->f5, 0, pout);
  1212. // This HACK is for FH4.0 only. If you have any questions
  1213. // talk to PingW or ChandanC.
  1214. // July 21st 1994.
  1215. //
  1216. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_ADD_MSTT) {
  1217. ExtEscape(hdc32,
  1218. ADD_MSTT,
  1219. 0,
  1220. NULL,
  1221. 60,
  1222. ach);
  1223. }
  1224. // pass in 60 as a magic number. Just copy out the valid string.
  1225. ul = GETINT16(ExtEscape(hdc32,
  1226. INT32(parg16->f2),
  1227. INT32(parg16->f3),
  1228. pin,
  1229. 60,
  1230. ach));
  1231. ach[sizeof(ach)-1] = '\0';
  1232. len = strlen(ach)+1;
  1233. len = min(len, sizeof(ach));
  1234. strncpy (pout, ach, len);
  1235. FREEOPTPTR(pout);
  1236. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
  1237. SetMapMode(hdc32,iMapMode);
  1238. }
  1239. break;
  1240. case EPSPRINTING:
  1241. {
  1242. WORD InData;
  1243. PWORD lpInData = NULL;
  1244. if (pin)
  1245. {
  1246. InData = FETCHWORD(*(PWORD)pin);
  1247. lpInData = &InData;
  1248. }
  1249. ul = GETINT16(ExtEscape(hdc32,
  1250. INT32(parg16->f2),
  1251. sizeof(BOOL),
  1252. (LPCSTR)lpInData,
  1253. 0,
  1254. NULL));
  1255. }
  1256. break;
  1257. case GETTECHNOLOGY:
  1258. {
  1259. PVOID pout;
  1260. buf[0] = '\0';
  1261. GETOPTPTR(parg16->f5, 0, pout);
  1262. if (!(CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCENOPOSTSCRIPT))
  1263. {
  1264. ul = GETINT16(ExtEscape(hdc32,
  1265. INT32(parg16->f2),
  1266. INT32(parg16->f3),
  1267. pin,
  1268. sizeof(buf),
  1269. buf));
  1270. #ifdef FE_SB
  1271. // #636 When function is not supported,
  1272. // wow may destroy app's stack
  1273. if ((int)ul < 0)
  1274. buf[0] = '\0';
  1275. #endif // FE_SB
  1276. }
  1277. // we don't have a clue as to how big the app's buffer is here.
  1278. if (pout) {
  1279. strcpy(pout, buf);
  1280. FREEOPTPTR(pout);
  1281. }
  1282. }
  1283. break;
  1284. case SETCOPYCOUNT:
  1285. {
  1286. int cCopiesOut, cCopiesIn=1;
  1287. if (pin)
  1288. cCopiesIn = *(UNALIGNED SHORT *)pin;
  1289. ul = GETINT16(Escape(hdc32,
  1290. INT32(parg16->f2),
  1291. pin ? sizeof(cCopiesIn) : 0,
  1292. pin ? &cCopiesIn : pin,
  1293. parg16->f5 ? &cCopiesOut : NULL));
  1294. if ( parg16->f5 ) {
  1295. if ( (INT)ul > 0 ) {
  1296. PUTINT16(parg16->f5, cCopiesOut);
  1297. } else {
  1298. // Pagemaker v4 needs the output value
  1299. PUTINT16(parg16->f5, 1);
  1300. }
  1301. }
  1302. }
  1303. break;
  1304. case STARTDOC:
  1305. {
  1306. PVOID pout;
  1307. GETOPTPTR(parg16->f5, 0, pout);
  1308. //
  1309. // Win32 StartDoc depends on having the correct current directory
  1310. // when printing to FILE: (which pops up for a filename).
  1311. //
  1312. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  1313. ul = GETINT16(Escape(hdc32,
  1314. INT32(parg16->f2),
  1315. INT32(parg16->f3),
  1316. pin,
  1317. pout));
  1318. //
  1319. // PhotoShop needs a StartPage when it does StartDoc Escape.
  1320. // PingW, ChandanC 3/22/94
  1321. //
  1322. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_NEEDSTARTPAGE) {
  1323. int l;
  1324. char szBuf[80];
  1325. //
  1326. // It should be done ONLY for POSTSCRIPT drivers
  1327. //
  1328. if ((l = ExtEscape(hdc32,
  1329. GETTECHNOLOGY,
  1330. 0,
  1331. NULL,
  1332. sizeof(szBuf),
  1333. szBuf)) > 0) {
  1334. if (!WOW32_stricmp(szBuf, szPostscript)) {
  1335. l = StartPage(hdc32);
  1336. }
  1337. }
  1338. }
  1339. FREEOPTPTR(pout);
  1340. }
  1341. break;
  1342. // Win'95 really messed us up here. They changed the DRAWPATTERNRECT
  1343. // structure instead of defining a new DRAWPATTERNRECT32 struct.
  1344. // On NT, all metafiles are 32-bit. So if an app is building a metafile,
  1345. // it will only know how to do 16-bit DRAWPATTERNRECT (DPR). We have
  1346. // to convert it to a 32-bit DPR before passing it to GDI. On the other
  1347. // hand, if an app is reading a metafile (either memory or disk file) it
  1348. // will be 32-bit if it was created by calls to NT's metafile API, or it
  1349. // could be 16-bit if it is something the app created or a file shipped
  1350. // with the app. If the app handles it correctly by using the size
  1351. // field in the metafile record, then we can fix them up correctly.
  1352. case DRAWPATTERNRECT:
  1353. {
  1354. DRAWPATRECT dpr32in;
  1355. if(pin) {
  1356. // if the app specifies that it is a 32-bit sized DPR struct
  1357. if(INT32(parg16->f3) == sizeof(DRAWPATRECT)) {
  1358. dpr32in.ptPosition.x =
  1359. (LONG)FETCHDWORD(((PDRAWPATRECT)pin)->ptPosition.x);
  1360. dpr32in.ptPosition.y =
  1361. (LONG)FETCHDWORD(((PDRAWPATRECT)pin)->ptPosition.y);
  1362. dpr32in.ptSize.x =
  1363. (LONG)FETCHDWORD(((PDRAWPATRECT)pin)->ptSize.x);
  1364. dpr32in.ptSize.y =
  1365. (LONG)FETCHDWORD(((PDRAWPATRECT)pin)->ptSize.y);
  1366. dpr32in.wStyle =
  1367. FETCHWORD(((PDRAWPATRECT)pin)->wStyle);
  1368. dpr32in.wPattern =
  1369. FETCHWORD(((PDRAWPATRECT)pin)->wPattern);
  1370. }
  1371. // else any other size, all we can do is assume that they
  1372. // are passing it as a 16-bit DRAWPATTERNRECT
  1373. else {
  1374. dpr32in.ptPosition.x =
  1375. (LONG)FETCHWORD(((PDPR16)pin)->ptPosition.x);
  1376. dpr32in.ptPosition.y =
  1377. (LONG)FETCHWORD(((PDPR16)pin)->ptPosition.y);
  1378. dpr32in.ptSize.x =
  1379. (LONG)FETCHWORD(((PDPR16)pin)->ptSize.x);
  1380. dpr32in.ptSize.y =
  1381. (LONG)FETCHWORD(((PDPR16)pin)->ptSize.y);
  1382. dpr32in.wStyle = FETCHWORD(((PDPR16)pin)->wStyle);
  1383. dpr32in.wPattern = FETCHWORD(((PDPR16)pin)->wPattern);
  1384. }
  1385. ul = GETINT16(Escape(hdc32,
  1386. DRAWPATTERNRECT,
  1387. sizeof(DRAWPATRECT),
  1388. (PVOID)&dpr32in,
  1389. NULL));
  1390. }
  1391. }
  1392. break;
  1393. default:
  1394. {
  1395. PVOID pout;
  1396. GETOPTPTR(parg16->f5, 0, pout);
  1397. ul = GETINT16(Escape(hdc32,
  1398. INT32(parg16->f2),
  1399. INT32(parg16->f3),
  1400. pin,
  1401. pout));
  1402. FREEOPTPTR(pout);
  1403. }
  1404. break;
  1405. } // end switch
  1406. FREEOPTPTR(pin);
  1407. FREEARGPTR(parg16);
  1408. RETURN(ul);
  1409. }
  1410. ULONG FASTCALL WG32GetBitmapDimension(PVDMFRAME pFrame)
  1411. {
  1412. ULONG ul;
  1413. SIZE size2;
  1414. register PGETBITMAPDIMENSION16 parg16;
  1415. GETARGPTR(pFrame, sizeof(GETBITMAPDIMENSION16), parg16);
  1416. ul = 0;
  1417. if (GetBitmapDimensionEx(HBITMAP32(parg16->f1), &size2)) {
  1418. ul = (WORD)size2.cx | (size2.cy << 16);
  1419. }
  1420. else {
  1421. WOW32APIWARN (ul, "GetBitmapDimension");
  1422. }
  1423. FREEARGPTR(parg16);
  1424. RETURN(ul);
  1425. }
  1426. ULONG FASTCALL WG32GetBrushOrg(PVDMFRAME pFrame)
  1427. {
  1428. ULONG ul;
  1429. POINT pt;
  1430. POINT pt2;
  1431. HANDLE hdc32;
  1432. register PGETBRUSHORG16 parg16;
  1433. GETARGPTR(pFrame, sizeof(GETBRUSHORG16), parg16);
  1434. // for windows compatability, we must first add the DCorg
  1435. // since windows brushorg is relative to the screen where as NT
  1436. // is relative to the window. In the future, this should call
  1437. // a private gdi entry point to avoid an extra c/s hit. (erick)
  1438. ul = 0;
  1439. hdc32 = HDC32(parg16->f1);
  1440. if (GetDCOrgEx(hdc32, &pt))
  1441. {
  1442. if (GetBrushOrgEx(hdc32, &pt2)) {
  1443. ul = (WORD)(pt2.x + pt.x) | ((pt2.y + pt.y) << 16);
  1444. }
  1445. }
  1446. FREEARGPTR(parg16);
  1447. RETURN(ul);
  1448. }
  1449. ULONG FASTCALL WG32GetClipBox(PVDMFRAME pFrame)
  1450. {
  1451. ULONG ul;
  1452. RECT t2;
  1453. register PGETCLIPBOX16 parg16;
  1454. HDC hdc;
  1455. GETARGPTR(pFrame, sizeof(GETCLIPBOX16), parg16);
  1456. hdc = HDC32(parg16->f1);
  1457. ul = GETINT16(GetClipBox(hdc,&t2));
  1458. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_SIMPLEREGION) {
  1459. ul = SIMPLEREGION;
  1460. }
  1461. PUTRECT16(parg16->f2, &t2);
  1462. FREEARGPTR(parg16);
  1463. RETURN(ul);
  1464. }
  1465. ULONG FASTCALL WG32GetCurrentPosition(PVDMFRAME pFrame)
  1466. {
  1467. ULONG ul;
  1468. POINT pt;
  1469. register PGETCURRENTPOSITION16 parg16;
  1470. GETARGPTR(pFrame, sizeof(GETCURRENTPOSITION16), parg16);
  1471. ul = 0;
  1472. if (GetCurrentPositionEx(HDC32(parg16->f1), &pt)) {
  1473. ul = (WORD)pt.x | (pt.y << 16);
  1474. }
  1475. FREEARGPTR(parg16);
  1476. RETURN(ul);
  1477. }
  1478. ULONG FASTCALL WG32GetDCOrg(PVDMFRAME pFrame)
  1479. {
  1480. ULONG ul;
  1481. POINT pt;
  1482. register PGETDCORG16 parg16;
  1483. GETARGPTR(pFrame, sizeof(GETDCORG16), parg16);
  1484. ul = 0;
  1485. if ( GetDCOrgEx(HDC32(parg16->f1),&pt) ) {
  1486. ul = (WORD)pt.x | (pt.y << 16);
  1487. }
  1488. LOGDEBUG(6,("GetDCOrg for hdc %x returns %lx\n",parg16->f1,ul));
  1489. FREEARGPTR(parg16);
  1490. RETURN(ul);
  1491. }
  1492. // PowerPoint 2&3 call this 2 times for each slide in the slide previewer
  1493. // the lpvBits == NULL on the first call (presumably to find the size to
  1494. // allocate) -- in which case Win3.x returns 1
  1495. ULONG FASTCALL WG32GetDIBits(PVDMFRAME pFrame)
  1496. {
  1497. INT nbmiSize;
  1498. ULONG ul = 0L;
  1499. PBYTE pb5;
  1500. PBYTE pb6;
  1501. STACKBMI32 bmi32;
  1502. LPBITMAPINFO lpbmi32;
  1503. register PGETDIBITS16 parg16;
  1504. GETARGPTR(pFrame, sizeof(GETDIBITS16), parg16);
  1505. GETMISCPTR(parg16->f5, pb5);
  1506. GETMISCPTR(parg16->f6, pb6);
  1507. // copy just the BITMAPINFOHEADER portion of the BITMAPINFO struct
  1508. if(lpbmi32=(LPBITMAPINFO)CopyBMIH16ToBMIH32((PVPVOID)FETCHDWORD(parg16->f6),
  1509. (LPBITMAPINFOHEADER)&bmi32)) {
  1510. // gdi32 will adjust key fields of the BITMAPINFOHEADER & copy the
  1511. // color table into the 32-bit BITMAPINFO struct
  1512. if( ul = GETINT16(GetDIBits(HDC32(parg16->f1),
  1513. HBITMAP32(parg16->f2),
  1514. WORD32(parg16->f3),
  1515. WORD32(parg16->f4),
  1516. pb5,
  1517. lpbmi32,
  1518. WORD32(parg16->f7))) ) {
  1519. // if lpvBits, then they want the bits of the bitmap too
  1520. if(pb5) {
  1521. ul = WORD32(parg16->f4); // return # scanlines requested
  1522. FLUSHVDMPTR(parg16->f5, SIZE_BOGUS, pb5);
  1523. }
  1524. // else tell app that BITMAPINFO structure filled in only
  1525. else {
  1526. ul = 1L;
  1527. }
  1528. // copy the updated BITMAPINFO struct back into the 16-bit version
  1529. nbmiSize = GetBMI32Size(lpbmi32, WORD32(parg16->f7));
  1530. RtlCopyMemory(pb6, lpbmi32, nbmiSize);
  1531. FLUSHVDMPTR(parg16->f6, nbmiSize, pb6);
  1532. }
  1533. }
  1534. FREEMISCPTR(pb5);
  1535. FREEMISCPTR(pb6);
  1536. FREEARGPTR(parg16);
  1537. RETURN(ul);
  1538. }
  1539. ULONG FASTCALL WG32GetDeviceCaps(PVDMFRAME pFrame)
  1540. {
  1541. ULONG ul;
  1542. HANDLE hdc32;
  1543. register PGETDEVICECAPS16 parg16;
  1544. GETARGPTR(pFrame, sizeof(GETDEVICECAPS16), parg16);
  1545. if (INT32(parg16->f2) == COLORRES) {
  1546. ul = 18;
  1547. }
  1548. else {
  1549. hdc32 = HDC32(parg16->f1);
  1550. ul = GetDeviceCaps(hdc32, INT32(parg16->f2));
  1551. if (ul == (ULONG)-1) {
  1552. switch (parg16->f2) {
  1553. case NUMBRUSHES:
  1554. case NUMPENS:
  1555. case NUMCOLORS:
  1556. ul = 2048;
  1557. break;
  1558. default:
  1559. break;
  1560. }
  1561. } else if(ul > 32767) {
  1562. // 16-bit apps can't handle 16M colors in a 16-bit INT
  1563. // most just check if the return is <= 2 to see if they are
  1564. // going to print mono-chrome or color.
  1565. if(parg16->f2 == NUMCOLORS) {
  1566. ul = 32767;
  1567. }
  1568. }
  1569. // if the 4plane conversion flag is set, tell them we are 4 planes 1bpp
  1570. // instead of 1plane 4bpp.
  1571. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_4PLANECONVERSION) {
  1572. if (INT32(parg16->f2) == BITSPIXEL) {
  1573. if ((ul == 4) && (GetDeviceCaps(hdc32, PLANES) == 1))
  1574. ul = 1;
  1575. }
  1576. else if (INT32(parg16->f2) == PLANES) {
  1577. if ((ul == 1) && (GetDeviceCaps(hdc32, BITSPIXEL) == 4))
  1578. ul = 4;
  1579. }
  1580. }
  1581. if ( (POLYGONALCAPS == parg16->f2) && (CURRENTPTD()->dwWOWCompatFlags & WOWCF_NOPC_RECTANGLE)) {
  1582. ul &= !PC_RECTANGLE; // Quattro Pro 1.0 for Windows doesn't handle this bit well.
  1583. }
  1584. if ( RASTERCAPS == INT32(parg16->f2) )
  1585. {
  1586. //
  1587. // bjm 10/10/97
  1588. // This is always on in Win31 and Win95 (supporting BITMAPS is
  1589. // pretty much a requirement for drivers) so Win32 killed
  1590. // the bit and will never return it.
  1591. // So, let's make sure it's always on.
  1592. //
  1593. ul |= 0x8000;
  1594. }
  1595. }
  1596. ul = GETINT16(ul);
  1597. FREEARGPTR(parg16);
  1598. RETURN(ul);
  1599. }
  1600. ULONG FASTCALL WG32GetEnvironment(PVDMFRAME pFrame)
  1601. {
  1602. // not a Win32 function
  1603. //
  1604. // if lpEnviron==NULL then the user is querying the size of device
  1605. // data. WinProj doesn't check the return value, calling the driver
  1606. // with an undersized buffer, trashing the global heap.
  1607. // WinFax passes a hard coded 0xA9 == 0x44+0x69 == sizeof(win3.0 DevMode) +
  1608. // known WinFax.DRV->dmDriverExtra. Beware also that WinFax calls this
  1609. // whenever an app calls any API that requires a DevMode.
  1610. INT len;
  1611. ULONG ul=0;
  1612. register PGETENVIRONMENT16 parg16;
  1613. PSZ psz;
  1614. PSZ psz1 = NULL;
  1615. VPDEVMODE31 vpdm2;
  1616. CHAR *pszDriver = NULL;
  1617. UINT cbT = 0;
  1618. WORD nMaxBytes;
  1619. GETARGPTR(pFrame, sizeof(GETENVIRONMENT16), parg16);
  1620. // save off the 16-bit params now since this could callback into a 16-bit
  1621. // fax driver & cause 16-bit memory to move.
  1622. GETPSZPTR(parg16->f1, psz);
  1623. if(psz) {
  1624. len = lstrlen(psz) + 1;
  1625. psz1 = malloc_w(len);
  1626. if(psz1) {
  1627. strcpy(psz1, psz);
  1628. len = max(len,40);
  1629. pszDriver = malloc_w(len);
  1630. }
  1631. }
  1632. FREEPSZPTR(psz);
  1633. vpdm2 = FETCHDWORD(parg16->f2);
  1634. nMaxBytes = FETCHWORD(parg16->f3);
  1635. FREEARGPTR(parg16);
  1636. // invalidate all flat ptrs to 16:16 memory now
  1637. // this implies that psz1 may also be bad
  1638. if(!pszDriver) {
  1639. goto exitpath;
  1640. }
  1641. if (!(spoolerapis[WOW_EXTDEVICEMODE].lpfn)) {
  1642. if (!LoadLibraryAndGetProcAddresses(L"WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  1643. goto exitpath;
  1644. }
  1645. }
  1646. // get required size for output buffer
  1647. // When WinFax calls this api, calls to GetDriverName for pszDriver ==
  1648. // "FaxModem" seem to fail -- this is a good thing if the app called
  1649. // ExtDeviceMode() because we would get into an infinite loop here. WinFax
  1650. // just fills in a DevMode with default values if this api fails.
  1651. if (GetDriverName(psz1, pszDriver, len)) {
  1652. ul = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL,
  1653. NULL,
  1654. NULL,
  1655. pszDriver,
  1656. psz1,
  1657. NULL,
  1658. NULL,
  1659. 0);
  1660. LOGDEBUG(6,("WOW::GetEnvironment returning ul = %d, for Device = %s, Port = %s \n", ul, pszDriver, psz1));
  1661. // adjust the size for our DEVMODE handling (see note in wstruc.c)
  1662. // (it won't hurt to allocate too much)
  1663. if(ul) {
  1664. ul += sizeof(WOWDM31);
  1665. cbT = (UINT)ul;
  1666. }
  1667. // if they also want us to fill in their environment structure...
  1668. if ((vpdm2 != 0) && (ul != 0)) {
  1669. LPDEVMODE lpdmOutput;
  1670. if (lpdmOutput = malloc_w(ul)) {
  1671. // this might be calling into a 16-bit fax driver!!
  1672. ul = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL,
  1673. NULL,
  1674. lpdmOutput,
  1675. pszDriver,
  1676. psz1,
  1677. NULL,
  1678. NULL,
  1679. DM_OUT_BUFFER);
  1680. // if a WinFax call to GetDriverName() succeeds & gets to here
  1681. // we may need to hack on the lpdmOutput->dmSize==0x40
  1682. // (Win3.0 size) to account for the hard coded buffer size of
  1683. // 0xa9 the app passes. So far I haven't seen WinFax get past
  1684. // GetDriverName() call & it still seems to work OK.
  1685. if (ul > 0L) {
  1686. // Use the min of nMaxBytes & what we calculated
  1687. ThunkDevMode32to16(vpdm2, lpdmOutput, min(nMaxBytes, cbT));
  1688. }
  1689. free_w(lpdmOutput);
  1690. LOGDEBUG(6,("WOW::GetEnvironment getting DEVMODE structure, ul = %d, for Device = %s, Port = %s \n", ul, pszDriver, psz1));
  1691. }
  1692. }
  1693. }
  1694. exitpath:
  1695. if(psz1) {
  1696. free_w(psz1);
  1697. }
  1698. if(pszDriver) {
  1699. free_w(pszDriver);
  1700. }
  1701. RETURN(ul);
  1702. }
  1703. ULONG FASTCALL WG32GetObject(PVDMFRAME pFrame)
  1704. {
  1705. ULONG ul;
  1706. HANDLE hgdi;
  1707. register PGETOBJECT16 parg16;
  1708. GETARGPTR(pFrame, sizeof(GETOBJECT16), parg16);
  1709. hgdi = HOBJ32(parg16->f1);
  1710. switch (GetObjectType(hgdi)) {
  1711. case OBJ_BITMAP:
  1712. {
  1713. BITMAP bm;
  1714. ul = GETINT16(GetObject(hgdi, sizeof(BITMAP), (LPSTR)&bm));
  1715. if (ul) {
  1716. PUTBITMAP16(parg16->f3, parg16->f2, &bm);
  1717. if ( ul > sizeof(BITMAP16) ) {
  1718. ul = sizeof(BITMAP16);
  1719. }
  1720. }
  1721. }
  1722. break;
  1723. case OBJ_BRUSH:
  1724. {
  1725. LOGBRUSH lb;
  1726. ul = GETINT16(GetObject(hgdi, sizeof(LOGBRUSH), (LPSTR)&lb));
  1727. if (ul) {
  1728. PUTLOGBRUSH16(parg16->f3, parg16->f2, &lb);
  1729. if (ul > sizeof(LOGBRUSH16)) {
  1730. ul = sizeof(LOGBRUSH16);
  1731. }
  1732. }
  1733. }
  1734. break;
  1735. case OBJ_PEN:
  1736. {
  1737. LOGPEN lp;
  1738. ul = GETINT16(GetObject(hgdi, sizeof(LOGPEN), (LPSTR)&lp));
  1739. if (ul) {
  1740. PUTLOGPEN16(parg16->f3, parg16->f2, &lp);
  1741. if (ul > sizeof(LOGPEN16)) {
  1742. ul = sizeof(LOGPEN16);
  1743. }
  1744. }
  1745. }
  1746. break;
  1747. case OBJ_FONT:
  1748. {
  1749. LOGFONT lf;
  1750. ul = GETINT16(GetObject(hgdi, sizeof(LOGFONT), (LPSTR)&lf));
  1751. if (ul) {
  1752. PUTLOGFONT16(parg16->f3, parg16->f2, &lf);
  1753. if (ul > sizeof(LOGFONT16)) {
  1754. ul = sizeof(LOGFONT16);
  1755. }
  1756. }
  1757. }
  1758. break;
  1759. case OBJ_PAL:
  1760. {
  1761. PSHORT16 lpT;
  1762. SHORT sT;
  1763. ul = GETINT16(GetObject(hgdi, sizeof(SHORT), (LPSTR)&sT));
  1764. if (ul && (FETCHWORD(parg16->f2) >= sizeof(WORD))) {
  1765. GETVDMPTR(FETCHDWORD(parg16->f3), sizeof(WORD), lpT);
  1766. if (lpT) {
  1767. STOREWORD(lpT[0], sT);
  1768. }
  1769. FREEVDMPTR(lpT);
  1770. }
  1771. }
  1772. break;
  1773. default:
  1774. {
  1775. PBYTE pb3;
  1776. LOGDEBUG(LOG_ALWAYS,(" HACK: GetObject handle unknown, contact ChandanC\n"));
  1777. GETVDMPTR(parg16->f3, parg16->f2, pb3);
  1778. ul = GETINT16(GetObject(hgdi, INT32(parg16->f2), pb3));
  1779. FLUSHVDMPTR(parg16->f3, parg16->f2, pb3);
  1780. FREEVDMPTR(pb3);
  1781. }
  1782. } // switch
  1783. WOW32APIWARN(ul, "GetObject");
  1784. FREEARGPTR(parg16);
  1785. RETURN(ul);
  1786. }
  1787. ULONG FASTCALL WG32GetRgnBox(PVDMFRAME pFrame)
  1788. {
  1789. ULONG ul;
  1790. RECT t2;
  1791. register PGETRGNBOX16 parg16;
  1792. GETARGPTR(pFrame, sizeof(GETRGNBOX16), parg16);
  1793. ul = GETINT16(GetRgnBox(HRGN32(parg16->f1), &t2));
  1794. PUTRECT16(parg16->f2, &t2);
  1795. FREEARGPTR(parg16);
  1796. RETURN(ul);
  1797. }
  1798. ULONG FASTCALL WG32GetViewportExt(PVDMFRAME pFrame)
  1799. {
  1800. ULONG ul;
  1801. SIZE size;
  1802. register PGETVIEWPORTEXT16 parg16;
  1803. GETARGPTR(pFrame, sizeof(GETVIEWPORTEXT16), parg16);
  1804. ul = 0;
  1805. if (GetViewportExtEx(HDC32(parg16->f1), &size)) {
  1806. //
  1807. // win31 returns 1 rather than 0 unless there was an error
  1808. //
  1809. if (!(ul = (WORD)size.cx | (size.cy << 16)))
  1810. ul = 1;
  1811. }
  1812. FREEARGPTR(parg16);
  1813. RETURN(ul);
  1814. }
  1815. ULONG FASTCALL WG32GetViewportOrg(PVDMFRAME pFrame)
  1816. {
  1817. ULONG ul;
  1818. POINT pt;
  1819. register PGETVIEWPORTORG16 parg16;
  1820. GETARGPTR(pFrame, sizeof(GETVIEWPORTORG16), parg16);
  1821. ul = 0;
  1822. if (GetViewportOrgEx(HDC32(parg16->f1), &pt)) {
  1823. ul = (WORD)pt.x | (pt.y << 16);
  1824. }
  1825. FREEARGPTR(parg16);
  1826. RETURN(ul);
  1827. }
  1828. ULONG FASTCALL WG32GetWindowExt(PVDMFRAME pFrame)
  1829. {
  1830. ULONG ul;
  1831. SIZE size;
  1832. register PGETWINDOWEXT16 parg16;
  1833. GETARGPTR(pFrame, sizeof(GETWINDOWEXT16), parg16);
  1834. ul = 0;
  1835. if (GetWindowExtEx(HDC32(parg16->f1), &size)) {
  1836. if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
  1837. ul = 1;
  1838. }
  1839. FREEARGPTR(parg16);
  1840. RETURN(ul);
  1841. }
  1842. ULONG FASTCALL WG32GetWindowOrg(PVDMFRAME pFrame)
  1843. {
  1844. ULONG ul;
  1845. POINT pt;
  1846. register PGETWINDOWORG16 parg16;
  1847. GETARGPTR(pFrame, sizeof(GETWINDOWORG16), parg16);
  1848. ul = 0;
  1849. if (GetWindowOrgEx(HDC32(parg16->f1), &pt)) {
  1850. ul = (WORD)pt.x | (pt.y << 16);
  1851. }
  1852. FREEARGPTR(parg16);
  1853. RETURN(ul);
  1854. }
  1855. ULONG FASTCALL WG32LPtoDP(PVDMFRAME pFrame)
  1856. {
  1857. ULONG ul=0;
  1858. LPPOINT t2;
  1859. register PLPTODP16 parg16;
  1860. POINT BufferT[128];
  1861. GETARGPTR(pFrame, sizeof(LPTODP16), parg16);
  1862. t2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
  1863. if (t2) {
  1864. getpoint16(parg16->f2, parg16->f3, t2);
  1865. ul = GETBOOL16(LPtoDP(HDC32(parg16->f1), t2, INT32(parg16->f3)));
  1866. PUTPOINTARRAY16(parg16->f2, parg16->f3, t2);
  1867. STACKORHEAPFREE(t2, BufferT);
  1868. }
  1869. FREEARGPTR(parg16);
  1870. RETURN(ul);
  1871. }
  1872. void W32LineDDAFunc(int x, int y, PLINEDDADATA pDDAData)
  1873. {
  1874. PARM16 Parm16;
  1875. WOW32ASSERT(pDDAData);
  1876. Parm16.LineDDAProc.vpData = (VPVOID)pDDAData->dwUserDDAParam;
  1877. Parm16.LineDDAProc.x = (SHORT)x;
  1878. Parm16.LineDDAProc.y = (SHORT)y;
  1879. Parm16.LineDDAProc.vpData = (VPVOID)pDDAData->dwUserDDAParam;
  1880. CallBack16(RET_LINEDDAPROC, &Parm16, pDDAData->vpfnLineDDAProc, NULL);
  1881. return;
  1882. }
  1883. ULONG FASTCALL WG32LineDDA(PVDMFRAME pFrame)
  1884. {
  1885. LINEDDADATA DDAData;
  1886. register PLINEDDA16 parg16;
  1887. GETARGPTR(pFrame, sizeof(LINEDDA16), parg16);
  1888. DDAData.vpfnLineDDAProc = DWORD32(parg16->f5);
  1889. DDAData.dwUserDDAParam = DWORD32(parg16->f6);
  1890. LineDDA(INT32(parg16->f1),
  1891. INT32(parg16->f2),
  1892. INT32(parg16->f3),
  1893. INT32(parg16->f4),
  1894. (LINEDDAPROC)W32LineDDAFunc,
  1895. (LPARAM)&DDAData);
  1896. // 16-bit memory may have moved - invalidate flat pointers now
  1897. FREEVDMPTR(pFrame);
  1898. FREEARGPTR(parg16);
  1899. RETURN(1L);
  1900. }
  1901. ULONG FASTCALL WG32MoveTo(PVDMFRAME pFrame)
  1902. {
  1903. ULONG ul;
  1904. POINT pt;
  1905. register PMOVETO16 parg16;
  1906. GETARGPTR(pFrame, sizeof(MOVETO16), parg16);
  1907. ul = 0;
  1908. pt.x = 1L; // see "METAFILE NOTE"
  1909. pt.y = 0L;
  1910. if (MoveToEx(HDC32(parg16->f1),
  1911. INT32(parg16->f2),
  1912. INT32(parg16->f3),
  1913. &pt)) {
  1914. ul = (WORD)pt.x | (pt.y << 16);
  1915. }
  1916. FREEARGPTR(parg16);
  1917. RETURN(ul);
  1918. }
  1919. ULONG FASTCALL WG32OffsetViewportOrg(PVDMFRAME pFrame)
  1920. {
  1921. ULONG ul;
  1922. POINT pt;
  1923. register POFFSETVIEWPORTORG16 parg16;
  1924. GETARGPTR(pFrame, sizeof(OFFSETVIEWPORTORG16), parg16);
  1925. ul = 0;
  1926. pt.x = 1L; // see "METAFILE NOTE"
  1927. pt.y = 0L;
  1928. if (OffsetViewportOrgEx(HDC32(parg16->f1),
  1929. INT32(parg16->f2),
  1930. INT32(parg16->f3),
  1931. &pt)) {
  1932. ul = (WORD)pt.x | (pt.y << 16);
  1933. }
  1934. FREEARGPTR(parg16);
  1935. RETURN(ul);
  1936. }
  1937. ULONG FASTCALL WG32OffsetWindowOrg(PVDMFRAME pFrame)
  1938. {
  1939. ULONG ul;
  1940. POINT pt;
  1941. register POFFSETWINDOWORG16 parg16;
  1942. GETARGPTR(pFrame, sizeof(OFFSETWINDOWORG16), parg16);
  1943. ul = 0;
  1944. pt.x = 1L; // see "METAFILE NOTE"
  1945. pt.y = 0L;
  1946. if (OffsetWindowOrgEx(HDC32(parg16->f1),
  1947. INT32(parg16->f2),
  1948. INT32(parg16->f3),
  1949. &pt)) {
  1950. ul = (WORD)pt.x | (pt.y << 16);
  1951. }
  1952. FREEARGPTR(parg16);
  1953. RETURN(ul);
  1954. }
  1955. ULONG FASTCALL WG32PolyPolygon(PVDMFRAME pFrame)
  1956. {
  1957. ULONG ul=0;
  1958. LPPOINT pPoints;
  1959. PINT pPolyCnt;
  1960. UINT cpts = 0;
  1961. INT ii;
  1962. register PPOLYPOLYGON16 parg16;
  1963. INT cInt16;
  1964. INT BufferT[256]; // comfortably large array
  1965. GETARGPTR(pFrame, sizeof(POLYPOLYGON16), parg16);
  1966. cInt16 = INT32(parg16->f4);
  1967. pPolyCnt = STACKORHEAPALLOC(cInt16 * sizeof(INT), sizeof(BufferT), BufferT);
  1968. if (!pPolyCnt) {
  1969. FREEARGPTR(parg16);
  1970. RETURN(0);
  1971. }
  1972. getintarray16(parg16->f3, cInt16, pPolyCnt);
  1973. for (ii=0; ii < cInt16; ii++)
  1974. cpts += pPolyCnt[ii];
  1975. pPoints = STACKORHEAPALLOC(cpts * sizeof(POINT),
  1976. sizeof(BufferT) - cInt16 * sizeof(INT),
  1977. BufferT + cInt16);
  1978. if (pPoints) {
  1979. getpoint16(parg16->f2, cpts, pPoints);
  1980. ul = GETBOOL16(PolyPolygon(HDC32(parg16->f1),
  1981. pPoints,
  1982. pPolyCnt,
  1983. INT32(parg16->f4)));
  1984. STACKORHEAPFREE(pPoints, BufferT + cInt16);
  1985. }
  1986. STACKORHEAPFREE(pPolyCnt, BufferT);
  1987. FREEARGPTR(parg16);
  1988. RETURN(ul);
  1989. }
  1990. ULONG FASTCALL WG32PolyPolylineWOW(PVDMFRAME pFrame)
  1991. {
  1992. ULONG ul;
  1993. register PPOLYPOLYLINEWOW16 parg16;
  1994. LPPOINT pptArray;
  1995. LPDWORD pcntArray;
  1996. DWORD cnt;
  1997. GETARGPTR(pFrame, sizeof(POLYPOLYLINEWOW16), parg16);
  1998. cnt = FETCHDWORD(parg16->f4);
  1999. GETVDMPTR(parg16->f2, sizeof(POINT)*cnt, pptArray);
  2000. GETVDMPTR(parg16->f3, sizeof(DWORD)*cnt, pcntArray);
  2001. ul = GETBOOL16(PolyPolyline(HDC32(parg16->f1),
  2002. pptArray,
  2003. pcntArray,
  2004. cnt));
  2005. FREEVDMPTR(pptArray);
  2006. FREEVDMPTR(pcntArray);
  2007. FREEARGPTR(parg16);
  2008. RETURN(ul);
  2009. }
  2010. ULONG FASTCALL WG32Polygon(PVDMFRAME pFrame)
  2011. {
  2012. ULONG ul=0;
  2013. LPPOINT p2;
  2014. register PPOLYGON16 parg16;
  2015. POINT BufferT[128];
  2016. HANDLE hdc32;
  2017. #ifdef FE_SB // for Japanese Lotus Freelance
  2018. HBRUSH hbr = 0;
  2019. #endif // FE_SB
  2020. GETARGPTR(pFrame, sizeof(POLYGON16), parg16);
  2021. p2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
  2022. hdc32 = HDC32(parg16->f1);
  2023. if (p2) {
  2024. getpoint16(parg16->f2, parg16->f3, p2);
  2025. #ifdef FE_SB
  2026. // WOWCF_FE_FLW2_PRINTING_PS, Japanese Lotus Freelance
  2027. // printing with PostScript.
  2028. // Between Escape( BEGIN_PATH ) and Escape( END_PATH ),
  2029. // select brush object with WHITE_BRUSH
  2030. if (GetSystemDefaultLangID() == 0x411 && fCmptFLW &&
  2031. CURRENTPTD()->dwWOWCompatFlagsFE & WOWCF_FE_FLW2_PRINTING_PS) {
  2032. hbr = SelectObject(hdc32, GetStockObject( WHITE_BRUSH ));
  2033. }
  2034. #endif // FE_SB
  2035. ul = GETBOOL16(Polygon(hdc32, p2, INT32(parg16->f3)));
  2036. #ifdef FE_SB
  2037. if (hbr) {
  2038. SelectObject(hdc32, hbr );
  2039. }
  2040. #endif // FE_SB
  2041. STACKORHEAPFREE(p2, BufferT);
  2042. }
  2043. FREEARGPTR(parg16);
  2044. RETURN(ul);
  2045. }
  2046. ULONG FASTCALL WG32Polyline(PVDMFRAME pFrame)
  2047. {
  2048. ULONG ul=0;
  2049. PPOINT t2;
  2050. register PPOLYLINE16 parg16;
  2051. POINT BufferT[128];
  2052. GETARGPTR(pFrame, sizeof(POLYLINE16), parg16);
  2053. t2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
  2054. if (t2) {
  2055. getpoint16(parg16->f2, parg16->f3, t2);
  2056. ul = GETBOOL16(Polyline(HDC32(parg16->f1), t2, INT32(parg16->f3)));
  2057. STACKORHEAPFREE(t2, BufferT);
  2058. }
  2059. FREEARGPTR(parg16);
  2060. RETURN(ul);
  2061. }
  2062. ULONG FASTCALL WG32RectInRegion(PVDMFRAME pFrame)
  2063. {
  2064. ULONG ul;
  2065. RECT t2;
  2066. register PRECTINREGION16 parg16;
  2067. GETARGPTR(pFrame, sizeof(RECTINREGION16), parg16);
  2068. WOW32VERIFY(GETRECT16(parg16->f2, &t2));
  2069. ul = GETBOOL16(RectInRegion(HRGN32(parg16->f1), &t2));
  2070. FREEARGPTR(parg16);
  2071. RETURN(ul);
  2072. }
  2073. ULONG FASTCALL WG32RectVisible(PVDMFRAME pFrame)
  2074. {
  2075. ULONG ul;
  2076. RECT t2;
  2077. register PRECTVISIBLE16 parg16;
  2078. GETARGPTR(pFrame, sizeof(RECTVISIBLE16), parg16);
  2079. WOW32VERIFY(GETRECT16(parg16->f2, &t2));
  2080. ul = GETBOOL16(RectVisible(HDC32(parg16->f1), &t2));
  2081. FREEARGPTR(parg16);
  2082. RETURN(ul);
  2083. }
  2084. ULONG FASTCALL WG32ScaleViewportExt(PVDMFRAME pFrame)
  2085. {
  2086. ULONG ul;
  2087. SIZE size;
  2088. register PSCALEVIEWPORTEXT16 parg16;
  2089. GETARGPTR(pFrame, sizeof(SCALEVIEWPORTEXT16), parg16);
  2090. ul = 0;
  2091. if (ScaleViewportExtEx(HDC32(parg16->f1),
  2092. INT32(parg16->f2),
  2093. INT32(parg16->f3),
  2094. INT32(parg16->f4),
  2095. INT32(parg16->f5),
  2096. &size)) {
  2097. if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
  2098. ul = 1;
  2099. }
  2100. FREEARGPTR(parg16);
  2101. RETURN(ul);
  2102. }
  2103. ULONG FASTCALL WG32ScaleWindowExt(PVDMFRAME pFrame)
  2104. {
  2105. ULONG ul;
  2106. SIZE size;
  2107. register PSCALEWINDOWEXT16 parg16;
  2108. GETARGPTR(pFrame, sizeof(SCALEWINDOWEXT16), parg16);
  2109. ul = 0;
  2110. if (ScaleWindowExtEx(HDC32(parg16->f1),
  2111. INT32(parg16->f2),
  2112. INT32(parg16->f3),
  2113. INT32(parg16->f4),
  2114. INT32(parg16->f5),
  2115. &size)) {
  2116. if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
  2117. ul = 1;
  2118. }
  2119. FREEARGPTR(parg16);
  2120. RETURN(ul);
  2121. }
  2122. /******************************Public*Routine******************************\
  2123. * PBYTE pjCvtPlaneToPacked4
  2124. *
  2125. * Convert a 4plane, 1bpp bitmap into a 1plane, 4bpp bitmap.
  2126. * This functions returns a pointer that must later be freed with LocalFree().
  2127. *
  2128. * This has been added for PhotoShop 16 color vga compatability.
  2129. *
  2130. * History:
  2131. * 28-May-1993 -by- Eric Kutter [erick]
  2132. * Wrote it.
  2133. \**************************************************************************/
  2134. PBYTE pjCvtPlaneToPacked4(
  2135. BITMAP *pbm,
  2136. PBYTE pjSrc,
  2137. DWORD *pcjSrc)
  2138. {
  2139. PBYTE pjDstRet;
  2140. PBYTE pjDst;
  2141. PBYTE pjPlane[4]; // pointer to first byte of current scan for each plane
  2142. DWORD cjWidth; // width of the destination in bytes
  2143. DWORD cjSrcWidth; // width of the source scan in bytes inc. all planes
  2144. DWORD cy; // number of scans
  2145. BYTE shift; // shift value,
  2146. DWORD i,x,y;
  2147. // just grab the width of the dest out of the BITMAP
  2148. cjWidth = pbm->bmWidthBytes;
  2149. // the src should be word aligned for each plane with 4 planes
  2150. cjSrcWidth = ((pbm->bmWidth + 15) & ~15) / 8 * 4;
  2151. if (!cjSrcWidth) {
  2152. WOW32ASSERT ( 0 != cjSrcWidth );
  2153. return(NULL);
  2154. }
  2155. // compute the height, the smaller of the bm height and the source height
  2156. cy = min((DWORD)pbm->bmHeight,(DWORD)(*pcjSrc / cjSrcWidth));
  2157. // allocate the new chunk of memory
  2158. *pcjSrc = cy * cjWidth;
  2159. pjDst = LocalAlloc(LMEM_FIXED,*pcjSrc);
  2160. if (pjDst == NULL)
  2161. return(NULL);
  2162. pjDstRet = pjDst;
  2163. // intialize the beginings of the planes
  2164. for (i = 0; i < 4; ++i)
  2165. pjPlane[i] = pjSrc + (cjSrcWidth / 4) * i;
  2166. // loop through the scans
  2167. for (y = 0; y < cy; ++y)
  2168. {
  2169. shift = 7;
  2170. // loop through the bytes within a scan
  2171. for (x = 0; x < cjWidth; ++x)
  2172. {
  2173. // bit 7 -> nibble 1
  2174. // bit 6 -> nibble 0
  2175. // bit 5 -> nibble 3
  2176. // bit 4 -> nibble 2
  2177. // . . .
  2178. *pjDst = (((pjPlane[0][x/4] >> (shift-1)) & 1) << 0 ) | // 0x01
  2179. (((pjPlane[1][x/4] >> (shift-1)) & 1) << 1 ) | // 0x02
  2180. (((pjPlane[2][x/4] >> (shift-1)) & 1) << 2 ) | // 0x04
  2181. (((pjPlane[3][x/4] >> (shift-1)) & 1) << 3 ) | // 0x08
  2182. (((pjPlane[0][x/4] >> (shift-0)) & 1) << 4 ) | // 0x10
  2183. (((pjPlane[1][x/4] >> (shift-0)) & 1) << 5 ) | // 0x20
  2184. (((pjPlane[2][x/4] >> (shift-0)) & 1) << 6 ) | // 0x40
  2185. (((pjPlane[3][x/4] >> (shift-0)) & 1) << 7 ); // 0x80
  2186. pjDst++;
  2187. shift = (shift - 2) & 7;
  2188. }
  2189. pjPlane[0] += cjSrcWidth;
  2190. pjPlane[1] += cjSrcWidth;
  2191. pjPlane[2] += cjSrcWidth;
  2192. pjPlane[3] += cjSrcWidth;
  2193. }
  2194. return(pjDstRet);
  2195. }
  2196. ULONG FASTCALL WG32SetBitmapBits(PVDMFRAME pFrame)
  2197. {
  2198. ULONG ul = 0;
  2199. PBYTE pb3;
  2200. register PSETBITMAPBITS16 parg16;
  2201. HBITMAP hbm;
  2202. DWORD cj;
  2203. BITMAP bm;
  2204. BOOL fValidObj;
  2205. GETARGPTR(pFrame, sizeof(SETBITMAPBITS16), parg16);
  2206. GETOPTPTR(parg16->f3, 0, pb3);
  2207. hbm = HBITMAP32(parg16->f1);
  2208. cj = DWORD32(parg16->f2);
  2209. fValidObj = (GetObject(hbm,sizeof(BITMAP),&bm) == sizeof(BITMAP));
  2210. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_4PLANECONVERSION) {
  2211. // Get the size of the destination bitmap
  2212. if (fValidObj &&
  2213. (bm.bmPlanes == 1) &&
  2214. (bm.bmBitsPixel == 4))
  2215. {
  2216. PBYTE pjCvt = pjCvtPlaneToPacked4(&bm,pb3,&cj);
  2217. if (pjCvt)
  2218. ul = SetBitmapBits(hbm,cj,pjCvt);
  2219. else
  2220. ul = 0;
  2221. LocalFree(pjCvt);
  2222. hbm = 0;
  2223. }
  2224. }
  2225. else {
  2226. cj = min(cj, (DWORD)(bm.bmWidthBytes * bm.bmHeight));
  2227. }
  2228. if (hbm != 0)
  2229. ul = GETLONG16(SetBitmapBits(hbm,cj,pb3));
  2230. WOW32APIWARN (ul, "SetBitmapBits");
  2231. FREEMISCPTR(pb3);
  2232. FREEARGPTR(parg16);
  2233. RETURN(ul);
  2234. }
  2235. ULONG FASTCALL WG32SetBitmapDimension(PVDMFRAME pFrame)
  2236. {
  2237. ULONG ul;
  2238. SIZE size4;
  2239. register PSETBITMAPDIMENSION16 parg16;
  2240. GETARGPTR(pFrame, sizeof(SETBITMAPDIMENSION16), parg16);
  2241. ul = 0;
  2242. if (SetBitmapDimensionEx(HBITMAP32(parg16->f1),
  2243. INT32(parg16->f2),
  2244. INT32(parg16->f3),
  2245. &size4)) {
  2246. ul = (WORD)size4.cx | (size4.cy << 16);
  2247. }
  2248. FREEARGPTR(parg16);
  2249. RETURN(ul);
  2250. }
  2251. ULONG FASTCALL WG32SetBrushOrg(PVDMFRAME pFrame)
  2252. {
  2253. ULONG ul = 0;
  2254. POINT pt;
  2255. POINT pt2;
  2256. HANDLE hdc32;
  2257. register PSETBRUSHORG16 parg16;
  2258. GETARGPTR(pFrame, sizeof(SETBRUSHORG16), parg16);
  2259. // for windows compatability, we must first subtract off the DCorg
  2260. // since windows brushorg is relative to the screen where as NT
  2261. // is relative to the window. In the future, this should call
  2262. // a private gdi entry point to avoid an extra c/s hit. (erick)
  2263. hdc32 = HDC32(parg16->f1);
  2264. if (GetDCOrgEx(hdc32, &pt))
  2265. {
  2266. ul = 0;
  2267. pt2.x = 1L; // see "METAFILE NOTE"
  2268. pt2.y = 0L;
  2269. if (SetBrushOrgEx(hdc32,
  2270. INT32(parg16->f2) - pt.x,
  2271. INT32(parg16->f3) - pt.y,
  2272. &pt2)) {
  2273. // add the origin back on so the app gets a consistent return value.
  2274. // view...all from micrografx designer doesn't work unless this returns
  2275. // the right thing.
  2276. ul = (WORD)(pt2.x + pt.x) | ((pt2.y + pt.y) << 16);
  2277. }
  2278. }
  2279. FREEARGPTR(parg16);
  2280. RETURN(ul);
  2281. }
  2282. ULONG FASTCALL WG32SetDIBits(PVDMFRAME pFrame)
  2283. {
  2284. ULONG ul = 0L;
  2285. PBYTE pb5;
  2286. STACKBMI32 bmi32;
  2287. LPBITMAPINFO lpbmi32;
  2288. register PSETDIBITS16 parg16;
  2289. GETARGPTR(pFrame, sizeof(SETDIBITS16), parg16);
  2290. GETMISCPTR(parg16->f5, pb5);
  2291. lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f6),
  2292. (LPBITMAPINFO)&bmi32,
  2293. FETCHWORD(parg16->f7));
  2294. // see if we need to adjust the image sze for RLE bitmaps
  2295. if(lpbmi32 && pb5) {
  2296. if((lpbmi32->bmiHeader.biCompression == BI_RLE4) ||
  2297. (lpbmi32->bmiHeader.biCompression == BI_RLE8)) {
  2298. if(lpbmi32->bmiHeader.biSizeImage == 0) {
  2299. lpbmi32->bmiHeader.biSizeImage =
  2300. Get_RLE_Compression_Size(lpbmi32->bmiHeader.biCompression,
  2301. pb5,
  2302. parg16->f5);
  2303. }
  2304. }
  2305. }
  2306. ul = GETINT16(SetDIBits(HDC32(parg16->f1),
  2307. HBITMAP32(parg16->f2),
  2308. WORD32(parg16->f3),
  2309. WORD32(parg16->f4),
  2310. pb5,
  2311. lpbmi32,
  2312. WORD32(parg16->f7)));
  2313. WOW32APIWARN (ul, "WG32SetDIBits\n");
  2314. FREEMISCPTR(pb5);
  2315. FREEARGPTR(parg16);
  2316. RETURN(ul);
  2317. }
  2318. ULONG FASTCALL WG32SetDIBitsToDevice(PVDMFRAME pFrame)
  2319. {
  2320. ULONG ul = 0L;
  2321. PSZ p10;
  2322. STACKBMI32 bmi32;
  2323. LPBITMAPINFO lpbmi32;
  2324. register PSETDIBITSTODEVICE16 parg16;
  2325. GETARGPTR(pFrame, sizeof(SETDIBITSTODEVICE16), parg16);
  2326. GETMISCPTR(parg16->f10, p10);
  2327. lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f11),
  2328. (LPBITMAPINFO)&bmi32,
  2329. FETCHWORD(parg16->f12));
  2330. // these are doc'd as WORD in Win3.0, doc'd as INT in Win3.1
  2331. WOW32ASSERTMSG(((INT)parg16->f4 >= 0),("WOW:signed val - CMJones\n"));
  2332. WOW32ASSERTMSG(((INT)parg16->f5 >= 0),("WOW:signed val - CMJones\n"));
  2333. WOW32ASSERTMSG(((INT)parg16->f8 >= 0),("WOW:signed val - CMJones\n"));
  2334. WOW32ASSERTMSG(((INT)parg16->f9 >= 0),("WOW:signed val - CMJones\n"));
  2335. // see if we need to adjust the image sze for RLE bitmaps
  2336. if(lpbmi32 && p10) {
  2337. if((lpbmi32->bmiHeader.biCompression == BI_RLE4) ||
  2338. (lpbmi32->bmiHeader.biCompression == BI_RLE8)) {
  2339. if(lpbmi32->bmiHeader.biSizeImage == 0) {
  2340. lpbmi32->bmiHeader.biSizeImage =
  2341. Get_RLE_Compression_Size(lpbmi32->bmiHeader.biCompression,
  2342. p10,
  2343. parg16->f10);
  2344. }
  2345. }
  2346. }
  2347. ul = GETINT16(SetDIBitsToDevice(HDC32(parg16->f1),
  2348. INT32(parg16->f2),
  2349. INT32(parg16->f3),
  2350. WORD32(parg16->f4),
  2351. WORD32(parg16->f5),
  2352. INT32(parg16->f6),
  2353. INT32(parg16->f7),
  2354. WORD32(parg16->f8),
  2355. WORD32(parg16->f9),
  2356. p10,
  2357. lpbmi32,
  2358. WORD32(parg16->f12)));
  2359. WOW32APIWARN (ul, "WG32SetDIBitsToDevice\n");
  2360. FREEMISCPTR(p10);
  2361. FREEARGPTR(parg16);
  2362. RETURN(ul);
  2363. }
  2364. ULONG FASTCALL WG32SetViewportExt(PVDMFRAME pFrame)
  2365. {
  2366. ULONG ul;
  2367. SIZE size;
  2368. register PSETVIEWPORTEXT16 parg16;
  2369. GETARGPTR(pFrame, sizeof(SETVIEWPORTEXT16), parg16);
  2370. ul = 0;
  2371. if (SetViewportExtEx(HDC32(parg16->f1),
  2372. INT32(parg16->f2),
  2373. INT32(parg16->f3),
  2374. &size)) {
  2375. if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
  2376. ul = 1;
  2377. }
  2378. FREEARGPTR(parg16);
  2379. RETURN(ul);
  2380. }
  2381. ULONG FASTCALL WG32SetViewportOrg(PVDMFRAME pFrame)
  2382. {
  2383. ULONG ul;
  2384. POINT pt;
  2385. register PSETVIEWPORTORG16 parg16;
  2386. GETARGPTR(pFrame, sizeof(SETVIEWPORTORG16), parg16);
  2387. ul = 0;
  2388. pt.x = 1L; // see "METAFILE NOTE"
  2389. pt.y = 0L;
  2390. if (SetViewportOrgEx(HDC32(parg16->f1),
  2391. INT32(parg16->f2),
  2392. INT32(parg16->f3),
  2393. &pt)) {
  2394. ul = (WORD)pt.x | (pt.y << 16);
  2395. }
  2396. FREEARGPTR(parg16);
  2397. RETURN(ul);
  2398. }
  2399. ULONG FASTCALL WG32SetWindowExt(PVDMFRAME pFrame)
  2400. {
  2401. ULONG ul;
  2402. SIZE size;
  2403. register PSETWINDOWEXT16 parg16;
  2404. GETARGPTR(pFrame, sizeof(SETWINDOWEXT16), parg16);
  2405. ul = 0;
  2406. if (SetWindowExtEx(HDC32(parg16->f1),
  2407. INT32(parg16->f2),
  2408. INT32(parg16->f3),
  2409. &size)) {
  2410. if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
  2411. ul = 1;
  2412. }
  2413. FREEARGPTR(parg16);
  2414. RETURN(ul);
  2415. }
  2416. ULONG FASTCALL WG32SetWindowOrg(PVDMFRAME pFrame)
  2417. {
  2418. ULONG ul;
  2419. POINT pt;
  2420. register PSETWINDOWORG16 parg16;
  2421. GETARGPTR(pFrame, sizeof(SETWINDOWORG16), parg16);
  2422. ul = 0;
  2423. pt.x = 1L; // see "METAFILE NOTE"
  2424. pt.y = 0L;
  2425. if (SetWindowOrgEx(HDC32(parg16->f1),
  2426. INT32(parg16->f2),
  2427. INT32(parg16->f3),
  2428. &pt)) {
  2429. ul = (WORD)pt.x | (pt.y << 16);
  2430. }
  2431. FREEARGPTR(parg16);
  2432. RETURN(ul);
  2433. }
  2434. ULONG FASTCALL WG32StretchDIBits(PVDMFRAME pFrame)
  2435. {
  2436. ULONG ul = 0L;
  2437. PBYTE pb10;
  2438. STACKBMI32 bmi32;
  2439. LPBITMAPINFO lpbmi32;
  2440. register PSTRETCHDIBITS16 parg16;
  2441. GETARGPTR(pFrame, sizeof(STRETCHDIBITS16), parg16);
  2442. GETMISCPTR(parg16->f10, pb10);
  2443. lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f11),
  2444. (LPBITMAPINFO)&bmi32,
  2445. FETCHWORD(parg16->f12));
  2446. // see if we need to adjust the image sze for RLE bitmaps
  2447. if(lpbmi32 && pb10) {
  2448. if((lpbmi32->bmiHeader.biCompression == BI_RLE4) ||
  2449. (lpbmi32->bmiHeader.biCompression == BI_RLE8)) {
  2450. if(lpbmi32->bmiHeader.biSizeImage == 0) {
  2451. lpbmi32->bmiHeader.biSizeImage =
  2452. Get_RLE_Compression_Size(lpbmi32->bmiHeader.biCompression,
  2453. pb10,
  2454. parg16->f10);
  2455. }
  2456. }
  2457. }
  2458. ul = GETINT16(StretchDIBits(HDC32(parg16->f1),
  2459. INT32(parg16->f2),
  2460. INT32(parg16->f3),
  2461. INT32(parg16->f4),
  2462. INT32(parg16->f5),
  2463. INT32(parg16->f6),
  2464. INT32(parg16->f7),
  2465. INT32(parg16->f8),
  2466. INT32(parg16->f9),
  2467. pb10,
  2468. lpbmi32,
  2469. (DWORD)FETCHWORD(parg16->f12),
  2470. DWORD32(parg16->f13)));
  2471. WOW32APIWARN (ul, "WG32StretchDIBits\n");
  2472. FREEMISCPTR(pb10);
  2473. FREEARGPTR(parg16);
  2474. RETURN(ul);
  2475. }
  2476. //
  2477. // This routine calls back the apps SetAbortProc routine.
  2478. //
  2479. LONG W32AbortProc(HDC hPr, int code)
  2480. {
  2481. LONG lReturn;
  2482. PARM16 Parm16;
  2483. register PTD ptd;
  2484. DWORD AbortProcT;
  2485. ptd = CURRENTPTD();
  2486. WOW32ASSERT(ptd->htask16);
  2487. AbortProcT = ((PTDB)SEGPTR(ptd->htask16, 0))->TDB_vpfnAbortProc;
  2488. if (AbortProcT) {
  2489. Parm16.SetAbortProc.hPr = GETHDC16(hPr);
  2490. Parm16.SetAbortProc.code = (SHORT) code;
  2491. CallBack16(RET_SETABORTPROC,
  2492. &Parm16,
  2493. AbortProcT,
  2494. (PVPVOID)&lReturn);
  2495. lReturn = (LONG)LOWORD(lReturn); // Returns a BOOL
  2496. }
  2497. else {
  2498. lReturn = (LONG)TRUE;
  2499. }
  2500. return (lReturn);
  2501. }
  2502. // note: cb is the number of data bytes in lpData NOT including the USHORT byte
  2503. // count at the start of the data stream. In other words, lpData contains
  2504. // cb + sizeof(USHORT) bytes.
  2505. LONG HandleFormFeedHack(HDC hdc, LPBYTE lpdata, int cb)
  2506. {
  2507. int cbBytes;
  2508. LONG ul;
  2509. PFORMFEEDHACK pCur;
  2510. // look for a node with a pointer to a data stream buffer from the previous
  2511. // call to Escape(,,PASSTHROUGH,,)...
  2512. pCur = FindFormFeedHackNode(hdc);
  2513. // if we found one, it's time to send the data stream to the printer...
  2514. if(pCur) {
  2515. // ...time to send it to the printer
  2516. ul = GETINT16(Escape(hdc,
  2517. PASSTHROUGH,
  2518. pCur->cbBytes + sizeof(USHORT),
  2519. pCur->lpBytes,
  2520. NULL));
  2521. // free the current node
  2522. FreeFormFeedHackNode(pCur);
  2523. // if there was a problem we're done
  2524. if(ul <= 0) {
  2525. return(ul);
  2526. }
  2527. }
  2528. // send everything up to the last form feed in the new data stream
  2529. cbBytes = cb;
  2530. lpdata = SendFrontEndOfDataStream(hdc, lpdata, &cbBytes, &ul);
  2531. // if there was a problem
  2532. // OR if the entire data stream got sent since it didn't contain a formfeed
  2533. // -- we're done
  2534. if(lpdata == NULL) {
  2535. return(ul); // this will contain error code OR number of bytes sent
  2536. }
  2537. // else create a node for this data stream
  2538. else {
  2539. pCur = CreateFormFeedHackNode(hdc, cbBytes, lpdata);
  2540. // if we can't allocate a new node...
  2541. if(pCur == NULL) {
  2542. // Things are in pretty bad shape if we get to here...
  2543. // We need to write the byte count at the front of the data stream.
  2544. // Remember lpdata had a word size byte count at the front of it
  2545. // when it was sent to us.
  2546. // if any bytes got sent via SendFrontEndOfDataStream()...
  2547. if(cbBytes < cb) {
  2548. // ...first we need to word align this for Escape32()...
  2549. if((DWORD)lpdata & 0x00000001) {
  2550. lpdata--;
  2551. *lpdata = '\0'; // stick a harmless char in the stream
  2552. cbBytes++; // ...and account for it
  2553. }
  2554. // ...adjust the data stream ptr to accomodate the byte count...
  2555. lpdata -= sizeof(USHORT);
  2556. }
  2557. // ...write in the byte count...
  2558. *(UNALIGNED USHORT *)lpdata = (USHORT)cbBytes;
  2559. // ...and send the remainder of the data stream to the printer.
  2560. // If an extra page gets sent to the printer, too bad.
  2561. ul = GETINT16(Escape(hdc,
  2562. PASSTHROUGH,
  2563. cbBytes + sizeof(USHORT),
  2564. lpdata,
  2565. NULL));
  2566. // if the was an error, return it to the app
  2567. if(ul <= 0) {
  2568. return(ul);
  2569. }
  2570. // else we managed to get everything sent to the printer OK
  2571. else {
  2572. return(cb); // return the number of bytes the app sent
  2573. }
  2574. }
  2575. }
  2576. // return the number of bytes the app requested to send
  2577. return(cb);
  2578. }
  2579. LPBYTE SendFrontEndOfDataStream(HDC hdc, LPBYTE lpData, int *cb, LONG *ul)
  2580. {
  2581. int diff;
  2582. LPBYTE lpByte, lpStart;
  2583. // if there's no data or a bad cb, just send it so we can get the error code
  2584. if((lpData == NULL) || (*cb <= 0)) {
  2585. *ul = GETINT16(Escape(hdc,
  2586. PASSTHROUGH,
  2587. *cb + sizeof(USHORT),
  2588. lpData,
  2589. NULL));
  2590. return(NULL);
  2591. }
  2592. // find the start of the actual data after the byte count
  2593. lpStart = lpData + sizeof(USHORT);
  2594. // look for a formfeed char at or near the end of the data stream
  2595. lpByte = lpStart + ((*cb - 1) * sizeof(BYTE));
  2596. while(lpByte >= lpStart) {
  2597. // if we have found the odious formfeed char....
  2598. if((UCHAR)(*lpByte) == 0x0c) {
  2599. diff = lpByte - lpStart;
  2600. // send everything in the stream up to (but not incl) the formfeed
  2601. if(diff) {
  2602. // adjust the byte count in the data stream
  2603. *(UNALIGNED USHORT *)lpData = (USHORT)diff;
  2604. // send it to the printer
  2605. *ul = GETINT16(Escape(hdc,
  2606. PASSTHROUGH,
  2607. diff + sizeof(USHORT),
  2608. lpData,
  2609. NULL));
  2610. // if there was a problem, return it to the app
  2611. if(*ul <= 0) {
  2612. return(NULL);
  2613. }
  2614. }
  2615. // else formfeed is the first char in the data stream
  2616. else {
  2617. *ul = *cb; // just lie and say we sent it all
  2618. }
  2619. // adjust the remaining number of bytes
  2620. *cb -= diff;
  2621. // return ptr to the formfeed char as new start of data stream
  2622. return(lpByte);
  2623. }
  2624. lpByte--;
  2625. }
  2626. // if there are no formfeed's in the data stream just send the whole thing
  2627. *ul = GETINT16(Escape(hdc,
  2628. PASSTHROUGH,
  2629. *cb + sizeof(USHORT),
  2630. lpData,
  2631. NULL));
  2632. return(NULL); // specify we sent the whole thing
  2633. }
  2634. // note: this assumes that if there is a node, there is a list
  2635. void FreeFormFeedHackNode(PFORMFEEDHACK pNode)
  2636. {
  2637. PFORMFEEDHACK pCur, pPrev, pListStart;
  2638. pPrev = NULL;
  2639. pCur = pListStart = gpFormFeedHackList;
  2640. // if there is a node, there must be a node list
  2641. WOW32ASSERT(pCur);
  2642. if(pNode) {
  2643. while(pCur) {
  2644. if(pCur == pNode) {
  2645. if(pNode->lpBytes) {
  2646. free_w(pNode->lpBytes);
  2647. }
  2648. if(pPrev) {
  2649. pPrev->next = pCur->next;
  2650. }
  2651. else {
  2652. pListStart = pCur->next;
  2653. }
  2654. free_w(pNode);
  2655. break;
  2656. }
  2657. else {
  2658. pPrev = pCur;
  2659. pCur = pCur->next;
  2660. }
  2661. }
  2662. }
  2663. gpFormFeedHackList = pListStart;
  2664. }
  2665. void FreeTaskFormFeedHacks(HAND16 h16)
  2666. {
  2667. PFORMFEEDHACK pNext, pCur;
  2668. pCur = gpFormFeedHackList;
  2669. while(pCur) {
  2670. if(pCur->hTask16 == h16) {
  2671. // we already told the app we sent this so give it one last try
  2672. Escape(pCur->hdc,
  2673. PASSTHROUGH,
  2674. pCur->cbBytes + sizeof(USHORT),
  2675. pCur->lpBytes,
  2676. NULL);
  2677. pNext = pCur->next;
  2678. if(pCur->lpBytes) {
  2679. free_w(pCur->lpBytes);
  2680. }
  2681. if(pCur == gpFormFeedHackList) {
  2682. gpFormFeedHackList = pNext;
  2683. }
  2684. free_w(pCur);
  2685. pCur = pNext;
  2686. }
  2687. }
  2688. }
  2689. // this should only be called by Escape(,,ENDDOC,,)
  2690. void SendFormFeedHack(HDC hdc)
  2691. {
  2692. int cb;
  2693. LPBYTE pBytes = NULL;
  2694. PFORMFEEDHACK pCur;
  2695. pCur = gpFormFeedHackList;
  2696. while(pCur) {
  2697. if(pCur->hdc == hdc) {
  2698. if(pCur->lpBytes) {
  2699. cb = pCur->cbBytes;
  2700. // point to actual data after byte count
  2701. pBytes = pCur->lpBytes + sizeof(USHORT);
  2702. // strip the form feed from the buffered data stream...
  2703. if((UCHAR)(*pBytes) == 0x0c) {
  2704. *pBytes = '\0';
  2705. pBytes++;
  2706. cb--;
  2707. }
  2708. // strip the carriage ret from the buffered data stream...
  2709. // (some apps put a carriage return after the last formfeed)
  2710. if((UCHAR)(*pBytes) == 0x0d) {
  2711. *pBytes = '\0';
  2712. cb--;
  2713. }
  2714. // ...and send it to the printer
  2715. if(cb > 0) {
  2716. Escape(hdc,
  2717. PASSTHROUGH,
  2718. cb + sizeof(USHORT),
  2719. pCur->lpBytes,
  2720. NULL);
  2721. }
  2722. }
  2723. // free this node from the hack list now
  2724. FreeFormFeedHackNode(pCur);
  2725. break;
  2726. }
  2727. pCur = pCur->next;
  2728. }
  2729. }
  2730. PFORMFEEDHACK FindFormFeedHackNode(HDC hdc)
  2731. {
  2732. PFORMFEEDHACK pCur;
  2733. pCur = gpFormFeedHackList;
  2734. while(pCur) {
  2735. if(pCur->hdc == hdc) {
  2736. return(pCur);
  2737. }
  2738. pCur = pCur->next;
  2739. }
  2740. return(NULL);
  2741. }
  2742. // this will only get called if PART of the data stream got sent to the printer
  2743. PFORMFEEDHACK CreateFormFeedHackNode(HDC hdc, int cb, LPBYTE lpData)
  2744. {
  2745. LPBYTE pBytes;
  2746. PFORMFEEDHACK pNode;
  2747. // allocate a new node
  2748. pNode = malloc_w(sizeof(FORMFEEDHACK));
  2749. // if we were able to get one...
  2750. if(pNode) {
  2751. // ...allocate a buffer for the data stream
  2752. pBytes = malloc_w(cb + sizeof(USHORT));
  2753. // if we were able to get one...
  2754. if(pBytes) {
  2755. // ...fill in the node...
  2756. pNode->hdc = hdc;
  2757. pNode->lpBytes = pBytes;
  2758. pNode->cbBytes = cb;
  2759. pNode->hTask16 = CURRENTPTD()->htask16;
  2760. // ...and stick the new node at the front of the node list
  2761. pNode->next = gpFormFeedHackList;
  2762. gpFormFeedHackList = pNode;
  2763. // add the new size to the front of the data stream
  2764. *(UNALIGNED USHORT *)pBytes = (USHORT)cb;
  2765. pBytes += sizeof(USHORT);
  2766. // copy the the data stream into the node buffer
  2767. RtlCopyMemory(pBytes, lpData, cb);
  2768. return(pNode);
  2769. }
  2770. // else if we couldn't get a data stream buffer...
  2771. else {
  2772. free_w(pNode);
  2773. }
  2774. }
  2775. return(NULL); // return NULL if either allocate failed
  2776. }
  2777. // this should only be called by Escape(,,AbortDOC,,) and AbortDoc()
  2778. void RemoveFormFeedHack(HDC hdc)
  2779. {
  2780. PFORMFEEDHACK pNode;
  2781. pNode = FindFormFeedHackNode(hdc);
  2782. if(pNode) {
  2783. FreeFormFeedHackNode(pNode);
  2784. }
  2785. }
  2786. #ifdef FE_SB //GetFontAssocStatus, pisuih, 10/5/94'
  2787. int GetFontAssocStatus(HDC hdc); //Modified by bklee. 02/01/95
  2788. ULONG FASTCALL WG32GetFontAssocStatus(PVDMFRAME pFrame)
  2789. {
  2790. ULONG ul;
  2791. register PGETFONTASSOCSTATUS16 parg16;
  2792. GETARGPTR(pFrame, sizeof(GETFONTASSOCSTATUS16), parg16);
  2793. ul = GetFontAssocStatus(HDC32(parg16->f1));
  2794. FREEARGPTR(parg16);
  2795. RETURN (ul);
  2796. }
  2797. #endif //FE_SB
  2798. /*+++
  2799. This returns the number of bytes in RLE4 and RLE8 compressed bitmaps.
  2800. Code below fixes problems in Sounditoutland with RLE-encoded
  2801. bitmaps which have biSizeImage == 0. On Win 3.1 they work since
  2802. gdi is happy with decoding some piece of memory. NT GDI however
  2803. needs to know the size of bits passed. We remedy this by calculating
  2804. size using RET_GETDIBSIZE (GetSelectorLimit). GDI won't copy the
  2805. memory, it will just use size as indication of accessibility
  2806. Applications: "Sound It Out Land", QuarkXpress, KidPhonics
  2807. ---*/
  2808. ULONG Get_RLE_Compression_Size(DWORD RLE_Type, PBYTE pStart, VPVOID vpBytes)
  2809. {
  2810. BOOL bDone = FALSE;
  2811. PBYTE pBytes = pStart;
  2812. PARM16 Parm16;
  2813. ULONG ulSelectorLimit;
  2814. LONG lSize;
  2815. if(pBytes && vpBytes) {
  2816. Parm16.WndProc.wParam = HIWORD(vpBytes);
  2817. // get # bytes allocated to the selector (this even works for huge)
  2818. CallBack16(RET_GETDIBSIZE, &Parm16, 0, (PVPVOID)&ulSelectorLimit);
  2819. // is the selector valid?
  2820. if(ulSelectorLimit != 0 && ulSelectorLimit != 0xffffffff) {
  2821. // max byte buffer = memory block size - starting offset
  2822. lSize = (LONG)ulSelectorLimit - LOWORD(vpBytes) + 1;
  2823. } else {
  2824. LOGDEBUG(LOG_ALWAYS, ("WOW:Get_RLE_Compression_Size: Selector [ptr:%x] is invalid\n", (DWORD)vpBytes));
  2825. return(0);
  2826. }
  2827. while (!bDone) {
  2828. // if absolute mode
  2829. if (*pBytes == 0) {
  2830. switch (pBytes[1]) {
  2831. case 0: // end of line
  2832. pBytes += 2;
  2833. break;
  2834. case 1: // end of bitmap
  2835. pBytes += 2;
  2836. bDone = TRUE;
  2837. break;
  2838. case 2: // offset
  2839. pBytes += 4;
  2840. break;
  2841. default:
  2842. // align the bytes to word boundries
  2843. if(RLE_Type == BI_RLE4) {
  2844. pBytes += ((2 + ((pBytes[1] + 3) / 2)) & ~1);
  2845. } else {
  2846. pBytes += ((2 + pBytes[1] + 1) & ~1);
  2847. }
  2848. break;
  2849. }
  2850. } else { // else encoded mode
  2851. pBytes += 2;
  2852. }
  2853. // are we past the end of the selector?
  2854. if ( lSize < (pBytes - pStart + 1) ) {
  2855. LOGDEBUG(LOG_ALWAYS, ("WOW:Get_RLE_Compression_Size:Bad RLE size: %x < %x\n", lSize, (pBytes - pStart)));
  2856. return(lSize);
  2857. }
  2858. }
  2859. }
  2860. return((ULONG)(pBytes - pStart));
  2861. }