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
12 static HGLOBAL
ClipboardReadMemoryBlock(HANDLE hFile
, DWORD dwOffset
, DWORD dwLength
)
18 hData
= GlobalAlloc(GHND
, dwLength
);
22 lpData
= GlobalLock(hData
);
29 if (SetFilePointer(hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
36 if (!ReadFile(hFile
, lpData
, dwLength
, &dwBytesRead
, NULL
))
48 static BOOL
ClipboardReadMemory(HANDLE hFile
, DWORD dwFormat
, DWORD dwOffset
, DWORD dwLength
, WORD FileIdentifier
, PVOID lpFormatName
)
53 hData
= ClipboardReadMemoryBlock(hFile
, dwOffset
, dwLength
);
57 if ((dwFormat
>= 0xC000) && (dwFormat
<= 0xFFFF))
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
);
75 if (!SetClipboardData(dwTemp
, hData
))
84 static BOOL
ClipboardWriteMemory(HANDLE hFile
, DWORD dwFormat
, DWORD dwOffset
, PDWORD pdwLength
)
90 hData
= GetClipboardData(dwFormat
);
94 lpData
= GlobalLock(hData
);
98 *pdwLength
= GlobalSize(hData
);
100 if (SetFilePointer(hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
106 if (!WriteFile(hFile
, lpData
, *pdwLength
, &dwBytesWritten
, NULL
))
117 static BOOL
ClipboardReadPalette(HANDLE hFile
, DWORD dwOffset
, DWORD dwLength
)
119 LPLOGPALETTE lpPalette
;
123 hData
= ClipboardReadMemoryBlock(hFile
, dwOffset
, dwLength
);
129 lpPalette
= GlobalLock(hData
);
136 hPalette
= CreatePalette(lpPalette
);
141 SetLastError(ERROR_OUTOFMEMORY
);
148 if (!SetClipboardData(CF_PALETTE
, hPalette
))
150 DeleteObject(hPalette
);
157 static BOOL
ClipboardReadMetafile(HANDLE hFile
, DWORD dwOffset
, DWORD dwLength
)
163 hData
= ClipboardReadMemoryBlock(hFile
, dwOffset
, dwLength
);
169 lpData
= GlobalLock(hData
);
176 hMf
= SetMetaFileBitsEx(dwLength
, lpData
);
183 SetLastError(ERROR_OUTOFMEMORY
);
187 if (!SetClipboardData(CF_METAFILEPICT
, hMf
))
196 static BOOL
ClipboardReadEnhMetafile(HANDLE hFile
, DWORD dwOffset
, DWORD dwLength
)
202 hData
= ClipboardReadMemoryBlock(hFile
, dwOffset
, dwLength
);
208 lpData
= GlobalLock(hData
);
215 hEmf
= SetEnhMetaFileBits(dwLength
, lpData
);
222 SetLastError(ERROR_OUTOFMEMORY
);
226 if (!SetClipboardData(CF_ENHMETAFILE
, hEmf
))
228 DeleteEnhMetaFile(hEmf
);
235 static BOOL
ClipboardReadBitmap(HANDLE hFile
, DWORD dwOffset
, DWORD dwLength
)
241 hData
= ClipboardReadMemoryBlock(hFile
, dwOffset
, dwLength
);
247 lpBitmap
= GlobalLock(hData
);
254 lpBitmap
->bmBits
= lpBitmap
+ sizeof(BITMAP
) + 1;
256 hBitmap
= CreateBitmapIndirect(lpBitmap
);
263 SetLastError(ERROR_OUTOFMEMORY
);
267 if (!SetClipboardData(CF_BITMAP
, hBitmap
))
269 DeleteObject(hBitmap
);
276 void ReadClipboardFile(LPCWSTR lpFileName
)
278 CLIPFILEHEADER ClipFileHeader
;
279 CLIPFORMATHEADER ClipFormatArray
;
280 NTCLIPFILEHEADER NtClipFileHeader
;
281 NTCLIPFORMATHEADER NtClipFormatArray
;
282 PVOID pClipFileHeader
;
283 PVOID pClipFormatArray
;
284 DWORD SizeOfFileHeader
, SizeOfFormatHeader
;
286 WORD wFileIdentifier
;
298 /* Open the file for read access */
299 hFile
= CreateFileW(lpFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
300 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
301 if (hFile
== INVALID_HANDLE_VALUE
)
303 ShowLastWin32Error(Globals
.hMainWnd
);
307 /* Just read enough bytes to get the clipboard file format ID */
308 if (!ReadFile(hFile
, &wFileIdentifier
, sizeof(wFileIdentifier
), &dwBytesRead
, NULL
))
310 ShowLastWin32Error(Globals
.hMainWnd
);
314 /* Set data according to the clipboard file format ID */
315 switch (wFileIdentifier
)
318 SizeOfFileHeader
= sizeof(CLIPFILEHEADER
);
319 SizeOfFormatHeader
= sizeof(CLIPFORMATHEADER
);
320 pClipFileHeader
= &ClipFileHeader
;
321 pClipFormatArray
= &ClipFormatArray
;
326 SizeOfFileHeader
= sizeof(NTCLIPFILEHEADER
);
327 SizeOfFormatHeader
= sizeof(NTCLIPFORMATHEADER
);
328 pClipFileHeader
= &NtClipFileHeader
;
329 pClipFormatArray
= &NtClipFormatArray
;
333 MessageBoxRes(Globals
.hMainWnd
, Globals
.hInstance
, ERROR_INVALID_FILE_FORMAT
, 0, MB_ICONSTOP
| MB_OK
);
337 /* Completely read the header */
338 SetFilePointer(hFile
, 0, NULL
, FILE_BEGIN
);
339 if (!ReadFile(hFile
, pClipFileHeader
, SizeOfFileHeader
, &dwBytesRead
, NULL
) ||
340 dwBytesRead
!= SizeOfFileHeader
)
342 ShowLastWin32Error(Globals
.hMainWnd
);
346 /* Get header data */
347 switch (wFileIdentifier
)
350 assert(wFileIdentifier
== ((CLIPFILEHEADER
*)pClipFileHeader
)->wFileIdentifier
);
351 wFormatCount
= ((CLIPFILEHEADER
*)pClipFileHeader
)->wFormatCount
;
356 assert(wFileIdentifier
== ((NTCLIPFILEHEADER
*)pClipFileHeader
)->wFileIdentifier
);
357 wFormatCount
= ((NTCLIPFILEHEADER
*)pClipFileHeader
)->wFormatCount
;
361 /* Loop through the format data array */
362 for (i
= 0; i
< wFormatCount
; i
++)
364 if (SetFilePointer(hFile
, SizeOfFileHeader
+ i
* SizeOfFormatHeader
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
366 ShowLastWin32Error(Globals
.hMainWnd
);
370 if (!ReadFile(hFile
, pClipFormatArray
, SizeOfFormatHeader
, &dwBytesRead
, NULL
))
372 ShowLastWin32Error(Globals
.hMainWnd
);
376 /* Get format data */
377 switch (wFileIdentifier
)
380 dwFormatID
= ((CLIPFORMATHEADER
*)pClipFormatArray
)->dwFormatID
;
381 dwLenData
= ((CLIPFORMATHEADER
*)pClipFormatArray
)->dwLenData
;
382 dwOffData
= ((CLIPFORMATHEADER
*)pClipFormatArray
)->dwOffData
;
383 szName
= ((CLIPFORMATHEADER
*)pClipFormatArray
)->szName
;
388 dwFormatID
= ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->dwFormatID
;
389 dwLenData
= ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->dwLenData
;
390 dwOffData
= ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->dwOffData
;
391 szName
= ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->szName
;
397 case CF_OWNERDISPLAY
:
405 bResult
= ClipboardReadBitmap(hFile
, dwOffData
, dwLenData
);
409 case CF_METAFILEPICT
:
410 case CF_DSPMETAFILEPICT
:
412 bResult
= ClipboardReadMetafile(hFile
, dwOffData
, dwLenData
);
417 case CF_DSPENHMETAFILE
:
419 bResult
= ClipboardReadEnhMetafile(hFile
, dwOffData
, dwLenData
);
425 bResult
= ClipboardReadPalette(hFile
, dwOffData
, dwLenData
);
431 if ((dwFormatID
< CF_PRIVATEFIRST
) || (dwFormatID
> CF_PRIVATELAST
))
433 bResult
= ClipboardReadMemory(hFile
, dwFormatID
, dwOffData
, dwLenData
, wFileIdentifier
, szName
);
440 ShowLastWin32Error(Globals
.hMainWnd
);
444 if (hFile
!= INVALID_HANDLE_VALUE
)
450 void WriteClipboardFile(LPCWSTR lpFileName
, WORD wFileIdentifier
)
452 CLIPFILEHEADER ClipFileHeader
;
453 CLIPFORMATHEADER ClipFormatArray
;
454 NTCLIPFILEHEADER NtClipFileHeader
;
455 NTCLIPFORMATHEADER NtClipFormatArray
;
456 PVOID pClipFileHeader
;
457 PVOID pClipFormatArray
;
458 DWORD SizeOfFileHeader
, SizeOfFormatHeader
;
467 DWORD dwBytesWritten
;
470 /* Create the file for write access */
471 hFile
= CreateFileW(lpFileName
, GENERIC_WRITE
, 0, NULL
,
472 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
473 if (hFile
== INVALID_HANDLE_VALUE
)
475 ShowLastWin32Error(Globals
.hMainWnd
);
479 wFormatCount
= CountClipboardFormats();
481 /* Select the file format and setup the header according to the clipboard file format ID */
482 switch (wFileIdentifier
)
485 SizeOfFileHeader
= sizeof(CLIPFILEHEADER
);
486 SizeOfFormatHeader
= sizeof(CLIPFORMATHEADER
);
487 pClipFileHeader
= &ClipFileHeader
;
488 pClipFormatArray
= &ClipFormatArray
;
490 ClipFileHeader
.wFileIdentifier
= CLIP_FMT_31
; // wFileIdentifier
491 ClipFileHeader
.wFormatCount
= wFormatCount
;
496 SizeOfFileHeader
= sizeof(NTCLIPFILEHEADER
);
497 SizeOfFormatHeader
= sizeof(NTCLIPFORMATHEADER
);
498 pClipFileHeader
= &NtClipFileHeader
;
499 pClipFormatArray
= &NtClipFormatArray
;
501 NtClipFileHeader
.wFileIdentifier
= CLIP_FMT_NT
; // wFileIdentifier
502 NtClipFileHeader
.wFormatCount
= wFormatCount
;
506 MessageBoxRes(Globals
.hMainWnd
, Globals
.hInstance
, ERROR_INVALID_FILE_FORMAT
, 0, MB_ICONSTOP
| MB_OK
);
510 /* Write the header */
511 SetFilePointer(hFile
, 0, NULL
, FILE_BEGIN
);
512 if (!WriteFile(hFile
, pClipFileHeader
, SizeOfFileHeader
, &dwBytesWritten
, NULL
) ||
513 dwBytesWritten
!= SizeOfFileHeader
)
515 ShowLastWin32Error(Globals
.hMainWnd
);
519 /* Compute where the data should start (after the file header and the format array) */
520 dwOffData
= SizeOfFileHeader
+ wFormatCount
* SizeOfFormatHeader
;
522 /* Loop through each format and save the data */
524 dwFormatID
= EnumClipboardFormats(0);
527 if (i
>= wFormatCount
)
529 /* Must never happen! */
534 /* Write the clipboard data at the specified offset, and retrieve its length */
535 if (!ClipboardWriteMemory(hFile
, dwFormatID
, dwOffData
, &dwLenData
))
538 /* Write the format data header */
539 switch (wFileIdentifier
)
542 ZeroMemory(pClipFormatArray
, sizeof(CLIPFORMATHEADER
));
543 ((CLIPFORMATHEADER
*)pClipFormatArray
)->dwFormatID
= dwFormatID
;
544 ((CLIPFORMATHEADER
*)pClipFormatArray
)->dwLenData
= dwLenData
;
545 ((CLIPFORMATHEADER
*)pClipFormatArray
)->dwOffData
= dwOffData
;
546 RetrieveClipboardFormatName(Globals
.hInstance
,
549 ((CLIPFORMATHEADER
*)pClipFormatArray
)->szName
,
550 ARRAYSIZE(((CLIPFORMATHEADER
*)pClipFormatArray
)->szName
));
555 ZeroMemory(pClipFormatArray
, sizeof(NTCLIPFORMATHEADER
));
556 ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->dwFormatID
= dwFormatID
;
557 ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->dwLenData
= dwLenData
;
558 ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->dwOffData
= dwOffData
;
559 RetrieveClipboardFormatName(Globals
.hInstance
,
562 ((NTCLIPFORMATHEADER
*)pClipFormatArray
)->szName
,
563 ARRAYSIZE(((NTCLIPFORMATHEADER
*)pClipFormatArray
)->szName
));
567 if (SetFilePointer(hFile
, SizeOfFileHeader
+ i
* SizeOfFormatHeader
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
569 ShowLastWin32Error(Globals
.hMainWnd
);
573 if (!WriteFile(hFile
, pClipFormatArray
, SizeOfFormatHeader
, &dwBytesWritten
, NULL
))
575 ShowLastWin32Error(Globals
.hMainWnd
);
579 /* Adjust the offset for the next data stream */
580 dwOffData
+= dwLenData
;
584 dwFormatID
= EnumClipboardFormats(dwFormatID
);
588 if (hFile
!= INVALID_HANDLE_VALUE
)