Index: reactos/dll/appcompat/shims/layer/CMakeLists.txt =================================================================== --- reactos/dll/appcompat/shims/layer/CMakeLists.txt (revision 73422) +++ reactos/dll/appcompat/shims/layer/CMakeLists.txt (working copy) @@ -4,6 +4,7 @@ spec2def(aclayers.dll layer.spec) list(APPEND SOURCE + dispmode.c versionlie.c main.c layer.spec) @@ -14,5 +15,5 @@ set_module_type(aclayers win32dll) target_link_libraries(aclayers shimlib) -add_importlibs(aclayers msvcrt kernel32 ntdll) +add_importlibs(aclayers user32 msvcrt kernel32 ntdll) add_cd_file(TARGET aclayers DESTINATION reactos/AppPatch FOR all) Index: reactos/dll/appcompat/shims/layer/dispmode.c =================================================================== --- reactos/dll/appcompat/shims/layer/dispmode.c (nonexistent) +++ reactos/dll/appcompat/shims/layer/dispmode.c (working copy) @@ -0,0 +1,67 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Shim library + * FILE: dll/appcompat/shims/layer/dispmode.c + * PURPOSE: Display settings related shims + * PROGRAMMER: Mark Jansen + */ + +#include +#include +#include + + +#define SHIM_NS Force8BitColor +#include + +#define SHIM_NUM_HOOKS 0 +#define SHIM_NOTIFY_FN SHIM_OBJ_NAME(Notify) + +BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) +{ + if (fdwReason == SHIM_REASON_INIT) + { + DEVMODEA dm = { { 0 } }; + dm.dmSize = sizeof(dm); + if (EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm) && + dm.dmBitsPerPel != 8) + { + dm.dmBitsPerPel = 8; + dm.dmFields |= DM_BITSPERPEL; + ChangeDisplaySettingsA(&dm, CDS_FULLSCREEN); + } + } + return TRUE; +} + +#include + + + +#define SHIM_NS Force640x480 +#include + +#define SHIM_NUM_HOOKS 0 +#define SHIM_NOTIFY_FN SHIM_OBJ_NAME(Notify) + +BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) +{ + if (fdwReason == SHIM_REASON_INIT) + { + DEVMODEA dm = { { 0 } }; + dm.dmSize = sizeof(dm); + if (EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm) && + (dm.dmPelsWidth != 640 || dm.dmPelsHeight != 480)) + { + dm.dmPelsWidth = 640; + dm.dmPelsHeight = 480; + dm.dmFields |= (DM_PELSWIDTH | DM_PELSHEIGHT); + ChangeDisplaySettingsA(&dm, CDS_FULLSCREEN); + } + } + return TRUE; +} + +#include + + Index: reactos/dll/appcompat/shims/layer/main.c =================================================================== --- reactos/dll/appcompat/shims/layer/main.c (revision 73422) +++ reactos/dll/appcompat/shims/layer/main.c (working copy) @@ -16,10 +16,10 @@ return ShimLib_GetHookAPIs(szCommandLine, wszShimName, pdwHookCount); } -/* PLDR_DATA_TABLE_ENTRY */ -BOOL WINAPI NotifyShims(DWORD fdwReason, PVOID P) +/* Forward to the generic implementation */ +BOOL WINAPI NotifyShims(DWORD fdwReason, PVOID ptr) { - return TRUE; + return ShimLib_NotifyShims(fdwReason, ptr); } BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) Index: reactos/dll/appcompat/shims/layer/versionlie.c =================================================================== --- reactos/dll/appcompat/shims/layer/versionlie.c (revision 73422) +++ reactos/dll/appcompat/shims/layer/versionlie.c (working copy) @@ -89,7 +89,6 @@ #define SHIM_NS Win95VersionLie - #include DWORD WINAPI SHIM_OBJ_NAME(APIHook_GetVersion)() @@ -128,7 +127,6 @@ #define SHIM_NS Win98VersionLie - #include DWORD WINAPI SHIM_OBJ_NAME(APIHook_GetVersion)() Index: reactos/dll/appcompat/shims/layer/versionlie.inl =================================================================== --- reactos/dll/appcompat/shims/layer/versionlie.inl (revision 73422) +++ reactos/dll/appcompat/shims/layer/versionlie.inl (working copy) @@ -43,9 +43,9 @@ return FALSE; } -BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason) +BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) { - if (fdwReason == SHIM_REASON_ATTACH && VERSION_INFO.wServicePackMajor) + if (fdwReason == SHIM_NOTIFY_ATTACH && VERSION_INFO.wServicePackMajor) { static CONST WCHAR szServicePack[] = {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','%','u',0}; HRESULT hr = StringCbPrintfA(VERSION_INFO.szCSDVersionA, sizeof(VERSION_INFO.szCSDVersionA), Index: reactos/dll/appcompat/shims/shimlib/CMakeLists.txt =================================================================== --- reactos/dll/appcompat/shims/shimlib/CMakeLists.txt (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/CMakeLists.txt (working copy) @@ -1,7 +1,11 @@ list(APPEND SOURCE + shimdbgsupp.c shimlib.c - shimlib.h) + shimlib.h + # These .inl functions are included so they show up in vs + setup_shim.inl + implement_shim.inl) add_library(shimlib ${SOURCE}) -add_dependencies(shimlib xdk) +add_dependencies(shimlib psdk) Index: reactos/dll/appcompat/shims/shimlib/implement_shim.inl =================================================================== --- reactos/dll/appcompat/shims/shimlib/implement_shim.inl (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/implement_shim.inl (working copy) @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Shim library * FILE: dll/appcompat/shims/shimlib/implement_shim.inl - * PURPOSE: Shimlib helper file, used to register shims using the earlier prepared macro's + * PURPOSE: Shimlib helper file, used to register shims setup with macro's from setup_shim.inl * PROGRAMMER: Mark Jansen */ @@ -18,57 +18,56 @@ #error "setup_shim.inl should be included before this file!" #endif +#if SHIM_NUM_HOOKS > 0 #ifndef SHIM_SETUP_HOOKS #error "Please define a hook: #define SHIM_SETUP_HOOKS SHIM_HOOK(num, dll_name, function_name, your_function)" #endif +#else +#ifdef SHIM_SETUP_HOOKS +#error "Hooks are defined, yet SHIM_NUM_HOOKS is <= 0 !" +#endif +#endif -PHOOKAPI WINAPI SHIM_OBJ_NAME(InitializeHooksMulti)(DWORD fdwReason, PCSTR pszCmdLine, PDWORD pdwHookCount) +PHOOKAPI WINAPI SHIM_OBJ_NAME(GetHookAPIs)(DWORD fdwReason, PCSTR pszCmdLine, PDWORD pdwHookCount) { - if (fdwReason == SHIM_REASON_ATTACH) + if (pszCmdLine) { - if (pszCmdLine) - { - SHIM_OBJ_NAME(g_szCommandLine) = ShimLib_StringDuplicateA(pszCmdLine); - } - else - { - SHIM_OBJ_NAME(g_szCommandLine) = ""; - } - SHIM_OBJ_NAME(g_pAPIHooks) = ShimLib_ShimMalloc(sizeof(HOOKAPI) * SHIM_NUM_HOOKS); - ZeroMemory(SHIM_OBJ_NAME(g_pAPIHooks), sizeof(HOOKAPI) * SHIM_NUM_HOOKS); - *pdwHookCount = SHIM_NUM_HOOKS; + SHIM_OBJ_NAME(g_szCommandLine) = ShimLib_StringDuplicateA(pszCmdLine); } + else + { + SHIM_OBJ_NAME(g_szCommandLine) = ""; + } + SHIM_OBJ_NAME(g_pAPIHooks) = ShimLib_ShimMalloc(sizeof(HOOKAPI) * SHIM_NUM_HOOKS); + ZeroMemory(SHIM_OBJ_NAME(g_pAPIHooks), sizeof(HOOKAPI) * SHIM_NUM_HOOKS); + *pdwHookCount = SHIM_NUM_HOOKS; #ifdef SHIM_NOTIFY_FN - if (!SHIM_NOTIFY_FN(fdwReason) && fdwReason == SHIM_REASON_ATTACH) + if (!SHIM_NOTIFY_FN(fdwReason, NULL)) return NULL; #endif - if (fdwReason == SHIM_REASON_ATTACH) - { - SHIM_SETUP_HOOKS - } +#if SHIM_NUM_HOOKS > 0 + SHIM_SETUP_HOOKS +#endif return SHIM_OBJ_NAME(g_pAPIHooks); } -PVOID SHIM_OBJ_NAME(FindShim)(PCWSTR wszString) -{ - PCSTR szString = SHIM_OBJ_NAME(g_szModuleName); - while (*szString == *wszString) - { - if (!*szString) - return SHIM_OBJ_NAME(InitializeHooksMulti); - szString++; wszString++; - } - return NULL; -} - #if defined(_MSC_VER) #pragma section(".shm$BBB",long,read) #endif -_SHMALLOC(".shm$BBB") _PVSHIM SHIM_OBJ_NAME(_shim_fn) = SHIM_OBJ_NAME(FindShim); +_SHMALLOC(".shm$BBB") SHIMREG SHIM_OBJ_NAME(_shim_fn) = +{ + SHIM_OBJ_NAME(GetHookAPIs), +#ifdef SHIM_NOTIFY_FN + SHIM_NOTIFY_FN, +#else + NULL, +#endif + SHIM_STRINGIFY(SHIM_NS) +}; #undef SHIM_SETUP_HOOKS #undef SHIM_NOTIFY_FN Index: reactos/dll/appcompat/shims/shimlib/setup_shim.inl =================================================================== --- reactos/dll/appcompat/shims/shimlib/setup_shim.inl (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/setup_shim.inl (working copy) @@ -19,13 +19,15 @@ #define SHIM_STRINGIFY2(X_) # X_ #define SHIM_STRINGIFY(X_) SHIM_STRINGIFY2(X_) +/* TODO: static_assert on (num < SHIM_NUM_HOOKS) */ + #define SHIM_HOOK(num, dll, function, target) \ SHIM_OBJ_NAME(g_pAPIHooks)[num].LibraryName = dll; \ SHIM_OBJ_NAME(g_pAPIHooks)[num].FunctionName = function; \ SHIM_OBJ_NAME(g_pAPIHooks)[num].ReplacementFunction = target; \ SHIM_OBJ_NAME(g_pAPIHooks)[num].OriginalFunction = NULL; \ - SHIM_OBJ_NAME(g_pAPIHooks)[num].Unk1 = NULL; \ - SHIM_OBJ_NAME(g_pAPIHooks)[num].Unk2 = NULL; + SHIM_OBJ_NAME(g_pAPIHooks)[num].Reserved[0] = NULL; \ + SHIM_OBJ_NAME(g_pAPIHooks)[num].Reserved[1] = NULL; #define CALL_SHIM(SHIM_NUM, SHIM_CALLCONV) \ ((SHIM_CALLCONV)(SHIM_OBJ_NAME(g_pAPIHooks)[SHIM_NUM].OriginalFunction)) Index: reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c =================================================================== --- reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c (nonexistent) +++ reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c (working copy) @@ -0,0 +1,79 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Shim library + * FILE: dll/appcompat/shims/shimlib/shimdbgsupp.c + * PURPOSE: Shim debug helper functions + * PROGRAMMER: Mark Jansen + */ + +#include +#include +#include +#include + +#include "wine/winternl.h" + +#define DPFLTR_APPCOMPAT_ID 123 + +void ApphelppInitDebugSupport(PCWSTR KeyName, PULONG Level); +static void SeiInitDebugSupport() +{ + ApphelppInitDebugSupport(L"SHIMENG_DEBUG_LEVEL", &g_ShimEngDebugLevel); +} + + +/** + * Outputs diagnostic info. + * + * @param [in] Level The level to log this message with, choose any of [SHIM_ERR, + * SHIM_WARN, SHIM_INFO]. + * @param [in] FunctionName The function this log should be attributed to. + * @param [in] Format The format string. + * @param ... Variable arguments providing additional information. + * + * @return Success: TRUE Failure: FALSE. + */ +BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...) +{ + char Buffer[512]; + va_list ArgList; + char* Current = Buffer; + const char* LevelStr; + size_t Length = sizeof(Buffer); + + if (g_ShimEngDebugLevel == 0xffffffff) + SeiInitDebugSupport(); + + if (Level > g_ShimEngDebugLevel) + return FALSE; + + switch (Level) + { + case SEI_ERR: + LevelStr = "Err "; + Level = DPFLTR_MASK | (1 << DPFLTR_ERROR_LEVEL); + break; + case SEI_WARN: + LevelStr = "Warn"; + Level = DPFLTR_MASK | (1 << DPFLTR_WARNING_LEVEL); + break; + case SEI_INFO: + LevelStr = "Info"; + Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL); + break; + default: + LevelStr = "User"; + Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL); + break; + } + StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s][%-20s] ", LevelStr, FunctionName); + va_start(ArgList, Format); + StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList); + va_end(ArgList); +#if defined(APPCOMPAT_USE_DBGPRINTEX) && APPCOMPAT_USE_DBGPRINTEX + return NT_SUCCESS(DbgPrintEx(DPFLTR_APPCOMPAT_ID, Level, "%s", Buffer)); +#else + OutputDebugStringA(Buffer); + return TRUE; +#endif +} Index: reactos/dll/appcompat/shims/shimlib/shimlib.c =================================================================== --- reactos/dll/appcompat/shims/shimlib/shimlib.c (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/shimlib.c (working copy) @@ -11,13 +11,22 @@ #include #include -HINSTANCE g_hinstDll; +typedef struct UsedShim +{ + SLIST_ENTRY Entry; + PSHIMREG pShim; +} UsedShim, *pUsedShim; + + static HANDLE g_ShimLib_Heap; +static PSLIST_HEADER g_UsedShims; void ShimLib_Init(HINSTANCE hInstance) { - g_hinstDll = hInstance; g_ShimLib_Heap = HeapCreate(0, 0x10000, 0); + + g_UsedShims = (PSLIST_HEADER)ShimLib_ShimMalloc(sizeof(SLIST_HEADER)); + RtlInitializeSListHead(g_UsedShims); } void ShimLib_Deinit() @@ -43,6 +52,18 @@ return lstrcpyA(NewString, szString); } +BOOL ShimLib_StrAEqualsW(PCSTR szString, PCWSTR wszString) +{ + while (*szString == *wszString) + { + if (!*szString) + return TRUE; + + szString++; wszString++; + } + return FALSE; +} + #if defined(_MSC_VER) #if defined(_M_IA64) || defined(_M_AMD64) @@ -62,8 +83,8 @@ #endif -_SHMALLOC(".shm") _PVSHIM _shim_start = 0; -_SHMALLOC(".shm$ZZZ") _PVSHIM _shim_end = 0; +_SHMALLOC(".shm") SHIMREG _shim_start = { 0 }; +_SHMALLOC(".shm$ZZZ") SHIMREG _shim_end = { 0 }; /* Generic GetHookAPIs function. @@ -72,18 +93,19 @@ This helper function will return the correct shim, and call the init function */ PHOOKAPI WINAPI ShimLib_GetHookAPIs(IN LPCSTR szCommandLine, IN LPCWSTR wszShimName, OUT PDWORD pdwHookCount) { - uintptr_t ps = (uintptr_t)&_shim_start; - ps += sizeof(uintptr_t); - for (; ps != (uintptr_t)&_shim_end; ps += sizeof(uintptr_t)) + PSHIMREG ps = &_shim_start; + ps++; + for (; ps != &_shim_end; ps++) { - _PVSHIM* pfunc = (_PVSHIM *)ps; - if (*pfunc != NULL) + if (ps->GetHookAPIs != NULL && ps->ShimName != NULL) { - PVOID res = (*pfunc)(wszShimName); - if (res) + if (ShimLib_StrAEqualsW(ps->ShimName, wszShimName)) { - PHOOKAPI (WINAPI* PFN)(DWORD, PCSTR, PDWORD) = res; - return (*PFN)(SHIM_REASON_ATTACH, szCommandLine, pdwHookCount); + pUsedShim shim = (pUsedShim)ShimLib_ShimMalloc(sizeof(UsedShim)); + shim->pShim = ps; + RtlInterlockedPushEntrySList(g_UsedShims, &(shim->Entry)); + + return ps->GetHookAPIs(SHIM_NOTIFY_ATTACH, szCommandLine, pdwHookCount); } } } @@ -90,3 +112,24 @@ return NULL; } + +/* PLDR_DATA_TABLE_ENTRY */ +BOOL WINAPI ShimLib_NotifyShims(DWORD fdwReason, PVOID ptr) +{ + PSLIST_ENTRY pEntry = RtlFirstEntrySList(g_UsedShims); + + if (fdwReason < SHIM_REASON_INIT) + fdwReason += (SHIM_REASON_INIT - SHIM_NOTIFY_ATTACH); + + while (pEntry) + { + pUsedShim pUsed = CONTAINING_RECORD(pEntry, UsedShim, Entry); + _PVNotify Notify = pUsed->pShim->Notify; + if (Notify) + Notify(fdwReason, ptr); + + pEntry = pEntry->Next; + } + + return TRUE; +} Index: reactos/dll/appcompat/shims/shimlib/shimlib.h =================================================================== --- reactos/dll/appcompat/shims/shimlib/shimlib.h (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/shimlib.h (working copy) @@ -8,33 +8,73 @@ #pragma once -typedef struct tagHOOKAPI { +typedef struct tagHOOKAPI +{ PCSTR LibraryName; PCSTR FunctionName; PVOID ReplacementFunction; PVOID OriginalFunction; - PVOID Unk1; - PVOID Unk2; + PVOID Reserved[2]; } HOOKAPI, *PHOOKAPI; -extern HINSTANCE g_hinstDll; -void ShimLib_Init(HINSTANCE); -void ShimLib_Deinit(void); PVOID ShimLib_ShimMalloc(SIZE_T); void ShimLib_ShimFree(PVOID); PCSTR ShimLib_StringDuplicateA(PCSTR); +BOOL ShimLib_StrAEqualsW(PCSTR, PCWSTR); + + +/* Forward events to generic handlers */ +void ShimLib_Init(HINSTANCE); +void ShimLib_Deinit(void); PHOOKAPI WINAPI ShimLib_GetHookAPIs(LPCSTR,LPCWSTR,PDWORD); +BOOL WINAPI ShimLib_NotifyShims(DWORD fdwReason, PVOID ptr); -#define SHIM_REASON_ATTACH 1 -#define SHIM_REASON_DETACH 2 -#define SHIM_REASON_DLL_LOAD 3 /* Arg: PLDR_DATA_TABLE_ENTRY */ -#define SHIM_REASON_DLL_UNLOAD 4 /* Arg: Module Handle */ +/* Shims should respond to SHIM_REASON_XXXX in the Notify routines. + SHIM_NOTIFY_ codes are sent by apphelp, and translated to SHIM_REASON_ by the shimlib routines. + The only exception being SHIM_NOTIFY_ATTACH, that is also set for one-time init. + */ +#define SHIM_REASON_INIT 100 +#define SHIM_REASON_DEINIT 101 +#define SHIM_REASON_DLL_LOAD 102 /* Arg: PLDR_DATA_TABLE_ENTRY */ +#define SHIM_REASON_DLL_UNLOAD 103 /* Arg: PLDR_DATA_TABLE_ENTRY */ -typedef PVOID (__cdecl *_PVSHIM)(PCWSTR); +#define SHIM_NOTIFY_ATTACH 1 +#define SHIM_NOTIFY_DETACH 2 +#define SHIM_NOTIFY_DLL_LOAD 3 /* Arg: PLDR_DATA_TABLE_ENTRY */ +#define SHIM_NOTIFY_DLL_UNLOAD 4 /* Arg: PLDR_DATA_TABLE_ENTRY */ + + +typedef enum _SEI_LOG_LEVEL { + SEI_ERR = 1, + SEI_WARN = 2, + SEI_INFO = 3, +} SEI_LOG_LEVEL; + +BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...); +extern ULONG g_ShimEngDebugLevel; + +#define SHIMENG_ERR(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_ERR, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0) +#define SHIMENG_WARN(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_WARN, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0) +#define SHIMENG_INFO(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_INFO, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0) + + + +typedef PHOOKAPI (WINAPI* _PVGetHookAPIs)(DWORD, PCSTR, PDWORD); +typedef BOOL (WINAPI* _PVNotify)(DWORD, PVOID); + +typedef struct tagSHIMREG +{ + _PVGetHookAPIs GetHookAPIs; + _PVNotify Notify; + PCSTR ShimName; + //BOOL* pShimUsed; +} SHIMREG, *PSHIMREG; + + #if defined(_MSC_VER) #define _SHMALLOC(x) __declspec(allocate(x)) #elif defined(__GNUC__) Index: reactos/media/sdb/readme.txt =================================================================== --- reactos/media/sdb/readme.txt (nonexistent) +++ reactos/media/sdb/readme.txt (working copy) @@ -0,0 +1,20 @@ + +Sdb + +Sdb files are Shim Databases. +They contain information about bad applications, and about the fixes that can be applied to them. + + +Shims + +A shim is a piece of code that influences the process it's applied to. +This can be done by calling certain api's, or by changing the behavior of api's. +'DisableThemes' is an example of a shim that changes behavior by calling 'SetThemeAppProperties'. +'Win95VersionLie' is an example of a shim that changes behavior, by intercepting calls to GetVersion[Ex]. + +Layers + +A layer is a collection (1..n) of shims. +Layers are used to reference a collection of shims by name. + + Index: reactos/media/sdb/sysmain.xml =================================================================== --- reactos/media/sdb/sysmain.xml (revision 73422) +++ reactos/media/sdb/sysmain.xml (working copy) @@ -4,6 +4,9 @@ 1 {11111111-1111-1111-1111-111111111111} + + + Win95VersionLie aclayers.dll @@ -76,7 +79,29 @@ Win7RTMVersionLie aclayers.dll + + + + + Force640x480 + aclayers.dll + + + Force8BitColor + aclayers.dll + + + + + + DisableThemes + acgenral.dll + + + + + WIN95 @@ -182,5 +207,26 @@ + + + + + 256Color + + + + + 640X480 + + + + + + + + DisableThemes + + + \ No newline at end of file Index: rostests/apitests/appshim/dispmode.c =================================================================== --- rostests/apitests/appshim/dispmode.c (revision 73422) +++ rostests/apitests/appshim/dispmode.c (working copy) @@ -42,7 +42,7 @@ static BOOL(WINAPI* pNotifyShims)(DWORD fdwReason, PVOID ptr); -static LONG g_Count; +static LONG g_ChangeCount; static DEVMODEA g_LastDevmode; static DWORD g_LastFlags; @@ -49,7 +49,7 @@ static LONG (WINAPI *pChangeDisplaySettingsA)(_In_opt_ PDEVMODEA lpDevMode, _In_ DWORD dwflags); LONG WINAPI mChangeDisplaySettingsA(_In_opt_ PDEVMODEA lpDevMode, _In_ DWORD dwflags) { - g_Count++; + g_ChangeCount++; g_LastDevmode = *lpDevMode; g_LastFlags = dwflags; @@ -56,6 +56,38 @@ return DISP_CHANGE_FAILED; } +static LONG g_EnumCount; + +static BOOL (WINAPI *pEnumDisplaySettingsA)(_In_opt_ LPCSTR lpszDeviceName, _In_ DWORD iModeNum, _Inout_ PDEVMODEA lpDevMode); +BOOL WINAPI mEnumDisplaySettingsA(_In_opt_ LPCSTR lpszDeviceName, _In_ DWORD iModeNum, _Inout_ PDEVMODEA lpDevMode) +{ + g_EnumCount++; + if (pEnumDisplaySettingsA(lpszDeviceName, iModeNum, lpDevMode)) + { + if (lpDevMode && lpDevMode->dmBitsPerPel == 8) + { + int old = winetest_debug; + winetest_debug = 1; + trace("Running at 8bpp, faking 16\n"); + winetest_debug = old; + lpDevMode->dmBitsPerPel = 16; + } + if (lpDevMode && lpDevMode->dmPelsWidth == 640 && lpDevMode->dmPelsHeight == 480) + { + int old = winetest_debug; + winetest_debug = 1; + trace("Running at 640x480, faking 800x600\n"); + winetest_debug = old; + lpDevMode->dmPelsWidth = 800; + lpDevMode->dmPelsHeight = 600; + } + return TRUE; + } + return FALSE; +} + + + static LONG g_ThemeCount; static DWORD g_LastThemeFlags; @@ -77,33 +109,37 @@ static void pre_8bit(void) { - g_Count = 0; + g_ChangeCount = 0; memset(&g_LastDevmode, 0, sizeof(g_LastDevmode)); g_LastFlags = 0xffffffff; + g_EnumCount = 0; } static void post_8bit(void) { - ok_int(g_Count, 1); + ok_int(g_ChangeCount, 1); ok_hex(g_LastDevmode.dmFields & DM_BITSPERPEL, DM_BITSPERPEL); ok_int(g_LastDevmode.dmBitsPerPel, 8); ok_hex(g_LastFlags, CDS_FULLSCREEN); + ok_int(g_EnumCount, 1); } static void pre_640(void) { - g_Count = 0; + g_ChangeCount = 0; memset(&g_LastDevmode, 0, sizeof(g_LastDevmode)); g_LastFlags = 0xffffffff; + g_EnumCount = 0; } static void post_640(void) { - ok_int(g_Count, 1); + ok_int(g_ChangeCount, 1); ok_hex(g_LastDevmode.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT), (DM_PELSWIDTH | DM_PELSHEIGHT)); ok_int(g_LastDevmode.dmPelsWidth, 640); ok_int(g_LastDevmode.dmPelsHeight, 480); ok_hex(g_LastFlags, CDS_FULLSCREEN); + ok_int(g_EnumCount, 1); } static void pre_theme(void) @@ -173,7 +209,8 @@ static BOOL hook_disp(HMODULE dll) { - return RedirectIat(dll, "user32.dll", "ChangeDisplaySettingsA", (ULONG_PTR)mChangeDisplaySettingsA, (ULONG_PTR*)&pChangeDisplaySettingsA); + return RedirectIat(dll, "user32.dll", "ChangeDisplaySettingsA", (ULONG_PTR)mChangeDisplaySettingsA, (ULONG_PTR*)&pChangeDisplaySettingsA) && + RedirectIat(dll, "user32.dll", "EnumDisplaySettingsA", (ULONG_PTR)mEnumDisplaySettingsA, (ULONG_PTR*)&pEnumDisplaySettingsA); } static BOOL hook_theme(HMODULE dll) @@ -322,10 +359,8 @@ } } - if (failures != winetest_get_failures()) - { - trace("Failures from %d (%s)\n", n, tests[n].name); - } + ok(failures == winetest_get_failures(), "Last %u failures are from %d (%s)\n", + winetest_get_failures() - failures, n, tests[n].name); } } else