[APPSHIM_APITEST] Add test for shims in AcGenral
authorMark Jansen <mark.jansen@reactos.org>
Wed, 14 Jun 2017 16:38:41 +0000 (18:38 +0200)
committerMark Jansen <mark.jansen@reactos.org>
Sun, 21 Jan 2018 20:13:08 +0000 (21:13 +0100)
modules/rostests/apitests/appshim/CMakeLists.txt
modules/rostests/apitests/appshim/appshim_apitest.h [new file with mode: 0644]
modules/rostests/apitests/appshim/dispmode.c
modules/rostests/apitests/appshim/genral_hooks.c [new file with mode: 0644]
modules/rostests/apitests/appshim/testlist.c
modules/rostests/apitests/appshim/versionlie.c

index 48a4db1..fa7a765 100644 (file)
@@ -3,8 +3,10 @@ add_definitions(-D__ROS_LONG64__)
 
 list(APPEND SOURCE
     dispmode.c
+    genral_hooks.c
     versionlie.c
-    testlist.c)
+    testlist.c
+    appshim_apitest.h)
 
 add_executable(appshim_apitest ${SOURCE})
 set_module_type(appshim_apitest win32cui)
diff --git a/modules/rostests/apitests/appshim/appshim_apitest.h b/modules/rostests/apitests/appshim/appshim_apitest.h
new file mode 100644 (file)
index 0000000..1f3a0f6
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef APPSHIM_APITEST_H
+#define APPSHIM_APITEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct tagHOOKAPI {
+    PCSTR LibraryName;
+    PCSTR FunctionName;
+    PVOID ReplacementFunction;
+    PVOID OriginalFunction;
+    PVOID Unk1;
+    PVOID Unk2;
+} HOOKAPI, *PHOOKAPI;
+
+typedef BOOL (WINAPI* tSDBGETAPPPATCHDIR)(PVOID hsdb, LPWSTR path, DWORD size);
+typedef PHOOKAPI (WINAPI* tGETHOOKAPIS)(LPCSTR szCommandLine, LPCWSTR wszShimName, PDWORD pdwHookCount);
+
+
+/* versionlie.c */
+void expect_shim_imp(PHOOKAPI hook, PCSTR library, PCSTR function, PCSTR shim, int* same);
+#define expect_shim  (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_shim_imp
+
+
+BOOL LoadShimDLL(PCWSTR ShimDll, HMODULE* module, tGETHOOKAPIS* ppGetHookAPIs);
+tGETHOOKAPIS LoadShimDLL2(PCWSTR ShimDll);
+
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // APPHELP_APITEST_H
index 0f8b3aa..68c3b2f 100644 (file)
@@ -2,7 +2,7 @@
  * PROJECT:     appshim_apitest
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * PURPOSE:     Tests for display mode shims
- * COPYRIGHT:   Copyright 2016 Mark Jansen (mark.jansen@reactos.org)
+ * COPYRIGHT:   Copyright 2016-2018 Mark Jansen (mark.jansen@reactos.org)
  */
 
 #include <ntstatus.h>
 #include <strsafe.h>
 #include "wine/test.h"
 #include "apitest_iathook.h"
+#include "appshim_apitest.h"
 
 static DWORD g_Version;
 #define WINVER_ANY     0
 
-
-/* apphelp.dll */
-static BOOL(WINAPI* pSdbGetAppPatchDir)(PVOID, LPWSTR, DWORD);
-
 /* aclayers.dll / acgenral.dll */
-static PVOID(WINAPI* pGetHookAPIs)(LPCSTR, LPCWSTR, PDWORD);
+static tGETHOOKAPIS pGetHookAPIs;
 static BOOL(WINAPI* pNotifyShims)(DWORD fdwReason, PVOID ptr);
 
+
 DWORD get_module_version(HMODULE mod)
 {
     DWORD dwVersion = 0;
@@ -123,14 +121,6 @@ void WINAPI mSetThemeAppProperties(DWORD dwFlags)
 }
 
 
-static const WCHAR* shim_dll(const WCHAR* name)
-{
-    static WCHAR buf[MAX_PATH];
-    pSdbGetAppPatchDir(NULL, buf, MAX_PATH);
-    StringCchCatW(buf, _countof(buf), name);
-    return buf;
-}
-
 static void pre_8bit(void)
 {
     g_ChangeCount = 0;
@@ -379,18 +369,18 @@ static struct test_info
 } tests[] =
 {
     /* Success */
-    { "Force8BitColor", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_8bit, post_8bit, post_8bit_no },
-    { "Force8BitColor", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp,pre_8bit, post_8bit, post_8bit_no },
-    { "Force640x480", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_640, post_640, post_640_no },
-    { "Force640x480", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_640, post_640, post_640_no },
-    { "DisableThemes", L"\\acgenral.dll", WINVER_ANY, 1, hook_theme, unhook_theme, pre_theme, post_theme, post_theme_no },
-    { "DisableThemes", L"\\acgenral.dll", _WIN32_WINNT_VISTA, 100, hook_theme, unhook_theme, pre_theme, post_theme, post_theme_no },
+    { "Force8BitColor", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_8bit, post_8bit, post_8bit_no },
+    { "Force8BitColor", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp,pre_8bit, post_8bit, post_8bit_no },
+    { "Force640x480", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_640, post_640, post_640_no },
+    { "Force640x480", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_640, post_640, post_640_no },
+    { "DisableThemes", L"acgenral.dll", WINVER_ANY, 1, hook_theme, unhook_theme, pre_theme, post_theme, post_theme_no },
+    { "DisableThemes", L"acgenral.dll", _WIN32_WINNT_VISTA, 100, hook_theme, unhook_theme, pre_theme, post_theme, post_theme_no },
 
     /* No need to change anything */
-    { "Force8BitColor", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no },
-    { "Force8BitColor", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no },
-    { "Force640x480", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_640_2, post_640_2, post_640_2_no },
-    { "Force640x480", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_640_2, post_640_2, post_640_2_no },
+    { "Force8BitColor", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no },
+    { "Force8BitColor", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no },
+    { "Force640x480", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_640_2, post_640_2, post_640_2_no },
+    { "Force640x480", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_640_2, post_640_2, post_640_2_no },
 };
 
 
@@ -398,16 +388,15 @@ static void run_test(size_t n, BOOL unload)
 {
     BOOL ret;
     HMODULE dll;
-    const WCHAR* buf = shim_dll(tests[n].dll);
 
-    dll = LoadLibraryW(shim_dll(tests[n].dll));
-    pGetHookAPIs = (void*)GetProcAddress(dll, "GetHookAPIs");
+    if (!LoadShimDLL(tests[n].dll, &dll, &pGetHookAPIs))
+        pGetHookAPIs = NULL;
     pNotifyShims = (void*)GetProcAddress(dll, "NotifyShims");
 
     if (!pGetHookAPIs || !pNotifyShims)
     {
-        skip("aclayers.dll not loaded, or does not export GetHookAPIs or pNotifyShims (%s, %p, %p)\n",
-            tests[n].name, pGetHookAPIs, pNotifyShims);
+        skip("%s not loaded, or does not export GetHookAPIs or pNotifyShims (%s, %p, %p)\n",
+             wine_dbgstr_w(tests[n].dll), tests[n].name, pGetHookAPIs, pNotifyShims);
         return;
     }
 
@@ -435,8 +424,8 @@ static void run_test(size_t n, BOOL unload)
     FreeLibrary(dll);
     if (unload)
     {
-        dll = GetModuleHandleW(buf);
-        ok(dll == NULL, "Unable to unload %s\n", wine_dbgstr_w(buf));
+        dll = GetModuleHandleW(tests[n].dll);
+        ok(dll == NULL, "Unable to unload %s\n", wine_dbgstr_w(tests[n].dll));
     }
 }
 
@@ -448,21 +437,14 @@ START_TEST(dispmode)
     int argc;
     char **argv;
 
-    pSdbGetAppPatchDir = (void*)GetProcAddress(dll, "SdbGetAppPatchDir");
-    if (!pSdbGetAppPatchDir)
-    {
-        skip("apphelp.dll not loaded, or does not export SdbGetAppPatchDir\n");
-        return;
-    }
-
     argc = winetest_get_mainargs(&argv);
     if (argc < 3)
     {
         WCHAR path[MAX_PATH];
         GetModuleFileNameW(NULL, path, _countof(path));
-        dll = GetModuleHandleW(shim_dll(L"\\aclayers.dll"));
+        dll = GetModuleHandleW(L"aclayers.dll");
         if (!dll)
-            dll = GetModuleHandleW(shim_dll(L"\\acgenral.dll"));
+            dll = GetModuleHandleW(L"acgenral.dll");
         if (dll != NULL)
             trace("Loaded under a shim, running each test in it's own process\n");
 
diff --git a/modules/rostests/apitests/appshim/genral_hooks.c b/modules/rostests/apitests/appshim/genral_hooks.c
new file mode 100644 (file)
index 0000000..72680c7
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * PROJECT:     appshim_apitest
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Test to document the hooks used by various shims in AcGenral
+ * COPYRIGHT:   Copyright 2017-2018 Mark Jansen (mark.jansen@reactos.org)
+ */
+
+#include <ntstatus.h>
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <ndk/rtlfuncs.h>
+#include <strsafe.h>
+#include "wine/test.h"
+
+#include "appshim_apitest.h"
+
+static DWORD g_WinVersion;
+#define WINVER_WIN8    0x0602
+
+
+typedef struct expect_shim_hook
+{
+    const char* Library;
+    const char* Function;
+} expect_shim_hook;
+
+typedef struct expect_shim_data
+{
+    const WCHAR* ShimName;
+    DWORD MinVersion;
+    expect_shim_hook hooks[4];
+} expect_shim_data;
+
+
+static expect_shim_data data[] =
+{
+    {
+        L"IgnoreChromeSandbox",
+        WINVER_WIN8,
+        {
+            { "KERNEL32.DLL", "CreateProcessW" },
+        }
+    },
+    {
+        L"AddProcessParametersFlags",
+        0,
+        /* No hooks */
+    },
+    {
+        L"DisableThemes",
+        0,
+        /* No hooks */
+    },
+};
+
+static DWORD count_shims(expect_shim_data* data)
+{
+    DWORD num;
+    for (num = 0; num < _countof(data->hooks) && data->hooks[num].Library;)
+    {
+        ++num;
+    }
+    return num;
+}
+
+static const char* safe_str(const char* ptr)
+{
+    static char buffer[2][30];
+    static int index = 0;
+    if (HIWORD(ptr))
+        return ptr;
+
+    index ^= 1;
+    StringCchPrintfA(buffer[index], _countof(buffer[index]), "#%d", (int)ptr);
+    return buffer[index];
+}
+
+START_TEST(genral_hooks)
+{
+    RTL_OSVERSIONINFOEXW rtlinfo = {0};
+    size_t n, h;
+
+    tGETHOOKAPIS pGetHookAPIs = LoadShimDLL2(L"AcGenral.dll");
+    if (!pGetHookAPIs)
+        return;
+
+    rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo);
+    RtlGetVersion((PRTL_OSVERSIONINFOW)&rtlinfo);
+    g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
+
+
+
+    for (n = 0; n < _countof(data); ++n)
+    {
+        expect_shim_data* current = data + n;
+        DWORD num_shims = 0, expected_shims = count_shims(current);
+
+        PHOOKAPI hook = pGetHookAPIs("", current->ShimName, &num_shims);
+
+        if (current->MinVersion > g_WinVersion && !hook)
+            continue;
+
+        ok(!!hook, "Expected a valid pointer, got nothing for %s\n", wine_dbgstr_w(current->ShimName));
+        ok(num_shims == expected_shims, "Expected %u shims, got %u for %s\n",
+           expected_shims, num_shims, wine_dbgstr_w(current->ShimName));
+        for (h = 0; h < min(num_shims, expected_shims); ++h)
+        {
+            expect_shim_hook* expect_hk = current->hooks + h;
+            PHOOKAPI got_hk = hook+h;
+            int lib = lstrcmpA(expect_hk->Library, got_hk->LibraryName);
+            int fn = lstrcmpA(safe_str(expect_hk->Function), safe_str(got_hk->FunctionName));
+            ok(lib == 0, "Expected LibraryName to be %s, was: %s for %s\n",
+               expect_hk->Library, got_hk->LibraryName, wine_dbgstr_w(current->ShimName));
+            ok(fn == 0, "Expected FunctionName to be %s, was: %s for %s\n",
+               safe_str(expect_hk->Function), safe_str(got_hk->FunctionName), wine_dbgstr_w(current->ShimName));
+        }
+        if (num_shims > expected_shims)
+        {
+            for (h = expected_shims; h < num_shims; ++h)
+            {
+                PHOOKAPI got_hk = hook+h;
+
+                ok(0, "Extra shim: %s!%s for %s\n",
+                   got_hk->LibraryName, safe_str(got_hk->FunctionName), wine_dbgstr_w(current->ShimName));
+            }
+        }
+        else
+        {
+            for (h = num_shims; h < expected_shims; ++h)
+            {
+                expect_shim_hook* expect_hk = current->hooks + h;
+
+                ok(0, "Missing shim: %s!%s for %s\n",
+                   expect_hk->Library, safe_str(expect_hk->Function), wine_dbgstr_w(current->ShimName));
+            }
+        }
+    }
+}
index b3b8a21..2b2e692 100644 (file)
@@ -4,11 +4,13 @@
 #include <wine/test.h>
 
 extern void func_dispmode(void);
+extern void func_genral_hooks(void);
 extern void func_versionlie(void);
 
 const struct test winetest_testlist[] =
 {
     { "dispmode", func_dispmode },
+    { "genral_hooks", func_genral_hooks },
     { "versionlie", func_versionlie },
     { 0, 0 }
 };
index ad38731..5322b8a 100644 (file)
@@ -2,7 +2,7 @@
  * PROJECT:     appshim_apitest
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * PURPOSE:     Tests for versionlie shims
- * COPYRIGHT:   Copyright 2015 Mark Jansen (mark.jansen@reactos.org)
+ * COPYRIGHT:   Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org)
  */
 
 #include <ntstatus.h>
 #else
 #include <winternl.h>
 #endif
-#include <stdio.h>
 #include "wine/test.h"
+#include <strsafe.h>
 
-typedef struct tagHOOKAPI {
-    PCSTR LibraryName;
-    PCSTR FunctionName;
-    PVOID ReplacementFunction;
-    PVOID OriginalFunction;
-    PVOID Unk1;
-    PVOID Unk2;
-} HOOKAPI, *PHOOKAPI;
+#include "appshim_apitest.h"
 
-static BOOL (WINAPI* pSdbGetAppPatchDir)(PVOID,LPWSTR,DWORD);
-static PHOOKAPI (WINAPI* pGetHookAPIs)(LPCSTR,LPCWSTR,PDWORD);
+static tGETHOOKAPIS pGetHookAPIs;
 
 
 static DWORD g_WinVersion;
@@ -48,7 +40,7 @@ typedef BOOL(WINAPI* GETVERSIONEXAPROC)(LPOSVERSIONINFOEXA);
 typedef BOOL(WINAPI* GETVERSIONEXWPROC)(LPOSVERSIONINFOEXW);
 typedef DWORD(WINAPI* GETVERSIONPROC)(void);
 
-static void expect_shim_imp(PHOOKAPI hook, PCSTR library, PCSTR function, PCSTR shim, int* same)
+void expect_shim_imp(PHOOKAPI hook, PCSTR library, PCSTR function, PCSTR shim, int* same)
 {
     int lib = lstrcmpA(library, hook->LibraryName);
     int fn = lstrcmpA(function, hook->FunctionName);
@@ -86,7 +78,7 @@ static void verify_shima_imp(PHOOKAPI hook, const VersionLieInfo* info, PCSTR sh
             winetest_ok(info->dwPlatformId == v2.dwPlatformId, "Expected dwPlatformId to be equal, was: %u, %u for %s\n", info->dwPlatformId, v2.dwPlatformId, shim);
 
             if (info->wServicePackMajor)
-                sprintf(szCSDVersion, "Service Pack %u", info->wServicePackMajor);
+                StringCchPrintfA(szCSDVersion, _countof(szCSDVersion), "Service Pack %u", info->wServicePackMajor);
             winetest_ok(lstrcmpA(szCSDVersion, v2.szCSDVersion) == 0, "Expected szCSDVersion to be equal, was: %s, %s for %s\n", szCSDVersion, v2.szCSDVersion, shim);
 
             if (v1.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA))
@@ -150,7 +142,6 @@ static void verify_shimw_imp(PHOOKAPI hook, const VersionLieInfo* info, PCSTR sh
         }
         if (ok1 && ok2)
         {
-            static const WCHAR szCSDFMT[] = {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','%','u',0};
             WCHAR szCSDVersion[128] = { 0 };
             winetest_ok(v1.dwOSVersionInfoSize == v2.dwOSVersionInfoSize, "Expected dwOSVersionInfoSize to be equal, was: %u, %u for %s\n", v1.dwOSVersionInfoSize, v2.dwOSVersionInfoSize, shim);
             winetest_ok(info->dwMajorVersion == v2.dwMajorVersion, "Expected dwMajorVersion to be equal, was: %u, %u for %s\n", info->dwMajorVersion, v2.dwMajorVersion, shim);
@@ -159,7 +150,7 @@ static void verify_shimw_imp(PHOOKAPI hook, const VersionLieInfo* info, PCSTR sh
             winetest_ok(info->dwPlatformId == v2.dwPlatformId, "Expected dwPlatformId to be equal, was: %u, %u for %s\n", info->dwPlatformId, v2.dwPlatformId, shim);
 
             if (info->wServicePackMajor)
-                swprintf(szCSDVersion, szCSDFMT, info->wServicePackMajor);
+                StringCchPrintfW(szCSDVersion, _countof(szCSDVersion), L"Service Pack %u", info->wServicePackMajor);
             winetest_ok(lstrcmpW(szCSDVersion, v2.szCSDVersion) == 0, "Expected szCSDVersion to be equal, was: %s, %s for %s\n", wine_dbgstr_w(szCSDVersion), wine_dbgstr_w(v2.szCSDVersion), shim);
 
             if (v1.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
@@ -209,7 +200,6 @@ static void verify_shim_imp(PHOOKAPI hook, const VersionLieInfo* info, PCSTR shi
 }
 
 
-#define expect_shim  (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_shim_imp
 #define verify_shima  (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_shima_imp
 #define verify_shimw  (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_shimw_imp
 #define verify_shim  (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_shim_imp
@@ -303,28 +293,78 @@ DWORD get_host_winver(void)
     return (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
 }
 
-START_TEST(versionlie)
+BOOL LoadShimDLL(PCWSTR ShimDll, HMODULE* module, tGETHOOKAPIS* ppGetHookAPIs)
 {
-    HMODULE dll = LoadLibraryA("apphelp.dll");
-    WCHAR buf[MAX_PATH];
-    WCHAR aclayers[] = {'\\','a','c','l','a','y','e','r','s','.','d','l','l',0};
-    pSdbGetAppPatchDir = (void*)GetProcAddress(dll, "SdbGetAppPatchDir");
+    static tSDBGETAPPPATCHDIR pSdbGetAppPatchDir = NULL;
+    HMODULE dll;
+    WCHAR buf[MAX_PATH] = {0};
     if (!pSdbGetAppPatchDir)
     {
-        skip("apphelp.dll not loaded, or does not export SdbGetAppPatchDir\n");
-        return;
+        dll = LoadLibraryA("apphelp.dll");
+        pSdbGetAppPatchDir = (tSDBGETAPPPATCHDIR)GetProcAddress(dll, "SdbGetAppPatchDir");
+
+        if (!pSdbGetAppPatchDir)
+        {
+            skip("Unable to retrieve SdbGetAppPatchDir (%p, %p)\n", dll, pSdbGetAppPatchDir);
+        }
+    }
+
+    if (!pSdbGetAppPatchDir || !pSdbGetAppPatchDir(NULL, buf, MAX_PATH))
+    {
+        skip("Unable to retrieve AppPatch dir, building manually\n");
+        if (!GetSystemWindowsDirectoryW(buf, MAX_PATH))
+        {
+            skip("Unable to build AppPatch name(1)\n");
+            return FALSE;
+        }
+        if (!SUCCEEDED(StringCchCatW(buf, _countof(buf), L"\\AppPatch")))
+        {
+            skip("Unable to build AppPatch name(2)\n");
+            return FALSE;
+        }
+    }
+    if (!SUCCEEDED(StringCchCatW(buf, _countof(buf), L"\\")) ||
+        !SUCCEEDED(StringCchCatW(buf, _countof(buf), ShimDll)))
+    {
+        skip("Unable to append dll name\n");
+        return FALSE;
     }
 
-    pSdbGetAppPatchDir(NULL, buf, MAX_PATH);
-    lstrcatW(buf, aclayers);
     dll = LoadLibraryW(buf);
-    pGetHookAPIs = (void*)GetProcAddress(dll, "GetHookAPIs");
+    if (!dll)
+    {
+        skip("Unable to load shim dll\n");
+        return FALSE;
+    }
+    *module = dll;
+    *ppGetHookAPIs = (tGETHOOKAPIS)GetProcAddress(dll, "GetHookAPIs");
 
-    if (!pGetHookAPIs)
+    return *ppGetHookAPIs != NULL;
+}
+
+
+tGETHOOKAPIS LoadShimDLL2(PCWSTR ShimDll)
+{
+    HMODULE module;
+    tGETHOOKAPIS pGetHookAPIs;
+
+    if (LoadShimDLL(ShimDll, &module, &pGetHookAPIs))
     {
-        skip("aclayers.dll not loaded, or does not export GetHookAPIs\n");
-        return;
+        if (!pGetHookAPIs)
+            skip("No GetHookAPIs found\n");
+        return pGetHookAPIs;
     }
+    return NULL;
+}
+
+
+START_TEST(versionlie)
+{
+    pGetHookAPIs = LoadShimDLL2(L"aclayers.dll");
+
+    if (!pGetHookAPIs)
+        return;
+
     g_WinVersion = get_host_winver();
 
     run_test("Win95VersionLie", &g_Win95);