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.
747 lines
20 KiB
747 lines
20 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: hdata.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* DDE Manager data handle functions
|
|
*
|
|
* Created: 11/12/91 Sanford Staab
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#define DDEMLDB
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
/***************************************************************************\
|
|
* DdeCreateDataHandle (DDEML API)
|
|
*
|
|
* Description
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
|
|
FUNCLOG7(LOG_GENERAL, HDDEDATA, DUMMYCALLINGTYPE, DdeCreateDataHandle, DWORD, idInst, LPBYTE, pSrc, DWORD, cb, DWORD, cbOff, HSZ, hszItem, UINT, wFmt, UINT, afCmd)
|
|
HDDEDATA DdeCreateDataHandle(
|
|
DWORD idInst,
|
|
LPBYTE pSrc,
|
|
DWORD cb,
|
|
DWORD cbOff,
|
|
HSZ hszItem,
|
|
UINT wFmt,
|
|
UINT afCmd)
|
|
{
|
|
PCL_INSTANCE_INFO pcii;
|
|
HDDEDATA hRet = 0;
|
|
|
|
if (cb == -1) {
|
|
RIPMSG0(RIP_WARNING, "DdeCreateDataHandle called with cb == -1");
|
|
return NULL;
|
|
}
|
|
|
|
EnterDDECrit;
|
|
|
|
pcii = ValidateInstance((HANDLE)LongToHandle( idInst ));
|
|
if (pcii == NULL) {
|
|
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
|
|
goto Exit;
|
|
}
|
|
if (afCmd & ~HDATA_APPOWNED) {
|
|
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
|
|
goto Exit;
|
|
}
|
|
|
|
if (cb + cbOff < sizeof(DWORD) && pSrc == NULL &&
|
|
(wFmt == CF_METAFILEPICT ||
|
|
wFmt == CF_DSPMETAFILEPICT ||
|
|
wFmt == CF_DIB ||
|
|
wFmt == CF_BITMAP ||
|
|
wFmt == CF_DSPBITMAP ||
|
|
wFmt == CF_PALETTE ||
|
|
wFmt == CF_ENHMETAFILE ||
|
|
wFmt == CF_DSPENHMETAFILE)) {
|
|
/*
|
|
* We have the nasty possibility of blowing up in FreeDDEData if we
|
|
* don't initialize the data for formats with indirect data to 0.
|
|
* This is because GlobalLock/GlobalSize do not adequately validate
|
|
* random numbers given to them.
|
|
*/
|
|
cb += 4;
|
|
}
|
|
hRet = InternalCreateDataHandle(pcii, pSrc, cb, cbOff,
|
|
hszItem ? afCmd : (afCmd | HDATA_EXECUTE),
|
|
(WORD)((afCmd & HDATA_APPOWNED) ? 0 : DDE_FRELEASE), (WORD)wFmt);
|
|
|
|
if (!hRet) {
|
|
SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
|
|
}
|
|
Exit:
|
|
LeaveDDECrit;
|
|
return (hRet);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* InternalCreateDataHandle
|
|
*
|
|
* Description:
|
|
* Worker function for creating a data handle. If cb is -1, pSrc is
|
|
* a GMEM_DDESHARE data handle. 0 is return ed on error.
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
HDDEDATA InternalCreateDataHandle(
|
|
PCL_INSTANCE_INFO pcii,
|
|
LPBYTE pSrc,
|
|
DWORD cb, // cb of actual data to initialize with
|
|
DWORD cbOff, // offset from start of data
|
|
DWORD flags,
|
|
WORD wStatus,
|
|
WORD wFmt)
|
|
{
|
|
PDDEMLDATA pdd;
|
|
HDDEDATA hRet;
|
|
LPBYTE p;
|
|
DWORD cbOff2;
|
|
|
|
CheckDDECritIn;
|
|
|
|
pdd = (PDDEMLDATA)DDEMLAlloc(sizeof(DDEMLDATA));
|
|
if (pdd == NULL) {
|
|
return (0);
|
|
}
|
|
if (cb == -1) {
|
|
pdd->hDDE = (HANDLE)pSrc;
|
|
} else {
|
|
if (flags & HDATA_EXECUTE) {
|
|
cbOff2 = 0;
|
|
} else {
|
|
cbOff2 = sizeof(WORD) + sizeof(WORD); // skip wStatus, wFmt
|
|
}
|
|
pdd->hDDE = UserGlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
|
|
cb + cbOff + cbOff2);
|
|
if (pdd->hDDE == NULL) {
|
|
DDEMLFree(pdd);
|
|
return (0);
|
|
}
|
|
|
|
if (!(flags & HDATA_EXECUTE)) {
|
|
PDDE_DATA pdde;
|
|
|
|
USERGLOBALLOCK(pdd->hDDE, pdde);
|
|
UserAssert(pdde);
|
|
pdde->wStatus = wStatus;
|
|
pdde->wFmt = wFmt;
|
|
USERGLOBALUNLOCK(pdd->hDDE);
|
|
}
|
|
}
|
|
pdd->flags = (WORD)flags;
|
|
hRet = (HDDEDATA)CreateHandle((ULONG_PTR)pdd, HTYPE_DATA_HANDLE,
|
|
InstFromHandle(pcii->hInstClient));
|
|
if (!hRet) {
|
|
WOWGLOBALFREE(pdd->hDDE);
|
|
DDEMLFree(pdd);
|
|
return (0);
|
|
}
|
|
if (cb != -1 && pSrc != NULL) {
|
|
USERGLOBALLOCK(pdd->hDDE, p);
|
|
UserAssert(p);
|
|
RtlCopyMemory(p + cbOff + cbOff2, pSrc, cb);
|
|
USERGLOBALUNLOCK(pdd->hDDE);
|
|
pdd->flags |= HDATA_INITIALIZED;
|
|
}
|
|
return (hRet);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* DdeAddData (DDEML API)
|
|
*
|
|
* Description:
|
|
* Copys data from a user buffer to a data handles. Reallocates if needed.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
|
|
FUNCLOG4(LOG_GENERAL, HDDEDATA, DUMMYCALLINGTYPE, DdeAddData, HDDEDATA, hData, LPBYTE, pSrc, DWORD, cb, DWORD, cbOff)
|
|
HDDEDATA DdeAddData(
|
|
HDDEDATA hData,
|
|
LPBYTE pSrc,
|
|
DWORD cb,
|
|
DWORD cbOff)
|
|
{
|
|
LPSTR pMem;
|
|
PDDEMLDATA pdd;
|
|
PCL_INSTANCE_INFO pcii;
|
|
HDDEDATA hRet = 0;
|
|
HANDLE hTempDDE;
|
|
|
|
EnterDDECrit;
|
|
|
|
pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)hData, HTYPE_DATA_HANDLE, HINST_ANY);
|
|
if (pdd == NULL) {
|
|
goto Exit;
|
|
}
|
|
pcii = PciiFromHandle((HANDLE)hData);
|
|
if (pcii == NULL) {
|
|
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
|
|
goto Exit;
|
|
}
|
|
if (!(pdd->flags & HDATA_EXECUTE)) {
|
|
cbOff += 4;
|
|
}
|
|
if (cb + cbOff > UserGlobalSize(pdd->hDDE)) {
|
|
/*
|
|
* If the realloc failed, free the old ptr. We continue
|
|
* on in order to maintain compatibility with previous DDE code.
|
|
*/
|
|
hTempDDE = UserGlobalReAlloc(pdd->hDDE, cb + cbOff,
|
|
GMEM_MOVEABLE | GMEM_ZEROINIT);
|
|
|
|
if ((hTempDDE == NULL) && ((pdd->hDDE) != NULL)) {
|
|
UserGlobalFree(pdd->hDDE);
|
|
}
|
|
pdd->hDDE = hTempDDE;
|
|
}
|
|
|
|
USERGLOBALLOCK(pdd->hDDE, pMem);
|
|
|
|
if (pMem == NULL) {
|
|
SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
|
|
goto Exit;
|
|
}
|
|
|
|
hRet = hData;
|
|
|
|
if (pSrc != NULL) {
|
|
try {
|
|
RtlCopyMemory(pMem + cbOff, pSrc, cb);
|
|
pdd->flags |= HDATA_INITIALIZED;
|
|
} except(W32ExceptionHandler(FALSE, RIP_WARNING)) {
|
|
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
|
|
hRet = 0;
|
|
}
|
|
}
|
|
|
|
USERGLOBALUNLOCK(pdd->hDDE);
|
|
|
|
Exit:
|
|
LeaveDDECrit;
|
|
return (hRet);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* DdeGetData (DDEML API)
|
|
*
|
|
* Description:
|
|
* Copys data from a data handle into a user buffer.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
|
|
FUNCLOG4(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, DdeGetData, HDDEDATA, hData, LPBYTE, pDst, DWORD, cbMax, DWORD, cbOff)
|
|
DWORD DdeGetData(
|
|
HDDEDATA hData,
|
|
LPBYTE pDst,
|
|
DWORD cbMax,
|
|
DWORD cbOff)
|
|
{
|
|
DWORD cbCopied = 0;
|
|
DWORD cbSize;
|
|
PDDEMLDATA pdd;
|
|
PCL_INSTANCE_INFO pcii;
|
|
|
|
EnterDDECrit;
|
|
|
|
pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)hData,
|
|
HTYPE_DATA_HANDLE, HINST_ANY);
|
|
if (pdd == NULL) {
|
|
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
|
|
goto Exit;
|
|
}
|
|
pcii = PciiFromHandle((HANDLE)hData);
|
|
if (pcii == NULL) {
|
|
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
|
|
goto Exit;
|
|
}
|
|
if (!(pdd->flags & HDATA_EXECUTE)) {
|
|
cbOff += 4;
|
|
}
|
|
cbSize = (DWORD)UserGlobalSize(pdd->hDDE);
|
|
if (cbOff >= cbSize) {
|
|
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
|
|
goto Exit;
|
|
}
|
|
if (pDst == NULL) {
|
|
cbCopied = cbSize - cbOff;
|
|
goto Exit;
|
|
} else {
|
|
LPSTR pMem;
|
|
|
|
cbCopied = min(cbMax, cbSize - cbOff);
|
|
USERGLOBALLOCK(pdd->hDDE, pMem);
|
|
UserAssert(pMem);
|
|
try {
|
|
RtlCopyMemory(pDst, pMem + cbOff, cbCopied);
|
|
} except(W32ExceptionHandler(FALSE, RIP_WARNING)) {
|
|
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
|
|
cbCopied = 0;
|
|
}
|
|
if (pMem != NULL) {
|
|
USERGLOBALUNLOCK(pdd->hDDE);
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
LeaveDDECrit;
|
|
return (cbCopied);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* DdeAccessData (DDEML API)
|
|
*
|
|
* Description:
|
|
* Locks a data handle for access.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
|
|
FUNCLOG2(LOG_GENERAL, LPBYTE, DUMMYCALLINGTYPE, DdeAccessData, HDDEDATA, hData, LPDWORD, pcbDataSize)
|
|
LPBYTE DdeAccessData(
|
|
HDDEDATA hData,
|
|
LPDWORD pcbDataSize)
|
|
{
|
|
PCL_INSTANCE_INFO pcii;
|
|
PDDEMLDATA pdd;
|
|
LPBYTE pRet = NULL;
|
|
DWORD cbOff;
|
|
|
|
EnterDDECrit;
|
|
|
|
pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)hData,
|
|
HTYPE_DATA_HANDLE, HINST_ANY);
|
|
if (pdd == NULL) {
|
|
goto Exit;
|
|
}
|
|
pcii = PciiFromHandle((HANDLE)hData);
|
|
cbOff = pdd->flags & HDATA_EXECUTE ? 0 : 4;
|
|
if (pcbDataSize != NULL) {
|
|
*pcbDataSize = (DWORD)UserGlobalSize(pdd->hDDE) - cbOff;
|
|
}
|
|
USERGLOBALLOCK(pdd->hDDE, pRet);
|
|
UserAssert(pRet);
|
|
pRet = (LPBYTE)pRet + cbOff;
|
|
|
|
Exit:
|
|
LeaveDDECrit;
|
|
return (pRet);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* DdeUnaccessData (DDEML API)
|
|
*
|
|
* Description:
|
|
* Unlocks a data handle
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
|
|
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeUnaccessData, HDDEDATA, hData)
|
|
BOOL DdeUnaccessData(
|
|
HDDEDATA hData)
|
|
{
|
|
PDDEMLDATA pdd;
|
|
BOOL fSuccess = FALSE;
|
|
|
|
EnterDDECrit;
|
|
|
|
pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)hData,
|
|
HTYPE_DATA_HANDLE, HINST_ANY);
|
|
if (pdd == NULL) {
|
|
goto Exit;
|
|
}
|
|
USERGLOBALUNLOCK(pdd->hDDE);
|
|
fSuccess = TRUE;
|
|
|
|
Exit:
|
|
LeaveDDECrit;
|
|
return (fSuccess);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* DdeFreeDataHandle (DDEML API)
|
|
*
|
|
* Description:
|
|
* Releases application interest in a data handle.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
|
|
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeFreeDataHandle, HDDEDATA, hData)
|
|
BOOL DdeFreeDataHandle(
|
|
HDDEDATA hData)
|
|
{
|
|
PDDEMLDATA pdd;
|
|
BOOL fSuccess = FALSE;
|
|
|
|
EnterDDECrit;
|
|
|
|
pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)hData,
|
|
HTYPE_DATA_HANDLE, HINST_ANY);
|
|
if (pdd == NULL) {
|
|
goto Exit;
|
|
}
|
|
if (pdd->flags & HDATA_NOAPPFREE) {
|
|
fSuccess = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
fSuccess = InternalFreeDataHandle(hData, TRUE);
|
|
|
|
Exit:
|
|
LeaveDDECrit;
|
|
return (fSuccess);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* InternalFreeDataHandle
|
|
*
|
|
* Description:
|
|
* Frees a data handle and its contents. The contents are NOT freed for
|
|
* APPOWNED data handles unless fIgnorefRelease is set.
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
BOOL InternalFreeDataHandle(
|
|
HDDEDATA hData,
|
|
BOOL fIgnorefRelease)
|
|
{
|
|
PDDEMLDATA pdd;
|
|
|
|
CheckDDECritIn;
|
|
|
|
pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)hData,
|
|
HTYPE_DATA_HANDLE, HINST_ANY);
|
|
if (pdd == NULL) {
|
|
return (FALSE);
|
|
}
|
|
if (pdd->flags & HDATA_EXECUTE) {
|
|
if (!(pdd->flags & HDATA_APPOWNED) || fIgnorefRelease) {
|
|
WOWGLOBALFREE(pdd->hDDE);
|
|
}
|
|
} else {
|
|
FreeDDEData(pdd->hDDE, fIgnorefRelease, TRUE);
|
|
}
|
|
DDEMLFree(pdd);
|
|
DestroyHandle((HANDLE)hData);
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ApplyFreeDataHandle
|
|
*
|
|
* Description:
|
|
* Used during data handle cleanup.
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
BOOL ApplyFreeDataHandle(
|
|
HANDLE hData)
|
|
{
|
|
BOOL fRet;
|
|
|
|
CheckDDECritOut;
|
|
EnterDDECrit;
|
|
fRet = InternalFreeDataHandle((HDDEDATA)hData, FALSE);
|
|
LeaveDDECrit;
|
|
return(fRet);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* FreeDDEData
|
|
*
|
|
* Description:
|
|
* Used for freeing DDE data including any special indirect objects
|
|
* associated with the data depending on the format. This function
|
|
* SHOULD NOT BE USED TO FREE EXECUTE DATA!
|
|
*
|
|
* The data is not freed if the fRelease bit is clear and fIgnoreRelease
|
|
* is FALSE.
|
|
*
|
|
* The fFreeTruelyGlobalObjects parameter is used to distinguish tracking
|
|
* layer frees from DDEML frees. Data in certain formats (CF_BITMAP,
|
|
* CF_PALETTE) is maintained on the gdi CSR server side. When this is
|
|
* passed between processes, gdi is not able to maintain multiple process
|
|
* ownership on these objects so the objects must be made global. Thus
|
|
* the tracking layer should NOT free these objects on behalf of another
|
|
* process because they are truely global- however, DDEML can do this
|
|
* because it is following the protocol which delclares who is in charge
|
|
* of freeing global data. (YUCK!)
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
/*
|
|
* WARNING: This is exported for NetDDE use - DO NOT CHANGE THE PARAMETERS!
|
|
*/
|
|
VOID FreeDDEData(
|
|
HANDLE hDDE,
|
|
BOOL fIgnorefRelease,
|
|
BOOL fFreeTruelyGlobalObjects)
|
|
{
|
|
PDDE_DATA pdde;
|
|
LPMETAFILEPICT pmfPict;
|
|
DWORD cb;
|
|
|
|
USERGLOBALLOCK(hDDE, pdde);
|
|
if (pdde == NULL) {
|
|
return ;
|
|
}
|
|
|
|
if ((pdde->wStatus & DDE_FRELEASE) || fIgnorefRelease) {
|
|
cb = (DWORD)GlobalSize(hDDE);
|
|
/*
|
|
* Because there is the possibility that the data never got
|
|
* initialized we need to do this in a try-except so we
|
|
* behave nicely.
|
|
*/
|
|
switch (pdde->wFmt) {
|
|
case CF_BITMAP:
|
|
case CF_DSPBITMAP:
|
|
case CF_PALETTE:
|
|
if (cb >= sizeof(HANDLE)) {
|
|
if (fFreeTruelyGlobalObjects) {
|
|
if (pdde->Data != 0) {
|
|
DeleteObject((HANDLE)pdde->Data);
|
|
}
|
|
} else {
|
|
/*
|
|
* !fFreeTruelyGlobalObject implies we are only freeing
|
|
* the Gdi proxy. (another process may still have this
|
|
* object in use.)
|
|
*
|
|
* ChrisWil: removed this call. No longer
|
|
* applicable in KMode.
|
|
*
|
|
* GdiDeleteLocalObject((ULONG)pdde->Data);
|
|
*
|
|
*/
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CF_DIB:
|
|
if (cb >= sizeof(HANDLE)) {
|
|
if (pdde->Data != 0) {
|
|
WOWGLOBALFREE((HANDLE)pdde->Data);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CF_METAFILEPICT:
|
|
case CF_DSPMETAFILEPICT:
|
|
if (cb >= sizeof(HANDLE)) {
|
|
if (pdde->Data != 0) {
|
|
USERGLOBALLOCK(pdde->Data, pmfPict);
|
|
if (pmfPict != NULL) {
|
|
if (GlobalSize((HANDLE)pdde->Data) >= sizeof(METAFILEPICT)) {
|
|
DeleteMetaFile(pmfPict->hMF);
|
|
}
|
|
USERGLOBALUNLOCK((HANDLE)pdde->Data);
|
|
WOWGLOBALFREE((HANDLE)pdde->Data);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CF_ENHMETAFILE:
|
|
case CF_DSPENHMETAFILE:
|
|
if (cb >= sizeof(HANDLE)) {
|
|
if (pdde->Data != 0) {
|
|
DeleteEnhMetaFile((HANDLE)pdde->Data);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
USERGLOBALUNLOCK(hDDE);
|
|
WOWGLOBALFREE(hDDE);
|
|
} else {
|
|
USERGLOBALUNLOCK(hDDE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
HBITMAP CopyBitmap(
|
|
HBITMAP hbm)
|
|
{
|
|
BITMAP bm;
|
|
HBITMAP hbm2 = NULL, hbmOld1, hbmOld2;
|
|
HDC hdc, hdcMem1, hdcMem2;
|
|
|
|
if (!GetObject(hbm, sizeof(BITMAP), &bm)) {
|
|
return(0);
|
|
}
|
|
hdc = NtUserGetDC(NULL); // screen DC
|
|
if (!hdc) {
|
|
return(0);
|
|
}
|
|
hdcMem1 = CreateCompatibleDC(hdc);
|
|
if (!hdcMem1) {
|
|
goto Cleanup3;
|
|
}
|
|
hdcMem2 = CreateCompatibleDC(hdc);
|
|
if (!hdcMem2) {
|
|
goto Cleanup2;
|
|
}
|
|
hbmOld1 = SelectObject(hdcMem1, hbm);
|
|
hbm2 = CreateCompatibleBitmap(hdcMem1, bm.bmWidth, bm.bmHeight);
|
|
if (!hbm2) {
|
|
goto Cleanup1;
|
|
}
|
|
hbmOld2 = SelectObject(hdcMem2, hbm2);
|
|
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY);
|
|
SelectObject(hdcMem1, hbmOld1);
|
|
SelectObject(hdcMem2, hbmOld2);
|
|
Cleanup1:
|
|
DeleteDC(hdcMem2);
|
|
Cleanup2:
|
|
DeleteDC(hdcMem1);
|
|
Cleanup3:
|
|
NtUserReleaseDC(NULL, hdc);
|
|
return(hbm2);
|
|
}
|
|
|
|
|
|
HPALETTE CopyPalette(
|
|
HPALETTE hpal)
|
|
{
|
|
int cPalEntries;
|
|
LOGPALETTE *plp;
|
|
|
|
if (!GetObject(hpal, sizeof(int), &cPalEntries)) {
|
|
return(0);
|
|
}
|
|
plp = (LOGPALETTE *)DDEMLAlloc(sizeof(LOGPALETTE) +
|
|
(cPalEntries - 1) * sizeof(PALETTEENTRY));
|
|
if (!plp) {
|
|
return(0);
|
|
}
|
|
if (!GetPaletteEntries(hpal, 0, cPalEntries, plp->palPalEntry)) {
|
|
DDEMLFree(plp);
|
|
return(0);
|
|
}
|
|
plp->palVersion = 0x300;
|
|
plp->palNumEntries = (WORD)cPalEntries;
|
|
hpal = CreatePalette(plp);
|
|
if (hpal != NULL) {
|
|
if (!SetPaletteEntries(hpal, 0, cPalEntries, plp->palPalEntry)) {
|
|
DeleteObject(hpal);
|
|
hpal = NULL;
|
|
}
|
|
}
|
|
DDEMLFree(plp);
|
|
return(hpal);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* CopyDDEData
|
|
*
|
|
* Description:
|
|
* Used to copy DDE data apropriately.
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
HANDLE CopyDDEData(
|
|
HANDLE hDDE,
|
|
BOOL fIsExecute)
|
|
{
|
|
HANDLE hDDENew;
|
|
PDDE_DATA pdde, pddeNew;
|
|
LPMETAFILEPICT pmfPict;
|
|
HANDLE hmfPict;
|
|
|
|
hDDENew = UserGlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,
|
|
UserGlobalSize(hDDE));
|
|
if (!hDDENew) {
|
|
return (0);
|
|
}
|
|
USERGLOBALLOCK(hDDE, pdde);
|
|
if (pdde == NULL) {
|
|
UserGlobalFree(hDDENew);
|
|
return (0);
|
|
}
|
|
USERGLOBALLOCK(hDDENew, pddeNew);
|
|
UserAssert(pddeNew);
|
|
RtlCopyMemory(pddeNew, pdde, UserGlobalSize(hDDE));
|
|
|
|
if (!fIsExecute) {
|
|
switch (pdde->wFmt) {
|
|
case CF_BITMAP:
|
|
case CF_DSPBITMAP:
|
|
pddeNew->Data = (KERNEL_PVOID)CopyBitmap((HBITMAP)pdde->Data);
|
|
break;
|
|
|
|
case CF_PALETTE:
|
|
pddeNew->Data = (KERNEL_PVOID)CopyPalette((HPALETTE)pdde->Data);
|
|
break;
|
|
|
|
case CF_DIB:
|
|
pddeNew->Data = (KERNEL_PVOID)CopyDDEData((HANDLE)pdde->Data, TRUE);
|
|
break;
|
|
|
|
case CF_METAFILEPICT:
|
|
case CF_DSPMETAFILEPICT:
|
|
hmfPict = CopyDDEData((HANDLE)pdde->Data, TRUE);
|
|
USERGLOBALLOCK(hmfPict, pmfPict);
|
|
if (pmfPict == NULL) {
|
|
WOWGLOBALFREE(hmfPict);
|
|
USERGLOBALUNLOCK(hDDENew);
|
|
WOWGLOBALFREE(hDDENew);
|
|
USERGLOBALUNLOCK(hDDE);
|
|
return (FALSE);
|
|
}
|
|
pmfPict->hMF = CopyMetaFile(pmfPict->hMF, NULL);
|
|
USERGLOBALUNLOCK(hmfPict);
|
|
pddeNew->Data = (KERNEL_PVOID)hmfPict;
|
|
break;
|
|
|
|
case CF_ENHMETAFILE:
|
|
case CF_DSPENHMETAFILE:
|
|
pddeNew->Data = (KERNEL_PVOID)CopyEnhMetaFile((HANDLE)pdde->Data, NULL);
|
|
break;
|
|
}
|
|
}
|
|
USERGLOBALUNLOCK(hDDENew);
|
|
USERGLOBALUNLOCK(hDDE);
|
|
return (hDDENew);
|
|
}
|