[CLIPBRD]
[reactos.git] / reactos / base / applications / clipbrd / fileutils.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Clipboard Viewer
4 * FILE: base/applications/clipbrd/fileutils.c
5 * PURPOSE: Clipboard file format helper functions.
6 * PROGRAMMERS: Ricardo Hanke
7 */
8
9 #include "precomp.h"
10
11 static HGLOBAL ClipboardReadMemoryBlock(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
12 {
13 HGLOBAL hData;
14 LPVOID lpData;
15 DWORD dwBytesRead;
16
17 hData = GlobalAlloc(GHND, dwLength);
18 if (!hData)
19 {
20 return NULL;
21 }
22
23 lpData = GlobalLock(hData);
24 if (!lpData)
25 {
26 GlobalFree(hData);
27 return NULL;
28 }
29
30 if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
31 {
32 GlobalUnlock(hData);
33 GlobalFree(hData);
34 return NULL;
35 }
36
37 if (!ReadFile(hFile, lpData, dwLength, &dwBytesRead, NULL))
38 {
39 GlobalUnlock(hData);
40 GlobalFree(hData);
41 return NULL;
42 }
43
44 GlobalUnlock(hData);
45
46 return hData;
47 }
48
49 static BOOL ClipboardReadMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, DWORD dwLength, LPCWSTR lpFormatName)
50 {
51 HGLOBAL hData;
52 DWORD dwTemp;
53
54 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
55 if (!hData)
56 {
57 return FALSE;
58 }
59
60 if ((dwFormat >= 0xC000) && (dwFormat <= 0xFFFF))
61 {
62 dwTemp = RegisterClipboardFormatW(lpFormatName);
63 if (!dwTemp)
64 {
65 GlobalFree(hData);
66 return FALSE;
67 }
68 }
69 else
70 {
71 dwTemp = dwFormat;
72 }
73
74 if (!SetClipboardData(dwTemp, hData))
75 {
76 GlobalFree(hData);
77 return FALSE;
78 }
79
80 return TRUE;
81 }
82
83 static BOOL ClipboardReadPalette(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
84 {
85 LPLOGPALETTE lpPalette;
86 HPALETTE hPalette;
87 HGLOBAL hData;
88
89 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
90 if (!hData)
91 {
92 return FALSE;
93 }
94
95 lpPalette = GlobalLock(hData);
96 if (!lpPalette)
97 {
98 GlobalFree(hData);
99 return FALSE;
100 }
101
102 hPalette = CreatePalette(lpPalette);
103 if (!hPalette)
104 {
105 GlobalUnlock(hData);
106 GlobalFree(hData);
107 SetLastError(ERROR_OUTOFMEMORY);
108 return FALSE;
109 }
110
111 GlobalUnlock(hData);
112 GlobalFree(hData);
113
114 if (!SetClipboardData(CF_PALETTE, hPalette))
115 {
116 DeleteObject(hPalette);
117 return FALSE;
118 }
119
120 return TRUE;
121 }
122
123 static BOOL ClipboardReadEnhMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
124 {
125 HENHMETAFILE hEmf;
126 HGLOBAL hData;
127 LPVOID lpData;
128
129 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
130 if (!hData)
131 {
132 return FALSE;
133 }
134
135 lpData = GlobalLock(hData);
136 if (!lpData)
137 {
138 GlobalFree(hData);
139 return FALSE;
140 }
141
142 hEmf = SetEnhMetaFileBits(dwLength, lpData);
143
144 GlobalUnlock(hData);
145 GlobalFree(hData);
146
147 if (!hEmf)
148 {
149 SetLastError(ERROR_OUTOFMEMORY);
150 return FALSE;
151 }
152
153 if (!SetClipboardData(CF_ENHMETAFILE, hEmf))
154 {
155 DeleteEnhMetaFile(hEmf);
156 return FALSE;
157 }
158
159 return TRUE;
160 }
161
162 static BOOL ClipboardReadBitmap(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
163 {
164 HGLOBAL hData;
165 HBITMAP hBitmap;
166 LPBITMAP lpBitmap;
167
168 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
169 if (!hData)
170 {
171 return FALSE;
172 }
173
174 lpBitmap = GlobalLock(hData);
175 if (!lpBitmap)
176 {
177 GlobalFree(hData);
178 return FALSE;
179 }
180
181 lpBitmap->bmBits = lpBitmap + sizeof(BITMAP) + 1;
182
183 hBitmap = CreateBitmapIndirect(lpBitmap);
184
185 GlobalUnlock(hData);
186 GlobalFree(hData);
187
188 if (!hBitmap)
189 {
190 SetLastError(ERROR_OUTOFMEMORY);
191 return FALSE;
192 }
193
194 if (!SetClipboardData(CF_BITMAP, hBitmap))
195 {
196 DeleteObject(hBitmap);
197 return FALSE;
198 }
199
200 return TRUE;
201 }
202
203 void ReadClipboardFile(LPCWSTR lpFileName)
204 {
205 CLIPBOARDFILEHEADER cfhFileHeader;
206 CLIPBOARDFORMATHEADER *cfhFormatArray = NULL;
207 HANDLE hFile;
208 DWORD dwBytesRead;
209 BOOL bResult;
210 int i;
211
212 hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
213 if (hFile == INVALID_HANDLE_VALUE)
214 {
215 ShowLastWin32Error(Globals.hMainWnd);
216 goto done;
217 }
218
219 if (!ReadFile(hFile, &cfhFileHeader, sizeof(cfhFileHeader), &dwBytesRead, NULL))
220 {
221 ShowLastWin32Error(Globals.hMainWnd);
222 goto done;
223 }
224
225 if ((cfhFileHeader.wFileIdentifier != CLIPBOARD_FORMAT_NT) && (cfhFileHeader.wFileIdentifier != CLIPBOARD_FORMAT_BK))
226 {
227 MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK);
228 goto done;
229 }
230
231 cfhFormatArray = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cfhFileHeader.wFormatCount * sizeof(CLIPBOARDFORMATHEADER));
232 if (!cfhFormatArray)
233 {
234 SetLastError(ERROR_OUTOFMEMORY);
235 ShowLastWin32Error(Globals.hMainWnd);
236 goto done;
237 }
238
239 if (!ReadFile(hFile, cfhFormatArray, cfhFileHeader.wFormatCount * sizeof(CLIPBOARDFORMATHEADER), &dwBytesRead, NULL))
240 {
241 ShowLastWin32Error(Globals.hMainWnd);
242 goto done;
243 }
244
245 for (i = 0; i < cfhFileHeader.wFormatCount; i++)
246 {
247 switch (cfhFormatArray[i].dwFormatID)
248 {
249 case CF_OWNERDISPLAY:
250 case CF_DSPMETAFILEPICT:
251 case CF_METAFILEPICT:
252 {
253 break;
254 }
255
256 case CF_BITMAP:
257 case CF_DSPBITMAP:
258 {
259 bResult = ClipboardReadBitmap(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData);
260 break;
261 }
262
263 case CF_DSPENHMETAFILE:
264 case CF_ENHMETAFILE:
265 {
266 bResult = ClipboardReadEnhMetafile(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData);
267 break;
268 }
269
270 case CF_PALETTE:
271 {
272 bResult = ClipboardReadPalette(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData);
273 break;
274 }
275
276 default:
277 {
278 if ((cfhFormatArray[i].dwFormatID < CF_PRIVATEFIRST) || (cfhFormatArray[i].dwFormatID > CF_PRIVATELAST))
279 {
280 bResult = ClipboardReadMemory(hFile, cfhFormatArray[i].dwFormatID, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData, cfhFormatArray[i].szName);
281 }
282 break;
283 }
284 }
285
286 if (!bResult)
287 {
288 ShowLastWin32Error(Globals.hMainWnd);
289 }
290 }
291
292 done:
293 if (hFile != INVALID_HANDLE_VALUE)
294 {
295 CloseHandle(hFile);
296 }
297
298 if (cfhFormatArray)
299 {
300 HeapFree(GetProcessHeap(), 0, cfhFormatArray);
301 }
302
303 return;
304 }
305
306 void WriteClipboardFile(LPCWSTR lpFileName)
307 {
308 MessageBoxW(Globals.hMainWnd, L"This function is currently not implemented.", L"Clipboard", MB_OK | MB_ICONINFORMATION);
309 return;
310 }