Source code of Windows XP (NT5)
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.

645 lines
16 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name:MF.C (Extensible Compound Documents - Metafile)
  3. *
  4. * PURPOSE:Handles all API routines for the metafile sub-dll of the ole dll.
  5. *
  6. * Created: 1990
  7. *
  8. * Copyright (c) 1990, 1991 Microsoft Corporation
  9. *
  10. * History:
  11. *
  12. * Raor, Srinik (../../1990,91) Designed, coded
  13. *
  14. \***************************************************************************/
  15. #include <windows.h>
  16. #include "dll.h"
  17. #include "pict.h"
  18. WORD wGDIds = NULL;
  19. OLESTATUS FARINTERNAL wCreateDummyMetaFile (LPOBJECT_MF, int, int);
  20. #pragma alloc_text(_TEXT, MfSaveToStream, MfLoadFromStream, GetBytes, PutBytes, PutStrWithLen, MfQueryBounds, OleIsDcMeta, GetGDIds, IsMetaDC)
  21. OLEOBJECTVTBL vtblMF = {
  22. ErrQueryProtocol, // check whether the speced protocol is supported
  23. MfRelease, // Release
  24. ErrShow, // show
  25. ErrPlay, // play
  26. MfGetData, // Get the object data
  27. ErrSetData, // Set the object data
  28. ErrSetTargetDevice,//
  29. ErrSetBounds, // set viewport bounds
  30. MfEnumFormat, // enumerate supported formats
  31. ErrSetColorScheme, //
  32. MfRelease, // delete
  33. ErrSetHostNames, //
  34. MfSaveToStream, // write to file
  35. MfClone, // clone object
  36. ErrCopyFromLink, // Create embedded from Lnk
  37. MfEqual, // compares the given objects for data equality
  38. MfCopy, // copy to clip
  39. MfDraw, // draw the object
  40. ErrActivate, // open
  41. ErrExecute, // excute
  42. ErrClose, // stop
  43. ErrUpdate, // Update
  44. ErrReconnect, // Reconnect
  45. ErrObjectConvert, // convert object to specified type
  46. ErrGetUpdateOptions, // update options
  47. ErrSetUpdateOptions, // update options
  48. ObjRename, // Change Object name
  49. ObjQueryName, // Get current object name
  50. ObjQueryType, // Object type
  51. MfQueryBounds, // QueryBounds
  52. ObjQuerySize, // Find the size of the object
  53. ErrQueryOpen, // Query open
  54. ErrQueryOutOfDate, // query whether object is current
  55. ErrQueryRelease, // release related stuff
  56. ErrQueryRelease,
  57. ErrQueryRelease,
  58. ErrRequestData, // requestdata
  59. ErrObjectLong, // objectLong
  60. MfChangeData // change data of the existing object
  61. };
  62. OLESTATUS FARINTERNAL MfRelease (lpobj)
  63. LPOBJECT_MF lpobj;
  64. {
  65. HOBJECT hobj;
  66. if (lpobj->mfp.hMF) {
  67. DeleteMetaFile (lpobj->mfp.hMF);
  68. lpobj->mfp.hMF = NULL;
  69. }
  70. if (lpobj->hmfp)
  71. GlobalFree (lpobj->hmfp);
  72. if (lpobj->head.lhclientdoc)
  73. DocDeleteObject ((LPOLEOBJECT)lpobj);
  74. if (hobj = lpobj->head.hobj) {
  75. lpobj->head.hobj = NULL;
  76. GlobalUnlock (hobj);
  77. GlobalFree (hobj);
  78. }
  79. return OLE_OK;
  80. }
  81. OLESTATUS FARINTERNAL MfSaveToStream (lpobj, lpstream)
  82. LPOBJECT_MF lpobj;
  83. LPOLESTREAM lpstream;
  84. {
  85. OLESTATUS retVal = OLE_ERROR_STREAM;
  86. HANDLE hBits;
  87. LPSTR lpBits;
  88. if (!lpobj->mfp.hMF)
  89. return OLE_ERROR_BLANK;
  90. if (PutBytes (lpstream, (LPSTR) &dwVerToFile, sizeof(LONG)))
  91. return OLE_ERROR_STREAM;
  92. if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG)))
  93. return OLE_ERROR_STREAM;
  94. if (PutStrWithLen(lpstream, (LPSTR)"METAFILEPICT"))
  95. return OLE_ERROR_STREAM;
  96. if (PutBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
  97. return OLE_ERROR_STREAM;
  98. if (PutBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
  99. return OLE_ERROR_STREAM;
  100. if (PutBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
  101. return OLE_ERROR_STREAM;
  102. if (!(hBits = GetMetaFileBits (lpobj->mfp.hMF)))
  103. return OLE_ERROR_MEMORY;
  104. if (lpBits = (LPSTR) GlobalLock (hBits)) {
  105. if (!PutBytes (lpstream, (LPSTR)&lpobj->mfp, sizeof(METAFILEPICT)))
  106. if (!PutBytes (lpstream, (LPSTR)lpBits,
  107. lpobj->sizeBytes - sizeof(METAFILEPICT)))
  108. retVal = OLE_OK;
  109. GlobalUnlock(hBits);
  110. }
  111. else
  112. retVal = OLE_ERROR_MEMORY;
  113. lpobj->mfp.hMF = SetMetaFileBits (hBits);
  114. return retVal;
  115. }
  116. OLESTATUS FARINTERNAL MfClone (lpobjsrc, lpclient, lhclientdoc, lpobjname, lplpobj)
  117. LPOBJECT_MF lpobjsrc;
  118. LPOLECLIENT lpclient;
  119. LHCLIENTDOC lhclientdoc;
  120. LPSTR lpobjname;
  121. LPOBJECT_MF FAR * lplpobj;
  122. {
  123. LPOBJECT_MF lpobjMf;
  124. HANDLE hmf;
  125. *lplpobj = NULL;
  126. if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
  127. return OLE_ERROR_HANDLE;
  128. if (!(hmf = CopyMetaFile (lpobjsrc->mfp.hMF, NULL)))
  129. return OLE_ERROR_MEMORY;
  130. if (lpobjMf = MfCreateBlank (lhclientdoc, lpobjname,
  131. lpobjsrc->head.ctype)) {
  132. lpobjMf->mfp = lpobjsrc->mfp;
  133. lpobjMf->sizeBytes = lpobjsrc->sizeBytes;
  134. lpobjMf->mfp.hMF = hmf;
  135. lpobjMf->head.lpclient = lpclient;
  136. lpobjMf->head.mm = lpobjMf->mfp.mm;
  137. MfSetExtents (lpobjMf);
  138. *lplpobj = lpobjMf;
  139. return OLE_OK;
  140. }
  141. return OLE_ERROR_MEMORY;
  142. }
  143. OLESTATUS FARINTERNAL MfEqual (lpobj1, lpobj2)
  144. LPOBJECT_MF lpobj1;
  145. LPOBJECT_MF lpobj2;
  146. {
  147. HANDLE hBits1 = NULL, hBits2 = NULL;
  148. OLESTATUS retval = OLE_ERROR_NOT_EQUAL;
  149. if (!(hBits1 = GetMetaFileBits (lpobj1->mfp.hMF)))
  150. goto errEqual;
  151. if (!(hBits2 = GetMetaFileBits (lpobj2->mfp.hMF)))
  152. goto errEqual;
  153. if (CmpGlobals (hBits1, hBits2))
  154. retval = OLE_OK;
  155. errEqual:
  156. if (hBits1)
  157. lpobj1->mfp.hMF = SetMetaFileBits (hBits1);
  158. if (hBits2)
  159. lpobj2->mfp.hMF = SetMetaFileBits (hBits2);
  160. return retval;
  161. }
  162. OLESTATUS FARINTERNAL MfCopy (LPOBJECT_MF lpobj)
  163. {
  164. HANDLE hMF;
  165. if (!(hMF = CopyMetaFile (lpobj->mfp.hMF, NULL)))
  166. return OLE_ERROR_MEMORY;
  167. return (MfCopyToClip (lpobj, hMF));
  168. }
  169. OLESTATUS FARINTERNAL MfQueryBounds (lpobj, lpRc)
  170. LPOBJECT_MF lpobj;
  171. LPRECT lpRc;
  172. {
  173. Puts("MfQueryBounds");
  174. if (!lpobj->mfp.hMF)
  175. return OLE_ERROR_BLANK;
  176. // Bounds are given in MM_HIMETRIC mode.
  177. lpRc->left = 0;
  178. lpRc->top = 0;
  179. lpRc->right = (int) lpobj->head.cx;
  180. lpRc->bottom = (int) lpobj->head.cy;
  181. return OLE_OK;
  182. }
  183. OLECLIPFORMAT FARINTERNAL MfEnumFormat (lpobj, cfFormat)
  184. LPOBJECT_MF lpobj;
  185. OLECLIPFORMAT cfFormat;
  186. {
  187. if (!cfFormat)
  188. return CF_METAFILEPICT;
  189. return NULL;
  190. }
  191. OLESTATUS FARINTERNAL MfGetData (lpobj, cfFormat, lphandle)
  192. LPOBJECT_MF lpobj;
  193. OLECLIPFORMAT cfFormat;
  194. LPHANDLE lphandle;
  195. {
  196. if (cfFormat != CF_METAFILEPICT)
  197. return OLE_ERROR_FORMAT;
  198. if (!(*lphandle = GetHmfp (lpobj)))
  199. return OLE_ERROR_BLANK;
  200. return OLE_OK;
  201. }
  202. LPOBJECT_MF FARINTERNAL MfCreateObject (hMeta, lpclient, fDelete, lhclientdoc, lpobjname, objType)
  203. HANDLE hMeta;
  204. LPOLECLIENT lpclient;
  205. BOOL fDelete;
  206. LHCLIENTDOC lhclientdoc;
  207. LPSTR lpobjname;
  208. LONG objType;
  209. {
  210. LPOBJECT_MF lpobj;
  211. if (lpobj = MfCreateBlank (lhclientdoc, lpobjname, objType)) {
  212. if (MfChangeData (lpobj, hMeta, lpclient, fDelete) != OLE_OK) {
  213. MfRelease (lpobj);
  214. lpobj = NULL;
  215. }
  216. }
  217. return lpobj;
  218. }
  219. // If the routine fails then the object will be left with it's old data.
  220. // If fDelete is TRUE, then hMeta, and the hMF it contains will be deleted
  221. // whether the routine is successful or not.
  222. OLESTATUS FARINTERNAL MfChangeData (lpobj, hMeta, lpclient, fDelete)
  223. LPOBJECT_MF lpobj;
  224. HANDLE hMeta;
  225. LPOLECLIENT lpclient;
  226. BOOL fDelete;
  227. {
  228. HANDLE hNewMF;
  229. LPMETAFILEPICT lpMetaPict;
  230. if ((lpMetaPict = (LPMETAFILEPICT) GlobalLock (hMeta)) == NULL) {
  231. if (fDelete)
  232. GlobalFree (hMeta);
  233. return OLE_ERROR_MEMORY;
  234. }
  235. GlobalUnlock (hMeta);
  236. if (!fDelete) {
  237. if (!(hNewMF = CopyMetaFile (lpMetaPict->hMF, NULL)))
  238. return OLE_ERROR_MEMORY;
  239. }
  240. else {
  241. hNewMF = lpMetaPict->hMF;
  242. }
  243. return MfUpdateStruct (lpobj, lpclient, hMeta, lpMetaPict, hNewMF, fDelete);
  244. }
  245. OLESTATUS INTERNAL MfUpdateStruct (lpobj, lpclient, hMeta, lpMetaPict, hMF, fDelete)
  246. LPOBJECT_MF lpobj;
  247. LPOLECLIENT lpclient;
  248. HANDLE hMeta;
  249. LPMETAFILEPICT lpMetaPict;
  250. HANDLE hMF;
  251. BOOL fDelete;
  252. {
  253. OLESTATUS retVal;
  254. DWORD size;
  255. HANDLE hOldMF;
  256. hOldMF = lpobj->mfp.hMF;
  257. ASSERT(lpMetaPict->mm == MM_ANISOTROPIC, "Wrong mapping mode")
  258. if (lpMetaPict->mm != MM_ANISOTROPIC)
  259. retVal = OLE_ERROR_METAFILE;
  260. else if (!(size = MfGetSize (&hMF)))
  261. retVal = OLE_ERROR_BLANK;
  262. else {
  263. lpobj->mfp = *lpMetaPict;
  264. lpobj->mfp.hMF = hMF;
  265. lpobj->sizeBytes = size + sizeof(METAFILEPICT);
  266. lpobj->head.lpclient = lpclient;
  267. lpobj->head.mm = lpobj->mfp.mm;
  268. if (lpobj->hmfp) {
  269. GlobalFree (lpobj->hmfp);
  270. lpobj->hmfp = NULL;
  271. }
  272. MfSetExtents (lpobj);
  273. if (hOldMF)
  274. DeleteMetaFile (hOldMF);
  275. retVal = OLE_OK;
  276. }
  277. if (retVal != OLE_OK)
  278. DeleteMetaFile (hMF);
  279. if (fDelete)
  280. GlobalFree (hMeta);
  281. return retVal;
  282. }
  283. LPOBJECT_MF FARINTERNAL MfCreateBlank(lhclientdoc, lpobjname, objType)
  284. LHCLIENTDOC lhclientdoc;
  285. LPSTR lpobjname;
  286. LONG objType;
  287. {
  288. HOBJECT hobj;
  289. LPOBJECT_MF lpobj;
  290. if(!(hobj = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof (OBJECT_MF))))
  291. return NULL;
  292. if (!(lpobj = (LPOBJECT_MF) GlobalLock (hobj))){
  293. GlobalFree (hobj);
  294. return NULL;
  295. }
  296. lpobj->head.objId[0] = 'L';
  297. lpobj->head.objId[1] = 'E';
  298. lpobj->head.ctype = objType;
  299. lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblMF;
  300. lpobj->head.iTable = INVALID_INDEX;
  301. lpobj->head.mm = MM_TEXT;
  302. lpobj->head.hobj = hobj;
  303. if (objType == CT_STATIC)
  304. DocAddObject ((LPCLIENTDOC) lhclientdoc,
  305. (LPOLEOBJECT) lpobj, lpobjname);
  306. // Unlock will be done at object deletion time.
  307. return lpobj;
  308. }
  309. OLESTATUS FARINTERNAL MfLoadFromStream (lpstream, lpclient, lhclientdoc, lpobjname, lplpobj, objType)
  310. LPOLESTREAM lpstream;
  311. LPOLECLIENT lpclient;
  312. LHCLIENTDOC lhclientdoc;
  313. LPSTR lpobjname;
  314. LPOLEOBJECT FAR * lplpobj;
  315. LONG objType;
  316. {
  317. LPOBJECT_MF lpobj = NULL;
  318. OLESTATUS retVal = OLE_ERROR_STREAM;
  319. HANDLE hBits;
  320. LPSTR lpBits;
  321. DWORD dwSizeMfp = NULL;
  322. // Class name would've been read by this time.
  323. *lplpobj = NULL;
  324. if (!(lpobj = MfCreateBlank (lhclientdoc, lpobjname, objType)))
  325. return OLE_ERROR_MEMORY;
  326. lpobj->head.lpclient = lpclient;
  327. if (GetBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
  328. goto errLoad;
  329. if (GetBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
  330. goto errLoad;
  331. if (GetBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
  332. goto errLoad;
  333. if (!lpobj->sizeBytes) {
  334. retVal = OLE_ERROR_BLANK;
  335. goto errLoad;
  336. }
  337. // if we are reading a MAC object we want to skip this
  338. if (HIWORD(dwVerFromFile) == OS_WIN16) {
  339. if (GetBytes (lpstream, (LPSTR) &lpobj->mfp, sizeof(METAFILEPICT)))
  340. goto errLoad;
  341. dwSizeMfp = sizeof(METAFILEPICT);
  342. }
  343. retVal = OLE_ERROR_MEMORY;
  344. if (!(hBits = GlobalAlloc (GMEM_MOVEABLE, lpobj->sizeBytes - dwSizeMfp)))
  345. goto errLoad;
  346. if (!(lpBits = (LPSTR)GlobalLock (hBits)))
  347. goto errMem;
  348. if (GetBytes (lpstream, (LPSTR)lpBits, lpobj->sizeBytes - dwSizeMfp)) {
  349. retVal = OLE_ERROR_MEMORY;
  350. GlobalUnlock (hBits);
  351. goto errMem;
  352. }
  353. lpobj->head.mm = lpobj->mfp.mm;
  354. GlobalUnlock (hBits);
  355. if (HIWORD(dwVerFromFile) == OS_WIN16) {
  356. if (!(lpobj->mfp.hMF = SetMetaFileBits (hBits)))
  357. goto errMem;
  358. }
  359. else {
  360. // if we are reading a MAC object we want to delete the original
  361. // presentation data and show some rectangle
  362. GlobalFree (hBits);
  363. lpobj->mfp.xExt = (int) lpobj->head.cx;
  364. lpobj->mfp.yExt = (int) lpobj->head.cy;
  365. if ((retVal = wCreateDummyMetaFile (lpobj, lpobj->mfp.xExt,
  366. lpobj->mfp.yExt)) != OLE_OK)
  367. goto errLoad;
  368. }
  369. MfSetExtents (lpobj);
  370. *lplpobj = (LPOLEOBJECT) lpobj;
  371. return OLE_OK;
  372. errMem:
  373. GlobalFree (hBits);
  374. errLoad:
  375. OleDelete ((LPOLEOBJECT)lpobj);
  376. return retVal;
  377. }
  378. OLESTATUS FARINTERNAL MfPaste (lpclient, lhclientdoc, lpobjname, lplpoleobject, objType)
  379. LPOLECLIENT lpclient;
  380. LHCLIENTDOC lhclientdoc;
  381. LPSTR lpobjname;
  382. LPOLEOBJECT FAR * lplpoleobject;
  383. LONG objType;
  384. {
  385. HANDLE hMeta;
  386. *lplpoleobject = NULL;
  387. if((hMeta = GetClipboardData (CF_METAFILEPICT)) == NULL)
  388. return OLE_ERROR_MEMORY;
  389. if (!(*lplpoleobject = (LPOLEOBJECT) MfCreateObject (hMeta, lpclient,
  390. FALSE, lhclientdoc,
  391. lpobjname, objType)))
  392. return OLE_ERROR_MEMORY;
  393. return OLE_OK;
  394. }
  395. OLESTATUS INTERNAL MfCopyToClip (lpobj, hMF)
  396. LPOBJECT_MF lpobj;
  397. HANDLE hMF;
  398. {
  399. LPMETAFILEPICT lpMeta;
  400. HANDLE hMeta;
  401. if (!(hMeta = GlobalAlloc (GMEM_MOVEABLE, sizeof(METAFILEPICT))))
  402. return OLE_ERROR_MEMORY;
  403. if (lpMeta = (LPMETAFILEPICT) GlobalLock(hMeta)){
  404. *lpMeta = lpobj->mfp;
  405. if (hMF)
  406. lpMeta->hMF = hMF;
  407. else
  408. lpobj->mfp.hMF = NULL;
  409. GlobalUnlock (hMeta);
  410. SetClipboardData(CF_METAFILEPICT, hMeta);
  411. return OLE_OK;
  412. }
  413. GlobalFree(hMeta);
  414. return OLE_ERROR_MEMORY;
  415. }
  416. void FARINTERNAL MfSetExtents (LPOBJECT_MF lpobj)
  417. {
  418. if (lpobj->mfp.xExt > 0) {
  419. // The extents are assumed to be in MM_HIMETIRC units
  420. lpobj->head.cx = (LONG) lpobj->mfp.xExt;
  421. lpobj->head.cy = (LONG) - lpobj->mfp.yExt;
  422. }
  423. }
  424. DWORD INTERNAL MfGetSize (lphmf)
  425. LPHANDLE lphmf;
  426. {
  427. HANDLE hBits;
  428. DWORD size;
  429. if ((hBits = GetMetaFileBits (*lphmf)) == NULL)
  430. return NULL;
  431. size = GlobalSize(hBits);
  432. *lphmf = SetMetaFileBits (hBits);
  433. return size;
  434. }
  435. HANDLE INTERNAL GetHmfp (lpobj)
  436. LPOBJECT_MF lpobj;
  437. {
  438. HANDLE hmfp;
  439. LPMETAFILEPICT lpmfp = NULL;
  440. if (lpobj->hmfp)
  441. return lpobj->hmfp;
  442. if (!(hmfp = GlobalAlloc (GMEM_MOVEABLE, sizeof(METAFILEPICT))))
  443. return NULL;
  444. if (!(lpmfp = (LPMETAFILEPICT) GlobalLock (hmfp))) {
  445. GlobalFree (hmfp);
  446. return NULL;
  447. }
  448. *lpmfp = lpobj->mfp;
  449. GlobalUnlock (hmfp);
  450. return (lpobj->hmfp = hmfp);
  451. }
  452. BOOL FAR PASCAL OleIsDcMeta (hdc)
  453. HDC hdc;
  454. {
  455. if (!bWLO && (wWinVer == 0x0003)) {
  456. WORD wDsAlias, wGDIcs = HIWORD(SaveDC);
  457. WORD wOffset = LOWORD(((DWORD)SaveDC));
  458. WORD FAR PASCAL AllocCStoDSAlias (WORD);
  459. WORD FAR PASCAL FreeSelector (WORD);
  460. if (!wGDIds) {
  461. wDsAlias = AllocCStoDSAlias (wGDIcs);
  462. wGDIds = GetGDIds (MAKELONG(wOffset, wDsAlias));
  463. FreeSelector (wDsAlias);
  464. }
  465. return IsMetaDC (hdc, wGDIds);
  466. }
  467. else
  468. return (GetDeviceCaps (hdc, TECHNOLOGY) == DT_METAFILE);
  469. }
  470. OLESTATUS FARINTERNAL wCreateDummyMetaFile (
  471. LPOBJECT_MF lpobj,
  472. int xExt,
  473. int yExt)
  474. {
  475. HDC hMetaDC;
  476. if (!(hMetaDC = CreateMetaFile (NULL)))
  477. return OLE_ERROR_MEMORY;
  478. SetWindowOrg (hMetaDC, 0, 0);
  479. SetWindowExt (hMetaDC, xExt, yExt);
  480. Rectangle (hMetaDC, 0, 0, xExt, yExt);
  481. if (!(lpobj->mfp.hMF = CloseMetaFile (hMetaDC)))
  482. return OLE_ERROR_MEMORY;
  483. lpobj->mfp.mm = MM_ANISOTROPIC;
  484. lpobj->sizeBytes = MfGetSize (&lpobj->mfp.hMF) + sizeof(METAFILEPICT);
  485. return OLE_OK;
  486. }