|
|
/*++
* File name: * clputil.c * Contents: * Clipboard functions * * Copyright (C) 1998-1999 Microsoft Corp. --*/ #include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#pragma warning(disable:4706) // assignment within conditional expression
#ifdef _CLPUTIL
enum {ERROR_MESSAGE = 0, WARNING_MESSAGE, INFO_MESSAGE, ALIVE_MESSAGE}; #define TRACE(_x_) LocalPrintMessage _x_
#else // !_CLPUTIL
#include "protocol.h"
/*
* Externals */ extern void (__cdecl *g_pfnPrintMessage) (MESSAGETYPE, LPCSTR, ...);
#define TRACE(_x_) if (g_pfnPrintMessage) {\
g_pfnPrintMessage(INFO_MESSAGE, "Worker:%d ", GetCurrentThreadId());\ g_pfnPrintMessage _x_; }
#endif // !_CLPUTIL
typedef struct _CLIPBOARDFORMATS { UINT uiFormat; LPCSTR szFormat; } CLIPBOARDFORMATS, *PCLIPBOARDFORMATS;
const CLIPBOARDFORMATS KnownFormats[] = { {CF_TEXT, "Text"}, {CF_BITMAP, "Bitmap"}, {CF_METAFILEPICT, "MetaFile"}, {CF_SYLK, "Sylk"}, {CF_DIF, "DIF"}, {CF_TIFF, "TIFF"}, {CF_OEMTEXT, "OEMText"}, {CF_DIB, "DIB"}, {CF_PALETTE, "Palette"}, {CF_PENDATA, "PenData"}, {CF_RIFF, "Riff"}, {CF_WAVE, "Wave"}, {CF_UNICODETEXT,"Unicode"}, {CF_ENHMETAFILE,"ENHMetafile"}, {CF_HDROP, "HDROP"}, {CF_LOCALE, "Locale"}, {CF_DIBV5, "DIBV5"} };
typedef struct { UINT32 mm; UINT32 xExt; UINT32 yExt; } CLIPBOARD_MFPICT, *PCLIPBOARD_MFPICT;
/*
* Clipboard functions definitions */ VOID Clp_ListAllFormats(VOID);
//VOID
//Clp_ListAllAvailableFormats(VOID);
UINT Clp_GetClipboardFormat(LPCSTR szFormatLookup);
VOID Clp_PutIntoClipboard(CHAR *g_szFileName);
VOID Clp_GetClipboardData( UINT format, HGLOBAL hClipData, INT *pnClipDataSize, HGLOBAL *phNewData);
BOOL Clp_SetClipboardData( UINT formatID, HGLOBAL hClipData, INT nClipDataSize, BOOL *pbFreeHandle);
HGLOBAL Clp_GetMFData(HANDLE hData, PUINT pDataLen);
HGLOBAL Clp_SetMFData(UINT dataLen, PVOID pData);
VOID _cdecl LocalPrintMessage(INT errlevel, CHAR *format, ...);
VOID Clp_ListAllFormats(VOID) { UINT format = 0; CHAR szFormatName[_MAX_PATH];
while ((format = EnumClipboardFormats(format))) { *szFormatName = 0; GetClipboardFormatNameA(format, szFormatName, _MAX_PATH);
if (!(*szFormatName)) // No format, check for known format
{ INT fmti, fmtnum;
fmtnum = sizeof(KnownFormats)/sizeof(KnownFormats[0]); for (fmti = 0; KnownFormats[fmti].uiFormat != format && fmti < fmtnum; fmti ++);
if (fmti < fmtnum) strcpy(szFormatName, KnownFormats[fmti].szFormat); }
if (*szFormatName) { TRACE((INFO_MESSAGE, "%s[%d(0x%X)]\n", szFormatName, format, format)); } else { TRACE((ERROR_MESSAGE, "Can't find format name for: 0x%x\n", format)); } } } /*
VOID Clp_ListAllAvailableFormats(VOID) { UINT format = 0; CHAR szFormatName[_MAX_PATH];
while ((format = EnumClipboardFormats(format))) { if (!IsClipboardFormatAvailable(format)) // Skip the unavalable formats
continue; *szFormatName = 0; GetClipboardFormatName(format, szFormatName, _MAX_PATH);
if (!(*szFormatName)) // No format, check for known format
{ INT fmti, fmtnum;
fmtnum = sizeof(KnownFormats)/sizeof(KnownFormats[0]); for (fmti = 0; KnownFormats[fmti].uiFormat != format && fmti < fmtnum; fmti ++);
if (fmti < fmtnum) strcpy(szFormatName, KnownFormats[fmti].szFormat); }
if (*szFormatName) TRACE((INFO_MESSAGE, "%s\n", szFormatName)); else TRACE((ERROR_MESSAGE, "Can't find format name for: 0x%x\n", format)); } } */ UINT Clp_GetClipboardFormat(LPCSTR szFormatLookup) // Returns the clipboard ID
{ UINT format = 0; CHAR szFormatName[_MAX_PATH]; BOOL bFound = FALSE;
*szFormatName = 0; while (!bFound && (format = EnumClipboardFormats(format))) { if (!IsClipboardFormatAvailable(format)) // Skip the unavalable formats
continue;
*szFormatName = 0; GetClipboardFormatNameA(format, szFormatName, _MAX_PATH);
if (!(*szFormatName)) // No format, check for known format
{ INT fmti, fmtnum;
fmtnum = sizeof(KnownFormats)/sizeof(KnownFormats[0]); for (fmti = 0; KnownFormats[fmti].uiFormat != format && fmti < fmtnum; fmti ++);
if (fmti < fmtnum) strcpy(szFormatName, KnownFormats[fmti].szFormat); } bFound = (_stricmp(szFormatName, szFormatLookup) == 0); }
return format; }
VOID Clp_PutIntoClipboard(CHAR *szFileName) { INT hFile = -1; LONG clplength = 0; UINT uiFormat = 0; HGLOBAL ghClipData = NULL; PBYTE pClipData = NULL; BOOL bClipboardOpen = FALSE; BOOL bFreeClipHandle = TRUE;
hFile = _open(szFileName, _O_RDONLY|_O_BINARY); if (hFile == -1) { TRACE((ERROR_MESSAGE, "Error opening file: %s. errno=%d\n", szFileName, errno)); goto exitpt; }
clplength = _filelength(hFile) - sizeof(uiFormat); if (_read(hFile, &uiFormat, sizeof(uiFormat)) != sizeof(uiFormat)) { TRACE((ERROR_MESSAGE, "Error reading from file. errno=%d\n", errno)); goto exitpt; }
ghClipData = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, clplength); if (!ghClipData) { TRACE((ERROR_MESSAGE, "Can't allocate %d bytes\n", clplength)); goto exitpt; }
pClipData = (PBYTE) GlobalLock(ghClipData); if (!pClipData) { TRACE((ERROR_MESSAGE, "Can't lock handle 0x%x\n", ghClipData)); goto exitpt; }
if (_read(hFile, pClipData, clplength) != clplength) { TRACE((ERROR_MESSAGE, "Error reading from file. errno=%d\n", errno)); goto exitpt; }
GlobalUnlock(ghClipData);
if (!OpenClipboard(NULL)) { TRACE((ERROR_MESSAGE, "Can't open the clipboard. GetLastError=%d\n", GetLastError())); goto exitpt; }
bClipboardOpen = TRUE;
// Empty the clipboard, so we'll have only one entry
EmptyClipboard();
if (!Clp_SetClipboardData(uiFormat, ghClipData, clplength, &bFreeClipHandle)) { TRACE((ERROR_MESSAGE, "SetClipboardData failed.\n")); } else { TRACE((INFO_MESSAGE, "Clipboard is loaded successfuly. File: %s, %d bytes\n", szFileName, clplength)); }
exitpt: // Do the cleanup
// Close the clipboard
if (bClipboardOpen) CloseClipboard();
// Release the clipboard handle
if (pClipData) GlobalUnlock(ghClipData);
if (ghClipData && bFreeClipHandle) GlobalFree(ghClipData);
// Close the file
if (hFile != -1) _close(hFile); }
VOID Clp_GetClipboardData( UINT format, HGLOBAL hClipData, INT *pnClipDataSize, HGLOBAL *phNewData) { HGLOBAL hData = hClipData; UINT dataLen = 0; WORD numEntries; DWORD dwEntries; PVOID pData;
*phNewData = NULL; *pnClipDataSize = 0; if (format == CF_PALETTE) { /****************************************************************/ /* Find out how many entries there are in the palette and */ /* allocate enough memory to hold them all. */ /****************************************************************/ if (GetObjectA(hData, sizeof(numEntries), (LPSTR)&numEntries) == 0) { numEntries = 256; }
dataLen = sizeof(LOGPALETTE) + ((numEntries - 1) * sizeof(PALETTEENTRY));
*phNewData = GlobalAlloc(GHND, dataLen); if (*phNewData == 0) { TRACE((ERROR_MESSAGE, "Failed to get %d bytes for palette", dataLen)); goto exitpt; } else { /************************************************************/ /* now get the palette entries into the new buffer */ /************************************************************/ pData = GlobalLock(*phNewData); dwEntries = (WORD)GetPaletteEntries((HPALETTE)hData, 0, numEntries, (PALETTEENTRY*)pData); GlobalUnlock(*phNewData); if (dwEntries == 0) { TRACE((ERROR_MESSAGE, "Failed to get any palette entries")); goto exitpt; } dataLen = dwEntries * sizeof(PALETTEENTRY);
} } else if (format == CF_METAFILEPICT) { *phNewData = Clp_GetMFData(hData, &dataLen); if (!*phNewData) { TRACE((ERROR_MESSAGE, "Failed to set MF data")); goto exitpt; } } else { if (format == CF_DIB) { // Get the exact DIB size
BITMAPINFOHEADER *pBMI = (BITMAPINFOHEADER *) GlobalLock(hData);
if (pBMI) { if (pBMI->biSizeImage) dataLen = pBMI->biSize + pBMI->biSizeImage; GlobalUnlock(hData); } }
/****************************************************************/ /* just get the length of the block */ /****************************************************************/ if (!dataLen) dataLen = (DWORD)GlobalSize(hData); }
*pnClipDataSize = dataLen;
exitpt: ; }
BOOL Clp_SetClipboardData( UINT formatID, HGLOBAL hClipData, INT nClipDataSize, BOOL *pbFreeHandle) { BOOL rv = FALSE; PVOID pData = NULL; HGLOBAL hData = NULL; LOGPALETTE *pLogPalette = NULL; UINT numEntries, memLen;
if (!pbFreeHandle) goto exitpt;
*pbFreeHandle = TRUE;
if (formatID == CF_METAFILEPICT) { /********************************************************************/ /* We have to put a handle to the metafile on the clipboard - which */ /* means creating a metafile from the received data first */ /********************************************************************/ pData = GlobalLock(hClipData); if (!pData) { TRACE((ERROR_MESSAGE, "Failed to lock buffer\n")); goto exitpt; }
hData = Clp_SetMFData(nClipDataSize, pData); if (!hData) { TRACE((ERROR_MESSAGE, "Failed to set MF data\n")); } else if (SetClipboardData(formatID, hData) != hData) { TRACE((ERROR_MESSAGE, "SetClipboardData. GetLastError=%d\n", GetLastError())); }
GlobalUnlock(hClipData);
} else if (formatID == CF_PALETTE) { /********************************************************************/ /* We have to put a handle to the palette on the clipboard - again */ /* this means creating one from the received data first */ /* */ /* Allocate memory for a LOGPALETTE structure large enough to hold */ /* all the PALETTE ENTRY structures, and fill it in. */ /********************************************************************/ numEntries = (nClipDataSize / sizeof(PALETTEENTRY)); memLen = (sizeof(LOGPALETTE) + ((numEntries - 1) * sizeof(PALETTEENTRY))); pLogPalette = (LOGPALETTE *) malloc(memLen); if (!pLogPalette) { TRACE((ERROR_MESSAGE, "Failed to get %d bytes", memLen)); goto exitpt; }
pLogPalette->palVersion = 0x300; pLogPalette->palNumEntries = (WORD)numEntries;
/********************************************************************/ /* get a pointer to the data and copy it to the palette */ /********************************************************************/ pData = GlobalLock(hClipData); if (pData == NULL) { TRACE((ERROR_MESSAGE, "Failed to lock buffer")); goto exitpt; } memcpy(pLogPalette->palPalEntry, pData, nClipDataSize);
/********************************************************************/ /* unlock the buffer */ /********************************************************************/ GlobalUnlock(hClipData);
/********************************************************************/ /* now create a palette */ /********************************************************************/ hData = CreatePalette(pLogPalette); if (!hData) { TRACE((ERROR_MESSAGE, "CreatePalette failed\n")); goto exitpt; }
/********************************************************************/ /* and set the palette handle to the Clipboard */ /********************************************************************/ if (SetClipboardData(formatID, hData) != hData) { TRACE((ERROR_MESSAGE, "SetClipboardData. GetLastError=%d\n", GetLastError())); } } else { /****************************************************************/ /* Just set it onto the clipboard */ /****************************************************************/ if (SetClipboardData(formatID, hClipData) != hClipData) { TRACE((ERROR_MESSAGE, "SetClipboardData. GetLastError=%d, hClipData=0x%x\n", GetLastError(), hClipData)); goto exitpt; }
// Only in this case we don't need to free the handle
*pbFreeHandle = FALSE;
}
rv = TRUE;
exitpt: if (!pLogPalette) { free(pLogPalette); }
return rv; }
HGLOBAL Clp_GetMFData(HANDLE hData, PUINT pDataLen) { UINT lenMFBits = 0; BOOL rc = FALSE; LPMETAFILEPICT pMFP = NULL; HDC hMFDC = NULL; HMETAFILE hMF = NULL; // HGLOBAL hMFBits = NULL;
HANDLE hNewData = NULL; CHAR *pNewData = NULL; // PVOID pBits = NULL;
/************************************************************************/ /* Lock the memory to get a pointer to a METAFILEPICT header structure */ /* and create a METAFILEPICT DC. */ /************************************************************************/ pMFP = (LPMETAFILEPICT)GlobalLock(hData); if (pMFP == NULL) goto exitpt;
hMFDC = CreateMetaFileA(NULL); if (hMFDC == NULL) goto exitpt;
/************************************************************************/ /* Copy the MFP by playing it into the DC and closing it. */ /************************************************************************/ if (!PlayMetaFile(hMFDC, pMFP->hMF)) { CloseMetaFile(hMFDC); goto exitpt; } hMF = CloseMetaFile(hMFDC); if (hMF == NULL) goto exitpt;
/************************************************************************/ /* Get the MF bits and determine how long they are. */ /************************************************************************/ #ifdef OS_WIN16
hMFBits = GetMetaFileBitsA(hMF); lenMFBits = GlobalSize(hMFBits); #else
lenMFBits = GetMetaFileBitsEx(hMF, 0, NULL); #endif
if (lenMFBits == 0) goto exitpt;
/************************************************************************/ /* Work out how much memory we need and get a buffer */ /************************************************************************/ *pDataLen = sizeof(CLIPBOARD_MFPICT) + lenMFBits; hNewData = GlobalAlloc(GHND, *pDataLen); if (hNewData == NULL) goto exitpt;
pNewData = (char *) GlobalLock(hNewData);
/************************************************************************/ /* Copy the MF header and bits into the buffer. */ /************************************************************************/ ((PCLIPBOARD_MFPICT)pNewData)->mm = pMFP->mm; ((PCLIPBOARD_MFPICT)pNewData)->xExt = pMFP->xExt; ((PCLIPBOARD_MFPICT)pNewData)->yExt = pMFP->yExt;
#ifdef OS_WIN16
pBits = GlobalLock(hMFBits); memcpy((pNewData + sizeof(CLIPBOARD_MFPICT)), pBits, lenMFBits); GlobalUnlock(hMFBits); #else
lenMFBits = GetMetaFileBitsEx(hMF, lenMFBits, (pNewData + sizeof(CLIPBOARD_MFPICT))); if (lenMFBits == 0) goto exitpt; #endif
/************************************************************************/ /* all OK */ /************************************************************************/ rc = TRUE;
exitpt: /************************************************************************/ /* Unlock any global mem. */ /************************************************************************/ if (pMFP) { GlobalUnlock(hData); } if (pNewData) { GlobalUnlock(hNewData); }
/************************************************************************/ /* if things went wrong, then free the new data */ /************************************************************************/ if ((rc == FALSE) && (hNewData != NULL)) { GlobalFree(hNewData); hNewData = NULL; }
return(hNewData);
}
HGLOBAL Clp_SetMFData(UINT dataLen, PVOID pData) { BOOL rc = FALSE; HGLOBAL hMFBits = NULL; PVOID pMFMem = NULL; HMETAFILE hMF = NULL; HGLOBAL hMFPict = NULL; LPMETAFILEPICT pMFPict = NULL;
/************************************************************************/ /* Allocate memory to hold the MF bits (we need the handle to pass to */ /* SetMetaFileBits). */ /************************************************************************/ hMFBits = GlobalAlloc(GHND, dataLen - sizeof(CLIPBOARD_MFPICT)); if (hMFBits == NULL) goto exitpt;
/************************************************************************/ /* Lock the handle and copy in the MF header. */ /************************************************************************/ pMFMem = GlobalLock(hMFBits); if (pMFMem == NULL) goto exitpt;
memcpy(pMFMem, (PVOID)((CHAR *)pData + sizeof(CLIPBOARD_MFPICT)), dataLen - sizeof(CLIPBOARD_MFPICT) );
GlobalUnlock(hMFBits);
/************************************************************************/ /* Now use the copied MF bits to create the actual MF bits and get a */ /* handle to the MF. */ /************************************************************************/ #ifdef OS_WIN16
hMF = SetMetaFileBits(hMFBits); #else
hMF = SetMetaFileBitsEx(dataLen - sizeof(CLIPBOARD_MFPICT), (const BYTE *) pMFMem); #endif
if (hMF == NULL) goto exitpt;
/************************************************************************/ /* Allocate a new METAFILEPICT structure, and use the data from the */ /* header. */ /************************************************************************/ hMFPict = GlobalAlloc(GHND, sizeof(METAFILEPICT)); pMFPict = (LPMETAFILEPICT)GlobalLock(hMFPict); if (!pMFPict) goto exitpt;
pMFPict->mm = (long)((PCLIPBOARD_MFPICT)pData)->mm; pMFPict->xExt = (long)((PCLIPBOARD_MFPICT)pData)->xExt; pMFPict->yExt = (long)((PCLIPBOARD_MFPICT)pData)->yExt; pMFPict->hMF = hMF;
GlobalUnlock(hMFPict);
rc = TRUE;
exitpt: /************************************************************************/ /* tidy up */ /************************************************************************/ if (!rc) { if (hMFPict) { GlobalFree(hMFPict); } if (hMFBits) { GlobalFree(hMFBits); } }
return(hMFPict);
}
BOOL Clp_EmptyClipboard(VOID) { BOOL rv = FALSE;
if (OpenClipboard(NULL)) { EmptyClipboard(); rv = TRUE; CloseClipboard(); }
return rv; }
BOOL Clp_CheckEmptyClipboard(VOID) { BOOL rv = TRUE;
if (OpenClipboard(NULL)) { if (EnumClipboardFormats(0)) // format is available, not empty
rv = FALSE; CloseClipboard(); }
return rv; }
// Checks for known format names and returns it's ID
UINT _GetKnownClipboardFormatIDByName(LPCSTR szFormatName) { INT fmti, fmtnum; UINT rv = 0;
fmtnum = sizeof(KnownFormats)/sizeof(KnownFormats[0]); for (fmti = 0; fmti < fmtnum && _stricmp(szFormatName, KnownFormats[fmti].szFormat); fmti ++) ;
if (fmti < fmtnum) rv = KnownFormats[fmti].uiFormat;
return rv; }
VOID _cdecl LocalPrintMessage(INT errlevel, CHAR *format, ...) { CHAR szBuffer[256]; CHAR *type; va_list arglist; INT nchr;
va_start (arglist, format); nchr = _vsnprintf (szBuffer, sizeof(szBuffer), format, arglist); szBuffer[SIZEOF_ARRAY(szBuffer) - 1] = 0; va_end (arglist);
switch(errlevel) { case INFO_MESSAGE: type = "INF"; break; case ALIVE_MESSAGE: type = "ALV"; break; case WARNING_MESSAGE: type = "WRN"; break; case ERROR_MESSAGE: type = "ERR"; break; default: type = "UNKNOWN"; }
printf("%s:%s", type, szBuffer); }
|