Something went wrong. Try again.
Reactos
Something went wrong. Try again.
16 kB · 591 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592/* * PROJECT: ReactOS Clipboard Viewer * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: Clipboard file format helper functions. * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke * Copyright 2015-2018 Hermes Belusca-Maito */
#include "precomp.h"
static HGLOBAL ClipboardReadMemoryBlock(HANDLE hFile, DWORD dwOffset, DWORD dwLength){ HGLOBAL hData; LPVOID lpData; DWORD dwBytesRead;
hData = GlobalAlloc(GHND, dwLength); if (!hData) return NULL;
lpData = GlobalLock(hData); if (!lpData) { GlobalFree(hData); return NULL; }
if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { GlobalUnlock(hData); GlobalFree(hData); return NULL; }
if (!ReadFile(hFile, lpData, dwLength, &dwBytesRead, NULL)) { GlobalUnlock(hData); GlobalFree(hData); return NULL; }
GlobalUnlock(hData);
return hData;}
static BOOL ClipboardReadMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, DWORD dwLength, WORD FileIdentifier, PVOID lpFormatName){ HGLOBAL hData; DWORD dwTemp = 0;
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength); if (!hData) return FALSE;
if ((dwFormat >= 0xC000) && (dwFormat <= 0xFFFF)) { if (FileIdentifier == CLIP_FMT_31) dwTemp = RegisterClipboardFormatA((LPCSTR)lpFormatName); else if ((FileIdentifier == CLIP_FMT_NT) || (FileIdentifier == CLIP_FMT_BK)) dwTemp = RegisterClipboardFormatW((LPCWSTR)lpFormatName);
if (!dwTemp) { GlobalFree(hData); return FALSE; } } else { dwTemp = dwFormat; }
if (!SetClipboardData(dwTemp, hData)) { GlobalFree(hData); return FALSE; }
return TRUE;}
static BOOL ClipboardWriteMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, PDWORD pdwLength){ HGLOBAL hData; LPVOID lpData; DWORD dwBytesWritten;
hData = GetClipboardData(dwFormat); if (!hData) return FALSE;
lpData = GlobalLock(hData); if (!lpData) return FALSE;
*pdwLength = GlobalSize(hData);
if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { GlobalUnlock(hData); return FALSE; }
if (!WriteFile(hFile, lpData, *pdwLength, &dwBytesWritten, NULL)) { GlobalUnlock(hData); return FALSE; }
GlobalUnlock(hData);
return TRUE;}
static BOOL ClipboardReadPalette(HANDLE hFile, DWORD dwOffset, DWORD dwLength){ LPLOGPALETTE lpPalette; HPALETTE hPalette; HGLOBAL hData;
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength); if (!hData) { return FALSE; }
lpPalette = GlobalLock(hData); if (!lpPalette) { GlobalFree(hData); return FALSE; }
hPalette = CreatePalette(lpPalette); if (!hPalette) { GlobalUnlock(hData); GlobalFree(hData); SetLastError(ERROR_OUTOFMEMORY); return FALSE; }
GlobalUnlock(hData); GlobalFree(hData);
if (!SetClipboardData(CF_PALETTE, hPalette)) { DeleteObject(hPalette); return FALSE; }
return TRUE;}
static BOOL ClipboardReadMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength){ HMETAFILE hMf; HGLOBAL hData; LPVOID lpData;
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength); if (!hData) { return FALSE; }
lpData = GlobalLock(hData); if (!lpData) { GlobalFree(hData); return FALSE; }
hMf = SetMetaFileBitsEx(dwLength, lpData);
GlobalUnlock(hData); GlobalFree(hData);
if (!hMf) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; }
if (!SetClipboardData(CF_METAFILEPICT, hMf)) { DeleteMetaFile(hMf); return FALSE; }
return TRUE;}
static BOOL ClipboardReadEnhMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength){ HENHMETAFILE hEmf; HGLOBAL hData; LPVOID lpData;
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength); if (!hData) { return FALSE; }
lpData = GlobalLock(hData); if (!lpData) { GlobalFree(hData); return FALSE; }
hEmf = SetEnhMetaFileBits(dwLength, lpData);
GlobalUnlock(hData); GlobalFree(hData);
if (!hEmf) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; }
if (!SetClipboardData(CF_ENHMETAFILE, hEmf)) { DeleteEnhMetaFile(hEmf); return FALSE; }
return TRUE;}
static BOOL ClipboardReadBitmap(HANDLE hFile, DWORD dwOffset, DWORD dwLength){ HGLOBAL hData; HBITMAP hBitmap; LPBITMAP lpBitmap;
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength); if (!hData) { return FALSE; }
lpBitmap = GlobalLock(hData); if (!lpBitmap) { GlobalFree(hData); return FALSE; }
lpBitmap->bmBits = lpBitmap + sizeof(BITMAP) + 1;
hBitmap = CreateBitmapIndirect(lpBitmap);
GlobalUnlock(hData); GlobalFree(hData);
if (!hBitmap) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; }
if (!SetClipboardData(CF_BITMAP, hBitmap)) { DeleteObject(hBitmap); return FALSE; }
return TRUE;}
void ReadClipboardFile(LPCWSTR lpFileName){ CLIPFILEHEADER ClipFileHeader; CLIPFORMATHEADER ClipFormatArray; NTCLIPFILEHEADER NtClipFileHeader; NTCLIPFORMATHEADER NtClipFormatArray; PVOID pClipFileHeader; PVOID pClipFormatArray; DWORD SizeOfFileHeader, SizeOfFormatHeader;
WORD wFileIdentifier; WORD wFormatCount; DWORD dwFormatID; DWORD dwLenData; DWORD dwOffData; PVOID szName;
HANDLE hFile; DWORD dwBytesRead; BOOL bResult; int i;
/* Open the file for read access */ hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
/* Just read enough bytes to get the clipboard file format ID */ if (!ReadFile(hFile, &wFileIdentifier, sizeof(wFileIdentifier), &dwBytesRead, NULL)) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
/* Set data according to the clipboard file format ID */ switch (wFileIdentifier) { case CLIP_FMT_31: SizeOfFileHeader = sizeof(CLIPFILEHEADER); SizeOfFormatHeader = sizeof(CLIPFORMATHEADER); pClipFileHeader = &ClipFileHeader; pClipFormatArray = &ClipFormatArray; break;
case CLIP_FMT_NT: case CLIP_FMT_BK: SizeOfFileHeader = sizeof(NTCLIPFILEHEADER); SizeOfFormatHeader = sizeof(NTCLIPFORMATHEADER); pClipFileHeader = &NtClipFileHeader; pClipFormatArray = &NtClipFormatArray; break;
default: MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK); goto done; }
/* Completely read the header */ SetFilePointer(hFile, 0, NULL, FILE_BEGIN); if (!ReadFile(hFile, pClipFileHeader, SizeOfFileHeader, &dwBytesRead, NULL) || dwBytesRead != SizeOfFileHeader) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
/* Get header data */ switch (wFileIdentifier) { case CLIP_FMT_31: assert(wFileIdentifier == ((CLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier); wFormatCount = ((CLIPFILEHEADER*)pClipFileHeader)->wFormatCount; break;
case CLIP_FMT_NT: case CLIP_FMT_BK: assert(wFileIdentifier == ((NTCLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier); wFormatCount = ((NTCLIPFILEHEADER*)pClipFileHeader)->wFormatCount; break; }
/* Loop through the format data array */ for (i = 0; i < wFormatCount; i++) { if (SetFilePointer(hFile, SizeOfFileHeader + i * SizeOfFormatHeader, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
if (!ReadFile(hFile, pClipFormatArray, SizeOfFormatHeader, &dwBytesRead, NULL)) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
/* Get format data */ switch (wFileIdentifier) { case CLIP_FMT_31: dwFormatID = ((CLIPFORMATHEADER*)pClipFormatArray)->dwFormatID; dwLenData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwLenData; dwOffData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwOffData; szName = ((CLIPFORMATHEADER*)pClipFormatArray)->szName; break;
case CLIP_FMT_NT: case CLIP_FMT_BK: dwFormatID = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwFormatID; dwLenData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwLenData; dwOffData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwOffData; szName = ((NTCLIPFORMATHEADER*)pClipFormatArray)->szName; break; }
switch (dwFormatID) { case CF_OWNERDISPLAY: { break; }
case CF_DSPBITMAP: case CF_BITMAP: { bResult = ClipboardReadBitmap(hFile, dwOffData, dwLenData); break; }
case CF_DSPMETAFILEPICT: case CF_METAFILEPICT: { bResult = ClipboardReadMetafile(hFile, dwOffData, dwLenData); break; }
case CF_DSPENHMETAFILE: case CF_ENHMETAFILE: { bResult = ClipboardReadEnhMetafile(hFile, dwOffData, dwLenData); break; }
case CF_PALETTE: { bResult = ClipboardReadPalette(hFile, dwOffData, dwLenData); break; }
default: { if ((dwFormatID < CF_PRIVATEFIRST) || (dwFormatID > CF_PRIVATELAST)) { bResult = ClipboardReadMemory(hFile, dwFormatID, dwOffData, dwLenData, wFileIdentifier, szName); } break; } }
if (!bResult) ShowLastWin32Error(Globals.hMainWnd); }
done: if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
return;}
void WriteClipboardFile(LPCWSTR lpFileName, WORD wFileIdentifier){ CLIPFILEHEADER ClipFileHeader; CLIPFORMATHEADER ClipFormatArray; NTCLIPFILEHEADER NtClipFileHeader; NTCLIPFORMATHEADER NtClipFormatArray; PVOID pClipFileHeader; PVOID pClipFormatArray; DWORD SizeOfFileHeader, SizeOfFormatHeader;
WORD wFormatCount; DWORD dwFormatID; DWORD dwLenData; DWORD dwOffData; // PVOID szName;
HANDLE hFile; DWORD dwBytesWritten; int i;
/* Create the file for write access */ hFile = CreateFileW(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
wFormatCount = CountClipboardFormats();
/* Select the file format and setup the header according to the clipboard file format ID */ switch (wFileIdentifier) { case CLIP_FMT_31: SizeOfFileHeader = sizeof(CLIPFILEHEADER); SizeOfFormatHeader = sizeof(CLIPFORMATHEADER); pClipFileHeader = &ClipFileHeader; pClipFormatArray = &ClipFormatArray;
ClipFileHeader.wFileIdentifier = CLIP_FMT_31; // wFileIdentifier ClipFileHeader.wFormatCount = wFormatCount; break;
case CLIP_FMT_NT: case CLIP_FMT_BK: SizeOfFileHeader = sizeof(NTCLIPFILEHEADER); SizeOfFormatHeader = sizeof(NTCLIPFORMATHEADER); pClipFileHeader = &NtClipFileHeader; pClipFormatArray = &NtClipFormatArray;
NtClipFileHeader.wFileIdentifier = CLIP_FMT_NT; // wFileIdentifier NtClipFileHeader.wFormatCount = wFormatCount; break;
default: MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK); goto done; }
/* Write the header */ SetFilePointer(hFile, 0, NULL, FILE_BEGIN); if (!WriteFile(hFile, pClipFileHeader, SizeOfFileHeader, &dwBytesWritten, NULL) || dwBytesWritten != SizeOfFileHeader) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
/* Compute where the data should start (after the file header and the format array) */ dwOffData = SizeOfFileHeader + wFormatCount * SizeOfFormatHeader;
/* Loop through each format and save the data */ i = 0; dwFormatID = EnumClipboardFormats(0); while (dwFormatID) { if (i >= wFormatCount) { /* Must never happen! */ assert(FALSE); break; }
/* Write the clipboard data at the specified offset, and retrieve its length */ if (!ClipboardWriteMemory(hFile, dwFormatID, dwOffData, &dwLenData)) goto Cont;
/* Write the format data header */ switch (wFileIdentifier) { case CLIP_FMT_31: ZeroMemory(pClipFormatArray, sizeof(CLIPFORMATHEADER)); ((CLIPFORMATHEADER*)pClipFormatArray)->dwFormatID = dwFormatID; ((CLIPFORMATHEADER*)pClipFormatArray)->dwLenData = dwLenData; ((CLIPFORMATHEADER*)pClipFormatArray)->dwOffData = dwOffData; RetrieveClipboardFormatName(Globals.hInstance, dwFormatID, FALSE, ((CLIPFORMATHEADER*)pClipFormatArray)->szName, ARRAYSIZE(((CLIPFORMATHEADER*)pClipFormatArray)->szName)); break;
case CLIP_FMT_NT: case CLIP_FMT_BK: ZeroMemory(pClipFormatArray, sizeof(NTCLIPFORMATHEADER)); ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwFormatID = dwFormatID; ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwLenData = dwLenData; ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwOffData = dwOffData; RetrieveClipboardFormatName(Globals.hInstance, dwFormatID, TRUE, ((NTCLIPFORMATHEADER*)pClipFormatArray)->szName, ARRAYSIZE(((NTCLIPFORMATHEADER*)pClipFormatArray)->szName)); break; }
if (SetFilePointer(hFile, SizeOfFileHeader + i * SizeOfFormatHeader, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
if (!WriteFile(hFile, pClipFormatArray, SizeOfFormatHeader, &dwBytesWritten, NULL)) { ShowLastWin32Error(Globals.hMainWnd); goto done; }
/* Adjust the offset for the next data stream */ dwOffData += dwLenData;
Cont: i++; dwFormatID = EnumClipboardFormats(dwFormatID); }
done: if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
return;}