windows-nt/Source/XPSP1/NT/base/mvdm/wow16/ole/client/bm.c
2020-09-26 16:20:57 +08:00

606 lines
16 KiB
C

/****************************** Module Header ******************************\
* Module Name: BM.C
*
* Handles all API routines for the bitmap sub-dll of the ole dll.
*
* Created: 1990
*
* Copyright (c) 1990, 1991 Microsoft Corporation
*
* History:
* Raor,Srinik (../../1990,91) Designed, coded
*
\***************************************************************************/
#include <windows.h>
#include "dll.h"
#include "pict.h"
extern int maxPixelsX, maxPixelsY;
void INTERNAL GetHimetricUnits(HBITMAP, LPPOINT);
#pragma alloc_text(_TEXT, BmSaveToStream, BmStreamWrite, BmLoadFromStream, BmStreamRead, GetBytes, PutBytes, PutStrWithLen, BmQueryBounds, BmChangeData, BmCopy, BmDuplicate, BmUpdateStruct, GetHimetricUnits)
OLEOBJECTVTBL vtblBM = {
ErrQueryProtocol, // check whether the speced protocol is supported
BmRelease, // Release
ErrShow, // Show
ErrPlay, // play
BmGetData, // Get the object data
ErrSetData, // Set the object data
ErrSetTargetDevice,//
ErrSetBounds, // set viewport bounds
BmEnumFormat, // enumerate supported formats
ErrSetColorScheme, //
BmRelease, // delete
ErrSetHostNames, //
BmSaveToStream, // write to file
BmClone, // clone object
ErrCopyFromLink, // Create embedded from Link
BmEqual, // compares the given objects for data equality
BmCopy, // copy to clip
BmDraw, // draw the object
ErrActivate, // open
ErrExecute, // excute
ErrClose, // Stop
ErrUpdate, // Update
ErrReconnect, // Reconnect
ErrObjectConvert, // convert object to specified type
ErrGetUpdateOptions,// update options
ErrSetUpdateOptions,// update options
ObjRename, // Change Object name
ObjQueryName, // Get current object name
ObjQueryType, // Object type
BmQueryBounds, // QueryBounds
ObjQuerySize, // Find the size of the object
ErrQueryOpen, // Query open
ErrQueryOutOfDate, // query whether object is current
ErrQueryRelease, // release related stuff
ErrQueryRelease,
ErrQueryRelease,
ErrRequestData, // requestdata
ErrObjectLong, // objectLong
BmChangeData // change data of the existing object
};
OLESTATUS FARINTERNAL BmRelease (lpobj)
LPOBJECT_BM lpobj;
{
HOBJECT hobj;
if (lpobj->hBitmap) {
DeleteObject (lpobj->hBitmap);
lpobj->hBitmap = NULL;
}
if (lpobj->head.lhclientdoc)
DocDeleteObject ((LPOLEOBJECT) lpobj);
if (hobj = lpobj->head.hobj){
lpobj->head.hobj = NULL;
GlobalUnlock (hobj);
GlobalFree (hobj);
}
return OLE_OK;
}
OLESTATUS FARINTERNAL BmSaveToStream (lpobj, lpstream)
LPOBJECT_BM lpobj;
LPOLESTREAM lpstream;
{
if (!lpobj->hBitmap || !lpobj->sizeBytes)
return OLE_ERROR_BLANK;
if (PutBytes (lpstream, (LPSTR) &dwVerToFile, sizeof(LONG)))
return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG)))
return OLE_ERROR_STREAM;
if (PutStrWithLen(lpstream, (LPSTR)"BITMAP"))
return OLE_ERROR_STREAM;
if (!PutBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG))) {
if (!PutBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
if (!PutBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(DWORD)))
return BmStreamWrite (lpstream, lpobj);
}
return OLE_ERROR_STREAM;
}
OLESTATUS FARINTERNAL BmClone (lpobjsrc, lpclient, lhclientdoc, lpobjname, lplpobj)
LPOBJECT_BM lpobjsrc;
LPOLECLIENT lpclient;
LHCLIENTDOC lhclientdoc;
LPSTR lpobjname;
LPOBJECT_BM FAR * lplpobj;
{
if (!CheckClientDoc ((LPCLIENTDOC)lhclientdoc))
return OLE_ERROR_HANDLE;
if (!(*lplpobj = BmCreateObject (lpobjsrc->hBitmap, lpclient, FALSE,
lhclientdoc, lpobjname, lpobjsrc->head.ctype)))
return OLE_ERROR_MEMORY;
else
return OLE_OK;
}
OLESTATUS FARINTERNAL BmEqual (lpobj1, lpobj2)
LPOBJECT_BM lpobj1;
LPOBJECT_BM lpobj2;
{
HANDLE hBits1 = NULL, hBits2 = NULL;
LPSTR lpBits1 = NULL, lpBits2 = NULL;
OLESTATUS retVal;
DWORD dwBytes1, dwBytes2;
if (lpobj1->sizeBytes != lpobj2->sizeBytes)
return OLE_ERROR_NOT_EQUAL;
retVal = OLE_ERROR_MEMORY;
if (!(hBits1 = GlobalAlloc (GMEM_MOVEABLE, lpobj1->sizeBytes)))
goto errEqual;
if (!(lpBits1 = GlobalLock (hBits1)))
goto errEqual;
if (!(hBits2 = GlobalAlloc (GMEM_MOVEABLE, lpobj2->sizeBytes)))
goto errEqual;
if (!(lpBits2 = GlobalLock (hBits2)))
goto errEqual;
dwBytes1 = GetBitmapBits (lpobj1->hBitmap, lpobj1->sizeBytes, lpBits1);
dwBytes2 = GetBitmapBits (lpobj2->hBitmap, lpobj2->sizeBytes, lpBits2);
if (dwBytes1 != dwBytes2) {
retVal = OLE_ERROR_NOT_EQUAL;
goto errEqual;
}
// !!! UtilMemCmp has to be redone for >64k bitmaps
if (UtilMemCmp (lpBits1, lpBits2, dwBytes1))
retVal = OLE_ERROR_NOT_EQUAL;
else
retVal = OLE_OK;
errEqual:
if (lpBits1)
GlobalUnlock (hBits1);
if (lpBits2)
GlobalUnlock (hBits2);
if (hBits1)
GlobalFree (hBits1);
if (hBits2)
GlobalFree (hBits2);
return retVal;
}
OLESTATUS FARINTERNAL BmCopy (lpobj)
LPOBJECT_BM lpobj;
{
HBITMAP hBitmap;
DWORD size;
if (!lpobj->hBitmap)
return OLE_ERROR_BLANK;
if(!(hBitmap = BmDuplicate (lpobj->hBitmap, &size, NULL)))
return OLE_ERROR_MEMORY;
SetClipboardData(CF_BITMAP, hBitmap);
return OLE_OK;
}
OLESTATUS FARINTERNAL BmQueryBounds (lpobj, lpRc)
LPOBJECT_BM lpobj;
LPRECT lpRc;
{
Puts("BmQueryBounds");
if (!lpobj->hBitmap)
return OLE_ERROR_BLANK;
lpRc->left = 0;
lpRc->top = 0;
lpRc->right = (int) lpobj->head.cx;
lpRc->bottom = (int) lpobj->head.cy;
return OLE_OK;
}
OLECLIPFORMAT FARINTERNAL BmEnumFormat (lpobj, cfFormat)
LPOBJECT_BM lpobj;
OLECLIPFORMAT cfFormat;
{
if (!cfFormat)
return CF_BITMAP;
return NULL;
}
OLESTATUS FARINTERNAL BmGetData (lpobj, cfFormat, lphandle)
LPOBJECT_BM lpobj;
OLECLIPFORMAT cfFormat;
LPHANDLE lphandle;
{
if (cfFormat != CF_BITMAP)
return OLE_ERROR_FORMAT;
if (!(*lphandle = lpobj->hBitmap))
return OLE_ERROR_BLANK;
return OLE_OK;
}
OLESTATUS FARINTERNAL BmLoadFromStream (lpstream, lpclient, lhclientdoc, lpobjname, lplpoleobject, objType)
LPOLESTREAM lpstream;
LPOLECLIENT lpclient;
LHCLIENTDOC lhclientdoc;
LPSTR lpobjname;
LPOLEOBJECT FAR * lplpoleobject;
LONG objType;
{
LPOBJECT_BM lpobj = NULL;
*lplpoleobject = NULL;
if (!(lpobj = BmCreateBlank (lhclientdoc, lpobjname, objType)))
return OLE_ERROR_MEMORY;
lpobj->head.lpclient = lpclient;
if (!GetBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG))) {
if (!GetBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
if (!GetBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(DWORD)))
if (BmStreamRead (lpstream, lpobj)) {
*lplpoleobject = (LPOLEOBJECT)lpobj;
return OLE_OK;
}
}
OleDelete ((LPOLEOBJECT)lpobj);
return OLE_ERROR_STREAM;;
}
OLESTATUS INTERNAL BmStreamWrite (lpstream, lpobj)
LPOLESTREAM lpstream;
LPOBJECT_BM lpobj;
{
HANDLE hBits;
LPSTR lpBits;
int retVal = OLE_ERROR_STREAM;
BITMAP bm;
DWORD dwSize; // size of bit array
dwSize = lpobj->sizeBytes - sizeof(BITMAP);
if (hBits = GlobalAlloc (GMEM_MOVEABLE, dwSize)) {
if (lpBits = (LPSTR) GlobalLock (hBits)) {
if (GetBitmapBits (lpobj->hBitmap, dwSize, lpBits)) {
GetObject (lpobj->hBitmap, sizeof(BITMAP), (LPSTR) &bm);
if (!PutBytes (lpstream, (LPSTR) &bm, sizeof(BITMAP)))
if (!PutBytes (lpstream, (LPSTR) lpBits, dwSize))
retVal = OLE_OK;
}
GlobalUnlock(hBits);
} else
retVal = OLE_ERROR_MEMORY;
GlobalFree(hBits);
} else
retVal = OLE_ERROR_MEMORY;
return retVal;
}
BOOL INTERNAL BmStreamRead (lpstream, lpobj)
LPOLESTREAM lpstream;
LPOBJECT_BM lpobj;
{
HANDLE hBits;
LPSTR lpBits;
BOOL retVal = FALSE;
BITMAP bm;
POINT point;
if (GetBytes (lpstream, (LPSTR)&bm, sizeof(BITMAP)))
return FALSE;
lpobj->sizeBytes = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
((DWORD) bm.bmPlanes) * ((DWORD) bm.bmBitsPixel);
if (hBits = GlobalAlloc (GMEM_MOVEABLE, lpobj->sizeBytes)) {
if (lpBits = (LPSTR) GlobalLock (hBits)) {
if (!GetBytes(lpstream, lpBits, lpobj->sizeBytes)) {
if (lpobj->hBitmap = CreateBitmap (bm.bmWidth,
bm.bmHeight,
bm.bmPlanes,
bm.bmBitsPixel,
lpBits)) {
retVal = TRUE;
lpobj->xSize = point.x = bm.bmWidth;
lpobj->ySize = point.y = bm.bmHeight;
// size of (bitmap header + bits)
lpobj->sizeBytes += sizeof(BITMAP);
#ifdef OLD
// !!! We shouldn't do the conversion. The info should be
// part of the stream.
if (!lpobj->head.cx) {
ConvertToHimetric (&point);
lpobj->head.cx = (LONG) point.x;
lpobj->head.cy = (LONG) point.y;
}
#endif
}
}
GlobalUnlock(hBits);
}
GlobalFree(hBits);
}
return retVal;
}
OLESTATUS FARINTERNAL BmPaste (lpclient, lhclientdoc, lpobjname, lplpoleobject, objType)
LPOLECLIENT lpclient;
LHCLIENTDOC lhclientdoc;
LPSTR lpobjname;
LPOLEOBJECT FAR * lplpoleobject;
LONG objType;
{
HBITMAP hBitmap;
*lplpoleobject = NULL;
if ((hBitmap = (HBITMAP) GetClipboardData(CF_BITMAP)) == NULL)
return OLE_ERROR_MEMORY;
if (!(*lplpoleobject = (LPOLEOBJECT) BmCreateObject (hBitmap,
lpclient, FALSE, lhclientdoc,
lpobjname, objType)))
return OLE_ERROR_MEMORY;
return OLE_OK;
}
LPOBJECT_BM INTERNAL BmCreateObject (hBitmap, lpclient, fDelete, lhclientdoc, lpobjname, objType)
HBITMAP hBitmap;
LPOLECLIENT lpclient;
BOOL fDelete;
LHCLIENTDOC lhclientdoc;
LPSTR lpobjname;
LONG objType;
{
LPOBJECT_BM lpobj;
if (lpobj = BmCreateBlank (lhclientdoc, lpobjname, objType)) {
if (BmChangeData (lpobj, hBitmap, lpclient, fDelete) != OLE_OK) {
BmRelease (lpobj);
lpobj = NULL;
}
}
return lpobj;
}
// If the routine fails then the object will be left with it's old data.
// If fDelete is TRUE, then hNewBitmap will be deleted whether the routine
// is successful or not.
OLESTATUS FARINTERNAL BmChangeData (lpobj, hNewBitmap, lpclient, fDelete)
LPOBJECT_BM lpobj;
HBITMAP hNewBitmap;
LPOLECLIENT lpclient;
BOOL fDelete;
{
BITMAP bm;
DWORD dwSize;
HBITMAP hOldBitmap;
hOldBitmap = lpobj->hBitmap;
if (!fDelete) {
if (!(hNewBitmap = BmDuplicate (hNewBitmap, &dwSize, &bm)))
return OLE_ERROR_MEMORY;
}
else {
if (!GetObject (hNewBitmap, sizeof(BITMAP), (LPSTR) &bm)) {
DeleteObject (hNewBitmap);
return OLE_ERROR_MEMORY;
}
dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
((DWORD) bm.bmPlanes) * ((DWORD) bm.bmBitsPixel);
}
BmUpdateStruct (lpobj, lpclient, hNewBitmap, &bm, dwSize);
if (hOldBitmap)
DeleteObject (hOldBitmap);
return OLE_OK;
}
void INTERNAL BmUpdateStruct (lpobj, lpclient, hBitmap, lpBm, dwBytes)
LPOBJECT_BM lpobj;
LPOLECLIENT lpclient;
HBITMAP hBitmap;
LPBITMAP lpBm;
DWORD dwBytes;
{
POINT point;
lpobj->head.lpclient = lpclient;
lpobj->xSize = point.x = lpBm->bmWidth;
lpobj->ySize = point.y = lpBm->bmHeight;
GetHimetricUnits (hBitmap, &point);
lpobj->head.cx = (LONG) point.x;
lpobj->head.cy = (LONG) point.y;
lpobj->sizeBytes = dwBytes + sizeof(BITMAP);
lpobj->hBitmap = hBitmap;
}
LPOBJECT_BM FARINTERNAL BmCreateBlank (lhclientdoc, lpobjname, objType)
LHCLIENTDOC lhclientdoc;
LPSTR lpobjname;
LONG objType;
{
HOBJECT hobj;
LPOBJECT_BM lpobj;
if ((hobj = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof (OBJECT_BM)))
== NULL)
return NULL;
if (!(lpobj = (LPOBJECT_BM) GlobalLock (hobj))){
GlobalFree (hobj);
return NULL;
}
lpobj->head.objId[0] = 'L';
lpobj->head.objId[1] = 'E';
lpobj->head.mm = MM_TEXT;
lpobj->head.ctype = objType;
lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblBM;
lpobj->head.iTable = INVALID_INDEX;
lpobj->head.hobj = hobj;
if (objType == CT_STATIC)
DocAddObject ((LPCLIENTDOC) lhclientdoc,
(LPOLEOBJECT) lpobj, lpobjname);
return lpobj;
}
HBITMAP FARINTERNAL BmDuplicate (hold, lpdwSize, lpBm)
HBITMAP hold;
DWORD FAR * lpdwSize;
LPBITMAP lpBm;
{
HBITMAP hnew;
HANDLE hMem;
LPSTR lpMem;
LONG retVal = TRUE;
DWORD dwSize;
BITMAP bm;
DWORD dwExtents = NULL;
// !!! another way to duplicate the bitmap
GetObject (hold, sizeof(BITMAP), (LPSTR) &bm);
dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
((DWORD) bm.bmPlanes) * ((DWORD) bm.bmBitsPixel);
if (!(hMem = GlobalAlloc (GMEM_MOVEABLE, dwSize)))
return NULL;
if (!(lpMem = GlobalLock (hMem))){
GlobalFree (hMem);
return NULL;
}
GetBitmapBits (hold, dwSize, lpMem);
if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
bm.bmPlanes, bm.bmBitsPixel, NULL))
retVal = SetBitmapBits (hnew, dwSize, lpMem);
GlobalUnlock (hMem);
GlobalFree (hMem);
if (hnew && (!retVal)) {
DeleteObject (hnew);
hnew = NULL;
}
*lpdwSize = dwSize;
if (lpBm)
*lpBm = bm;
if (dwExtents = GetBitmapDimension (hold))
SetBitmapDimension (hnew, LOWORD(dwExtents), HIWORD(dwExtents));
return hnew;
}
void INTERNAL GetHimetricUnits(HBITMAP hBitmap, LPPOINT lpPoint)
{
HDC hdc;
DWORD dwDim;
if (dwDim = GetBitmapDimension (hBitmap)) {
lpPoint->x = 10 * LOWORD(dwDim);
lpPoint->y = - (10 * HIWORD(dwDim));
return;
}
// clip if it exceeds maxPixels. Note that we have a limitation of
// 0x8FFF HIMETRIC units in OLE1.0
if (lpPoint->x > maxPixelsX)
lpPoint->x = maxPixelsX;
if (lpPoint->y > maxPixelsY)
lpPoint->y = maxPixelsY;
if (hdc = GetDC (NULL)) {
lpPoint->x = MulDiv (lpPoint->x, 2540,
GetDeviceCaps (hdc, LOGPIXELSX));
lpPoint->y = - MulDiv (lpPoint->y, 2540,
GetDeviceCaps (hdc, LOGPIXELSY));
ReleaseDC (NULL, hdc);
}
else {
lpPoint->x = 0;
lpPoint->y = 0;
}
}