|
|
/******************************Module*Header*******************************\
* Module Name: metasup.cxx * * Includes metafile support functions. * * Created: 17-July-1991 10:10:36 * Author: Hock San Lee [hockl] * * Copyright (c) 1991-1999 Microsoft Corporation \**************************************************************************/
#define NO_STRICT
extern "C" { #if defined(_GDIPLUS_)
#include <gpprefix.h>
#endif
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stddef.h>
#include <windows.h> // GDI function declarations.
#include <winerror.h>
#include "firewall.h"
#define __CPLUSPLUS
#include <winspool.h>
#include <w32gdip.h>
#include "ntgdistr.h"
#include "winddi.h"
#include "hmgshare.h"
#include "icm.h"
#include "local.h" // Local object support.
#include "gdiicm.h"
#include "metadef.h" // Metafile record type constants.
#include "mf16.h"
#include "ntgdi.h"
}
#include "rectl.hxx"
#include "mfdc.hxx" // Metafile DC class declarations.
#include "mfrec.hxx" // Metafile record class declarations.
extern "C" { HANDLE InternalCreateLocalMetaFile(HANDLE hSrv, DWORD iTypeReq); DWORD SetMapperFlagsInternal(HDC hdc,DWORD fl); }
PLINK aplHash[LINK_HASH_SIZE] = {0};
/******************************Public*Routine******************************\
* pmdcAllocMDC(hdcRef, pszFilename, pwszDescription) * * This routine allocates memory for an MDC and initializes it. It creates * a disk file if necessary. Returns a pointer to the new MDC. On error * returns NULL. * * This routine is called by API level DC allocation routines CreateEnhMetaFile. * * History: * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
PMDC pmdcAllocMDC(HDC hdcRef, LPCWSTR pwszFilename, LPCWSTR pwszDescription, HANDLE hEMFSpool) { PMDC pmdc, pmdcRc = (PMDC) NULL; ULONG ii;
PUTS("pmdcAllocMDC\n");
// Allocate a new MDC.
if (!(pmdc = (PMDC) LocalAlloc(LMEM_FIXED, sizeof(MDC)))) goto pmdcAllocMDC_cleanup;
// Initialize it.
pmdc->ident = MDC_IDENTIFIER; pmdc->hFile = INVALID_HANDLE_VALUE; pmdc->hData = NULL; pmdc->nMem = MF_BUFSIZE_INIT; pmdc->iMem = 0L; pmdc->fl = 0L; pmdc->pmhe = (PMHE) NULL; pmdc->cPalEntries = 0L; pmdc->iPalEntries = 0L; pmdc->pPalEntries = (PPALETTEENTRY) NULL; // allocate as needed
pmdc->erclMetaBounds = rclInfinity; // default clipping bounds
pmdc->erclClipBounds = rclInfinity; pmdc->hdcRef = hdcRef; pmdc->exFontScale(0.0f); pmdc->eyFontScale(0.0f); pmdc->vInitColorProfileList();
// Create a disk file if given. The filename is given in unicode.
if (pwszFilename) { LPWSTR pwszFilePart; // not used
// Convert the filename to a fully qualified pathname.
DWORD cPathname = GetFullPathNameW(pwszFilename, MAX_PATH, pmdc->wszPathname, &pwszFilePart);
if (!cPathname || cPathname > MAX_PATH) { ERROR_ASSERT(FALSE, "GetFullPathName failed"); if (cPathname > MAX_PATH) GdiSetLastError(ERROR_FILENAME_EXCED_RANGE); goto pmdcAllocMDC_cleanup; } pmdc->wszPathname[cPathname] = 0;
// Create the file.
if ((pmdc->hFile = CreateFileW(pmdc->wszPathname, // Filename
GENERIC_WRITE, // Write access
0L, // Non-shared
(LPSECURITY_ATTRIBUTES) NULL, // No security
CREATE_ALWAYS, // Always create
FILE_ATTRIBUTE_NORMAL, // normal attributes
(HANDLE) 0)) // no template file
== INVALID_HANDLE_VALUE) { ERROR_ASSERT(FALSE, "CreateFile failed"); goto pmdcAllocMDC_cleanup; } pmdc->fl |= MDC_DISKFILE; // this must be last! See vFreeMDC.
}
// Allocate memory for metafile.
// For disk metafile, it is used as a buffer.
// For memory metafile, it is the storage for the metafile.
if (hEMFSpool != NULL) { // Recording EMF data during EMF spooling
pmdc->fl |= MDC_EMFSPOOL; pmdc->hData = hEMFSpool;
if(!((EMFSpoolData *) hEMFSpool)->GetEMFData(pmdc)) goto pmdcAllocMDC_cleanup;
} else { if (!(pmdc->hData = LocalAlloc(LMEM_FIXED, MF_BUFSIZE_INIT))) goto pmdcAllocMDC_cleanup;
}
// Allocate memory for metafile handle table.
if (!(pmdc->pmhe = (PMHE) LocalAlloc(LMEM_FIXED, MHT_HANDLE_SIZE * sizeof(MHE)))) goto pmdcAllocMDC_cleanup;
// Initialize the new handles.
// The first entry is reserved and unused.
pmdc->pmhe[0].lhObject = (HANDLE) 0; pmdc->pmhe[0].metalink.vInit(INVALID_INDEX);
ii = pmdc->imheFree = 1L; pmdc->cmhe = MHT_HANDLE_SIZE; for ( ; ii < MHT_HANDLE_SIZE; ii++) { pmdc->pmhe[ii].lhObject = (HANDLE) 0; pmdc->pmhe[ii].metalink.vInit(ii+1); } pmdc->pmhe[ii-1].metalink.vInit(INVALID_INDEX);
// Create the first metafile record.
// The description string is part of the header record.
// Get the length of the description string including the NULLs.
PMRMETAFILE pmrmf; UINT cwszDescription;
if (pwszDescription != (LPWSTR) NULL) { for ( cwszDescription = 0; pwszDescription[cwszDescription] != (WCHAR) 0 || pwszDescription[cwszDescription + 1] != (WCHAR) 0; cwszDescription++ ) ; // NULL expression
cwszDescription += 2; // add terminating nulls
if (cwszDescription > 512) { WARNING("pmdcAllocMDC: Description string is > 512 chars\n"); } } else cwszDescription = 0;
// Allocate dword aligned structure.
if (!(pmrmf = (PMRMETAFILE) pmdc->pvNewRecord (SIZEOF_MRMETAFILE(cwszDescription)))) goto pmdcAllocMDC_cleanup;
pmrmf->vInit(hdcRef, pwszDescription, cwszDescription);
// Save a copy of it in the metafile DC.
pmdc->mrmf = *(PENHMETAHEADER) pmrmf;
// Commit it.
pmrmf->vCommit(pmdc);
// If the reference DC has a pixel format selected, record
// it in the metafile
int iPixelFormat;
if ((iPixelFormat = GetPixelFormat(hdcRef)) != 0) { PMRPIXELFORMAT pmrpf; PIXELFORMATDESCRIPTOR pfd;
if (!DescribePixelFormat(hdcRef, iPixelFormat, sizeof(pfd), &pfd)) { goto pmdcAllocMDC_cleanup; }
pmrpf = (PMRPIXELFORMAT)pmdc->pvNewRecord(SIZEOF_MRPIXELFORMAT); if (pmrpf == NULL) { goto pmdcAllocMDC_cleanup; }
pmrpf->vInit(&pfd); pmrpf->vCommit(pmdc); }
pmdcRc = pmdc;
// Cleanup and go home.
pmdcAllocMDC_cleanup:
if (!pmdcRc) if (pmdc) { pmdc->fl |= MDC_FATALERROR; // set to delete the disk metafile
vFreeMDC(pmdc); }
ERROR_ASSERT(pmdcRc, "pmdcAllocMDC failed"); return(pmdcRc); }
/******************************Public*Routine******************************\
* vFreeMDC (pmdc) * * This is a low level routine which frees the resouces in the MDC. * * This function is intended to be called from the routine CloseEnhMetaFile. * * Arguments: * pmdc - The MDC to be freed. * * History: * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
VOID vFreeMDC(PMDC pmdc) { ULONG ii;
PUTS("vFreeMDC\n");
ASSERTGDI(pmdc->ident == MDC_IDENTIFIER, "Bad MDC");
// Free the resources.
if (pmdc->pPalEntries) { if (LocalFree(pmdc->pPalEntries)) { ASSERTGDI(FALSE, "LocalFree failed"); } }
// Cleanup objects and metalinks.
pmdc->vFreeColorProfileList();
if (pmdc->pmhe) { // The first entry is reserved and unused.
for (ii = 1 ; ii < pmdc->cmhe; ii++) { if (pmdc->pmhe[ii].lhObject != (HANDLE) 0) vFreeMHE(pmdc->hdcRef, ii); } if (LocalFree(pmdc->pmhe)) { ASSERTGDI(FALSE, "LocalFree failed"); } } if (pmdc->hData) { if (pmdc->bIsEMFSpool()) { pmdc->CompleteEMFData(FALSE); } else { if (LocalFree(pmdc->hData)) { ASSERTGDI(FALSE, "LocalFree failed"); } } }
if (pmdc->hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(pmdc->hFile)) { ASSERTGDI(FALSE, "CloseHandle failed"); } }
// Delete the disk metafile we created if we encountered any fatal error.
if (pmdc->bIsDiskFile() && pmdc->bFatalError()) {
#if DBG
SetLastError(0); #endif
if (!DeleteFileW(pmdc->wszPathname)) { #if DBG
DbgPrint("vFreeMDC: DeleteFile failed with error code %ld\n", GetLastError()); #endif
//
// There are certain conditions causing fatal errors accessing
// files that equally prevent the deletion of the file
// (such as out of quota or pool)
// If we can't delete the file, we can't do anything about it
// anyway - let's not force an ASSERT even on checked builds unless
// we set the debug flags. We will make do with an error message
// and appropriate error code above.
//
ERROR_ASSERT(FALSE, "vFreeMDC: DeleteFile failed"); } }
// Smash the identifier.
pmdc->ident = 0;
// Free the memory.
if (LocalFree(pmdc)) { ASSERTGDI(FALSE, "LocalFree failed"); } }
/******************************Public*Routine******************************\
* pmfAllocMF(fl, pb, pwszFilename) * * This routine allocates memory for an MF and initializes it. * Returns a pointer to the new MF. On error returns NULL. * It accepts only enhanced metafiles. * * This routine is called by API level MF allocation routines CloseEnhMetaFile, * GetEnhMetaFile, SetEnhMetaFileBits and CopyEnhMetaFile. * * Arguments: * fl - ALLOCMF_TRANSFER_BUFFER is set if storage for memory metafile * is to be set directly into MF. Otherwise, a copy of the * memory metafile is duplicated. * pb - Pointer to a memory metafile if non-null. * pwszFilename - Filename of a disk metafile if non-null. * * History: * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
PMF pmfAllocMF(ULONG fl, CONST UNALIGNED DWORD *pb, LPCWSTR pwszFilename, HANDLE hFile, UINT64 fileOffset, HANDLE hExtra) { PMF pmf = NULL; PMF pmfRc = (PMF) NULL; PENHMETAHEADER pmrmf = NULL;
PUTS("pmfAllocMF\n");
ASSERTGDI(!(fl & ~ALLOCMF_TRANSFER_BUFFER), "pmfAllocMF: Invalid fl");
// Allocate a new MF.
if (!(pmf = (PMF) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(MF)))) goto pmfAllocMF_cleanup;
// Initialize it.
pmf->ident = MF_IDENTIFIER; pmf->hFile = INVALID_HANDLE_VALUE; pmf->hFileMap = NULL; pmf->pvFileMapping = NULL; pmf->pvLocalCopy = NULL; pmf->pEMFSpool = hExtra ? (EMFSpoolData*) hExtra : NULL; pmf->iMem = 0L; pmf->pht = (PHANDLETABLE) NULL; pmf->fl = 0L; pmf->hdcXform = 0;
// Memory mapped the disk file if given.
if (pwszFilename) { pmf->fl |= MF_DISKFILE; // this must be first! See vFreeMF.
LPWSTR pwszFilePart; // not used
UINT64 fileSize;
// Convert the filename to a fully qualified pathname.
DWORD cPathname = GetFullPathNameW(pwszFilename, MAX_PATH, pmf->wszPathname, &pwszFilePart);
if (!cPathname || cPathname > MAX_PATH) { ERROR_ASSERT(FALSE, "GetFullPathName failed"); if (cPathname > MAX_PATH) GdiSetLastError(ERROR_FILENAME_EXCED_RANGE); goto pmfAllocMF_cleanup; } pmf->wszPathname[cPathname] = 0;
if ((pmf->hFile = CreateFileW(pmf->wszPathname, // Filename
GENERIC_READ, // Read access
FILE_SHARE_READ, // Share read
(LPSECURITY_ATTRIBUTES) 0L,// No security
OPEN_EXISTING, // Re-open
0, // file attributes ignored
(HANDLE) 0)) // no template file
== INVALID_HANDLE_VALUE) { ERROR_ASSERT(FALSE, "CreateFile failed"); goto pmfAllocMF_cleanup; }
if(!GetFileSizeEx(pmf->hFile, (PLARGE_INTEGER) &fileSize)) { ERROR_ASSERT(FALSE, "GetFileSizeEx failed"); goto pmfAllocMF_cleanup; }
if(fileSize > (UINT64) 0xFFFFFFFF) { ERROR_ASSERT(FALSE, "EMF File too large\n"); goto pmfAllocMF_cleanup; }
if (!(pmf->hFileMap = CreateFileMappingW(pmf->hFile, (LPSECURITY_ATTRIBUTES) 0L, PAGE_READONLY, 0L, 0L, (LPWSTR) NULL))) { ERROR_ASSERT(FALSE, "CreateFileMapping failed"); goto pmfAllocMF_cleanup; }
if (!(pmf->pvFileMapping = (PENHMETAHEADER) MapViewOfFile(pmf->hFileMap, FILE_MAP_READ, 0, 0, 0))) { ERROR_ASSERT(FALSE, "MapViewOfFile failed"); goto pmfAllocMF_cleanup; }
pmf->emfc.Init((PENHMETAHEADER) pmf->pvFileMapping, (UINT32) fileSize);
} else if (fl & ALLOCMF_TRANSFER_BUFFER) { // If this is our memory metafile from MDC, transfer it to MF.
if(pb) { pmf->emfc.Init((PENHMETAHEADER) pb, ((PENHMETAHEADER) pb)->nBytes);
// We now own the reference which we must free
pmf->pvLocalCopy = (PVOID) pb; } else if(hFile) { pmf->emfc.Init(hFile, fileOffset, 0);
// We now own the reference which we must now Close
pmf->hFile = hFile; } else { ERROR_ASSERT(hFile != NULL, "pmfAllocMF: exepect hHandle or pb to be non-null\n"); goto pmfAllocMF_cleanup; }
} else { // Otherwise, make a copy of memory metafile.
if (!(pmf->pvLocalCopy = (PENHMETAHEADER) LocalAlloc(LMEM_FIXED, (UINT) ((PENHMETAHEADER) pb)->nBytes))) goto pmfAllocMF_cleanup;
RtlCopyMemory((PBYTE) pmf->pvLocalCopy, pb, ((PENHMETAHEADER) pb)->nBytes);
pmf->emfc.Init((PENHMETAHEADER) pmf->pvLocalCopy, ((PENHMETAHEADER) pb)->nBytes);
}
// Verify metafile header
pmrmf = pmf->emfc.GetEMFHeader();
if(!pmrmf) { WARNING("pmfAllocMF: failed to get emf header\n"); goto pmfAllocMF_cleanup; }
if (!((PMRMETAFILE) pmrmf)->bValid()) { ERROR_ASSERT(FALSE, "pmfAllocMF: Metafile has an invalid header; Failing\n"); goto pmfAllocMF_cleanup; }
// Allocate and initialize the playback object handle table.
// The first entry of pht is initialized to hemf in PlayEnhMetaFile
// and EnumEnhMetaFile.
if (!(pmf->pht = (PHANDLETABLE) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, pmrmf->nHandles * sizeof(HANDLE)))) goto pmfAllocMF_cleanup;
// Allocate a virtual device for transform computation.
if (!(pmf->hdcXform = CreateICA((LPCSTR) "DISPLAY", (LPCSTR) NULL, (LPCSTR) NULL, (LPDEVMODEA) NULL))) { ERROR_ASSERT(FALSE, "CreateICA failed"); goto pmfAllocMF_cleanup; }
// The transform DC must be in the advanced graphics mode.
// The world transform can only be set in the advanced graphics mode.
if (!SetGraphicsMode(pmf->hdcXform, GM_ADVANCED)) goto pmfAllocMF_cleanup;
// Everything is golden.
pmfRc = pmf;
// Cleanup and go home.
pmfAllocMF_cleanup:
if (!pmfRc) if (pmf) { if (fl & ALLOCMF_TRANSFER_BUFFER) pmf->pvLocalCopy = 0; // let caller free the buffer.
vFreeMF(pmf); }
ERROR_ASSERT(pmfRc, "pmfAllocMF failed"); return(pmfRc); }
/******************************Public*Routine******************************\
* vFreeMF (pmf) * * This is a low level routine which frees the resouces in the MF. * * This function is intended to be called from the routines CloseEnhMetaFile * and DeleteEnhMetaFile. * * Arguments: * pmf - The MF to be freed. * * History: * Tue Jul 02 13:43:18 1991 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
VOID vFreeMF(PMF pmf) { PUTS("vFreeMF\n");
ASSERTGDI(pmf->ident == MF_IDENTIFIER, "Bad MF");
// Free the resources.
if (pmf->hdcXform) DeleteDC(pmf->hdcXform);
pmf->emfc.Term();
if (pmf->pht) { // Objects created during play are freed in PlayEnhMetaFile and
// EnumEnhMetaFile.
PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
if (pmrmf) { for (WORD ii = 1; ii < pmrmf->nHandles; ii++) { ASSERTGDI(!pmf->pht->objectHandle[ii], "vFreeMF: Handle table not empty"); } }
if (LocalFree(pmf->pht)) { ASSERTGDI(FALSE, "LocalFree failed"); } }
if (!pmf->bIsDiskFile()) { // Free memory metafile.
if (pmf->pvLocalCopy && LocalFree(pmf->pvLocalCopy)) { ASSERTGDI(FALSE, "LocalFree failed"); }
// If we are spooling, then the spooler needs to deal
// with closing the file handle, otherwise we own it
// and need to close it.
if(!pmf->bIsEMFSpool()) { if (pmf->hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(pmf->hFile)) { ASSERTGDI(FALSE, "CloseHandle failed"); } else { pmf->hFile = NULL; } } } } else { // Unmap disk file.
if (pmf->pvFileMapping && !UnmapViewOfFile(pmf->pvFileMapping)) { ASSERTGDI(FALSE, "UmmapViewOfFile failed"); }
if (pmf->hFileMap) { if (!CloseHandle(pmf->hFileMap)) { ASSERTGDI(FALSE, "CloseHandle failed"); } else { pmf->hFileMap = NULL; } }
if (pmf->hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(pmf->hFile)) { ASSERTGDI(FALSE, "CloseHandle failed"); } else { pmf->hFile = NULL; } }
}
// Smash the identifier.
pmf->ident = 0;
// Free the memory.
if (LocalFree(pmf)) { ASSERTGDI(FALSE, "LocalFree failed"); } }
/******************************Public*Routine******************************\
* vFreeMFAlt (pmf, bAllocBuffer) * * This is a low level routine which frees the resouces in the MF. * * This function is intended to be called from the routines InternalDeleteEnhMetaFile * * Arguments: * pmf - The MF to be freed. * bAllocBuffer - flag to free buffer * \**************************************************************************/
VOID vFreeMFAlt(PMF pmf, BOOL bAllocBuffer) { PUTS("vFreeMF\n");
ASSERTGDI(pmf->ident == MF_IDENTIFIER, "Bad MF");
// Free the resources.
if (pmf->hdcXform) DeleteDC(pmf->hdcXform);
pmf->emfc.Term();
if (pmf->pht) { // Objects created during play are freed in PlayEnhMetaFile and
// EnumEnhMetaFile.
PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
if (pmrmf) { for (WORD ii = 1; ii < pmrmf->nHandles; ii++) { ASSERTGDI(!pmf->pht->objectHandle[ii], "vFreeMF: Handle table not empty"); } }
if (LocalFree(pmf->pht)) { ASSERTGDI(FALSE, "LocalFree failed"); } }
if (bAllocBuffer) { if (!pmf->bIsDiskFile()) { // Free memory metafile.
if (pmf->pvLocalCopy && LocalFree(pmf->pvLocalCopy)) { ASSERTGDI(FALSE, "LocalFree failed"); }
if(!pmf->bIsEMFSpool()) { // If we are spooling, then the spooler needs to deal
// with closing the file handle, otherwise we own it
// and need to close it.
if (pmf->hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(pmf->hFile)) { ASSERTGDI(FALSE, "CloseHandle failed"); } else { pmf->hFile = NULL; } } } } else { // Unmap disk file.
if (pmf->pvFileMapping && !UnmapViewOfFile(pmf->pvFileMapping)) { ASSERTGDI(FALSE, "UmmapViewOfFile failed"); }
if (pmf->hFileMap) { if (!CloseHandle(pmf->hFileMap)) { ASSERTGDI(FALSE, "CloseHandle failed"); } else { pmf->hFileMap = NULL; } } if (pmf->hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(pmf->hFile)) { ASSERTGDI(FALSE, "CloseHandle failed"); } else { pmf->hFile = NULL; } } }
} // Smash the identifier.
pmf->ident = 0;
// Free the memory.
if (LocalFree(pmf)) { ASSERTGDI(FALSE, "LocalFree failed"); } }
/******************************Public*Routine******************************\
* bMetaResetDC (hdc) * * Initialize the destination DC before playing a metafile to that DC. * * History: * Fri Nov 01 15:02:58 1991 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
BOOL bMetaResetDC(HDC hdc) { // Make sure we do everything
// If the destination is a metafile DC, we want to embed
// the calls made in this function.
POINT ptOrg; FLOAT eMiterLimit;
// Reset to default objects.
SelectObject(hdc, GetStockObject(WHITE_BRUSH)); SelectObject(hdc, GetStockObject(BLACK_PEN)); SelectObject(hdc, GetStockObject(DEVICE_DEFAULT_FONT)); SelectPalette(hdc,GetStockObject(DEFAULT_PALETTE),TRUE);
// Attributes cache.
SetBkColor(hdc, 0xffffff); SetTextColor(hdc, 0); SetTextCharacterExtra(hdc, 0); SetBkMode(hdc, OPAQUE);
SetPolyFillMode(hdc, ALTERNATE); SetROP2(hdc, R2_COPYPEN); SetStretchBltMode(hdc, BLACKONWHITE); SetTextAlign(hdc, 0);
// Reset server attributes.
// Mapper flags.
// Metafile it only if the previous mapper flags is not default.
if (SetMapperFlagsInternal(hdc, 0) != 0) // if the previous flags is
{ if (SetMapperFlags(hdc, 0) == GDI_ERROR) // not default, set to default
{ ASSERTGDI(FALSE, "SetMapperFlags failed"); } }
SetBrushOrgEx(hdc, 0, 0, (LPPOINT) NULL); SetMiterLimit(hdc, 10.0f, (PFLOAT) NULL); SetTextJustification(hdc, 0, 0); SetArcDirection(hdc, AD_COUNTERCLOCKWISE); MoveToEx(hdc, 0, 0, (LPPOINT) NULL);
return(TRUE); }
/******************************Public*Routine******************************\
* bIsPoly16(pptl, cptl) * * Return TRUE if all the points in the poly array are 16-bit signed integers. * Otherwise, it is FALSE. * * History: * Sat Mar 07 17:07:33 1992 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
BOOL bIsPoly16(PPOINTL pptl, DWORD cptl) { while (cptl--) { if ( pptl->x < (LONG) (SHORT) MINSHORT || pptl->x > (LONG) (SHORT) MAXSHORT || pptl->y < (LONG) (SHORT) MINSHORT || pptl->y > (LONG) (SHORT) MAXSHORT ) return(FALSE); pptl++; } return(TRUE); }
/******************************Public*Routine******************************\
* imheAllocMHE(hdc, lhObject) * * Allocates a MHE from the Metafile Handle Table in the metafile DC, * initializes fields in the MHE, and updates the object's metalink. * Returns the MHE index or INVALID_INDEX on error. * * Since the first entry is reserved, index zero is never returned. * * When a object's metalink is first created, a 16-bit metafile object-link * should be added to the begining of the metafile link as necessary. The * 16-bit metafile object-link should be removed as necessary when the last * metalink is deleted. * * History: * Tue Aug 06 15:41:52 1991 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
ULONG imheAllocMHE(HDC hdc, HANDLE lhObject) { PMDC pmdc = GET_PMDC(hdc); ULONG imhe = INVALID_INDEX; ULONG ii; PMHE pmhe;
// Get critical for handle allocation.
ENTERCRITICALSECTION(&semLocal);
// Make sure a handle is available.
if (pmdc->imheFree == INVALID_INDEX) { // Allocate more handles up to the max size.
PMHE pmhe1; UINT cmhe1;
if (pmdc->cmhe == MHT_MAX_HANDLE_SIZE) { ERROR_ASSERT(FALSE, "imheAllocMHE: max handle table size reached"); goto imheAllocMHE_exit; }
cmhe1 = min((UINT) pmdc->cmhe + MHT_HANDLE_SIZE, (UINT) MHT_MAX_HANDLE_SIZE);
if (!(pmhe1 = (PMHE) LocalReAlloc ( pmdc->pmhe, cmhe1 * sizeof(MHE), LMEM_MOVEABLE ) ) ) { ERROR_ASSERT(FALSE, "LocalReAlloc failed"); goto imheAllocMHE_exit; }
pmdc->pmhe = pmhe1;
// Initialize the new handles.
ii = pmdc->imheFree = pmdc->cmhe; pmdc->cmhe = cmhe1; for ( ; ii < pmdc->cmhe; ii++) { pmdc->pmhe[ii].lhObject = (HANDLE) 0; pmdc->pmhe[ii].metalink.vInit(ii+1); } pmdc->pmhe[ii-1].metalink.vInit(INVALID_INDEX); }
// First, make sure the object has a 16-bit metafile object-link.
// we have this in brackets to reduce scope of pmetalink16
{ METALINK16 *pmetalink16 = pmetalink16Get(lhObject);
if (pmetalink16 == NULL) { pmetalink16 = pmetalink16Create(lhObject);
if (pmetalink16 == NULL) { ERROR_ASSERT(FALSE, "LocalAlloc failed"); goto imheAllocMHE_exit; }
ASSERTGDI ( pmetalink16->metalink == 0 && pmetalink16->cMetaDC16 == 0 && pmetalink16->ahMetaDC16[0] == (HDC) 0, "imheAllocMHE: METALINK16 not initialized properly" ); }
imhe = pmdc->imheFree; pmhe = pmdc->pmhe + imhe; pmdc->imheFree = (ULONG) pmhe->metalink;
ASSERTGDI(imhe != 0, "imheAllocMHE: index zero is reserved"); ASSERTGDI(pmhe->lhObject == (HANDLE) 0, "imheAllocMHE: imheFree in use");
// Update and add the metalink to the link list.
pmhe->lhObject = lhObject; pmhe->metalink.vInit(pmetalink16->metalink); ((PMETALINK) &pmetalink16->metalink)->vInit((USHORT) imhe, H_INDEX(hdc)); }
imheAllocMHE_exit:
// Leave the critical section.
LEAVECRITICALSECTION(&semLocal); return(imhe); }
/******************************Public*Routine******************************\
* vFreeMHE(hdc, imhe) * * Free up a MHE and insert it into the Metafile Handle Table free list. * It also updates the object's metalink. * * When the last metalink is removed, the 16-bit metafile object-link should * also be removed if it is not used. * * History: * Tue Aug 06 15:41:52 1991 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
VOID vFreeMHE(HDC hdc, ULONG imhe) { PMETALINK16 pmetalink16; PMDC pmdc = GET_PMDC(hdc); HANDLE hobj;
ASSERTGDI(imhe != 0, "vFreeMHE: index zero is reserved");
// Get critical for handle deallocation.
ENTERCRITICALSECTION(&semLocal);
// Remove it from the object metalink friend list.
hobj = pmdc->pmhe[imhe].lhObject; pmetalink16 = pmetalink16Get(hobj);
ASSERTGDI(pmetalink16, "vFreeMHE: pmetalink16 Invalid");
METALINK metalink(pmetalink16);
ASSERTGDI(metalink.bValid(), "vFreeMHE: Invalid imhe");
if (metalink.bEqual((USHORT) imhe, H_INDEX(hdc))) { pmetalink16->metalink = (ULONG) pmdc->pmhe[imhe].metalink; } else { while (!(metalink.pmetalinkNext())->bEqual((USHORT) imhe, H_INDEX(hdc))) { metalink.vNext(); ASSERTGDI(metalink.bValid(), "vFreeMHE: Invalid imhe"); }
*(metalink.pmetalinkNext()) = pmdc->pmhe[imhe].metalink; }
// Add the handle to the free list.
pmdc->pmhe[imhe].lhObject = (HANDLE) 0; pmdc->pmhe[imhe].metalink.vInit(pmdc->imheFree); pmdc->imheFree = imhe;
// If there is no more metalink, remove the 16-bit metafile object-link
// if it's not used.
if (!pmetalink16->metalink && !pmetalink16->cMetaDC16) { if (!bDeleteMetalink16(hobj)) { ASSERTGDI(FALSE, "LocalFree failed"); } }
// Leave the critical section.
LEAVECRITICALSECTION(&semLocal); }
/******************************Public*Routine******************************\
* GdiConvertMetaFilePict * GdiConvertEnhMetaFile * * A server handle is created that is an exact copy of the client * MetaFilePict or EnhMetaFile data. The caller (clipbrd) is responsible * for deleting both the client and server copies when they are no longer * needed. * * A MetaFilePict is a structure containing a metafile size and a handle * to a metafile. Both MetaFilePict and EnhMetaFile are used primarily by * the clipboard interface. When an app puts a MetaFilePict or an * EnhMetaFile in the clipboard we have to create a server copy because * the app can terminate and another application can still query the * clipboard data. * * The format for the client-server data is as follows: * * DWORD iType MFEN_IDENTIFIER or MFPICT_IDENTIFIER * DWORD mm used by MetaFilePict only * DWORD xExt used by MetaFilePict only * DWORD yExt used by MetaFilePict only * DWORD nBytes number of bytes in pClientData * PBYTE pClientData contains the metafile bits * * Returns a server handle that is a copy of the metafile data. * Returns zero if an error occurs. * * History: * Wed Sep 16 09:42:22 1992 -by- Hock San Lee [hockl] * Rewrote it. * 28-Oct-1991 -by- John Colleran [johnc] * Wrote it. \**************************************************************************/
HANDLE GdiConvertMetaFilePict(HANDLE hmem) { HANDLE hRet = (HANDLE) 0; PMETAFILE16 pmf16; LPMETAFILEPICT lpmfp;
PUTS("GdiConvertMetaFilePict\n");
// Get the METAFILEPICT
lpmfp = (LPMETAFILEPICT) GlobalLock(hmem); if (!lpmfp) { WARNING("GdiConvertMetaFilePict GlobalLock(hmem) Failed\n"); return((HANDLE) 0); }
pmf16 = GET_PMF16(lpmfp->hMF);
// Validate the hmf field of the METAFILEPICT
if (pmf16 == NULL) { WARNING("GdiConvertMetaFilePict invalid handle\n"); GdiSetLastError(ERROR_INVALID_HANDLE); goto GCMFP_Exit; }
// Get the size of the metafile.
ASSERTGDI(IsValidMetaHeader16(&pmf16->metaHeader), "GdiConvertMetaFilePict: Bad metafile");
hRet = NtGdiCreateServerMetaFile(MFPICT_IDENTIFIER, pmf16->metaHeader.mtSize * sizeof(WORD), (PBYTE) pmf16->hMem, lpmfp->mm, lpmfp->xExt, lpmfp->yExt);
GCMFP_Exit: GlobalUnlock(hmem); ERROR_ASSERT(hRet, "GdiConvertMetaFilePict failed\n"); return(hRet); }
HANDLE GdiConvertEnhMetaFile(HENHMETAFILE hemf) { HANDLE hRet; PMF pmf;
PUTS("GdiConvertEnhMetaFile\n");
if (!(pmf = GET_PMF(hemf))) { WARNING("GdiConvertEnhMetaFile: bad hemf\n"); return((HMETAFILE) 0); }
PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
if(!pmrmf) { WARNING("GdiConvertEnhMetaFile: failed getting header\n"); return((HMETAFILE) 0); }
PBYTE pb = (PBYTE) pmf->emfc.ObtainPtr(0, pmrmf->nBytes);
if(!pb) { WARNING("GdiConvertEnhMetaFile: failed getting data\n"); return((HMETAFILE) 0); }
hRet = NtGdiCreateServerMetaFile(MFEN_IDENTIFIER, pmrmf->nBytes, pb, 0, 0, 0);
pmf->emfc.ReleasePtr(pb);
ERROR_ASSERT(hRet, "GdiConvertEnhMetaFile failed"); return((HMETAFILE) hRet); }
/******************************Public*Routine******************************\
* GdiCreateLocalMetaFilePict * GdiCreateLocalEnhMetaFile * * Creates a local MetaFilePict or EnhMetaFile handle that is a copy of * the server handle. The server handle can be either a standard metafile * or an enhanced metafile. The functions will perform metafile conversion * to the requested format (MetaFilePict or EnhMetaFile) if necessary. * * The caller is responsible for deleting the local handle when it is no * longer needed. By Windows convention the app that recieves the * MetaFilePict will delete it by first deleting the metafile and then * freeing the global handle * * The format for the client-server data is as follows: * * HANDLE hSrv server handle (can be standard or enhanced metafile) * DWORD iType return MFPICT_IDENTIFIER or MFEN_IDENTIFIER * DWORD mm return by MetaFilePict only * DWORD xExt return by MetaFilePict only * DWORD yExt return by MetaFilePict only * DWORD nBytes zero to query size of metafile bits in pClientData. * otherwise it is the size of pClientData that is to * receive the metafile bits. * PBYTE pClientData to receive the metafile bits * * Returns a client MetaFilePict or EnhMetaFile handle that is a copy of * the server metafile. Returns zero if an error occurs * * History: * Wed Sep 16 09:42:22 1992 -by- Hock San Lee [hockl] * Rewrote it. * 28-Oct-1991 -by- John Colleran [johnc] * Wrote it. \**************************************************************************/
HANDLE GdiCreateLocalMetaFilePict(HANDLE hSrv) { return(InternalCreateLocalMetaFile(hSrv, MFPICT_IDENTIFIER)); }
HENHMETAFILE GdiCreateLocalEnhMetaFile(HANDLE hSrv) { return((HENHMETAFILE) InternalCreateLocalMetaFile((HANDLE) hSrv, MFEN_IDENTIFIER)); }
ULONG GetServerMetaFileBits(HANDLE hSrv, DWORD nBytes, PBYTE pMFBits, PDWORD piType, PDWORD pmm, PDWORD pxExt, PDWORD pyExt) { ULONG cRet = 0;
PUTS("GetServerMetaFileBits\n");
cRet = NtGdiGetServerMetaFileBits( hSrv, (ULONG)nBytes, (LPBYTE)pMFBits, piType, pmm, pxExt, pyExt);
return(cRet); }
HANDLE InternalCreateLocalMetaFile(HANDLE hSrv, DWORD iTypeReq) { DWORD iTypeSrv; DWORD mm; DWORD xExt; DWORD yExt; ULONG cbData; PBYTE pData = (PBYTE) NULL; LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) NULL; HANDLE hRet = (HANDLE) 0;
ASSERTGDI(iTypeReq == MFEN_IDENTIFIER || iTypeReq == MFPICT_IDENTIFIER, "InternalCreateLocalMetaFile: bad metafile type\n");
if (!hSrv) { VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: hSrv is 0"); return((HANDLE) 0); }
// Get the size of the server metafile bits.
cbData = GetServerMetaFileBits(hSrv, 0, (PBYTE) NULL, (PDWORD) NULL, (PDWORD) NULL, (PDWORD) NULL, (PDWORD) NULL); if (!cbData) { ASSERTGDI(FALSE, "InternalCreateLocalMetaFile: size query failed"); return((HANDLE) 0); }
// Allocate a buffer to retrieve the metafile bits.
pData = (PBYTE) LocalAlloc(LMEM_FIXED, (UINT) cbData); if (!pData) return((HANDLE) 0);
// Retrieve the server metafile bits.
if (GetServerMetaFileBits(hSrv, cbData, pData, &iTypeSrv, &mm, &xExt, &yExt) != cbData) { ASSERTGDI(FALSE, "InternalCreateLocalMetaFile: not all data returned"); goto ICLMF_exit; }
// Allocate the MetaFilePict structure if necessary.
if (iTypeReq == MFPICT_IDENTIFIER) { lpmfp = (LPMETAFILEPICT) GlobalAlloc(GMEM_FIXED, sizeof(METAFILEPICT)); if (!lpmfp) { VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: GlobalAlloc failed\n"); goto ICLMF_exit; } }
// Create the same type of metafile as requested.
switch (iTypeSrv) { case MFEN_IDENTIFIER: if (iTypeReq == MFPICT_IDENTIFIER) { UINT cbMeta16; LPBYTE lpMeta16; HDC hdcICScreen; HENHMETAFILE hemf; PENHMETAHEADER pEMH = (PENHMETAHEADER) pData;
PUTS("InternalCreateLocalMetaFile: EMF -> MFPICT\n");
lpmfp->mm = MM_ANISOTROPIC; lpmfp->xExt = (DWORD) (pEMH->rclFrame.right - pEMH->rclFrame.left); lpmfp->yExt = (DWORD) (pEMH->rclFrame.bottom - pEMH->rclFrame.top );
if (hemf = SetEnhMetaFileBitsAlt((HLOCAL) pData, NULL, NULL, 0)) pData = (PBYTE) NULL; // pData has been moved to the metafile
else VERIFYGDI(hemf, "InternalCreateLocalMetaFile: SetEnhMetaFileBitsAlt failed");
hdcICScreen = CreateICA((LPCSTR)"DISPLAY", (LPCSTR)NULL, (LPCSTR)NULL, (LPDEVMODEA)NULL); VERIFYGDI(hdcICScreen, "InternalCreateLocalMetaFile: CreateICA failed");
cbMeta16 = GetWinMetaFileBits(hemf, 0, (LPBYTE) NULL, MM_ANISOTROPIC, hdcICScreen); if (cbMeta16) { lpMeta16 = (PBYTE) LocalAlloc(LMEM_FIXED, cbMeta16);
if (lpMeta16) { if ((GetWinMetaFileBits(hemf, cbMeta16, lpMeta16, MM_ANISOTROPIC, hdcICScreen) != cbMeta16) // use the memory handle for the metafile!
|| !(lpmfp->hMF = SetMetaFileBitsAlt((HLOCAL) lpMeta16))) { VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: SetMetaFileBitsAlt failed"); LocalFree((HANDLE) lpMeta16); } else hRet = (HANDLE) lpmfp; } }
DeleteEnhMetaFile(hemf); DeleteDC(hdcICScreen); } else { PUTS("InternalCreateLocalMetaFile: EMF -> EMF\n");
if (hRet = (HANDLE) SetEnhMetaFileBitsAlt((HLOCAL) pData, NULL, NULL, 0)) pData = (PBYTE) NULL; // pData has been moved to the metafile
else { VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: SetEnhMetaFileBitsAlt failed"); } } break;
case MFPICT_IDENTIFIER: if (iTypeReq == MFPICT_IDENTIFIER) { PUTS("InternalCreateLocalMetaFile: MFPICT -> MFPICT\n");
lpmfp->mm = mm; lpmfp->xExt = xExt; lpmfp->yExt = yExt;
if (lpmfp->hMF = SetMetaFileBitsAlt((HLOCAL) pData)) { pData = (PBYTE) NULL; // pData has been moved to the metafile
hRet = (HANDLE) lpmfp; } else VERIFYGDI(FALSE, "InternalCreateLocalMetaFile: SetMetaFileBitsAlt failed"); } else { METAFILEPICT mfp;
PUTS("InternalCreateLocalMetaFile: MFPICT -> EMF\n");
mfp.mm = mm; mfp.xExt = xExt; mfp.yExt = yExt; mfp.hMF = (HMETAFILE) 0;
hRet = (HANDLE) SetWinMetaFileBits((UINT) cbData, pData, (HDC) 0, &mfp); VERIFYGDI(hRet, "InternalCreateLocalMetaFile: SetWinMetaFileBits failed"); } break;
default: ASSERTGDI(FALSE, "InternalCreateLocalMetaFile unknown metafile type\n"); break; }
// Cleanup if we failed
ICLMF_exit: if (!hRet && lpmfp) { if (GlobalFree((HANDLE) lpmfp)) { ASSERTGDI(FALSE, "InternalCreateLocalMetaFile: GlobalFree failed"); } }
if (pData) { LocalFree((HANDLE) pData); }
ERROR_ASSERT(hRet, "InternalCreateLocalMetaFile failed"); return(hRet); }
/******************************Public*Routine******************************\
* GetRandomRgnBounds * * Wrote it. * Fri Jul 24 09:35:24 1992 -by- Hock San Lee [hockl] \**************************************************************************/
BOOL APIENTRY GetRandomRgnBounds(HDC hdc,PRECTL prcl,INT iType) { BOOL bRet = FALSE; HRGN hrgnTmp;
// We should be able to get the region handle without creating a copy!
// Make a copy of the specified clip region.
if (!(hrgnTmp = CreateRectRgn(0, 0, 0, 0))) return(bRet);
switch (GetRandomRgn(hdc, hrgnTmp, (int) iType)) { case -1: // error
WARNING("GetRandomRgn failed"); break;
case 0: // no initial clip region
*prcl = rclInfinity; bRet = TRUE; break;
case 1: // has initial clip region
bRet = (GetRgnBox(hrgnTmp, (LPRECT) prcl) != RGN_ERROR); break; }
if (!DeleteObject(hrgnTmp)) { ASSERTGDI(FALSE, "DeleteObject failed"); }
return(bRet); }
/**************************************************************************\
* * misc statistics * \**************************************************************************/
#if DBG
ULONG gcMetalinks = 0; ULONG gcQueries = 0; ULONG gcQueriesExtra = 0; ULONG gcHits = 0;
#define INC_QUERIES (++gcQueries)
#define INC_QUERIESX (++gcQueries)
#define INC_HITS (++gcHits)
#define INC_LINKS (++gcMetalinks)
#define DEC_LINKS (--gcMetalinks,++gcHits)
BOOL gbdbgml = 0; #else
#define gbdbgml FALSE
#define INC_QUERIES
#define INC_QUERIESX
#define INC_HITS
#define INC_LINKS
#define DEC_LINKS
#endif
/******************************Public*Routine******************************\
* PLINK plinkGet() * * This routine locks semLocal critical section while traversing the table. * * History: * 14-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
PLINK plinkGet( HANDLE h ) { PLINK plink = NULL;
// see if we need to search. We do a quick test before entering the critical
// section to see if the cache entry is empty. For cases where the entry is
// not in the cache, the entry will usualy be empty. We need to recheck the
// value once we are in the critical section to make sure it hasn't gone away
if (h && aplHash[LINK_HASH_INDEX(h)]) { INC_QUERIES;
ENTERCRITICALSECTION(&semLocal);
plink = aplHash[LINK_HASH_INDEX(h)];
while (plink && DIFFHANDLE(plink->hobj,h)) { INC_QUERIESX;
plink = plink->plinkNext; }
LEAVECRITICALSECTION(&semLocal);
if (plink) { INC_HITS; } }
#if DBG
if (gbdbgml) DbgPrint("plinkGet(%p) = %p, ihash = %ld\n", h,plink, LINK_HASH_INDEX(h)); #endif
return(plink); }
/******************************Public*Routine******************************\
* PLINK plinkCreate() * * Note that this does not need to grab semLocal. All callers must already * have done that. * * History: * 14-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
PLINK plinkCreate( HANDLE h, ULONG ulSize ) { PLINK plink = (PLINK)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,ulSize);
if (plink) { INC_LINKS;
plink->plinkNext = aplHash[LINK_HASH_INDEX(h)]; plink->hobj = h;
aplHash[LINK_HASH_INDEX(h)] = plink; }
#if DBG
if (gbdbgml) DbgPrint("plinkCreate(%p) = %p, ihash = %ld\n", h,plink, LINK_HASH_INDEX(h)); #endif
return(plink); }
/******************************Public*Routine******************************\
* BOOL bDeletelink() * * This routine locks semLocal critical section while traversing the table. * * History: * 14-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
BOOL bDeleteLink( HANDLE h ) { BOOL bSuccess = FALSE; PLINK plink = NULL;
if (h) { ENTERCRITICALSECTION(&semLocal);
plink = aplHash[LINK_HASH_INDEX(h)];
if (plink) { INC_QUERIES;
// see if it is the first on the list.
if (SAMEHANDLE(plink->hobj,h)) { aplHash[LINK_HASH_INDEX(h)] = plink->plinkNext; bSuccess = TRUE; DEC_LINKS; } else { // it isn't the first so lets run the list. We know pmetalink16 is
// valid and that it is not the element
while (plink->plinkNext) { INC_QUERIESX;
if (SAMEHANDLE(plink->plinkNext->hobj,h)) { PLINK plinkDel = plink->plinkNext; plink->plinkNext = plinkDel->plinkNext;
plink = plinkDel; // so we can delete it.
bSuccess = TRUE;
DEC_LINKS; break; }
plink = plink->plinkNext; } }
}
LEAVECRITICALSECTION(&semLocal);
if (bSuccess) LocalFree(plink); } #if DBG
if (gbdbgml) DbgPrint("bDeleteLink(%p) = %p, ihash = %ld\n", h,plink, LINK_HASH_INDEX(h)); #endif
return(bSuccess); }
/******************************Public*Routine******************************\
* PMETALINK16 pmetalink16Resize() * * This routine locks semLocal critical section while traversing the table. * * History: * 14-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
PMETALINK16 pmetalink16Resize( HANDLE h, int cObj ) { PMETALINK16 pmetalink16 = NULL; int cj = sizeof(METALINK16) + sizeof(HDC) * (cObj-1);
if (h) { ENTERCRITICALSECTION(&semLocal);
pmetalink16 = (PMETALINK16)aplHash[LINK_HASH_INDEX(h)];
if (pmetalink16) { INC_QUERIES;
// see if it is the first on the list.
if (SAMEHANDLE(pmetalink16->hobj,h)) { pmetalink16 = (PMETALINK16)LocalReAlloc(pmetalink16,cj,LMEM_MOVEABLE); if (pmetalink16) aplHash[LINK_HASH_INDEX(h)] = (PLINK)pmetalink16; } else { // it isn't the first so lets run the list. We know pmetalink16 is
// valid and that it is not the element
while (pmetalink16->pmetalink16Next) { INC_QUERIESX;
if (SAMEHANDLE(pmetalink16->pmetalink16Next->hobj,h)) { PMETALINK16 ptmpmetalink16;
ptmpmetalink16 = (PMETALINK16)LocalReAlloc( pmetalink16->pmetalink16Next,cj,LMEM_MOVEABLE);
if (ptmpmetalink16) { pmetalink16->pmetalink16Next = ptmpmetalink16; pmetalink16 = pmetalink16->pmetalink16Next; } else { pmetalink16 = ptmpmetalink16; } break; }
pmetalink16 = pmetalink16->pmetalink16Next; } } }
LEAVECRITICALSECTION(&semLocal); }
#if DBG
if (gbdbgml) DbgPrint("pmetalink16Resize(%p) = %p, ihash = %ld\n", h,pmetalink16, aplHash[LINK_HASH_INDEX(h)]); #endif
return(pmetalink16); }
/******************************Public*Routine******************************\
* * History: * 03-Aug-1995 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
PMDC pmdcGetFromHdc( HDC hdc) { PLDC pldc = pldcGet(hdc);
return((PMDC)(pldc ? pldc->pvPMDC : NULL)); }
/******************************Public*Routine******************************\
* HANDLE hCreateClientObjLink() * * ClientObjLinks are just associations of a server handle with a client pointer. * * History: * 17-Jan-1995 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
HANDLE hCreateClientObjLink( PVOID pv, ULONG ulType) { HANDLE h = CreateClientObj(ulType);
if (h) { PLINK plink;
ENTERCRITICALSECTION(&semLocal);
plink = plinkCreate(h,sizeof(LINK));
LEAVECRITICALSECTION(&semLocal);
if (plink) { plink->pv = pv; } else { DeleteClientObj(h); h = NULL; } }
#if DBG
if (gbdbgml) DbgPrint("hCreateClientObjLink = %p\n",h); #endif
return(h); }
/******************************Public*Routine******************************\
* PVOID pvClientObjGet() * * Given a handle, find the client pv field of the client object. The GRE * type of the handle will be CLIENTOBJ_TYPE. * * History: * 18-Jan-1995 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
PVOID pvClientObjGet( HANDLE h, DWORD dwLoType) { if (LO_TYPE(h) == dwLoType) { PLINK plink = plinkGet(h);
#if DBG
if (gbdbgml) DbgPrint("pvClientObjGet(%p) = %p\n",h,plink ? plink->pv : NULL); #endif
if (plink) { return(plink->pv); } } else { WARNING1("pvClientObjGet (metafile stuff) - invalid handle\n"); }
GdiSetLastError(ERROR_INVALID_HANDLE); return(NULL); }
/******************************Public*Routine******************************\
* BOOL bDeleteClientObjLink() * * * History: * 18-Jan-1995 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
BOOL bDeleteClientObjLink( HANDLE h) { #if DBG
if (gbdbgml) DbgPrint("bDeleteClientObjLink = %p\n",h); #endif
if (bDeleteLink(h)) { DeleteClientObj(h); return(TRUE); } else { return(FALSE); } }
|