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.

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