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