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 AcGenral
5  * COPYRIGHT:   Copyright 2017-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 #define WINVER_WIN8    0x0602
19 
20 
21 typedef struct expect_shim_hook
22 {
23     const char* Library;
24     const char* Function;
25 } expect_shim_hook;
26 
27 typedef struct expect_shim_data
28 {
29     const WCHAR* ShimName;
30     DWORD MinVersion;
31     expect_shim_hook hooks[4];
32 } expect_shim_data;
33 
34 
35 static expect_shim_data data[] =
36 {
37     {
38         L"IgnoreChromeSandbox",
39         WINVER_WIN8,
40         {
41             { "KERNEL32.DLL", "CreateProcessW" },
42         }
43     },
44     {
45         L"AddProcessParametersFlags",
46         0,
47         /* No hooks */
48     },
49     {
50         L"DisableThemes",
51         0,
52         /* No hooks */
53     },
54 };
55 
56 static DWORD count_shims(expect_shim_data* data)
57 {
58     DWORD num;
59     for (num = 0; num < _countof(data->hooks) && data->hooks[num].Library;)
60     {
61         ++num;
62     }
63     return num;
64 }
65 
66 static const char* safe_str(const char* ptr)
67 {
68     static char buffer[2][30];
69     static int index = 0;
70     if (HIWORD(ptr))
71         return ptr;
72 
73     index ^= 1;
74     StringCchPrintfA(buffer[index], _countof(buffer[index]), "#%Id", (intptr_t)ptr);
75     return buffer[index];
76 }
77 
78 START_TEST(genral_hooks)
79 {
80     RTL_OSVERSIONINFOEXW rtlinfo = {0};
81     size_t n, h;
82 
83     tGETHOOKAPIS pGetHookAPIs = LoadShimDLL2(L"AcGenral.dll");
84     if (!pGetHookAPIs)
85         return;
86 
87     rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo);
88     RtlGetVersion((PRTL_OSVERSIONINFOW)&rtlinfo);
89     g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
90 
91 
92 
93     for (n = 0; n < _countof(data); ++n)
94     {
95         expect_shim_data* current = data + n;
96         DWORD num_shims = 0, expected_shims = count_shims(current);
97 
98         PHOOKAPI hook = pGetHookAPIs("", current->ShimName, &num_shims);
99 
100         if (current->MinVersion > g_WinVersion && !hook)
101             continue;
102 
103         ok(!!hook, "Expected a valid pointer, got nothing for %s\n", wine_dbgstr_w(current->ShimName));
104         ok(num_shims == expected_shims, "Expected %u shims, got %u for %s\n",
105            expected_shims, num_shims, wine_dbgstr_w(current->ShimName));
106         for (h = 0; h < min(num_shims, expected_shims); ++h)
107         {
108             expect_shim_hook* expect_hk = current->hooks + h;
109             PHOOKAPI got_hk = hook+h;
110             int lib = lstrcmpA(expect_hk->Library, got_hk->LibraryName);
111             int fn = lstrcmpA(safe_str(expect_hk->Function), safe_str(got_hk->FunctionName));
112             ok(lib == 0, "Expected LibraryName to be %s, was: %s for %s\n",
113                expect_hk->Library, got_hk->LibraryName, wine_dbgstr_w(current->ShimName));
114             ok(fn == 0, "Expected FunctionName to be %s, was: %s for %s\n",
115                safe_str(expect_hk->Function), safe_str(got_hk->FunctionName), wine_dbgstr_w(current->ShimName));
116         }
117         if (num_shims > expected_shims)
118         {
119             for (h = expected_shims; h < num_shims; ++h)
120             {
121                 PHOOKAPI got_hk = hook+h;
122 
123                 ok(0, "Extra shim: %s!%s for %s\n",
124                    got_hk->LibraryName, safe_str(got_hk->FunctionName), wine_dbgstr_w(current->ShimName));
125             }
126         }
127         else
128         {
129             for (h = num_shims; h < expected_shims; ++h)
130             {
131                 expect_shim_hook* expect_hk = current->hooks + h;
132 
133                 ok(0, "Missing shim: %s!%s for %s\n",
134                    expect_hk->Library, safe_str(expect_hk->Function), wine_dbgstr_w(current->ShimName));
135             }
136         }
137     }
138 }
139