Leaked source code of windows server 2003
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

/****************************** 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);
}