From d06631bfb27bf6291b79c613a261ed5bb9f6f2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 28 Nov 2015 01:22:34 +0000 Subject: [PATCH] [CLIPBRD] Implement loading the clipboard contents from a file. By Ricardo Hanke :) CORE-10550 svn path=/trunk/; revision=70173 --- reactos/base/applications/clipbrd/clipbrd.c | 8 +- reactos/base/applications/clipbrd/cliputils.c | 2 +- reactos/base/applications/clipbrd/fileutils.c | 291 +++++++++++++++++- .../base/applications/clipbrd/lang/de-DE.rc | 1 + .../base/applications/clipbrd/lang/en-US.rc | 1 + .../base/applications/clipbrd/lang/fr-FR.rc | 1 + reactos/base/applications/clipbrd/resources.h | 3 +- 7 files changed, 300 insertions(+), 7 deletions(-) diff --git a/reactos/base/applications/clipbrd/clipbrd.c b/reactos/base/applications/clipbrd/clipbrd.c index e86ce26aae2..12a9d62c027 100644 --- a/reactos/base/applications/clipbrd/clipbrd.c +++ b/reactos/base/applications/clipbrd/clipbrd.c @@ -37,7 +37,7 @@ static void SaveClipboardToFile(void) if (!GetSaveFileNameW(&sfn)) return; - if (!OpenClipboard(NULL)) + if (!OpenClipboard(Globals.hMainWnd)) { ShowLastWin32Error(Globals.hMainWnd); return; @@ -72,7 +72,7 @@ static void LoadClipboardFromFile(void) if (!GetOpenFileNameW(&ofn)) return; - if (!OpenClipboard(NULL)) + if (!OpenClipboard(Globals.hMainWnd)) { ShowLastWin32Error(Globals.hMainWnd); return; @@ -94,7 +94,7 @@ static void LoadClipboardFromDrop(HDROP hDrop) DragQueryFileW(hDrop, 0, szFileName, ARRAYSIZE(szFileName)); DragFinish(hDrop); - if (!OpenClipboard(NULL)) + if (!OpenClipboard(Globals.hMainWnd)) { ShowLastWin32Error(Globals.hMainWnd); return; @@ -163,7 +163,7 @@ void UpdateDisplayMenu(void) if (CountClipboardFormats() == 0) return; - if (!OpenClipboard(NULL)) + if (!OpenClipboard(Globals.hMainWnd)) return; AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL); diff --git a/reactos/base/applications/clipbrd/cliputils.c b/reactos/base/applications/clipbrd/cliputils.c index a6a20a15b16..006fee7c5cb 100644 --- a/reactos/base/applications/clipbrd/cliputils.c +++ b/reactos/base/applications/clipbrd/cliputils.c @@ -97,7 +97,7 @@ void RetrieveClipboardFormatName(HINSTANCE hInstance, UINT uFormat, LPWSTR lpszF void DeleteClipboardContent(void) { - if (!OpenClipboard(NULL)) + if (!OpenClipboard(Globals.hMainWnd)) { ShowLastWin32Error(Globals.hMainWnd); return; diff --git a/reactos/base/applications/clipbrd/fileutils.c b/reactos/base/applications/clipbrd/fileutils.c index 0ac45868869..dd0cc967cc1 100644 --- a/reactos/base/applications/clipbrd/fileutils.c +++ b/reactos/base/applications/clipbrd/fileutils.c @@ -8,9 +8,298 @@ #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, LPCWSTR lpFormatName) +{ + HGLOBAL hData; + DWORD dwTemp; + + hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength); + if (!hData) + { + return FALSE; + } + + if ((dwFormat >= 0xC000) && (dwFormat <= 0xFFFF)) + { + dwTemp = RegisterClipboardFormatW(lpFormatName); + if (!dwTemp) + { + GlobalFree(hData); + return FALSE; + } + } + else + { + dwTemp = dwFormat; + } + + if (!SetClipboardData(dwTemp, hData)) + { + GlobalFree(hData); + return FALSE; + } + + 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 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) { - MessageBoxW(Globals.hMainWnd, L"This function is currently not implemented.", L"Clipboard", MB_OK | MB_ICONINFORMATION); + CLIPBOARDFILEHEADER cfhFileHeader; + CLIPBOARDFORMATHEADER *cfhFormatArray = NULL; + HANDLE hFile; + DWORD dwBytesRead; + BOOL bResult; + int i; + + hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + ShowLastWin32Error(Globals.hMainWnd); + goto done; + } + + if (!ReadFile(hFile, &cfhFileHeader, sizeof(cfhFileHeader), &dwBytesRead, NULL)) + { + ShowLastWin32Error(Globals.hMainWnd); + goto done; + } + + if ((cfhFileHeader.wFileIdentifier != CLIPBOARD_FORMAT_NT) && (cfhFileHeader.wFileIdentifier != CLIPBOARD_FORMAT_BK)) + { + MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK); + goto done; + } + + cfhFormatArray = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cfhFileHeader.wFormatCount * sizeof(CLIPBOARDFORMATHEADER)); + if (!cfhFormatArray) + { + SetLastError(ERROR_OUTOFMEMORY); + ShowLastWin32Error(Globals.hMainWnd); + goto done; + } + + if (!ReadFile(hFile, cfhFormatArray, cfhFileHeader.wFormatCount * sizeof(CLIPBOARDFORMATHEADER), &dwBytesRead, NULL)) + { + ShowLastWin32Error(Globals.hMainWnd); + goto done; + } + + for (i = 0; i < cfhFileHeader.wFormatCount; i++) + { + switch (cfhFormatArray[i].dwFormatID) + { + case CF_OWNERDISPLAY: + case CF_DSPMETAFILEPICT: + case CF_METAFILEPICT: + { + break; + } + + case CF_BITMAP: + case CF_DSPBITMAP: + { + bResult = ClipboardReadBitmap(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData); + break; + } + + case CF_DSPENHMETAFILE: + case CF_ENHMETAFILE: + { + bResult = ClipboardReadEnhMetafile(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData); + break; + } + + case CF_PALETTE: + { + bResult = ClipboardReadPalette(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData); + break; + } + + default: + { + if ((cfhFormatArray[i].dwFormatID < CF_PRIVATEFIRST) || (cfhFormatArray[i].dwFormatID > CF_PRIVATELAST)) + { + bResult = ClipboardReadMemory(hFile, cfhFormatArray[i].dwFormatID, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData, cfhFormatArray[i].szName); + } + break; + } + } + + if (!bResult) + { + ShowLastWin32Error(Globals.hMainWnd); + } + } + +done: + if (hFile != INVALID_HANDLE_VALUE) + { + CloseHandle(hFile); + } + + if (cfhFormatArray) + { + HeapFree(GetProcessHeap(), 0, cfhFormatArray); + } + return; } diff --git a/reactos/base/applications/clipbrd/lang/de-DE.rc b/reactos/base/applications/clipbrd/lang/de-DE.rc index b6a81608364..29d4c46d30c 100644 --- a/reactos/base/applications/clipbrd/lang/de-DE.rc +++ b/reactos/base/applications/clipbrd/lang/de-DE.rc @@ -60,4 +60,5 @@ END STRINGTABLE BEGIN ERROR_UNSUPPORTED_FORMAT "Die Daten in der Zwischenablage liegen in einem Format vor, welches nicht angezeigt werden kann." + ERROR_INVALID_FILE_FORMAT "Die ausgewählte Datei ist keine gültige Zwischenablagedatei." END diff --git a/reactos/base/applications/clipbrd/lang/en-US.rc b/reactos/base/applications/clipbrd/lang/en-US.rc index f648c066541..1ad8fb57c46 100644 --- a/reactos/base/applications/clipbrd/lang/en-US.rc +++ b/reactos/base/applications/clipbrd/lang/en-US.rc @@ -60,4 +60,5 @@ END STRINGTABLE BEGIN ERROR_UNSUPPORTED_FORMAT "The Clipboard contains data in a format, that cannot be displayed." + ERROR_INVALID_FILE_FORMAT "The selected file is not a valid clipboard file." END diff --git a/reactos/base/applications/clipbrd/lang/fr-FR.rc b/reactos/base/applications/clipbrd/lang/fr-FR.rc index 45513fc7b2c..4ae69fb1bf8 100644 --- a/reactos/base/applications/clipbrd/lang/fr-FR.rc +++ b/reactos/base/applications/clipbrd/lang/fr-FR.rc @@ -60,4 +60,5 @@ END STRINGTABLE BEGIN ERROR_UNSUPPORTED_FORMAT "Le Presse-papiers contient des données dans un format qui ne peut être affiché." + ERROR_INVALID_FILE_FORMAT "Le fichier sélectionné n'est pas un fichier valide du presse-papiers." END diff --git a/reactos/base/applications/clipbrd/resources.h b/reactos/base/applications/clipbrd/resources.h index 49f4a52df8d..f85336e22a4 100644 --- a/reactos/base/applications/clipbrd/resources.h +++ b/reactos/base/applications/clipbrd/resources.h @@ -34,4 +34,5 @@ #define STRING_CF_DIF 212 #define STRING_CF_HDROP 213 -#define ERROR_UNSUPPORTED_FORMAT 300 +#define ERROR_UNSUPPORTED_FORMAT 300 +#define ERROR_INVALID_FILE_FORMAT 301