Windows2003-3790/windows/appcompat/shims/general/correctcreatesurface.cpp
2020-09-30 16:53:55 +02:00

440 lines
10 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
CorrectCreateSurface.cpp
Abstract:
Clean up bad ddraw CreateSurface caps.
Command Line FIX;CHK:Flags;DEL:Flags;ADD=Flags
e.g., - FIX;CHK:DDSCAPS_TEXTURE;DEL:DDSCAPS_3DDEVICE
FIX - Sets the flags which indicate whether to
fix the flags and call the interface or to
make a call and retry after fixing caps if the call fails.
The default is to call the interface with
passed in parameters and if the call fails
then the flags are fixed and a retry is made.
CHK - Check for flags (condition)
ADD - Add flags
DEL - Delete flags
Notes:
This is a general purpose shim.
History:
02/16/2001 a-leelat Created
02/13/2002 astritz Security Review
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(CorrectCreateSurface)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY_DIRECTX_COMSERVER()
APIHOOK_ENUM_END
IMPLEMENT_DIRECTX_COMSERVER_HOOKS()
DWORD g_dwFlagsChk = 0;
DWORD g_dwFlagsAdd = 0;
DWORD g_dwFlagsDel = 0;
BOOL g_bTryAndFix = TRUE;
struct DDFLAGS
{
WCHAR * lpszFlagName;
DWORD dwFlag;
};
//Hold the falg entries
//add any undefined flags to this array
static DDFLAGS g_DDFlags[] =
{
{L"DDSCAPS_3DDEVICE", DDSCAPS_3DDEVICE},
{L"DDSCAPS_ALLOCONLOAD", DDSCAPS_ALLOCONLOAD},
{L"DDSCAPS_ALPHA", DDSCAPS_ALPHA},
{L"DDSCAPS_BACKBUFFER", DDSCAPS_BACKBUFFER},
{L"DDSCAPS_COMPLEX", DDSCAPS_COMPLEX},
{L"DDSCAPS_FLIP", DDSCAPS_FLIP},
{L"DDSCAPS_FRONTBUFFER", DDSCAPS_FRONTBUFFER},
{L"DDSCAPS_HWCODEC", DDSCAPS_HWCODEC},
{L"DDSCAPS_LIVEVIDEO", DDSCAPS_LIVEVIDEO},
{L"DDSCAPS_LOCALVIDMEM", DDSCAPS_LOCALVIDMEM},
{L"DDSCAPS_MIPMAP", DDSCAPS_MIPMAP},
{L"DDSCAPS_MODEX", DDSCAPS_MODEX},
{L"DDSCAPS_NONLOCALVIDMEM", DDSCAPS_NONLOCALVIDMEM},
{L"DDSCAPS_OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
{L"DDSCAPS_OPTIMIZED", DDSCAPS_OPTIMIZED},
{L"DDSCAPS_OVERLAY", DDSCAPS_OVERLAY},
{L"DDSCAPS_OWNDC", DDSCAPS_OWNDC},
{L"DDSCAPS_PALETTE", DDSCAPS_PALETTE},
{L"DDSCAPS_PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
{L"DDSCAPS_STANDARDVGAMODE", DDSCAPS_STANDARDVGAMODE},
{L"DDSCAPS_SYSTEMMEMORY", DDSCAPS_SYSTEMMEMORY},
{L"DDSCAPS_TEXTURE", DDSCAPS_TEXTURE},
{L"DDSCAPS_VIDEOMEMORY", DDSCAPS_VIDEOMEMORY},
{L"DDSCAPS_VIDEOPORT", DDSCAPS_VIDEOPORT},
{L"DDSCAPS_VISIBLE", DDSCAPS_VISIBLE},
{L"DDSCAPS_WRITEONLY", DDSCAPS_WRITEONLY},
{L"DDSCAPS_ZBUFFER", DDSCAPS_ZBUFFER},
};
#define DDFLAGSSIZE sizeof(g_DDFlags) / sizeof(g_DDFlags[0])
DWORD GetDWord(const CString & lpFlag)
{
for ( int i = 0; i < DDFLAGSSIZE; i++ )
{
if (lpFlag.CompareNoCase(g_DDFlags[i].lpszFlagName) == 0)
{
return g_DDFlags[i].dwFlag;
}
}
return 0;
}
const WCHAR * GetName(DWORD dwDDSCAPS)
{
for ( int i = 0; i < DDFLAGSSIZE; i++ )
{
if (g_DDFlags[i].dwFlag == dwDDSCAPS)
{
return g_DDFlags[i].lpszFlagName;
}
}
return NULL;
}
VOID FixCaps(LPDDSURFACEDESC lpDDSurfaceDesc)
{
if ( lpDDSurfaceDesc->dwFlags & DDSD_CAPS )
{
//To Check
if( !lpDDSurfaceDesc->ddsCaps.dwCaps || lpDDSurfaceDesc->ddsCaps.dwCaps & g_dwFlagsChk )
{
//To remove
lpDDSurfaceDesc->ddsCaps.dwCaps &= ~g_dwFlagsDel;
//To add
lpDDSurfaceDesc->ddsCaps.dwCaps |= g_dwFlagsAdd;
}
}
}
VOID FixCaps2(LPDDSURFACEDESC2 lpDDSurfaceDesc)
{
if ( lpDDSurfaceDesc->dwFlags & DDSD_CAPS )
{
//To Check
if ( !lpDDSurfaceDesc->ddsCaps.dwCaps || lpDDSurfaceDesc->ddsCaps.dwCaps & g_dwFlagsChk )
{
//To remove
lpDDSurfaceDesc->ddsCaps.dwCaps &= ~g_dwFlagsDel;
//To add
lpDDSurfaceDesc->ddsCaps.dwCaps |= g_dwFlagsAdd;
}
}
}
HRESULT
COMHOOK(IDirectDraw, CreateSurface)(
PVOID pThis,
LPDDSURFACEDESC lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface,
IUnknown* pUnkOuter
)
{
_pfn_IDirectDraw_CreateSurface pfnOld =
ORIGINAL_COM(IDirectDraw, CreateSurface, pThis);
//Fix it anyway
if ( !g_bTryAndFix )
FixCaps(lpDDSurfaceDesc);
HRESULT hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
if ( (hRet == DDERR_INVALIDCAPS) || (hRet == DDERR_INVALIDPIXELFORMAT)||
(hRet == DDERR_UNSUPPORTED) || (hRet == DDERR_OUTOFVIDEOMEMORY ) ||
(hRet == DDERR_INVALIDPARAMS) )
{
FixCaps(lpDDSurfaceDesc);
hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
}
return hRet;
}
/*++
Hook create surface and fix parameters
--*/
HRESULT
COMHOOK(IDirectDraw2, CreateSurface)(
PVOID pThis,
LPDDSURFACEDESC lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface,
IUnknown* pUnkOuter
)
{
_pfn_IDirectDraw2_CreateSurface pfnOld =
ORIGINAL_COM(IDirectDraw2, CreateSurface, pThis);
//Fix it anyway
if ( !g_bTryAndFix )
FixCaps(lpDDSurfaceDesc);
HRESULT hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
if ( (hRet == DDERR_INVALIDCAPS) || (hRet == DDERR_INVALIDPIXELFORMAT) ||
(hRet == DDERR_UNSUPPORTED) || (hRet == DDERR_OUTOFVIDEOMEMORY ) ||
(hRet == DDERR_INVALIDPARAMS) )
{
FixCaps(lpDDSurfaceDesc);
hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
}
return hRet;
}
/*++
Hook create surface and fix parameters
--*/
HRESULT
COMHOOK(IDirectDraw4, CreateSurface)(
PVOID pThis,
LPDDSURFACEDESC2 lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface,
IUnknown* pUnkOuter
)
{
_pfn_IDirectDraw4_CreateSurface pfnOld =
ORIGINAL_COM(IDirectDraw4, CreateSurface, pThis);
//Fix it anyway
if ( !g_bTryAndFix )
FixCaps2(lpDDSurfaceDesc);
HRESULT hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
if ( (hRet == DDERR_INVALIDCAPS) || (hRet == DDERR_INVALIDPIXELFORMAT) ||
(hRet == DDERR_UNSUPPORTED) || (hRet == DDERR_OUTOFVIDEOMEMORY ) ||
(hRet == DDERR_INVALIDPARAMS) )
{
FixCaps2(lpDDSurfaceDesc);
hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
}
return hRet;
}
/*++
Hook create surface and fix parameters
--*/
HRESULT
COMHOOK(IDirectDraw7, CreateSurface)(
PVOID pThis,
LPDDSURFACEDESC2 lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface,
IUnknown* pUnkOuter
)
{
_pfn_IDirectDraw7_CreateSurface pfnOld =
ORIGINAL_COM(IDirectDraw7, CreateSurface, pThis);
if ( !g_bTryAndFix )
FixCaps2(lpDDSurfaceDesc);
HRESULT hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
if ( (hRet == DDERR_INVALIDCAPS) || (hRet == DDERR_INVALIDPIXELFORMAT) ||
(hRet == DDERR_UNSUPPORTED) || (hRet == DDERR_OUTOFVIDEOMEMORY) ||
(hRet == DDERR_INVALIDPARAMS ) )
{
FixCaps2(lpDDSurfaceDesc);
hRet = (*pfnOld)(
pThis,
lpDDSurfaceDesc,
lplpDDSurface,
pUnkOuter);
}
return hRet;
}
BOOL
ParseCommandLine(const char * lpszCommandLine)
{
CSTRING_TRY
{
DPFN( eDbgLevelInfo, "[ParseCommandLine] CommandLine(%s)\n", lpszCommandLine);
CStringToken csCommandLine(lpszCommandLine, ";|:=");
CString csOperator;
while (csCommandLine.GetToken(csOperator))
{
if (csOperator.CompareNoCase(L"Fix") == 0)
{
//Go ahead and fix the caps
//before we make the call.
g_bTryAndFix = FALSE;
DPFN( eDbgLevelInfo, "[ParseCommandLine] Do not fix\n", lpszCommandLine);
}
else
{
// The next token is the caps to add
CString csDDSCAPS;
csCommandLine.GetToken(csDDSCAPS);
DWORD dwDDSCAPS = GetDWord(csDDSCAPS); // returns 0 for unknown DDSCAPS
if (dwDDSCAPS)
{
if (csOperator.CompareNoCase(L"Add") == 0)
{
DPFN( eDbgLevelInfo, "[ParseCommandLine] Add(%S)\n", GetName(dwDDSCAPS));
g_dwFlagsAdd |= dwDDSCAPS;
}
else if (csOperator.CompareNoCase(L"Del") == 0)
{
DPFN( eDbgLevelInfo, "[ParseCommandLine] Del(%S)\n", GetName(dwDDSCAPS));
g_dwFlagsDel |= dwDDSCAPS;
}
else if (csOperator.CompareNoCase(L"Chk") == 0)
{
DPFN( eDbgLevelInfo, "[ParseCommandLine] Chk(%S)\n", GetName(dwDDSCAPS));
g_dwFlagsChk |= dwDDSCAPS;
}
}
}
}
}
CSTRING_CATCH
{
return FALSE;
}
return TRUE;
}
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason)
{
BOOL bSuccess = TRUE;
if (fdwReason == DLL_PROCESS_ATTACH)
{
// Run the command line to check for adjustments to defaults
bSuccess = ParseCommandLine(COMMAND_LINE);
}
return bSuccess;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
CALL_NOTIFY_FUNCTION
APIHOOK_ENTRY_DIRECTX_COMSERVER()
COMHOOK_ENTRY(DirectDraw, IDirectDraw, CreateSurface, 6)
COMHOOK_ENTRY(DirectDraw, IDirectDraw2, CreateSurface, 6)
COMHOOK_ENTRY(DirectDraw, IDirectDraw4, CreateSurface, 6)
COMHOOK_ENTRY(DirectDraw, IDirectDraw7, CreateSurface, 6)
HOOK_END
IMPLEMENT_SHIM_END