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.

1951 lines
54 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: metasup.cxx
  3. *
  4. * Includes metafile support functions.
  5. *
  6. * Created: 17-July-1991 10:10:36
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * Copyright (c) 1991-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #define NO_STRICT
  12. extern "C" {
  13. #if defined(_GDIPLUS_)
  14. #include <gpprefix.h>
  15. #endif
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <stddef.h>
  20. #include <windows.h> // GDI function declarations.
  21. #include <winerror.h>
  22. #include "firewall.h"
  23. #define __CPLUSPLUS
  24. #include <winspool.h>
  25. #include <w32gdip.h>
  26. #include "ntgdistr.h"
  27. #include "winddi.h"
  28. #include "hmgshare.h"
  29. #include "icm.h"
  30. #include "local.h" // Local object support.
  31. #include "gdiicm.h"
  32. #include "metadef.h" // Metafile record type constants.
  33. #include "mf16.h"
  34. #include "ntgdi.h"
  35. }
  36. #include "rectl.hxx"
  37. #include "mfdc.hxx" // Metafile DC class declarations.
  38. #include "mfrec.hxx" // Metafile record class declarations.
  39. extern "C" {
  40. HANDLE InternalCreateLocalMetaFile(HANDLE hSrv, DWORD iTypeReq);
  41. DWORD SetMapperFlagsInternal(HDC hdc,DWORD fl);
  42. }
  43. PLINK aplHash[LINK_HASH_SIZE] = {0};
  44. /******************************Public*Routine******************************\
  45. * pmdcAllocMDC(hdcRef, pszFilename, pwszDescription)
  46. *
  47. * This routine allocates memory for an MDC and initializes it. It creates
  48. * a disk file if necessary. Returns a pointer to the new MDC. On error
  49. * returns NULL.
  50. *
  51. * This routine is called by API level DC allocation routines CreateEnhMetaFile.
  52. *
  53. * History:
  54. * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl]
  55. * Wrote it.
  56. \**************************************************************************/
  57. PMDC pmdcAllocMDC(HDC hdcRef, LPCWSTR pwszFilename, LPCWSTR pwszDescription, HANDLE hEMFSpool)
  58. {
  59. PMDC pmdc, pmdcRc = (PMDC) NULL;
  60. ULONG ii;
  61. PUTS("pmdcAllocMDC\n");
  62. // Allocate a new MDC.
  63. if (!(pmdc = (PMDC) LocalAlloc(LMEM_FIXED, sizeof(MDC))))
  64. goto pmdcAllocMDC_cleanup;
  65. // Initialize it.
  66. pmdc->ident = MDC_IDENTIFIER;
  67. pmdc->hFile = INVALID_HANDLE_VALUE;
  68. pmdc->hData = NULL;
  69. pmdc->nMem = MF_BUFSIZE_INIT;
  70. pmdc->iMem = 0L;
  71. pmdc->fl = 0L;
  72. pmdc->pmhe = (PMHE) NULL;
  73. pmdc->cPalEntries = 0L;
  74. pmdc->iPalEntries = 0L;
  75. pmdc->pPalEntries = (PPALETTEENTRY) NULL; // allocate as needed
  76. pmdc->erclMetaBounds = rclInfinity; // default clipping bounds
  77. pmdc->erclClipBounds = rclInfinity;
  78. pmdc->hdcRef = hdcRef;
  79. pmdc->exFontScale(0.0f);
  80. pmdc->eyFontScale(0.0f);
  81. pmdc->vInitColorProfileList();
  82. // Create a disk file if given. The filename is given in unicode.
  83. if (pwszFilename)
  84. {
  85. LPWSTR pwszFilePart; // not used
  86. // Convert the filename to a fully qualified pathname.
  87. DWORD cPathname = GetFullPathNameW(pwszFilename,
  88. MAX_PATH,
  89. pmdc->wszPathname,
  90. &pwszFilePart);
  91. if (!cPathname || cPathname > MAX_PATH)
  92. {
  93. ERROR_ASSERT(FALSE, "GetFullPathName failed");
  94. if (cPathname > MAX_PATH)
  95. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  96. goto pmdcAllocMDC_cleanup;
  97. }
  98. pmdc->wszPathname[cPathname] = 0;
  99. // Create the file.
  100. if ((pmdc->hFile = CreateFileW(pmdc->wszPathname, // Filename
  101. GENERIC_WRITE, // Write access
  102. 0L, // Non-shared
  103. (LPSECURITY_ATTRIBUTES) NULL, // No security
  104. CREATE_ALWAYS, // Always create
  105. FILE_ATTRIBUTE_NORMAL, // normal attributes
  106. (HANDLE) 0)) // no template file
  107. == INVALID_HANDLE_VALUE)
  108. {
  109. ERROR_ASSERT(FALSE, "CreateFile failed");
  110. goto pmdcAllocMDC_cleanup;
  111. }
  112. pmdc->fl |= MDC_DISKFILE; // this must be last! See vFreeMDC.
  113. }
  114. // Allocate memory for metafile.
  115. // For disk metafile, it is used as a buffer.
  116. // For memory metafile, it is the storage for the metafile.
  117. if (hEMFSpool != NULL)
  118. {
  119. // Recording EMF data during EMF spooling
  120. pmdc->fl |= MDC_EMFSPOOL;
  121. pmdc->hData = hEMFSpool;
  122. if(!((EMFSpoolData *) hEMFSpool)->GetEMFData(pmdc))
  123. goto pmdcAllocMDC_cleanup;
  124. }
  125. else
  126. {
  127. if (!(pmdc->hData = LocalAlloc(LMEM_FIXED, MF_BUFSIZE_INIT)))
  128. goto pmdcAllocMDC_cleanup;
  129. }
  130. // Allocate memory for metafile handle table.
  131. if (!(pmdc->pmhe = (PMHE) LocalAlloc(LMEM_FIXED, MHT_HANDLE_SIZE * sizeof(MHE))))
  132. goto pmdcAllocMDC_cleanup;
  133. // Initialize the new handles.
  134. // The first entry is reserved and unused.
  135. pmdc->pmhe[0].lhObject = (HANDLE) 0;
  136. pmdc->pmhe[0].metalink.vInit(INVALID_INDEX);
  137. ii = pmdc->imheFree = 1L;
  138. pmdc->cmhe = MHT_HANDLE_SIZE;
  139. for ( ; ii < MHT_HANDLE_SIZE; ii++)
  140. {
  141. pmdc->pmhe[ii].lhObject = (HANDLE) 0;
  142. pmdc->pmhe[ii].metalink.vInit(ii+1);
  143. }
  144. pmdc->pmhe[ii-1].metalink.vInit(INVALID_INDEX);
  145. // Create the first metafile record.
  146. // The description string is part of the header record.
  147. // Get the length of the description string including the NULLs.
  148. PMRMETAFILE pmrmf;
  149. UINT cwszDescription;
  150. if (pwszDescription != (LPWSTR) NULL)
  151. {
  152. for
  153. (
  154. cwszDescription = 0;
  155. pwszDescription[cwszDescription] != (WCHAR) 0
  156. || pwszDescription[cwszDescription + 1] != (WCHAR) 0;
  157. cwszDescription++
  158. )
  159. ; // NULL expression
  160. cwszDescription += 2; // add terminating nulls
  161. if (cwszDescription > 512)
  162. {
  163. WARNING("pmdcAllocMDC: Description string is > 512 chars\n");
  164. }
  165. }
  166. else
  167. cwszDescription = 0;
  168. // Allocate dword aligned structure.
  169. if (!(pmrmf = (PMRMETAFILE) pmdc->pvNewRecord
  170. (SIZEOF_MRMETAFILE(cwszDescription))))
  171. goto pmdcAllocMDC_cleanup;
  172. pmrmf->vInit(hdcRef, pwszDescription, cwszDescription);
  173. // Save a copy of it in the metafile DC.
  174. pmdc->mrmf = *(PENHMETAHEADER) pmrmf;
  175. // Commit it.
  176. pmrmf->vCommit(pmdc);
  177. // If the reference DC has a pixel format selected, record
  178. // it in the metafile
  179. int iPixelFormat;
  180. if ((iPixelFormat = GetPixelFormat(hdcRef)) != 0)
  181. {
  182. PMRPIXELFORMAT pmrpf;
  183. PIXELFORMATDESCRIPTOR pfd;
  184. if (!DescribePixelFormat(hdcRef, iPixelFormat, sizeof(pfd), &pfd))
  185. {
  186. goto pmdcAllocMDC_cleanup;
  187. }
  188. pmrpf = (PMRPIXELFORMAT)pmdc->pvNewRecord(SIZEOF_MRPIXELFORMAT);
  189. if (pmrpf == NULL)
  190. {
  191. goto pmdcAllocMDC_cleanup;
  192. }
  193. pmrpf->vInit(&pfd);
  194. pmrpf->vCommit(pmdc);
  195. }
  196. pmdcRc = pmdc;
  197. // Cleanup and go home.
  198. pmdcAllocMDC_cleanup:
  199. if (!pmdcRc)
  200. if (pmdc)
  201. {
  202. pmdc->fl |= MDC_FATALERROR; // set to delete the disk metafile
  203. vFreeMDC(pmdc);
  204. }
  205. ERROR_ASSERT(pmdcRc, "pmdcAllocMDC failed");
  206. return(pmdcRc);
  207. }
  208. /******************************Public*Routine******************************\
  209. * vFreeMDC (pmdc)
  210. *
  211. * This is a low level routine which frees the resouces in the MDC.
  212. *
  213. * This function is intended to be called from the routine CloseEnhMetaFile.
  214. *
  215. * Arguments:
  216. * pmdc - The MDC to be freed.
  217. *
  218. * History:
  219. * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl]
  220. * Wrote it.
  221. \**************************************************************************/
  222. VOID vFreeMDC(PMDC pmdc)
  223. {
  224. ULONG ii;
  225. PUTS("vFreeMDC\n");
  226. ASSERTGDI(pmdc->ident == MDC_IDENTIFIER, "Bad MDC");
  227. // Free the resources.
  228. if (pmdc->pPalEntries)
  229. {
  230. if (LocalFree(pmdc->pPalEntries))
  231. {
  232. ASSERTGDI(FALSE, "LocalFree failed");
  233. }
  234. }
  235. // Cleanup objects and metalinks.
  236. pmdc->vFreeColorProfileList();
  237. if (pmdc->pmhe)
  238. {
  239. // The first entry is reserved and unused.
  240. for (ii = 1 ; ii < pmdc->cmhe; ii++)
  241. {
  242. if (pmdc->pmhe[ii].lhObject != (HANDLE) 0)
  243. vFreeMHE(pmdc->hdcRef, ii);
  244. }
  245. if (LocalFree(pmdc->pmhe))
  246. {
  247. ASSERTGDI(FALSE, "LocalFree failed");
  248. }
  249. }
  250. if (pmdc->hData)
  251. {
  252. if (pmdc->bIsEMFSpool())
  253. {
  254. pmdc->CompleteEMFData(FALSE);
  255. }
  256. else
  257. {
  258. if (LocalFree(pmdc->hData))
  259. {
  260. ASSERTGDI(FALSE, "LocalFree failed");
  261. }
  262. }
  263. }
  264. if (pmdc->hFile != INVALID_HANDLE_VALUE)
  265. {
  266. if (!CloseHandle(pmdc->hFile))
  267. {
  268. ASSERTGDI(FALSE, "CloseHandle failed");
  269. }
  270. }
  271. // Delete the disk metafile we created if we encountered any fatal error.
  272. if (pmdc->bIsDiskFile() && pmdc->bFatalError())
  273. {
  274. #if DBG
  275. SetLastError(0);
  276. #endif
  277. if (!DeleteFileW(pmdc->wszPathname))
  278. {
  279. #if DBG
  280. DbgPrint("vFreeMDC: DeleteFile failed with error code %ld\n",
  281. GetLastError());
  282. #endif
  283. //
  284. // There are certain conditions causing fatal errors accessing
  285. // files that equally prevent the deletion of the file
  286. // (such as out of quota or pool)
  287. // If we can't delete the file, we can't do anything about it
  288. // anyway - let's not force an ASSERT even on checked builds unless
  289. // we set the debug flags. We will make do with an error message
  290. // and appropriate error code above.
  291. //
  292. ERROR_ASSERT(FALSE, "vFreeMDC: DeleteFile failed");
  293. }
  294. }
  295. // Smash the identifier.
  296. pmdc->ident = 0;
  297. // Free the memory.
  298. if (LocalFree(pmdc))
  299. {
  300. ASSERTGDI(FALSE, "LocalFree failed");
  301. }
  302. }
  303. /******************************Public*Routine******************************\
  304. * pmfAllocMF(fl, pb, pwszFilename)
  305. *
  306. * This routine allocates memory for an MF and initializes it.
  307. * Returns a pointer to the new MF. On error returns NULL.
  308. * It accepts only enhanced metafiles.
  309. *
  310. * This routine is called by API level MF allocation routines CloseEnhMetaFile,
  311. * GetEnhMetaFile, SetEnhMetaFileBits and CopyEnhMetaFile.
  312. *
  313. * Arguments:
  314. * fl - ALLOCMF_TRANSFER_BUFFER is set if storage for memory metafile
  315. * is to be set directly into MF. Otherwise, a copy of the
  316. * memory metafile is duplicated.
  317. * pb - Pointer to a memory metafile if non-null.
  318. * pwszFilename - Filename of a disk metafile if non-null.
  319. *
  320. * History:
  321. * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl]
  322. * Wrote it.
  323. \**************************************************************************/
  324. PMF pmfAllocMF(ULONG fl, CONST UNALIGNED DWORD *pb, LPCWSTR pwszFilename, HANDLE hFile, UINT64 fileOffset, HANDLE hExtra)
  325. {
  326. PMF pmf = NULL;
  327. PMF pmfRc = (PMF) NULL;
  328. PENHMETAHEADER pmrmf = NULL;
  329. PUTS("pmfAllocMF\n");
  330. ASSERTGDI(!(fl & ~ALLOCMF_TRANSFER_BUFFER), "pmfAllocMF: Invalid fl");
  331. // Allocate a new MF.
  332. if (!(pmf = (PMF) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(MF))))
  333. goto pmfAllocMF_cleanup;
  334. // Initialize it.
  335. pmf->ident = MF_IDENTIFIER;
  336. pmf->hFile = INVALID_HANDLE_VALUE;
  337. pmf->hFileMap = NULL;
  338. pmf->pvFileMapping = NULL;
  339. pmf->pvLocalCopy = NULL;
  340. pmf->pEMFSpool = hExtra ? (EMFSpoolData*) hExtra : NULL;
  341. pmf->iMem = 0L;
  342. pmf->pht = (PHANDLETABLE) NULL;
  343. pmf->fl = 0L;
  344. pmf->hdcXform = 0;
  345. // Memory mapped the disk file if given.
  346. if (pwszFilename)
  347. {
  348. pmf->fl |= MF_DISKFILE; // this must be first! See vFreeMF.
  349. LPWSTR pwszFilePart; // not used
  350. UINT64 fileSize;
  351. // Convert the filename to a fully qualified pathname.
  352. DWORD cPathname = GetFullPathNameW(pwszFilename,
  353. MAX_PATH,
  354. pmf->wszPathname,
  355. &pwszFilePart);
  356. if (!cPathname || cPathname > MAX_PATH)
  357. {
  358. ERROR_ASSERT(FALSE, "GetFullPathName failed");
  359. if (cPathname > MAX_PATH)
  360. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  361. goto pmfAllocMF_cleanup;
  362. }
  363. pmf->wszPathname[cPathname] = 0;
  364. if ((pmf->hFile = CreateFileW(pmf->wszPathname, // Filename
  365. GENERIC_READ, // Read access
  366. FILE_SHARE_READ, // Share read
  367. (LPSECURITY_ATTRIBUTES) 0L,// No security
  368. OPEN_EXISTING, // Re-open
  369. 0, // file attributes ignored
  370. (HANDLE) 0)) // no template file
  371. == INVALID_HANDLE_VALUE)
  372. {
  373. ERROR_ASSERT(FALSE, "CreateFile failed");
  374. goto pmfAllocMF_cleanup;
  375. }
  376. if(!GetFileSizeEx(pmf->hFile, (PLARGE_INTEGER) &fileSize))
  377. {
  378. ERROR_ASSERT(FALSE, "GetFileSizeEx failed");
  379. goto pmfAllocMF_cleanup;
  380. }
  381. if(fileSize > (UINT64) 0xFFFFFFFF)
  382. {
  383. ERROR_ASSERT(FALSE, "EMF File too large\n");
  384. goto pmfAllocMF_cleanup;
  385. }
  386. if (!(pmf->hFileMap = CreateFileMappingW(pmf->hFile,
  387. (LPSECURITY_ATTRIBUTES) 0L,
  388. PAGE_READONLY,
  389. 0L,
  390. 0L,
  391. (LPWSTR) NULL)))
  392. {
  393. ERROR_ASSERT(FALSE, "CreateFileMapping failed");
  394. goto pmfAllocMF_cleanup;
  395. }
  396. if (!(pmf->pvFileMapping = (PENHMETAHEADER) MapViewOfFile(pmf->hFileMap, FILE_MAP_READ, 0, 0, 0)))
  397. {
  398. ERROR_ASSERT(FALSE, "MapViewOfFile failed");
  399. goto pmfAllocMF_cleanup;
  400. }
  401. pmf->emfc.Init((PENHMETAHEADER) pmf->pvFileMapping, (UINT32) fileSize);
  402. }
  403. else if (fl & ALLOCMF_TRANSFER_BUFFER)
  404. {
  405. // If this is our memory metafile from MDC, transfer it to MF.
  406. if(pb)
  407. {
  408. pmf->emfc.Init((PENHMETAHEADER) pb, ((PENHMETAHEADER) pb)->nBytes);
  409. // We now own the reference which we must free
  410. pmf->pvLocalCopy = (PVOID) pb;
  411. }
  412. else if(hFile)
  413. {
  414. pmf->emfc.Init(hFile, fileOffset, 0);
  415. // We now own the reference which we must now Close
  416. pmf->hFile = hFile;
  417. }
  418. else
  419. {
  420. ERROR_ASSERT(hFile != NULL, "pmfAllocMF: exepect hHandle or pb to be non-null\n");
  421. goto pmfAllocMF_cleanup;
  422. }
  423. }
  424. else
  425. {
  426. // Otherwise, make a copy of memory metafile.
  427. if (!(pmf->pvLocalCopy = (PENHMETAHEADER) LocalAlloc(LMEM_FIXED, (UINT) ((PENHMETAHEADER) pb)->nBytes)))
  428. goto pmfAllocMF_cleanup;
  429. RtlCopyMemory((PBYTE) pmf->pvLocalCopy, pb, ((PENHMETAHEADER) pb)->nBytes);
  430. pmf->emfc.Init((PENHMETAHEADER) pmf->pvLocalCopy, ((PENHMETAHEADER) pb)->nBytes);
  431. }
  432. // Verify metafile header
  433. pmrmf = pmf->emfc.GetEMFHeader();
  434. if(!pmrmf)
  435. {
  436. WARNING("pmfAllocMF: failed to get emf header\n");
  437. goto pmfAllocMF_cleanup;
  438. }
  439. if (!((PMRMETAFILE) pmrmf)->bValid())
  440. {
  441. ERROR_ASSERT(FALSE,
  442. "pmfAllocMF: Metafile has an invalid header; Failing\n");
  443. goto pmfAllocMF_cleanup;
  444. }
  445. // Allocate and initialize the playback object handle table.
  446. // The first entry of pht is initialized to hemf in PlayEnhMetaFile
  447. // and EnumEnhMetaFile.
  448. if (!(pmf->pht
  449. = (PHANDLETABLE) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
  450. pmrmf->nHandles * sizeof(HANDLE))))
  451. goto pmfAllocMF_cleanup;
  452. // Allocate a virtual device for transform computation.
  453. if (!(pmf->hdcXform = CreateICA((LPCSTR) "DISPLAY",
  454. (LPCSTR) NULL,
  455. (LPCSTR) NULL,
  456. (LPDEVMODEA) NULL)))
  457. {
  458. ERROR_ASSERT(FALSE, "CreateICA failed");
  459. goto pmfAllocMF_cleanup;
  460. }
  461. // The transform DC must be in the advanced graphics mode.
  462. // The world transform can only be set in the advanced graphics mode.
  463. if (!SetGraphicsMode(pmf->hdcXform, GM_ADVANCED))
  464. goto pmfAllocMF_cleanup;
  465. // Everything is golden.
  466. pmfRc = pmf;
  467. // Cleanup and go home.
  468. pmfAllocMF_cleanup:
  469. if (!pmfRc)
  470. if (pmf)
  471. {
  472. if (fl & ALLOCMF_TRANSFER_BUFFER)
  473. pmf->pvLocalCopy = 0; // let caller free the buffer.
  474. vFreeMF(pmf);
  475. }
  476. ERROR_ASSERT(pmfRc, "pmfAllocMF failed");
  477. return(pmfRc);
  478. }
  479. /******************************Public*Routine******************************\
  480. * vFreeMF (pmf)
  481. *
  482. * This is a low level routine which frees the resouces in the MF.
  483. *
  484. * This function is intended to be called from the routines CloseEnhMetaFile
  485. * and DeleteEnhMetaFile.
  486. *
  487. * Arguments:
  488. * pmf - The MF to be freed.
  489. *
  490. * History:
  491. * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl]
  492. * Wrote it.
  493. \**************************************************************************/
  494. VOID vFreeMF(PMF pmf)
  495. {
  496. PUTS("vFreeMF\n");
  497. ASSERTGDI(pmf->ident == MF_IDENTIFIER, "Bad MF");
  498. // Free the resources.
  499. if (pmf->hdcXform)
  500. DeleteDC(pmf->hdcXform);
  501. pmf->emfc.Term();
  502. if (pmf->pht)
  503. {
  504. // Objects created during play are freed in PlayEnhMetaFile and
  505. // EnumEnhMetaFile.
  506. PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
  507. if (pmrmf)
  508. {
  509. for (WORD ii = 1; ii < pmrmf->nHandles; ii++)
  510. {
  511. ASSERTGDI(!pmf->pht->objectHandle[ii],
  512. "vFreeMF: Handle table not empty");
  513. }
  514. }
  515. if (LocalFree(pmf->pht))
  516. {
  517. ASSERTGDI(FALSE, "LocalFree failed");
  518. }
  519. }
  520. if (!pmf->bIsDiskFile())
  521. {
  522. // Free memory metafile.
  523. if (pmf->pvLocalCopy && LocalFree(pmf->pvLocalCopy))
  524. {
  525. ASSERTGDI(FALSE, "LocalFree failed");
  526. }
  527. // If we are spooling, then the spooler needs to deal
  528. // with closing the file handle, otherwise we own it
  529. // and need to close it.
  530. if(!pmf->bIsEMFSpool())
  531. {
  532. if (pmf->hFile != INVALID_HANDLE_VALUE)
  533. {
  534. if (!CloseHandle(pmf->hFile))
  535. {
  536. ASSERTGDI(FALSE, "CloseHandle failed");
  537. }
  538. else
  539. {
  540. pmf->hFile = NULL;
  541. }
  542. }
  543. }
  544. }
  545. else
  546. {
  547. // Unmap disk file.
  548. if (pmf->pvFileMapping && !UnmapViewOfFile(pmf->pvFileMapping))
  549. {
  550. ASSERTGDI(FALSE, "UmmapViewOfFile failed");
  551. }
  552. if (pmf->hFileMap)
  553. {
  554. if (!CloseHandle(pmf->hFileMap))
  555. {
  556. ASSERTGDI(FALSE, "CloseHandle failed");
  557. }
  558. else
  559. {
  560. pmf->hFileMap = NULL;
  561. }
  562. }
  563. if (pmf->hFile != INVALID_HANDLE_VALUE)
  564. {
  565. if (!CloseHandle(pmf->hFile))
  566. {
  567. ASSERTGDI(FALSE, "CloseHandle failed");
  568. }
  569. else
  570. {
  571. pmf->hFile = NULL;
  572. }
  573. }
  574. }
  575. // Smash the identifier.
  576. pmf->ident = 0;
  577. // Free the memory.
  578. if (LocalFree(pmf))
  579. {
  580. ASSERTGDI(FALSE, "LocalFree failed");
  581. }
  582. }
  583. /******************************Public*Routine******************************\
  584. * vFreeMFAlt (pmf, bAllocBuffer)
  585. *
  586. * This is a low level routine which frees the resouces in the MF.
  587. *
  588. * This function is intended to be called from the routines InternalDeleteEnhMetaFile
  589. *
  590. * Arguments:
  591. * pmf - The MF to be freed.
  592. * bAllocBuffer - flag to free buffer
  593. *
  594. \**************************************************************************/
  595. VOID vFreeMFAlt(PMF pmf, BOOL bAllocBuffer)
  596. {
  597. PUTS("vFreeMF\n");
  598. ASSERTGDI(pmf->ident == MF_IDENTIFIER, "Bad MF");
  599. // Free the resources.
  600. if (pmf->hdcXform)
  601. DeleteDC(pmf->hdcXform);
  602. pmf->emfc.Term();
  603. if (pmf->pht)
  604. {
  605. // Objects created during play are freed in PlayEnhMetaFile and
  606. // EnumEnhMetaFile.
  607. PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
  608. if (pmrmf)
  609. {
  610. for (WORD ii = 1; ii < pmrmf->nHandles; ii++)
  611. {
  612. ASSERTGDI(!pmf->pht->objectHandle[ii],
  613. "vFreeMF: Handle table not empty");
  614. }
  615. }
  616. if (LocalFree(pmf->pht))
  617. {
  618. ASSERTGDI(FALSE, "LocalFree failed");
  619. }
  620. }
  621. if (bAllocBuffer)
  622. {
  623. if (!pmf->bIsDiskFile())
  624. {
  625. // Free memory metafile.
  626. if (pmf->pvLocalCopy && LocalFree(pmf->pvLocalCopy))
  627. {
  628. ASSERTGDI(FALSE, "LocalFree failed");
  629. }
  630. if(!pmf->bIsEMFSpool())
  631. {
  632. // If we are spooling, then the spooler needs to deal
  633. // with closing the file handle, otherwise we own it
  634. // and need to close it.
  635. if (pmf->hFile != INVALID_HANDLE_VALUE)
  636. {
  637. if (!CloseHandle(pmf->hFile))
  638. {
  639. ASSERTGDI(FALSE, "CloseHandle failed");
  640. }
  641. else
  642. {
  643. pmf->hFile = NULL;
  644. }
  645. }
  646. }
  647. }
  648. else
  649. {
  650. // Unmap disk file.
  651. if (pmf->pvFileMapping && !UnmapViewOfFile(pmf->pvFileMapping))
  652. {
  653. ASSERTGDI(FALSE, "UmmapViewOfFile failed");
  654. }
  655. if (pmf->hFileMap)
  656. {
  657. if (!CloseHandle(pmf->hFileMap))
  658. {
  659. ASSERTGDI(FALSE, "CloseHandle failed");
  660. }
  661. else
  662. {
  663. pmf->hFileMap = NULL;
  664. }
  665. }
  666. if (pmf->hFile != INVALID_HANDLE_VALUE)
  667. {
  668. if (!CloseHandle(pmf->hFile))
  669. {
  670. ASSERTGDI(FALSE, "CloseHandle failed");
  671. }
  672. else
  673. {
  674. pmf->hFile = NULL;
  675. }
  676. }
  677. }
  678. }
  679. // Smash the identifier.
  680. pmf->ident = 0;
  681. // Free the memory.
  682. if (LocalFree(pmf))
  683. {
  684. ASSERTGDI(FALSE, "LocalFree failed");
  685. }
  686. }
  687. /******************************Public*Routine******************************\
  688. * bMetaResetDC (hdc)
  689. *
  690. * Initialize the destination DC before playing a metafile to that DC.
  691. *
  692. * History:
  693. * Fri Nov 01 15:02:58 1991 -by- Hock San Lee [hockl]
  694. * Wrote it.
  695. \**************************************************************************/
  696. BOOL bMetaResetDC(HDC hdc)
  697. {
  698. // Make sure we do everything
  699. // If the destination is a metafile DC, we want to embed
  700. // the calls made in this function.
  701. POINT ptOrg;
  702. FLOAT eMiterLimit;
  703. // Reset to default objects.
  704. SelectObject(hdc, GetStockObject(WHITE_BRUSH));
  705. SelectObject(hdc, GetStockObject(BLACK_PEN));
  706. SelectObject(hdc, GetStockObject(DEVICE_DEFAULT_FONT));
  707. SelectPalette(hdc,GetStockObject(DEFAULT_PALETTE),TRUE);
  708. // Attributes cache.
  709. SetBkColor(hdc, 0xffffff);
  710. SetTextColor(hdc, 0);
  711. SetTextCharacterExtra(hdc, 0);
  712. SetBkMode(hdc, OPAQUE);
  713. SetPolyFillMode(hdc, ALTERNATE);
  714. SetROP2(hdc, R2_COPYPEN);
  715. SetStretchBltMode(hdc, BLACKONWHITE);
  716. SetTextAlign(hdc, 0);
  717. // Reset server attributes.
  718. // Mapper flags.
  719. // Metafile it only if the previous mapper flags is not default.
  720. if (SetMapperFlagsInternal(hdc, 0) != 0) // if the previous flags is
  721. {
  722. if (SetMapperFlags(hdc, 0) == GDI_ERROR) // not default, set to default
  723. {
  724. ASSERTGDI(FALSE, "SetMapperFlags failed");
  725. }
  726. }
  727. SetBrushOrgEx(hdc, 0, 0, (LPPOINT) NULL);
  728. SetMiterLimit(hdc, 10.0f, (PFLOAT) NULL);
  729. SetTextJustification(hdc, 0, 0);
  730. SetArcDirection(hdc, AD_COUNTERCLOCKWISE);
  731. MoveToEx(hdc, 0, 0, (LPPOINT) NULL);
  732. return(TRUE);
  733. }
  734. /******************************Public*Routine******************************\
  735. * bIsPoly16(pptl, cptl)
  736. *
  737. * Return TRUE if all the points in the poly array are 16-bit signed integers.
  738. * Otherwise, it is FALSE.
  739. *
  740. * History:
  741. * Sat Mar 07 17:07:33 1992 -by- Hock San Lee [hockl]
  742. * Wrote it.
  743. \**************************************************************************/
  744. BOOL bIsPoly16(PPOINTL pptl, DWORD cptl)
  745. {
  746. while (cptl--)
  747. {
  748. if
  749. (
  750. pptl->x < (LONG) (SHORT) MINSHORT
  751. || pptl->x > (LONG) (SHORT) MAXSHORT
  752. || pptl->y < (LONG) (SHORT) MINSHORT
  753. || pptl->y > (LONG) (SHORT) MAXSHORT
  754. )
  755. return(FALSE);
  756. pptl++;
  757. }
  758. return(TRUE);
  759. }
  760. /******************************Public*Routine******************************\
  761. * imheAllocMHE(hdc, lhObject)
  762. *
  763. * Allocates a MHE from the Metafile Handle Table in the metafile DC,
  764. * initializes fields in the MHE, and updates the object's metalink.
  765. * Returns the MHE index or INVALID_INDEX on error.
  766. *
  767. * Since the first entry is reserved, index zero is never returned.
  768. *
  769. * When a object's metalink is first created, a 16-bit metafile object-link
  770. * should be added to the begining of the metafile link as necessary. The
  771. * 16-bit metafile object-link should be removed as necessary when the last
  772. * metalink is deleted.
  773. *
  774. * History:
  775. * Tue Aug 06 15:41:52 1991 -by- Hock San Lee [hockl]
  776. * Wrote it.
  777. \**************************************************************************/
  778. ULONG imheAllocMHE(HDC hdc, HANDLE lhObject)
  779. {
  780. PMDC pmdc = GET_PMDC(hdc);
  781. ULONG imhe = INVALID_INDEX;
  782. ULONG ii;
  783. PMHE pmhe;
  784. // Get critical for handle allocation.
  785. ENTERCRITICALSECTION(&semLocal);
  786. // Make sure a handle is available.
  787. if (pmdc->imheFree == INVALID_INDEX)
  788. {
  789. // Allocate more handles up to the max size.
  790. PMHE pmhe1;
  791. UINT cmhe1;
  792. if (pmdc->cmhe == MHT_MAX_HANDLE_SIZE)
  793. {
  794. ERROR_ASSERT(FALSE, "imheAllocMHE: max handle table size reached");
  795. goto imheAllocMHE_exit;
  796. }
  797. cmhe1 = min((UINT) pmdc->cmhe + MHT_HANDLE_SIZE,
  798. (UINT) MHT_MAX_HANDLE_SIZE);
  799. if (!(pmhe1 = (PMHE) LocalReAlloc
  800. (
  801. pmdc->pmhe,
  802. cmhe1 * sizeof(MHE),
  803. LMEM_MOVEABLE
  804. )
  805. )
  806. )
  807. {
  808. ERROR_ASSERT(FALSE, "LocalReAlloc failed");
  809. goto imheAllocMHE_exit;
  810. }
  811. pmdc->pmhe = pmhe1;
  812. // Initialize the new handles.
  813. ii = pmdc->imheFree = pmdc->cmhe;
  814. pmdc->cmhe = cmhe1;
  815. for ( ; ii < pmdc->cmhe; ii++)
  816. {
  817. pmdc->pmhe[ii].lhObject = (HANDLE) 0;
  818. pmdc->pmhe[ii].metalink.vInit(ii+1);
  819. }
  820. pmdc->pmhe[ii-1].metalink.vInit(INVALID_INDEX);
  821. }
  822. // First, make sure the object has a 16-bit metafile object-link.
  823. // we have this in brackets to reduce scope of pmetalink16
  824. {
  825. METALINK16 *pmetalink16 = pmetalink16Get(lhObject);
  826. if (pmetalink16 == NULL)
  827. {
  828. pmetalink16 = pmetalink16Create(lhObject);
  829. if (pmetalink16 == NULL)
  830. {
  831. ERROR_ASSERT(FALSE, "LocalAlloc failed");
  832. goto imheAllocMHE_exit;
  833. }
  834. ASSERTGDI
  835. (
  836. pmetalink16->metalink == 0
  837. && pmetalink16->cMetaDC16 == 0
  838. && pmetalink16->ahMetaDC16[0] == (HDC) 0,
  839. "imheAllocMHE: METALINK16 not initialized properly"
  840. );
  841. }
  842. imhe = pmdc->imheFree;
  843. pmhe = pmdc->pmhe + imhe;
  844. pmdc->imheFree = (ULONG) pmhe->metalink;
  845. ASSERTGDI(imhe != 0, "imheAllocMHE: index zero is reserved");
  846. ASSERTGDI(pmhe->lhObject == (HANDLE) 0, "imheAllocMHE: imheFree in use");
  847. // Update and add the metalink to the link list.
  848. pmhe->lhObject = lhObject;
  849. pmhe->metalink.vInit(pmetalink16->metalink);
  850. ((PMETALINK) &pmetalink16->metalink)->vInit((USHORT) imhe, H_INDEX(hdc));
  851. }
  852. imheAllocMHE_exit:
  853. // Leave the critical section.
  854. LEAVECRITICALSECTION(&semLocal);
  855. return(imhe);
  856. }
  857. /******************************Public*Routine******************************\
  858. * vFreeMHE(hdc, imhe)
  859. *
  860. * Free up a MHE and insert it into the Metafile Handle Table free list.
  861. * It also updates the object's metalink.
  862. *
  863. * When the last metalink is removed, the 16-bit metafile object-link should
  864. * also be removed if it is not used.
  865. *
  866. * History:
  867. * Tue Aug 06 15:41:52 1991 -by- Hock San Lee [hockl]
  868. * Wrote it.
  869. \**************************************************************************/
  870. VOID vFreeMHE(HDC hdc, ULONG imhe)
  871. {
  872. PMETALINK16 pmetalink16;
  873. PMDC pmdc = GET_PMDC(hdc);
  874. HANDLE hobj;
  875. ASSERTGDI(imhe != 0, "vFreeMHE: index zero is reserved");
  876. // Get critical for handle deallocation.
  877. ENTERCRITICALSECTION(&semLocal);
  878. // Remove it from the object metalink friend list.
  879. hobj = pmdc->pmhe[imhe].lhObject;
  880. pmetalink16 = pmetalink16Get(hobj);
  881. ASSERTGDI(pmetalink16, "vFreeMHE: pmetalink16 Invalid");
  882. METALINK metalink(pmetalink16);
  883. ASSERTGDI(metalink.bValid(), "vFreeMHE: Invalid imhe");
  884. if (metalink.bEqual((USHORT) imhe, H_INDEX(hdc)))
  885. {
  886. pmetalink16->metalink = (ULONG) pmdc->pmhe[imhe].metalink;
  887. }
  888. else
  889. {
  890. while (!(metalink.pmetalinkNext())->bEqual((USHORT) imhe, H_INDEX(hdc)))
  891. {
  892. metalink.vNext();
  893. ASSERTGDI(metalink.bValid(), "vFreeMHE: Invalid imhe");
  894. }
  895. *(metalink.pmetalinkNext()) = pmdc->pmhe[imhe].metalink;
  896. }
  897. // Add the handle to the free list.
  898. pmdc->pmhe[imhe].lhObject = (HANDLE) 0;
  899. pmdc->pmhe[imhe].metalink.vInit(pmdc->imheFree);
  900. pmdc->imheFree = imhe;
  901. // If there is no more metalink, remove the 16-bit metafile object-link
  902. // if it's not used.
  903. if (!pmetalink16->metalink
  904. && !pmetalink16->cMetaDC16)
  905. {
  906. if (!bDeleteMetalink16(hobj))
  907. {
  908. ASSERTGDI(FALSE, "LocalFree failed");
  909. }
  910. }
  911. // Leave the critical section.
  912. LEAVECRITICALSECTION(&semLocal);
  913. }
  914. /******************************Public*Routine******************************\
  915. * GdiConvertMetaFilePict
  916. * GdiConvertEnhMetaFile
  917. *
  918. * A server handle is created that is an exact copy of the client
  919. * MetaFilePict or EnhMetaFile data. The caller (clipbrd) is responsible
  920. * for deleting both the client and server copies when they are no longer
  921. * needed.
  922. *
  923. * A MetaFilePict is a structure containing a metafile size and a handle
  924. * to a metafile. Both MetaFilePict and EnhMetaFile are used primarily by
  925. * the clipboard interface. When an app puts a MetaFilePict or an
  926. * EnhMetaFile in the clipboard we have to create a server copy because
  927. * the app can terminate and another application can still query the
  928. * clipboard data.
  929. *
  930. * The format for the client-server data is as follows:
  931. *
  932. * DWORD iType MFEN_IDENTIFIER or MFPICT_IDENTIFIER
  933. * DWORD mm used by MetaFilePict only
  934. * DWORD xExt used by MetaFilePict only
  935. * DWORD yExt used by MetaFilePict only
  936. * DWORD nBytes number of bytes in pClientData
  937. * PBYTE pClientData contains the metafile bits
  938. *
  939. * Returns a server handle that is a copy of the metafile data.
  940. * Returns zero if an error occurs.
  941. *
  942. * History:
  943. * Wed Sep 16 09:42:22 1992 -by- Hock San Lee [hockl]
  944. * Rewrote it.
  945. * 28-Oct-1991 -by- John Colleran [johnc]
  946. * Wrote it.
  947. \**************************************************************************/
  948. HANDLE GdiConvertMetaFilePict(HANDLE hmem)
  949. {
  950. HANDLE hRet = (HANDLE) 0;
  951. PMETAFILE16 pmf16;
  952. LPMETAFILEPICT lpmfp;
  953. PUTS("GdiConvertMetaFilePict\n");
  954. // Get the METAFILEPICT
  955. lpmfp = (LPMETAFILEPICT) GlobalLock(hmem);
  956. if (!lpmfp)
  957. {
  958. WARNING("GdiConvertMetaFilePict GlobalLock(hmem) Failed\n");
  959. return((HANDLE) 0);
  960. }
  961. pmf16 = GET_PMF16(lpmfp->hMF);
  962. // Validate the hmf field of the METAFILEPICT
  963. if (pmf16 == NULL)
  964. {
  965. WARNING("GdiConvertMetaFilePict invalid handle\n");
  966. GdiSetLastError(ERROR_INVALID_HANDLE);
  967. goto GCMFP_Exit;
  968. }
  969. // Get the size of the metafile.
  970. ASSERTGDI(IsValidMetaHeader16(&pmf16->metaHeader),
  971. "GdiConvertMetaFilePict: Bad metafile");
  972. hRet = NtGdiCreateServerMetaFile(MFPICT_IDENTIFIER,
  973. pmf16->metaHeader.mtSize * sizeof(WORD), (PBYTE) pmf16->hMem,
  974. lpmfp->mm, lpmfp->xExt, lpmfp->yExt);
  975. GCMFP_Exit:
  976. GlobalUnlock(hmem);
  977. ERROR_ASSERT(hRet, "GdiConvertMetaFilePict failed\n");
  978. return(hRet);
  979. }
  980. HANDLE GdiConvertEnhMetaFile(HENHMETAFILE hemf)
  981. {
  982. HANDLE hRet;
  983. PMF pmf;
  984. PUTS("GdiConvertEnhMetaFile\n");
  985. if (!(pmf = GET_PMF(hemf)))
  986. {
  987. WARNING("GdiConvertEnhMetaFile: bad hemf\n");
  988. return((HMETAFILE) 0);
  989. }
  990. PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
  991. if(!pmrmf)
  992. {
  993. WARNING("GdiConvertEnhMetaFile: failed getting header\n");
  994. return((HMETAFILE) 0);
  995. }
  996. PBYTE pb = (PBYTE) pmf->emfc.ObtainPtr(0, pmrmf->nBytes);
  997. if(!pb)
  998. {
  999. WARNING("GdiConvertEnhMetaFile: failed getting data\n");
  1000. return((HMETAFILE) 0);
  1001. }
  1002. hRet = NtGdiCreateServerMetaFile(MFEN_IDENTIFIER, pmrmf->nBytes,
  1003. pb, 0, 0, 0);
  1004. pmf->emfc.ReleasePtr(pb);
  1005. ERROR_ASSERT(hRet, "GdiConvertEnhMetaFile failed");
  1006. return((HMETAFILE) hRet);
  1007. }
  1008. /******************************Public*Routine******************************\
  1009. * GdiCreateLocalMetaFilePict
  1010. * GdiCreateLocalEnhMetaFile
  1011. *
  1012. * Creates a local MetaFilePict or EnhMetaFile handle that is a copy of
  1013. * the server handle. The server handle can be either a standard metafile
  1014. * or an enhanced metafile. The functions will perform metafile conversion
  1015. * to the requested format (MetaFilePict or EnhMetaFile) if necessary.
  1016. *
  1017. * The caller is responsible for deleting the local handle when it is no
  1018. * longer needed. By Windows convention the app that recieves the
  1019. * MetaFilePict will delete it by first deleting the metafile and then
  1020. * freeing the global handle
  1021. *
  1022. * The format for the client-server data is as follows:
  1023. *
  1024. * HANDLE hSrv server handle (can be standard or enhanced metafile)
  1025. * DWORD iType return MFPICT_IDENTIFIER or MFEN_IDENTIFIER
  1026. * DWORD mm return by MetaFilePict only
  1027. * DWORD xExt return by MetaFilePict only
  1028. * DWORD yExt return by MetaFilePict only
  1029. * DWORD nBytes zero to query size of metafile bits in pClientData.
  1030. * otherwise it is the size of pClientData that is to
  1031. * receive the metafile bits.
  1032. * PBYTE pClientData to receive the metafile bits
  1033. *
  1034. * Returns a client MetaFilePict or EnhMetaFile handle that is a copy of
  1035. * the server metafile. Returns zero if an error occurs
  1036. *
  1037. * History:
  1038. * Wed Sep 16 09:42:22 1992 -by- Hock San Lee [hockl]
  1039. * Rewrote it.
  1040. * 28-Oct-1991 -by- John Colleran [johnc]
  1041. * Wrote it.
  1042. \**************************************************************************/
  1043. HANDLE GdiCreateLocalMetaFilePict(HANDLE hSrv)
  1044. {
  1045. return(InternalCreateLocalMetaFile(hSrv, MFPICT_IDENTIFIER));
  1046. }
  1047. HENHMETAFILE GdiCreateLocalEnhMetaFile(HANDLE hSrv)
  1048. {
  1049. return((HENHMETAFILE) InternalCreateLocalMetaFile((HANDLE) hSrv, MFEN_IDENTIFIER));
  1050. }
  1051. ULONG GetServerMetaFileBits(HANDLE hSrv, DWORD nBytes, PBYTE pMFBits,
  1052. PDWORD piType, PDWORD pmm, PDWORD pxExt, PDWORD pyExt)
  1053. {
  1054. ULONG cRet = 0;
  1055. PUTS("GetServerMetaFileBits\n");
  1056. cRet = NtGdiGetServerMetaFileBits(
  1057. hSrv,
  1058. (ULONG)nBytes,
  1059. (LPBYTE)pMFBits,
  1060. piType,
  1061. pmm,
  1062. pxExt,
  1063. pyExt);
  1064. return(cRet);
  1065. }
  1066. HANDLE InternalCreateLocalMetaFile(HANDLE hSrv, DWORD iTypeReq)
  1067. {
  1068. DWORD iTypeSrv;
  1069. DWORD mm;
  1070. DWORD xExt;
  1071. DWORD yExt;
  1072. ULONG cbData;
  1073. PBYTE pData = (PBYTE) NULL;
  1074. LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) NULL;
  1075. HANDLE hRet = (HANDLE) 0;
  1076. ASSERTGDI(iTypeReq == MFEN_IDENTIFIER || iTypeReq == MFPICT_IDENTIFIER,
  1077. "InternalCreateLocalMetaFile: bad metafile type\n");
  1078. if (!hSrv)
  1079. {
  1080. VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: hSrv is 0");
  1081. return((HANDLE) 0);
  1082. }
  1083. // Get the size of the server metafile bits.
  1084. cbData = GetServerMetaFileBits(hSrv, 0, (PBYTE) NULL, (PDWORD) NULL,
  1085. (PDWORD) NULL, (PDWORD) NULL, (PDWORD) NULL);
  1086. if (!cbData)
  1087. {
  1088. ASSERTGDI(FALSE, "InternalCreateLocalMetaFile: size query failed");
  1089. return((HANDLE) 0);
  1090. }
  1091. // Allocate a buffer to retrieve the metafile bits.
  1092. pData = (PBYTE) LocalAlloc(LMEM_FIXED, (UINT) cbData);
  1093. if (!pData)
  1094. return((HANDLE) 0);
  1095. // Retrieve the server metafile bits.
  1096. if (GetServerMetaFileBits(hSrv, cbData, pData, &iTypeSrv, &mm, &xExt, &yExt)
  1097. != cbData)
  1098. {
  1099. ASSERTGDI(FALSE, "InternalCreateLocalMetaFile: not all data returned");
  1100. goto ICLMF_exit;
  1101. }
  1102. // Allocate the MetaFilePict structure if necessary.
  1103. if (iTypeReq == MFPICT_IDENTIFIER)
  1104. {
  1105. lpmfp = (LPMETAFILEPICT) GlobalAlloc(GMEM_FIXED, sizeof(METAFILEPICT));
  1106. if (!lpmfp)
  1107. {
  1108. VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: GlobalAlloc failed\n");
  1109. goto ICLMF_exit;
  1110. }
  1111. }
  1112. // Create the same type of metafile as requested.
  1113. switch (iTypeSrv)
  1114. {
  1115. case MFEN_IDENTIFIER:
  1116. if (iTypeReq == MFPICT_IDENTIFIER)
  1117. {
  1118. UINT cbMeta16;
  1119. LPBYTE lpMeta16;
  1120. HDC hdcICScreen;
  1121. HENHMETAFILE hemf;
  1122. PENHMETAHEADER pEMH = (PENHMETAHEADER) pData;
  1123. PUTS("InternalCreateLocalMetaFile: EMF -> MFPICT\n");
  1124. lpmfp->mm = MM_ANISOTROPIC;
  1125. lpmfp->xExt = (DWORD) (pEMH->rclFrame.right - pEMH->rclFrame.left);
  1126. lpmfp->yExt = (DWORD) (pEMH->rclFrame.bottom - pEMH->rclFrame.top );
  1127. if (hemf = SetEnhMetaFileBitsAlt((HLOCAL) pData, NULL, NULL, 0))
  1128. pData = (PBYTE) NULL; // pData has been moved to the metafile
  1129. else
  1130. VERIFYGDI(hemf, "InternalCreateLocalMetaFile: SetEnhMetaFileBitsAlt failed");
  1131. hdcICScreen = CreateICA((LPCSTR)"DISPLAY", (LPCSTR)NULL,
  1132. (LPCSTR)NULL, (LPDEVMODEA)NULL);
  1133. VERIFYGDI(hdcICScreen, "InternalCreateLocalMetaFile: CreateICA failed");
  1134. cbMeta16 = GetWinMetaFileBits(hemf, 0, (LPBYTE) NULL,
  1135. MM_ANISOTROPIC, hdcICScreen);
  1136. if (cbMeta16)
  1137. {
  1138. lpMeta16 = (PBYTE) LocalAlloc(LMEM_FIXED, cbMeta16);
  1139. if (lpMeta16)
  1140. {
  1141. if ((GetWinMetaFileBits(hemf, cbMeta16, lpMeta16, MM_ANISOTROPIC, hdcICScreen)
  1142. != cbMeta16)
  1143. // use the memory handle for the metafile!
  1144. || !(lpmfp->hMF = SetMetaFileBitsAlt((HLOCAL) lpMeta16)))
  1145. {
  1146. VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: SetMetaFileBitsAlt failed");
  1147. LocalFree((HANDLE) lpMeta16);
  1148. }
  1149. else
  1150. hRet = (HANDLE) lpmfp;
  1151. }
  1152. }
  1153. DeleteEnhMetaFile(hemf);
  1154. DeleteDC(hdcICScreen);
  1155. }
  1156. else
  1157. {
  1158. PUTS("InternalCreateLocalMetaFile: EMF -> EMF\n");
  1159. if (hRet = (HANDLE) SetEnhMetaFileBitsAlt((HLOCAL) pData, NULL, NULL, 0))
  1160. pData = (PBYTE) NULL; // pData has been moved to the metafile
  1161. else
  1162. {
  1163. VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: SetEnhMetaFileBitsAlt failed");
  1164. }
  1165. }
  1166. break;
  1167. case MFPICT_IDENTIFIER:
  1168. if (iTypeReq == MFPICT_IDENTIFIER)
  1169. {
  1170. PUTS("InternalCreateLocalMetaFile: MFPICT -> MFPICT\n");
  1171. lpmfp->mm = mm;
  1172. lpmfp->xExt = xExt;
  1173. lpmfp->yExt = yExt;
  1174. if (lpmfp->hMF = SetMetaFileBitsAlt((HLOCAL) pData))
  1175. {
  1176. pData = (PBYTE) NULL; // pData has been moved to the metafile
  1177. hRet = (HANDLE) lpmfp;
  1178. }
  1179. else
  1180. VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: SetMetaFileBitsAlt failed");
  1181. }
  1182. else
  1183. {
  1184. METAFILEPICT mfp;
  1185. PUTS("InternalCreateLocalMetaFile: MFPICT -> EMF\n");
  1186. mfp.mm = mm;
  1187. mfp.xExt = xExt;
  1188. mfp.yExt = yExt;
  1189. mfp.hMF = (HMETAFILE) 0;
  1190. hRet = (HANDLE) SetWinMetaFileBits((UINT) cbData, pData, (HDC) 0, &mfp);
  1191. VERIFYGDI(hRet, "InternalCreateLocalMetaFile: SetWinMetaFileBits failed");
  1192. }
  1193. break;
  1194. default:
  1195. ASSERTGDI(FALSE, "InternalCreateLocalMetaFile unknown metafile type\n");
  1196. break;
  1197. }
  1198. // Cleanup if we failed
  1199. ICLMF_exit:
  1200. if (!hRet && lpmfp)
  1201. {
  1202. if (GlobalFree((HANDLE) lpmfp))
  1203. {
  1204. ASSERTGDI(FALSE, "InternalCreateLocalMetaFile: GlobalFree failed");
  1205. }
  1206. }
  1207. if (pData)
  1208. {
  1209. LocalFree((HANDLE) pData);
  1210. }
  1211. ERROR_ASSERT(hRet, "InternalCreateLocalMetaFile failed");
  1212. return(hRet);
  1213. }
  1214. /******************************Public*Routine******************************\
  1215. * GetRandomRgnBounds
  1216. *
  1217. * Wrote it.
  1218. * Fri Jul 24 09:35:24 1992 -by- Hock San Lee [hockl]
  1219. \**************************************************************************/
  1220. BOOL APIENTRY GetRandomRgnBounds(HDC hdc,PRECTL prcl,INT iType)
  1221. {
  1222. BOOL bRet = FALSE;
  1223. HRGN hrgnTmp;
  1224. // We should be able to get the region handle without creating a copy!
  1225. // Make a copy of the specified clip region.
  1226. if (!(hrgnTmp = CreateRectRgn(0, 0, 0, 0)))
  1227. return(bRet);
  1228. switch (GetRandomRgn(hdc, hrgnTmp, (int) iType))
  1229. {
  1230. case -1: // error
  1231. WARNING("GetRandomRgn failed");
  1232. break;
  1233. case 0: // no initial clip region
  1234. *prcl = rclInfinity;
  1235. bRet = TRUE;
  1236. break;
  1237. case 1: // has initial clip region
  1238. bRet = (GetRgnBox(hrgnTmp, (LPRECT) prcl) != RGN_ERROR);
  1239. break;
  1240. }
  1241. if (!DeleteObject(hrgnTmp))
  1242. {
  1243. ASSERTGDI(FALSE, "DeleteObject failed");
  1244. }
  1245. return(bRet);
  1246. }
  1247. /**************************************************************************\
  1248. *
  1249. * misc statistics
  1250. *
  1251. \**************************************************************************/
  1252. #if DBG
  1253. ULONG gcMetalinks = 0;
  1254. ULONG gcQueries = 0;
  1255. ULONG gcQueriesExtra = 0;
  1256. ULONG gcHits = 0;
  1257. #define INC_QUERIES (++gcQueries)
  1258. #define INC_QUERIESX (++gcQueries)
  1259. #define INC_HITS (++gcHits)
  1260. #define INC_LINKS (++gcMetalinks)
  1261. #define DEC_LINKS (--gcMetalinks,++gcHits)
  1262. BOOL gbdbgml = 0;
  1263. #else
  1264. #define gbdbgml FALSE
  1265. #define INC_QUERIES
  1266. #define INC_QUERIESX
  1267. #define INC_HITS
  1268. #define INC_LINKS
  1269. #define DEC_LINKS
  1270. #endif
  1271. /******************************Public*Routine******************************\
  1272. * PLINK plinkGet()
  1273. *
  1274. * This routine locks semLocal critical section while traversing the table.
  1275. *
  1276. * History:
  1277. * 14-Nov-1994 -by- Eric Kutter [erick]
  1278. * Wrote it.
  1279. \**************************************************************************/
  1280. PLINK plinkGet(
  1281. HANDLE h
  1282. )
  1283. {
  1284. PLINK plink = NULL;
  1285. // see if we need to search. We do a quick test before entering the critical
  1286. // section to see if the cache entry is empty. For cases where the entry is
  1287. // not in the cache, the entry will usualy be empty. We need to recheck the
  1288. // value once we are in the critical section to make sure it hasn't gone away
  1289. if (h && aplHash[LINK_HASH_INDEX(h)])
  1290. {
  1291. INC_QUERIES;
  1292. ENTERCRITICALSECTION(&semLocal);
  1293. plink = aplHash[LINK_HASH_INDEX(h)];
  1294. while (plink && DIFFHANDLE(plink->hobj,h))
  1295. {
  1296. INC_QUERIESX;
  1297. plink = plink->plinkNext;
  1298. }
  1299. LEAVECRITICALSECTION(&semLocal);
  1300. if (plink)
  1301. {
  1302. INC_HITS;
  1303. }
  1304. }
  1305. #if DBG
  1306. if (gbdbgml)
  1307. DbgPrint("plinkGet(%p) = %p, ihash = %ld\n",
  1308. h,plink,
  1309. LINK_HASH_INDEX(h));
  1310. #endif
  1311. return(plink);
  1312. }
  1313. /******************************Public*Routine******************************\
  1314. * PLINK plinkCreate()
  1315. *
  1316. * Note that this does not need to grab semLocal. All callers must already
  1317. * have done that.
  1318. *
  1319. * History:
  1320. * 14-Nov-1994 -by- Eric Kutter [erick]
  1321. * Wrote it.
  1322. \**************************************************************************/
  1323. PLINK plinkCreate(
  1324. HANDLE h,
  1325. ULONG ulSize
  1326. )
  1327. {
  1328. PLINK plink = (PLINK)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,ulSize);
  1329. if (plink)
  1330. {
  1331. INC_LINKS;
  1332. plink->plinkNext = aplHash[LINK_HASH_INDEX(h)];
  1333. plink->hobj = h;
  1334. aplHash[LINK_HASH_INDEX(h)] = plink;
  1335. }
  1336. #if DBG
  1337. if (gbdbgml)
  1338. DbgPrint("plinkCreate(%p) = %p, ihash = %ld\n",
  1339. h,plink,
  1340. LINK_HASH_INDEX(h));
  1341. #endif
  1342. return(plink);
  1343. }
  1344. /******************************Public*Routine******************************\
  1345. * BOOL bDeletelink()
  1346. *
  1347. * This routine locks semLocal critical section while traversing the table.
  1348. *
  1349. * History:
  1350. * 14-Nov-1994 -by- Eric Kutter [erick]
  1351. * Wrote it.
  1352. \**************************************************************************/
  1353. BOOL bDeleteLink(
  1354. HANDLE h
  1355. )
  1356. {
  1357. BOOL bSuccess = FALSE;
  1358. PLINK plink = NULL;
  1359. if (h)
  1360. {
  1361. ENTERCRITICALSECTION(&semLocal);
  1362. plink = aplHash[LINK_HASH_INDEX(h)];
  1363. if (plink)
  1364. {
  1365. INC_QUERIES;
  1366. // see if it is the first on the list.
  1367. if (SAMEHANDLE(plink->hobj,h))
  1368. {
  1369. aplHash[LINK_HASH_INDEX(h)] = plink->plinkNext;
  1370. bSuccess = TRUE;
  1371. DEC_LINKS;
  1372. }
  1373. else
  1374. {
  1375. // it isn't the first so lets run the list. We know pmetalink16 is
  1376. // valid and that it is not the element
  1377. while (plink->plinkNext)
  1378. {
  1379. INC_QUERIESX;
  1380. if (SAMEHANDLE(plink->plinkNext->hobj,h))
  1381. {
  1382. PLINK plinkDel = plink->plinkNext;
  1383. plink->plinkNext = plinkDel->plinkNext;
  1384. plink = plinkDel; // so we can delete it.
  1385. bSuccess = TRUE;
  1386. DEC_LINKS;
  1387. break;
  1388. }
  1389. plink = plink->plinkNext;
  1390. }
  1391. }
  1392. }
  1393. LEAVECRITICALSECTION(&semLocal);
  1394. if (bSuccess)
  1395. LocalFree(plink);
  1396. }
  1397. #if DBG
  1398. if (gbdbgml)
  1399. DbgPrint("bDeleteLink(%p) = %p, ihash = %ld\n",
  1400. h,plink,
  1401. LINK_HASH_INDEX(h));
  1402. #endif
  1403. return(bSuccess);
  1404. }
  1405. /******************************Public*Routine******************************\
  1406. * PMETALINK16 pmetalink16Resize()
  1407. *
  1408. * This routine locks semLocal critical section while traversing the table.
  1409. *
  1410. * History:
  1411. * 14-Nov-1994 -by- Eric Kutter [erick]
  1412. * Wrote it.
  1413. \**************************************************************************/
  1414. PMETALINK16 pmetalink16Resize(
  1415. HANDLE h,
  1416. int cObj
  1417. )
  1418. {
  1419. PMETALINK16 pmetalink16 = NULL;
  1420. int cj = sizeof(METALINK16) + sizeof(HDC) * (cObj-1);
  1421. if (h)
  1422. {
  1423. ENTERCRITICALSECTION(&semLocal);
  1424. pmetalink16 = (PMETALINK16)aplHash[LINK_HASH_INDEX(h)];
  1425. if (pmetalink16)
  1426. {
  1427. INC_QUERIES;
  1428. // see if it is the first on the list.
  1429. if (SAMEHANDLE(pmetalink16->hobj,h))
  1430. {
  1431. pmetalink16 = (PMETALINK16)LocalReAlloc(pmetalink16,cj,LMEM_MOVEABLE);
  1432. if (pmetalink16)
  1433. aplHash[LINK_HASH_INDEX(h)] = (PLINK)pmetalink16;
  1434. }
  1435. else
  1436. {
  1437. // it isn't the first so lets run the list. We know pmetalink16 is
  1438. // valid and that it is not the element
  1439. while (pmetalink16->pmetalink16Next)
  1440. {
  1441. INC_QUERIESX;
  1442. if (SAMEHANDLE(pmetalink16->pmetalink16Next->hobj,h))
  1443. {
  1444. PMETALINK16 ptmpmetalink16;
  1445. ptmpmetalink16 = (PMETALINK16)LocalReAlloc(
  1446. pmetalink16->pmetalink16Next,cj,LMEM_MOVEABLE);
  1447. if (ptmpmetalink16)
  1448. {
  1449. pmetalink16->pmetalink16Next = ptmpmetalink16;
  1450. pmetalink16 = pmetalink16->pmetalink16Next;
  1451. }
  1452. else
  1453. {
  1454. pmetalink16 = ptmpmetalink16;
  1455. }
  1456. break;
  1457. }
  1458. pmetalink16 = pmetalink16->pmetalink16Next;
  1459. }
  1460. }
  1461. }
  1462. LEAVECRITICALSECTION(&semLocal);
  1463. }
  1464. #if DBG
  1465. if (gbdbgml)
  1466. DbgPrint("pmetalink16Resize(%p) = %p, ihash = %ld\n",
  1467. h,pmetalink16,
  1468. aplHash[LINK_HASH_INDEX(h)]);
  1469. #endif
  1470. return(pmetalink16);
  1471. }
  1472. /******************************Public*Routine******************************\
  1473. *
  1474. * History:
  1475. * 03-Aug-1995 -by- Eric Kutter [erick]
  1476. * Wrote it.
  1477. \**************************************************************************/
  1478. PMDC pmdcGetFromHdc(
  1479. HDC hdc)
  1480. {
  1481. PLDC pldc = pldcGet(hdc);
  1482. return((PMDC)(pldc ? pldc->pvPMDC : NULL));
  1483. }
  1484. /******************************Public*Routine******************************\
  1485. * HANDLE hCreateClientObjLink()
  1486. *
  1487. * ClientObjLinks are just associations of a server handle with a client pointer.
  1488. *
  1489. * History:
  1490. * 17-Jan-1995 -by- Eric Kutter [erick]
  1491. * Wrote it.
  1492. \**************************************************************************/
  1493. HANDLE hCreateClientObjLink(
  1494. PVOID pv,
  1495. ULONG ulType)
  1496. {
  1497. HANDLE h = CreateClientObj(ulType);
  1498. if (h)
  1499. {
  1500. PLINK plink;
  1501. ENTERCRITICALSECTION(&semLocal);
  1502. plink = plinkCreate(h,sizeof(LINK));
  1503. LEAVECRITICALSECTION(&semLocal);
  1504. if (plink)
  1505. {
  1506. plink->pv = pv;
  1507. }
  1508. else
  1509. {
  1510. DeleteClientObj(h);
  1511. h = NULL;
  1512. }
  1513. }
  1514. #if DBG
  1515. if (gbdbgml)
  1516. DbgPrint("hCreateClientObjLink = %p\n",h);
  1517. #endif
  1518. return(h);
  1519. }
  1520. /******************************Public*Routine******************************\
  1521. * PVOID pvClientObjGet()
  1522. *
  1523. * Given a handle, find the client pv field of the client object. The GRE
  1524. * type of the handle will be CLIENTOBJ_TYPE.
  1525. *
  1526. * History:
  1527. * 18-Jan-1995 -by- Eric Kutter [erick]
  1528. * Wrote it.
  1529. \**************************************************************************/
  1530. PVOID pvClientObjGet(
  1531. HANDLE h,
  1532. DWORD dwLoType)
  1533. {
  1534. if (LO_TYPE(h) == dwLoType)
  1535. {
  1536. PLINK plink = plinkGet(h);
  1537. #if DBG
  1538. if (gbdbgml)
  1539. DbgPrint("pvClientObjGet(%p) = %p\n",h,plink ? plink->pv : NULL);
  1540. #endif
  1541. if (plink)
  1542. {
  1543. return(plink->pv);
  1544. }
  1545. }
  1546. else
  1547. {
  1548. WARNING1("pvClientObjGet (metafile stuff) - invalid handle\n");
  1549. }
  1550. GdiSetLastError(ERROR_INVALID_HANDLE);
  1551. return(NULL);
  1552. }
  1553. /******************************Public*Routine******************************\
  1554. * BOOL bDeleteClientObjLink()
  1555. *
  1556. *
  1557. * History:
  1558. * 18-Jan-1995 -by- Eric Kutter [erick]
  1559. * Wrote it.
  1560. \**************************************************************************/
  1561. BOOL bDeleteClientObjLink(
  1562. HANDLE h)
  1563. {
  1564. #if DBG
  1565. if (gbdbgml)
  1566. DbgPrint("bDeleteClientObjLink = %p\n",h);
  1567. #endif
  1568. if (bDeleteLink(h))
  1569. {
  1570. DeleteClientObj(h);
  1571. return(TRUE);
  1572. }
  1573. else
  1574. {
  1575. return(FALSE);
  1576. }
  1577. }