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

/******************************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);
}
}