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.
 
 
 
 
 
 

1608 lines
44 KiB

/*****************************************************************************
C L I P F I L E
Name: clipfile.c
Date: 19-Apr-1994
Creator: Unknown
Description:
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 <windows.h>
#include <windowsx.h>
#include <string.h>
#include <strsafe.h>
#include "common.h"
#include "clipfile.h"
#include "clipfile.h"
#include "dib.h"
#include "debugout.h"
#include "render.h"
#include "security.h"
#define ARRAYSIZE(a) (sizeof(a)/sizeof((a)[0]))
BOOL fAnythingToRender;
TCHAR szFileSpecifier[] = TEXT("*.CLP");
TCHAR szFileName[MAX_PATH+1];
TCHAR szSaveFileName[MAX_PATH+1]; // Saved filename for delayed render
BOOL fNTReadFileFormat;
BOOL fNTSaveFileFormat;
UINT cf_link;
UINT cf_objectlink;
UINT cf_linkcopy;
UINT cf_objectlinkcopy;
BOOL AddDIBtoDDB(VOID);
/*******************
File read routines
*******************/
/*
* ReadFileHeader
*
* 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);
}
/*
* ReadFormatHeader
*/
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.
*
* Return Value: READFILE_IMPROPERFORMAT
* READFILE_OPENCLIPBRDFAIL
* READFILE_SUCCESS
*/
short ReadClipboardFromFile(
HWND hwnd,
HANDLE fh)
{
register unsigned i;
unsigned cFormats;
FORMATHEADER FormatHeader;
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);
if (FormatHeader.FormatID == CF_DIB)
SetClipboardData (CF_BITMAP, NULL);
}
/* Now, clipbrd viewer has something to render */
if (cFormats > 0)
{
PINFO(TEXT("fAnythingToRender = TRUE\r\n"));
fAnythingToRender = TRUE;
}
SyncCloseClipboard();
return(READFILE_SUCCESS);
}
/*
* OpenClipboardFile
*/
DWORD OpenClipboardFile(
HWND hwnd,
LPTSTR szName)
{
HANDLE fh;
DWORD dwErr = NO_ERROR;
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.
StringCchCopy(szSaveFileName, MAX_PATH+1, szName);
// Read it.
switch (ReadClipboardFromFile (hwnd, fh))
{
case READFILE_IMPROPERFORMAT:
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
case READFILE_OPENCLIPBRDFAIL:
dwErr = ERROR_CLIPBOARD_NOT_OPEN;
break;
case READFILE_SUCCESS:
default:
dwErr = NO_ERROR;
break;
}
CloseHandle (fh);
}
else
{
PERROR(TEXT("ClSrv\\OpClpFile: can't open file!"));
dwErr = GetLastError ();
}
return dwErr;
}
/*
* RenderFormatFormFile
*
* Purpose: Go get the given format from the given file.
*/
HANDLE RenderFormatFromFile(
LPTSTR szFile,
WORD wFormat)
{
HANDLE fh;
FORMATHEADER FormatHeader;
HANDLE hData = NULL;
unsigned cFormats;
unsigned i;
BOOL bHasDib = FALSE;
PINFO(TEXT("ClpSrv\\RndrFmtFromFile: Opening file %s.\r\n"),szFile);
fh = CreateFile (szFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == fh)
{
PERROR(TEXT("Can't open file\r\n"));
goto done;
}
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"));
goto done;
}
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);
}
if (FormatHeader.FormatID == CF_DIB)
bHasDib = TRUE;
}
// make CF_BITMAP available when there's CF_DIB
if (!hData && wFormat == CF_BITMAP && bHasDib)
{
if (SetFilePointer (fh, 0, 0, FILE_BEGIN) == 0xFFFFFFFF)
{
PERROR(TEXT("Cannot set file pointer to FILE_BEGIN\n"));
goto done;
}
cFormats = ReadFileHeader (fh);
for (i=0; i < cFormats; i++)
{
ReadFormatHeader (fh, &FormatHeader, i);
PINFO (TEXT("Got format %ws\n"), FormatHeader.Name);
if (FormatHeader.FormatID == CF_DIB)
hData = RenderFormatDibToBitmap (&FormatHeader,
fh,
RenderFormatFromFile (szFile, CF_PALETTE));
}
}
done:
if (fh != INVALID_HANDLE_VALUE)
CloseHandle (fh);
return(hData);
}
/*
* RenderAllFromFile
*
* Purpose: Go get all formats from the given file.
*/
HANDLE RenderAllFromFile(
LPTSTR szFile)
{
HANDLE fh;
FORMATHEADER FormatHeader;
HANDLE hData;
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!
*/
if (CountClipboardFormats() && fAnythingToRender)
{
/* Empty the clipboard */
if (!SyncOpenClipboard(hwndApp))
{
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);
}
/*
* Count16BitClipboardFormats
*
* 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;
}
/*
* WriteFormatBlock
*
* 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;
StringCchCopyW(FormatHeader.Name, CCHFMTNAMEMAX, wszName);
WriteFile (fh, &FormatHeader, sizeof(FormatHeader), &dwBytesWritten, NULL);
}
else
{
OLDFORMATHEADER OldFormatHeader;
memset(&OldFormatHeader,0, sizeof(OldFormatHeader));
OldFormatHeader.FormatID = (WORD)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;
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"));
return 0;
}
/* 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. */
w31mfp.mm = (WORD)lpMFP->mm;
w31mfp.xExt = (WORD)lpMFP->xExt;
w31mfp.yExt = (WORD)lpMFP->yExt;
w31mfp.hMF = (WORD)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. */
Format = CF_DIB;
GetObject((HBITMAP)hData, sizeof(BITMAP), &bitmap);
if (hBitmap = DibFromBitmap ((HBITMAP)hData,
BI_RGB,
(WORD) (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 = (DWORD)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 = (DWORD)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);
}
/*
* GetClipboardNameW
*/
void GetClipboardNameW(
register int fmt,
LPWSTR wszName,
register int iSize)
{
LPWSTR lprgch = NULL;
HANDLE hrgch = NULL;
*wszName = '\0';
/* Get global memory that everyone can get to */
if (!(hrgch = GlobalAlloc(GMEM_MOVEABLE, (LONG)(iSize + 1)*sizeof(WCHAR))))
{
PERROR(TEXT("GetClipboardNameW: bad alloc\r\n"));
goto done;
}
if (!(lprgch = (LPWSTR)GlobalLock(hrgch)))
{
PERROR(TEXT("GetClipboardNameW: bad lock\r\n"));
goto done;
}
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:
case CF_UNICODETEXT:
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"));
LoadStringW(hInst, fmt, lprgch, iSize);
break;
default:
GetClipboardFormatNameW(fmt, lprgch, iSize);
break;
}
StringCchCopyW(wszName, iSize, lprgch);
done:
if (lprgch) GlobalUnlock(hrgch);
if (hrgch) GlobalFree(hrgch);
}
/*
* 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.
*
* Returns:
* NO_ERROR if no error otherwise an error code.
*/
DWORD SaveClipboardData(
HWND hwnd,
LPTSTR szFileName,
BOOL fPage)
{
register HANDLE fh;
register WORD Format;
SECURITY_ATTRIBUTES sa;
DWORD HeaderPos;
DWORD DataPos;
DWORD datasize;
HCURSOR hCursor;
FILEHEADER FileHeader;
WCHAR wszName[CCHFMTNAMEMAX];
UINT wHeaderSize;
UINT uiSizeHeaderToWrite;
BOOL fDIBUsed = FALSE;
DWORD dwTemp;
DWORD dwRet = NO_ERROR;
/* First open the clipboard */
if (!SyncOpenClipboard(hwndApp))
return ERROR_CLIPBOARD_NOT_OPEN;
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 (fh == INVALID_HANDLE_VALUE)
{
PERROR ("Error opening clipboard file!\r\n");
dwRet = GetLastError ();
goto done;
}
/* 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);
/* Enumerate all formats */
Format = 0;
while ((Format = (WORD)EnumClipboardFormats(Format)))
{
if (IsWriteable(Format))
{
// DO NOT write CF_BITMAP to disk. Transform to CF_DIB
// and write that instead.
// If there's CF_DIB, then don't do CF_BITMAP
if (CF_BITMAP == Format)
if (IsClipboardFormatAvailable (CF_DIB)
&& GetClipboardData (CF_DIB))
continue; // We have DIB, don't worry about BITMAP.
if (CF_BITMAP == Format || CF_DIB == Format)
{
if (!fDIBUsed)
fDIBUsed = TRUE;
else
// Already done DIB, go on to the next format.
continue;
}
GetClipboardNameW (Format == CF_BITMAP ? CF_DIB : Format,
wszName,
ARRAYSIZE(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"));
dwRet = ERROR_NOT_ENOUGH_MEMORY;
break;
}
HeaderPos += wHeaderSize;
/* Update the data pos for the next block */
DataPos += datasize;
FileHeader.FormatCount++; /* this format has been written */
}
}
}
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);
if (!WriteFile (fh, &FileHeader, sizeof(FileHeader), &dwTemp, NULL))
dwRet = GetLastError ();
/* 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 */
StringCchCopy(szSaveFileName, MAX_PATH+1, szFileName);
PINFO(TEXT("sAVEcLIPBOARDdATA: Copied name %s to name %s\r\n"), szSaveFileName, szFileName);
fNTReadFileFormat = fNTSaveFileFormat;
if (dwRet == NO_ERROR) //bRet)
{
switch (ReadClipboardFromFile (hwndApp, fh))
{
case READFILE_IMPROPERFORMAT:
dwRet = ERROR_NOT_ENOUGH_MEMORY;
break;
case READFILE_OPENCLIPBRDFAIL:
dwRet = ERROR_CLIPBOARD_NOT_OPEN;
break;
case READFILE_SUCCESS:
default:
dwRet = NO_ERROR;
break;
}
}
CloseHandle(fh);
if (dwRet != NO_ERROR)
{
PERROR(TEXT("SCD: Trouble in ReadClipboardFromFile\r\n"));
DeleteFile(szFileName);
}
done:
if (sa.lpSecurityDescriptor)
{
GlobalFree((HGLOBAL)sa.lpSecurityDescriptor);
}
SyncCloseClipboard();
return dwRet;
}
/*
* 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: NO_ERROR if no error occured otherwise an error code.
*
*/
DWORD SaveClipboardToFile(
HWND hwnd,
TCHAR *szShareName,
TCHAR *szFileName,
BOOL fPage)
{
DWORD dwErr = NO_ERROR;
PINFO(TEXT("\r\n Entering SaveClipboardToFile\r\n"));
if (fPage)
{
AddNetInfoToClipboard( szShareName );
AddPreviewFormat();
}
dwErr = SaveClipboardData(hwnd, szFileName, fPage);
if (dwErr != NO_ERROR)
{
/* If Failure, Delete the incomplete file */
PERROR(TEXT("SaveClipboardData failed!"));
DeleteFile(szSaveFileName);
}
return dwErr;
}
/*
* AddPreviewFormat
*/
BOOL AddPreviewFormat (VOID)
{
LPMETAFILEPICT lpMF;
HANDLE hClpData;
HANDLE hBmpData;
HBITMAP hBitmap;
HBITMAP hClpBmp;
HBITMAP hOldDstBmp;
HBITMAP hOldSrcBmp;
BITMAP Bitmap;
HDC hDC;
HDC hDstDC;
HDC hSrcDC;
LPBYTE lpBmp;
int ret = FALSE;
RECT rc;
int OldMode;
if (!IsClipboardFormatAvailable(CF_TEXT) &&
!IsClipboardFormatAvailable(CF_BITMAP) &&
!IsClipboardFormatAvailable(CF_METAFILEPICT) &&
!IsClipboardFormatAvailable(CF_ENHMETAFILE) &&
!IsClipboardFormatAvailable(CF_UNICODETEXT))
return FALSE;
if ( !SyncOpenClipboard(hwndApp))
return FALSE;
if ( !(hBmpData = GlobalAlloc ( GHND, 64 * 64 / 8 )) )
{
SyncCloseClipboard();
return FALSE;
}
hDC = GetDC ( hwndApp );
hDstDC = CreateCompatibleDC ( hDC );
hSrcDC = CreateCompatibleDC ( hDC );
ReleaseDC ( hwndApp, 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 )
PERROR(TEXT("GetBitmapBits failed\n\r"));
GlobalUnlock ( hBmpData );
SetClipboardData ( cf_preview, hBmpData );
ret = TRUE;
DeleteObject ( hBitmap );
SyncCloseClipboard();
return ret;
}
/*
* AddCopiedFormat
*/
BOOL AddCopiedFormat (
UINT ufmtOriginal,
UINT ufmtCopy)
{
LPBYTE lpOriginal;
LPBYTE lpCopy;
HANDLE hOriginal;
HANDLE hCopy = NULL;
BOOL ret = FALSE;
int i;
if (IsClipboardFormatAvailable(ufmtOriginal) && SyncOpenClipboard(hwndApp))
{
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;
}
/*
* AddNetInfoToClipboard
*/
BOOL AddNetInfoToClipboard (
TCHAR *szShareName )
{
HANDLE hData;
HANDLE hNewData;
TCHAR szServerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwNameLen;
LPTSTR src;
LPTSTR dst;
cf_link = RegisterClipboardFormat (SZLINK);
cf_linkcopy = RegisterClipboardFormat (SZLINKCOPY);
cf_objectlink = RegisterClipboardFormat (SZOBJECTLINK);
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;
}
if (IsClipboardFormatAvailable (cf_link))
{
AddCopiedFormat (cf_link, cf_linkcopy);
if (!SyncOpenClipboard (hwndApp))
return (FALSE);
dwNameLen = MAX_COMPUTERNAME_LENGTH+1;
GetComputerName (szServerName, &dwNameLen);
PINFO(TEXT("link data found\n\r"));
if (hData = GetClipboardData (cf_link))
{
if (src = GlobalLock (hData))
{
// approx 20 extra chars for the \\, \ndde$, .dde, and the 2 NULL chars
size_t Size = GlobalSize(hData) + lstrlen (szServerName) +lstrlen (szShareName) +20;
hNewData = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, Size);
dst = GlobalLock (hNewData);
StringCchPrintf (dst, Size, TEXT("\\\\%s\\%s"), szServerName, TEXT("NDDE$"));
Size -= (lstrlen(dst) + 1);
dst += lstrlen(dst) + 1;
StringCchCopy ( dst, Size, szShareName );
*dst = SHR_CHAR;
Size -= lstrlen(dst);
StringCchCat( dst, Size, TEXT(".dde") );
Size -= 5;
dst += lstrlen(dst) + 1;
src += lstrlen(src) + 1;
src += lstrlen(src) + 1;
StringCchCopy ( dst, Size, src );
GlobalUnlock (hData);
GlobalUnlock (hNewData);
SetClipboardData (cf_link, hNewData);
}
}
SyncCloseClipboard ();
}
if (IsClipboardFormatAvailable (cf_objectlink))
{
AddCopiedFormat (cf_objectlink, cf_objectlinkcopy);
if (!SyncOpenClipboard (hwndApp))
return (FALSE);
dwNameLen = MAX_COMPUTERNAME_LENGTH+1;
GetComputerName (szServerName, &dwNameLen);
PINFO(TEXT("objectlink data found\n\r"));
if (hData = GetClipboardData (cf_objectlink))
{
if (src = GlobalLock (hData))
{
// approx 20 extra chars for the \\, \ndde$, .dde, and the 2 NULL chars
size_t Size = GlobalSize(hData) +lstrlen (szServerName) +lstrlen (szShareName) +20;
hNewData = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, Size);
dst = GlobalLock (hNewData);
StringCchPrintf(dst, Size, TEXT("\\\\%s\\%s"), szServerName, TEXT("NDDE$"));
Size -= (lstrlen(dst) + 1);
dst += lstrlen(dst) + 1;
StringCchCopy (dst, Size, szShareName);
Size -= lstrlen(szShareName);
*dst = SHR_CHAR;
StringCchCat (dst, Size, TEXT(".ole"));
dst += lstrlen(dst) + 1;
Size -= 5;
src += lstrlen(src) + 1;
src += lstrlen(src) + 1;
StringCchCopy (dst, Size, src);
GlobalUnlock (hData);
GlobalUnlock (hNewData);
SetClipboardData (cf_objectlink, hNewData);
}
}
SyncCloseClipboard ();
}
return TRUE;
}