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.

2976 lines
87 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: MfRec16.c
  3. *
  4. * Copyright (c) 1991-1999 Microsoft Corporation
  5. *
  6. * DESCRIPTIVE NAME: Metafile Recorder
  7. *
  8. * FUNCTION: Records GDI functions in memory and disk metafiles.
  9. *
  10. * PUBLIC ENTRY POINTS:
  11. * CloseMetaFile
  12. * CopyMetaFile
  13. * CreateMetaFile
  14. * GetMetaFileBitsEx
  15. * SetMetaFileBitsEx
  16. * PRIVATE ENTRY POINTS:
  17. * RecordParms
  18. * AttemptWrite
  19. * MarkMetaFile
  20. * RecordObject
  21. * ProbeSize
  22. * AddObjectToDCTable
  23. *
  24. * History:
  25. * 02-Jul-1991 -by- John Colleran [johnc]
  26. * Combined From Win 3.1 and WLO 1.0 sources
  27. \***************************************************************************/
  28. #include "precomp.h"
  29. #pragma hdrstop
  30. #include "mf16.h"
  31. UINT AddObjectToDCTable(HDC hdc, HANDLE hObject, PUINT piPosition, BOOL bRealAdd);
  32. BOOL AddDCToObjectMetaList16(HDC hMeta16DC, HANDLE hObject);
  33. BOOL AttemptWrite(PMFRECORDER16 pMFRec, DWORD dwBytes, LPBYTE lpData);
  34. VOID MarkMetaFile(PMFRECORDER16 pMFRec);
  35. BOOL MakeLogPalette(HDC hdc, HANDLE hPal, WORD magic);
  36. HANDLE ProbeSize(PMFRECORDER16 pMF, DWORD dwLength);
  37. BOOL RecordCommonBitBlt(HDC hdcDest, INT x, INT y, INT nWidth, INT nHeight,
  38. HDC hdcSrc, INT xSrc, INT ySrc, INT nSrcWidth, INT nSrcHeight,
  39. DWORD rop, WORD wFunc);
  40. BOOL UnlistObjects(HDC hMetaDC);
  41. BOOL MF16_DeleteRgn(HDC hdc, HANDLE hrgn);
  42. // Metafile Logging stubs for 3.x Metafiles
  43. /******************************Public*Routine******************************\
  44. * XXX_RecordParms
  45. *
  46. * These routines package up the parameters of an NT GDI call and send
  47. * them to a general purpose recording routine that validates the metafile
  48. * DC and records the parameters.
  49. *
  50. * Returns
  51. * TRUE iff successful
  52. *
  53. * Warnings
  54. * Windows 3.x metafile behavior is that when a function is being metafiled
  55. * the routine itself is not called; eg SetPixel does not call GreSetPixel
  56. * but (GDI) SetPixel intercepts the calls and records the parameters and
  57. * returns without taking further action
  58. *
  59. * History:
  60. * 24-Nov-1991 -by- John Colleran [johnc]
  61. * Wrote it.
  62. \**************************************************************************/
  63. BOOL MF16_RecordParms1(HDC hdc, WORD Func)
  64. {
  65. return RecordParms(hdc, Func, 0, (LPWORD)NULL);
  66. }
  67. BOOL MF16_RecordParms2(HDC hdc, INT parm2, WORD Func)
  68. {
  69. return RecordParms(hdc, Func, 1, (LPWORD)&parm2);
  70. }
  71. BOOL MF16_RecordParms3(HDC hdc, INT parm2, INT parm3, WORD Func)
  72. {
  73. WORD aw[2];
  74. aw[0] = (WORD)parm3;
  75. aw[1] = (WORD)parm2;
  76. return RecordParms(hdc, Func, 2, aw);
  77. }
  78. BOOL MF16_RecordParms5(HDC hdc, INT parm2, INT parm3, INT parm4, INT parm5, WORD Func)
  79. {
  80. WORD aw[4];
  81. aw[0] = (WORD)parm5;
  82. aw[1] = (WORD)parm4;
  83. aw[2] = (WORD)parm3;
  84. aw[3] = (WORD)parm2;
  85. return RecordParms(hdc, Func, 4, aw);
  86. }
  87. BOOL MF16_RecordParms7(HDC hdc, INT parm2, INT parm3, INT parm4, INT parm5, INT parm6, INT parm7, WORD Func)
  88. {
  89. WORD aw[6];
  90. aw[0] = (WORD)parm7;
  91. aw[1] = (WORD)parm6;
  92. aw[2] = (WORD)parm5;
  93. aw[3] = (WORD)parm4;
  94. aw[4] = (WORD)parm3;
  95. aw[5] = (WORD)parm2;
  96. return RecordParms(hdc, Func, 6, aw);
  97. }
  98. BOOL MF16_RecordParms9(HDC hdc, INT parm2, INT parm3, INT parm4, INT parm5,
  99. INT parm6, INT parm7, INT parm8, INT parm9, WORD Func)
  100. {
  101. WORD aw[8];
  102. aw[0] = (WORD)parm9;
  103. aw[1] = (WORD)parm8;
  104. aw[2] = (WORD)parm7;
  105. aw[3] = (WORD)parm6;
  106. aw[4] = (WORD)parm5;
  107. aw[5] = (WORD)parm4;
  108. aw[6] = (WORD)parm3;
  109. aw[7] = (WORD)parm2;
  110. return RecordParms(hdc, Func, 8, aw);
  111. }
  112. BOOL MF16_RecordParmsD(HDC hdc, DWORD d1, WORD Func)
  113. {
  114. return RecordParms(hdc, Func, 2, (LPWORD) &d1);
  115. }
  116. BOOL MF16_RecordParmsWWD(HDC hdc, WORD w1, WORD w2, DWORD d3, WORD Func)
  117. {
  118. WORD aw[4];
  119. aw[0] = LOWORD(d3);
  120. aw[1] = HIWORD(d3);
  121. aw[2] = w2;
  122. aw[3] = w1;
  123. return RecordParms(hdc, Func, 4, aw);
  124. }
  125. BOOL MF16_RecordParmsWWDW(HDC hdc, WORD w1, WORD w2, DWORD d3, WORD w4, WORD Func)
  126. {
  127. WORD aw[5];
  128. aw[0] = w4;
  129. aw[1] = LOWORD(d3);
  130. aw[2] = HIWORD(d3);
  131. aw[3] = w2;
  132. aw[4] = w1;
  133. return RecordParms(hdc, Func, 5, aw);
  134. }
  135. BOOL MF16_RecordParmsWWWWD(HDC hdc, WORD w1, WORD w2, WORD w3, WORD w4, DWORD d5, WORD Func)
  136. {
  137. WORD aw[6];
  138. aw[0] = LOWORD(d5);
  139. aw[1] = HIWORD(d5);
  140. aw[2] = w4;
  141. aw[3] = w3;
  142. aw[4] = w2;
  143. aw[5] = w1;
  144. return RecordParms(hdc, Func, 6, aw);
  145. }
  146. BOOL MF16_RecordParmsPoly(HDC hdc, LPPOINT lpPoint, INT nCount, WORD Func)
  147. {
  148. BOOL fRet;
  149. LPWORD lpW,lpT;
  150. DWORD cw;
  151. INT ii;
  152. cw = (nCount*sizeof(POINTS)/sizeof(WORD))+1;
  153. lpT = lpW = (LPWORD)LocalAlloc(LMEM_FIXED, cw*sizeof(WORD));
  154. if (!lpW)
  155. return(FALSE);
  156. *lpW++ = (WORD)nCount;
  157. for(ii=0; ii<nCount; ii++)
  158. {
  159. *lpW++ = (WORD)lpPoint[ii].x;
  160. *lpW++ = (WORD)lpPoint[ii].y;
  161. }
  162. fRet = RecordParms(hdc, Func, cw, lpT);
  163. if (LocalFree((HANDLE)lpT))
  164. ASSERTGDI(FALSE, "MF16_RecordParmsPoly: LocalFree Failed\n");
  165. return (fRet);
  166. }
  167. // SetDIBitsToDevice
  168. // StretchDIBits
  169. BOOL MF16_RecordDIBits
  170. (
  171. HDC hdcDst,
  172. int xDst,
  173. int yDst,
  174. int cxDst,
  175. int cyDst,
  176. int xDib,
  177. int yDib,
  178. int cxDib,
  179. int cyDib,
  180. DWORD iStartScan,
  181. DWORD cScans,
  182. DWORD cbBitsDib,
  183. CONST VOID * pBitsDib,
  184. DWORD cbBitsInfoDib,
  185. CONST BITMAPINFO *pBitsInfoDib,
  186. DWORD iUsageDib,
  187. DWORD rop,
  188. DWORD mrType
  189. )
  190. {
  191. BOOL fRet;
  192. LPWORD lpW;
  193. LPWORD lpWStart;
  194. WORD cwParms;
  195. PBMIH lpDIBInfoHeader;
  196. PUTS("MF16_RecrodDIBits\n");
  197. ASSERTGDI(mrType == META_SETDIBTODEV || mrType == META_STRETCHDIB,
  198. "MF16_RecrodDIBits: Bad mrType");
  199. // Get the number of parameters to save.
  200. cwParms = (WORD) ((mrType == META_SETDIBTODEV) ? 9 : 11); // in words
  201. // Allocate space for DIB plus parameters.
  202. lpWStart = lpW = (LPWORD) LocalAlloc(LMEM_FIXED,
  203. cbBitsInfoDib + (cbBitsDib + 1) / 2 * 2 + cwParms*sizeof(WORD));
  204. if (!lpW)
  205. {
  206. ERROR_ASSERT(FALSE, "MF16_RecordDIBits: out of memory\n");
  207. return(FALSE);
  208. }
  209. // Copy the parameters.
  210. if (mrType == META_SETDIBTODEV)
  211. {
  212. *lpW++ = (WORD) iUsageDib;
  213. *lpW++ = (WORD) cScans;
  214. *lpW++ = (WORD) iStartScan;
  215. *lpW++ = (WORD) yDib;
  216. *lpW++ = (WORD) xDib;
  217. *lpW++ = (WORD) cyDib;
  218. *lpW++ = (WORD) cxDib;
  219. *lpW++ = (WORD) yDst;
  220. *lpW++ = (WORD) xDst;
  221. }
  222. else
  223. {
  224. *lpW++ = (WORD) LOWORD(rop);
  225. *lpW++ = (WORD) HIWORD(rop);
  226. *lpW++ = (WORD) iUsageDib;
  227. *lpW++ = (WORD) cyDib;
  228. *lpW++ = (WORD) cxDib;
  229. *lpW++ = (WORD) yDib;
  230. *lpW++ = (WORD) xDib;
  231. *lpW++ = (WORD) cyDst;
  232. *lpW++ = (WORD) cxDst;
  233. *lpW++ = (WORD) yDst;
  234. *lpW++ = (WORD) xDst;
  235. }
  236. // Save the start of the bitmap info header field.
  237. lpDIBInfoHeader = (LPBITMAPINFOHEADER) lpW;
  238. // cbBitsInfoDib must be word sized
  239. ASSERTGDI(cbBitsInfoDib % 2 == 0,
  240. "MF16_RecordDIBits: cbBitsInfoDib is not word aligned");
  241. // Copy dib info if given.
  242. if (cbBitsInfoDib)
  243. {
  244. if (pBitsInfoDib->bmiHeader.biSize == sizeof(BMCH))
  245. {
  246. CopyCoreToInfoHeader
  247. (
  248. lpDIBInfoHeader,
  249. (LPBITMAPCOREHEADER) pBitsInfoDib
  250. );
  251. if (iUsageDib == DIB_RGB_COLORS)
  252. {
  253. RGBQUAD *prgbq;
  254. RGBTRIPLE *prgbt;
  255. UINT ui;
  256. prgbq = ((PBMI) lpDIBInfoHeader)->bmiColors;
  257. prgbt = ((PBMC) pBitsInfoDib)->bmciColors;
  258. ASSERTGDI(cbBitsInfoDib >= sizeof(BMIH),
  259. "MF16_RecordDIBits: Bad cbBitsInfoDib size");
  260. for
  261. (
  262. ui = (UINT) (cbBitsInfoDib - sizeof(BMIH))
  263. / sizeof(RGBQUAD);
  264. ui;
  265. ui--
  266. )
  267. {
  268. prgbq->rgbBlue = prgbt->rgbtBlue;
  269. prgbq->rgbGreen = prgbt->rgbtGreen;
  270. prgbq->rgbRed = prgbt->rgbtRed;
  271. prgbq->rgbReserved = 0;
  272. prgbq++; prgbt++;
  273. }
  274. }
  275. else
  276. {
  277. RtlCopyMemory
  278. (
  279. (PBYTE) lpDIBInfoHeader + sizeof(BMIH),
  280. (PBYTE) pBitsInfoDib + sizeof(BMCH),
  281. cbBitsInfoDib - sizeof(BMIH)
  282. );
  283. }
  284. }
  285. else
  286. {
  287. RtlCopyMemory
  288. (
  289. (PBYTE) lpDIBInfoHeader,
  290. (PBYTE) pBitsInfoDib,
  291. cbBitsInfoDib
  292. );
  293. if (pBitsInfoDib->bmiHeader.biBitCount >= 16)
  294. {
  295. DWORD UNALIGNED *pClrUsed = (DWORD UNALIGNED *)&lpDIBInfoHeader->biClrUsed;
  296. *pClrUsed = 0;
  297. }
  298. }
  299. }
  300. // Copy dib bits.
  301. RtlCopyMemory((PBYTE) lpDIBInfoHeader + cbBitsInfoDib, pBitsDib, cbBitsDib);
  302. // Finally record the parameters into the file.
  303. fRet = RecordParms(hdcDst, mrType,
  304. cwParms + (cbBitsInfoDib + cbBitsDib + 1) / sizeof(WORD),
  305. lpWStart);
  306. if (lpWStart)
  307. if (LocalFree((HANDLE) lpWStart))
  308. ASSERTGDI(FALSE, "MF16_RecordDIBits: LocalFree Failed\n");
  309. return(fRet);
  310. }
  311. BOOL MF16_BitBlt(HDC hdcDest, INT x, INT y, INT nWidth, INT nHeight,
  312. HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop)
  313. {
  314. WORD aw[9];
  315. // This is how windows works but really it should look at the ROP
  316. if (hdcDest == hdcSrc || hdcSrc == NULL)
  317. {
  318. aw[0] = (WORD)LOWORD(rop);
  319. aw[1] = (WORD)HIWORD(rop);
  320. aw[2] = (WORD)ySrc;
  321. aw[3] = (WORD)xSrc;
  322. aw[4] = (WORD)0; // No DC necessary
  323. aw[5] = (WORD)nHeight;
  324. aw[6] = (WORD)nWidth;
  325. aw[7] = (WORD)y;
  326. aw[8] = (WORD)x;
  327. return(RecordParms(hdcDest, META_DIBBITBLT, 9, aw));
  328. }
  329. else
  330. return(RecordCommonBitBlt(hdcDest,x,y,nWidth,nHeight,hdcSrc,
  331. xSrc,ySrc,nWidth,nHeight,rop,META_DIBBITBLT));
  332. }
  333. BOOL MF16_StretchBlt(HDC hdcDest, INT x, INT y, INT nWidth, INT nHeight,
  334. HDC hdcSrc, INT xSrc, INT ySrc, INT nSrcWidth, INT nSrcHeight, DWORD rop)
  335. {
  336. WORD aw[11];
  337. // This is how windows works but really it should look at the ROP
  338. if (hdcDest == hdcSrc || hdcSrc == NULL)
  339. {
  340. aw[0] = (WORD)LOWORD(rop);
  341. aw[1] = (WORD)HIWORD(rop);
  342. aw[2] = (WORD)nSrcHeight;
  343. aw[3] = (WORD)nSrcWidth;
  344. aw[4] = (WORD)ySrc;
  345. aw[5] = (WORD)xSrc;
  346. aw[6] = (WORD)0; // No DC necessary
  347. aw[7] = (WORD)nHeight;
  348. aw[8] = (WORD)nWidth;
  349. aw[9] = (WORD)y;
  350. aw[10] = (WORD)x;
  351. return(RecordParms(hdcDest, META_DIBSTRETCHBLT, 11, aw));
  352. }
  353. else
  354. return(RecordCommonBitBlt(hdcDest,x,y,nWidth,nHeight,hdcSrc,
  355. xSrc,ySrc,nSrcWidth,nSrcHeight,rop,META_DIBSTRETCHBLT));
  356. }
  357. BOOL RecordCommonBitBlt(HDC hdcDest, INT x, INT y, INT nWidth, INT nHeight,
  358. HDC hdcSrc, INT xSrc, INT ySrc, INT nSrcWidth, INT nSrcHeight, DWORD rop,
  359. WORD wFunc)
  360. {
  361. BOOL fRet = FALSE;
  362. HBITMAP hBitmap;
  363. LPWORD lpW;
  364. LPWORD lpWStart = (LPWORD) NULL;
  365. WORD cwParms;
  366. BMIH bmih;
  367. DWORD cbBitsInfo;
  368. DWORD cbBits;
  369. PBMIH lpDIBInfoHeader;
  370. // hdcSrc must be a memory DC.
  371. if (GetObjectType((HANDLE)hdcSrc) != OBJ_MEMDC)
  372. {
  373. ERROR_ASSERT(FALSE, "RecordCommonBitblt hdcSrc must be MEMDC\n");
  374. GdiSetLastError(ERROR_INVALID_HANDLE);
  375. return(FALSE);
  376. }
  377. // Retrieve the source bitmap.
  378. hBitmap = SelectObject(hdcSrc, GetStockObject(PRIV_STOCK_BITMAP));
  379. ERROR_ASSERT(hBitmap, "RecordCommonBitblt: SelectObject1 failed\n");
  380. // Get the bitmap info header and sizes.
  381. if (!bMetaGetDIBInfo(hdcSrc, hBitmap, &bmih,
  382. &cbBitsInfo, &cbBits, DIB_RGB_COLORS, 0, TRUE))
  383. goto RecordCommonBitBlt_exit;
  384. // Get the number of parameters to save.
  385. cwParms = (WORD) ((wFunc == META_DIBSTRETCHBLT) ? 10 : 8); // in words
  386. // Allocate space for DIB plus parameters.
  387. lpWStart = lpW = (LPWORD) LocalAlloc(LMEM_FIXED,
  388. cbBitsInfo + cbBits + cwParms*sizeof(WORD));
  389. if (!lpW)
  390. {
  391. ERROR_ASSERT(FALSE, "RecordCommonBitblt: out of memory\n");
  392. goto RecordCommonBitBlt_exit;
  393. }
  394. // Copy the parameters.
  395. *lpW++ = (WORD)LOWORD(rop);
  396. *lpW++ = (WORD)HIWORD(rop);
  397. if (wFunc == META_DIBSTRETCHBLT)
  398. {
  399. *lpW++ = (WORD)nSrcHeight;
  400. *lpW++ = (WORD)nSrcWidth;
  401. }
  402. *lpW++ = (WORD)ySrc;
  403. *lpW++ = (WORD)xSrc;
  404. *lpW++ = (WORD)nHeight;
  405. *lpW++ = (WORD)nWidth;
  406. *lpW++ = (WORD)y;
  407. *lpW++ = (WORD)x;
  408. // Save the start of the bitmap info header field.
  409. lpDIBInfoHeader = (LPBITMAPINFOHEADER) lpW;
  410. // Copy the bitmap info header.
  411. *lpDIBInfoHeader = bmih;
  412. // Get bitmap info and bits.
  413. if (!GetDIBits(hdcSrc,
  414. hBitmap,
  415. 0,
  416. (UINT) bmih.biHeight,
  417. (LPBYTE) ((PBYTE) lpW + cbBitsInfo),
  418. (LPBITMAPINFO) lpDIBInfoHeader,
  419. DIB_RGB_COLORS))
  420. {
  421. ERROR_ASSERT(FALSE, "RecordCommonBitBlt: GetDIBits2 failed\n");
  422. goto RecordCommonBitBlt_exit;
  423. }
  424. // Finally record the parameters into the file.
  425. fRet = RecordParms(hdcDest, wFunc,
  426. cwParms + (cbBitsInfo + cbBits) / sizeof(WORD),
  427. lpWStart);
  428. RecordCommonBitBlt_exit:
  429. if (lpWStart)
  430. if (LocalFree((HANDLE)lpWStart))
  431. ASSERTGDI(FALSE, "RecordCommonBitBlt: LocalFree Failed\n");
  432. if (!SelectObject(hdcSrc, hBitmap))
  433. ASSERTGDI(FALSE, "RecordCommonBitblt: SelectObject2 failed\n");
  434. return(fRet);
  435. }
  436. BOOL MF16_DeleteRgn(HDC hdc, HANDLE hrgn)
  437. {
  438. UINT pos;
  439. if (AddObjectToDCTable(hdc, hrgn, &pos, FALSE) != 1)
  440. ASSERTGDI(FALSE, "MF16_DeleteRgn: AddObjectToDCTable failed");
  441. return(RecordParms(hdc, META_DELETEOBJECT, 1, (LPWORD)&pos));
  442. }
  443. BOOL MF16_DeleteObject(HANDLE hObject)
  444. {
  445. INT iCurDC;
  446. UINT pos;
  447. UINT iObjType;
  448. PMFRECORDER16 pMFRec;
  449. PMETALINK16 pml16;
  450. pml16 = pmetalink16Get(hObject);
  451. ASSERTGDI(pml16, "MF16_DeleteObject: Metalink is NULL\n");
  452. iObjType = GetObjectType(hObject);
  453. ASSERTGDI(iObjType != OBJ_REGION, "MF16_DeleteObject: region unexpected");
  454. // Delete the object from each metafile DC which references it.
  455. for(iCurDC = pml16->cMetaDC16 - 1; iCurDC >= 0; iCurDC--)
  456. {
  457. // Send a DeleteObject record to each metafile
  458. HDC hdc16 = pml16->ahMetaDC16[iCurDC];
  459. if (!IS_METADC16_TYPE(hdc16))
  460. {
  461. RIP("MF16_DELETEOBJECT: invalid metaDC16\n");
  462. continue;
  463. }
  464. // If the object is not selected then delete it, if it is then mark as predeleted
  465. GET_PMFRECORDER16(pMFRec,hdc16);
  466. if (pMFRec->recCurObjects[iObjType - MIN_OBJ_TYPE] != hObject)
  467. {
  468. if (AddObjectToDCTable(hdc16, hObject, &pos, FALSE) == 1)
  469. RecordParms(hdc16, META_DELETEOBJECT, 1, (LPWORD)&pos);
  470. else
  471. RIP("MF16_DeleteObject Metalink16 and metadc table not in sync\n");
  472. }
  473. else
  474. {
  475. if (pMFRec->metaHeader.mtNoObjects)
  476. {
  477. UINT ii;
  478. POBJECTTABLE pobjt;
  479. pobjt = (POBJECTTABLE) pMFRec->hObjectTable;
  480. for (ii=0; ii < (UINT) pMFRec->metaHeader.mtNoObjects; ii++)
  481. {
  482. if (pobjt[ii].CurHandle == hObject)
  483. {
  484. pobjt[ii].fPreDeleted = TRUE;
  485. break;
  486. }
  487. }
  488. }
  489. }
  490. }
  491. // This Object has been freed from all 3.x metafiles so free its MetaList16
  492. // if the metalink field is in use resize METALINK16
  493. if (pml16->metalink)
  494. {
  495. if (pml16->cMetaDC16 > 1)
  496. pml16 = pmetalink16Resize(hObject,1);
  497. if (pml16 == NULL)
  498. {
  499. ASSERTGDI(FALSE, "MF16_DeleteObject LocalReAlloc failed\n");
  500. return (FALSE);
  501. }
  502. pml16->cMetaDC16 = 0;
  503. pml16->ahMetaDC16[0] = (HDC) 0;
  504. }
  505. else
  506. {
  507. if (!bDeleteMetalink16(hObject))
  508. ASSERTGDI(FALSE, "MF16_DeleteObject LocalFree failed\n");
  509. }
  510. return(TRUE);
  511. }
  512. BOOL MF16_RealizePalette(HDC hdc)
  513. {
  514. HPALETTE hpal;
  515. PMFRECORDER16 pMFRec;
  516. PMETALINK16 pml16;
  517. ASSERTGDI(IS_METADC16_TYPE(hdc),"MF16_RealizePalette - invalid handle\n");
  518. GET_PMFRECORDER16(pMFRec,hdc);
  519. hpal = pMFRec->recCurObjects[OBJ_PAL - MIN_OBJ_TYPE];
  520. ASSERTGDI(hpal, "MF16_RealizePalette: bad hpal\n");
  521. // emit the palette again only if the palette is dirty.
  522. pml16 = pmetalink16Get(hpal);
  523. ASSERTGDI(IS_STOCKOBJ(hpal) || pml16,"MF16_RealizePalette - pml16 == NULL\n");
  524. if (pml16)
  525. {
  526. if (PtrToUlong(pml16->pv) != pMFRec->iPalVer)
  527. if (!MakeLogPalette(hdc, hpal, META_SETPALENTRIES))
  528. return(FALSE);
  529. // record which version of the palette the metafile is synced to.
  530. pMFRec->iPalVer = PtrToUlong(pml16->pv);
  531. }
  532. return(RecordParms(hdc, META_REALIZEPALETTE, 0, (LPWORD)NULL));
  533. }
  534. BOOL MF16_AnimatePalette
  535. (
  536. HPALETTE hpal,
  537. UINT iStart,
  538. UINT cEntries,
  539. CONST PALETTEENTRY *pPalEntries
  540. )
  541. {
  542. INT iCurDC;
  543. PMETALINK16 pml16;
  544. LPWORD lpW,lpT;
  545. DWORD cw;
  546. UINT ii;
  547. PMFRECORDER16 pMFRec;
  548. if (!(pml16 = pmetalink16Get(hpal)))
  549. return(FALSE);
  550. cw = (cEntries * sizeof(PALETTEENTRY) / sizeof(WORD)) + 2;
  551. lpT = lpW = (LPWORD) LocalAlloc(LMEM_FIXED, cw * sizeof(WORD));
  552. if (!lpW)
  553. return(FALSE);
  554. *lpW++ = (WORD) iStart;
  555. *lpW++ = (WORD) cEntries;
  556. for (ii = 0; ii < cEntries; ii++)
  557. ((PPALETTEENTRY) lpW)[ii] = pPalEntries[ii];
  558. // Send a AnimatePalette record to each associated metafile that has the
  559. // palette selected.
  560. for (iCurDC = pml16->cMetaDC16 - 1; iCurDC >= 0; iCurDC--)
  561. {
  562. HDC hdc16 = pml16->ahMetaDC16[iCurDC];
  563. if (!IS_METADC16_TYPE(hdc16))
  564. {
  565. ASSERTGDI(FALSE, "MF16_AnimatePalette: invalid metaDC16\n");
  566. continue;
  567. }
  568. GET_PMFRECORDER16(pMFRec,hdc16);
  569. if (pMFRec->recCurObjects[OBJ_PAL - MIN_OBJ_TYPE] == hpal)
  570. if (!RecordParms(pml16->ahMetaDC16[iCurDC], META_ANIMATEPALETTE, cw, lpT))
  571. ASSERTGDI(FALSE, "MF16_AnimatePalette: RecordParms Failed\n");
  572. }
  573. if (LocalFree((HANDLE) lpT))
  574. ASSERTGDI(FALSE, "MF16_AnimatePalette: LocalFree Failed\n");
  575. return(TRUE);
  576. }
  577. BOOL MF16_ResizePalette(HPALETTE hpal, UINT nCount)
  578. {
  579. INT iCurDC;
  580. PMETALINK16 pml16;
  581. PMFRECORDER16 pMFRec;
  582. if (!(pml16 = pmetalink16Get(hpal)))
  583. return(FALSE);
  584. // Send a ResizePalette record to each associated metafile that has the
  585. // palette selected.
  586. for (iCurDC = pml16->cMetaDC16 - 1; iCurDC >= 0; iCurDC--)
  587. {
  588. HDC hdc16 = pml16->ahMetaDC16[iCurDC];
  589. if (!IS_METADC16_TYPE(hdc16))
  590. {
  591. ASSERTGDI(FALSE, "MF16_ResizePalette: invalid metaDC16\n");
  592. continue;
  593. }
  594. GET_PMFRECORDER16(pMFRec,hdc16);
  595. if (pMFRec->recCurObjects[OBJ_PAL - MIN_OBJ_TYPE] == hpal)
  596. if (!RecordParms(pml16->ahMetaDC16[iCurDC], META_RESIZEPALETTE, 1, (LPWORD) &nCount))
  597. ASSERTGDI(FALSE, "MF16_ResizePalette: RecordParms Failed\n");
  598. }
  599. return(TRUE);
  600. }
  601. BOOL MF16_DrawRgn(HDC hdc, HRGN hrgn, HBRUSH hBrush, INT cx, INT cy, WORD Func)
  602. {
  603. WORD aw[4];
  604. BOOL bRet;
  605. // Each region function has at least a region to record
  606. aw[0] = (WORD)RecordObject(hdc, hrgn);
  607. switch(Func)
  608. {
  609. case META_PAINTREGION:
  610. case META_INVERTREGION:
  611. bRet = RecordParms(hdc, Func, 1, aw);
  612. break;
  613. case META_FILLREGION:
  614. aw[1] = (WORD)RecordObject(hdc, hBrush);
  615. bRet = RecordParms(hdc, Func, 2, aw);
  616. break;
  617. case META_FRAMEREGION:
  618. aw[1] = (WORD)RecordObject(hdc, hBrush);
  619. aw[2] = (WORD)cy;
  620. aw[3] = (WORD)cx;
  621. bRet = RecordParms(hdc, Func, 4, aw);
  622. break;
  623. default:
  624. ASSERTGDI(FALSE, "MF16_DrawRgn: Bad Func\n");
  625. bRet = FALSE;
  626. break;
  627. }
  628. // Delete the metafile region handle in the metafile after use!
  629. // The reason is that a region can be modified (e.g. SetRectRgn)
  630. // between each use and we have to re-record it each time it is used
  631. // unless we use a dirty flag.
  632. if (!MF16_DeleteRgn(hdc, hrgn))
  633. ASSERTGDI(FALSE, "MF16_DrawRgn: MF16_DeleteRgn failed\n");
  634. return(bRet);
  635. }
  636. BOOL MF16_PolyPolygon(HDC hdc, CONST POINT *lpPoint, CONST INT *lpPolyCount, INT nCount)
  637. {
  638. BOOL fRet;
  639. LPWORD lpW,lpT;
  640. DWORD cw;
  641. INT cPt = 0;
  642. INT ii;
  643. for(ii=0; ii<nCount; ii++)
  644. cPt += lpPolyCount[ii];
  645. cw = 1+nCount+(cPt*sizeof(POINTS)/sizeof(WORD));
  646. lpT = lpW = (LPWORD)LocalAlloc(LMEM_FIXED, cw*sizeof(WORD));
  647. if (!lpW)
  648. return(FALSE);
  649. // first is the count
  650. *lpW++ = (WORD)nCount;
  651. // second is the list of poly counts
  652. for(ii=0; ii<nCount; ii++)
  653. *lpW++ = (WORD)lpPolyCount[ii];
  654. // third is the list of points
  655. for(ii=0; ii<cPt; ii++)
  656. {
  657. *lpW++ = (WORD)lpPoint[ii].x;
  658. *lpW++ = (WORD)lpPoint[ii].y;
  659. }
  660. fRet = RecordParms(hdc, META_POLYPOLYGON, cw, lpT);
  661. if(LocalFree((HANDLE)lpT))
  662. ASSERTGDI(FALSE, "MF16_PolyPolygon: LocalFree Failed\n");
  663. return (fRet);
  664. }
  665. BOOL MF16_SelectClipRgn(HDC hdc, HRGN hrgn, int iMode)
  666. {
  667. PMFRECORDER16 pMFRec;
  668. if (!IS_METADC16_TYPE(hdc))
  669. {
  670. GdiSetLastError(ERROR_INVALID_HANDLE);
  671. return(FALSE);
  672. }
  673. PUTS("MF16_SelectClipRgn\n");
  674. GET_PMFRECORDER16(pMFRec,hdc);
  675. if (iMode != RGN_COPY)
  676. return(FALSE);
  677. // We will emit SelectObject record for clip region just like Windows.
  678. // However, a null region cannot be recorded in the SelectObject call since
  679. // the handle does not identify the object type. This is a bug in Win 3.1!
  680. //
  681. // BUG 8419 winproj 4 has a bug where it counts on this bug. Chicago
  682. // also has this bug so we will have this bug.
  683. if (hrgn == (HRGN) 0)
  684. {
  685. #ifdef RECORD_SELECTCLIPRGN_NULL
  686. BOOL fRet;
  687. fRet = MF16_RecordParms2(hdc, 0, META_SELECTCLIPREGION);
  688. // maintain the new selection in the CurObject table
  689. pMFRec->recCurObjects[OBJ_REGION - MIN_OBJ_TYPE] = 0;
  690. return(fRet);
  691. #else
  692. return TRUE;
  693. #endif
  694. }
  695. else
  696. return(MF16_SelectObject(hdc, hrgn) ? TRUE : FALSE);
  697. }
  698. // SelectObject returns previous object! - new in win3.1
  699. HANDLE MF16_SelectObject(HDC hdc, HANDLE h)
  700. {
  701. HANDLE hOldObject;
  702. WORD position;
  703. PMFRECORDER16 pMFRec;
  704. UINT iType;
  705. PUTS("MF16_SelectObject\n");
  706. GET_PMFRECORDER16(pMFRec,hdc);
  707. if (!IS_METADC16_TYPE(hdc) || !pMFRec)
  708. {
  709. GdiSetLastError(ERROR_INVALID_HANDLE);
  710. return(0);
  711. }
  712. iType = GetObjectType(h);
  713. if ((iType == 0) || !h || (position = (WORD) RecordObject(hdc, h)) == (WORD) -1)
  714. return((HANDLE) 0);
  715. else
  716. {
  717. if (!RecordParms(hdc, META_SELECTOBJECT, 1, &position))
  718. return((HANDLE) 0);
  719. // maintain the new selection in the CurObject table
  720. ASSERTGDI(iType <= MAX_OBJ_TYPE && iType >= MIN_OBJ_TYPE,
  721. "MF16_SelectObject type > max\n");
  722. hOldObject = pMFRec->recCurObjects[iType - MIN_OBJ_TYPE];
  723. pMFRec->recCurObjects[iType - MIN_OBJ_TYPE] = h;
  724. // return the previously selected object or 1 if it is a region
  725. // (for compatibility) - new in win3.1
  726. if (iType == OBJ_REGION)
  727. {
  728. // We also delete the region handle here!
  729. // The reason is that a region can be modified (e.g. SetRectRgn)
  730. // between each use and we have to re-record it each time it is used
  731. // unless we use a dirty flag. This is a bug in win3.1
  732. return(MF16_DeleteRgn(hdc, h) ? (HANDLE) 1 : (HANDLE) 0);
  733. }
  734. else
  735. {
  736. return(hOldObject);
  737. }
  738. }
  739. }
  740. BOOL MF16_SelectPalette(HDC hdc, HPALETTE hpal)
  741. {
  742. WORD position;
  743. PMFRECORDER16 pMFRec;
  744. GET_PMFRECORDER16(pMFRec,hdc);
  745. if (!IS_METADC16_TYPE(hdc) || !pMFRec)
  746. {
  747. GdiSetLastError(ERROR_INVALID_HANDLE);
  748. return(0);
  749. }
  750. if (!hpal || (position = (WORD) RecordObject(hdc, (HANDLE) hpal)) == (WORD) -1)
  751. return(FALSE);
  752. else
  753. {
  754. PMETALINK16 pml16;
  755. if (!RecordParms(hdc, META_SELECTPALETTE, 1, &position))
  756. return(FALSE);
  757. // maintain the new selection in the CurObject table
  758. pMFRec->recCurObjects[OBJ_PAL - MIN_OBJ_TYPE] = hpal;
  759. // Also record which version of the palette we are synced with
  760. // so we know whether to emit a new palette when RealizePalette
  761. // is called
  762. pml16 = pmetalink16Get(hpal);
  763. ASSERTGDI(IS_STOCKOBJ(hpal) || pml16,"MF16_RealizePalette - pml16 == NULL\n");
  764. if (pml16)
  765. pMFRec->iPalVer = PtrToUlong(pml16->pv);
  766. return(TRUE);
  767. }
  768. }
  769. BOOL MF16_TextOut(HDC hdc, INT x, INT y, LPCSTR lpString, INT nCount, BOOL bUnicode)
  770. {
  771. BOOL fRet;
  772. LPWORD lpw, lpT;
  773. DWORD cw;
  774. cw = (nCount + 1)/sizeof(WORD) + 3; // word-aligned character string
  775. lpT = lpw = (LPWORD) LocalAlloc(LMEM_FIXED, cw*sizeof(WORD));
  776. if (!lpw)
  777. return(FALSE);
  778. *lpw++ = (WORD)nCount;
  779. // Copy the string
  780. if (!bUnicode)
  781. {
  782. RtlCopyMemory(lpw, lpString, nCount);
  783. }
  784. else
  785. {
  786. (void) bToASCII_N((LPSTR) lpw, nCount, (LPWSTR) lpString, nCount);
  787. }
  788. lpw += (nCount+1)/sizeof(WORD); // keep word aligned
  789. *lpw++ = (WORD)y;
  790. *lpw++ = (WORD)x;
  791. fRet = RecordParms(hdc, META_TEXTOUT, cw, lpT);
  792. if(LocalFree((HANDLE)lpT))
  793. ASSERTGDI(FALSE, "MF16_TextOut: LocalFree Failed\n");
  794. return (fRet);
  795. }
  796. BOOL MF16_PolyTextOut(HDC hdc, CONST POLYTEXTA *ppta, int cpta, BOOL bUnicode)
  797. {
  798. int i;
  799. for (i = 0; i < cpta; i++)
  800. {
  801. if (!MF16_ExtTextOut(hdc, ppta[i].x, ppta[i].y, ppta[i].uiFlags,
  802. &ppta[i].rcl, (LPCSTR) ppta[i].lpstr, (INT) ppta[i].n,
  803. (LPINT) ppta[i].pdx, bUnicode))
  804. return(FALSE);
  805. }
  806. return(TRUE);
  807. }
  808. BOOL MF16_ExtTextOut(HDC hdc, INT x, INT y, UINT flOptions, CONST RECT *lpRect,
  809. LPCSTR lpString, INT nCount, CONST INT *lpDX, BOOL bUnicode)
  810. {
  811. BOOL fRet;
  812. LPWORD lpw, lpT;
  813. DWORD cw = 0;
  814. INT nUnicodeCount = nCount;
  815. char *pjAnsiString = NULL;
  816. if(bUnicode)
  817. {
  818. // compute the real count of characters in the string
  819. RtlUnicodeToMultiByteSize((PULONG) &nCount, (PWCH) lpString,
  820. nCount * sizeof(WCHAR));
  821. }
  822. // Compute buffer space needed
  823. // room for the char string
  824. // room for the 4 words that are the fixed parms
  825. // if there is a dx array, we need room for it
  826. // if the rectangle is being used, we need room for it
  827. // and we need extra byte for eventual word roundoff
  828. //
  829. if (flOptions & ETO_PDY)
  830. return FALSE;
  831. cw += (lpDX) ? nCount : 0; // DX array
  832. cw += (flOptions & (ETO_OPAQUE | ETO_CLIPPED)) ? 4 : 0; // sizeof RECTS
  833. cw += 4; // x,y,options and count
  834. cw += (nCount + 1)/sizeof(WORD);
  835. lpT = lpw = (LPWORD) LocalAlloc(LMEM_FIXED, cw*sizeof(WORD));
  836. if (!lpw)
  837. return(FALSE);
  838. *lpw++ = (WORD)y;
  839. *lpw++ = (WORD)x;
  840. *lpw++ = (WORD)nCount;
  841. *lpw++ = (WORD)flOptions;
  842. // Copy the rect if present
  843. if (flOptions & (ETO_OPAQUE | ETO_CLIPPED))
  844. {
  845. ERROR_ASSERT(lpRect, "MF16_ExtTextOut: expect valid lpRect\n");
  846. *lpw++ = (WORD)lpRect->left;
  847. *lpw++ = (WORD)lpRect->top;
  848. *lpw++ = (WORD)lpRect->right;
  849. *lpw++ = (WORD)lpRect->bottom;
  850. }
  851. // Copy the string
  852. if (!bUnicode)
  853. {
  854. RtlCopyMemory(lpw, lpString, nCount);
  855. }
  856. else
  857. {
  858. (void) bToASCII_N((LPSTR) lpw, nCount, (LPWSTR) lpString, nUnicodeCount);
  859. pjAnsiString = (char*) lpw;
  860. }
  861. lpw += (nCount+1)/sizeof(WORD); // keep word aligned
  862. if (lpDX)
  863. {
  864. INT ii;
  865. if(nCount != nUnicodeCount)
  866. {
  867. INT jj;
  868. for(ii=0,jj=0; ii < nCount; ii++,jj++)
  869. {
  870. *lpw++ = (WORD)lpDX[jj];
  871. if(IsDBCSLeadByte(pjAnsiString[ii]))
  872. {
  873. *lpw++ = 0;
  874. ii++;
  875. }
  876. }
  877. }
  878. else
  879. {
  880. for(ii=0; ii<nCount; ii++)
  881. *lpw++ = (WORD)lpDX[ii];
  882. }
  883. }
  884. fRet = RecordParms(hdc, META_EXTTEXTOUT, cw, lpT);
  885. if (LocalFree((HANDLE)lpT))
  886. ASSERTGDI(FALSE, "MF16_ExtTextOut: LocalFree Failed\n");
  887. return (fRet);
  888. }
  889. BOOL MF16_Escape(HDC hdc, int nEscape, int nCount, LPCSTR lpInData, LPVOID lpOutData)
  890. {
  891. BOOL fRet;
  892. LPWORD lpW,lpT;
  893. DWORD cw;
  894. // If a metafile is retrieved from GetWinMetaFileBits, it may contain
  895. // an embedded enhanced metafile. Do not include the enhanced metafile
  896. // if we are playing the metafile to another metafile.
  897. if (nEscape == MFCOMMENT
  898. && nCount > sizeof(META_ESCAPE_ENHANCED_METAFILE) - sizeof(DWORD) - 3 * sizeof(WORD)
  899. && ((DWORD UNALIGNED *) lpInData)[0] == MFCOMMENT_IDENTIFIER
  900. && ((DWORD UNALIGNED *) lpInData)[1] == MFCOMMENT_ENHANCED_METAFILE)
  901. {
  902. return(TRUE);
  903. }
  904. // Some wow apps (e.g. amipro) use metafiles for printing. As a result,
  905. // we need to record these printing escapes.
  906. cw = 2 + ((nCount + 1) / sizeof(WORD));
  907. lpT = lpW = (LPWORD) LocalAlloc(LMEM_FIXED, cw * sizeof(WORD));
  908. if (!lpW)
  909. return(FALSE);
  910. *lpW++ = (WORD) nEscape; // escape number
  911. *lpW++ = (WORD) nCount; // count of input data buffer
  912. RtlCopyMemory(lpW, lpInData, nCount);
  913. fRet = RecordParms(hdc, META_ESCAPE, cw, lpT);
  914. if (LocalFree((HANDLE) lpT))
  915. ASSERTGDI(FALSE, "MF16_Escape: LocalFree Failed\n");
  916. return(fRet);
  917. }
  918. /****************************************************************************
  919. * *
  920. * RecordParms *
  921. * *
  922. * Parameters: 1.hMF handle to a metafile header. *
  923. * 2.The magic number of the function being recorded. *
  924. * 3.The number of parmmeter of the function (size of lpParm *
  925. * in words) *
  926. * 4.A long pointer to parameters stored in reverse order *
  927. * *
  928. * Warning call only once per function because max record is updated. *
  929. * *
  930. ****************************************************************************/
  931. BOOL RecordParms(HDC hdc, DWORD magic, DWORD cw, CONST WORD *lpParm)
  932. {
  933. PMFRECORDER16 pMFRec;
  934. METARECORD MFRecord;
  935. PUTSX("RecordParms %lX\n", (ULONG)magic);
  936. ASSERTGDI(HIWORD(magic) == 0, "RecordParms: bad magic\n");
  937. GET_PMFRECORDER16(pMFRec,hdc);
  938. if (!IS_METADC16_TYPE(hdc) || !pMFRec)
  939. {
  940. GdiSetLastError(ERROR_INVALID_HANDLE);
  941. return(FALSE);
  942. }
  943. // Make sure the Metafile hasn't died before we continue
  944. if (!(pMFRec->recFlags & METAFILEFAILURE))
  945. {
  946. MFRecord.rdSize = SIZEOF_METARECORDHEADER/sizeof(WORD) + cw;
  947. MFRecord.rdFunction = (WORD)magic;
  948. // Write the header
  949. if (!AttemptWrite(pMFRec, SIZEOF_METARECORDHEADER, (LPBYTE)&MFRecord))
  950. return(FALSE);
  951. // Write the data
  952. if (!AttemptWrite(pMFRec, cw*sizeof(WORD), (LPBYTE)lpParm))
  953. return(FALSE);
  954. // Update max record size
  955. if (MFRecord.rdSize > pMFRec->metaHeader.mtMaxRecord)
  956. pMFRec->metaHeader.mtMaxRecord = MFRecord.rdSize;
  957. }
  958. return (TRUE); // Win 3.1 returns true even if METAFAILEFAILURE is on!
  959. }
  960. /***************************** Internal Function ***************************\
  961. * AttemptWrite
  962. *
  963. * Tries to write data to a metafile disk file
  964. *
  965. * dwBytes is the byte count of lpData.
  966. *
  967. * Returns TRUE iff the write was sucessful
  968. *
  969. *
  970. \***************************************************************************/
  971. BOOL AttemptWrite(PMFRECORDER16 pMFRec, DWORD dwBytes, LPBYTE lpData)
  972. {
  973. DWORD cbWritten;
  974. BOOL fRet;
  975. PUTS("AttemptWrite\n");
  976. ASSERTGDI(dwBytes % 2 == 0, "AttemptWrite: bad dwBytes\n"); // must be even
  977. ASSERTGDI(!(pMFRec->recFlags & METAFILEFAILURE),
  978. "AttemptWrite: Bad recording\n");
  979. // Handle disk file.
  980. if (pMFRec->metaHeader.mtType == DISKMETAFILE)
  981. {
  982. // Flush the buffer if it's not large enough.
  983. if (dwBytes + pMFRec->ibBuffer > pMFRec->cbBuffer)
  984. {
  985. fRet = WriteFile(pMFRec->hFile, (LPBYTE)pMFRec->hMem,
  986. pMFRec->ibBuffer, &cbWritten, (LPOVERLAPPED)NULL);
  987. if (!fRet || (cbWritten != pMFRec->ibBuffer))
  988. {
  989. ERROR_ASSERT(FALSE, "AttemptWrite: Write1 failed\n");
  990. goto AttemptWrite_Error;
  991. }
  992. pMFRec->ibBuffer = 0; // reset buffer info
  993. }
  994. // If the data is still too large, write it out to disk directly.
  995. if (dwBytes + pMFRec->ibBuffer > pMFRec->cbBuffer)
  996. {
  997. fRet = WriteFile(pMFRec->hFile, lpData,
  998. dwBytes, &cbWritten, (LPOVERLAPPED)NULL);
  999. if (!fRet || (cbWritten != dwBytes))
  1000. {
  1001. ERROR_ASSERT(FALSE, "AttemptWrite: Write2 failed\n");
  1002. goto AttemptWrite_Error;
  1003. }
  1004. }
  1005. else
  1006. {
  1007. // Store data in the buffer.
  1008. RtlCopyMemory((LPBYTE)pMFRec->hMem + pMFRec->ibBuffer, lpData, dwBytes);
  1009. pMFRec->ibBuffer += dwBytes;
  1010. }
  1011. }
  1012. else
  1013. {
  1014. // Handle memory file.
  1015. // Grow the buffer if necessary.
  1016. if (dwBytes + pMFRec->ibBuffer > pMFRec->cbBuffer)
  1017. {
  1018. DWORD cbNewSize;
  1019. HANDLE hMem;
  1020. cbNewSize = pMFRec->cbBuffer + MF16_BUFSIZE_INC
  1021. + dwBytes / MF16_BUFSIZE_INC * MF16_BUFSIZE_INC;
  1022. hMem = LocalReAlloc(pMFRec->hMem, cbNewSize, LMEM_MOVEABLE);
  1023. if (hMem == NULL)
  1024. {
  1025. ERROR_ASSERT(FALSE, "AttemptWrite: out of memory\n");
  1026. goto AttemptWrite_Error;
  1027. }
  1028. pMFRec->hMem = hMem;
  1029. pMFRec->cbBuffer = cbNewSize;
  1030. }
  1031. // Record the data.
  1032. RtlCopyMemory((LPBYTE)pMFRec->hMem + pMFRec->ibBuffer, lpData, dwBytes);
  1033. pMFRec->ibBuffer += dwBytes;
  1034. }
  1035. // Update the header size.
  1036. pMFRec->metaHeader.mtSize += dwBytes/sizeof(WORD);
  1037. return(TRUE);
  1038. AttemptWrite_Error:
  1039. MarkMetaFile(pMFRec);
  1040. return(FALSE);
  1041. }
  1042. /***************************** Internal Function ***************************\
  1043. * VOID MarkMetaFile
  1044. *
  1045. * Marks a metafile as failed
  1046. *
  1047. * Effects:
  1048. * Frees the metafile resources
  1049. *
  1050. \***************************************************************************/
  1051. VOID MarkMetaFile(PMFRECORDER16 pMFRec)
  1052. {
  1053. // Clean up is done in CloseMetaFile.
  1054. PUTS("MarkMetaFile\n");
  1055. pMFRec->recFlags |= METAFILEFAILURE;
  1056. }
  1057. /***************************** Internal Function **************************\
  1058. * MakeLogPalette
  1059. *
  1060. * Records either CreatePalette or SetPaletteEntries
  1061. *
  1062. * Returns TRUE iff sucessful
  1063. *
  1064. *
  1065. \***************************************************************************/
  1066. BOOL MakeLogPalette(HDC hdc, HANDLE hPal, WORD magic)
  1067. {
  1068. WORD cPalEntries;
  1069. BOOL fStatus = FALSE;
  1070. DWORD cbPalette;
  1071. LPLOGPALETTE lpPalette;
  1072. PUTS("MakeLogPalette\n");
  1073. if (!GetObject(hPal, sizeof(WORD), &cPalEntries))
  1074. {
  1075. ERROR_ASSERT(FALSE, "MakeLogPalette: GetObject Failed\n");
  1076. return(fStatus);
  1077. }
  1078. // alloc memory and get the palette entries
  1079. if (lpPalette = (LPLOGPALETTE)LocalAlloc(LMEM_FIXED,
  1080. cbPalette = sizeof(LOGPALETTE)-sizeof(PALETTEENTRY)+sizeof(PALETTEENTRY)*cPalEntries))
  1081. {
  1082. lpPalette->palNumEntries = cPalEntries;
  1083. GetPaletteEntries(hPal, 0, cPalEntries, lpPalette->palPalEntry);
  1084. if (magic == (META_CREATEPALETTE & 255))
  1085. {
  1086. lpPalette->palVersion = 0x300;
  1087. magic = META_CREATEPALETTE;
  1088. }
  1089. else if (magic == (META_SETPALENTRIES & 255))
  1090. {
  1091. lpPalette->palVersion = 0; /* really "starting index" */
  1092. magic = META_SETPALENTRIES;
  1093. }
  1094. fStatus = RecordParms(hdc, magic, (DWORD)cbPalette >> 1, (LPWORD)lpPalette);
  1095. if (LocalFree((HANDLE)lpPalette))
  1096. ASSERTGDI(FALSE, "MakeLogPalette: LocalFree Failed\n");
  1097. }
  1098. return(fStatus);
  1099. }
  1100. /***************************** Internal Function ***************************\
  1101. * RecordObject
  1102. *
  1103. * Records the use of an object by creating the object
  1104. *
  1105. * Returns: index of object in table
  1106. * -1 if error
  1107. *
  1108. \***************************************************************************/
  1109. WIN3REGION w3rgnEmpty =
  1110. {
  1111. 0, // nextInChain
  1112. 6, // ObjType
  1113. 0x2F6, // ObjCount
  1114. sizeof(WIN3REGION) - sizeof(SCAN) + 2,
  1115. // cbRegion
  1116. 0, // cScans
  1117. 0, // maxScan
  1118. {0,0,0,0}, // rcBounding
  1119. {0,0,0,{0,0},0} // aScans[]
  1120. };
  1121. WORD RecordObject(HDC hdc, HANDLE hObject)
  1122. {
  1123. UINT status;
  1124. UINT iPosition;
  1125. HDC hdcScreen = (HDC) 0;
  1126. int iType;
  1127. UINT iUsage;
  1128. PUTS("RecordObject\n");
  1129. // Validate the object.
  1130. iType = LO_TYPE(hObject);
  1131. if (iType != LO_PEN_TYPE &&
  1132. iType != LO_BRUSH_TYPE &&
  1133. iType != LO_FONT_TYPE &&
  1134. iType != LO_REGION_TYPE &&
  1135. iType != LO_PALETTE_TYPE
  1136. )
  1137. {
  1138. GdiSetLastError(ERROR_INVALID_HANDLE);
  1139. return((WORD) -1);
  1140. }
  1141. // Add the object to the metafiles list.
  1142. status = AddObjectToDCTable(hdc, hObject, &iPosition, TRUE);
  1143. // An error occurred.
  1144. if (status == (UINT) -1)
  1145. return((WORD) -1);
  1146. // Object already exists.
  1147. if (status == 1)
  1148. return((WORD) iPosition);
  1149. ASSERTGDI(!status, "RecordObject: Bad return code from AddObjectToDCTable\n");
  1150. // Object does not exist, record it.
  1151. if (iType != LO_REGION_TYPE) // don't add regions to the metalist!
  1152. if (!AddDCToObjectMetaList16(hdc,hObject))
  1153. return((WORD) -1);
  1154. switch (iType)
  1155. {
  1156. case LO_PEN_TYPE:
  1157. {
  1158. LOGPEN16 logpen16;
  1159. GetObject16AndType(hObject, (LPVOID)&logpen16);
  1160. status = (UINT) RecordParms(hdc, (WORD)META_CREATEPENINDIRECT,
  1161. (DWORD)((sizeof(LOGPEN16) + 1) >> 1),
  1162. (LPWORD)&logpen16);
  1163. break;
  1164. }
  1165. case LO_FONT_TYPE:
  1166. {
  1167. LOGFONT16 logfont16;
  1168. GetObject16AndType(hObject, (LPVOID)&logfont16);
  1169. /* size of LOGFONT adjusted based on the length of the facename */
  1170. status = (UINT) RecordParms(hdc, META_CREATEFONTINDIRECT,
  1171. (DWORD)((sizeof(LOGFONT16) + 1) >> 1),
  1172. (LPWORD) &logfont16);
  1173. break;
  1174. }
  1175. /*
  1176. * in win2, METACREATEREGION records contained an entire region object,
  1177. * including the full header. this header changed in win3.
  1178. *
  1179. * to remain compatible, the region records will be saved with the
  1180. * win2 header. here we save our region with a win2 header.
  1181. */
  1182. case LO_REGION_TYPE:
  1183. {
  1184. PWIN3REGION lpw3rgn;
  1185. DWORD cbNTRgnData;
  1186. DWORD curRectl;
  1187. WORD cScans;
  1188. WORD maxScanEntry;
  1189. WORD curScanEntry;
  1190. DWORD cbw3data;
  1191. PRGNDATA lprgn;
  1192. LPRECT lprc;
  1193. PSCAN lpScan;
  1194. ASSERTGDI(!status, "RecordObject: bad status\n");
  1195. // Get the NT Region Data
  1196. cbNTRgnData = GetRegionData(hObject, 0, NULL);
  1197. if (cbNTRgnData == 0)
  1198. break;
  1199. lprgn = (PRGNDATA) LocalAlloc(LMEM_FIXED, cbNTRgnData);
  1200. if (!lprgn)
  1201. break;
  1202. cbNTRgnData = GetRegionData(hObject, cbNTRgnData, lprgn);
  1203. if (cbNTRgnData == 0)
  1204. {
  1205. LocalFree((HANDLE) lprgn);
  1206. break;
  1207. }
  1208. // Handle the empty region.
  1209. if (!lprgn->rdh.nCount)
  1210. {
  1211. status = (UINT) RecordParms(hdc, META_CREATEREGION,
  1212. (sizeof(WIN3REGION) - sizeof(SCAN)) >> 1, // Convert to count of words
  1213. (LPWORD) &w3rgnEmpty);
  1214. LocalFree((HANDLE)lprgn);
  1215. break;
  1216. }
  1217. lprc = (LPRECT)lprgn->Buffer;
  1218. // Create the Windows 3.x equivalent
  1219. // worst case is one scan for each rect
  1220. cbw3data = 2*sizeof(WIN3REGION) + (WORD)lprgn->rdh.nCount*sizeof(SCAN);
  1221. lpw3rgn = (PWIN3REGION)LocalAlloc(LMEM_FIXED, cbw3data);
  1222. if (!lpw3rgn)
  1223. {
  1224. LocalFree((HANDLE) lprgn);
  1225. break;
  1226. }
  1227. // Grab the bounding rect.
  1228. lpw3rgn->rcBounding.left = (SHORT)lprgn->rdh.rcBound.left;
  1229. lpw3rgn->rcBounding.right = (SHORT)lprgn->rdh.rcBound.right;
  1230. lpw3rgn->rcBounding.top = (SHORT)lprgn->rdh.rcBound.top;
  1231. lpw3rgn->rcBounding.bottom = (SHORT)lprgn->rdh.rcBound.bottom;
  1232. cbw3data = sizeof(WIN3REGION) - sizeof(SCAN) + 2;
  1233. // visit all the rects
  1234. curRectl = 0;
  1235. cScans = 0;
  1236. maxScanEntry = 0;
  1237. lpScan = lpw3rgn->aScans;
  1238. while(curRectl < lprgn->rdh.nCount)
  1239. {
  1240. LPWORD lpXEntry;
  1241. DWORD cbScan;
  1242. curScanEntry = 0; // Current X pair in this scan
  1243. lpScan->scnPntTop = (WORD)lprc[curRectl].top;
  1244. lpScan->scnPntBottom = (WORD)lprc[curRectl].bottom;
  1245. lpXEntry = (LPWORD) lpScan->scnPntsX;
  1246. // handle rects on this scan
  1247. do
  1248. {
  1249. lpXEntry[curScanEntry + 0] = (WORD)lprc[curRectl].left;
  1250. lpXEntry[curScanEntry + 1] = (WORD)lprc[curRectl].right;
  1251. curScanEntry += 2;
  1252. curRectl++;
  1253. } while ((curRectl < lprgn->rdh.nCount)
  1254. && (lprc[curRectl-1].top == lprc[curRectl].top)
  1255. && (lprc[curRectl-1].bottom == lprc[curRectl].bottom)
  1256. );
  1257. lpScan->scnPntCnt = curScanEntry;
  1258. lpXEntry[curScanEntry] = curScanEntry; // Count also follows Xs
  1259. cScans++;
  1260. if (curScanEntry > maxScanEntry)
  1261. maxScanEntry = curScanEntry;
  1262. // account for each new scan + each X1 X2 Entry but the first
  1263. cbScan = sizeof(SCAN)-(sizeof(WORD)*2) + (curScanEntry*sizeof(WORD));
  1264. cbw3data += cbScan;
  1265. lpScan = (PSCAN)(((LPBYTE)lpScan) + cbScan);
  1266. }
  1267. // Initialize the header
  1268. lpw3rgn->nextInChain = 0;
  1269. lpw3rgn->ObjType = 6; // old Windows OBJ_RGN identifier
  1270. lpw3rgn->ObjCount= 0x2F6; // any non-zero number
  1271. lpw3rgn->cbRegion = (WORD)cbw3data; // don't count type and next
  1272. lpw3rgn->cScans = cScans;
  1273. lpw3rgn->maxScan = maxScanEntry;
  1274. status = (UINT) RecordParms(hdc, META_CREATEREGION,
  1275. (cbw3data-2) >> 1, // Convert to count of words
  1276. (LPWORD) lpw3rgn);
  1277. if (LocalFree((HANDLE)lprgn))
  1278. ASSERTGDI(FALSE, "RecordObject: LocalFree(lprgn) Failed\n");
  1279. if (LocalFree((HANDLE)lpw3rgn))
  1280. ASSERTGDI(FALSE, "RecordObject: LocalFree(lpw3rgn) Failed\n");
  1281. break;
  1282. }
  1283. case LO_BRUSH_TYPE:
  1284. {
  1285. LOGBRUSH lb;
  1286. if (!GetObjectA(hObject, sizeof(LOGBRUSH), &lb))
  1287. break;
  1288. switch (lb.lbStyle)
  1289. {
  1290. case BS_HATCHED:
  1291. case BS_HOLLOW:
  1292. case BS_SOLID:
  1293. {
  1294. LOGBRUSH16 lb16;
  1295. LOGBRUSH16FROMLOGBRUSH32(&lb16, &lb);
  1296. // non-pattern brush
  1297. status = (UINT) RecordParms(hdc, META_CREATEBRUSHINDIRECT,
  1298. (DWORD) ((sizeof(LOGBRUSH16) + 1) >> 1),
  1299. (LPWORD) &lb16);
  1300. break;
  1301. }
  1302. case BS_PATTERN:
  1303. case BS_DIBPATTERN:
  1304. case BS_DIBPATTERNPT:
  1305. {
  1306. HBITMAP hbmRemote;
  1307. BMIH bmih;
  1308. DWORD cbBitsInfo;
  1309. DWORD cbBits;
  1310. LPWORD lpWStart, lpW;
  1311. DWORD lbStyle = BS_DIBPATTERN;
  1312. PBMIH lpDIBInfoHeader;
  1313. if (!(hbmRemote = GetObjectBitmapHandle((HBRUSH) hObject, &iUsage)))
  1314. {
  1315. ASSERTGDI(FALSE, "RecordObject: GetObjectBitmapHandle failed");
  1316. break;
  1317. }
  1318. // For a pattern brush, if it is color, it is recorded as a
  1319. // DIB pattern brush with BS_DIBPATTERN style. If it is
  1320. // monochrome, it is recorded as a DIB pattern brush with
  1321. // BS_PATTERN style. The playback code has a special
  1322. // case to deal with monochrome brushes.
  1323. if (lb.lbStyle == BS_PATTERN)
  1324. {
  1325. iUsage = DIB_RGB_COLORS;
  1326. if (MonoBitmap(hbmRemote))
  1327. lbStyle = BS_PATTERN;
  1328. }
  1329. hdcScreen = CreateCompatibleDC((HDC) 0); // freed below
  1330. // Get the bitmap info header and sizes.
  1331. if (!bMetaGetDIBInfo(hdcScreen, hbmRemote, &bmih,
  1332. &cbBitsInfo, &cbBits, iUsage, 0, TRUE))
  1333. break;
  1334. // Make sure that cbBitsInfo is dword aligned
  1335. // If we have converted the bitmap format in bMetaGetDIBInfo,
  1336. // modify the iUsage to match the new format.
  1337. if (bmih.biBitCount == 24)
  1338. iUsage = DIB_RGB_COLORS;
  1339. // Allocate space for DIB plus parameters.
  1340. lpWStart = lpW = (LPWORD) LocalAlloc(LMEM_FIXED,
  1341. cbBitsInfo + cbBits + 2*sizeof(WORD));
  1342. if (!lpW)
  1343. {
  1344. ERROR_ASSERT(FALSE, "RecordObject: out of memory\n");
  1345. break;
  1346. }
  1347. *lpW++ = (WORD) lbStyle; // BS_PATTERN or BS_DIBPATTERN
  1348. *lpW++ = (WORD) iUsage; // usage word
  1349. // Save the start of the bitmap info header field.
  1350. lpDIBInfoHeader = (LPBITMAPINFOHEADER) lpW;
  1351. // Copy the bitmap info header.
  1352. *lpDIBInfoHeader = bmih;
  1353. // Get bitmap info and bits.
  1354. if (GetBrushBits(hdcScreen,
  1355. hbmRemote,
  1356. (UINT) iUsage,
  1357. cbBitsInfo,
  1358. (LPVOID) ((PBYTE) lpW + cbBitsInfo),
  1359. (LPBITMAPINFO) lpDIBInfoHeader))
  1360. {
  1361. // Finally record the parameters into the file.
  1362. status = (UINT) RecordParms(hdc, META_DIBCREATEPATTERNBRUSH,
  1363. 2 + (cbBitsInfo + cbBits) / sizeof(WORD),
  1364. (LPWORD) lpWStart);
  1365. }
  1366. if (LocalFree((HANDLE) lpWStart))
  1367. ASSERTGDI(FALSE, "RecordObject: LocalFree Failed\n");
  1368. break;
  1369. }
  1370. default:
  1371. {
  1372. ASSERTGDI(FALSE, "RecordObject: Bad brush style");
  1373. break;
  1374. }
  1375. } // switch(lb.lbStyle)
  1376. break;
  1377. } // case LO_BRUSH
  1378. case LO_PALETTE_TYPE:
  1379. status = (UINT) MakeLogPalette(hdc, hObject, META_CREATEPALETTE);
  1380. break;
  1381. default:
  1382. ERROR_ASSERT(FALSE, "unknown case RecordObject");
  1383. break;
  1384. }
  1385. // Free the DC created in the brush case.
  1386. if (hdcScreen)
  1387. if (!DeleteDC(hdcScreen))
  1388. ASSERTGDI(FALSE, "RecordObject: DeleteDC Failed\n");
  1389. ASSERTGDI(status == TRUE, "RecordObject: Failing\n");
  1390. return ((WORD) (status == TRUE ? iPosition : -1));
  1391. } /* RecordObject */
  1392. BOOL AddDCToObjectMetaList16(HDC hMetaDC16, HANDLE hObject)
  1393. {
  1394. ULONG cMetaDC16New;
  1395. PMETALINK16 pml16;
  1396. ASSERTGDI(LO_TYPE(hObject) != LO_REGION_TYPE,
  1397. "AddDCToObjectMetaList16: unexpected region object");
  1398. // If the object is a stock object there is no work to do
  1399. if (IS_STOCKOBJ(hObject))
  1400. return(TRUE);
  1401. // If the Object's MetaList16 is NULL create allocate one
  1402. pml16 = pmetalink16Get(hObject);
  1403. if (!pml16)
  1404. {
  1405. ENTERCRITICALSECTION(&semLocal);
  1406. pml16 = pmetalink16Create(hObject);
  1407. LEAVECRITICALSECTION(&semLocal);
  1408. if (pml16)
  1409. {
  1410. pml16->metalink = 0;
  1411. pml16->cMetaDC16 = 1;
  1412. pml16->ahMetaDC16[0] = hMetaDC16;
  1413. }
  1414. else
  1415. {
  1416. ASSERTGDI(FALSE, "AddDCToObjectMetaList16: Out of Memory 1");
  1417. return(FALSE);
  1418. }
  1419. }
  1420. else
  1421. {
  1422. int cj;
  1423. cMetaDC16New = pml16->cMetaDC16 + 1;
  1424. if (pml16 = pmetalink16Resize(hObject,cMetaDC16New))
  1425. {
  1426. pml16->ahMetaDC16[pml16->cMetaDC16++] = hMetaDC16;
  1427. }
  1428. else
  1429. {
  1430. ASSERTGDI(FALSE, "AddDCToObjectMetaList16: Out of Memory 2");
  1431. return(FALSE);
  1432. }
  1433. }
  1434. return(TRUE);
  1435. }
  1436. /***************************** Internal Function ***************************\
  1437. * AddObjectToDCTable
  1438. *
  1439. * Add an object (brush, pen...) to a list of objects associated with the
  1440. * metafile.
  1441. *
  1442. *
  1443. *
  1444. * Returns: 1 if object is already in table
  1445. * 0 if object was just added to table
  1446. * -1 if failure
  1447. *
  1448. * Remarks
  1449. * bAdd is TRUE iff the object is being added otherwise it is being deleted
  1450. *
  1451. \***************************************************************************/
  1452. UINT AddObjectToDCTable(HDC hdc, HANDLE hObject, PUINT pPosition, BOOL bAdd)
  1453. {
  1454. UINT iEmptySpace = (UINT) -1;
  1455. UINT i;
  1456. UINT status = (UINT) -1;
  1457. POBJECTTABLE pHandleTable;
  1458. PMFRECORDER16 pMFRec;
  1459. PUTS("AddObjectToDCTable\n");
  1460. GET_PMFRECORDER16(pMFRec,hdc);
  1461. if (!IS_METADC16_TYPE(hdc) || !pMFRec)
  1462. {
  1463. GdiSetLastError(ERROR_INVALID_HANDLE);
  1464. return((UINT)-1);
  1465. }
  1466. // if the Object table already exists search it for the object
  1467. if (pHandleTable = (POBJECTTABLE)pMFRec->hObjectTable)
  1468. {
  1469. for (i=0; i < (UINT) pMFRec->metaHeader.mtNoObjects; ++i)
  1470. {
  1471. if (hObject == pHandleTable[i].CurHandle)
  1472. {
  1473. *pPosition = i;
  1474. status = 1; // the object exists in the table
  1475. // if we are doing a METADELETEOBJECT.
  1476. // delete object from table
  1477. if (!bAdd)
  1478. {
  1479. pHandleTable[i].fPreDeleted = FALSE;
  1480. pHandleTable[i].CurHandle = (HANDLE)NULL;
  1481. }
  1482. goto AddObjectToTable10;
  1483. }
  1484. else if ((pHandleTable[i].CurHandle == 0) && (iEmptySpace == (UINT) -1))
  1485. {
  1486. // if the entry has been deleted, we want to add a new object
  1487. // in its place. iEmptySpace will tell us where that place is.
  1488. iEmptySpace = i;
  1489. }
  1490. } // for
  1491. }
  1492. if (bAdd)
  1493. {
  1494. // If there is no object table for this MetaFile then Allocate one.
  1495. if (pHandleTable == (POBJECTTABLE)NULL)
  1496. {
  1497. pHandleTable = (POBJECTTABLE) LocalAlloc(LMEM_FIXED, sizeof(OBJECTTABLE));
  1498. pMFRec->hObjectTable = (HANDLE) pHandleTable;
  1499. }
  1500. else if (iEmptySpace == (UINT) -1)
  1501. {
  1502. pHandleTable = (POBJECTTABLE) LocalReAlloc(pMFRec->hObjectTable,
  1503. (pMFRec->metaHeader.mtNoObjects + 1) * sizeof(OBJECTTABLE),
  1504. LMEM_MOVEABLE);
  1505. if (pHandleTable)
  1506. pMFRec->hObjectTable = (HANDLE) pHandleTable;
  1507. }
  1508. if (pHandleTable)
  1509. {
  1510. if (iEmptySpace == (UINT) -1)
  1511. *pPosition = pMFRec->metaHeader.mtNoObjects++;
  1512. else
  1513. *pPosition = iEmptySpace;
  1514. pHandleTable[*pPosition].fPreDeleted = FALSE;
  1515. pHandleTable[*pPosition].CurHandle = hObject;
  1516. status = 0; // the object is added to the table
  1517. }
  1518. }
  1519. AddObjectToTable10:
  1520. ERROR_ASSERT(status != (UINT) -1, "AddObjectToTable: Failing\n");
  1521. return(status);
  1522. }
  1523. /***************************** Internal Function **************************\
  1524. * HDC WINAPI CreateMetaFileW
  1525. *
  1526. * Creates a MetaFile DC
  1527. *
  1528. * The internal format for a MetaFileRecorder has two formats one
  1529. * for a memory MetaFile and one for a disk based MetaFile
  1530. *
  1531. \***************************************************************************/
  1532. HDC WINAPI CreateMetaFileA(LPCSTR pszFileName)
  1533. {
  1534. UINT cch;
  1535. WCHAR awch[MAX_PATH];
  1536. if (pszFileName)
  1537. {
  1538. cch = strlen(pszFileName)+1;
  1539. if (cch > MAX_PATH)
  1540. {
  1541. ERROR_ASSERT(FALSE, "CreateMetaFileA filename too long");
  1542. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  1543. return((HDC) 0);
  1544. }
  1545. vToUnicodeN(awch, MAX_PATH, pszFileName, cch);
  1546. return (CreateMetaFileW(awch));
  1547. }
  1548. else
  1549. return (CreateMetaFileW((LPWSTR)NULL));
  1550. }
  1551. HDC WINAPI CreateMetaFileW(LPCWSTR pwszFileName)
  1552. {
  1553. PMFRECORDER16 pMFRec;
  1554. HDC hdc;
  1555. PUTS("CreateMetaFileW\n");
  1556. if (!(pMFRec = (PMFRECORDER16) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
  1557. sizeof(MFRECORDER16))))
  1558. goto CreateMetaFileW_error;
  1559. // pMFRec->ident = ID_METADC16;
  1560. // pMFRec->hMem = 0;
  1561. pMFRec->hFile = INVALID_HANDLE_VALUE;
  1562. pMFRec->cbBuffer = MF16_BUFSIZE_INIT;
  1563. // pMFRec->ibBuffer = 0;
  1564. pMFRec->metaHeader.mtHeaderSize = sizeof(METAHEADER)/sizeof(WORD);
  1565. pMFRec->metaHeader.mtVersion = METAVERSION300;
  1566. // pMFRec->metaHeader.mtSize = 0;
  1567. // pMFRec->metaHeader.mtNoObjects = 0;
  1568. // pMFRec->metaHeader.mtMaxRecord = 0;
  1569. // pMFRec->metaHeader.mtNoParameters = 0;
  1570. // pMFRec->recFlags = 0;
  1571. // pMFRec->recCurObjects[] = 0;
  1572. pMFRec->recCurObjects[OBJ_PEN - MIN_OBJ_TYPE]
  1573. = GetStockObject(BLACK_PEN);
  1574. pMFRec->recCurObjects[OBJ_BRUSH - MIN_OBJ_TYPE]
  1575. = GetStockObject(WHITE_BRUSH);
  1576. pMFRec->recCurObjects[OBJ_FONT - MIN_OBJ_TYPE]
  1577. = GetStockObject(DEVICE_DEFAULT_FONT);
  1578. pMFRec->recCurObjects[OBJ_BITMAP - MIN_OBJ_TYPE]
  1579. = GetStockObject(PRIV_STOCK_BITMAP);
  1580. pMFRec->recCurObjects[OBJ_REGION - MIN_OBJ_TYPE]
  1581. = (HANDLE) NULL;
  1582. pMFRec->recCurObjects[OBJ_PAL - MIN_OBJ_TYPE]
  1583. = GetStockObject(DEFAULT_PALETTE);
  1584. // pMFRec->iPalVer = 0;
  1585. // Create a disk file if given. The filename is given in unicode.
  1586. if (pwszFileName)
  1587. {
  1588. LPWSTR pwszFilePart; // not used
  1589. DWORD cPathname;
  1590. // Convert the filename to a fully qualified pathname.
  1591. cPathname = GetFullPathNameW(pwszFileName,
  1592. MAX_PATH,
  1593. pMFRec->wszFullPathName,
  1594. &pwszFilePart);
  1595. if (!cPathname || cPathname > MAX_PATH)
  1596. {
  1597. ERROR_ASSERT(FALSE, "GetFullPathName failed");
  1598. if (cPathname > MAX_PATH)
  1599. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  1600. goto CreateMetaFileW_error;
  1601. }
  1602. pMFRec->wszFullPathName[cPathname] = 0;
  1603. // Create the file.
  1604. if ((pMFRec->hFile = CreateFileW(pMFRec->wszFullPathName,// Filename
  1605. GENERIC_WRITE, // Write access
  1606. 0L, // Non-shared
  1607. (LPSECURITY_ATTRIBUTES) NULL, // No security
  1608. CREATE_ALWAYS, // Always create
  1609. FILE_ATTRIBUTE_NORMAL, // normal attributes
  1610. (HANDLE) 0)) // no template file
  1611. == INVALID_HANDLE_VALUE)
  1612. {
  1613. // Milestones, Etc. 3.1 creates the file for read/write access when
  1614. // it calls CreateMetaFile. This causes the above CreateFile to
  1615. // fail. However, we do not want to modify the above call since
  1616. // it provides serialization and access to the metafile. Instead,
  1617. // we add in this hack for Milestones. The only difference is
  1618. // that the metafile is shared for read/write access.
  1619. if ((pMFRec->hFile = CreateFileW(pMFRec->wszFullPathName,
  1620. GENERIC_WRITE,
  1621. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1622. (LPSECURITY_ATTRIBUTES) NULL,
  1623. CREATE_ALWAYS,
  1624. FILE_ATTRIBUTE_NORMAL,
  1625. (HANDLE) 0))
  1626. == INVALID_HANDLE_VALUE)
  1627. {
  1628. ERROR_ASSERT(FALSE, "CreateFile failed");
  1629. goto CreateMetaFileW_error;
  1630. }
  1631. WARNING("CreateMetaFileW: Creating metafile with read/write share\n");
  1632. }
  1633. pMFRec->metaHeader.mtType = DISKMETAFILE;
  1634. }
  1635. else
  1636. {
  1637. pMFRec->metaHeader.mtType = MEMORYMETAFILE;
  1638. }
  1639. // Allocate memory for metafile.
  1640. // For disk metafile, it is used as a buffer.
  1641. // For memory metafile, it is the storage for the metafile.
  1642. if (!(pMFRec->hMem = LocalAlloc(LMEM_FIXED, MF16_BUFSIZE_INIT)))
  1643. goto CreateMetaFileW_error;
  1644. // Write the header.
  1645. if (!AttemptWrite(pMFRec, sizeof(METAHEADER), (LPBYTE)&pMFRec->metaHeader))
  1646. goto CreateMetaFileW_error;
  1647. // Finally, allocate a local handle for the metafile DC. It references
  1648. // the metafile recorder info.
  1649. hdc = hCreateClientObjLink(pMFRec,LO_METADC16_TYPE);
  1650. if (!hdc)
  1651. {
  1652. ERROR_ASSERT(FALSE, "CreateMetaFileW: iAllocHandle failed\n");
  1653. goto CreateMetaFileW_error;
  1654. }
  1655. return(hdc);
  1656. CreateMetaFileW_error:
  1657. if (pMFRec)
  1658. {
  1659. if (pMFRec->hFile != INVALID_HANDLE_VALUE)
  1660. {
  1661. if (!CloseHandle(pMFRec->hFile))
  1662. ASSERTGDI(FALSE, "CloseHandle failed\n");
  1663. if (!DeleteFileW(pMFRec->wszFullPathName))
  1664. WARNING("CreateMetaFileW: DeleteFile failed\n");
  1665. }
  1666. if (pMFRec->hMem)
  1667. if (LocalFree(pMFRec->hMem))
  1668. ASSERTGDI(FALSE, "LocalFree failed");
  1669. if (LocalFree((HANDLE) pMFRec))
  1670. ASSERTGDI(FALSE, "CreateMetaFileW: LocalFree failed\n");
  1671. }
  1672. ERROR_ASSERT(FALSE, "CreateMetaFileW failed\n");
  1673. return((HDC) 0);
  1674. }
  1675. /***************************** Internal Function **************************\
  1676. * HMETAFILE WINAPI CloseMetaFile
  1677. *
  1678. * The CloseMetaFile function closes the metafile device context and creates a
  1679. * metafile handle that can be used to play the metafile by using the
  1680. * PlayMetaFile function.
  1681. *
  1682. * The internal format for a MetaFile has two formats one
  1683. * for a memory MetaFile and one for a disk based MetaFile
  1684. *
  1685. * Effects:
  1686. *
  1687. \***************************************************************************/
  1688. HMETAFILE WINAPI CloseMetaFile(HDC hdc)
  1689. {
  1690. PMFRECORDER16 pmfRec;
  1691. HMETAFILE hmf = (HMETAFILE) 0;
  1692. PUTS("CloseMetaFile\n");
  1693. GET_PMFRECORDER16(pmfRec,hdc);
  1694. ASSERTGDI(pmfRec, "CloseMetaFile: pmfRec is NULL!");
  1695. if (!IS_METADC16_TYPE(hdc) || !pmfRec)
  1696. {
  1697. GdiSetLastError(ERROR_INVALID_HANDLE);
  1698. return(hmf);
  1699. }
  1700. // If the metafile was aborted then free the MetaDC handle memory and go home.
  1701. if (pmfRec->recFlags & METAFILEFAILURE)
  1702. goto CLM_Cleanup;
  1703. // Write the terminate Record
  1704. if (!RecordParms(hdc, 0, 0, (LPWORD)NULL))
  1705. goto CLM_Cleanup;
  1706. // Flush the buffer and update the header record.
  1707. if (pmfRec->metaHeader.mtType == DISKMETAFILE)
  1708. {
  1709. BOOL fRet;
  1710. DWORD dwT;
  1711. ASSERTGDI(pmfRec->metaHeader.mtType == DISKMETAFILE,
  1712. "CloseMetaFile: unknown metafile type");
  1713. // Flush the memory buffer
  1714. fRet = WriteFile(pmfRec->hFile, (LPBYTE)pmfRec->hMem,
  1715. pmfRec->ibBuffer, &dwT, (LPOVERLAPPED)NULL);
  1716. if (!fRet || (dwT != pmfRec->ibBuffer))
  1717. {
  1718. ERROR_ASSERT(FALSE, "CloseMetaFile: Write1 failed\n");
  1719. goto CLM_Cleanup;
  1720. }
  1721. // Rewind the file and write the header out
  1722. if (SetFilePointer(pmfRec->hFile, 0, (LPLONG)NULL, FILE_BEGIN) != 0)
  1723. {
  1724. ERROR_ASSERT(FALSE, "CloseMetaFile: SetFilePointer failed\n");
  1725. goto CLM_Cleanup;
  1726. }
  1727. // Fix up data written to disk as a memory metafile
  1728. pmfRec->metaHeader.mtType = MEMORYMETAFILE;
  1729. fRet = WriteFile(pmfRec->hFile, (LPBYTE)& pmfRec->metaHeader,
  1730. sizeof(METAHEADER), &dwT, (LPOVERLAPPED)NULL);
  1731. pmfRec->metaHeader.mtType = DISKMETAFILE; // restore it
  1732. if (!fRet || (dwT != sizeof(METAHEADER)))
  1733. {
  1734. ERROR_ASSERT(FALSE, "CloseMetaFile: Write2 failed\n");
  1735. goto CLM_Cleanup;
  1736. }
  1737. // Close the file.
  1738. if (!CloseHandle(pmfRec->hFile))
  1739. ASSERTGDI(FALSE, "CloseMetaFile: FileError\n");
  1740. pmfRec->hFile = INVALID_HANDLE_VALUE; // don't close it again below
  1741. }
  1742. else
  1743. {
  1744. HANDLE hMemNew;
  1745. // Flush the header record.
  1746. *(PMETAHEADER) pmfRec->hMem = pmfRec->metaHeader;
  1747. // Realloc memory metafile to exact size
  1748. hMemNew = LocalReAlloc(pmfRec->hMem, pmfRec->metaHeader.mtSize * sizeof(WORD), LMEM_MOVEABLE);
  1749. if (!hMemNew)
  1750. {
  1751. ASSERTGDI(FALSE, "LocalReAlloc failed");
  1752. goto CLM_Cleanup;
  1753. }
  1754. pmfRec->hMem = hMemNew;
  1755. }
  1756. // Allocate and initialize a metafile.
  1757. if (pmfRec->metaHeader.mtType == DISKMETAFILE)
  1758. {
  1759. hmf = GetMetaFileW(pmfRec->wszFullPathName);
  1760. }
  1761. else
  1762. {
  1763. hmf = SetMetaFileBitsAlt((HLOCAL) pmfRec->hMem);
  1764. if (hmf)
  1765. pmfRec->hMem = 0; // don't free it below because it has been transfered
  1766. }
  1767. CLM_Cleanup:
  1768. // Remove the MetaFile from the list of active metafiles
  1769. if (pmfRec->hObjectTable)
  1770. {
  1771. UnlistObjects(hdc);
  1772. if (LocalFree((HANDLE) pmfRec->hObjectTable))
  1773. ASSERTGDI( FALSE, "CloseMetaFile: LocalFree object table failed\n");
  1774. }
  1775. // If the file handle exists at this time, we have an error.
  1776. if (pmfRec->hFile != INVALID_HANDLE_VALUE)
  1777. {
  1778. if (!CloseHandle(pmfRec->hFile))
  1779. ASSERTGDI(FALSE, "CloseHandle failed\n");
  1780. if (!DeleteFileW(pmfRec->wszFullPathName))
  1781. WARNING("CloseMetaFile: DeleteFile failed\n");
  1782. }
  1783. // Free the cache buffer.
  1784. if (pmfRec->hMem)
  1785. if (LocalFree(pmfRec->hMem))
  1786. ASSERTGDI(FALSE, "LocalFree failed");
  1787. // Free the memory for the metafile DC.
  1788. if (LocalFree((HANDLE) pmfRec))
  1789. ASSERTGDI(FALSE, "CloseMetaFile: LocalFree failed\n");
  1790. // Free the handle for the metafile DC.
  1791. if (!bDeleteClientObjLink(hdc))
  1792. RIP("CloseMetaFile - failed bDeleteClientObjLink\n");
  1793. ERROR_ASSERT(hmf != (HMETAFILE) 0, "CloseMetaFile failed\n");
  1794. return(hmf);
  1795. }
  1796. /***************************** Internal Function **************************\
  1797. * CopyMetaFile(hSrcMF, lpFileName)
  1798. *
  1799. * Copies the metafile (hSrcMF) to a new metafile with name lpFileName. The
  1800. * function then returns a handle to this new metafile if the function was
  1801. * successful.
  1802. *
  1803. * Retuns a handle to a new metafile, 0 iff failure
  1804. *
  1805. * IMPLEMENTATION:
  1806. * The source and target metafiles are checked to see if they are both memory
  1807. * metafile and if so a piece of Local memory is allocated and the metafile
  1808. * is simply copied.
  1809. * If this is not the case CreateMetaFile is called with lpFileName and then
  1810. * records are pulled out of the source metafile (using GetEvent) and written
  1811. * into the destination metafile one at a time (using RecordParms).
  1812. *
  1813. * Lock the source
  1814. * if source is a memory metafile and the destination is a memory metafile
  1815. * alloc the same size Local memory as the source
  1816. * copy the bits directly
  1817. * else
  1818. * get a metafile handle by calling CreateMetaFile
  1819. * while GetEvent returns records form the source
  1820. * record the record in the new metafile
  1821. *
  1822. * close the metafile
  1823. *
  1824. * return the new metafile handle
  1825. *
  1826. \***************************************************************************/
  1827. HMETAFILE WINAPI CopyMetaFileA(HMETAFILE hmf, LPCSTR psz)
  1828. {
  1829. UINT cch;
  1830. WCHAR awch[MAX_PATH];
  1831. if (psz != (LPSTR)NULL)
  1832. {
  1833. cch = strlen(psz)+1;
  1834. if (cch > MAX_PATH)
  1835. {
  1836. ERROR_ASSERT(FALSE, "CopyMetaFileA filename too long");
  1837. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  1838. return((HMETAFILE)0);
  1839. }
  1840. vToUnicodeN(awch, MAX_PATH, psz, cch);
  1841. return (CopyMetaFileW(hmf, awch));
  1842. }
  1843. else
  1844. return (CopyMetaFileW(hmf, (LPWSTR)NULL));
  1845. }
  1846. HMETAFILE WINAPI CopyMetaFileW(HMETAFILE hSrcMF, LPCWSTR pwszFileName)
  1847. {
  1848. PMETAFILE16 pMFSource;
  1849. HMETAFILE hMFDest = (HMETAFILE) 0;
  1850. HDC hMDCDest;
  1851. UINT state;
  1852. PUTS("CopyMetaFile\n");
  1853. pMFSource = GET_PMF16(hSrcMF);
  1854. if (pMFSource == NULL)
  1855. {
  1856. GdiSetLastError(ERROR_INVALID_HANDLE);
  1857. return(hMFDest);
  1858. }
  1859. state = (pMFSource->fl & MF16_DISKFILE) ? 2 : 0;
  1860. state |= (pwszFileName) ? 1 : 0;
  1861. switch (state)
  1862. {
  1863. case 0: /* memory -> memory */
  1864. hMFDest = SetMetaFileBitsEx
  1865. (
  1866. pMFSource->metaHeader.mtSize * sizeof(WORD),
  1867. (LPBYTE) pMFSource->hMem
  1868. );
  1869. break;
  1870. case 3: /* disk -> disk */
  1871. hMFDest = CopyFileW(pMFSource->wszFullPathName,
  1872. pwszFileName, FALSE)
  1873. ? GetMetaFileW(pwszFileName) : 0;
  1874. ERROR_ASSERT(hMFDest, "CopyMetaFileW: GetMetaFile Failed\n");
  1875. break;
  1876. case 1:
  1877. case 2:
  1878. if (hMDCDest = CreateMetaFileW(pwszFileName))
  1879. {
  1880. PMFRECORDER16 pMFRecDest;
  1881. PMETARECORD lpMR = NULL;
  1882. GET_PMFRECORDER16(pMFRecDest,hMDCDest);
  1883. while (lpMR = GetEvent(pMFSource, lpMR))
  1884. if ((lpMR == (PMETARECORD) -1)
  1885. || !RecordParms(hMDCDest, (DWORD)lpMR->rdFunction,
  1886. (DWORD)lpMR->rdSize - 3,
  1887. (LPWORD) lpMR->rdParm))
  1888. {
  1889. HMETAFILE hmfT;
  1890. MarkMetaFile(pMFRecDest);
  1891. if (hmfT = CloseMetaFile(hMDCDest))
  1892. DeleteMetaFile(hmfT);
  1893. return((HMETAFILE) 0);
  1894. }
  1895. // touch up the destination metafile header before we close
  1896. // the metafile!
  1897. pMFRecDest->metaHeader.mtNoObjects
  1898. = pMFSource->metaHeader.mtNoObjects;
  1899. ASSERTGDI(sizeof(METAHEADER) == 18, "CopyMetaFile: METAHEADER has changed!");
  1900. hMFDest = CloseMetaFile(hMDCDest);
  1901. }
  1902. break;
  1903. }
  1904. ERROR_ASSERT(hMFDest, "CopyMetaFileW Failing\n");
  1905. return(hMFDest);
  1906. }
  1907. /***************************** Internal Function ***************************\
  1908. * HANDLE WINAPI GetMetaFileBitsEx
  1909. *
  1910. * The GetMetaFileBits function returns a handle to a Windows metafile that
  1911. * contains the specified data describing the metafile.
  1912. *
  1913. * It does not invalidate the metafile handle like Windows!
  1914. *
  1915. * Effects:
  1916. *
  1917. \***************************************************************************/
  1918. UINT WINAPI GetMetaFileBitsEx(HMETAFILE hMF, UINT cbBuffer, LPVOID lpData)
  1919. {
  1920. DWORD cbHave;
  1921. PMETAFILE16 pmf16;
  1922. PUTS("GetMetaFileBitsEx\n");
  1923. pmf16 = GET_PMF16(hMF);
  1924. if (pmf16 == NULL)
  1925. {
  1926. GdiSetLastError(ERROR_INVALID_HANDLE);
  1927. return(0);
  1928. }
  1929. cbHave = pmf16->metaHeader.mtSize * sizeof(WORD);
  1930. // If lpData is NULL, return the size necessary to hold the data.
  1931. if (!lpData)
  1932. return(cbHave);
  1933. // Make sure the input buffer is large enough.
  1934. if (cbBuffer < cbHave)
  1935. return(0);
  1936. // Copy the bits. Win3.1 returns the bits for memory metafile only!
  1937. // We will do the right thing here.
  1938. RtlCopyMemory(lpData, (PBYTE) pmf16->hMem, cbHave);
  1939. // Return the number of bytes copied.
  1940. return(cbHave);
  1941. }
  1942. /***************************** Internal Function **************************\
  1943. * HMETAFILE WINAPI SetMetaFileBitsEx
  1944. *
  1945. * Creates a memory based Windows 3.X metafile from the data provided
  1946. *
  1947. * Returns: HMETAFILE iff succesful.
  1948. *
  1949. * Effects:
  1950. *
  1951. \***************************************************************************/
  1952. HMETAFILE WINAPI SetMetaFileBitsEx(UINT cbBuffer, CONST BYTE *lpData)
  1953. {
  1954. PMETAFILE16 pmf16;
  1955. HMETAFILE hmf;
  1956. PUTS("SetMetaFileBitsEx\n");
  1957. // Verify the input data.
  1958. if (cbBuffer < sizeof(METAHEADER)
  1959. || !IsValidMetaHeader16((PMETAHEADER) lpData))
  1960. {
  1961. ERROR_ASSERT(FALSE, "SetMetaFileBitsEx: Bad input data\n");
  1962. GdiSetLastError(ERROR_INVALID_DATA);
  1963. return((HMETAFILE) 0);
  1964. }
  1965. ERROR_ASSERT(((PMETAHEADER) lpData)->mtType == MEMORYMETAFILE,
  1966. "SetMetaFileBitsEx: Bad mtType\n");
  1967. // Allocate and initialize a metafile.
  1968. // Some Windows metafiles contain bad values in mtSize. As a result,
  1969. // we have to verify and fix the mtSize if neccessary. This is fixed
  1970. // in the following call.
  1971. if (!(pmf16 = pmf16AllocMF16(0, (DWORD) cbBuffer, (PDWORD)lpData, (LPWSTR) NULL)))
  1972. return((HMETAFILE) 0);
  1973. ASSERTGDI(pmf16->metaHeader.mtType == MEMORYMETAFILE,
  1974. "SetMetaFileBitsEx: Bad mtType\n");
  1975. ((PMETAHEADER) pmf16->hMem)->mtType = MEMORYMETAFILE; // just in case
  1976. // Allocate a local handle.
  1977. hmf = hmf16Create(pmf16);
  1978. if (hmf == NULL)
  1979. {
  1980. vFreeMF16(pmf16);
  1981. }
  1982. // Return the metafile handle.
  1983. return(hmf);
  1984. }
  1985. // Similar to Win3.x SetMetaFileBits.
  1986. // It is assumed that hMem is allocated with the LMEM_FIXED option.
  1987. // For internal use only.
  1988. HMETAFILE WINAPI SetMetaFileBitsAlt(HLOCAL hMem)
  1989. {
  1990. PMETAFILE16 pmf16;
  1991. HMETAFILE hmf;
  1992. PUTS("SetMetaFileBitsAlt\n");
  1993. // Allocate and initialize a metafile.
  1994. if (!(pmf16 = pmf16AllocMF16(ALLOCMF16_TRANSFER_BUFFER, 0, (PDWORD) hMem, (LPWSTR) NULL)))
  1995. return((HMETAFILE) 0);
  1996. ASSERTGDI(pmf16->metaHeader.mtType == MEMORYMETAFILE,
  1997. "SetMetaFileBitsAlt: Bad mtType\n");
  1998. ((PMETAHEADER) pmf16->hMem)->mtType = MEMORYMETAFILE; // just in case
  1999. // Allocate a local handle.
  2000. hmf = hmf16Create(pmf16);
  2001. if (hmf == NULL)
  2002. {
  2003. pmf16->hMem = NULL; // let caller free the buffer!
  2004. vFreeMF16(pmf16);
  2005. }
  2006. // Return the metafile handle.
  2007. return(hmf);
  2008. }
  2009. /***************************** Internal Function **************************\
  2010. * GetObject16AndType
  2011. *
  2012. * Returns the object type, eg OBJ_FONT, as well as a the LogObject
  2013. * in Windows 3.x Format
  2014. *
  2015. \***************************************************************************/
  2016. #define MAXOBJECTSIZE sizeof(LOGFONT)
  2017. DWORD GetObject16AndType(HANDLE hObj, LPVOID lpObjBuf16)
  2018. {
  2019. BYTE objBuf32[MAXOBJECTSIZE];
  2020. int iObj;
  2021. PUTS("GetObjectAndType\n");
  2022. ASSERTGDI(MAXOBJECTSIZE >= sizeof(LOGPEN),
  2023. "GetObject16AndType MAXOBJECTSIZE wrong\n");
  2024. if (!GetObject(hObj, MAXOBJECTSIZE, &objBuf32))
  2025. {
  2026. ERROR_ASSERT(FALSE, "GetObject16AndType GetObject Failed\n");
  2027. return(0);
  2028. }
  2029. switch(iObj = GetObjectType(hObj))
  2030. {
  2031. case OBJ_PEN:
  2032. LOGPEN16FROMLOGPEN32((PLOGPEN16)lpObjBuf16,(LPLOGPEN)objBuf32);
  2033. break;
  2034. case OBJ_FONT:
  2035. LOGFONT16FROMLOGFONT32((PLOGFONT16)lpObjBuf16,(LPLOGFONT)objBuf32);
  2036. break;
  2037. default:
  2038. ASSERTGDI(FALSE, "GetObject16AndType unknown object type\n");
  2039. return(0);
  2040. break;
  2041. }
  2042. return((DWORD) iObj);
  2043. }
  2044. /***************************** Internal Function **************************\
  2045. * BOOL UnlistObjects(hMetaDC)
  2046. *
  2047. * Each object has a list of metafiles the object is associated with.
  2048. * UnlistObjects removes hMetaDC from all of its object's metafile lists
  2049. *
  2050. * Effects:
  2051. *
  2052. \***************************************************************************/
  2053. BOOL UnlistObjects(HDC hMetaDC)
  2054. {
  2055. PMETALINK16 pml16;
  2056. UINT iCurObject;
  2057. UINT iCurMetaListEntry;
  2058. POBJECTTABLE pht;
  2059. PMFRECORDER16 pMFRec;
  2060. PUTS("UnlistObjects\n");
  2061. GET_PMFRECORDER16(pMFRec,hMetaDC);
  2062. if (!IS_METADC16_TYPE(hMetaDC) || !pMFRec)
  2063. {
  2064. GdiSetLastError(ERROR_INVALID_HANDLE);
  2065. return((UINT)-1);
  2066. }
  2067. if (pMFRec->metaHeader.mtNoObjects)
  2068. {
  2069. pht = (POBJECTTABLE) pMFRec->hObjectTable;
  2070. ASSERTGDI(pht, "UnlistObject: called even with no handle table");
  2071. // Loop through the objects and unlink this metafile
  2072. for (iCurObject=0; iCurObject < (UINT) pMFRec->metaHeader.mtNoObjects; iCurObject++)
  2073. {
  2074. HANDLE hObj;
  2075. if( (hObj = pht[iCurObject].CurHandle)
  2076. && (!pht[iCurObject].fPreDeleted))
  2077. {
  2078. if (IS_STOCKOBJ(hObj))
  2079. continue;
  2080. ASSERTGDI(LO_TYPE(hObj) != LO_REGION_TYPE,
  2081. "UnlistObjects: unexpected region object");
  2082. pml16 = pmetalink16Get(hObj);
  2083. // It cannot be a empty list.
  2084. ASSERTGDI(pml16, "UnlistObject: pml16 is NULL");
  2085. if (!pml16 || pml16->cMetaDC16 == 0)
  2086. continue;
  2087. // Find the metafile in the objects MetaLink16 list
  2088. for (iCurMetaListEntry=0;
  2089. iCurMetaListEntry<pml16->cMetaDC16;
  2090. iCurMetaListEntry++)
  2091. {
  2092. if(pml16->ahMetaDC16[iCurMetaListEntry] == hMetaDC)
  2093. break;
  2094. }
  2095. ASSERTGDI(iCurMetaListEntry < pml16->cMetaDC16,
  2096. "UnlistObject: Metafile not found");
  2097. // Slide the rest of the metafiles in the list "up"
  2098. for(; iCurMetaListEntry < (pml16->cMetaDC16-1); iCurMetaListEntry++)
  2099. pml16->ahMetaDC16[iCurMetaListEntry] = pml16->ahMetaDC16[iCurMetaListEntry+1];
  2100. pml16->cMetaDC16--; // just got rid of one
  2101. if (pml16->cMetaDC16 == 0)
  2102. {
  2103. // We can only free the METALINK16 if the metalink field is not being used
  2104. if (pml16->metalink)
  2105. {
  2106. pml16->cMetaDC16 = 0;
  2107. pml16->ahMetaDC16[0] = (HDC)NULL;
  2108. }
  2109. else
  2110. {
  2111. if (!bDeleteMetalink16(hObj))
  2112. ASSERTGDI(FALSE,"UnlistObjects: LocalFree Failed\n");
  2113. }
  2114. }
  2115. else
  2116. {
  2117. pml16 = pmetalink16Resize(hObj,pml16->cMetaDC16);
  2118. if (pml16 == NULL)
  2119. {
  2120. ASSERTGDI(FALSE,"UnlistObjects: LocalReAlloc Failed\n");
  2121. return (FALSE);
  2122. }
  2123. }
  2124. }
  2125. } // for
  2126. }
  2127. return(TRUE);
  2128. }
  2129. /******************************Public*Routine******************************\
  2130. * pmf16AllocMF16(fl, cb, pb, pwszFilename)
  2131. *
  2132. * This routine allocates memory for an METAFILE16 and initializes it.
  2133. * Returns a pointer to the new METAFILE16. On error returns NULL.
  2134. * It accepts only windows metafiles.
  2135. *
  2136. * This routine is called by API level METAFILE16 allocation routines
  2137. * CloseMetaFile, GetMetaFile, SetMetaFileBitsEx.
  2138. *
  2139. * Arguments:
  2140. * fl - ALLOCMF16_TRANSFER_BUFFER is set if storage for memory
  2141. * metafile is to be set directly into METAFILE16. Otherwise,
  2142. * a copy of the memory metafile is duplicated.
  2143. * cb - Size of pb in bytes if given. This parameter is given
  2144. * by SetMetaFileBitsEx only. It is used to compare and
  2145. * fixup bad mtSize if necessary.
  2146. * pb - Pointer to a memory metafile if non-null.
  2147. * pwszFilename - Filename of a disk metafile if non-null.
  2148. *
  2149. * History:
  2150. * Fri May 15 14:11:22 1992 -by- Hock San Lee [hockl]
  2151. * Wrote it.
  2152. \**************************************************************************/
  2153. PMETAFILE16 pmf16AllocMF16(DWORD fl, DWORD cb, CONST UNALIGNED DWORD *pb, LPCWSTR pwszFilename)
  2154. {
  2155. PMETAFILE16 pmf16, pmf16Rc = (PMETAFILE16) NULL;
  2156. PUTS("pmf16AllocMF16\n");
  2157. ASSERTGDI(!(fl & ~ALLOCMF16_TRANSFER_BUFFER), "pmf16AllocMF16: Invalid fl");
  2158. // Allocate a new METAFILE16.
  2159. if (!(pmf16 = (PMETAFILE16) LocalAlloc(LMEM_FIXED, sizeof(METAFILE16))))
  2160. goto pmf16AllocMF16_cleanup;
  2161. // Initialize it.
  2162. pmf16->ident = MF16_IDENTIFIER;
  2163. pmf16->hFile = INVALID_HANDLE_VALUE;
  2164. pmf16->hFileMap = (HANDLE) 0;
  2165. pmf16->hMem = (HANDLE) 0;
  2166. pmf16->iMem = 0;
  2167. pmf16->hMetaFileRecord = (HANDLE) 0;
  2168. pmf16->fl = 0L;
  2169. // Memory mapped the disk file if given.
  2170. if (pwszFilename)
  2171. {
  2172. LPWSTR pwszFilePart; // not used
  2173. DWORD cPathname;
  2174. pmf16->fl |= MF16_DISKFILE; // this must be first! See vFreeMF16.
  2175. // Convert the filename to a fully qualified pathname.
  2176. cPathname = GetFullPathNameW(pwszFilename,
  2177. MAX_PATH,
  2178. pmf16->wszFullPathName,
  2179. &pwszFilePart);
  2180. if (!cPathname || cPathname > MAX_PATH)
  2181. {
  2182. ERROR_ASSERT(FALSE, "GetFullPathName failed");
  2183. if (cPathname > MAX_PATH)
  2184. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  2185. goto pmf16AllocMF16_cleanup;
  2186. }
  2187. pmf16->wszFullPathName[cPathname] = 0;
  2188. if ((pmf16->hFile = CreateFileW(pmf16->wszFullPathName, // Filename
  2189. GENERIC_READ, // Read access
  2190. FILE_SHARE_READ, // Share read
  2191. (LPSECURITY_ATTRIBUTES) 0L,// No security
  2192. OPEN_EXISTING, // Re-open
  2193. 0, // file attributes ignored
  2194. (HANDLE) 0)) // no template file
  2195. == INVALID_HANDLE_VALUE)
  2196. {
  2197. // See the comment for Milestones in CreateMetaFileW.
  2198. if ((pmf16->hFile = CreateFileW(pmf16->wszFullPathName,
  2199. GENERIC_READ,
  2200. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2201. (LPSECURITY_ATTRIBUTES) 0L,
  2202. OPEN_EXISTING,
  2203. 0,
  2204. (HANDLE) 0))
  2205. == INVALID_HANDLE_VALUE)
  2206. {
  2207. ERROR_ASSERT(FALSE, "CreateFile failed");
  2208. goto pmf16AllocMF16_cleanup;
  2209. }
  2210. WARNING("pmf16AllocMF16: Opening metafile with read/write share\n");
  2211. }
  2212. if (!(pmf16->hFileMap = CreateFileMappingW(pmf16->hFile,
  2213. (LPSECURITY_ATTRIBUTES) 0L,
  2214. PAGE_READONLY,
  2215. 0L,
  2216. 0L,
  2217. (LPWSTR) NULL)))
  2218. {
  2219. ERROR_ASSERT(FALSE, "CreateFileMapping failed");
  2220. goto pmf16AllocMF16_cleanup;
  2221. }
  2222. if (!(pmf16->hMem = MapViewOfFile(pmf16->hFileMap, FILE_MAP_READ, 0, 0, 0)))
  2223. {
  2224. ERROR_ASSERT(FALSE, "MapViewOfFile failed");
  2225. goto pmf16AllocMF16_cleanup;
  2226. }
  2227. }
  2228. else if (fl & ALLOCMF16_TRANSFER_BUFFER)
  2229. {
  2230. // If this is our memory metafile from MDC, transfer it to METAFILE16.
  2231. pmf16->hMem = (BYTE *) pb;
  2232. }
  2233. else
  2234. {
  2235. // Otherwise, make a copy of memory metafile.
  2236. // We get here only if the caller is SetMetaFileBitsEx. Since some metafiles
  2237. // may contain a bad mtSize that is different than the actual file size, we
  2238. // need to fix it up if necessary!
  2239. DWORD mtSize = ((PMETAHEADER) pb)->mtSize;
  2240. if ((mtSize * 2 > cb) // mtSize greater than filesize
  2241. || (((PWORD) pb)[mtSize - 3] != 3) // EOF record should be 3,0,0
  2242. || (((PWORD) pb)[mtSize - 2] != 0)
  2243. || (((PWORD) pb)[mtSize - 1] != 0))
  2244. {
  2245. // Compute the correct mtSize!
  2246. PMETARECORD pMR;
  2247. DWORD mtSizeMax;
  2248. PUTS("pmf16AllocMF16: verifying mtSize\n");
  2249. mtSize = ((PMETAHEADER) pb)->mtHeaderSize;
  2250. pMR = (PMETARECORD) ((PWORD) pb + ((PMETAHEADER) pb)->mtHeaderSize);
  2251. mtSizeMax = cb / 2 - 3; // max mtSize not counting EOF record
  2252. while (mtSize <= mtSizeMax && pMR->rdFunction != 0)
  2253. {
  2254. mtSize += pMR->rdSize;
  2255. pMR = (PMETARECORD) ((PWORD) pMR + pMR->rdSize);
  2256. }
  2257. if (mtSize > mtSizeMax)
  2258. {
  2259. ERROR_ASSERT(FALSE, "pmf16AllocMF16: incomplete metafile\n");
  2260. goto pmf16AllocMF16_cleanup;
  2261. }
  2262. // Powerpnt uses 0,0,0 for the EOF record! We will change it to 3,0,0 below.
  2263. mtSize += 3; // include EOF record (pMR->rdSize may not be valid)
  2264. if (((PMETAHEADER) pb)->mtSize != mtSize)
  2265. {
  2266. ERROR_ASSERT(FALSE, "pmf16AllocMF16: fixing up bad mtSize\n");
  2267. }
  2268. }
  2269. if (!(pmf16->hMem = LocalAlloc(LMEM_FIXED, mtSize * sizeof(WORD))))
  2270. goto pmf16AllocMF16_cleanup;
  2271. RtlCopyMemory((PBYTE) pmf16->hMem, (PBYTE)pb, mtSize * sizeof(WORD));
  2272. ((PMETAHEADER) pmf16->hMem)->mtSize = mtSize; // update mtSize
  2273. VERIFYGDI(((PWORD) pmf16->hMem)[mtSize - 3] == 3
  2274. && ((PWORD) pmf16->hMem)[mtSize - 2] == 0
  2275. && ((PWORD) pmf16->hMem)[mtSize - 1] == 0,
  2276. "pmf16AllocMF16: fixing up bad EOF metafile record\n");
  2277. ((PWORD) pmf16->hMem)[mtSize - 3] = 3; // update EOF record
  2278. ((PWORD) pmf16->hMem)[mtSize - 2] = 0;
  2279. ((PWORD) pmf16->hMem)[mtSize - 1] = 0;
  2280. }
  2281. // Make a copy of the metafile header.
  2282. pmf16->metaHeader = *(PMETAHEADER) pmf16->hMem;
  2283. pmf16->metaHeader.mtType = (pmf16->fl & MF16_DISKFILE)
  2284. ? DISKMETAFILE
  2285. : MEMORYMETAFILE;
  2286. // Verify metafile header
  2287. if (!IsValidMetaHeader16(&pmf16->metaHeader))
  2288. {
  2289. ERROR_ASSERT(FALSE,
  2290. "pmf16AllocMF16: Metafile has an invalid header; Failing\n");
  2291. goto pmf16AllocMF16_cleanup;
  2292. }
  2293. // Everything is golden.
  2294. pmf16Rc = pmf16;
  2295. // Cleanup and go home.
  2296. pmf16AllocMF16_cleanup:
  2297. if (!pmf16Rc)
  2298. if (pmf16)
  2299. {
  2300. if (fl & ALLOCMF16_TRANSFER_BUFFER)
  2301. pmf16->hMem = NULL; // let caller free the buffer!
  2302. vFreeMF16(pmf16);
  2303. }
  2304. ERROR_ASSERT(pmf16Rc, "pmf16AllocMF16 failed");
  2305. return(pmf16Rc);
  2306. }
  2307. /******************************Public*Routine******************************\
  2308. * vFreeMF16 (pmf16)
  2309. *
  2310. * This is a low level routine which frees the resouces in the METAFILE16.
  2311. *
  2312. * This function is intended to be called from the routines CloseMetaFile
  2313. * and DeleteMetaFile.
  2314. *
  2315. * Arguments:
  2316. * pmf16 - The METAFILE16 to be freed.
  2317. *
  2318. * History:
  2319. * Fri May 15 14:11:22 1992 -by- Hock San Lee [hockl]
  2320. * Wrote it.
  2321. \**************************************************************************/
  2322. VOID vFreeMF16(PMETAFILE16 pmf16)
  2323. {
  2324. PUTS("vFreeMF16\n");
  2325. ASSERTGDI(pmf16->ident == MF16_IDENTIFIER, "Bad METAFILE16");
  2326. // Free the resources.
  2327. if (!(pmf16->fl & MF16_DISKFILE))
  2328. {
  2329. // Free memory metafile.
  2330. if (pmf16->hMem)
  2331. if (LocalFree(pmf16->hMem))
  2332. ASSERTGDI(FALSE, "LocalFree failed");
  2333. }
  2334. else
  2335. {
  2336. // Unmap disk file.
  2337. if (pmf16->hMem)
  2338. if (!UnmapViewOfFile((LPVOID) pmf16->hMem))
  2339. ASSERTGDI(FALSE, "UmmapViewOfFile failed");
  2340. if (pmf16->hFileMap)
  2341. if (!CloseHandle(pmf16->hFileMap))
  2342. ASSERTGDI(FALSE, "CloseHandle failed");
  2343. if (pmf16->hFile != INVALID_HANDLE_VALUE)
  2344. if (!CloseHandle(pmf16->hFile))
  2345. ASSERTGDI(FALSE, "CloseHandle failed");
  2346. }
  2347. // Smash the identifier.
  2348. pmf16->ident = 0;
  2349. // Free the memory.
  2350. if (LocalFree(pmf16))
  2351. ASSERTGDI(FALSE, "LocalFree failed");
  2352. }