[CLIPBRD]: Complete the read support from .clp clipboard files to be actually able...
[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 * Hermes Belusca-Maito
8 */
9
10 #include "precomp.h"
11
12 static HGLOBAL ClipboardReadMemoryBlock(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
13 {
14 HGLOBAL hData;
15 LPVOID lpData;
16 DWORD dwBytesRead;
17
18 hData = GlobalAlloc(GHND, dwLength);
19 if (!hData)
20 return NULL;
21
22 lpData = GlobalLock(hData);
23 if (!lpData)
24 {
25 GlobalFree(hData);
26 return NULL;
27 }
28
29 if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
30 {
31 GlobalUnlock(hData);
32 GlobalFree(hData);
33 return NULL;
34 }
35
36 if (!ReadFile(hFile, lpData, dwLength, &dwBytesRead, NULL))
37 {
38 GlobalUnlock(hData);
39 GlobalFree(hData);
40 return NULL;
41 }
42
43 GlobalUnlock(hData);
44
45 return hData;
46 }
47
48 static BOOL ClipboardReadMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, DWORD dwLength, WORD FileIdentifier, PVOID lpFormatName)
49 {
50 HGLOBAL hData;
51 DWORD dwTemp;
52
53 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
54 if (!hData)
55 return FALSE;
56
57 if ((dwFormat >= 0xC000) && (dwFormat <= 0xFFFF))
58 {
59 if (FileIdentifier == CLIP_FMT_31)
60 dwTemp = RegisterClipboardFormatA((LPCSTR)lpFormatName);
61 else if ((FileIdentifier == CLIP_FMT_NT) || (FileIdentifier == CLIP_FMT_BK))
62 dwTemp = RegisterClipboardFormatW((LPCWSTR)lpFormatName);
63
64 if (!dwTemp)
65 {
66 GlobalFree(hData);
67 return FALSE;
68 }
69 }
70 else
71 {
72 dwTemp = dwFormat;
73 }
74
75 if (!SetClipboardData(dwTemp, hData))
76 {
77 GlobalFree(hData);
78 return FALSE;
79 }
80
81 return TRUE;
82 }
83
84 static BOOL ClipboardReadPalette(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
85 {
86 LPLOGPALETTE lpPalette;
87 HPALETTE hPalette;
88 HGLOBAL hData;
89
90 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
91 if (!hData)
92 {
93 return FALSE;
94 }
95
96 lpPalette = GlobalLock(hData);
97 if (!lpPalette)
98 {
99 GlobalFree(hData);
100 return FALSE;
101 }
102
103 hPalette = CreatePalette(lpPalette);
104 if (!hPalette)
105 {
106 GlobalUnlock(hData);
107 GlobalFree(hData);
108 SetLastError(ERROR_OUTOFMEMORY);
109 return FALSE;
110 }
111
112 GlobalUnlock(hData);
113 GlobalFree(hData);
114
115 if (!SetClipboardData(CF_PALETTE, hPalette))
116 {
117 DeleteObject(hPalette);
118 return FALSE;
119 }
120
121 return TRUE;
122 }
123
124 static BOOL ClipboardReadMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
125 {
126 HMETAFILE hMf;
127 HGLOBAL hData;
128 LPVOID lpData;
129
130 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
131 if (!hData)
132 {
133 return FALSE;
134 }
135
136 lpData = GlobalLock(hData);
137 if (!lpData)
138 {
139 GlobalFree(hData);
140 return FALSE;
141 }
142
143 hMf = SetMetaFileBitsEx(dwLength, lpData);
144
145 GlobalUnlock(hData);
146 GlobalFree(hData);
147
148 if (!hMf)
149 {
150 SetLastError(ERROR_OUTOFMEMORY);
151 return FALSE;
152 }
153
154 if (!SetClipboardData(CF_METAFILEPICT, hMf))
155 {
156 DeleteMetaFile(hMf);
157 return FALSE;
158 }
159
160 return TRUE;
161 }
162
163 static BOOL ClipboardReadEnhMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
164 {
165 HENHMETAFILE hEmf;
166 HGLOBAL hData;
167 LPVOID lpData;
168
169 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
170 if (!hData)
171 {
172 return FALSE;
173 }
174
175 lpData = GlobalLock(hData);
176 if (!lpData)
177 {
178 GlobalFree(hData);
179 return FALSE;
180 }
181
182 hEmf = SetEnhMetaFileBits(dwLength, lpData);
183
184 GlobalUnlock(hData);
185 GlobalFree(hData);
186
187 if (!hEmf)
188 {
189 SetLastError(ERROR_OUTOFMEMORY);
190 return FALSE;
191 }
192
193 if (!SetClipboardData(CF_ENHMETAFILE, hEmf))
194 {
195 DeleteEnhMetaFile(hEmf);
196 return FALSE;
197 }
198
199 return TRUE;
200 }
201
202 static BOOL ClipboardReadBitmap(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
203 {
204 HGLOBAL hData;
205 HBITMAP hBitmap;
206 LPBITMAP lpBitmap;
207
208 hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
209 if (!hData)
210 {
211 return FALSE;
212 }
213
214 lpBitmap = GlobalLock(hData);
215 if (!lpBitmap)
216 {
217 GlobalFree(hData);
218 return FALSE;
219 }
220
221 lpBitmap->bmBits = lpBitmap + sizeof(BITMAP) + 1;
222
223 hBitmap = CreateBitmapIndirect(lpBitmap);
224
225 GlobalUnlock(hData);
226 GlobalFree(hData);
227
228 if (!hBitmap)
229 {
230 SetLastError(ERROR_OUTOFMEMORY);
231 return FALSE;
232 }
233
234 if (!SetClipboardData(CF_BITMAP, hBitmap))
235 {
236 DeleteObject(hBitmap);
237 return FALSE;
238 }
239
240 return TRUE;
241 }
242
243 void ReadClipboardFile(LPCWSTR lpFileName)
244 {
245 CLIPFILEHEADER ClipFileHeader;
246 CLIPFORMATHEADER ClipFormatArray;
247 NTCLIPFILEHEADER NtClipFileHeader;
248 NTCLIPFORMATHEADER NtClipFormatArray;
249 PVOID pClipFileHeader;
250 PVOID pClipFormatArray;
251 DWORD SizeOfFileHeader, SizeOfFormatHeader;
252
253 WORD wFileIdentifier;
254 WORD wFormatCount;
255 DWORD dwFormatID;
256 DWORD dwLenData;
257 DWORD dwOffData;
258 PVOID szName;
259
260 HANDLE hFile;
261 DWORD dwBytesRead;
262 BOOL bResult;
263 int i;
264
265 /* Open the file */
266 hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
267 if (hFile == INVALID_HANDLE_VALUE)
268 {
269 ShowLastWin32Error(Globals.hMainWnd);
270 goto done;
271 }
272
273 /* Just read enough bytes to get the clipboard file format ID */
274 if (!ReadFile(hFile, &wFileIdentifier, sizeof(wFileIdentifier), &dwBytesRead, NULL))
275 {
276 ShowLastWin32Error(Globals.hMainWnd);
277 goto done;
278 }
279 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
280
281 /* Set data according to the clipboard file format ID */
282 switch (wFileIdentifier)
283 {
284 case CLIP_FMT_31:
285 SizeOfFileHeader = sizeof(CLIPFILEHEADER);
286 SizeOfFormatHeader = sizeof(CLIPFORMATHEADER);
287 pClipFileHeader = &ClipFileHeader;
288 pClipFormatArray = &ClipFormatArray;
289 MessageBox(Globals.hMainWnd, L"We have a Win3.11 clipboard file!", L"File format", 0);
290 break;
291
292 case CLIP_FMT_NT:
293 case CLIP_FMT_BK:
294 SizeOfFileHeader = sizeof(NTCLIPFILEHEADER);
295 SizeOfFormatHeader = sizeof(NTCLIPFORMATHEADER);
296 pClipFileHeader = &NtClipFileHeader;
297 pClipFormatArray = &NtClipFormatArray;
298 MessageBox(Globals.hMainWnd, L"We have a WinNT clipboard file!", L"File format", 0);
299 break;
300
301 default:
302 MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK);
303 goto done;
304 }
305
306 /* Completely read the header */
307 if (!ReadFile(hFile, pClipFileHeader, SizeOfFileHeader, &dwBytesRead, NULL) ||
308 dwBytesRead != SizeOfFileHeader)
309 {
310 ShowLastWin32Error(Globals.hMainWnd);
311 goto done;
312 }
313
314 /* Get header data */
315 switch (wFileIdentifier)
316 {
317 case CLIP_FMT_31:
318 assert(wFileIdentifier == ((CLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier);
319 wFormatCount = ((CLIPFILEHEADER*)pClipFileHeader)->wFormatCount;
320 break;
321
322 case CLIP_FMT_NT:
323 case CLIP_FMT_BK:
324 assert(wFileIdentifier == ((NTCLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier);
325 wFormatCount = ((NTCLIPFILEHEADER*)pClipFileHeader)->wFormatCount;
326 break;
327 }
328
329 /* Loop through the data array */
330 for (i = 0; i < wFormatCount; i++)
331 {
332 if (SetFilePointer(hFile, SizeOfFileHeader + i * SizeOfFormatHeader, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
333 {
334 ShowLastWin32Error(Globals.hMainWnd);
335 goto done;
336 }
337
338 if (!ReadFile(hFile, pClipFormatArray, SizeOfFormatHeader, &dwBytesRead, NULL))
339 {
340 ShowLastWin32Error(Globals.hMainWnd);
341 goto done;
342 }
343
344 /* Get format data */
345 switch (wFileIdentifier)
346 {
347 case CLIP_FMT_31:
348 dwFormatID = ((CLIPFORMATHEADER*)pClipFormatArray)->dwFormatID;
349 dwLenData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwLenData;
350 dwOffData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwOffData;
351 szName = ((CLIPFORMATHEADER*)pClipFormatArray)->szName;
352 break;
353
354 case CLIP_FMT_NT:
355 case CLIP_FMT_BK:
356 dwFormatID = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwFormatID;
357 dwLenData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwLenData;
358 dwOffData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwOffData;
359 szName = ((NTCLIPFORMATHEADER*)pClipFormatArray)->szName;
360 break;
361 }
362
363 switch (dwFormatID)
364 {
365 case CF_OWNERDISPLAY:
366 {
367 break;
368 }
369
370 case CF_BITMAP:
371 case CF_DSPBITMAP:
372 {
373 bResult = ClipboardReadBitmap(hFile, dwOffData, dwLenData);
374 break;
375 }
376
377 case CF_METAFILEPICT:
378 case CF_DSPMETAFILEPICT:
379 {
380 bResult = ClipboardReadMetafile(hFile, dwOffData, dwLenData);
381 break;
382 }
383
384 case CF_ENHMETAFILE:
385 case CF_DSPENHMETAFILE:
386 {
387 bResult = ClipboardReadEnhMetafile(hFile, dwOffData, dwLenData);
388 break;
389 }
390
391 case CF_PALETTE:
392 {
393 bResult = ClipboardReadPalette(hFile, dwOffData, dwLenData);
394 break;
395 }
396
397 default:
398 {
399 if ((dwFormatID < CF_PRIVATEFIRST) || (dwFormatID > CF_PRIVATELAST))
400 {
401 bResult = ClipboardReadMemory(hFile, dwFormatID, dwOffData, dwLenData, wFileIdentifier, szName);
402 }
403 break;
404 }
405 }
406
407 if (!bResult)
408 ShowLastWin32Error(Globals.hMainWnd);
409 }
410
411 done:
412 if (hFile != INVALID_HANDLE_VALUE)
413 CloseHandle(hFile);
414
415 return;
416 }
417
418 void WriteClipboardFile(LPCWSTR lpFileName)
419 {
420 MessageBoxW(Globals.hMainWnd, L"This function is currently not implemented.", L"Clipboard", MB_OK | MB_ICONINFORMATION);
421 return;
422 }