553 lines
16 KiB
C++
553 lines
16 KiB
C++
/***************************************************************************\
|
|
*
|
|
* File: OSAL.cpp
|
|
*
|
|
* Description:
|
|
* OSAL.cpp implements the process-wide Operating System Abstraction Layer
|
|
* that allows DirectUser to run on different platforms.
|
|
*
|
|
*
|
|
* History:
|
|
* 1/18/2000: JStall: Created
|
|
*
|
|
* Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "Services.h"
|
|
#include "OSAL.h"
|
|
|
|
#define ENABLE_WINNT 1
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* Define OSAL's for different operating systems.
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
#if ENABLE_WINNT
|
|
|
|
//------------------------------------------------------------------------------
|
|
class WinNT : public OSAL
|
|
{
|
|
// USER Operations
|
|
public:
|
|
virtual int DrawText(HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);
|
|
|
|
// GDI Operations
|
|
public:
|
|
virtual BOOL TextOut(HDC, int, int, LPCWSTR, int);
|
|
virtual BOOL ExtTextOut(HDC, int, int, UINT, const RECT *, LPCWSTR, int, const int *);
|
|
virtual HFONT CreateFontIndirect(CONST LOGFONTW *);
|
|
virtual BOOL GetTextExtentPoint32(HDC, LPCWSTR, int, LPSIZE);
|
|
virtual BOOL GetTextExtentExPoint(HDC, LPCWSTR, int, int, LPINT, LPINT, LPSIZE);
|
|
|
|
// DirectUser/Core
|
|
public:
|
|
virtual void PushXForm(HDC hdc, XFORM * pxfOld);
|
|
virtual void PopXForm(HDC hdc, const XFORM * pxfOld);
|
|
virtual void RotateDC(HDC hdc, float flRotationRad);
|
|
virtual void ScaleDC(HDC hdc, float flScaleX, float flScaleY);
|
|
virtual void TranslateDC(HDC hdc, float flOffsetX, float flOffsetY);
|
|
virtual void SetWorldTransform(HDC hdc, const XFORM * pxfOld);
|
|
virtual void SetIdentityTransform(HDC hdc);
|
|
|
|
// DirectUser/Services
|
|
public:
|
|
virtual BOOL IsInsideLoaderLock();
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
class Win9x : public OSAL
|
|
{
|
|
// USER Operations
|
|
public:
|
|
virtual int DrawText(HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);
|
|
|
|
// GDI Operations
|
|
public:
|
|
virtual BOOL TextOut(HDC, int, int, LPCWSTR, int);
|
|
virtual BOOL ExtTextOut(HDC, int, int, UINT, const RECT *, LPCWSTR, int, const int *);
|
|
virtual HFONT CreateFontIndirect(CONST LOGFONTW *);
|
|
virtual BOOL GetTextExtentPoint32(HDC, LPCWSTR, int, LPSIZE);
|
|
virtual BOOL GetTextExtentExPoint(HDC, LPCWSTR, int, int, LPINT, LPINT, LPSIZE);
|
|
|
|
// DirectUser/Core
|
|
public:
|
|
virtual void PushXForm(HDC hdc, XFORM * pxfOld);
|
|
virtual void PopXForm(HDC hdc, const XFORM * pxfOld);
|
|
virtual void RotateDC(HDC hdc, float flRotationRad);
|
|
virtual void ScaleDC(HDC hdc, float flScaleX, float flScaleY);
|
|
virtual void TranslateDC(HDC hdc, float flOffsetX, float flOffsetY);
|
|
virtual void SetWorldTransform(HDC hdc, const XFORM * pxfOld);
|
|
virtual void SetIdentityTransform(HDC hdc);
|
|
|
|
// DirectUser/Services
|
|
public:
|
|
virtual BOOL IsInsideLoaderLock();
|
|
};
|
|
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* String Conversion Macros
|
|
*
|
|
* These macros are extensions of the normal ATLCONV that are designed to
|
|
* take the length of the string as a parameter instead of computing it.
|
|
* This gives better performance, and gives parity on platforms when the
|
|
* string has embedded '\0's.
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
#ifdef _CONVERSION_USES_THREAD_LOCALE
|
|
#define W2AN(lpw, cch) (\
|
|
((_lpw = lpw) == NULL) ? NULL : (\
|
|
_convert = (cch+1)*2,\
|
|
ATLW2AHELPER((LPSTR) alloca(_convert), _lpw, _convert, _acp)))
|
|
#else
|
|
#define W2AN(lpw, cch) (\
|
|
((_lpw = lpw) == NULL) ? NULL : (\
|
|
_convert = (cch+1)*2,\
|
|
ATLW2AHELPER((LPSTR) alloca(_convert), _lpw, _convert)))
|
|
#endif
|
|
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* class OSAL
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
OSAL * g_pOS = NULL;
|
|
OSInfo g_OSI;
|
|
PTOP_LEVEL_EXCEPTION_FILTER g_pfnRtlUnhandledExceptionFilter = NULL;
|
|
PRTL_IS_THREAD_WITHIN_LOADER_CALLOUT g_pfnRtlIsThreadWithinLoaderCallout = NULL;
|
|
|
|
class OSALCleanup
|
|
{
|
|
public:
|
|
~OSALCleanup()
|
|
{
|
|
ProcessDelete(OSAL, g_pOS);
|
|
g_pOS = NULL;
|
|
};
|
|
} g_OSALCleanup;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
OSAL::Init()
|
|
{
|
|
AssertMsg(g_pOS == NULL, "Only init one time");
|
|
|
|
OSVERSIONINFO ovi;
|
|
ZeroMemory(&ovi, sizeof(ovi));
|
|
ovi.dwOSVersionInfoSize = sizeof(ovi);
|
|
|
|
VerifyMsg(GetVersionEx(&ovi), "Must always be able to get the version");
|
|
|
|
g_OSI.fQInputAvailableFlag = IsWin98orWin2000(&ovi);
|
|
|
|
#if ENABLE_WINNT
|
|
if (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
|
//
|
|
// Running on Win9x, so don't have UNICODE
|
|
//
|
|
|
|
g_OSI.fUnicode = FALSE;
|
|
g_OSI.fXForm = FALSE;
|
|
g_pOS = ProcessNew(Win9x);
|
|
} else if (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
|
//
|
|
// Running on NT, so have UNICODE
|
|
//
|
|
|
|
g_OSI.fUnicode = TRUE;
|
|
g_OSI.fXForm = TRUE;
|
|
g_pOS = ProcessNew(WinNT);
|
|
|
|
HINSTANCE hinst = LoadLibrary("ntdll.dll");
|
|
if (hinst != NULL) {
|
|
g_pfnRtlUnhandledExceptionFilter = (PTOP_LEVEL_EXCEPTION_FILTER)
|
|
GetProcAddress(hinst, "RtlUnhandledExceptionFilter");
|
|
g_pfnRtlIsThreadWithinLoaderCallout =
|
|
(PRTL_IS_THREAD_WITHIN_LOADER_CALLOUT)GetProcAddress(hinst, "RtlIsThreadWithinLoaderCallout");
|
|
}
|
|
} else {
|
|
AssertMsg(0, "Unsupported OS");
|
|
return E_NOTIMPL;
|
|
}
|
|
#else // ENABLE_WINNT
|
|
g_OSI.fUnicode = FALSE;
|
|
g_OSI.fXForm = FALSE;
|
|
g_pOS = ProcessNew(Win9x);
|
|
#endif // ENABLE_WINNT
|
|
|
|
return g_pOS != NULL ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
LONG WINAPI
|
|
StdExceptionFilter(PEXCEPTION_POINTERS pei)
|
|
{
|
|
AutoTrace("ERROR: Unhandled exception during callback.\n");
|
|
AutoTrace("ERROR: This is not a problem with DirectUser.\n");
|
|
|
|
//
|
|
// Output Exception information
|
|
//
|
|
|
|
LONG nResult;
|
|
|
|
if (g_pfnRtlUnhandledExceptionFilter != NULL) {
|
|
nResult = (g_pfnRtlUnhandledExceptionFilter)(pei);
|
|
} else {
|
|
AutoTrace(" *** enter .exr %p for the exception record\n", pei->ExceptionRecord);
|
|
AutoTrace(" *** enter .cxr %p for the context\n", pei->ContextRecord);
|
|
|
|
nResult = EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
if (nResult == EXCEPTION_CONTINUE_SEARCH) {
|
|
return UnhandledExceptionFilter(pei);
|
|
} else {
|
|
return nResult;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* class WinNT
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
#if ENABLE_WINNT
|
|
|
|
//------------------------------------------------------------------------------
|
|
int
|
|
WinNT::DrawText(HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat)
|
|
{
|
|
return ::DrawTextW(hDC, lpString, nCount, lpRect, uFormat);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
WinNT::TextOut(HDC hdc, int x, int y, LPCWSTR psz, int cch)
|
|
{
|
|
return ::TextOutW(hdc, x, y, psz, cch);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
WinNT::ExtTextOut(HDC hdc, int x, int y, UINT fuOptions, const RECT * prc, LPCWSTR psz, int cch, const int * pDx)
|
|
{
|
|
return ::ExtTextOutW(hdc, x, y, fuOptions, prc, psz, cch, pDx);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HFONT
|
|
WinNT::CreateFontIndirect(CONST LOGFONTW * plf)
|
|
{
|
|
return ::CreateFontIndirectW(plf);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
WinNT::GetTextExtentPoint32(HDC hdc, LPCWSTR psz, int cch, LPSIZE psize)
|
|
{
|
|
return ::GetTextExtentPoint32W(hdc, psz, cch, psize);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
WinNT::GetTextExtentExPoint(HDC hdc, LPCWSTR psz, int cch, int nMax,
|
|
LPINT pnFit, LPINT apDx, LPSIZE psize)
|
|
{
|
|
return ::GetTextExtentExPointW(hdc, psz, cch, nMax, pnFit, apDx, psize);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
WinNT::PushXForm(HDC hdc, XFORM * pxfOld)
|
|
{
|
|
::GetWorldTransform(hdc, pxfOld);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
WinNT::PopXForm(HDC hdc, const XFORM * pxfOld)
|
|
{
|
|
::SetWorldTransform(hdc, pxfOld);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
WinNT::RotateDC(HDC hdc, float flRotationRad)
|
|
{
|
|
AssertMsg(GetGraphicsMode(hdc) == GM_ADVANCED, "Only can do in advanced mode");
|
|
|
|
float flCos = (float) cos(flRotationRad);
|
|
float flSin = (float) sin(flRotationRad);
|
|
|
|
XFORM xf;
|
|
xf.eM11 = flCos;
|
|
xf.eM12 = flSin;
|
|
xf.eM21 = - flSin;
|
|
xf.eM22 = flCos;
|
|
xf.eDx = 0;
|
|
xf.eDy = 0;
|
|
|
|
::ModifyWorldTransform(hdc, &xf, MWT_LEFTMULTIPLY);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
WinNT::ScaleDC(HDC hdc, float flScaleX, float flScaleY)
|
|
{
|
|
AssertMsg(GetGraphicsMode(hdc) == GM_ADVANCED, "Only can do in advanced mode");
|
|
|
|
XFORM xf;
|
|
xf.eM11 = flScaleX;
|
|
xf.eM12 = 0;
|
|
xf.eM21 = 0;
|
|
xf.eM22 = flScaleY;
|
|
xf.eDx = 0;
|
|
xf.eDy = 0;
|
|
|
|
::ModifyWorldTransform(hdc, &xf, MWT_LEFTMULTIPLY);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
WinNT::TranslateDC(HDC hdc, float flOffsetX, float flOffsetY)
|
|
{
|
|
AssertMsg(GetGraphicsMode(hdc) == GM_ADVANCED, "Only can do in advanced mode");
|
|
|
|
XFORM xf;
|
|
xf.eM11 = 1.0;
|
|
xf.eM12 = 0;
|
|
xf.eM21 = 0;
|
|
xf.eM22 = 1.0;
|
|
xf.eDx = flOffsetX;
|
|
xf.eDy = flOffsetY;
|
|
|
|
::ModifyWorldTransform(hdc, &xf, MWT_LEFTMULTIPLY);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
WinNT::SetWorldTransform(HDC hdc, const XFORM * pxf)
|
|
{
|
|
::SetWorldTransform(hdc, pxf);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
WinNT::SetIdentityTransform(HDC hdc)
|
|
{
|
|
ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
WinNT::IsInsideLoaderLock()
|
|
{
|
|
if (g_pfnRtlIsThreadWithinLoaderCallout != NULL) {
|
|
return (*g_pfnRtlIsThreadWithinLoaderCallout)() ? TRUE : FALSE;
|
|
} else {
|
|
PRTL_CRITICAL_SECTION pCS;
|
|
/*
|
|
* If we failed to find this export, then fallback to our bogus, XP
|
|
* behavior where we explicitly check the loader lock.
|
|
*/
|
|
pCS = reinterpret_cast<PRTL_CRITICAL_SECTION>(NtCurrentPeb()->LoaderLock);
|
|
return (HandleToUlong(pCS->OwningThread) == GetCurrentThreadId());
|
|
}
|
|
}
|
|
|
|
|
|
#endif // ENABLE_WINNT
|
|
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* class Win9x
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
//------------------------------------------------------------------------------
|
|
int
|
|
Win9x::DrawText(HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat)
|
|
{
|
|
USES_CONVERSION;
|
|
return ::DrawTextA(hDC, W2AN(lpString, nCount), nCount, lpRect, uFormat);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
Win9x::TextOut(HDC hdc, int x, int y, LPCWSTR psz, int cch)
|
|
{
|
|
return ::TextOutW(hdc, x, y, psz, cch);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
Win9x::ExtTextOut(HDC hdc, int x, int y, UINT fuOptions, const RECT * prc, LPCWSTR psz, int cch, const int * pDx)
|
|
{
|
|
return ::ExtTextOutW(hdc, x, y, fuOptions, prc, psz, cch, pDx);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HFONT
|
|
Win9x::CreateFontIndirect(CONST LOGFONTW * plf)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
LOGFONT lf;
|
|
lf.lfHeight = plf->lfHeight;
|
|
lf.lfWidth = plf->lfWidth;
|
|
lf.lfEscapement = plf->lfEscapement;
|
|
lf.lfOrientation = plf->lfOrientation;
|
|
lf.lfWeight = plf->lfWeight;
|
|
lf.lfItalic = plf->lfItalic;
|
|
lf.lfUnderline = plf->lfUnderline;
|
|
lf.lfStrikeOut = plf->lfStrikeOut;
|
|
lf.lfCharSet = plf->lfCharSet;
|
|
lf.lfOutPrecision = plf->lfOutPrecision;
|
|
lf.lfClipPrecision = plf->lfClipPrecision;
|
|
lf.lfQuality = plf->lfQuality;
|
|
lf.lfPitchAndFamily = plf->lfPitchAndFamily;
|
|
AtlW2AHelper(lf.lfFaceName, plf->lfFaceName, lstrlenW(plf->lfFaceName) + 1);
|
|
|
|
return ::CreateFontIndirectA(&lf);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
Win9x::GetTextExtentPoint32(HDC hdc, LPCWSTR psz, int cch, LPSIZE psize)
|
|
{
|
|
USES_CONVERSION;
|
|
return ::GetTextExtentPoint32A(hdc, W2AN(psz, cch), cch, psize);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
Win9x::GetTextExtentExPoint(HDC hdc, LPCWSTR psz, int cch, int nMax,
|
|
LPINT pnFit, LPINT apDx, LPSIZE psize)
|
|
{
|
|
USES_CONVERSION;
|
|
return ::GetTextExtentExPointA(hdc, W2AN(psz, cch), cch, nMax, pnFit, apDx, psize);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
Win9x::PushXForm(HDC hdc, XFORM * pxfOld)
|
|
{
|
|
POINT pt;
|
|
::GetWindowOrgEx(hdc, &pt);
|
|
pxfOld->eM11 = 1.0f;
|
|
pxfOld->eM12 = 0.0f;
|
|
pxfOld->eM21 = 0.0f;
|
|
pxfOld->eM22 = 1.0f;
|
|
pxfOld->eDx = (float) pt.x;
|
|
pxfOld->eDy = (float) pt.y;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
Win9x::PopXForm(HDC hdc, const XFORM * pxfOld)
|
|
{
|
|
POINT pt;
|
|
pt.x = (long) pxfOld->eDx;
|
|
pt.y = (long) pxfOld->eDy;
|
|
::SetWindowOrgEx(hdc, pt.x, pt.y, NULL);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
Win9x::RotateDC(HDC hdc, float flRotationRad)
|
|
{
|
|
UNREFERENCED_PARAMETER(hdc);
|
|
UNREFERENCED_PARAMETER(flRotationRad);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
Win9x::ScaleDC(HDC hdc, float flScaleX, float flScaleY)
|
|
{
|
|
UNREFERENCED_PARAMETER(hdc);
|
|
UNREFERENCED_PARAMETER(flScaleX);
|
|
UNREFERENCED_PARAMETER(flScaleY);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
Win9x::TranslateDC(HDC hdc, float flOffsetX, float flOffsetY)
|
|
{
|
|
::OffsetWindowOrgEx(hdc, -(int) flOffsetX, -(int) flOffsetY, NULL);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
Win9x::SetWorldTransform(HDC hdc, const XFORM * pxf)
|
|
{
|
|
::SetWindowOrgEx(hdc, -(int) pxf->eDx, -(int) pxf->eDy, NULL);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
Win9x::SetIdentityTransform(HDC hdc)
|
|
{
|
|
::SetWindowOrgEx(hdc, 0, 0, NULL);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOL
|
|
Win9x::IsInsideLoaderLock()
|
|
{
|
|
return FALSE;
|
|
}
|