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.

495 lines
13 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: DIB.C
  3. *
  4. * Handles all API routines for the device independent bitmap sub-dll of
  5. * the ole dll.
  6. *
  7. * Created: Oct-1990
  8. *
  9. * Copyright (c) 1990, 1991 Microsoft Corporation
  10. *
  11. * History:
  12. * Srinik, Raor (../../1990,91) Designed, coded
  13. *
  14. \***************************************************************************/
  15. #include <windows.h>
  16. #include "dll.h"
  17. #include "pict.h"
  18. void FARINTERNAL DibGetExtents (LPSTR, LPPOINT);
  19. #pragma alloc_text(_TEXT, DibSaveToStream, DibLoadFromStream, DibStreamRead, GetBytes, PutBytes, PutStrWithLen, DibGetExtents)
  20. OLEOBJECTVTBL vtblDIB = {
  21. ErrQueryProtocol, // check whether the speced protocol is supported
  22. DibRelease, // Release
  23. ErrShow, // Show
  24. ErrPlay, // show
  25. DibGetData, // Get the object data
  26. ErrSetData, // Set the object data
  27. ErrSetTargetDevice, //
  28. ErrSetBounds, // set viewport bounds
  29. DibEnumFormat, // enumerate supported formats
  30. ErrSetColorScheme, //
  31. DibRelease, // delete
  32. ErrSetHostNames, //
  33. DibSaveToStream, // write to file
  34. DibClone, // clone object
  35. ErrCopyFromLink, // Create embedded from Lnk
  36. DibEqual, // compares the given objects for data equality
  37. DibCopy, // copy to clip
  38. DibDraw, // draw the object
  39. ErrActivate, // open
  40. ErrExecute, // excute
  41. ErrClose, // Stop
  42. ErrUpdate, // Update
  43. ErrReconnect, // Reconnect
  44. ErrObjectConvert, // convert object to specified type
  45. ErrGetUpdateOptions, // update options
  46. ErrSetUpdateOptions, // update options
  47. ObjRename, // Change Object name
  48. ObjQueryName, // Get current object name
  49. ObjQueryType, // Object type
  50. DibQueryBounds, // QueryBounds
  51. ObjQuerySize, // Find the size of the object
  52. ErrQueryOpen, // Query open
  53. ErrQueryOutOfDate, // query whether object is current
  54. ErrQueryRelease, // release related stuff
  55. ErrQueryRelease,
  56. ErrQueryRelease,
  57. ErrRequestData, // requestdata
  58. ErrObjectLong, // objectLong
  59. DibChangeData // change data of the existing object
  60. };
  61. OLESTATUS FARINTERNAL DibRelease (lpobj)
  62. LPOBJECT_DIB lpobj;
  63. {
  64. HOBJECT hobj;
  65. if (lpobj->hDIB){
  66. GlobalFree (lpobj->hDIB);
  67. lpobj->hDIB = NULL;
  68. }
  69. if (lpobj->head.lhclientdoc)
  70. DocDeleteObject ((LPOLEOBJECT) lpobj);
  71. if (hobj = lpobj->head.hobj){
  72. lpobj->head.hobj = NULL;
  73. GlobalUnlock (hobj);
  74. GlobalFree (hobj);
  75. }
  76. return OLE_OK;
  77. }
  78. OLESTATUS FARINTERNAL DibSaveToStream (lpobj, lpstream)
  79. LPOBJECT_DIB lpobj;
  80. LPOLESTREAM lpstream;
  81. {
  82. LPSTR lpDIBbuf;
  83. if (!lpobj->hDIB)
  84. return OLE_ERROR_BLANK;
  85. if (PutBytes (lpstream, (LPSTR) &dwVerToFile, sizeof(LONG)))
  86. return OLE_ERROR_STREAM;
  87. if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG)))
  88. return OLE_ERROR_STREAM;
  89. if (PutStrWithLen (lpstream, (LPSTR)"DIB"))
  90. return OLE_ERROR_STREAM;
  91. if (PutBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
  92. return OLE_ERROR_STREAM;
  93. if (PutBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
  94. return OLE_ERROR_STREAM;
  95. lpobj->sizeBytes = GlobalSize (lpobj->hDIB);
  96. if (PutBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
  97. return OLE_ERROR_STREAM;
  98. if (!(lpDIBbuf = GlobalLock (lpobj->hDIB)))
  99. return OLE_ERROR_MEMORY;
  100. if (PutBytes (lpstream, lpDIBbuf, lpobj->sizeBytes))
  101. return OLE_ERROR_STREAM;
  102. GlobalUnlock (lpobj->hDIB);
  103. return OLE_OK;
  104. }
  105. OLESTATUS FARINTERNAL DibClone (lpobjsrc, lpclient, lhclientdoc, lpobjname, lplpobj)
  106. LPOBJECT_DIB lpobjsrc;
  107. LPOLECLIENT lpclient;
  108. LHCLIENTDOC lhclientdoc;
  109. LPSTR lpobjname;
  110. LPOBJECT_DIB FAR * lplpobj;
  111. {
  112. if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
  113. return OLE_ERROR_HANDLE;
  114. if (!(*lplpobj = DibCreateObject (lpobjsrc->hDIB, lpclient, FALSE,
  115. lhclientdoc, lpobjname, lpobjsrc->head.ctype)))
  116. return OLE_ERROR_MEMORY;
  117. else
  118. return OLE_OK;
  119. }
  120. OLESTATUS FARINTERNAL DibEqual (lpobj1, lpobj2)
  121. LPOBJECT_DIB lpobj1;
  122. LPOBJECT_DIB lpobj2;
  123. {
  124. if (CmpGlobals (lpobj1->hDIB, lpobj1->hDIB))
  125. return OLE_OK;
  126. return OLE_ERROR_NOT_EQUAL;
  127. }
  128. OLESTATUS FARINTERNAL DibCopy (lpobj)
  129. LPOBJECT_DIB lpobj;
  130. {
  131. HANDLE hDIB;
  132. if (!lpobj->hDIB)
  133. return OLE_ERROR_BLANK;
  134. if (!(hDIB = DuplicateGlobal (lpobj->hDIB, GMEM_MOVEABLE)))
  135. return OLE_ERROR_MEMORY;
  136. SetClipboardData (CF_DIB, hDIB);
  137. return OLE_OK;
  138. }
  139. OLESTATUS FARINTERNAL DibQueryBounds (lpobj, lpRc)
  140. LPOBJECT_DIB lpobj;
  141. LPRECT lpRc;
  142. {
  143. Puts("DibQueryBounds");
  144. if (!lpobj->hDIB)
  145. return OLE_ERROR_BLANK;
  146. lpRc->left = 0;
  147. lpRc->top = 0;
  148. lpRc->right = (int) lpobj->head.cx;
  149. lpRc->bottom = (int) lpobj->head.cy;
  150. return OLE_OK;
  151. }
  152. OLECLIPFORMAT FARINTERNAL DibEnumFormat (lpobj, cfFormat)
  153. LPOBJECT_DIB lpobj;
  154. OLECLIPFORMAT cfFormat;
  155. {
  156. if (!cfFormat)
  157. return CF_DIB;
  158. return NULL;
  159. }
  160. OLESTATUS FARINTERNAL DibGetData (lpobj, cfFormat, lphandle)
  161. LPOBJECT_DIB lpobj;
  162. OLECLIPFORMAT cfFormat;
  163. LPHANDLE lphandle;
  164. {
  165. if (cfFormat != CF_DIB)
  166. return OLE_ERROR_FORMAT;
  167. if (!(*lphandle = lpobj->hDIB))
  168. return OLE_ERROR_BLANK;
  169. return OLE_OK;
  170. }
  171. LPOBJECT_DIB FARINTERNAL DibCreateObject (hDIB, lpclient, fDelete, lhclientdoc, lpobjname, objType)
  172. HANDLE hDIB;
  173. LPOLECLIENT lpclient;
  174. BOOL fDelete;
  175. LHCLIENTDOC lhclientdoc;
  176. LPSTR lpobjname;
  177. LONG objType;
  178. {
  179. LPOBJECT_DIB lpobj;
  180. if (lpobj = DibCreateBlank (lhclientdoc, lpobjname, objType)) {
  181. if (DibChangeData (lpobj, hDIB, lpclient, fDelete) != OLE_OK) {
  182. DibRelease (lpobj);
  183. lpobj = NULL;
  184. }
  185. }
  186. return lpobj;
  187. }
  188. // If the routine fails then the object will be left with it's old data.
  189. // If fDelete is TRUE, then hNewDIB will be deleted whether the routine
  190. // is successful or not.
  191. OLESTATUS FARINTERNAL DibChangeData (lpobj, hNewDIB, lpclient, fDelete)
  192. LPOBJECT_DIB lpobj;
  193. HANDLE hNewDIB;
  194. LPOLECLIENT lpclient;
  195. BOOL fDelete;
  196. {
  197. BITMAPINFOHEADER bi;
  198. DWORD dwSize;
  199. LPBITMAPINFOHEADER lpBi;
  200. if (!hNewDIB)
  201. return OLE_ERROR_BLANK;
  202. lpBi = (LPBITMAPINFOHEADER) &bi;
  203. if (!fDelete) {
  204. if (!(hNewDIB = DuplicateGlobal (hNewDIB, GMEM_MOVEABLE)))
  205. return OLE_ERROR_MEMORY;
  206. }
  207. else {
  208. // change the ownership to yourself
  209. HANDLE htmp;
  210. if (!(htmp = GlobalReAlloc (hNewDIB, 0L, GMEM_MODIFY|GMEM_SHARE))) {
  211. htmp = DuplicateGlobal (hNewDIB, GMEM_MOVEABLE);
  212. GlobalFree (hNewDIB);
  213. if (!htmp)
  214. return OLE_ERROR_MEMORY;
  215. }
  216. hNewDIB = htmp;
  217. }
  218. if (!(lpBi = (LPBITMAPINFOHEADER) GlobalLock (hNewDIB))) {
  219. GlobalFree (hNewDIB);
  220. return OLE_ERROR_MEMORY;
  221. }
  222. dwSize = GlobalSize (hNewDIB);
  223. if (lpobj->hDIB)
  224. GlobalFree (lpobj->hDIB);
  225. DibUpdateStruct (lpobj, lpclient, hNewDIB, lpBi, dwSize);
  226. return OLE_OK;
  227. }
  228. void INTERNAL DibUpdateStruct (lpobj, lpclient, hDIB, lpBi, dwBytes)
  229. LPOBJECT_DIB lpobj;
  230. LPOLECLIENT lpclient;
  231. HANDLE hDIB;
  232. LPBITMAPINFOHEADER lpBi;
  233. DWORD dwBytes;
  234. {
  235. POINT point;
  236. lpobj->head.lpclient = lpclient;
  237. lpobj->sizeBytes = dwBytes;
  238. #ifdef OLD
  239. lpobj->xSize = point.x = (int) lpBi->biWidth;
  240. lpobj->ySize = point.y = (int) lpBi->biHeight;
  241. ConvertToHimetric (&point);
  242. #else
  243. DibGetExtents ((LPSTR) lpBi, &point);
  244. #endif
  245. lpobj->head.cx = (LONG) point.x;
  246. lpobj->head.cy = (LONG) point.y;
  247. lpobj->hDIB = hDIB;
  248. }
  249. OLESTATUS FARINTERNAL DibLoadFromStream (lpstream, lpclient, lhclientdoc, lpobjname, lplpoleobject, objType)
  250. LPOLESTREAM lpstream;
  251. LPOLECLIENT lpclient;
  252. LHCLIENTDOC lhclientdoc;
  253. LPSTR lpobjname;
  254. LPOLEOBJECT FAR * lplpoleobject;
  255. LONG objType;
  256. {
  257. LPOBJECT_DIB lpobj = NULL;
  258. *lplpoleobject = NULL;
  259. if (!(lpobj = DibCreateBlank (lhclientdoc, lpobjname, objType)))
  260. return OLE_ERROR_MEMORY;
  261. lpobj->head.lpclient = lpclient;
  262. if (GetBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
  263. goto errLoad;
  264. if (GetBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
  265. goto errLoad;
  266. if (GetBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
  267. goto errLoad;
  268. if (DibStreamRead (lpstream, lpobj)) {
  269. *lplpoleobject = (LPOLEOBJECT) lpobj;
  270. return OLE_OK;
  271. }
  272. errLoad:
  273. OleDelete ((LPOLEOBJECT) lpobj);
  274. return OLE_ERROR_STREAM;
  275. }
  276. LPOBJECT_DIB FARINTERNAL DibCreateBlank (lhclientdoc, lpobjname, objType)
  277. LHCLIENTDOC lhclientdoc;
  278. LPSTR lpobjname;
  279. LONG objType;
  280. {
  281. HOBJECT hobj;
  282. LPOBJECT_DIB lpobj;
  283. if((hobj = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof (OBJECT_DIB)))
  284. == NULL)
  285. return NULL;
  286. if (!(lpobj = (LPOBJECT_DIB) GlobalLock (hobj))){
  287. GlobalFree (hobj);
  288. return NULL;
  289. }
  290. // The structure is ZERO initialized at allocation time. So only the
  291. // fields that need to be filled with values other than ZEROS are
  292. // initialized below
  293. lpobj->head.objId[0] = 'L';
  294. lpobj->head.objId[1] = 'E';
  295. lpobj->head.mm = MM_TEXT;
  296. lpobj->head.ctype = objType;
  297. lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblDIB;
  298. lpobj->head.iTable = INVALID_INDEX;
  299. lpobj->head.hobj = hobj;
  300. if (objType == CT_STATIC)
  301. DocAddObject ((LPCLIENTDOC) lhclientdoc,
  302. (LPOLEOBJECT) lpobj, lpobjname);
  303. return lpobj;
  304. }
  305. BOOL INTERNAL DibStreamRead (lpstream, lpobj)
  306. LPOLESTREAM lpstream;
  307. LPOBJECT_DIB lpobj;
  308. {
  309. HANDLE hDIBbuf;
  310. LPSTR lpDIBbuf;
  311. BOOL retVal = FALSE;
  312. BITMAPINFOHEADER bi;
  313. if (GetBytes (lpstream, (LPSTR) &bi, sizeof(bi)))
  314. return FALSE;
  315. if (hDIBbuf = GlobalAlloc (GMEM_MOVEABLE, lpobj->sizeBytes)) {
  316. if (lpDIBbuf = (LPSTR)GlobalLock (hDIBbuf)){
  317. *((LPBITMAPINFOHEADER) lpDIBbuf) = bi;
  318. if (!GetBytes (lpstream, lpDIBbuf+sizeof(bi),
  319. (lpobj->sizeBytes - sizeof(bi)))) {
  320. lpobj->hDIB = hDIBbuf;
  321. #ifdef OLD
  322. //!!! this info should be part of the stream
  323. if (!lpobj->head.cx) {
  324. DibGetExtents ((LPSTR) lpDIBbuf, &point);
  325. lpobj->head.cx = (LONG) point.x;
  326. lpobj->head.cy = (LONG) point.y;
  327. }
  328. #endif
  329. retVal = TRUE;
  330. }
  331. GlobalUnlock(hDIBbuf);
  332. }
  333. //* Hang on to the memory allocated for the DIB
  334. }
  335. return retVal;
  336. }
  337. OLESTATUS FARINTERNAL DibPaste (lpclient, lhclientdoc, lpobjname, lplpoleobject, objType)
  338. LPOLECLIENT lpclient;
  339. LHCLIENTDOC lhclientdoc;
  340. LPSTR lpobjname;
  341. LPOLEOBJECT FAR * lplpoleobject;
  342. LONG objType;
  343. {
  344. HANDLE hDIB;
  345. if ((hDIB = GetClipboardData (CF_DIB)) == NULL)
  346. return OLE_ERROR_MEMORY;
  347. *lplpoleobject = (LPOLEOBJECT) DibCreateObject (hDIB, lpclient, FALSE,
  348. lhclientdoc, lpobjname, objType);
  349. return OLE_OK;
  350. }
  351. void FARINTERNAL DibGetExtents (lpData, lpPoint)
  352. LPSTR lpData;
  353. LPPOINT lpPoint;
  354. {
  355. #define HIMET_PER_METER 100000L // number of HIMETRIC units / meter
  356. LPBITMAPINFOHEADER lpbmi;
  357. lpbmi = (LPBITMAPINFOHEADER)lpData;
  358. if (!(lpbmi->biXPelsPerMeter && lpbmi->biYPelsPerMeter)) {
  359. HDC hdc;
  360. hdc = GetDC (NULL);
  361. lpbmi->biXPelsPerMeter = MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
  362. 10000, 254);
  363. lpbmi->biYPelsPerMeter = MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
  364. 10000, 254);
  365. ReleaseDC (NULL, hdc);
  366. }
  367. lpPoint->x = (int) (lpbmi->biWidth * HIMET_PER_METER
  368. / lpbmi->biXPelsPerMeter);
  369. lpPoint->y = -(int) (lpbmi->biHeight * HIMET_PER_METER
  370. / lpbmi->biYPelsPerMeter);
  371. }