/*++ * File name: * clputil.c * Contents: * Clipboard functions * * Copyright (C) 1998-1999 Microsoft Corp. --*/ #include #include #include #include #include #include #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); }