1 /*
2  * SetupAPI device class-related functions tests
3  *
4  * Copyright 2015 V�ctor Mart�nez (victor.martinez@reactos.org)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this library; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <apitest.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include <winuser.h>
25 #include <winreg.h>
26 #include <winsvc.h>
27 #include <setupapi.h>
28 #include <strsafe.h>
29 
30 static const char inffile[] = "test.inf";
31 static char CURR_DIR[MAX_PATH];
32 
33 /* Helpers */
34 
35 static void create_inf_file(LPCSTR filename, const char *data)
36 {
37     DWORD res;
38     BOOL ret;
39     HANDLE handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
40                                 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
41     assert(handle != INVALID_HANDLE_VALUE);
42     ret = WriteFile(handle, data, strlen(data), &res, NULL);
43     assert(ret != 0);
44     CloseHandle(handle);
45 }
46 
47 /* CBT hook to ensure a window (e.g., MessageBox) cannot be created */
48 static HHOOK hhook;
49 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
50 {
51     return nCode == HCBT_CREATEWND ? 1: CallNextHookEx(hhook, nCode, wParam, lParam);
52 }
53 
54 static void test_SetupInstallServicesFromInfSectionExA(void)
55 {
56     char inf[2048];
57     char path[MAX_PATH];
58     HINF infhandle;
59     BOOL ret;
60     SC_HANDLE scm_handle, svc_handle;
61 
62     /* Bail out if we are on win98 */
63     SetLastError(0xdeadbeef);
64     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
65 
66     if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
67     {
68         win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
69         return;
70     }
71     CloseServiceHandle(scm_handle);
72 
73     /* Basic inf file to satisfy SetupOpenInfFileA */
74     strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
75     create_inf_file(inffile, inf);
76     StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile);
77     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
78 
79     /* Nothing but the Version section */
80     SetLastError(0xdeadbeef);
81     ret = SetupInstallServicesFromInfSectionExA(infhandle, "trolololo", 0, NULL, NULL, NULL,NULL);
82     ok(!ret, "Expected failure\n");
83     ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
84        "Expected ERROR_SECTION_NOT_FOUND, got %08d\n", (int)GetLastError());
85     SetupCloseInfFile(infhandle);
86     DeleteFileA(inffile);
87 
88 
89     /* Add the section */
90     strcat(inf, "[Winetest.Services]\n");
91     create_inf_file(inffile, inf);
92     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
93     SetLastError(0xdeadbeef);
94     ret = SetupInstallServicesFromInfSectionExA(infhandle, "Winetest.Services", 0, NULL, NULL, NULL, NULL);
95     ok(!ret, "Expected failure\n");
96     ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
97        "Expected ERROR_SECTION_NOT_FOUND, got %08d\n", (int)GetLastError());
98     SetupCloseInfFile(infhandle);
99     DeleteFileA(inffile);
100 
101     /* Add a reference */
102     strcat(inf, "AddService=Winetest,,Winetest.Service\n");
103     create_inf_file(inffile, inf);
104     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
105     SetLastError(0xdeadbeef);
106     ret = SetupInstallServicesFromInfSectionExA(infhandle, "Winetest.Services", 0, NULL, NULL, NULL, NULL);
107     ok(!ret, "Expected failure\n");
108     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
109        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
110     SetupCloseInfFile(infhandle);
111     DeleteFileA(inffile);
112 
113     /* Add the section */
114     strcat(inf, "[Winetest.Service]\n");
115     create_inf_file(inffile, inf);
116     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
117     SetLastError(0xdeadbeef);
118     ret = SetupInstallServicesFromInfSectionExA(infhandle, "Winetest.Services", 0, NULL, NULL, NULL, NULL);
119     ok(!ret, "Expected failure\n");
120     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
121        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
122     SetupCloseInfFile(infhandle);
123     DeleteFileA(inffile);
124 
125     /* Just the ServiceBinary */
126     strcat(inf, "ServiceBinary=%12%\\winetest.sys\n");
127     create_inf_file(inffile, inf);
128     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
129     SetLastError(0xdeadbeef);
130     ret = SetupInstallServicesFromInfSectionExA(infhandle, "Winetest.Services", 0, NULL, NULL, NULL, NULL);
131     ok(!ret, "Expected failure\n");
132     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
133        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
134     SetupCloseInfFile(infhandle);
135     DeleteFileA(inffile);
136 
137     /* Add the ServiceType */
138     strcat(inf, "ServiceType=1\n");
139     create_inf_file(inffile, inf);
140     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
141     SetLastError(0xdeadbeef);
142     ret = SetupInstallServicesFromInfSectionExA(infhandle, "Winetest.Services", 0, NULL, NULL, NULL, NULL);
143     ok(!ret, "Expected failure\n");
144     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
145        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
146     SetupCloseInfFile(infhandle);
147     DeleteFileA(inffile);
148 
149     /* Add the StartType */
150     strcat(inf, "StartType=4\n");
151     create_inf_file(inffile, inf);
152     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
153     SetLastError(0xdeadbeef);
154     ret = SetupInstallServicesFromInfSectionExA(infhandle, "Winetest.Services", 0, NULL, NULL, NULL, NULL);
155     ok(!ret, "Expected failure\n");
156     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
157        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
158     SetupCloseInfFile(infhandle);
159     DeleteFileA(inffile);
160 
161     /* This should be it, the minimal entries to install a service */
162     strcat(inf, "ErrorControl=1");
163     create_inf_file(inffile, inf);
164     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
165     SetLastError(0xdeadbeef);
166     ret = SetupInstallServicesFromInfSectionExA(infhandle, "Winetest.Services", 0, NULL, NULL, NULL, NULL);
167     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
168     {
169         skip("Not enough rights to install the service\n");
170         SetupCloseInfFile(infhandle);
171         DeleteFileA(inffile);
172         return;
173     }
174     ok(ret, "Expected success\n");
175     ok(GetLastError() == ERROR_SUCCESS,
176        "Expected ERROR_SUCCESS, got %08d\n", (int)GetLastError());
177     SetupCloseInfFile(infhandle);
178     DeleteFileA(inffile);
179 
180     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
181 
182     /* Open the service to see if it's really there */
183     svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE);
184     ok(svc_handle != NULL, "Service was not created\n");
185 
186     SetLastError(0xdeadbeef);
187     ret = DeleteService(svc_handle);
188     ok(ret, "Service could not be deleted : %d\n", (int)GetLastError());
189 
190     CloseServiceHandle(svc_handle);
191     CloseServiceHandle(scm_handle);
192 
193     strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
194     strcat(inf, "[XSP.InstallPerVer]\n");
195     strcat(inf, "AddReg=AspEventlogMsg.Reg,Perf.Reg,AspVersions.Reg,FreeADO.Reg,IndexServer.Reg\n");
196     create_inf_file(inffile, inf);
197     StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile);
198     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
199 
200     SetLastError(0xdeadbeef);
201     ret = SetupInstallServicesFromInfSectionExA(infhandle, "XSP.InstallPerVer", 0, NULL, NULL, NULL,NULL);
202     ok(ret, "Expected success\n");
203     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08d\n", (int)GetLastError());
204     SetupCloseInfFile(infhandle);
205     DeleteFileA(inffile);
206 
207     /* TODO: Test the Flags */
208 }
209 static void test_SetupInstallServicesFromInfSectionExW(void)
210 {
211     char inf[2048];
212     char path[MAX_PATH];
213     HINF infhandle;
214     BOOL ret;
215     SC_HANDLE scm_handle, svc_handle;
216 
217     /* Bail out if we are on win98 */
218     SetLastError(0xdeadbeef);
219     scm_handle = OpenSCManagerW(NULL, NULL, GENERIC_ALL);
220 
221     if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
222     {
223         win_skip("OpenSCManagerW is not implemented, we are most likely on win9x\n");
224         return;
225     }
226     CloseServiceHandle(scm_handle);
227 
228     /* Basic inf file to satisfy SetupOpenInfFileA */
229     strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
230     create_inf_file(inffile, inf);
231     StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile);
232     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
233 
234     /* Nothing but the Version section */
235     SetLastError(0xdeadbeef);
236     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"trolololo", 0, NULL, NULL, NULL,NULL);
237     ok(!ret, "Expected failure\n");
238     ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
239        "Expected ERROR_SECTION_NOT_FOUND, got %08d\n", (int)GetLastError());
240     SetupCloseInfFile(infhandle);
241     DeleteFileA(inffile);
242 
243 
244     /* Add the section */
245     strcat(inf, "[Winetest.Services]\n");
246     create_inf_file(inffile, inf);
247     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
248     SetLastError(0xdeadbeef);
249     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"Winetest.Services", 0, NULL, NULL, NULL, NULL);
250     ok(!ret, "Expected failure\n");
251     ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
252        "Expected ERROR_SECTION_NOT_FOUND, got %08d\n", (int)GetLastError());
253     SetupCloseInfFile(infhandle);
254     DeleteFileA(inffile);
255 
256     /* Add a reference */
257     strcat(inf, "AddService=Winetest,,Winetest.Service\n");
258     create_inf_file(inffile, inf);
259     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
260     SetLastError(0xdeadbeef);
261     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"Winetest.Services", 0, NULL, NULL, NULL, NULL);
262     ok(!ret, "Expected failure\n");
263     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
264        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
265     SetupCloseInfFile(infhandle);
266     DeleteFileA(inffile);
267 
268     /* Add the section */
269     strcat(inf, "[Winetest.Service]\n");
270     create_inf_file(inffile, inf);
271     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
272     SetLastError(0xdeadbeef);
273     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"Winetest.Services", 0, NULL, NULL, NULL, NULL);
274     ok(!ret, "Expected failure\n");
275     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
276        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
277     SetupCloseInfFile(infhandle);
278     DeleteFileA(inffile);
279 
280     /* Just the ServiceBinary */
281     strcat(inf, "ServiceBinary=%12%\\winetest.sys\n");
282     create_inf_file(inffile, inf);
283     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
284     SetLastError(0xdeadbeef);
285     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"Winetest.Services", 0, NULL, NULL, NULL, NULL);
286     ok(!ret, "Expected failure\n");
287     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
288        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
289     SetupCloseInfFile(infhandle);
290     DeleteFileA(inffile);
291 
292     /* Add the ServiceType */
293     strcat(inf, "ServiceType=1\n");
294     create_inf_file(inffile, inf);
295     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
296     SetLastError(0xdeadbeef);
297     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"Winetest.Services", 0, NULL, NULL, NULL, NULL);
298     ok(!ret, "Expected failure\n");
299     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
300        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
301     SetupCloseInfFile(infhandle);
302     DeleteFileA(inffile);
303 
304     /* Add the StartType */
305     strcat(inf, "StartType=4\n");
306     create_inf_file(inffile, inf);
307     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
308     SetLastError(0xdeadbeef);
309     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"Winetest.Services", 0, NULL, NULL, NULL, NULL);
310     ok(!ret, "Expected failure\n");
311     ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
312        "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08d\n", (int)GetLastError());
313     SetupCloseInfFile(infhandle);
314     DeleteFileA(inffile);
315 
316     /* This should be it, the minimal entries to install a service */
317     strcat(inf, "ErrorControl=1");
318     create_inf_file(inffile, inf);
319     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
320     SetLastError(0xdeadbeef);
321     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"Winetest.Services", 0, NULL, NULL, NULL, NULL);
322     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
323     {
324         skip("Not enough rights to install the service\n");
325         SetupCloseInfFile(infhandle);
326         DeleteFileA(inffile);
327         return;
328     }
329     ok(ret, "Expected success\n");
330     ok(GetLastError() == ERROR_SUCCESS,
331        "Expected ERROR_SUCCESS, got %08d\n", (int)GetLastError());
332     SetupCloseInfFile(infhandle);
333     DeleteFileA(inffile);
334 
335     scm_handle = OpenSCManagerW(NULL, NULL, GENERIC_ALL);
336 
337     /* Open the service to see if it's really there */
338     svc_handle = OpenServiceW(scm_handle, L"Winetest", DELETE);
339     ok(svc_handle != NULL, "Service was not created\n");
340 
341     SetLastError(0xdeadbeef);
342     ret = DeleteService(svc_handle);
343     ok(ret, "Service could not be deleted : %d\n", (int)GetLastError());
344 
345     CloseServiceHandle(svc_handle);
346     CloseServiceHandle(scm_handle);
347 
348     strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
349     strcat(inf, "[XSP.InstallPerVer]\n");
350     strcat(inf, "AddReg=AspEventlogMsg.Reg,Perf.Reg,AspVersions.Reg,FreeADO.Reg,IndexServer.Reg\n");
351     create_inf_file(inffile, inf);
352     StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile);
353     infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
354 
355     SetLastError(0xdeadbeef);
356     ret = SetupInstallServicesFromInfSectionExW(infhandle, L"XSP.InstallPerVer", 0, NULL, NULL, NULL, NULL);
357     ok(ret, "Expected success\n");
358     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08d\n", (int)GetLastError());
359     SetupCloseInfFile(infhandle);
360     DeleteFileA(inffile);
361 
362     /* TODO: Test the Flags */
363 }
364 
365 
366 START_TEST(SetupInstallServicesFromInfSectionEx)
367 {
368     char temp_path[MAX_PATH], prev_path[MAX_PATH];
369 
370     GetCurrentDirectoryA(MAX_PATH, prev_path);
371     GetTempPathA(MAX_PATH, temp_path);
372     SetCurrentDirectoryA(temp_path);
373 
374     strcpy(CURR_DIR, temp_path);
375 
376     /* Set CBT hook to disallow MessageBox creation in current thread */
377     hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
378     assert(hhook != 0);
379 
380     test_SetupInstallServicesFromInfSectionExA();
381     test_SetupInstallServicesFromInfSectionExW();
382 
383     UnhookWindowsHookEx(hhook);
384     SetCurrentDirectoryA(prev_path);
385 }
386