Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1608 lines
44 KiB

  1. /*****************************************************************************
  2. C L I P F I L E
  3. Name: clipfile.c
  4. Date: 19-Apr-1994
  5. Creator: Unknown
  6. Description:
  7. Windows Clipboard File I/O Routines.
  8. NOTE:
  9. When saving the contents of the clipboard we SetClipboardData(fmt, NULL)
  10. to free up the memory associated with each clipboard format. Then
  11. after we are done saving we take over as the clipboard owner. This
  12. causes OWNERDRAW formats to be lost in the save process.
  13. *****************************************************************************/
  14. #include <windows.h>
  15. #include <windowsx.h>
  16. #include <string.h>
  17. #include <strsafe.h>
  18. #include "common.h"
  19. #include "clipfile.h"
  20. #include "clipfile.h"
  21. #include "dib.h"
  22. #include "debugout.h"
  23. #include "render.h"
  24. #include "security.h"
  25. #define ARRAYSIZE(a) (sizeof(a)/sizeof((a)[0]))
  26. BOOL fAnythingToRender;
  27. TCHAR szFileSpecifier[] = TEXT("*.CLP");
  28. TCHAR szFileName[MAX_PATH+1];
  29. TCHAR szSaveFileName[MAX_PATH+1]; // Saved filename for delayed render
  30. BOOL fNTReadFileFormat;
  31. BOOL fNTSaveFileFormat;
  32. UINT cf_link;
  33. UINT cf_objectlink;
  34. UINT cf_linkcopy;
  35. UINT cf_objectlinkcopy;
  36. BOOL AddDIBtoDDB(VOID);
  37. /*******************
  38. File read routines
  39. *******************/
  40. /*
  41. * ReadFileHeader
  42. *
  43. * Purpose: Read the file header in the given .clp file, and get the number
  44. * of formats. Also sets the fNTReadFileFormat flag appropriately.
  45. *
  46. * Parameters:
  47. * fh - Handle to the file.
  48. *
  49. * Returns:
  50. * The number of formats, or 0 if it isn't a valid .clp file.
  51. */
  52. unsigned ReadFileHeader(
  53. HANDLE fh)
  54. {
  55. FILEHEADER FileHeader;
  56. DWORD dwBytesRead;
  57. // PINFO(TEXT("ClSrv\\RdFileHdr"));
  58. /* Read the File Header */
  59. SetFilePointer(fh, 0, NULL, FILE_BEGIN);
  60. ReadFile(fh, &FileHeader, sizeof(FileHeader), &dwBytesRead, NULL);
  61. if (dwBytesRead == sizeof(FILEHEADER))
  62. {
  63. // Make sure that this is a .CLP file
  64. if (FileHeader.magic == CLPBK_NT_ID ||
  65. FileHeader.magic == CLP_NT_ID)
  66. {
  67. fNTReadFileFormat = TRUE;
  68. }
  69. else if (FileHeader.magic == CLP_ID)
  70. {
  71. fNTReadFileFormat = FALSE;
  72. }
  73. else
  74. {
  75. PERROR(TEXT("Invalid magic member (not long enough?)\r\n"));
  76. FileHeader.FormatCount = 0;
  77. }
  78. // Check number of formats for additional reassurance.
  79. if (FileHeader.FormatCount > 100)
  80. {
  81. PERROR(TEXT("Too many formats!!!\r\n"));
  82. FileHeader.FormatCount = 0;
  83. }
  84. }
  85. else
  86. {
  87. PERROR("Read err\r\n");
  88. FileHeader.FormatCount = 0;
  89. }
  90. if (FileHeader.FormatCount)
  91. {
  92. // PINFO(TEXT("\r\n"));
  93. }
  94. return(FileHeader.FormatCount);
  95. }
  96. /*
  97. * ReadFormatHeader
  98. */
  99. BOOL ReadFormatHeader(
  100. HANDLE fh,
  101. FORMATHEADER *pfh,
  102. unsigned iFormat)
  103. {
  104. DWORD dwMrPibb;
  105. OLDFORMATHEADER OldFormatHeader;
  106. // PINFO(TEXT("ClSrv\\RdFmtHdr"));
  107. if (NULL == pfh || NULL == fh)
  108. {
  109. PERROR("RdFmtHdr got NULL pointer\r\n");
  110. return FALSE;
  111. }
  112. SetFilePointer (fh,
  113. sizeof(FILEHEADER) + iFormat *
  114. (fNTReadFileFormat ? sizeof(FORMATHEADER) : sizeof(OLDFORMATHEADER)),
  115. NULL,
  116. FILE_BEGIN);
  117. if (fNTReadFileFormat)
  118. {
  119. ReadFile(fh, pfh, sizeof(FORMATHEADER), &dwMrPibb, NULL);
  120. if (dwMrPibb != sizeof(FORMATHEADER))
  121. {
  122. PERROR(TEXT("Bad new format rd\r\n"));
  123. return FALSE;
  124. }
  125. }
  126. else
  127. {
  128. ReadFile(fh, &OldFormatHeader, sizeof(OldFormatHeader), &dwMrPibb, NULL);
  129. if (dwMrPibb != sizeof(OLDFORMATHEADER))
  130. {
  131. PERROR(TEXT("Bad old format rd\r\n"));
  132. return FALSE;
  133. }
  134. pfh->FormatID = OldFormatHeader.FormatID;
  135. pfh->DataLen = OldFormatHeader.DataLen;
  136. pfh->DataOffset = OldFormatHeader.DataOffset;
  137. MultiByteToWideChar (CP_ACP,
  138. MB_PRECOMPOSED,
  139. OldFormatHeader.Name,
  140. -1,
  141. pfh->Name,
  142. CCHFMTNAMEMAX);
  143. }
  144. // PINFO(TEXT("\r\n"));
  145. return TRUE;
  146. }
  147. /*
  148. * ReadClipboardFromFile()
  149. *
  150. * Read in a clipboard file and register all the formats in delayed mode.
  151. * to render things for real reopen the file specified by ofStruct.
  152. *
  153. * NOTE:
  154. * This makes us the clipboard owner.
  155. *
  156. * Return Value: READFILE_IMPROPERFORMAT
  157. * READFILE_OPENCLIPBRDFAIL
  158. * READFILE_SUCCESS
  159. */
  160. short ReadClipboardFromFile(
  161. HWND hwnd,
  162. HANDLE fh)
  163. {
  164. register unsigned i;
  165. unsigned cFormats;
  166. FORMATHEADER FormatHeader;
  167. PINFO(TEXT("Entering ReadClipboardFromFile\r\n"));
  168. if (!(cFormats = ReadFileHeader(fh)) )
  169. {
  170. return(READFILE_IMPROPERFORMAT);
  171. }
  172. /* We become the clipboard owner here! */
  173. if (!SyncOpenClipboard(hwnd))
  174. {
  175. PERROR(TEXT("Could not open clipboard!!!"));
  176. return(READFILE_OPENCLIPBRDFAIL);
  177. }
  178. EmptyClipboard();
  179. for (i=0; i < cFormats; i++)
  180. {
  181. ReadFormatHeader (fh, &FormatHeader, i);
  182. if (PRIVATE_FORMAT(FormatHeader.FormatID))
  183. {
  184. FormatHeader.FormatID = RegisterClipboardFormatW ((LPWSTR)FormatHeader.Name);
  185. }
  186. /*Delayed Render. */
  187. PINFO(TEXT("Set up delayed render for format %d .\r\n"), FormatHeader.FormatID);
  188. SetClipboardData (FormatHeader.FormatID, NULL);
  189. if (FormatHeader.FormatID == CF_DIB)
  190. SetClipboardData (CF_BITMAP, NULL);
  191. }
  192. /* Now, clipbrd viewer has something to render */
  193. if (cFormats > 0)
  194. {
  195. PINFO(TEXT("fAnythingToRender = TRUE\r\n"));
  196. fAnythingToRender = TRUE;
  197. }
  198. SyncCloseClipboard();
  199. return(READFILE_SUCCESS);
  200. }
  201. /*
  202. * OpenClipboardFile
  203. */
  204. DWORD OpenClipboardFile(
  205. HWND hwnd,
  206. LPTSTR szName)
  207. {
  208. HANDLE fh;
  209. DWORD dwErr = NO_ERROR;
  210. PINFO(TEXT("OpenClipboardFile: %s \r\n"),szName);
  211. fh = CreateFile ((LPCTSTR)szName,
  212. GENERIC_READ,
  213. FILE_SHARE_READ,
  214. NULL,
  215. OPEN_EXISTING,
  216. FILE_ATTRIBUTE_NORMAL,
  217. NULL);
  218. if (fh != INVALID_HANDLE_VALUE)
  219. {
  220. // Store file name for delayed rendering stuff.
  221. StringCchCopy(szSaveFileName, MAX_PATH+1, szName);
  222. // Read it.
  223. switch (ReadClipboardFromFile (hwnd, fh))
  224. {
  225. case READFILE_IMPROPERFORMAT:
  226. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  227. break;
  228. case READFILE_OPENCLIPBRDFAIL:
  229. dwErr = ERROR_CLIPBOARD_NOT_OPEN;
  230. break;
  231. case READFILE_SUCCESS:
  232. default:
  233. dwErr = NO_ERROR;
  234. break;
  235. }
  236. CloseHandle (fh);
  237. }
  238. else
  239. {
  240. PERROR(TEXT("ClSrv\\OpClpFile: can't open file!"));
  241. dwErr = GetLastError ();
  242. }
  243. return dwErr;
  244. }
  245. /*
  246. * RenderFormatFormFile
  247. *
  248. * Purpose: Go get the given format from the given file.
  249. */
  250. HANDLE RenderFormatFromFile(
  251. LPTSTR szFile,
  252. WORD wFormat)
  253. {
  254. HANDLE fh;
  255. FORMATHEADER FormatHeader;
  256. HANDLE hData = NULL;
  257. unsigned cFormats;
  258. unsigned i;
  259. BOOL bHasDib = FALSE;
  260. PINFO(TEXT("ClpSrv\\RndrFmtFromFile: Opening file %s.\r\n"),szFile);
  261. fh = CreateFile (szFile,
  262. GENERIC_READ,
  263. FILE_SHARE_READ,
  264. NULL,
  265. OPEN_EXISTING,
  266. FILE_ATTRIBUTE_NORMAL,
  267. NULL);
  268. if (INVALID_HANDLE_VALUE == fh)
  269. {
  270. PERROR(TEXT("Can't open file\r\n"));
  271. goto done;
  272. }
  273. cFormats = ReadFileHeader(fh);
  274. // If ReadFile didn't get the whole header, don't try to read anything else.
  275. if (0 == cFormats)
  276. {
  277. PERROR(TEXT("Bad file header.\r\n"));
  278. goto done;
  279. }
  280. for (i=0; i < cFormats; i++)
  281. {
  282. ReadFormatHeader(fh, &FormatHeader, i);
  283. PINFO(TEXT("Got format %ws\r\n"),FormatHeader.Name);
  284. if (PRIVATE_FORMAT(FormatHeader.FormatID))
  285. {
  286. FormatHeader.FormatID = RegisterClipboardFormatW(FormatHeader.Name);
  287. }
  288. if (FormatHeader.FormatID == wFormat)
  289. {
  290. hData = RenderFormat(&FormatHeader, fh);
  291. }
  292. if (FormatHeader.FormatID == CF_DIB)
  293. bHasDib = TRUE;
  294. }
  295. // make CF_BITMAP available when there's CF_DIB
  296. if (!hData && wFormat == CF_BITMAP && bHasDib)
  297. {
  298. if (SetFilePointer (fh, 0, 0, FILE_BEGIN) == 0xFFFFFFFF)
  299. {
  300. PERROR(TEXT("Cannot set file pointer to FILE_BEGIN\n"));
  301. goto done;
  302. }
  303. cFormats = ReadFileHeader (fh);
  304. for (i=0; i < cFormats; i++)
  305. {
  306. ReadFormatHeader (fh, &FormatHeader, i);
  307. PINFO (TEXT("Got format %ws\n"), FormatHeader.Name);
  308. if (FormatHeader.FormatID == CF_DIB)
  309. hData = RenderFormatDibToBitmap (&FormatHeader,
  310. fh,
  311. RenderFormatFromFile (szFile, CF_PALETTE));
  312. }
  313. }
  314. done:
  315. if (fh != INVALID_HANDLE_VALUE)
  316. CloseHandle (fh);
  317. return(hData);
  318. }
  319. /*
  320. * RenderAllFromFile
  321. *
  322. * Purpose: Go get all formats from the given file.
  323. */
  324. HANDLE RenderAllFromFile(
  325. LPTSTR szFile)
  326. {
  327. HANDLE fh;
  328. FORMATHEADER FormatHeader;
  329. HANDLE hData;
  330. unsigned cFormats;
  331. unsigned i;
  332. /* Check if the clipbrd viewer has done any File I/O before.
  333. * If it has not, then it has nothing to render!
  334. */
  335. if (CountClipboardFormats() && fAnythingToRender)
  336. {
  337. /* Empty the clipboard */
  338. if (!SyncOpenClipboard(hwndApp))
  339. {
  340. PERROR("Couldn't open clipboard!\r\n");
  341. }
  342. else
  343. {
  344. EmptyClipboard();
  345. fh = CreateFile (szFile,
  346. GENERIC_READ,
  347. FILE_SHARE_READ,
  348. NULL,
  349. OPEN_EXISTING,
  350. FILE_ATTRIBUTE_NORMAL,
  351. NULL);
  352. if (INVALID_HANDLE_VALUE != fh)
  353. {
  354. cFormats = ReadFileHeader(fh);
  355. // If ReadFile didn't get the whole header, don't try to read anything
  356. // else.
  357. if (0 == cFormats)
  358. {
  359. PERROR(TEXT("Bad file header.\r\n"));
  360. }
  361. for (i=0; i < cFormats; i++)
  362. {
  363. ReadFormatHeader(fh, &FormatHeader, i);
  364. PINFO(TEXT("Got format %ws\r\n"),FormatHeader.Name);
  365. if (PRIVATE_FORMAT(FormatHeader.FormatID))
  366. {
  367. FormatHeader.FormatID =
  368. RegisterClipboardFormatW(FormatHeader.Name);
  369. }
  370. // Render the format and set it into the clipboard
  371. hData = RenderFormat(&FormatHeader, fh);
  372. if ( hData != NULL )
  373. {
  374. if (!SetClipboardData(FormatHeader.FormatID, hData))
  375. {
  376. PERROR(TEXT("SetClipboardData fail\n\r"));
  377. }
  378. }
  379. else
  380. {
  381. PERROR(TEXT("hData == NULL, bad\r\n"));
  382. }
  383. }
  384. CloseHandle(fh);
  385. }
  386. else
  387. {
  388. PERROR(TEXT("Can't open file\r\n"));
  389. }
  390. SyncCloseClipboard();
  391. }
  392. }
  393. return(0L);
  394. }
  395. /********************
  396. File write routines
  397. ********************/
  398. /*
  399. * IsWriteable()
  400. *
  401. * Test if a clipboard format is writeable(i.e. if it makes sense to write it)
  402. * OWNERDRAW and others can't be written because we (CLIPBRD) will become the
  403. * owner when the files are reopened.
  404. */
  405. BOOL IsWriteable(WORD Format)
  406. {
  407. /* Are the PRIVATEFIRST and PRIVATELAST things right? */
  408. if ((Format >= CF_PRIVATEFIRST && Format <= CF_PRIVATELAST)
  409. || Format == CF_OWNERDISPLAY)
  410. {
  411. return FALSE;
  412. }
  413. // If we're not saving an NT clipboard, don't save NT-specific formats.
  414. if (!fNTSaveFileFormat &&
  415. (Format == CF_UNICODETEXT || Format == CF_ENHMETAFILE
  416. || Format == CF_DSPENHMETAFILE)
  417. )
  418. {
  419. return(FALSE);
  420. }
  421. return(TRUE);
  422. }
  423. /*
  424. * Count16BitClipboardFormats
  425. *
  426. * This function will return the number of clipboard formats compatible with
  427. * the Windows 3.1 clipboard, this excludes CF_UNICODETEXT, CF_ENHMETAFILE and
  428. * CF_DSPENHMETAFILE
  429. */
  430. int Count16BitClipboardFormats(void)
  431. {
  432. int iCount;
  433. iCount = CountClipboardFormats();
  434. if (IsClipboardFormatAvailable(CF_UNICODETEXT))
  435. iCount--;
  436. if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
  437. iCount--;
  438. if (IsClipboardFormatAvailable(CF_DSPENHMETAFILE))
  439. iCount--;
  440. return iCount;
  441. }
  442. /*
  443. * WriteFormatBlock
  444. *
  445. * Purpose: Writes the format header for a single data format.
  446. *
  447. * Parameters:
  448. * fh - File handle to write to.
  449. * offset - Position in the file to write the format block.
  450. * DataOffset - Position in the file where the data for this format will be.
  451. * DataLen - Length of the data for this format.
  452. * Format - The format number.
  453. * szName - Name of the format.
  454. *
  455. * Returns:
  456. * The number of bytes written to the file.
  457. */
  458. DWORD WriteFormatBlock(
  459. HANDLE fh,
  460. DWORD offset,
  461. DWORD DataOffset,
  462. DWORD DataLen,
  463. UINT Format,
  464. LPWSTR wszName)
  465. {
  466. DWORD dwBytesWritten = 0;
  467. SetFilePointer(fh, offset, NULL, FILE_BEGIN);
  468. if (fNTSaveFileFormat)
  469. {
  470. FORMATHEADER FormatHeader;
  471. memset (&FormatHeader, 0, sizeof(FormatHeader));
  472. FormatHeader.FormatID = Format;
  473. FormatHeader.DataLen = DataLen;
  474. FormatHeader.DataOffset = DataOffset;
  475. StringCchCopyW(FormatHeader.Name, CCHFMTNAMEMAX, wszName);
  476. WriteFile (fh, &FormatHeader, sizeof(FormatHeader), &dwBytesWritten, NULL);
  477. }
  478. else
  479. {
  480. OLDFORMATHEADER OldFormatHeader;
  481. memset(&OldFormatHeader,0, sizeof(OldFormatHeader));
  482. OldFormatHeader.FormatID = (WORD)Format;
  483. OldFormatHeader.DataLen = DataLen;
  484. OldFormatHeader.DataOffset = DataOffset;
  485. WideCharToMultiByte(CP_ACP,
  486. 0,
  487. wszName,
  488. -1,
  489. OldFormatHeader.Name,
  490. CCHFMTNAMEMAX,
  491. NULL,
  492. NULL);
  493. WriteFile (fh,
  494. &OldFormatHeader,
  495. sizeof(OldFormatHeader),
  496. &dwBytesWritten,
  497. NULL);
  498. }
  499. return(dwBytesWritten);
  500. }
  501. /*
  502. * WriteDataBlock() -
  503. *
  504. * Returns:
  505. * # of bytes written to the output file
  506. *
  507. * NOTE: Write saves the name of a temp file in the clipboard for it's
  508. * own internal clipboard format. This file goes aways when Write
  509. * (or windows?) shuts down. Thus saving Write clipboards won't work
  510. * (should we special case hack this?)
  511. *
  512. */
  513. DWORD WriteDataBlock(
  514. register HANDLE hFile,
  515. DWORD offset,
  516. WORD Format)
  517. {
  518. WORD wPalEntries;
  519. LPSTR lpData;
  520. DWORD dwSize = 0;
  521. BITMAP bitmap;
  522. HANDLE hMF;
  523. HANDLE hBitmap;
  524. register HANDLE hData;
  525. LPLOGPALETTE lpLogPalette;
  526. LPMETAFILEPICT lpMFP;
  527. DWORD dwMFPSize;
  528. BOOL fOK = FALSE;
  529. if (!(hData = GetClipboardData(Format)) ||
  530. SetFilePointer (hFile, offset, NULL, FILE_BEGIN) != offset)
  531. {
  532. PERROR(TEXT("WriteDataBlock: couldn't get format data\n\r"));
  533. return 0;
  534. }
  535. /* We have to special case a few common formats but most things
  536. * get handled in the default case.
  537. */
  538. switch (Format)
  539. {
  540. case CF_ENHMETAFILE:
  541. dwSize = (DWORD) GetEnhMetaFileBits(hData, 0, NULL); /* Get data size */
  542. if (lpData = GlobalAllocPtr(GHND, dwSize)) /* allocate mem for EMF bits */
  543. {
  544. if (GetEnhMetaFileBits(hData, dwSize, (LPBYTE)lpData))
  545. {
  546. WriteFile(hFile, lpData, dwSize, &dwSize, NULL);
  547. fOK = TRUE;
  548. }
  549. GlobalFreePtr(lpData);
  550. }
  551. if (!fOK)
  552. {
  553. PERROR(TEXT("WriteDataBlock: couldn't write CF_ENHMETAFILE\r\n"));
  554. dwSize = 0;
  555. }
  556. break;
  557. case CF_METAFILEPICT:
  558. if (lpMFP = (LPMETAFILEPICT)GlobalLock(hData)) /* get header */
  559. {
  560. // Write METAFILEPICT header -- if we're saving in Win31 format,
  561. // write the old-style header.
  562. if (fNTSaveFileFormat)
  563. {
  564. WriteFile(hFile, lpMFP, sizeof(METAFILEPICT),
  565. &dwMFPSize, NULL);
  566. }
  567. else
  568. {
  569. WIN31METAFILEPICT w31mfp;
  570. /* If we save the metafile in the Windows 3.1 .CLP file format
  571. we have to save the METAFILEPICT structure as a 16bit METAFILEPICT
  572. structure. This may cause loss of information if the
  573. high half of the METAFILEPICT structure's fields are used. */
  574. w31mfp.mm = (WORD)lpMFP->mm;
  575. w31mfp.xExt = (WORD)lpMFP->xExt;
  576. w31mfp.yExt = (WORD)lpMFP->yExt;
  577. w31mfp.hMF = (WORD)0;
  578. WriteFile(hFile, &w31mfp, sizeof(WIN31METAFILEPICT), &dwMFPSize, NULL);
  579. }
  580. hMF = lpMFP->hMF;
  581. GlobalUnlock(hData); /* unlock the header */
  582. /* Figure out how big a block we need */
  583. dwSize = GetMetaFileBitsEx(hMF, 0, NULL);
  584. if (dwSize)
  585. {
  586. if (lpData = GlobalAllocPtr(GHND, dwSize))
  587. {
  588. if (dwSize == GetMetaFileBitsEx(hMF, dwSize, lpData))
  589. {
  590. WriteFile(hFile, lpData, dwSize, &dwSize, NULL);
  591. dwSize += dwMFPSize;
  592. }
  593. else
  594. {
  595. dwSize = 0;
  596. }
  597. GlobalFreePtr(lpData);
  598. }
  599. else
  600. {
  601. dwSize = 0;
  602. }
  603. }
  604. }
  605. break;
  606. case CF_BITMAP:
  607. /* Writing DDBs to disk is bad. Therefore, we */
  608. /* write an intelligent CF_DIB block instead. */
  609. Format = CF_DIB;
  610. GetObject((HBITMAP)hData, sizeof(BITMAP), &bitmap);
  611. if (hBitmap = DibFromBitmap ((HBITMAP)hData,
  612. BI_RGB,
  613. (WORD) (bitmap.bmBitsPixel * bitmap.bmPlanes),
  614. IsClipboardFormatAvailable(CF_PALETTE) ?
  615. GetClipboardData(CF_PALETTE) : NULL))
  616. {
  617. if (lpData = GlobalLock(hBitmap))
  618. {
  619. // dwSize might be too big, but we can live with that.
  620. dwSize = (DWORD)GlobalSize(lpData);
  621. WriteFile(hFile, lpData, dwSize, &dwSize, NULL);
  622. // Clean up
  623. GlobalUnlock(hBitmap);
  624. GlobalFree(hBitmap);
  625. }
  626. }
  627. break;
  628. case CF_PALETTE:
  629. /* Get the number of palette entries */
  630. GetObject(hData, sizeof(WORD), (LPBYTE)&wPalEntries);
  631. /* Allocate enough place to build the LOGPALETTE struct */
  632. dwSize = (DWORD)(sizeof(LOGPALETTE) +
  633. (LONG)wPalEntries * sizeof(PALETTEENTRY));
  634. if (lpLogPalette = (LPLOGPALETTE)GlobalAllocPtr(GHND, dwSize))
  635. {
  636. lpLogPalette->palVersion = 0x300; /* Windows 3.00 */
  637. lpLogPalette->palNumEntries = wPalEntries;
  638. if (GetPaletteEntries(hData, 0, wPalEntries,
  639. (LPPALETTEENTRY)(lpLogPalette->palPalEntry)) != 0)
  640. {
  641. /* Write the LOGPALETTE structure onto disk */
  642. WriteFile(hFile, lpLogPalette, dwSize, &dwSize, NULL);
  643. }
  644. else
  645. {
  646. dwSize = 0;
  647. }
  648. GlobalFreePtr(lpLogPalette);
  649. }
  650. else
  651. {
  652. dwSize = 0L;
  653. }
  654. break;
  655. default:
  656. dwSize = (DWORD)GlobalSize(hData);
  657. // Just lock the data down and write it out.
  658. if (lpData = GlobalLock(hData))
  659. {
  660. WriteFile(hFile, lpData, dwSize, &dwSize, NULL);
  661. GlobalUnlock(hData);
  662. }
  663. else
  664. {
  665. dwSize = 0;
  666. }
  667. break;
  668. }
  669. /* Return the number of bytes written. */
  670. return(dwSize);
  671. }
  672. /*
  673. * GetClipboardNameW
  674. */
  675. void GetClipboardNameW(
  676. register int fmt,
  677. LPWSTR wszName,
  678. register int iSize)
  679. {
  680. LPWSTR lprgch = NULL;
  681. HANDLE hrgch = NULL;
  682. *wszName = '\0';
  683. /* Get global memory that everyone can get to */
  684. if (!(hrgch = GlobalAlloc(GMEM_MOVEABLE, (LONG)(iSize + 1)*sizeof(WCHAR))))
  685. {
  686. PERROR(TEXT("GetClipboardNameW: bad alloc\r\n"));
  687. goto done;
  688. }
  689. if (!(lprgch = (LPWSTR)GlobalLock(hrgch)))
  690. {
  691. PERROR(TEXT("GetClipboardNameW: bad lock\r\n"));
  692. goto done;
  693. }
  694. memset(lprgch, 0, (iSize+1)*sizeof(WCHAR));
  695. switch (fmt)
  696. {
  697. case CF_RIFF:
  698. case CF_WAVE:
  699. case CF_PENDATA:
  700. case CF_SYLK:
  701. case CF_DIF:
  702. case CF_TIFF:
  703. case CF_TEXT:
  704. case CF_BITMAP:
  705. case CF_METAFILEPICT:
  706. case CF_ENHMETAFILE:
  707. case CF_OEMTEXT:
  708. case CF_DIB:
  709. case CF_PALETTE:
  710. case CF_DSPTEXT:
  711. case CF_DSPBITMAP:
  712. case CF_DSPMETAFILEPICT:
  713. case CF_DSPENHMETAFILE:
  714. case CF_UNICODETEXT:
  715. LoadStringW(hInst, fmt, lprgch, iSize);
  716. break;
  717. case CF_OWNERDISPLAY: /* Clipbrd owner app supplies name */
  718. // Note: This should NEVER happen because this function only gets
  719. // called when we're writing a given clipboard format. Clipbrd can't
  720. // get away with writing CF_OWNERDISPLAY because we become clipboard
  721. // owner when we re-read the file, and we won't know how to deal.
  722. PERROR(TEXT("GetClipboardName on OwnerDisplay format!\r\n"));
  723. LoadStringW(hInst, fmt, lprgch, iSize);
  724. break;
  725. default:
  726. GetClipboardFormatNameW(fmt, lprgch, iSize);
  727. break;
  728. }
  729. StringCchCopyW(wszName, iSize, lprgch);
  730. done:
  731. if (lprgch) GlobalUnlock(hrgch);
  732. if (hrgch) GlobalFree(hrgch);
  733. }
  734. /*
  735. * SaveClipboardData() - Writes a clipboard file.
  736. *
  737. * In:
  738. * hwnd handle of wnd that becomes the clipboard owner
  739. * szFileName file handle to read from
  740. * fPage TRUE if this is a clipbook page (which means we secure it)
  741. *
  742. * NOTE:
  743. * When done we call ReadClipboardFromFile(). this makes us the
  744. * clipboard owner.
  745. *
  746. * Returns:
  747. * NO_ERROR if no error otherwise an error code.
  748. */
  749. DWORD SaveClipboardData(
  750. HWND hwnd,
  751. LPTSTR szFileName,
  752. BOOL fPage)
  753. {
  754. register HANDLE fh;
  755. register WORD Format;
  756. SECURITY_ATTRIBUTES sa;
  757. DWORD HeaderPos;
  758. DWORD DataPos;
  759. DWORD datasize;
  760. HCURSOR hCursor;
  761. FILEHEADER FileHeader;
  762. WCHAR wszName[CCHFMTNAMEMAX];
  763. UINT wHeaderSize;
  764. UINT uiSizeHeaderToWrite;
  765. BOOL fDIBUsed = FALSE;
  766. DWORD dwTemp;
  767. DWORD dwRet = NO_ERROR;
  768. /* First open the clipboard */
  769. if (!SyncOpenClipboard(hwndApp))
  770. return ERROR_CLIPBOARD_NOT_OPEN;
  771. sa.nLength = sizeof(sa);
  772. sa.lpSecurityDescriptor = (fPage ? CurrentUserOnlySD() : NULL);
  773. sa.bInheritHandle = FALSE;
  774. fh = CreateFile((LPCTSTR)szFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  775. &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  776. if (fh == INVALID_HANDLE_VALUE)
  777. {
  778. PERROR ("Error opening clipboard file!\r\n");
  779. dwRet = GetLastError ();
  780. goto done;
  781. }
  782. /* Fill out the file header structure */
  783. if (fNTSaveFileFormat)
  784. {
  785. FileHeader.magic = CLPBK_NT_ID; /* magic number to tag our files */
  786. uiSizeHeaderToWrite = sizeof(FORMATHEADER);
  787. }
  788. else
  789. {
  790. FileHeader.magic = CLP_ID; /* magic number to tag our files */
  791. uiSizeHeaderToWrite = sizeof(OLDFORMATHEADER);
  792. }
  793. FileHeader.FormatCount = 0; /* dummy for now */
  794. /* Update HeaderPos and DataPos */
  795. HeaderPos = sizeof(FILEHEADER);
  796. /* This is the maximum number of formats that will be written. Potentially
  797. * some may fail and some space will be wasted.
  798. */
  799. if (fNTSaveFileFormat)
  800. {
  801. DataPos = HeaderPos + (uiSizeHeaderToWrite * CountClipboardFormats());
  802. }
  803. else
  804. {
  805. DataPos = HeaderPos + (uiSizeHeaderToWrite * Count16BitClipboardFormats());
  806. }
  807. /* Now loop throught the data, one format at a time, and write out the data. */
  808. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  809. ShowCursor(TRUE);
  810. /* Enumerate all formats */
  811. Format = 0;
  812. while ((Format = (WORD)EnumClipboardFormats(Format)))
  813. {
  814. if (IsWriteable(Format))
  815. {
  816. // DO NOT write CF_BITMAP to disk. Transform to CF_DIB
  817. // and write that instead.
  818. // If there's CF_DIB, then don't do CF_BITMAP
  819. if (CF_BITMAP == Format)
  820. if (IsClipboardFormatAvailable (CF_DIB)
  821. && GetClipboardData (CF_DIB))
  822. continue; // We have DIB, don't worry about BITMAP.
  823. if (CF_BITMAP == Format || CF_DIB == Format)
  824. {
  825. if (!fDIBUsed)
  826. fDIBUsed = TRUE;
  827. else
  828. // Already done DIB, go on to the next format.
  829. continue;
  830. }
  831. GetClipboardNameW (Format == CF_BITMAP ? CF_DIB : Format,
  832. wszName,
  833. ARRAYSIZE(wszName));
  834. PINFO(TEXT("SClipboardData: writing %ls (#)%d\r\n"), wszName,Format);
  835. if (datasize = WriteDataBlock(fh, DataPos, Format))
  836. {
  837. /* Create a Format header and write it to the file */
  838. wHeaderSize = (WORD)WriteFormatBlock (fh,
  839. HeaderPos,
  840. DataPos,
  841. datasize,
  842. Format == CF_BITMAP ? CF_DIB : Format,
  843. wszName);
  844. if (wHeaderSize < uiSizeHeaderToWrite)
  845. {
  846. PERROR(TEXT("SaveClipboardData: error writing format block\n\r"));
  847. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  848. break;
  849. }
  850. HeaderPos += wHeaderSize;
  851. /* Update the data pos for the next block */
  852. DataPos += datasize;
  853. FileHeader.FormatCount++; /* this format has been written */
  854. }
  855. }
  856. }
  857. ShowCursor(FALSE);
  858. SetCursor(hCursor);
  859. SyncCloseClipboard(); /* we are done looking at this */
  860. // Go back and write the file header at the front of the file
  861. SetFilePointer (fh, 0L, NULL, FILE_BEGIN);
  862. if (!WriteFile (fh, &FileHeader, sizeof(FileHeader), &dwTemp, NULL))
  863. dwRet = GetLastError ();
  864. /* Now we open the clipboard and become the owner. this places
  865. * all the things we just saved in the clipboard (and throws out
  866. * those things we didn't save)
  867. */
  868. // Set us back to the beginning
  869. SetFilePointer(fh, 0L, NULL, FILE_BEGIN);
  870. /* Under NT, the save filename will be used to get the file back */
  871. StringCchCopy(szSaveFileName, MAX_PATH+1, szFileName);
  872. PINFO(TEXT("sAVEcLIPBOARDdATA: Copied name %s to name %s\r\n"), szSaveFileName, szFileName);
  873. fNTReadFileFormat = fNTSaveFileFormat;
  874. if (dwRet == NO_ERROR) //bRet)
  875. {
  876. switch (ReadClipboardFromFile (hwndApp, fh))
  877. {
  878. case READFILE_IMPROPERFORMAT:
  879. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  880. break;
  881. case READFILE_OPENCLIPBRDFAIL:
  882. dwRet = ERROR_CLIPBOARD_NOT_OPEN;
  883. break;
  884. case READFILE_SUCCESS:
  885. default:
  886. dwRet = NO_ERROR;
  887. break;
  888. }
  889. }
  890. CloseHandle(fh);
  891. if (dwRet != NO_ERROR)
  892. {
  893. PERROR(TEXT("SCD: Trouble in ReadClipboardFromFile\r\n"));
  894. DeleteFile(szFileName);
  895. }
  896. done:
  897. if (sa.lpSecurityDescriptor)
  898. {
  899. GlobalFree((HGLOBAL)sa.lpSecurityDescriptor);
  900. }
  901. SyncCloseClipboard();
  902. return dwRet;
  903. }
  904. /*
  905. * SaveClipboardToFile() -
  906. * Parameters:
  907. * hwnd - Passed to SaveClipboardData
  908. * szShareName - Clipbook page name
  909. * szFileName - Filename to save to
  910. * fPage - TRUE if this is a clbook page, FALSE if a file saved
  911. * by the user.
  912. *
  913. * Returns: NO_ERROR if no error occured otherwise an error code.
  914. *
  915. */
  916. DWORD SaveClipboardToFile(
  917. HWND hwnd,
  918. TCHAR *szShareName,
  919. TCHAR *szFileName,
  920. BOOL fPage)
  921. {
  922. DWORD dwErr = NO_ERROR;
  923. PINFO(TEXT("\r\n Entering SaveClipboardToFile\r\n"));
  924. if (fPage)
  925. {
  926. AddNetInfoToClipboard( szShareName );
  927. AddPreviewFormat();
  928. }
  929. dwErr = SaveClipboardData(hwnd, szFileName, fPage);
  930. if (dwErr != NO_ERROR)
  931. {
  932. /* If Failure, Delete the incomplete file */
  933. PERROR(TEXT("SaveClipboardData failed!"));
  934. DeleteFile(szSaveFileName);
  935. }
  936. return dwErr;
  937. }
  938. /*
  939. * AddPreviewFormat
  940. */
  941. BOOL AddPreviewFormat (VOID)
  942. {
  943. LPMETAFILEPICT lpMF;
  944. HANDLE hClpData;
  945. HANDLE hBmpData;
  946. HBITMAP hBitmap;
  947. HBITMAP hClpBmp;
  948. HBITMAP hOldDstBmp;
  949. HBITMAP hOldSrcBmp;
  950. BITMAP Bitmap;
  951. HDC hDC;
  952. HDC hDstDC;
  953. HDC hSrcDC;
  954. LPBYTE lpBmp;
  955. int ret = FALSE;
  956. RECT rc;
  957. int OldMode;
  958. if (!IsClipboardFormatAvailable(CF_TEXT) &&
  959. !IsClipboardFormatAvailable(CF_BITMAP) &&
  960. !IsClipboardFormatAvailable(CF_METAFILEPICT) &&
  961. !IsClipboardFormatAvailable(CF_ENHMETAFILE) &&
  962. !IsClipboardFormatAvailable(CF_UNICODETEXT))
  963. return FALSE;
  964. if ( !SyncOpenClipboard(hwndApp))
  965. return FALSE;
  966. if ( !(hBmpData = GlobalAlloc ( GHND, 64 * 64 / 8 )) )
  967. {
  968. SyncCloseClipboard();
  969. return FALSE;
  970. }
  971. hDC = GetDC ( hwndApp );
  972. hDstDC = CreateCompatibleDC ( hDC );
  973. hSrcDC = CreateCompatibleDC ( hDC );
  974. ReleaseDC ( hwndApp, hDC );
  975. if ( !( hBitmap = CreateBitmap ( 64, 64, 1, 1, NULL )) )
  976. PERROR (TEXT("CreateBitmap failed\n\r"));
  977. hOldDstBmp = SelectObject ( hDstDC, hBitmap );
  978. rc.top = rc.left = 0;
  979. rc.bottom = rc.right = 64;
  980. PatBlt ( hDstDC, 0, 0, 64, 64, WHITENESS );
  981. if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
  982. {
  983. HENHMETAFILE hemf;
  984. ENHMETAHEADER enheader;
  985. if (hemf = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE))
  986. {
  987. GetEnhMetaFileHeader(hemf, sizeof(enheader), &enheader);
  988. SaveDC(hDstDC);
  989. SetMapMode( hDstDC, MM_ISOTROPIC);
  990. SetViewportExtEx(hDstDC, 64, 64, NULL);
  991. SetWindowExtEx(hDstDC, enheader.rclBounds.right, enheader.rclBounds.bottom, NULL);
  992. PlayEnhMetaFile(hDstDC, hemf, (LPRECT)&enheader.rclBounds);
  993. RestoreDC(hDstDC, -1);
  994. }
  995. else
  996. {
  997. PERROR(TEXT("GetClipboardData fail on CF_ENHMETAFILE\r\n"));
  998. }
  999. }
  1000. else if ( IsClipboardFormatAvailable ( CF_METAFILEPICT ))
  1001. {
  1002. if ( hClpData = GetClipboardData ( CF_METAFILEPICT ))
  1003. {
  1004. if ( lpMF = (LPMETAFILEPICT)GlobalLock ( hClpData ) )
  1005. {
  1006. SaveDC(hDstDC);
  1007. SetMapMode( hDstDC, lpMF->mm);
  1008. if ( lpMF->xExt >= lpMF->yExt )
  1009. {
  1010. SetViewportExtEx( hDstDC, 64,
  1011. (int)((64L*(LONG)lpMF->yExt)/(LONG)lpMF->xExt), NULL);
  1012. SetViewportOrgEx ( hDstDC, 0,
  1013. (64 - (int)((64L*(LONG)lpMF->yExt)/(LONG)lpMF->xExt))
  1014. / 2, NULL );
  1015. }
  1016. else
  1017. {
  1018. SetViewportExtEx( hDstDC,
  1019. (int)((64L*(LONG)lpMF->xExt)/(LONG)lpMF->yExt),64, NULL);
  1020. SetViewportOrgEx( hDstDC,
  1021. ( 64 - (int)((64L*(LONG)lpMF->xExt)/(LONG)lpMF->yExt))
  1022. / 2, 0, NULL);
  1023. }
  1024. if ( !PlayMetaFile ( hDstDC, lpMF->hMF ))
  1025. PERROR(TEXT("playmetafile failed\n\r"));
  1026. GlobalUnlock ( hClpData );
  1027. RestoreDC( hDstDC, -1 );
  1028. }
  1029. else
  1030. PERROR(TEXT("couldn't LOCK it though...\n\r"));
  1031. }
  1032. else
  1033. PERROR(TEXT("couldn't GET it though...\n\r"));
  1034. }
  1035. else if ( IsClipboardFormatAvailable ( CF_BITMAP ))
  1036. {
  1037. if ( hClpBmp = GetClipboardData ( CF_BITMAP ))
  1038. {
  1039. GetObject ( hClpBmp, sizeof(BITMAP), &Bitmap );
  1040. hOldSrcBmp = SelectObject ( hSrcDC, hClpBmp );
  1041. OldMode = SetStretchBltMode ( hDstDC, COLORONCOLOR);
  1042. StretchBlt ( hDstDC, 0, 0, 64, 64,
  1043. hSrcDC, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight,
  1044. SRCCOPY );
  1045. SetStretchBltMode ( hDstDC, OldMode );
  1046. SelectObject ( hSrcDC, hOldSrcBmp );
  1047. }
  1048. }
  1049. else if ( IsClipboardFormatAvailable ( CF_TEXT ))
  1050. {
  1051. LPSTR lpText;
  1052. HFONT hSmallFont, hOldFont;
  1053. if ( hClpData = GetClipboardData ( CF_TEXT ))
  1054. {
  1055. lpText = (LPSTR)GlobalLock ( hClpData );
  1056. FillRect ( hDstDC, &rc, GetStockObject ( WHITE_BRUSH ) );
  1057. hSmallFont = CreateFont( -6,
  1058. 0, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
  1059. CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  1060. VARIABLE_PITCH | FF_SWISS, TEXT("Small Fonts")
  1061. );
  1062. hOldFont = SelectObject ( hDstDC, hSmallFont );
  1063. DrawTextA( hDstDC,lpText, lstrlenA(lpText),
  1064. &rc, DT_LEFT);
  1065. SelectObject ( hDstDC, hOldFont );
  1066. DeleteObject ( hSmallFont );
  1067. GlobalUnlock ( hClpData );
  1068. }
  1069. }
  1070. else if ( IsClipboardFormatAvailable (CF_UNICODETEXT))
  1071. {
  1072. LPWSTR lpText;
  1073. HFONT hSmallFont, hOldFont;
  1074. if ( hClpData = GetClipboardData ( CF_UNICODETEXT ))
  1075. {
  1076. lpText = (LPWSTR)GlobalLock ( hClpData );
  1077. FillRect ( hDstDC, &rc, GetStockObject ( WHITE_BRUSH ) );
  1078. hSmallFont = CreateFont( -6,
  1079. 0, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
  1080. CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  1081. VARIABLE_PITCH | FF_SWISS, TEXT("Small Fonts")
  1082. );
  1083. hOldFont = SelectObject ( hDstDC, hSmallFont );
  1084. DrawTextW( hDstDC,lpText, lstrlenW(lpText),
  1085. &rc, DT_LEFT);
  1086. SelectObject ( hDstDC, hOldFont );
  1087. DeleteObject ( hSmallFont );
  1088. GlobalUnlock ( hClpData );
  1089. }
  1090. }
  1091. SelectObject ( hDstDC, hOldDstBmp );
  1092. DeleteDC ( hDstDC );
  1093. DeleteDC ( hSrcDC );
  1094. lpBmp = GlobalLock ( hBmpData );
  1095. if ( GetBitmapBits ( hBitmap, 64 * 64 / 8, lpBmp ) != 64*64/8 )
  1096. PERROR(TEXT("GetBitmapBits failed\n\r"));
  1097. GlobalUnlock ( hBmpData );
  1098. SetClipboardData ( cf_preview, hBmpData );
  1099. ret = TRUE;
  1100. DeleteObject ( hBitmap );
  1101. SyncCloseClipboard();
  1102. return ret;
  1103. }
  1104. /*
  1105. * AddCopiedFormat
  1106. */
  1107. BOOL AddCopiedFormat (
  1108. UINT ufmtOriginal,
  1109. UINT ufmtCopy)
  1110. {
  1111. LPBYTE lpOriginal;
  1112. LPBYTE lpCopy;
  1113. HANDLE hOriginal;
  1114. HANDLE hCopy = NULL;
  1115. BOOL ret = FALSE;
  1116. int i;
  1117. if (IsClipboardFormatAvailable(ufmtOriginal) && SyncOpenClipboard(hwndApp))
  1118. {
  1119. if ( hOriginal = GetClipboardData(ufmtOriginal))
  1120. {
  1121. if ( hCopy = GlobalAlloc( GHND, GlobalSize(hOriginal)))
  1122. {
  1123. if ( lpOriginal = GlobalLock(hOriginal))
  1124. {
  1125. if ( lpCopy = GlobalLock (hCopy))
  1126. {
  1127. for ( i=(int)GlobalSize(hOriginal); i--; )
  1128. *lpCopy++ = *lpOriginal++;
  1129. GlobalUnlock(hCopy);
  1130. #ifdef DEBUG
  1131. lpCopy = GlobalLock(hCopy);
  1132. GlobalUnlock(hCopy);
  1133. #endif
  1134. ret = ( SetClipboardData ( ufmtCopy, hCopy ) != NULL );
  1135. }
  1136. GlobalUnlock(hOriginal);
  1137. }
  1138. }
  1139. }
  1140. SyncCloseClipboard();
  1141. }
  1142. if ( !ret )
  1143. {
  1144. PERROR(TEXT("AddCopiedFormat returning FALSE!\n\r"));
  1145. if ( hCopy )
  1146. GlobalFree (hCopy);
  1147. }
  1148. return ret;
  1149. }
  1150. /*
  1151. * AddNetInfoToClipboard
  1152. */
  1153. BOOL AddNetInfoToClipboard (
  1154. TCHAR *szShareName )
  1155. {
  1156. HANDLE hData;
  1157. HANDLE hNewData;
  1158. TCHAR szServerName[MAX_COMPUTERNAME_LENGTH + 1];
  1159. DWORD dwNameLen;
  1160. LPTSTR src;
  1161. LPTSTR dst;
  1162. cf_link = RegisterClipboardFormat (SZLINK);
  1163. cf_linkcopy = RegisterClipboardFormat (SZLINKCOPY);
  1164. cf_objectlink = RegisterClipboardFormat (SZOBJECTLINK);
  1165. cf_objectlinkcopy = RegisterClipboardFormat (SZOBJECTLINKCOPY);
  1166. // check to see if this info already added:
  1167. if (IsClipboardFormatAvailable (cf_linkcopy))
  1168. {
  1169. PINFO(TEXT("AddNetInfo: Already added\n\r"));
  1170. return FALSE;
  1171. }
  1172. if (IsClipboardFormatAvailable (cf_link))
  1173. {
  1174. AddCopiedFormat (cf_link, cf_linkcopy);
  1175. if (!SyncOpenClipboard (hwndApp))
  1176. return (FALSE);
  1177. dwNameLen = MAX_COMPUTERNAME_LENGTH+1;
  1178. GetComputerName (szServerName, &dwNameLen);
  1179. PINFO(TEXT("link data found\n\r"));
  1180. if (hData = GetClipboardData (cf_link))
  1181. {
  1182. if (src = GlobalLock (hData))
  1183. {
  1184. // approx 20 extra chars for the \\, \ndde$, .dde, and the 2 NULL chars
  1185. size_t Size = GlobalSize(hData) + lstrlen (szServerName) +lstrlen (szShareName) +20;
  1186. hNewData = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, Size);
  1187. dst = GlobalLock (hNewData);
  1188. StringCchPrintf (dst, Size, TEXT("\\\\%s\\%s"), szServerName, TEXT("NDDE$"));
  1189. Size -= (lstrlen(dst) + 1);
  1190. dst += lstrlen(dst) + 1;
  1191. StringCchCopy ( dst, Size, szShareName );
  1192. *dst = SHR_CHAR;
  1193. Size -= lstrlen(dst);
  1194. StringCchCat( dst, Size, TEXT(".dde") );
  1195. Size -= 5;
  1196. dst += lstrlen(dst) + 1;
  1197. src += lstrlen(src) + 1;
  1198. src += lstrlen(src) + 1;
  1199. StringCchCopy ( dst, Size, src );
  1200. GlobalUnlock (hData);
  1201. GlobalUnlock (hNewData);
  1202. SetClipboardData (cf_link, hNewData);
  1203. }
  1204. }
  1205. SyncCloseClipboard ();
  1206. }
  1207. if (IsClipboardFormatAvailable (cf_objectlink))
  1208. {
  1209. AddCopiedFormat (cf_objectlink, cf_objectlinkcopy);
  1210. if (!SyncOpenClipboard (hwndApp))
  1211. return (FALSE);
  1212. dwNameLen = MAX_COMPUTERNAME_LENGTH+1;
  1213. GetComputerName (szServerName, &dwNameLen);
  1214. PINFO(TEXT("objectlink data found\n\r"));
  1215. if (hData = GetClipboardData (cf_objectlink))
  1216. {
  1217. if (src = GlobalLock (hData))
  1218. {
  1219. // approx 20 extra chars for the \\, \ndde$, .dde, and the 2 NULL chars
  1220. size_t Size = GlobalSize(hData) +lstrlen (szServerName) +lstrlen (szShareName) +20;
  1221. hNewData = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, Size);
  1222. dst = GlobalLock (hNewData);
  1223. StringCchPrintf(dst, Size, TEXT("\\\\%s\\%s"), szServerName, TEXT("NDDE$"));
  1224. Size -= (lstrlen(dst) + 1);
  1225. dst += lstrlen(dst) + 1;
  1226. StringCchCopy (dst, Size, szShareName);
  1227. Size -= lstrlen(szShareName);
  1228. *dst = SHR_CHAR;
  1229. StringCchCat (dst, Size, TEXT(".ole"));
  1230. dst += lstrlen(dst) + 1;
  1231. Size -= 5;
  1232. src += lstrlen(src) + 1;
  1233. src += lstrlen(src) + 1;
  1234. StringCchCopy (dst, Size, src);
  1235. GlobalUnlock (hData);
  1236. GlobalUnlock (hNewData);
  1237. SetClipboardData (cf_objectlink, hNewData);
  1238. }
  1239. }
  1240. SyncCloseClipboard ();
  1241. }
  1242. return TRUE;
  1243. }