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.

1115 lines
28 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // ole2util.cpp
  5. //
  6. // Contents:
  7. // Ole internal utility routines
  8. //
  9. // Classes:
  10. //
  11. // Functions:
  12. //
  13. // History:
  14. // 06/01/94 - AlexGo - UtQueryPictFormat now supports
  15. // enhanced metafiles
  16. // 03/18/94 - AlexGo - fixed UtGetPresStreamName (incorrect
  17. // string processing)
  18. // 01/11/94 - ChrisWe - don't reference unlocked handle in
  19. // UtConvertBitmapToDib
  20. // 01/11/94 - alexgo - added VDATEHEAP macro to every function
  21. // 12/07/93 - ChrisWe - removed incorrect uses of (LPOLESTR);
  22. // removed duplicate GetClassFromDataObj function, which
  23. // is the same as UtGetClassID
  24. // 11/30/93 - ChrisWe - continue file cleanup; don't open
  25. // streams in UtRemoveExtraOlePresStreams()
  26. // 11/28/93 - ChrisWe - file cleanup and inspection;
  27. // reformatted many functions
  28. // 11/22/93 - ChrisWe - replace overloaded ==, != with
  29. // IsEqualIID and IsEqualCLSID
  30. // 06/28/93 - SriniK - added UtGetDibExtents
  31. // 11/16/92 - JasonFul - created; moved contents here from util.cpp
  32. //
  33. //-----------------------------------------------------------------------------
  34. #include <le2int.h>
  35. #pragma SEG(ole2util)
  36. NAME_SEG(Ole2Utils)
  37. ASSERTDATA
  38. #define WIDTHBYTES(i) ((i+31)/32*4)
  39. #define PALETTESIZE 256 /* Number of entries in the system palette */
  40. // REVIEW, according to the spec, IDataObject::EnumFormatEtc() is only
  41. // required to service one dwDirection DATADIR_ value at a time. This
  42. // function has been asking it to do more than one at a time, and expecting
  43. // return of FORMATETCs that match all the requested directions. Code
  44. // seen in OleRegEnumFormatEtc() checks on creation, and fails if any
  45. // value other than plain DATADIR_GET or plain DATADIR_SET is specified
  46. // so this has clearly never worked for OLE1, or registration database lookups
  47. // since the only caller of UtIsFormatSupported has always asked for both
  48. // at the same time.
  49. #pragma SEG(UtIsFormatSupported)
  50. FARINTERNAL_(BOOL) UtIsFormatSupported(IDataObject FAR* lpDataObj,
  51. DWORD dwDirection, CLIPFORMAT cfFormat)
  52. {
  53. VDATEHEAP();
  54. FORMATETC formatetc; // a place to fetch formats from the enumerator
  55. IEnumFORMATETC FAR* penm; // enumerates the formats of [lpDataObj]
  56. ULONG ulNumFetched; // a count of the number of formats fetched
  57. HRESULT error; // the error state so far
  58. // try to get the enumerator from the data object
  59. error = lpDataObj->EnumFormatEtc(dwDirection, &penm);
  60. if (error != NOERROR)
  61. {
  62. if (FAILED(error))
  63. return FALSE;
  64. else
  65. {
  66. CLSID clsid;
  67. // Use reg db; this case is primarily for the OLE1
  68. // compatibility code since it may talk to a data
  69. // object from a server in the same process as
  70. // the server.
  71. if (UtGetClassID(lpDataObj, &clsid) != TRUE)
  72. return(FALSE);
  73. // synthesize an enumerator
  74. // REVIEW, if the data object is synthesized for
  75. // the OLE1 object, why doesn't that implementation
  76. // go ahead and synthesize this? Why does it have
  77. // to be done like this? What if it's on the clipboard
  78. // and someone wants to use it?
  79. if (OleRegEnumFormatEtc(clsid, dwDirection, &penm)
  80. != NOERROR)
  81. return FALSE;
  82. Assert(penm);
  83. }
  84. }
  85. // check for the format we're looking for
  86. while(NOERROR == (error = penm->Next(1, &formatetc, &ulNumFetched)))
  87. {
  88. if ((ulNumFetched == 1) && (formatetc.cfFormat == cfFormat))
  89. break;
  90. }
  91. // release the enumerator
  92. penm->Release();
  93. // if error isn't S_FALSE, we fetched an item, and broke out of the
  94. // while loop above --> the format was found. Return TRUE indicating
  95. // that the format is supported
  96. return(error == NOERROR ? TRUE : FALSE);
  97. }
  98. #pragma SEG(UtDupPalette)
  99. FARINTERNAL_(HPALETTE) UtDupPalette(HPALETTE hpalette)
  100. {
  101. VDATEHEAP();
  102. WORD cEntries; // holds the number of entries in the palette
  103. HANDLE hLogPal; // ia a handle to a new logical palette
  104. LPLOGPALETTE pLogPal; // is a pointer to the new logical palette
  105. HPALETTE hpaletteNew = NULL; // the new palette we will return
  106. if (0 == GetObject(hpalette, sizeof(cEntries), &cEntries))
  107. return(NULL);
  108. if (NULL == (hLogPal = GlobalAlloc(GMEM_MOVEABLE,
  109. sizeof (LOGPALETTE) +
  110. cEntries * sizeof (PALETTEENTRY))))
  111. return(NULL);
  112. if (NULL == (pLogPal = (LPLOGPALETTE)GlobalLock(hLogPal)))
  113. goto errRtn;
  114. if (0 == GetPaletteEntries(hpalette, 0, cEntries,
  115. pLogPal->palPalEntry))
  116. goto errRtn;
  117. pLogPal->palVersion = 0x300;
  118. pLogPal->palNumEntries = cEntries;
  119. if (NULL == (hpaletteNew = CreatePalette(pLogPal)))
  120. goto errRtn;
  121. errRtn:
  122. if (pLogPal)
  123. GlobalUnlock(hLogPal);
  124. if (hLogPal)
  125. GlobalFree(hLogPal);
  126. AssertSz(hpaletteNew, "Warning: UtDupPalette Failed");
  127. return(hpaletteNew);
  128. }
  129. //+-------------------------------------------------------------------------
  130. //
  131. // Function: UtFormatToTymed
  132. //
  133. // Synopsis: gets the right TYMED for the given rendering format
  134. //
  135. // Effects:
  136. //
  137. // Arguments: [cf] -- the clipboard format
  138. //
  139. // Requires:
  140. //
  141. // Returns: one of the TYMED enumeration
  142. //
  143. // Signals:
  144. //
  145. // Modifies:
  146. //
  147. // Algorithm:
  148. //
  149. // History: dd-mmm-yy Author Comment
  150. // 07-Jul-94 alexgo added EMF's
  151. //
  152. // Notes: This should only be called for formats that we can
  153. // render
  154. //
  155. //--------------------------------------------------------------------------
  156. #pragma SEG(UtFormatToTymed)
  157. FARINTERNAL_(DWORD) UtFormatToTymed(CLIPFORMAT cf)
  158. {
  159. VDATEHEAP();
  160. if( cf == CF_METAFILEPICT )
  161. {
  162. return TYMED_MFPICT;
  163. }
  164. else if( cf == CF_BITMAP )
  165. {
  166. return TYMED_GDI;
  167. }
  168. else if( cf == CF_DIB )
  169. {
  170. return TYMED_HGLOBAL;
  171. }
  172. else if( cf == CF_ENHMETAFILE )
  173. {
  174. return TYMED_ENHMF;
  175. }
  176. else if( cf == CF_PALETTE )
  177. {
  178. LEWARN(1,"Trying to render CF_PALETTE");
  179. return TYMED_GDI;
  180. }
  181. LEDebugOut((DEB_WARN, "WARNING: trying to render clipformat (%lx)\n",
  182. cf));
  183. return TYMED_HGLOBAL;
  184. }
  185. //+-------------------------------------------------------------------------
  186. //
  187. // Function: UtQueryPictFormat
  188. //
  189. // Synopsis: finds our "preferred" drawing formatetc from the given
  190. // data object
  191. //
  192. // Effects:
  193. //
  194. // Arguments: [lpSrcDataObj] -- the source data object
  195. // [lpforetc] -- where to stuff the preferred format
  196. //
  197. // Requires:
  198. //
  199. // Returns:
  200. //
  201. // Signals:
  202. //
  203. // Modifies:
  204. //
  205. // Algorithm:
  206. //
  207. // History: dd-mmm-yy Author Comment
  208. // 01-Jun-94 alexgo rewrite/now supports Enhanced Metafiles
  209. //
  210. // Notes:
  211. //
  212. //--------------------------------------------------------------------------
  213. #pragma SEG(UtQueryPictFormat)
  214. FARINTERNAL_(BOOL) UtQueryPictFormat(LPDATAOBJECT lpSrcDataObj,
  215. LPFORMATETC lpforetc)
  216. {
  217. FORMATETC foretctemp; // local copy of current values of format desc
  218. VDATEHEAP();
  219. LEDebugOut((DEB_ITRACE, "%p _IN UtQueryPictFormat ( %p , %p )\n",
  220. NULL, lpSrcDataObj, lpforetc));
  221. // copy format descriptor
  222. foretctemp = *lpforetc;
  223. // set values and query for our preferred formats in order of
  224. // preference
  225. foretctemp.cfFormat = CF_METAFILEPICT;
  226. foretctemp.tymed = TYMED_MFPICT;
  227. if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR)
  228. {
  229. goto QuerySuccess;
  230. }
  231. foretctemp.cfFormat = CF_ENHMETAFILE;
  232. foretctemp.tymed = TYMED_ENHMF;
  233. if( lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR )
  234. {
  235. goto QuerySuccess;
  236. }
  237. foretctemp.cfFormat = CF_DIB;
  238. foretctemp.tymed = TYMED_HGLOBAL;
  239. if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR)
  240. {
  241. goto QuerySuccess;
  242. }
  243. foretctemp.cfFormat = CF_BITMAP;
  244. foretctemp.tymed = TYMED_GDI;
  245. if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR)
  246. {
  247. goto QuerySuccess;
  248. }
  249. LEDebugOut((DEB_ITRACE, "%p OUT UtQueryPictFormat ( %lu )\n",
  250. NULL, FALSE));
  251. return FALSE;
  252. QuerySuccess:
  253. // data object supports this format; change passed in
  254. // format to match
  255. lpforetc->cfFormat = foretctemp.cfFormat;
  256. lpforetc->tymed = foretctemp.tymed;
  257. // return success
  258. LEDebugOut((DEB_ITRACE, "%p OUT UtQueryPictFormat ( %lu )\n",
  259. NULL, TRUE));
  260. return(TRUE);
  261. }
  262. #pragma SEG(UtConvertDibToBitmap)
  263. FARINTERNAL_(HBITMAP) UtConvertDibToBitmap(HANDLE hDib)
  264. {
  265. VDATEHEAP();
  266. LPBITMAPINFOHEADER lpbmih;
  267. HDC hdc; // the device context to create the bitmap for
  268. size_t uBitsOffset; // the offset to where the image begins in the DIB
  269. HBITMAP hBitmap; // the bitmap we'll return
  270. if (!(lpbmih = (LPBITMAPINFOHEADER)GlobalLock(hDib)))
  271. return(NULL);
  272. if (!(hdc = GetDC(NULL))) // Get screen DC.
  273. {
  274. // REVIEW: we may have to use the target device of this
  275. // cache node.
  276. return(NULL);
  277. }
  278. uBitsOffset = sizeof(BITMAPINFOHEADER) +
  279. (lpbmih->biClrUsed ? lpbmih->biClrUsed :
  280. UtPaletteSize(lpbmih));
  281. hBitmap = CreateDIBitmap(hdc, lpbmih, CBM_INIT,
  282. ((BYTE *)lpbmih)+uBitsOffset,
  283. (LPBITMAPINFO) lpbmih, DIB_RGB_COLORS);
  284. // release the DC
  285. ReleaseDC(NULL, hdc);
  286. return hBitmap;
  287. }
  288. //+----------------------------------------------------------------------------
  289. //
  290. // Function:
  291. // UtConvertBitmapToDib, internal
  292. //
  293. // Synopsis:
  294. // Creates a Device Independent Bitmap capturing the content of
  295. // the argument bitmap.
  296. //
  297. // Arguments:
  298. // [hBitmap] -- Handle to the bitmap to convert
  299. // [hpal] -- color palette for the bitmap; may be null for
  300. // default stock palette
  301. //
  302. // Returns:
  303. // Handle to the DIB. May be null if any part of the conversion
  304. // failed.
  305. //
  306. // Notes:
  307. //
  308. // History:
  309. // 11/29/93 - ChrisWe - file inspection and cleanup
  310. // 07/18/94 - DavePl - fixed for 16, 32, bpp bitmaps
  311. //
  312. //-----------------------------------------------------------------------------
  313. FARINTERNAL_(HANDLE) UtConvertBitmapToDib(HBITMAP hBitmap, HPALETTE hpal)
  314. {
  315. VDATEHEAP();
  316. HDC hScreenDC;
  317. BITMAP bm; // bitmap for hBitmap
  318. UINT uBits; // number of color bits for bitmap
  319. size_t uBmiSize; // size of bitmap info for the DIB
  320. size_t biSizeImage; // temp to hold value in the handle memory
  321. HANDLE hBmi; // handle for the new DIB bitmap we'll create
  322. LPBITMAPINFOHEADER lpBmi; // pointer to the actual data area for DIB
  323. HANDLE hDib = NULL; // the DIB we'll return
  324. BOOL fSuccess = FALSE;
  325. DWORD dwCompression;
  326. BOOL fDeletePalette = FALSE;
  327. if (NULL == hBitmap)
  328. {
  329. return(NULL);
  330. }
  331. // if no palette provided, use the default
  332. if (NULL == hpal)
  333. {
  334. // This block fixes NTBUG #13029. The problem is that on a palette
  335. // device (ie a 256 color video driver), we don't get passed the palette
  336. // that is used by the DDB. So, we build the palette based on what
  337. // is currently selected into the system palette.
  338. // POSTPPC:
  339. //
  340. // We should change the clipboard code that calls this to ask for
  341. // CF_PALETTE from the IDataObject that the DDB was obtained from, that
  342. // way we know we get the colors that the calling app really intended
  343. HDC hDCGlobal = GetDC(NULL);
  344. if(!hDCGlobal)
  345. return NULL;
  346. int iRasterCaps = GetDeviceCaps(hDCGlobal, RASTERCAPS);
  347. ReleaseDC(NULL, hDCGlobal);
  348. if ((iRasterCaps & RC_PALETTE))
  349. {
  350. // Based the following code from the win sdk MYPAL example program.
  351. // this creates a palette out of the currently active palette.
  352. HANDLE hLogPal = GlobalAlloc (GHND,
  353. (sizeof (LOGPALETTE) +
  354. (sizeof (PALETTEENTRY) * (PALETTESIZE))));
  355. // if we are OOM, return failure now, because we aren't going
  356. // to make it through the allocations later on.
  357. if (!hLogPal)
  358. return NULL;
  359. LPLOGPALETTE pLogPal = (LPLOGPALETTE)GlobalLock (hLogPal);
  360. // 0x300 is a magic number required by GDI
  361. pLogPal->palVersion = 0x300;
  362. pLogPal->palNumEntries = PALETTESIZE;
  363. // fill in intensities for all palette entry colors
  364. for (int iLoop = 0; iLoop < PALETTESIZE; iLoop++)
  365. {
  366. *((WORD *) (&pLogPal->palPalEntry[iLoop].peRed)) = (WORD)iLoop;
  367. pLogPal->palPalEntry[iLoop].peBlue = 0;
  368. pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT;
  369. }
  370. // create a logical color palette according the information
  371. // in the LOGPALETTE structure.
  372. hpal = CreatePalette ((LPLOGPALETTE) pLogPal) ;
  373. GlobalUnlock(hLogPal);
  374. GlobalFree(hLogPal);
  375. if (!hpal)
  376. return NULL;
  377. fDeletePalette = TRUE;
  378. }
  379. else
  380. {
  381. hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  382. }
  383. }
  384. if (NULL == GetObject(hBitmap, sizeof(bm), (LPVOID)&bm))
  385. {
  386. return(NULL);
  387. }
  388. uBits = bm.bmPlanes * bm.bmBitsPixel;
  389. // Based on the number of bits per pixel, set up the size
  390. // of the color table, and the compression type as per the
  391. // the following table:
  392. //
  393. //
  394. // BPP Palette Size Compression
  395. // ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~
  396. // 1,2,4,8 2^BPP * sizeof(RGBQUAD) None
  397. // 16, 32 3 * sizeof(DWORD) masks BI_BITFIELDS
  398. // 24 0 None
  399. if (16 == bm.bmBitsPixel || 32 == bm.bmBitsPixel)
  400. {
  401. uBmiSize = sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
  402. dwCompression = BI_BITFIELDS;
  403. }
  404. else if (24 == bm.bmBitsPixel)
  405. {
  406. uBmiSize = sizeof(BITMAPINFOHEADER);
  407. dwCompression = BI_RGB;
  408. }
  409. else
  410. {
  411. Assert( bm.bmBitsPixel == 1 ||
  412. bm.bmBitsPixel == 2 ||
  413. bm.bmBitsPixel == 4 ||
  414. bm.bmBitsPixel == 8 );
  415. // VGA and EGA are planar devices on Chicago, so uBits needs
  416. // to be used when determining the size of the bitmap info +
  417. // the size of the color table.
  418. uBmiSize = sizeof(BITMAPINFOHEADER) +
  419. (1 << uBits) * sizeof(RGBQUAD);
  420. dwCompression = BI_RGB;
  421. }
  422. // Allocate enough memory to hold the BITMAPINFOHEADER
  423. hBmi = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)uBmiSize);
  424. if (NULL == hBmi)
  425. {
  426. return NULL;
  427. }
  428. lpBmi = (LPBITMAPINFOHEADER) GlobalLock(hBmi);
  429. if (NULL == lpBmi)
  430. {
  431. GlobalFree(hBmi);
  432. return NULL;
  433. }
  434. // Set up any interesting non-zero fields
  435. lpBmi->biSize = (LONG)sizeof(BITMAPINFOHEADER);
  436. lpBmi->biWidth = (LONG) bm.bmWidth;
  437. lpBmi->biHeight = (LONG) bm.bmHeight;
  438. lpBmi->biPlanes = 1;
  439. lpBmi->biBitCount = (WORD) uBits;
  440. lpBmi->biCompression = dwCompression;
  441. // Grab the screen DC and set out palette into it
  442. hScreenDC = GetDC(NULL);
  443. if (NULL == hScreenDC)
  444. {
  445. GlobalUnlock(hBmi);
  446. goto errRtn;
  447. }
  448. // Call GetDIBits with a NULL lpBits parm, so that it will calculate
  449. // the biSizeImage field for us
  450. GetDIBits(hScreenDC, // DC
  451. hBitmap, // Bitmap handle
  452. 0, // First scan line
  453. bm.bmHeight, // Number of scan lines
  454. NULL, // Buffer
  455. (LPBITMAPINFO)lpBmi, // BITMAPINFO
  456. DIB_RGB_COLORS);
  457. // If the driver did not fill in the biSizeImage field, make one up
  458. if (0 == lpBmi->biSizeImage)
  459. {
  460. LEDebugOut((DEB_WARN, "WARNING: biSizeImage was not computed for us\n"));
  461. lpBmi->biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * uBits) * bm.bmHeight;
  462. }
  463. // Realloc the buffer to provide space for the bits. Use a new handle so
  464. // that in the failure case we do not lose the exiting handle, which we
  465. // would need to clean up properly.
  466. biSizeImage = lpBmi->biSizeImage;
  467. GlobalUnlock(hBmi);
  468. hDib = GlobalReAlloc(hBmi, (uBmiSize + biSizeImage), GMEM_MOVEABLE);
  469. if (NULL == hDib)
  470. {
  471. goto errRtn;
  472. }
  473. // If the realloc succeeded, we can get rid of the old handle
  474. hBmi = NULL;
  475. // re-acquire the pointer to the handle
  476. lpBmi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
  477. if (NULL == lpBmi)
  478. {
  479. goto errRtn;
  480. }
  481. hpal = SelectPalette(hScreenDC, hpal, FALSE);
  482. RealizePalette(hScreenDC);
  483. // Call GetDIBits with a NON-NULL lpBits parm, and get the actual bits
  484. if (GetDIBits(hScreenDC, // DC
  485. hBitmap, // HBITMAP
  486. 0, // First scan line
  487. (WORD)lpBmi->biHeight, // Count of scan lines
  488. ((BYTE FAR *)lpBmi)+uBmiSize, // Bitmap bits
  489. (LPBITMAPINFO)lpBmi, // BITMAPINFOHEADER
  490. DIB_RGB_COLORS) // Palette style
  491. )
  492. {
  493. fSuccess = TRUE;
  494. }
  495. GlobalUnlock(hDib);
  496. errRtn:
  497. if (hScreenDC)
  498. {
  499. // Select back the old palette into the screen DC
  500. SelectPalette(hScreenDC, hpal, FALSE);
  501. ReleaseDC(NULL, hScreenDC);
  502. }
  503. if (fDeletePalette)
  504. {
  505. DeleteObject(hpal);
  506. }
  507. // If we failed, we need to free up the header and the DIB
  508. // memory
  509. if (FALSE == fSuccess)
  510. {
  511. if (hBmi)
  512. {
  513. GlobalFree(hBmi);
  514. }
  515. if (hDib)
  516. {
  517. GlobalFree(hDib);
  518. hDib = NULL;
  519. }
  520. }
  521. return(hDib);
  522. }
  523. //+----------------------------------------------------------------------------
  524. //
  525. // Function:
  526. // UtPaletteSize, internal
  527. //
  528. // Synopsis:
  529. // Returns the size of a color table for a palette given the
  530. // number of bits of color desired.
  531. //
  532. // Basically, the number of color table entries is:
  533. //
  534. // 1BPP
  535. // 1<<1 = 2
  536. //
  537. // 4BPP
  538. // if pbmi->biClrUsed is not zero and is less than 16, then use pbmi->biClrUsed,
  539. // otherwise use 1 << 4 = 16
  540. //
  541. // 8BPP
  542. // if pbmi->biClrUsed is not zero and is less than 256, then use pbmi->biClrUsed,
  543. // otherwise use 1 << 8 = 256
  544. //
  545. // 16BPP
  546. // if pbmi->biCompression is BITFIELDS then there are three color entries,
  547. // otherwise no color entries.
  548. //
  549. // 24BPP
  550. // pbmi->biCompression must be BI_RGB, there is no color table.
  551. //
  552. // 32BPP
  553. // if pbmi->biCompression is BITFIELDS then there are three color entries,
  554. // otherwise no color entries.
  555. //
  556. //
  557. // There is never a case with a color table larger than 256 colors.
  558. //
  559. // Arguments:
  560. // [lpHeader] -- ptr to BITMAPINFOHEADER structure
  561. //
  562. // Returns:
  563. // Size in bytes of color information
  564. //
  565. // Notes:
  566. //
  567. // History:
  568. // 11/29/93 - ChrisWe - change bit count argument to unsigned,
  569. // and return value to size_t
  570. //
  571. // 07/18/94 - DavePl - Fixed for 16, 24, 32bpp DIBs
  572. //
  573. //-----------------------------------------------------------------------------
  574. FARINTERNAL_(size_t) UtPaletteSize(BITMAPINFOHEADER * pbmi)
  575. {
  576. DWORD dwSize;
  577. WORD biBitCount = pbmi->biBitCount;
  578. VDATEHEAP();
  579. // Compute size of color table information in a DIB.
  580. if (8 >= biBitCount)
  581. {
  582. if (pbmi->biClrUsed && (pbmi->biClrUsed <= (DWORD) (1 << biBitCount)) )
  583. {
  584. dwSize = pbmi->biClrUsed * sizeof(RGBQUAD);
  585. }
  586. else
  587. {
  588. Assert(0 == pbmi->biClrUsed);
  589. dwSize = (1 << biBitCount) * sizeof(RGBQUAD);
  590. }
  591. }
  592. else if (BI_BITFIELDS == pbmi->biCompression)
  593. {
  594. Assert(24 != biBitCount); // BI_BITFIELDS should never be set for 24 bit.
  595. dwSize = 3 * sizeof(RGBQUAD);
  596. }
  597. else
  598. {
  599. dwSize = 0;
  600. }
  601. Assert( (dwSize < 65536) && "Palette size overflows WORD");
  602. return dwSize;
  603. }
  604. //+-------------------------------------------------------------------------
  605. //
  606. // Function: UtGetDibExtents
  607. //
  608. // Synopsis: Returns the size of the DIB in HIMETRIC units
  609. //
  610. // Effects:
  611. //
  612. // Arguments: [lpbmi] -- the BITMAPINFOHEADER for the DIB
  613. // [plWidth] -- OUT param for width
  614. // [plHeight] -- OUT param for height
  615. //
  616. // Requires:
  617. //
  618. // Returns:
  619. //
  620. // Signals:
  621. //
  622. // Modifies:
  623. //
  624. // Algorithm:
  625. //
  626. // History: dd-mmm-yy Author Comment
  627. // 04-Aug-94 Davepl Corrected logic
  628. //
  629. // Notes:
  630. //
  631. //--------------------------------------------------------------------------
  632. FARINTERNAL_(void) UtGetDibExtents(LPBITMAPINFOHEADER lpbmi,
  633. LONG FAR* plWidth, LONG FAR* plHeight)
  634. {
  635. VDATEHEAP();
  636. #define HIMET_PER_METER 100000L // number of HIMETRIC units / meter
  637. if (!(lpbmi->biXPelsPerMeter && lpbmi->biYPelsPerMeter))
  638. {
  639. HDC hdc;
  640. hdc = GetDC(NULL);
  641. if(!hdc)
  642. {
  643. *plWidth = 0;
  644. *plHeight = 0;
  645. return;
  646. }
  647. lpbmi->biXPelsPerMeter = MulDiv(GetDeviceCaps(hdc, LOGPIXELSX),
  648. 10000, 254);
  649. lpbmi->biYPelsPerMeter = MulDiv(GetDeviceCaps(hdc, LOGPIXELSY),
  650. 10000, 254);
  651. ReleaseDC(NULL, hdc);
  652. }
  653. *plWidth = (lpbmi->biWidth * HIMET_PER_METER / lpbmi->biXPelsPerMeter);
  654. *plHeight= (lpbmi->biHeight * HIMET_PER_METER / lpbmi->biYPelsPerMeter);
  655. // no longer need this
  656. #undef HIMET_PER_METER
  657. }
  658. #pragma SEG(UtGetClassID)
  659. FARINTERNAL_(BOOL) UtGetClassID(LPUNKNOWN lpUnk, CLSID FAR* lpClsid)
  660. {
  661. VDATEHEAP();
  662. LPOLEOBJECT lpOleObj; // IOleObject pointer
  663. LPPERSIST lpPersist; // IPersist pointer
  664. // try to ask it as an object
  665. if (lpUnk->QueryInterface(IID_IOleObject,
  666. (LPLPVOID)&lpOleObj) == NOERROR)
  667. {
  668. lpOleObj->GetUserClassID(lpClsid);
  669. lpOleObj->Release();
  670. return(TRUE);
  671. }
  672. // try to ask it as a persistent object
  673. if (lpUnk->QueryInterface(IID_IPersist,
  674. (LPLPVOID)&lpPersist) == NOERROR)
  675. {
  676. lpPersist->GetClassID(lpClsid);
  677. lpPersist->Release();
  678. return(TRUE);
  679. }
  680. *lpClsid = CLSID_NULL;
  681. return(FALSE);
  682. }
  683. #pragma SEG(UtGetIconData)
  684. FARINTERNAL UtGetIconData(LPDATAOBJECT lpSrcDataObj, REFCLSID rclsid,
  685. LPFORMATETC lpforetc, LPSTGMEDIUM lpstgmed)
  686. {
  687. VDATEHEAP();
  688. CLSID clsid = rclsid;
  689. lpstgmed->tymed = TYMED_NULL;
  690. lpstgmed->pUnkForRelease = NULL;
  691. lpstgmed->hGlobal = NULL;
  692. if (lpSrcDataObj)
  693. {
  694. if (lpSrcDataObj->GetData(lpforetc, lpstgmed) == NOERROR)
  695. return NOERROR;
  696. if (IsEqualCLSID(clsid, CLSID_NULL))
  697. UtGetClassID(lpSrcDataObj, &clsid);
  698. }
  699. // get data from registration database
  700. lpstgmed->hGlobal = OleGetIconOfClass(clsid, NULL, TRUE);
  701. if (lpstgmed->hGlobal == NULL)
  702. return ResultFromScode(E_OUTOFMEMORY);
  703. else
  704. lpstgmed->tymed = TYMED_MFPICT;
  705. return NOERROR;
  706. }
  707. // Performs operation like COPY, MOVE, REMOVE etc.. on src, dst storages. The
  708. // caller can specifiy which streams to be operated upon through
  709. // grfAllowedStreams parameter.
  710. STDAPI UtDoStreamOperation(LPSTORAGE pstgSrc, LPSTORAGE pstgDst, int iOpCode,
  711. DWORD grfAllowedStmTypes)
  712. {
  713. VDATEHEAP();
  714. HRESULT error; // error status so far
  715. IEnumSTATSTG FAR* penumStg; // used to enumerate the storage elements
  716. ULONG celtFetched; // how many storage elements were fetched
  717. STATSTG statstg;
  718. // get an enumerator over the source storage
  719. if (error = pstgSrc->EnumElements(NULL, NULL, NULL, &penumStg))
  720. return error;
  721. // repeat for every storage
  722. while(penumStg->Next(1, &statstg, &celtFetched) == NOERROR)
  723. {
  724. // operate on streams that we're interested in
  725. if (statstg.type == STGTY_STREAM)
  726. {
  727. DWORD stmType;
  728. // find the type of the stream
  729. // REVIEW, we must have constants for these name
  730. // prefixes!!!
  731. switch (statstg.pwcsName[0])
  732. {
  733. case '\1':
  734. stmType = STREAMTYPE_CONTROL;
  735. break;
  736. case '\2':
  737. stmType = STREAMTYPE_CACHE;
  738. break;
  739. case '\3':
  740. stmType = STREAMTYPE_CONTAINER;
  741. break;
  742. default:
  743. stmType = (DWORD)STREAMTYPE_OTHER;
  744. }
  745. // check whether it should be operated upon
  746. if (stmType & grfAllowedStmTypes)
  747. {
  748. switch(iOpCode)
  749. {
  750. #ifdef LATER
  751. case OPCODE_COPY:
  752. pstgDst->DestroyElement(
  753. statstg.pwcsName);
  754. error = pstgSrc->MoveElementTo(
  755. statstg.pwcsName,
  756. pstgDst,
  757. statstg.pwcsName,
  758. STGMOVE_COPY);
  759. break;
  760. case OPCODE_MOVE:
  761. pstgDst->DestroyElement(
  762. statstg.pwcsName);
  763. error = pstgSrc->MoveElementTo(
  764. statstg.pwcsName,
  765. pstgDst,
  766. statstg.pwcsName,
  767. STGMOVE_MOVE);
  768. break;
  769. case OPCODE_EXCLUDEFROMCOPY:
  770. AssertSz(FALSE, "Not yet implemented");
  771. break;
  772. #endif // LATER
  773. case OPCODE_REMOVE:
  774. error = pstgSrc->DestroyElement(
  775. statstg.pwcsName);
  776. break;
  777. default:
  778. AssertSz(FALSE, "Invalid opcode");
  779. break;
  780. }
  781. }
  782. }
  783. // if the enumerator allocated a new name string, get rid of it
  784. if (statstg.pwcsName)
  785. PubMemFree(statstg.pwcsName);
  786. // quit the enumeration loop if we've hit an error
  787. if (error != NOERROR)
  788. break;
  789. }
  790. // release the enumerator
  791. penumStg->Release();
  792. // return the error state
  793. return error;
  794. }
  795. FARINTERNAL_(void) UtGetPresStreamName(LPOLESTR lpszName, int iStreamNum)
  796. {
  797. VDATEHEAP();
  798. int i; // counts down the digits of iStreamNum
  799. // count down the last three '0' characters of OLE_PRESENTATION_STREAM
  800. // the -2 backs us up to the last character (remember the NULL
  801. // terminator!)
  802. for(lpszName += sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR) - 2,
  803. i = 3; i; --lpszName, --i)
  804. {
  805. *lpszName = OLESTR("0123456789")[iStreamNum % 10];
  806. if( iStreamNum > 0 )
  807. {
  808. iStreamNum /= 10;
  809. }
  810. }
  811. }
  812. FARINTERNAL_(void) UtRemoveExtraOlePresStreams(LPSTORAGE pstg, int iStart)
  813. {
  814. VDATEHEAP();
  815. HRESULT hr; // error code from stream deletion
  816. OLECHAR szName[sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
  817. // space for the stream names
  818. // if the stream number is invalid, do nothing
  819. if ((iStart < 0) || (iStart >= OLE_MAX_PRES_STREAMS))
  820. return;
  821. // create presentation stream name
  822. _xstrcpy(szName, OLE_PRESENTATION_STREAM);
  823. UtGetPresStreamName(szName, iStart);
  824. // for each of these streams that exists, get rid of it
  825. while((hr = pstg->DestroyElement(szName)) == NOERROR)
  826. {
  827. // if we've gotten to the end of the possible streams, quit
  828. if (++iStart >= OLE_MAX_PRES_STREAMS)
  829. break;
  830. // Get the next presentation stream name
  831. UtGetPresStreamName(szName, iStart);
  832. }
  833. // since the only reason these streams should be open, the first
  834. // failure had better be that the file was not found, and not
  835. // anything else (such as STG_E_ACCESSDENIED)
  836. AssertSz(hr == STG_E_FILENOTFOUND,
  837. "UtRemoveExtraOlePresStreams failure");
  838. }
  839. //+-------------------------------------------------------------------------
  840. //
  841. // Function: ConvertPixelsToHIMETRIC
  842. //
  843. // Synopsis: Converts a pixel dimension to HIMETRIC units
  844. //
  845. // Effects:
  846. //
  847. // Arguments: [hdcRef] -- the reference DC
  848. // [ulPels] -- dimension in pixel measurement
  849. // [pulHIMETRIC] -- OUT param of converted HIMETRIC result
  850. // [tDimension] -- indicates XDIMENSION or YDIMENSION of input
  851. //
  852. // Returns: S_OK, E_FAIL
  853. //
  854. // Algorithm: screen_mm * input_pels HIMETRICS/
  855. // ---------------------- * / == HIMETRICS
  856. // screen_pels /mm
  857. //
  858. // History: dd-mmm-yy Author Comment
  859. // 04-Aug-94 Davepl Created
  860. //
  861. // Notes: We need to know whether the input size is in the X or
  862. // Y dimension, since the aspect ratio could vary
  863. //
  864. //--------------------------------------------------------------------------
  865. FARINTERNAL ConvertPixelsToHIMETRIC (HDC hdcRef,
  866. ULONG lPels,
  867. ULONG * pulHIMETRIC,
  868. DIMENSION tDimension)
  869. {
  870. VDATEHEAP();
  871. VDATEPTROUT(pulHIMETRIC, ULONG *);
  872. // Clear OUT parameter in case of error
  873. *pulHIMETRIC = 0;
  874. ULONG scrmm = 0;
  875. ULONG scrpel = 0;
  876. const ULONG HIMETRIC_PER_MM = 100;
  877. // If we weren't given a reference DC, use the screen as a default
  878. BOOL fLocalDC = FALSE;
  879. if (NULL == hdcRef)
  880. {
  881. hdcRef = GetDC(NULL);
  882. if (hdcRef)
  883. {
  884. fLocalDC = TRUE;
  885. }
  886. }
  887. if (hdcRef)
  888. {
  889. Assert(tDimension == XDIMENSION || tDimension == YDIMENSION);
  890. // Get the count of pixels and millimeters for the screen
  891. if (tDimension == XDIMENSION)
  892. {
  893. scrmm = GetDeviceCaps(hdcRef, HORZSIZE);
  894. scrpel = GetDeviceCaps(hdcRef, HORZRES);
  895. }
  896. else
  897. {
  898. scrmm = GetDeviceCaps(hdcRef, VERTSIZE);
  899. scrpel = GetDeviceCaps(hdcRef, VERTRES);
  900. }
  901. // If we had to create a temporary DC, it can be released now
  902. if (TRUE == fLocalDC)
  903. {
  904. ReleaseDC(NULL, hdcRef);
  905. }
  906. }
  907. // If we successfully obtained the DC's size and resolution,
  908. // we can compute the HIMETRIC value.
  909. if (scrmm && scrpel)
  910. {
  911. *pulHIMETRIC = (scrmm * lPels * HIMETRIC_PER_MM) / scrpel;
  912. return S_OK;
  913. }
  914. return E_FAIL;
  915. }