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.
 
 
 
 
 
 

502 lines
13 KiB

/**************************************************************************\
*
* Copyright (c) 1998 Microsoft Corporation
*
* Abstract:
*
* Contains simple engine-wide prototypes and helper functions and
* compile time flags.
*
* History:
*
* 12/04/1998 davidx
* Created it.
*
\**************************************************************************/
#ifndef _ENGINE_HPP
#define _ENGINE_HPP
//--------------------------------------------------------------------------
// GDI+ internal prototypes
//--------------------------------------------------------------------------
class GpDevice;
struct DpPen;
USHORT
GetLanguageID();
BOOL
InitSystemFontsDirs(VOID); //WCHAR **system_dir, WCHAR **fonts_dir);
UINT32
Crc32(
IN const VOID* buf,
IN UINT size,
IN UINT32 checksum
);
// Get the ceiling the same way the rasterizer does
inline INT
RasterizerCeiling(
REAL value
)
{
return GpFix4Ceiling(GpRealToFix4(value));
}
GpStatus
BoundsFToRect(
const GpRectF *rectF,
GpRect * rect
);
/*
REAL
GetPenDelta(
const DpPen* pen,
const GpMatrix* matrix,
REAL dpiX,
REAL dpiY
);
*/
REAL GetDeviceWidth(
REAL width,
GpUnit unit,
REAL dpi);
VOID
TransformBounds(
const GpMatrix *matrix,
REAL x0,
REAL y0,
REAL x1,
REAL y1,
GpRectF *bounds
);
LONG
WINAPI
InterlockedCompareExchangeWin95(
IN OUT PLONG destination,
IN LONG exchange,
IN LONG comperand
);
LONG
WINAPI
InterlockedIncrementWin95(
IN LPLONG lpAddend
);
LONG
WINAPI
InterlockedDecrementWin95(
IN LPLONG lpAddend
);
BOOL
APIENTRY
GdiIsMetaPrintDCWin9x(
HDC hdc
);
//--------------------------------------------------------------------------
// The following macro is useful for checking if the creation of an
// internal object succeeds.
//
// We don't want to use exceptions to allow a constructor to indicate failure,
// so the object has to contain an 'IsValid()' member that returns TRUE if
// the object was successfully allocated. But then the caller has to write
// the following code:
//
// p = new Object();
// if (!p || !p->IsValid())
// {
// delete p;
// ...
//
// The following macro can be used to replace this with:
//
// p = new Object();
// if (!CheckValid(p))
// {
// ...
//
// !!!
// Note that CheckValid sets the input parameter to NULL
// when the return value is FALSE.
//
//--------------------------------------------------------------------------
template <class T>
inline BOOL
CheckValid(
T*& p
)
{
if (p && p->IsValid())
{
return TRUE;
}
else
{
delete p;
p = NULL;
return FALSE;
}
}
//--------------------------------------------------------------------------
// Name dynamic array types
//--------------------------------------------------------------------------
typedef DynArray<GpPointF> DynPointFArray;
typedef DynArray<GpPoint> DynPointArray;
typedef DynArray<BYTE> DynByteArray;
typedef DynArray<INT> DynIntArray;
typedef DynArray<REAL> DynRealArray;
typedef DynArray<VOID*> DynPointerArray;
//--------------------------------------------------------------------------
// Raw critical section object
// The Initialize function can throw.
//--------------------------------------------------------------------------
class GpSemaphore
{
private:
CRITICAL_SECTION CriticalSection;
BOOL Initialized;
public:
GpSemaphore()
{
Initialized = FALSE;
}
VOID
Initialize(
VOID
)
{
if (!Initialized)
{
// The caller has to have a Try_Except around us.
__try
{
InitializeCriticalSection(&CriticalSection);
}
__except(EXCEPTION_CONTINUE_SEARCH)
{
}
Initialized = TRUE;
}
}
VOID
Uninitialize(
VOID
);
VOID
Lock(
VOID
)
{
ASSERT(Initialized);
EnterCriticalSection(&CriticalSection);
}
VOID
Unlock(
VOID
)
{
ASSERT(Initialized);
LeaveCriticalSection(&CriticalSection);
}
BOOL
IsLocked(
VOID
);
BOOL
IsLockedByCurrentThread(
VOID
);
};
//------------------------------------------------------------------------
// FillMemoryInt32 - Fill an INT32 array with the specified value
// CopyMemoryInt32 - Copy INT32 values from one array to another
//------------------------------------------------------------------------
inline VOID
FillMemoryInt32(
VOID* buf,
INT count,
INT32 val
)
{
INT32* p = (INT32*) buf;
while (count-- > 0)
*p++ = val;
}
inline VOID
CopyMemoryInt32(
VOID* dst,
const VOID* src,
INT count
)
{
INT32* d = (INT32*) dst;
const INT32* s = (const INT32*) src;
while (count-- > 0)
*d++ = *s++;
}
//------------------------------------------------------------------------
// CompareExchangeLong_Ptr - Perform an interlocked compare-exchange
// on a LONG_PTR. Unfortunately, Win95 does not export
// InterlockedCompareExchange, so on that platform we have
// to create our own. But on NT, we CANNOT roll our own, because
// of MP and NT64 issues.
//
// This method should be called instead of calling through the
// Globals::InterlockedCompareExchangeFunction directly, because
// on Alpha machines, Globals::InterlockedCompareExchangeFunction does
// NOT get initialized.
//------------------------------------------------------------------------
inline LONG_PTR
CompareExchangeLong_Ptr(
LONG_PTR *destination,
LONG_PTR exchange,
LONG_PTR comperand
)
{
#if defined(_X86_)
return InterlockedCompareExchange(destination,
exchange,
comperand);
#else
return (LONG_PTR)InterlockedCompareExchangePointer(
(PVOID *)destination,
(PVOID)exchange,
(PVOID)comperand);
#endif
}
//------------------------------------------------------------------------
// CompareExchangePointer - Perform an interlocked compare-exchange
// on a pointer. Unfortunately, Win95 does not export
// InterlockedCompareExchangePointer, so on that platform we have
// to create our own. But on NT, we CANNOT roll our own, because
// of MP and NT64 issues.
//------------------------------------------------------------------------
inline VOID*
CompareExchangePointer(
VOID** destination,
VOID* exchange,
VOID* comperand
)
{
#if defined(_X86_)
return((VOID*) InterlockedCompareExchange((LONG*) destination,
(LONG) exchange,
(LONG) comperand));
#else
return(InterlockedCompareExchangePointer(destination,
exchange,
comperand));
#endif
}
//--------------------------------------------------------------------------
// This routine retrieves a quick, pre-allocated region from a one-deep
// cache. Note that the contents will be random. This call is intended
// largely for GDI API calls such as GetRandomRgn that require a pre-created
// region.
//
// NOTE: This can return a NULL region handle.
//--------------------------------------------------------------------------
inline
HRGN GetCachedGdiRegion(
VOID
)
{
HRGN regionHandle = Globals::CachedGdiRegion;
// If the Globals::CachedGdiRegion is NULL, that means that someone
// else has the cached region, so we create a new one.
// It is possible during multi thread access for us to create a region
// when it's not strictly necessary --- i.e. a thread releases the cached
// region when this thread is between the above assignment and the next
// if statement, but that's only non-optimal and we'll work correctly
// under those circumstances.
if ((regionHandle == NULL) ||
(CompareExchangePointer(
(VOID**) &Globals::CachedGdiRegion,
NULL,
(VOID*) regionHandle) != regionHandle
)
)
{
regionHandle = CreateRectRgn(0, 0, 1, 1);
}
return(regionHandle);
}
//--------------------------------------------------------------------------
// This routine releases a region to the one-deep cache.
//--------------------------------------------------------------------------
inline
VOID ReleaseCachedGdiRegion(
HRGN regionHandle
)
{
// Note that 'regionHandle' may be NULL at this point if the
// CreateRectRgn failed, but that's okay:
if (CompareExchangePointer((VOID**) &Globals::CachedGdiRegion,
(VOID*) regionHandle,
NULL) != NULL)
{
DeleteObject(regionHandle);
}
}
inline
HDC GetCleanHdc(
HWND hwnd
)
{
// Use GetDCEx(DCX_CACHE) to get a nice clean DC (not a CS_OWNDC).
// Note that with GetDCEx we have to explicitly respect the window's
// clipping styles. We stole this little bit of logic straight from
// ntuser\kernel\dc.c for the DCX_USESTYLE case:
DWORD getDcFlags = DCX_CACHE;
LONG classStyle = GetClassLongA(hwnd, GCL_STYLE);
LONG windowStyle = GetWindowLongA(hwnd, GWL_STYLE);
if (classStyle & CS_PARENTDC)
getDcFlags |= DCX_PARENTCLIP;
if (windowStyle & WS_CLIPCHILDREN)
getDcFlags |= DCX_CLIPCHILDREN;
if (windowStyle & WS_CLIPSIBLINGS)
getDcFlags |= DCX_CLIPSIBLINGS;
// Minimized windows never exclude their children.
if (windowStyle & WS_MINIMIZE)
getDcFlags &= ~DCX_CLIPCHILDREN;
return GetDCEx(hwnd, NULL, getDcFlags);
}
inline INT
GetIntDistance(
POINT & p1,
POINT & p2
)
{
double dx = (double)(p2.x - p1.x);
double dy = (double)(p2.y - p1.y);
REAL distance = (REAL)sqrt((dx * dx) + (dy * dy));
return GpRound(distance);
}
inline REAL
GetDistance(
GpPointF & p1,
GpPointF & p2
)
{
double dx = (double)p2.X - p1.X;
double dy = (double)p2.Y - p1.Y;
return (REAL)sqrt((dx * dx) + (dy * dy));
}
inline REAL
GetDegreesFromRadians(double radians)
{
return (REAL)(radians*180.0/3.1415926535897932);
}
// return angle in degrees from 2 points
inline REAL
GetAngleFromPoints(
const GpPointF & p1,
const GpPointF & p2
)
{
// Compute the angle of the line formed by p1 and p2.
// Note atan2 is only undefined if dP.Y == 0.0 and dP.X == 0.0
// and then it returns 0 radians.
// Also, atan2 correctly computes the quadrant from the two input points.
GpPointF dP = p2 - p1;
double radians = atan2((double)(dP.Y), (double)(dP.X));
return GetDegreesFromRadians(radians);
}
#define DEFAULT_RESOLUTION 96 // most display screens are set to 96 dpi
//--------------------------------------------------------------------------
// The following 3 functions should be used in place of GetObjectType due
// to a bug on Windows 9x where an OBJ_METAFILE and another type of object
// may share the same handle!
//
// GetObjectTypeInternal: Call this to determine any object type except
// when expecting OBJ_METAFILE or OBJ_*DC.
//
// GetDCType: Use this when the object should be a DC,and just the type of
// DC is required.
//
// IsValidMetaFile: OBJ_METAFILE is the special case. Use this function to
// validate when OBJ_METAFILE is expected. This only means
// there is a metafile with this handle. There could also
// be an "aliased" object which the caller intended to be
// used, so this should not be used to handle multiple
// object types.
//--------------------------------------------------------------------------
DWORD
GetObjectTypeInternal(
IN HGDIOBJ handle
);
DWORD
GetDCType(
IN HDC hdc
);
inline
BOOL
IsValidMetaFile(
HMETAFILE handle
)
{
return (GetObjectType(handle) == OBJ_METAFILE);
};
#endif // !_ENGINE_HPP