1 /*
2  * PROJECT:     appshim_apitest
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Test to document the hooks used by various shims in AcLayers
5  * COPYRIGHT:   Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include <ntstatus.h>
9 #define WIN32_NO_STATUS
10 #include <windows.h>
11 #include <ndk/rtlfuncs.h>
12 #include <strsafe.h>
13 #include "wine/test.h"
14 
15 #include "appshim_apitest.h"
16 
17 static DWORD g_WinVersion;
18 
19 
20 typedef struct expect_shim_hook
21 {
22     const char* Library;
23     const char* Function;
24 } expect_shim_hook;
25 
26 typedef struct expect_shim_data
27 {
28     const WCHAR* ShimName;
29     DWORD MinVersion;
30     expect_shim_hook hooks[6];
31 } expect_shim_data;
32 
33 
34 static expect_shim_data data[] =
35 {
36     {
37         L"ForceDXSetupSuccess",
38         0,
39         {
40             { "KERNEL32.DLL", "LoadLibraryA" },
41             { "KERNEL32.DLL", "LoadLibraryW" },
42             { "KERNEL32.DLL", "LoadLibraryExA" },
43             { "KERNEL32.DLL", "LoadLibraryExW" },
44             { "KERNEL32.DLL", "GetProcAddress" },
45             { "KERNEL32.DLL", "FreeLibrary" },
46         }
47     },
48     {
49         L"VerifyVersionInfoLite",
50         _WIN32_WINNT_VISTA,
51         {
52             { "KERNEL32.DLL", "VerifyVersionInfoA" },
53             { "KERNEL32.DLL", "VerifyVersionInfoW" },
54         }
55     },
56     /* Show that it is not case sensitive */
57     {
58         L"VeRiFyVeRsIoNInFoLiTe",
59         _WIN32_WINNT_VISTA,
60         {
61             { "KERNEL32.DLL", "VerifyVersionInfoA" },
62             { "KERNEL32.DLL", "VerifyVersionInfoW" },
63         }
64     },
65 };
66 
67 static DWORD count_shims(expect_shim_data* data)
68 {
69     DWORD num;
70     for (num = 0; num < _countof(data->hooks) && data->hooks[num].Library;)
71     {
72         ++num;
73     }
74     return num;
75 }
76 
77 static const char* safe_str(const char* ptr)
78 {
79     static char buffer[2][30];
80     static int index = 0;
81     if (HIWORD(ptr))
82         return ptr;
83 
84     index ^= 1;
85     StringCchPrintfA(buffer[index], _countof(buffer[index]), "#%Id", (intptr_t)ptr);
86     return buffer[index];
87 }
88 
89 START_TEST(layer_hooks)
90 {
91     RTL_OSVERSIONINFOEXW rtlinfo = {0};
92     size_t n, h;
93 
94     tGETHOOKAPIS pGetHookAPIs = LoadShimDLL2(L"AcLayers.dll");
95     if (!pGetHookAPIs)
96         return;
97 
98     rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo);
99     RtlGetVersion((PRTL_OSVERSIONINFOW)&rtlinfo);
100     g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
101 
102 
103 
104     for (n = 0; n < _countof(data); ++n)
105     {
106         expect_shim_data* current = data + n;
107         DWORD num_shims = 0, expected_shims = count_shims(current);
108 
109         PHOOKAPI hook = pGetHookAPIs("", current->ShimName, &num_shims);
110 
111         if (current->MinVersion > g_WinVersion && !hook)
112         {
113             skip("Shim %s not present\n", wine_dbgstr_w(current->ShimName));
114             continue;
115         }
116 
117         ok(!!hook, "Expected a valid pointer, got nothing for %s\n", wine_dbgstr_w(current->ShimName));
118         ok(num_shims == expected_shims, "Expected %u shims, got %u for %s\n",
119            expected_shims, num_shims, wine_dbgstr_w(current->ShimName));
120         for (h = 0; h < min(num_shims, expected_shims); ++h)
121         {
122             expect_shim_hook* expect_hk = current->hooks + h;
123             PHOOKAPI got_hk = hook+h;
124             int lib = lstrcmpA(expect_hk->Library, got_hk->LibraryName);
125             int fn = lstrcmpA(safe_str(expect_hk->Function), safe_str(got_hk->FunctionName));
126             ok(lib == 0, "Expected LibraryName to be %s, was: %s for %s\n",
127                expect_hk->Library, got_hk->LibraryName, wine_dbgstr_w(current->ShimName));
128             ok(fn == 0, "Expected FunctionName to be %s, was: %s for %s\n",
129                safe_str(expect_hk->Function), safe_str(got_hk->FunctionName), wine_dbgstr_w(current->ShimName));
130         }
131         if (num_shims > expected_shims)
132         {
133             for (h = expected_shims; h < num_shims; ++h)
134             {
135                 PHOOKAPI got_hk = hook+h;
136 
137                 ok(0, "Extra shim: %s!%s for %s\n",
138                    got_hk->LibraryName, safe_str(got_hk->FunctionName), wine_dbgstr_w(current->ShimName));
139             }
140         }
141         else
142         {
143             for (h = num_shims; h < expected_shims; ++h)
144             {
145                 expect_shim_hook* expect_hk = current->hooks + h;
146 
147                 ok(0, "Missing shim: %s!%s for %s\n",
148                    expect_hk->Library, safe_str(expect_hk->Function), wine_dbgstr_w(current->ShimName));
149             }
150         }
151     }
152 }
153