1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Test for RtlComputePrivatizedDllName_U
5  * COPYRIGHT:   Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 
11 static WCHAR ProcessDir[MAX_PATH];
12 static WCHAR LocalDir[MAX_PATH + 10];
13 
14 static BOOL InitTestData()
15 {
16     static const UNICODE_STRING PathDividerFind = RTL_CONSTANT_STRING(L"\\/");
17     UNICODE_STRING StrU;
18     USHORT PathDivider;
19 
20     GetModuleFileNameW(NULL, ProcessDir, RTL_NUMBER_OF(ProcessDir));
21     GetModuleFileNameW(NULL, LocalDir, RTL_NUMBER_OF(LocalDir));
22 
23     RtlInitUnicodeString(&StrU, ProcessDir);
24 
25     if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
26                                                &StrU, &PathDividerFind, &PathDivider)))
27     {
28         skip("Failed to find path divider\n");
29         return FALSE;
30     }
31     ProcessDir[PathDivider / sizeof(WCHAR) + 1] = UNICODE_NULL;
32 
33     RtlInitUnicodeString(&StrU, LocalDir);
34     StrU.MaximumLength = sizeof(LocalDir);
35 
36     if (!NT_SUCCESS(RtlAppendUnicodeToString(&StrU, L".Local\\")))
37     {
38         skip("Failed to append .Local\\\n");
39         return FALSE;
40     }
41     return TRUE;
42 }
43 
44 static void ok_strings_(PCUNICODE_STRING RealName, PCUNICODE_STRING LocalName, LPCWSTR DllName, int line)
45 {
46     WCHAR ExpectReal[MAX_PATH*2];
47     WCHAR ExpectLocal[MAX_PATH*2];
48     int RealLen;
49     int ExpectLen;
50 
51     RealLen = swprintf(ExpectReal, L"%s%s", ProcessDir, DllName) * sizeof(WCHAR);
52     ExpectLen = swprintf(ExpectLocal, L"%s%s", LocalDir, DllName) * sizeof(WCHAR);
53 
54     ok_(__FILE__, line)(RealLen == RealName->Length, "Expected Real %u, got %u\n",
55                         (UINT)RealLen, (UINT)RealName->Length);
56     ok_(__FILE__, line)(ExpectLen == LocalName->Length, "Expected Local %u, got %u\n",
57                         (UINT)ExpectLen, (UINT)LocalName->Length);
58 
59     ok_(__FILE__, line)(!wcscmp(RealName->Buffer, ExpectReal), "Expected Real %s, got %s\n",
60                         wine_dbgstr_w(ExpectReal), wine_dbgstr_w(RealName->Buffer));
61     ok_(__FILE__, line)(!wcscmp(LocalName->Buffer, ExpectLocal), "Expected Local %s, got %s\n",
62                         wine_dbgstr_w(ExpectLocal), wine_dbgstr_w(LocalName->Buffer));
63 }
64 #define ok_strings(Real, Local, Dll)    ok_strings_(Real, Local, Dll, __LINE__)
65 
66 
67 static void cleanup(PUNICODE_STRING String, WCHAR* Buffer, USHORT BufferSize)
68 {
69     if (String->Buffer != Buffer)
70     {
71         RtlFreeUnicodeString(String);
72         RtlInitEmptyUnicodeString(String, Buffer, BufferSize);
73     }
74 }
75 
76 
77 static void test_dllnames(void)
78 {
79     WCHAR Buf1[MAX_PATH];
80     WCHAR Buf2[MAX_PATH];
81 
82     UNICODE_STRING Str1, Str2;
83     UNICODE_STRING DllName;
84     NTSTATUS Status;
85 
86     RtlInitEmptyUnicodeString(&Str1, Buf1, sizeof(Buf1));
87     RtlInitEmptyUnicodeString(&Str2, Buf2, sizeof(Buf2));
88 
89     RtlInitUnicodeString(&DllName, L"kernel32.dll");
90     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
91     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
92     ok_strings(&Str1, &Str2, L"kernel32.dll");
93     cleanup(&Str1, Buf1, sizeof(Buf1));
94     cleanup(&Str2, Buf2, sizeof(Buf2));
95 
96 
97     RtlInitUnicodeString(&DllName, L"kernel32");
98     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
99     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
100     ok_strings(&Str1, &Str2, L"kernel32.DLL");
101     cleanup(&Str1, Buf1, sizeof(Buf1));
102     cleanup(&Str2, Buf2, sizeof(Buf2));
103 
104     RtlInitUnicodeString(&DllName, L"kernel32.dll.dll");
105     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
106     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
107     ok_strings(&Str1, &Str2, L"kernel32.dll.dll");
108     cleanup(&Str1, Buf1, sizeof(Buf1));
109     cleanup(&Str2, Buf2, sizeof(Buf2));
110 
111     RtlInitUnicodeString(&DllName, L"kernel32.dll.exe");
112     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
113     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
114     ok_strings(&Str1, &Str2, L"kernel32.dll.exe");
115     cleanup(&Str1, Buf1, sizeof(Buf1));
116     cleanup(&Str2, Buf2, sizeof(Buf2));
117 
118     RtlInitUnicodeString(&DllName, L"kernel32.");
119     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
120     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
121     ok_strings(&Str1, &Str2, L"kernel32.");
122     cleanup(&Str1, Buf1, sizeof(Buf1));
123     cleanup(&Str2, Buf2, sizeof(Buf2));
124 
125     RtlInitUnicodeString(&DllName, L".kernel32");
126     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
127     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
128     ok_strings(&Str1, &Str2, L".kernel32.DLL");
129     cleanup(&Str1, Buf1, sizeof(Buf1));
130     cleanup(&Str2, Buf2, sizeof(Buf2));
131 
132     RtlInitUnicodeString(&DllName, L"..kernel32");
133     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
134     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
135     ok_strings(&Str1, &Str2, L"..kernel32");
136     cleanup(&Str1, Buf1, sizeof(Buf1));
137     cleanup(&Str2, Buf2, sizeof(Buf2));
138 
139     RtlInitUnicodeString(&DllName, L".kernel32.");
140     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
141     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
142     ok_strings(&Str1, &Str2, L".kernel32.");
143     cleanup(&Str1, Buf1, sizeof(Buf1));
144     cleanup(&Str2, Buf2, sizeof(Buf2));
145 
146 
147     RtlInitUnicodeString(&DllName, L"test\\kernel32.dll");
148     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
149     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
150     ok_strings(&Str1, &Str2, L"kernel32.dll");
151     cleanup(&Str1, Buf1, sizeof(Buf1));
152     cleanup(&Str2, Buf2, sizeof(Buf2));
153 
154     RtlInitUnicodeString(&DllName, L"test/kernel32.dll");
155     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
156     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
157     ok_strings(&Str1, &Str2, L"kernel32.dll");
158     cleanup(&Str1, Buf1, sizeof(Buf1));
159     cleanup(&Str2, Buf2, sizeof(Buf2));
160 
161     RtlInitUnicodeString(&DllName, L"test.dll/kernel32");
162     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
163     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
164     ok_strings(&Str1, &Str2, L"kernel32.DLL");
165     cleanup(&Str1, Buf1, sizeof(Buf1));
166     cleanup(&Str2, Buf2, sizeof(Buf2));
167 
168     RtlInitUnicodeString(&DllName, L"test.dll\\kernel32");
169     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
170     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
171     ok_strings(&Str1, &Str2, L"kernel32.DLL");
172     cleanup(&Str1, Buf1, sizeof(Buf1));
173     cleanup(&Str2, Buf2, sizeof(Buf2));
174 
175     RtlInitUnicodeString(&DllName, L"//");
176     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
177     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
178     ok_strings(&Str1, &Str2, L".DLL");
179     cleanup(&Str1, Buf1, sizeof(Buf1));
180     cleanup(&Str2, Buf2, sizeof(Buf2));
181 
182     // Bug :)
183     RtlInitUnicodeString(&DllName, L"\\");
184     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
185     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
186     if (wcsstr(Str1.Buffer, L"\\\\"))
187     {
188         trace("Allowing bug found in windows' implementation\n");
189         ok_strings(&Str1, &Str2, L"\\.DLL");
190     }
191     else
192     {
193         ok_strings(&Str1, &Str2, L".DLL");
194     }
195     cleanup(&Str1, Buf1, sizeof(Buf1));
196     cleanup(&Str2, Buf2, sizeof(Buf2));
197 
198     RtlInitUnicodeString(&DllName, L"");
199     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
200     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
201     ok_strings(&Str1, &Str2, L".DLL");
202     cleanup(&Str1, Buf1, sizeof(Buf1));
203     cleanup(&Str2, Buf2, sizeof(Buf2));
204 }
205 
206 static void test_allocations(void)
207 {
208     WCHAR Buf1[10];
209     WCHAR Buf2[10];
210 
211     UNICODE_STRING Str1, Str2;
212     UNICODE_STRING DllName;
213     NTSTATUS Status;
214 
215     RtlInitEmptyUnicodeString(&Str1, Buf1, sizeof(Buf1));
216     RtlInitEmptyUnicodeString(&Str2, Buf2, sizeof(Buf2));
217 
218     RtlInitUnicodeString(&DllName, L"kernel32.dll");
219     Status = RtlComputePrivatizedDllName_U(&DllName, &Str1, &Str2);
220     ok(Status == STATUS_SUCCESS, "0x%lx\n", Status);
221     ok_strings(&Str1, &Str2, L"kernel32.dll");
222     ok(Str1.Buffer != Buf1, "Expected a changed buffer\n");
223     ok(Str2.Buffer != Buf2, "Expected a changed buffer\n");
224     cleanup(&Str1, Buf1, sizeof(Buf1));
225     cleanup(&Str2, Buf2, sizeof(Buf2));
226 }
227 
228 
229 START_TEST(RtlComputePrivatizedDllName_U)
230 {
231     if (!InitTestData())
232         return;
233 
234     test_dllnames();
235     test_allocations();
236 }
237