PageRenderTime 79ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/reactos/base/applications/clipbrd/fileutils.c

https://gitlab.com/dj-tech/reactos
C | 592 lines | 467 code | 100 blank | 25 comment | 72 complexity | 968afc1c746ab6683aff0435a358376d MD5 | raw file
  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. #include "precomp.h"
  10. static HGLOBAL ClipboardReadMemoryBlock(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
  11. {
  12. HGLOBAL hData;
  13. LPVOID lpData;
  14. DWORD dwBytesRead;
  15. hData = GlobalAlloc(GHND, dwLength);
  16. if (!hData)
  17. return NULL;
  18. lpData = GlobalLock(hData);
  19. if (!lpData)
  20. {
  21. GlobalFree(hData);
  22. return NULL;
  23. }
  24. if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  25. {
  26. GlobalUnlock(hData);
  27. GlobalFree(hData);
  28. return NULL;
  29. }
  30. if (!ReadFile(hFile, lpData, dwLength, &dwBytesRead, NULL))
  31. {
  32. GlobalUnlock(hData);
  33. GlobalFree(hData);
  34. return NULL;
  35. }
  36. GlobalUnlock(hData);
  37. return hData;
  38. }
  39. static BOOL ClipboardReadMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, DWORD dwLength, WORD FileIdentifier, PVOID lpFormatName)
  40. {
  41. HGLOBAL hData;
  42. DWORD dwTemp = 0;
  43. hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
  44. if (!hData)
  45. return FALSE;
  46. if ((dwFormat >= 0xC000) && (dwFormat <= 0xFFFF))
  47. {
  48. if (FileIdentifier == CLIP_FMT_31)
  49. dwTemp = RegisterClipboardFormatA((LPCSTR)lpFormatName);
  50. else if ((FileIdentifier == CLIP_FMT_NT) || (FileIdentifier == CLIP_FMT_BK))
  51. dwTemp = RegisterClipboardFormatW((LPCWSTR)lpFormatName);
  52. if (!dwTemp)
  53. {
  54. GlobalFree(hData);
  55. return FALSE;
  56. }
  57. }
  58. else
  59. {
  60. dwTemp = dwFormat;
  61. }
  62. if (!SetClipboardData(dwTemp, hData))
  63. {
  64. GlobalFree(hData);
  65. return FALSE;
  66. }
  67. return TRUE;
  68. }
  69. static BOOL ClipboardWriteMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, PDWORD pdwLength)
  70. {
  71. HGLOBAL hData;
  72. LPVOID lpData;
  73. DWORD dwBytesWritten;
  74. hData = GetClipboardData(dwFormat);
  75. if (!hData)
  76. return FALSE;
  77. lpData = GlobalLock(hData);
  78. if (!lpData)
  79. return FALSE;
  80. *pdwLength = GlobalSize(hData);
  81. if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  82. {
  83. GlobalUnlock(hData);
  84. return FALSE;
  85. }
  86. if (!WriteFile(hFile, lpData, *pdwLength, &dwBytesWritten, NULL))
  87. {
  88. GlobalUnlock(hData);
  89. return FALSE;
  90. }
  91. GlobalUnlock(hData);
  92. return TRUE;
  93. }
  94. static BOOL ClipboardReadPalette(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
  95. {
  96. LPLOGPALETTE lpPalette;
  97. HPALETTE hPalette;
  98. HGLOBAL hData;
  99. hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
  100. if (!hData)
  101. {
  102. return FALSE;
  103. }
  104. lpPalette = GlobalLock(hData);
  105. if (!lpPalette)
  106. {
  107. GlobalFree(hData);
  108. return FALSE;
  109. }
  110. hPalette = CreatePalette(lpPalette);
  111. if (!hPalette)
  112. {
  113. GlobalUnlock(hData);
  114. GlobalFree(hData);
  115. SetLastError(ERROR_OUTOFMEMORY);
  116. return FALSE;
  117. }
  118. GlobalUnlock(hData);
  119. GlobalFree(hData);
  120. if (!SetClipboardData(CF_PALETTE, hPalette))
  121. {
  122. DeleteObject(hPalette);
  123. return FALSE;
  124. }
  125. return TRUE;
  126. }
  127. static BOOL ClipboardReadMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
  128. {
  129. HMETAFILE hMf;
  130. HGLOBAL hData;
  131. LPVOID lpData;
  132. hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
  133. if (!hData)
  134. {
  135. return FALSE;
  136. }
  137. lpData = GlobalLock(hData);
  138. if (!lpData)
  139. {
  140. GlobalFree(hData);
  141. return FALSE;
  142. }
  143. hMf = SetMetaFileBitsEx(dwLength, lpData);
  144. GlobalUnlock(hData);
  145. GlobalFree(hData);
  146. if (!hMf)
  147. {
  148. SetLastError(ERROR_OUTOFMEMORY);
  149. return FALSE;
  150. }
  151. if (!SetClipboardData(CF_METAFILEPICT, hMf))
  152. {
  153. DeleteMetaFile(hMf);
  154. return FALSE;
  155. }
  156. return TRUE;
  157. }
  158. static BOOL ClipboardReadEnhMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
  159. {
  160. HENHMETAFILE hEmf;
  161. HGLOBAL hData;
  162. LPVOID lpData;
  163. hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
  164. if (!hData)
  165. {
  166. return FALSE;
  167. }
  168. lpData = GlobalLock(hData);
  169. if (!lpData)
  170. {
  171. GlobalFree(hData);
  172. return FALSE;
  173. }
  174. hEmf = SetEnhMetaFileBits(dwLength, lpData);
  175. GlobalUnlock(hData);
  176. GlobalFree(hData);
  177. if (!hEmf)
  178. {
  179. SetLastError(ERROR_OUTOFMEMORY);
  180. return FALSE;
  181. }
  182. if (!SetClipboardData(CF_ENHMETAFILE, hEmf))
  183. {
  184. DeleteEnhMetaFile(hEmf);
  185. return FALSE;
  186. }
  187. return TRUE;
  188. }
  189. static BOOL ClipboardReadBitmap(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
  190. {
  191. HGLOBAL hData;
  192. HBITMAP hBitmap;
  193. LPBITMAP lpBitmap;
  194. hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
  195. if (!hData)
  196. {
  197. return FALSE;
  198. }
  199. lpBitmap = GlobalLock(hData);
  200. if (!lpBitmap)
  201. {
  202. GlobalFree(hData);
  203. return FALSE;
  204. }
  205. lpBitmap->bmBits = lpBitmap + sizeof(BITMAP) + 1;
  206. hBitmap = CreateBitmapIndirect(lpBitmap);
  207. GlobalUnlock(hData);
  208. GlobalFree(hData);
  209. if (!hBitmap)
  210. {
  211. SetLastError(ERROR_OUTOFMEMORY);
  212. return FALSE;
  213. }
  214. if (!SetClipboardData(CF_BITMAP, hBitmap))
  215. {
  216. DeleteObject(hBitmap);
  217. return FALSE;
  218. }
  219. return TRUE;
  220. }
  221. void ReadClipboardFile(LPCWSTR lpFileName)
  222. {
  223. CLIPFILEHEADER ClipFileHeader;
  224. CLIPFORMATHEADER ClipFormatArray;
  225. NTCLIPFILEHEADER NtClipFileHeader;
  226. NTCLIPFORMATHEADER NtClipFormatArray;
  227. PVOID pClipFileHeader;
  228. PVOID pClipFormatArray;
  229. DWORD SizeOfFileHeader, SizeOfFormatHeader;
  230. WORD wFileIdentifier;
  231. WORD wFormatCount;
  232. DWORD dwFormatID;
  233. DWORD dwLenData;
  234. DWORD dwOffData;
  235. PVOID szName;
  236. HANDLE hFile;
  237. DWORD dwBytesRead;
  238. BOOL bResult;
  239. int i;
  240. /* Open the file for read access */
  241. hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  242. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  243. if (hFile == INVALID_HANDLE_VALUE)
  244. {
  245. ShowLastWin32Error(Globals.hMainWnd);
  246. goto done;
  247. }
  248. /* Just read enough bytes to get the clipboard file format ID */
  249. if (!ReadFile(hFile, &wFileIdentifier, sizeof(wFileIdentifier), &dwBytesRead, NULL))
  250. {
  251. ShowLastWin32Error(Globals.hMainWnd);
  252. goto done;
  253. }
  254. /* Set data according to the clipboard file format ID */
  255. switch (wFileIdentifier)
  256. {
  257. case CLIP_FMT_31:
  258. SizeOfFileHeader = sizeof(CLIPFILEHEADER);
  259. SizeOfFormatHeader = sizeof(CLIPFORMATHEADER);
  260. pClipFileHeader = &ClipFileHeader;
  261. pClipFormatArray = &ClipFormatArray;
  262. break;
  263. case CLIP_FMT_NT:
  264. case CLIP_FMT_BK:
  265. SizeOfFileHeader = sizeof(NTCLIPFILEHEADER);
  266. SizeOfFormatHeader = sizeof(NTCLIPFORMATHEADER);
  267. pClipFileHeader = &NtClipFileHeader;
  268. pClipFormatArray = &NtClipFormatArray;
  269. break;
  270. default:
  271. MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK);
  272. goto done;
  273. }
  274. /* Completely read the header */
  275. SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  276. if (!ReadFile(hFile, pClipFileHeader, SizeOfFileHeader, &dwBytesRead, NULL) ||
  277. dwBytesRead != SizeOfFileHeader)
  278. {
  279. ShowLastWin32Error(Globals.hMainWnd);
  280. goto done;
  281. }
  282. /* Get header data */
  283. switch (wFileIdentifier)
  284. {
  285. case CLIP_FMT_31:
  286. assert(wFileIdentifier == ((CLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier);
  287. wFormatCount = ((CLIPFILEHEADER*)pClipFileHeader)->wFormatCount;
  288. break;
  289. case CLIP_FMT_NT:
  290. case CLIP_FMT_BK:
  291. assert(wFileIdentifier == ((NTCLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier);
  292. wFormatCount = ((NTCLIPFILEHEADER*)pClipFileHeader)->wFormatCount;
  293. break;
  294. }
  295. /* Loop through the format data array */
  296. for (i = 0; i < wFormatCount; i++)
  297. {
  298. if (SetFilePointer(hFile, SizeOfFileHeader + i * SizeOfFormatHeader, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  299. {
  300. ShowLastWin32Error(Globals.hMainWnd);
  301. goto done;
  302. }
  303. if (!ReadFile(hFile, pClipFormatArray, SizeOfFormatHeader, &dwBytesRead, NULL))
  304. {
  305. ShowLastWin32Error(Globals.hMainWnd);
  306. goto done;
  307. }
  308. /* Get format data */
  309. switch (wFileIdentifier)
  310. {
  311. case CLIP_FMT_31:
  312. dwFormatID = ((CLIPFORMATHEADER*)pClipFormatArray)->dwFormatID;
  313. dwLenData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwLenData;
  314. dwOffData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwOffData;
  315. szName = ((CLIPFORMATHEADER*)pClipFormatArray)->szName;
  316. break;
  317. case CLIP_FMT_NT:
  318. case CLIP_FMT_BK:
  319. dwFormatID = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwFormatID;
  320. dwLenData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwLenData;
  321. dwOffData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwOffData;
  322. szName = ((NTCLIPFORMATHEADER*)pClipFormatArray)->szName;
  323. break;
  324. }
  325. switch (dwFormatID)
  326. {
  327. case CF_OWNERDISPLAY:
  328. {
  329. break;
  330. }
  331. case CF_BITMAP:
  332. case CF_DSPBITMAP:
  333. {
  334. bResult = ClipboardReadBitmap(hFile, dwOffData, dwLenData);
  335. break;
  336. }
  337. case CF_METAFILEPICT:
  338. case CF_DSPMETAFILEPICT:
  339. {
  340. bResult = ClipboardReadMetafile(hFile, dwOffData, dwLenData);
  341. break;
  342. }
  343. case CF_ENHMETAFILE:
  344. case CF_DSPENHMETAFILE:
  345. {
  346. bResult = ClipboardReadEnhMetafile(hFile, dwOffData, dwLenData);
  347. break;
  348. }
  349. case CF_PALETTE:
  350. {
  351. bResult = ClipboardReadPalette(hFile, dwOffData, dwLenData);
  352. break;
  353. }
  354. default:
  355. {
  356. if ((dwFormatID < CF_PRIVATEFIRST) || (dwFormatID > CF_PRIVATELAST))
  357. {
  358. bResult = ClipboardReadMemory(hFile, dwFormatID, dwOffData, dwLenData, wFileIdentifier, szName);
  359. }
  360. break;
  361. }
  362. }
  363. if (!bResult)
  364. ShowLastWin32Error(Globals.hMainWnd);
  365. }
  366. done:
  367. if (hFile != INVALID_HANDLE_VALUE)
  368. CloseHandle(hFile);
  369. return;
  370. }
  371. void WriteClipboardFile(LPCWSTR lpFileName, WORD wFileIdentifier)
  372. {
  373. CLIPFILEHEADER ClipFileHeader;
  374. CLIPFORMATHEADER ClipFormatArray;
  375. NTCLIPFILEHEADER NtClipFileHeader;
  376. NTCLIPFORMATHEADER NtClipFormatArray;
  377. PVOID pClipFileHeader;
  378. PVOID pClipFormatArray;
  379. DWORD SizeOfFileHeader, SizeOfFormatHeader;
  380. WORD wFormatCount;
  381. DWORD dwFormatID;
  382. DWORD dwLenData;
  383. DWORD dwOffData;
  384. // PVOID szName;
  385. HANDLE hFile;
  386. DWORD dwBytesWritten;
  387. int i;
  388. /* Create the file for write access */
  389. hFile = CreateFileW(lpFileName, GENERIC_WRITE, 0, NULL,
  390. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  391. if (hFile == INVALID_HANDLE_VALUE)
  392. {
  393. ShowLastWin32Error(Globals.hMainWnd);
  394. goto done;
  395. }
  396. wFormatCount = CountClipboardFormats();
  397. /* Select the file format and setup the header according to the clipboard file format ID */
  398. switch (wFileIdentifier)
  399. {
  400. case CLIP_FMT_31:
  401. SizeOfFileHeader = sizeof(CLIPFILEHEADER);
  402. SizeOfFormatHeader = sizeof(CLIPFORMATHEADER);
  403. pClipFileHeader = &ClipFileHeader;
  404. pClipFormatArray = &ClipFormatArray;
  405. ClipFileHeader.wFileIdentifier = CLIP_FMT_31; // wFileIdentifier
  406. ClipFileHeader.wFormatCount = wFormatCount;
  407. break;
  408. case CLIP_FMT_NT:
  409. case CLIP_FMT_BK:
  410. SizeOfFileHeader = sizeof(NTCLIPFILEHEADER);
  411. SizeOfFormatHeader = sizeof(NTCLIPFORMATHEADER);
  412. pClipFileHeader = &NtClipFileHeader;
  413. pClipFormatArray = &NtClipFormatArray;
  414. NtClipFileHeader.wFileIdentifier = CLIP_FMT_NT; // wFileIdentifier
  415. NtClipFileHeader.wFormatCount = wFormatCount;
  416. break;
  417. default:
  418. MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK);
  419. goto done;
  420. }
  421. /* Write the header */
  422. SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  423. if (!WriteFile(hFile, pClipFileHeader, SizeOfFileHeader, &dwBytesWritten, NULL) ||
  424. dwBytesWritten != SizeOfFileHeader)
  425. {
  426. ShowLastWin32Error(Globals.hMainWnd);
  427. goto done;
  428. }
  429. /* Compute where the data should start (after the file header and the format array) */
  430. dwOffData = SizeOfFileHeader + wFormatCount * SizeOfFormatHeader;
  431. /* Loop through each format and save the data */
  432. i = 0;
  433. dwFormatID = EnumClipboardFormats(0);
  434. while (dwFormatID)
  435. {
  436. if (i >= wFormatCount)
  437. {
  438. /* Must never happen! */
  439. assert(FALSE);
  440. break;
  441. }
  442. /* Write the clipboard data at the specified offset, and retrieve its length */
  443. if (!ClipboardWriteMemory(hFile, dwFormatID, dwOffData, &dwLenData))
  444. goto Cont;
  445. /* Write the format data header */
  446. switch (wFileIdentifier)
  447. {
  448. case CLIP_FMT_31:
  449. ZeroMemory(pClipFormatArray, sizeof(CLIPFORMATHEADER));
  450. ((CLIPFORMATHEADER*)pClipFormatArray)->dwFormatID = dwFormatID;
  451. ((CLIPFORMATHEADER*)pClipFormatArray)->dwLenData = dwLenData;
  452. ((CLIPFORMATHEADER*)pClipFormatArray)->dwOffData = dwOffData;
  453. RetrieveClipboardFormatName(Globals.hInstance,
  454. dwFormatID,
  455. FALSE,
  456. ((CLIPFORMATHEADER*)pClipFormatArray)->szName,
  457. ARRAYSIZE(((CLIPFORMATHEADER*)pClipFormatArray)->szName));
  458. break;
  459. case CLIP_FMT_NT:
  460. case CLIP_FMT_BK:
  461. ZeroMemory(pClipFormatArray, sizeof(NTCLIPFORMATHEADER));
  462. ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwFormatID = dwFormatID;
  463. ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwLenData = dwLenData;
  464. ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwOffData = dwOffData;
  465. RetrieveClipboardFormatName(Globals.hInstance,
  466. dwFormatID,
  467. TRUE,
  468. ((NTCLIPFORMATHEADER*)pClipFormatArray)->szName,
  469. ARRAYSIZE(((NTCLIPFORMATHEADER*)pClipFormatArray)->szName));
  470. break;
  471. }
  472. if (SetFilePointer(hFile, SizeOfFileHeader + i * SizeOfFormatHeader, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  473. {
  474. ShowLastWin32Error(Globals.hMainWnd);
  475. goto done;
  476. }
  477. if (!WriteFile(hFile, pClipFormatArray, SizeOfFormatHeader, &dwBytesWritten, NULL))
  478. {
  479. ShowLastWin32Error(Globals.hMainWnd);
  480. goto done;
  481. }
  482. /* Adjust the offset for the next data stream */
  483. dwOffData += dwLenData;
  484. Cont:
  485. i++;
  486. dwFormatID = EnumClipboardFormats(dwFormatID);
  487. }
  488. done:
  489. if (hFile != INVALID_HANDLE_VALUE)
  490. CloseHandle(hFile);
  491. return;
  492. }