2025-04-27 07:49:33 -04:00

1363 lines
37 KiB
C

/*
* CLIPFILE.C - Windows Clipboard File I/O Routines
*/
/* NOTE:
* When saving the contents of the clipboard we SetClipboardData(fmt, NULL)
* to free up the memory associated with each clipboard format. Then
* after we are done saving we take over as the clipboard owner. This
* causes OWNERDRAW formats to be lost in the save process.
*/
#include "clipshr.h"
#include "clipsrv.h"
#include <string.h>
#include <windowsx.h>
#include "..\common\dib.h"
#include "..\common\common.h"
BOOL fAnythingToRender;
TCHAR szFileSpecifier[] = TEXT("*.CLP");
TCHAR szFileName[MAX_PATH];
TCHAR szSaveFileName[MAX_PATH]; // Saved filename for delayed render
BOOL fNTReadFileFormat;
BOOL fNTSaveFileFormat;
extern TCHAR szCaptionName[];
UINT cf_link;
UINT cf_objectlink;
UINT cf_linkcopy;
UINT cf_objectlinkcopy;
extern HANDLE RenderFormat(FORMATHEADER *, register HANDLE);
// winball additions
extern BOOL AddNetInfoToClipboard ( TCHAR * );
extern BOOL AddPreviewFormat ( VOID );
extern BOOL AddCopiedFormat ( UINT ufmtOriginal, UINT ufmtCopy );
BOOL AddDIBtoDDB(VOID);
// end winball
/*-----------------------------------------------------------------------
* File read routines
*-----------------------------------------------------------------------*/
//
// Purpose: Read the file header in the given .clp file, and get the number
// of formats. Also sets the fNTReadFileFormat flag appropriately.
//
// Parameters:
// fh - Handle to the file.
//
// Returns:
// The number of formats, or 0 if it isn't a valid .clp file.
//
unsigned ReadFileHeader(
HANDLE fh)
{
FILEHEADER FileHeader;
DWORD dwBytesRead;
// PINFO(TEXT("ClSrv\\RdFileHdr"));
/* Read the File Header */
SetFilePointer(fh, 0, NULL, FILE_BEGIN);
ReadFile(fh, &FileHeader, sizeof(FileHeader), &dwBytesRead, NULL);
if (dwBytesRead == sizeof(FILEHEADER))
{
// Make sure that this is a .CLP file
if (FileHeader.magic == CLPBK_NT_ID ||
FileHeader.magic == CLP_NT_ID)
{
fNTReadFileFormat = TRUE;
}
else if (FileHeader.magic == CLP_ID)
{
fNTReadFileFormat = FALSE;
}
else
{
PERROR(TEXT("Invalid magic member (not long enough?)\r\n"));
FileHeader.FormatCount = 0;
}
// Check number of formats for additional reassurance.
if (FileHeader.FormatCount > 100)
{
PERROR(TEXT("Too many formats!!!\r\n"));
FileHeader.FormatCount = 0;
}
}
else
{
PERROR("Read err\r\n");
FileHeader.FormatCount = 0;
}
if (FileHeader.FormatCount)
{
// PINFO(TEXT("\r\n"));
}
return(FileHeader.FormatCount);
}
BOOL ReadFormatHeader(
HANDLE fh,
FORMATHEADER *pfh,
unsigned iFormat)
{
DWORD dwMrPibb;
OLDFORMATHEADER OldFormatHeader;
// PINFO(TEXT("ClSrv\\RdFmtHdr"));
if (NULL == pfh || NULL == fh)
{
PERROR("RdFmtHdr got NULL pointer\r\n");
return FALSE;
}
SetFilePointer(fh, sizeof(FILEHEADER) + iFormat *
(fNTReadFileFormat ? sizeof(FORMATHEADER) : sizeof(OLDFORMATHEADER)),
NULL, FILE_BEGIN);
if (fNTReadFileFormat)
{
ReadFile(fh, pfh, sizeof(FORMATHEADER), &dwMrPibb, NULL);
if (dwMrPibb != sizeof(FORMATHEADER))
{
PERROR(TEXT("Bad new format rd\r\n"));
return FALSE;
}
}
else
{
ReadFile(fh, &OldFormatHeader, sizeof(OldFormatHeader), &dwMrPibb, NULL);
if (dwMrPibb != sizeof(OLDFORMATHEADER))
{
PERROR(TEXT("Bad old format rd\r\n"));
return FALSE;
}
pfh->FormatID = OldFormatHeader.FormatID;
pfh->DataLen = OldFormatHeader.DataLen;
pfh->DataOffset = OldFormatHeader.DataOffset;
MultiByteToWideChar(
CP_ACP, MB_PRECOMPOSED, OldFormatHeader.Name, -1,
pfh->Name, CCHFMTNAMEMAX);
}
// PINFO(TEXT("\r\n"));
return TRUE;
}
/*
* ReadClipboardFromFile()
*
* Read in a clipboard file and register all the formats in delayed mode.
* to render things for real reopen the file specified by ofStruct.
*
* NOTE:
* This makes us the clipboard owner.
*
* Bug 14564: Changed return value to a short integer noting why the
* reading failed.
* Return Value: 0 Success
* 1 Improper format
* 2 SyncOpenClipboard failed
*/
#define READFILE_SUCCESS 0
#define READFILE_IMPROPERFORMAT 1
#define READFILE_OPENCLIPBRDFAIL 2
short ReadClipboardFromFile(
HWND hwnd,
HANDLE fh)
{
register unsigned i;
unsigned cFormats;
FORMATHEADER FormatHeader;
OLDFORMATHEADER OldFormatHeader;
// DWORD dwMrPibb; // Dummy var used for ReadFile
PINFO(TEXT("Entering ReadClipboardFromFile\r\n"));
if (!(cFormats = ReadFileHeader(fh)) )
{
return(READFILE_IMPROPERFORMAT);
}
/* We become the clipboard owner here! */
if (!SyncOpenClipboard(hwnd))
{
PERROR(TEXT("Could not open clipboard!!!"));
return(READFILE_OPENCLIPBRDFAIL);
}
EmptyClipboard();
for (i=0; i < cFormats; i++)
{
ReadFormatHeader(fh, &FormatHeader, i);
if (PRIVATE_FORMAT(FormatHeader.FormatID))
{
FormatHeader.FormatID = RegisterClipboardFormatW((LPWSTR)FormatHeader.Name);
}
/*Delayed Render. */
PINFO(TEXT("Set up delayed render for format %d .\r\n"), FormatHeader.FormatID);
SetClipboardData(FormatHeader.FormatID, NULL);
}
/* Now, clipbrd viewer has something to render */
if (cFormats > 0)
{
PINFO(TEXT("fAnythingToRender = TRUE\r\n"));
fAnythingToRender = TRUE;
}
SyncCloseClipboard();
return(READFILE_SUCCESS);
}
BOOL OpenClipboardFile(
HWND hwnd,
LPTSTR szName)
{
HANDLE fh;
BOOL nReadError = TRUE;
PINFO(TEXT("OpenClipboardFile: %s \r\n"),szName);
fh = CreateFile((LPCTSTR)szName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh != INVALID_HANDLE_VALUE)
{
// Store file name for delayed rendering stuff.
lstrcpy(szSaveFileName, szName);
// Read it.
nReadError = ReadClipboardFromFile(hwnd, fh);
CloseHandle(fh);
}
else
{
PERROR(TEXT("ClSrv\\OpClpFile: can't open file!"));
}
return !nReadError;
}
//
// Purpose: Go get the given format from the given file.
//
/////////////////////////////////////////////////////////////////
HANDLE RenderFormatFromFile(
LPTSTR szFile,
WORD wFormat)
{
HANDLE fh;
FORMATHEADER FormatHeader;
HANDLE hData = NULL;
DWORD dwBytesRead; // Dummy var for ReadFile
unsigned cFormats;
unsigned i;
PINFO(TEXT("ClSrv\\RndrFmtFromFile: Opening file %s.\r\n"),szSaveFileName);
fh = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != fh)
{
cFormats = ReadFileHeader(fh);
// If ReadFile didn't get the whole header, don't try to read anything
// else.
if (0 == cFormats)
{
PERROR(TEXT("Bad file header.\r\n"));
}
for (i=0; i < cFormats; i++)
{
ReadFormatHeader(fh, &FormatHeader, i);
PINFO(TEXT("Got format %ws\r\n"),FormatHeader.Name);
if (PRIVATE_FORMAT(FormatHeader.FormatID))
{
FormatHeader.FormatID = RegisterClipboardFormatW(FormatHeader.Name);
}
if (FormatHeader.FormatID == wFormat)
{
hData = RenderFormat(&FormatHeader, fh);
}
}
CloseHandle(fh);
}
else
{
PERROR(TEXT("Can't open file\r\n"));
}
return(hData);
}
//
// Purpose: Go get all formats from the given file.
//
/////////////////////////////////////////////////////////////////
HANDLE RenderAllFromFile(
LPTSTR szFile)
{
HANDLE fh;
FORMATHEADER FormatHeader;
HANDLE hData;
DWORD dwBytesRead; // Dummy var for ReadFile
unsigned cFormats;
unsigned i;
/* Check if the clipbrd viewer has done any File I/O before.
* If it has not, then it has nothing to render! Sankar
*/
if (CountClipboardFormats() && fAnythingToRender)
{
/* Empty the clipboard */
if (!SyncOpenClipboard(hwndServer))
{
PERROR("Couldn't open clipboard!\r\n");
}
else
{
EmptyClipboard();
fh = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != fh)
{
cFormats = ReadFileHeader(fh);
// If ReadFile didn't get the whole header, don't try to read anything
// else.
if (0 == cFormats)
{
PERROR(TEXT("Bad file header.\r\n"));
}
for (i=0; i < cFormats; i++)
{
ReadFormatHeader(fh, &FormatHeader, i);
PINFO(TEXT("Got format %ws\r\n"),FormatHeader.Name);
if (PRIVATE_FORMAT(FormatHeader.FormatID))
{
FormatHeader.FormatID =
RegisterClipboardFormatW(FormatHeader.Name);
}
// Render the format and set it into the clipboard
hData = RenderFormat(&FormatHeader, fh);
if ( hData != NULL )
{
if (!SetClipboardData(FormatHeader.FormatID, hData))
{
PERROR(TEXT("SetClipboardData fail\n\r"));
}
}
else
{
PERROR(TEXT("hData == NULL, bad\r\n"));
}
}
CloseHandle(fh);
}
else
{
PERROR(TEXT("Can't open file\r\n"));
}
SyncCloseClipboard();
}
}
return(0L);
}
/*-------------------------------------------------------------------------
* File write routines
*-------------------------------------------------------------------------*/
/*
* IsWriteable()
*
* Test if a clipboard format is writeable(i.e. if it makes sense to write it)
* OWNERDRAW and others can't be written because we (CLIPBRD) will become the
* owner when the files are reopened.
*/
BOOL IsWriteable(WORD Format)
{
/* Are the PRIVATEFIRST and PRIVATELAST things right? */
if ((Format >= CF_PRIVATEFIRST && Format <= CF_PRIVATELAST)
|| Format == CF_OWNERDISPLAY)
{
return FALSE;
}
// If we're not saving an NT clipboard, don't save NT-specific formats.
if (!fNTSaveFileFormat &&
(Format == CF_UNICODETEXT || Format == CF_ENHMETAFILE
|| Format == CF_DSPENHMETAFILE)
)
{
return(FALSE);
}
return(TRUE);
}
/* This function will return the number of clipboard formats compatible with
the Windows 3.1 clipboard, this excludes CF_UNICODETEXT, CF_ENHMETAFILE and
CF_DSPENHMETAFILE
*/
int Count16BitClipboardFormats(void)
{
int iCount;
iCount = CountClipboardFormats();
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
iCount--;
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
iCount--;
if (IsClipboardFormatAvailable(CF_DSPENHMETAFILE))
iCount--;
return iCount;
}
/*
* Purpose: Writes the format header for a single data format.
*
* Parameters:
* fh - File handle to write to.
* offset - Position in the file to write the format block.
* DataOffset - Position in the file where the data for this format will be.
* DataLen - Length of the data for this format.
* Format - The format number.
* szName - Name of the format.
*
* Returns:
* The number of bytes written to the file.
*/
DWORD WriteFormatBlock(
HANDLE fh,
DWORD offset,
DWORD DataOffset,
DWORD DataLen,
UINT Format,
LPWSTR wszName)
{
DWORD dwBytesWritten = 0;
SetFilePointer(fh, offset, NULL, FILE_BEGIN);
if (fNTSaveFileFormat)
{
FORMATHEADER FormatHeader;
memset(&FormatHeader,0, sizeof(FormatHeader));
FormatHeader.FormatID = Format;
FormatHeader.DataLen = DataLen;
FormatHeader.DataOffset = DataOffset;
lstrcpyW(FormatHeader.Name, wszName);
WriteFile(fh, &FormatHeader, sizeof(FormatHeader), &dwBytesWritten, NULL);
}
else
{
OLDFORMATHEADER OldFormatHeader;
memset(&OldFormatHeader,0, sizeof(OldFormatHeader));
OldFormatHeader.FormatID = Format;
OldFormatHeader.DataLen = DataLen;
OldFormatHeader.DataOffset = DataOffset;
WideCharToMultiByte(CP_ACP, 0, wszName, -1,
OldFormatHeader.Name, CCHFMTNAMEMAX, NULL, NULL);
WriteFile(fh, &OldFormatHeader, sizeof(OldFormatHeader),
&dwBytesWritten, NULL);
}
return(dwBytesWritten);
}
/*
* WriteDataBlock() -
*
* Returns:
* # of bytes written to the output file
*
* NOTE: Write saves the name of a temp file in the clipboard for it's
* own internal clipboard format. This file goes aways when Write
* (or windows?) shuts down. Thus saving Write clipboards won't work
* (should we special case hack this?)
*
*/
DWORD WriteDataBlock(
register HANDLE hFile,
DWORD offset,
WORD Format)
{
WORD wPalEntries;
LPSTR lpData;
DWORD dwSize = 0;
BITMAP bitmap;
HANDLE hMF;
HANDLE hBitmap;
HANDLE hLogPalette;
register HANDLE hData;
LPLOGPALETTE lpLogPalette;
LPMETAFILEPICT lpMFP;
DWORD dwMFPSize;
BOOL fOK = FALSE;
if (!(hData = GetClipboardData(Format)) ||
SetFilePointer(hFile, offset, NULL, FILE_BEGIN) != offset)
{
PERROR(TEXT("WriteDataBlock: couldn't get format data\n\r"));
}
else
{
/* We have to special case a few common formats but most things
* get handled in the default case.
*/
switch (Format)
{
case CF_ENHMETAFILE:
dwSize = (DWORD) GetEnhMetaFileBits(hData, 0, NULL); /* Get data size */
if (lpData = GlobalAllocPtr(GHND, dwSize)) /* allocate mem for EMF bits */
{
if (GetEnhMetaFileBits(hData, dwSize, (LPBYTE)lpData))
{
WriteFile(hFile, lpData, dwSize, &dwSize, NULL);
fOK = TRUE;
}
GlobalFreePtr(lpData);
}
if (!fOK)
{
PERROR(TEXT("WriteDataBlock: couldn't write CF_ENHMETAFILE\r\n"));
dwSize = 0;
}
break;
case CF_METAFILEPICT:
if (lpMFP = (LPMETAFILEPICT)GlobalLock(hData)) /* get header */
{
// Write METAFILEPICT header -- if we're saving in Win31 format,
// write the old-style header.
if (fNTSaveFileFormat)
{
WriteFile(hFile, lpMFP, sizeof(METAFILEPICT),
&dwMFPSize, NULL);
}
else
{
WIN31METAFILEPICT w31mfp;
/* If we save the metafile in the Windows 3.1 .CLP file format
we have to save the METAFILEPICT structure as a 16bit METAFILEPICT
structure. This may cause loss of information if the
high half of the METAFILEPICT structure's fields are used.
[pierrej 5/27/92] */
w31mfp.mm = lpMFP->mm;
w31mfp.xExt = lpMFP->xExt;
w31mfp.yExt = lpMFP->yExt;
w31mfp.hMF = 0;
WriteFile(hFile, &w31mfp, sizeof(WIN31METAFILEPICT),
&dwMFPSize, NULL);
}
hMF = lpMFP->hMF;
GlobalUnlock(hData); /* unlock the header */
/* Figure out how big a block we need */
dwSize = GetMetaFileBitsEx(hMF, 0, NULL);
if (dwSize)
{
if (lpData = GlobalAllocPtr(GHND, dwSize))
{
if (dwSize == GetMetaFileBitsEx(hMF, dwSize, lpData))
{
WriteFile(hFile, lpData, dwSize,
&dwSize, NULL);
dwSize += dwMFPSize;
}
else
{
dwSize = 0;
}
GlobalFreePtr(lpData);
}
else
{
dwSize = 0;
}
}
}
break;
case CF_BITMAP:
/* Writing DDBs to disk is bad. Therefore, we */
/* write an intelligent CF_DIB block instead. */
/* A-MGATES 9/29/92 */
Format = CF_DIB;
GetObject((HBITMAP)hData, sizeof(BITMAP), &bitmap);
if (hBitmap = DibFromBitmap((HBITMAP)hData, BI_RGB,
bitmap.bmBitsPixel * bitmap.bmPlanes,
IsClipboardFormatAvailable(CF_PALETTE) ?
GetClipboardData(CF_PALETTE) : NULL))
{
if (lpData = GlobalLock(hBitmap))
{
// dwSize might be too big, but we can live with that.
dwSize = GlobalSize(lpData);
WriteFile(hFile, lpData, dwSize,
&dwSize, NULL);
// Clean up
GlobalUnlock(hBitmap);
GlobalFree(hBitmap);
}
}
break;
case CF_PALETTE:
/* Get the number of palette entries */
GetObject(hData, sizeof(WORD), (LPBYTE)&wPalEntries);
/* Allocate enough place to build the LOGPALETTE struct */
dwSize = (DWORD)(sizeof(LOGPALETTE) +
(LONG)wPalEntries * sizeof(PALETTEENTRY));
if (lpLogPalette = (LPLOGPALETTE)GlobalAllocPtr(GHND, dwSize))
{
lpLogPalette->palVersion = 0x300; /* Windows 3.00 */
lpLogPalette->palNumEntries = wPalEntries;
if (GetPaletteEntries(hData, 0, wPalEntries,
(LPPALETTEENTRY)(lpLogPalette->palPalEntry)) != 0)
{
/* Write the LOGPALETTE structure onto disk */
WriteFile(hFile, lpLogPalette, dwSize, &dwSize, NULL);
}
else
{
dwSize = 0;
}
GlobalFreePtr(lpLogPalette);
}
else
{
dwSize = 0L;
}
break;
default:
dwSize = GlobalSize(hData);
// Just lock the data down and write it out.
if (lpData = GlobalLock(hData))
{
WriteFile(hFile, lpData, dwSize, &dwSize, NULL);
GlobalUnlock(hData);
}
else
{
dwSize = 0;
}
break;
}
}
/* Return the number of bytes written. */
return(dwSize);
}
/*--------------------------------------------------------------------------*/
/* */
/* SendOwnerMessage() - */
/* */
/*--------------------------------------------------------------------------*/
void SendOwnerMessage(
UINT message,
WPARAM wParam,
LPARAM lParam)
{
register HWND hwndOwner;
/* Send a message to the clipboard owner, if there is one */
hwndOwner = GetClipboardOwner();
if (hwndOwner != NULL)
SendMessage(hwndOwner, message, wParam, lParam);
}
/*--------------------------------------------------------------------------*/
/* */
/* GetClipboardNameW() - */
/* */
/*--------------------------------------------------------------------------*/
void GetClipboardNameW(
register int fmt,
LPWSTR wszName,
register int iSize)
{
LPWSTR lprgch;
HANDLE hrgch;
*wszName = '\0';
/* Get global memory that everyone can get to */
if (hrgch = GlobalAlloc(GMEM_MOVEABLE, (LONG)(iSize + 1)*sizeof(WCHAR)))
{
if ((lprgch = (LPWSTR)GlobalLock(hrgch)))
{
memset(lprgch, 0, (iSize+1)*sizeof(WCHAR));
switch (fmt)
{
case CF_RIFF:
case CF_WAVE:
case CF_PENDATA:
case CF_SYLK:
case CF_DIF:
case CF_TIFF:
case CF_TEXT:
case CF_BITMAP:
case CF_METAFILEPICT:
case CF_ENHMETAFILE:
case CF_OEMTEXT:
case CF_DIB:
case CF_PALETTE:
case CF_DSPTEXT:
case CF_DSPBITMAP:
case CF_DSPMETAFILEPICT:
case CF_DSPENHMETAFILE:
LoadStringW(hInst, fmt, lprgch, iSize);
break;
case CF_OWNERDISPLAY: /* Clipbrd owner app supplies name */
// Note: This should NEVER happen because this function only gets
// called when we're writing a given clipboard format. Clipbrd can't
// get away with writing CF_OWNERDISPLAY because we become clipboard
// owner when we re-read the file, and we won't know how to deal.
PERROR(TEXT("GetClipboardName on OwnerDisplay format!\r\n"));
// *lprgch = '\0';
// SendOwnerMessageW(WM_ASKCBFORMATNAME, iSize, (LPARAM)lprgch);
// if (!*lprgch)
LoadStringW(hInst, fmt, lprgch, iSize);
break;
default:
GetClipboardFormatNameW(fmt, lprgch, iSize);
break;
}
lstrcpyW(wszName, lprgch);
GlobalUnlock(hrgch);
}
else
{
PERROR(TEXT("GetClipboardNameW: bad lock\r\n"));
}
GlobalFree(hrgch);
}
else
{
PERROR(TEXT("GetClipboardNameW: bad alloc\r\n"));
}
}
extern PSECURITY_DESCRIPTOR CurrentUserOnlySD(void);
/*
* SaveClipboardData() - Writes a clipboard file.
*
* In:
* hwnd handle of wnd that becomes the clipboard owner
* szFileName file handle to read from
* fPage TRUE if this is a clipbook page (which means we secure it)
*
* NOTE:
* When done we call ReadClipboardFromFile(). this makes us the
* clipboard owner.
*/
BOOL SaveClipboardData(
HWND hwnd,
LPTSTR szFileName,
BOOL fPage)
{
register HANDLE fh;
register WORD Format;
DWORD HeaderPos;
DWORD DataPos;
DWORD datasize;
BOOL fComplain = TRUE;
HCURSOR hCursor;
FILEHEADER FileHeader;
// Must be WCHAR... it be format name!
WCHAR wszName[CCHFMTNAMEMAX];
UINT wHeaderSize;
UINT uiSizeHeaderToWrite;
BOOL fDIBUsed = FALSE;
DWORD dwQuaker100PercentNatural; // What I was eating when I created this meaningless temp variable
SECURITY_ATTRIBUTES sa;
PSECURITY_DESCRIPTOR pSDUser;
/* First open the clipboard */
if (SyncOpenClipboard(hwndServer))
{
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = (fPage ? CurrentUserOnlySD() : NULL);
sa.bInheritHandle = FALSE;
fh = CreateFile((LPCTSTR)szFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
&sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (sa.lpSecurityDescriptor)
{
GlobalFree((HGLOBAL)sa.lpSecurityDescriptor);
}
if (fh != INVALID_HANDLE_VALUE)
{
/* Fill out the file header structure */
if (fNTSaveFileFormat)
{
FileHeader.magic = CLPBK_NT_ID; /* magic number to tag our files */
uiSizeHeaderToWrite = sizeof(FORMATHEADER);
}
else
{
FileHeader.magic = CLP_ID; /* magic number to tag our files */
uiSizeHeaderToWrite = sizeof(OLDFORMATHEADER);
}
FileHeader.FormatCount = 0; /* dummy for now */
/* Update HeaderPos and DataPos */
HeaderPos = sizeof(FILEHEADER);
/* This is the maximum number of formats that will be written. Potentially
* some may fail and some space will be wasted.
*/
if (fNTSaveFileFormat)
{
DataPos = HeaderPos + (uiSizeHeaderToWrite *
CountClipboardFormats());
}
else
{
DataPos = HeaderPos + (uiSizeHeaderToWrite *
Count16BitClipboardFormats());
}
/* Now loop throught the data, one format at a time, and write out the data. */
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE);
fComplain = FALSE;
/* Enumerate all formats */
Format = 0;
while (Format = EnumClipboardFormats(Format))
{
if (IsWriteable(Format))
{
// DO NOT write CF_BITMAP to disk. Transform to CF_DIB
// and write that instead.
if (CF_BITMAP == Format || CF_DIB == Format)
{
if (!fDIBUsed)
{
fDIBUsed = TRUE;
}
// If I've already done DIB, go on to the next format.
else continue;
}
GetClipboardNameW(Format == CF_BITMAP ? CF_DIB : Format,
wszName, sizeof(wszName));
PINFO(TEXT("SClipboardData: writing %ls (#)%d\r\n"),
wszName,Format);
if (datasize = WriteDataBlock(fh, DataPos, Format))
{
/* Create a Format header and write it to the file */
wHeaderSize = (WORD)WriteFormatBlock(
fh,
HeaderPos,
DataPos, datasize,
Format == CF_BITMAP ? CF_DIB : Format,
wszName);
if (wHeaderSize < uiSizeHeaderToWrite)
{
PERROR(TEXT("SaveClipboardData: error writing format block\n\r"));
fComplain = TRUE;
break;
}
HeaderPos += wHeaderSize;
/* Update the data pos for the next block */
DataPos += datasize;
FileHeader.FormatCount++; /* this format has been written */
}
else
{
PERROR(TEXT("SaveClipboardData: error writing data block\n\r"));
fComplain = TRUE;
break;
}
}
}
ShowCursor(FALSE);
SetCursor(hCursor);
SyncCloseClipboard(); /* we are done looking at this */
// Go back and write the file header at the front of the file
SetFilePointer(fh, 0L, NULL, FILE_BEGIN);
WriteFile(fh, &FileHeader, sizeof(FileHeader),
&dwQuaker100PercentNatural, NULL);
/* Now we open the clipboard and become the owner. this places
* all the things we just saved in the clipboard (and throws out
* those things we didn't save)
*/
// Set us back to the beginning
SetFilePointer(fh, 0L, NULL, FILE_BEGIN);
/* Under NT, the save filename will be used to get the file back */
lstrcpy(szSaveFileName, szFileName);
PINFO(TEXT("sAVEcLIPBOARDdATA: Copied name %s to name %s\r\n"),
szSaveFileName, szFileName);
fNTReadFileFormat = fNTSaveFileFormat;
if (!fComplain)
{
fComplain = ReadClipboardFromFile(hwndServer, fh);
}
CloseHandle(fh);
if (fComplain)
{
PERROR(TEXT("SCD: Trouble in ReadClipboardFromFile\r\n"));
DeleteFile(szFileName);
}
}
else
{
PERROR ("Error opening clipboard file!\r\n");
GetLastError();
}
SyncCloseClipboard();
}
return !fComplain;
}
/*
* SaveClipboardToFile() -
* Parameters:
* hwnd - Passed to SaveClipboardData
* szShareName - Clipbook page name
* szFileName - Filename to save to
* fPage - TRUE if this is a clbook page, FALSE if a file saved
* by the user.
*
* Returns: TRUE on success, FALSE on failure.
*
*/
BOOL SaveClipboardToFile(
HWND hwnd,
TCHAR *szShareName,
TCHAR *szFileName,
BOOL fPage)
{
PINFO(TEXT("\r\n Entering SaveClipboardToFile\r\n"));
if (fPage)
{
AddNetInfoToClipboard( szShareName );
AddPreviewFormat();
}
if (!SaveClipboardData(hwnd, szFileName, fPage))
{
/* If Failure, Delete the incomplete file */
PERROR(TEXT("SaveClipboardData failed!"));
DeleteFile(szSaveFileName);
return FALSE;
}
return TRUE;
}
BOOL AddPreviewFormat (
VOID)
{
HANDLE hClpData, hBmpData;
HBITMAP hBitmap, hClpBmp, hOldDstBmp, hOldSrcBmp;
LPMETAFILEPICT lpMF;
BITMAP Bitmap;
HDC hDC, hDstDC, hSrcDC;
LPBYTE lpClpData, lpBmp;
int ret = FALSE;
RECT rc;
int OldMode;
if (IsClipboardFormatAvailable(CF_TEXT) ||
IsClipboardFormatAvailable(CF_BITMAP) ||
IsClipboardFormatAvailable(CF_METAFILEPICT) ||
IsClipboardFormatAvailable(CF_ENHMETAFILE) ||
IsClipboardFormatAvailable(CF_UNICODETEXT) )
{
if ( !SyncOpenClipboard(hwndServer))
return FALSE;
if ( !(hBmpData = GlobalAlloc ( GHND, 64 * 64 / 8 )) )
{
SyncCloseClipboard();
return FALSE;
}
hDC = GetDC ( hwndServer );
hDstDC = CreateCompatibleDC ( hDC );
hSrcDC = CreateCompatibleDC ( hDC );
ReleaseDC ( hwndServer, hDC );
if ( !( hBitmap = CreateBitmap ( 64, 64, 1, 1, NULL )) )
PERROR (TEXT("CreateBitmap failed\n\r"));
hOldDstBmp = SelectObject ( hDstDC, hBitmap );
rc.top = rc.left = 0;
rc.bottom = rc.right = 64;
PatBlt ( hDstDC, 0, 0, 64, 64, WHITENESS );
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
{
HENHMETAFILE hemf;
ENHMETAHEADER enheader;
if (hemf = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE))
{
GetEnhMetaFileHeader(hemf, sizeof(enheader), &enheader);
SaveDC(hDstDC);
SetMapMode( hDstDC, MM_ISOTROPIC);
SetViewportExtEx(hDstDC, 64, 64, NULL);
SetWindowExtEx(hDstDC, enheader.rclBounds.right, enheader.rclBounds.bottom, NULL);
PlayEnhMetaFile(hDstDC, hemf, (LPRECT)&enheader.rclBounds);
RestoreDC(hDstDC, -1);
}
else
{
PERROR(TEXT("GetClipboardData fail on CF_ENHMETAFILE\r\n"));
}
}
else if ( IsClipboardFormatAvailable ( CF_METAFILEPICT ))
{
if ( hClpData = GetClipboardData ( CF_METAFILEPICT ))
{
if ( lpMF = (LPMETAFILEPICT)GlobalLock ( hClpData ) )
{
SaveDC(hDstDC);
SetMapMode( hDstDC, lpMF->mm);
if ( lpMF->xExt >= lpMF->yExt )
{
SetViewportExtEx( hDstDC, 64,
(int)((64L*(LONG)lpMF->yExt)/(LONG)lpMF->xExt), NULL);
SetViewportOrgEx ( hDstDC, 0,
(64 - (int)((64L*(LONG)lpMF->yExt)/(LONG)lpMF->xExt))
/ 2, NULL );
}
else
{
SetViewportExtEx( hDstDC,
(int)((64L*(LONG)lpMF->xExt)/(LONG)lpMF->yExt),64, NULL);
SetViewportOrgEx( hDstDC,
( 64 - (int)((64L*(LONG)lpMF->xExt)/(LONG)lpMF->yExt))
/ 2, 0, NULL);
}
if ( !PlayMetaFile ( hDstDC, lpMF->hMF ))
PERROR(TEXT("playmetafile failed\n\r"));
GlobalUnlock ( hClpData );
RestoreDC( hDstDC, -1 );
}
else
PERROR(TEXT("couldn't LOCK it though...\n\r"));
}
else
PERROR(TEXT("couldn't GET it though...\n\r"));
}
else if ( IsClipboardFormatAvailable ( CF_BITMAP ))
{
if ( hClpBmp = GetClipboardData ( CF_BITMAP ))
{
GetObject ( hClpBmp, sizeof(BITMAP), &Bitmap );
hOldSrcBmp = SelectObject ( hSrcDC, hClpBmp );
OldMode = SetStretchBltMode ( hDstDC, COLORONCOLOR);
StretchBlt ( hDstDC, 0, 0, 64, 64,
hSrcDC, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight,
SRCCOPY );
SetStretchBltMode ( hDstDC, OldMode );
SelectObject ( hSrcDC, hOldSrcBmp );
}
}
else if ( IsClipboardFormatAvailable ( CF_TEXT ))
{
LPSTR lpText;
HFONT hSmallFont, hOldFont;
if ( hClpData = GetClipboardData ( CF_TEXT ))
{
lpText = (LPSTR)GlobalLock ( hClpData );
FillRect ( hDstDC, &rc, GetStockObject ( WHITE_BRUSH ) );
hSmallFont = CreateFont( -6,
0, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
VARIABLE_PITCH | FF_SWISS, TEXT("Small Fonts")
);
hOldFont = SelectObject ( hDstDC, hSmallFont );
DrawTextA( hDstDC,lpText, lstrlenA(lpText),
&rc, DT_LEFT);
SelectObject ( hDstDC, hOldFont );
DeleteObject ( hSmallFont );
GlobalUnlock ( hClpData );
}
}
else if ( IsClipboardFormatAvailable (CF_UNICODETEXT))
{
LPWSTR lpText;
HFONT hSmallFont, hOldFont;
if ( hClpData = GetClipboardData ( CF_UNICODETEXT ))
{
lpText = (LPWSTR)GlobalLock ( hClpData );
FillRect ( hDstDC, &rc, GetStockObject ( WHITE_BRUSH ) );
hSmallFont = CreateFont( -6,
0, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
VARIABLE_PITCH | FF_SWISS, TEXT("Small Fonts")
);
hOldFont = SelectObject ( hDstDC, hSmallFont );
DrawTextW( hDstDC,lpText, lstrlenW(lpText),
&rc, DT_LEFT);
SelectObject ( hDstDC, hOldFont );
DeleteObject ( hSmallFont );
GlobalUnlock ( hClpData );
}
}
SelectObject ( hDstDC, hOldDstBmp );
DeleteDC ( hDstDC );
DeleteDC ( hSrcDC );
lpBmp = GlobalLock ( hBmpData );
if ( GetBitmapBits ( hBitmap, 64 * 64 / 8, lpBmp ) != 64*64/8 )
// if ( GetBitmapBits ( hBitmap, 64 * 64 / 2, lpBmp ) != 64*64/2 )
PERROR(TEXT("GetBitmapBits failed\n\r"));
GlobalUnlock ( hBmpData );
SetClipboardData ( cf_preview, hBmpData );
ret = TRUE;
DeleteObject ( hBitmap );
SyncCloseClipboard();
}
return ret;
}
BOOL AddCopiedFormat (
UINT ufmtOriginal,
UINT ufmtCopy )
{
LPBYTE lpOriginal, lpCopy;
HANDLE hOriginal, hCopy = NULL;
BOOL ret = FALSE;
int i;
if (IsClipboardFormatAvailable(ufmtOriginal) && SyncOpenClipboard(hwndServer)) {
if ( hOriginal = GetClipboardData(ufmtOriginal)) {
if ( hCopy = GlobalAlloc( GHND, GlobalSize(hOriginal))) {
if ( lpOriginal = GlobalLock(hOriginal)) {
if ( lpCopy = GlobalLock (hCopy)) {
for ( i=(int)GlobalSize(hOriginal); i--; )
*lpCopy++ = *lpOriginal++;
GlobalUnlock(hCopy);
#ifdef DEBUG
lpCopy = GlobalLock(hCopy);
GlobalUnlock(hCopy);
#endif
ret = ( SetClipboardData ( ufmtCopy, hCopy ) != NULL );
}
GlobalUnlock(hOriginal);
}
}
}
SyncCloseClipboard();
}
if ( !ret ) {
PERROR(TEXT("AddCopiedFormat returning FALSE!\n\r"));
if ( hCopy )
GlobalFree ( hCopy );
}
return ret;
}
BOOL AddNetInfoToClipboard (
TCHAR *szShareName )
{
HANDLE hData, hNewData;
TCHAR szServerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwNameLen;
LPTSTR src,dst;
cf_link = RegisterClipboardFormat ( SZLINK );
cf_objectlink = RegisterClipboardFormat ( SZOBJECTLINK );
cf_linkcopy = RegisterClipboardFormat ( SZLINKCOPY );
cf_objectlinkcopy = RegisterClipboardFormat ( SZOBJECTLINKCOPY );
// check to see if this info already added:
if ( IsClipboardFormatAvailable ( cf_linkcopy ) )
{
PINFO(TEXT("AddNetInfo: Already added\n\r"));
return FALSE;
}
else if ( IsClipboardFormatAvailable ( cf_link ) )
{
AddCopiedFormat ( cf_link, cf_linkcopy );
if (!SyncOpenClipboard(hwndServer))
return(FALSE);
dwNameLen = MAX_COMPUTERNAME_LENGTH+1;
GetComputerName(szServerName, &dwNameLen);
PINFO(TEXT("link data found\n\r"));
hData = GetClipboardData ( cf_link );
src = GlobalLock ( hData );
hNewData = GlobalAlloc ( GMEM_MOVEABLE | GMEM_ZEROINIT,
GlobalSize( hData )
+ lstrlen ( szServerName ) + lstrlen(szShareName) + 3 );
dst = GlobalLock ( hNewData );
wsprintf( dst, TEXT("\\\\%s\\%s"), szServerName, TEXT("NDDE$") );
dst += lstrlen(dst) + 1;
lstrcpy ( dst, szShareName );
*dst = SHR_CHAR;
lstrcat ( dst, TEXT(".dde") );
// lstrcat ( dst, TEXT(".ole") );
dst += lstrlen(dst) + 1;
src += lstrlen(src) + 1;
src += lstrlen(src) + 1;
lstrcpy ( dst, src );
GlobalUnlock ( hData );
GlobalUnlock ( hNewData );
SetClipboardData ( cf_link, hNewData );
SyncCloseClipboard();
}
if ( IsClipboardFormatAvailable ( cf_objectlink ) )
{
AddCopiedFormat ( cf_objectlink, cf_objectlinkcopy );
if (!SyncOpenClipboard(hwndServer))
return(FALSE);
dwNameLen = MAX_COMPUTERNAME_LENGTH+1;
GetComputerName(szServerName, &dwNameLen);
PINFO(TEXT("objectlink data found\n\r"));
hData = GetClipboardData ( cf_objectlink );
src = GlobalLock ( hData );
hNewData = GlobalAlloc ( GMEM_MOVEABLE | GMEM_ZEROINIT,
GlobalSize( hData )
+ lstrlen(szServerName) + lstrlen(szShareName) + 3 );
dst = GlobalLock ( hNewData );
wsprintf( dst, TEXT("\\\\%s\\%s"), szServerName, TEXT("NDDE$") );
dst += lstrlen(dst) + 1;
lstrcpy ( dst, szShareName );
*dst = SHR_CHAR;
lstrcat ( dst, TEXT(".ole") );
dst += lstrlen(dst) + 1;
src += lstrlen(src) + 1;
src += lstrlen(src) + 1;
lstrcpy ( dst, src );
GlobalUnlock ( hData );
GlobalUnlock ( hNewData );
SetClipboardData ( cf_objectlink, hNewData );
SyncCloseClipboard();
}
return TRUE;
}