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 static void test_SetupDiInstallClassExA(void) 48 { 49 char inf[2048]; 50 char path[MAX_PATH]; 51 BOOL ret; 52 ULONG del; 53 HKEY RegHandle; 54 HINF infhandle; 55 SC_HANDLE scm_handle, svc_handle; 56 57 /* [Version]:Signature */ 58 strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n"); 59 create_inf_file(inffile, inf); 60 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 61 62 SetLastError(0xdeadbeef); 63 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 64 ok(!ret, "Expected failure\n"); 65 ok(GetLastError() == ERROR_INVALID_CLASS, 66 "Expected ERROR_INVALID_CLASS, got %08x\n", (int)GetLastError()); 67 DeleteFileA(inffile); 68 69 /* [Version]:Signature+Class */ 70 strcat(inf, "Class=MySampleClass\n"); 71 create_inf_file(inffile, inf); 72 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 73 74 SetLastError(0xdeadbeef); 75 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 76 ok(!ret, "Expected failure\n"); 77 ok(GetLastError() == ERROR_INVALID_CLASS, 78 "Expected ERROR_INVALID_CLASS, got %08x\n", (int)GetLastError()); 79 DeleteFileA(inffile); 80 81 /* [Version]:Signature+Class+ClassGUID */ 82 strcat(inf, "ClassGuid={3b409830-5f9d-432a-abf5-7d2e4e102467}\n"); 83 create_inf_file(inffile, inf); 84 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 85 86 SetLastError(0xdeadbeef); 87 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 88 ok(!ret, "Expected failure\n"); 89 ok(GetLastError() == ERROR_SECTION_NOT_FOUND, 90 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", (int)GetLastError()); 91 DeleteFileA(inffile); 92 93 /* [Version]Signature+Class+ClassGUID;[ClassInstall32.NT]Empty */ 94 strcat(inf, "[ClassInstall32.NT]\n"); 95 create_inf_file(inffile, inf); 96 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 97 98 SetLastError(0xdeadbeef); 99 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 100 ok(ret, "Expected success\n"); 101 ok(!GetLastError(), 102 "Expected no error, got %08x\n", (int)GetLastError()); 103 DeleteFileA(inffile); 104 if (ret == TRUE) 105 { 106 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM", 0, KEY_ALL_ACCESS, &RegHandle); 107 del = RegDeleteKeyW(RegHandle, L"CurrentControlSet\\Control\\Class\\{3B409830-5F9D-432A-ABF5-7D2E4E102467}"); 108 ok(del == ERROR_SUCCESS, "Expected success \n"); 109 } 110 111 /* [Version]Signature+Class+ClassGUID;[ClassInstall32.NT]AddReg */ 112 strcat(inf, "AddReg=SampleClassAddReg\n"); 113 create_inf_file(inffile, inf); 114 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 115 116 SetLastError(0xdeadbeef); 117 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 118 ok(ret, "Expected success\n"); 119 ok(!GetLastError(), 120 "Expected no error, got %08x\n", (int)GetLastError()); 121 DeleteFileA(inffile); 122 if (ret == TRUE) 123 { 124 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM", 0, KEY_ALL_ACCESS, &RegHandle); 125 del = RegDeleteKeyW(RegHandle, L"CurrentControlSet\\Control\\Class\\{3B409830-5F9D-432A-ABF5-7D2E4E102467}"); 126 ok(del == ERROR_SUCCESS, "Expected success \n"); 127 } 128 129 /* [Version]Signature+Class+ClassGUID;[ClassInstall32.NT]AddReg; [SampleClassAddReg];*/ 130 strcat(inf, "[SampleClassAddReg]\n"); 131 create_inf_file(inffile, inf); 132 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 133 134 SetLastError(0xdeadbeef); 135 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 136 ok(ret, "Expected success\n"); 137 ok(!GetLastError(), 138 "Expected no error, got %08x\n", (int)GetLastError()); 139 DeleteFileA(inffile); 140 if (ret == TRUE) 141 { 142 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM", 0, KEY_ALL_ACCESS, &RegHandle); 143 del = RegDeleteKeyW(RegHandle, L"CurrentControlSet\\Control\\Class\\{3B409830-5F9D-432A-ABF5-7D2E4E102467}"); 144 ok(del == ERROR_SUCCESS, "Expected success \n"); 145 } 146 147 /* [Version]Signature+Class+ClassGUID;[ClassInstall32.NT]AddReg; [SampleClassAddReg]HKR;*/ 148 strcat(inf, "HKR,,,,\"ReactOS Test SetupDiInstallClassExA\"\n"); 149 create_inf_file(inffile, inf); 150 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 151 152 SetLastError(0xdeadbeef); 153 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 154 ok(ret, "Expected success\n"); 155 ok(!GetLastError(), 156 "Expected no error, got %08x\n", (int)GetLastError()); 157 DeleteFileA(inffile); 158 if (ret == TRUE) 159 { 160 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM", 0, KEY_ALL_ACCESS, &RegHandle); 161 del = RegDeleteKeyW(RegHandle, L"CurrentControlSet\\Control\\Class\\{3B409830-5F9D-432A-ABF5-7D2E4E102467}"); 162 ok(del == ERROR_SUCCESS, "Expected success \n"); 163 } 164 165 /*[Version]Signature+Class+ClassGUID;[ClassInstall32.NT]AddReg;[SampleClassAddReg]HKR;[ClassInstall32.NT.Services]*/ 166 strcat(inf, "[ClassInstall32.NT.Services]\n"); 167 create_inf_file(inffile, inf); 168 StringCbPrintfA(path, sizeof(path), "%s\\%s", CURR_DIR, inffile); 169 170 SetLastError(0xdeadbeef); 171 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 172 ok(ret, "Expected success\n"); 173 ok(!GetLastError(), 174 "Expected no error, got %08x\n", (int)GetLastError()); 175 DeleteFileA(inffile); 176 if (ret == TRUE) 177 { 178 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM", 0, KEY_ALL_ACCESS, &RegHandle); 179 del = RegDeleteKeyW(RegHandle, L"CurrentControlSet\\Control\\Class\\{3B409830-5F9D-432A-ABF5-7D2E4E102467}"); 180 ok(del == ERROR_SUCCESS, "Expected success\n"); 181 } 182 183 /* Add a reference */ 184 strcat(inf, "AddService=Reactostest,,Reactostest.Service\n"); 185 create_inf_file(inffile, inf); 186 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 187 SetLastError(0xdeadbeef); 188 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 189 ok(!ret, "Expected failure\n"); 190 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 191 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", (int)GetLastError()); 192 SetupCloseInfFile(infhandle); 193 DeleteFileA(inffile); 194 195 /* Add the section */ 196 strcat(inf, "[Reactostest.Service]\n"); 197 create_inf_file(inffile, inf); 198 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 199 SetLastError(0xdeadbeef); 200 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 201 ok(!ret, "Expected failure\n"); 202 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 203 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", (int)GetLastError()); 204 SetupCloseInfFile(infhandle); 205 DeleteFileA(inffile); 206 207 /* Just the ServiceBinary */ 208 strcat(inf, "ServiceBinary=%12%\\reactostest.sys\n"); 209 create_inf_file(inffile, inf); 210 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 211 SetLastError(0xdeadbeef); 212 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 213 ok(!ret, "Expected failure\n"); 214 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 215 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", (int)GetLastError()); 216 SetupCloseInfFile(infhandle); 217 DeleteFileA(inffile); 218 219 /* Add the ServiceType */ 220 strcat(inf, "ServiceType=1\n"); 221 create_inf_file(inffile, inf); 222 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 223 SetLastError(0xdeadbeef); 224 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 225 ok(!ret, "Expected failure\n"); 226 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 227 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", (int)GetLastError()); 228 SetupCloseInfFile(infhandle); 229 DeleteFileA(inffile); 230 231 /* Add the StartType */ 232 strcat(inf, "StartType=4\n"); 233 create_inf_file(inffile, inf); 234 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 235 SetLastError(0xdeadbeef); 236 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 237 ok(!ret, "Expected failure\n"); 238 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 239 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", (int)GetLastError()); 240 SetupCloseInfFile(infhandle); 241 DeleteFileA(inffile); 242 243 /* This should be it, the minimal entries to install a service */ 244 strcat(inf, "ErrorControl=1"); 245 create_inf_file(inffile, inf); 246 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 247 SetLastError(0xdeadbeef); 248 ret = SetupDiInstallClassExA(NULL, path, DI_QUIETINSTALL, NULL, NULL, NULL,NULL); 249 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 250 { 251 skip("Not enough rights to install the service\n"); 252 SetupCloseInfFile(infhandle); 253 DeleteFileA(inffile); 254 return; 255 } 256 ok(ret, "Expected success\n"); 257 ok(GetLastError() == ERROR_SUCCESS, 258 "Expected ERROR_SUCCESS, got %08x\n", (int)GetLastError()); 259 SetupCloseInfFile(infhandle); 260 DeleteFileA(inffile); 261 262 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 263 264 /* Open the service to see if it's really there */ 265 svc_handle = OpenServiceA(scm_handle, "Reactostest", DELETE); 266 ok(svc_handle != NULL, "Service was not created\n"); 267 268 SetLastError(0xdeadbeef); 269 ret = DeleteService(svc_handle); 270 ok(ret, "Service could not be deleted : %d\n", (int)GetLastError()); 271 272 CloseServiceHandle(svc_handle); 273 CloseServiceHandle(scm_handle); 274 } 275 276 277 START_TEST(SetupDiInstallClassExA) 278 { 279 char temp_path[MAX_PATH], prev_path[MAX_PATH]; 280 DWORD len; 281 282 GetCurrentDirectoryA(MAX_PATH, prev_path); 283 GetTempPathA(MAX_PATH, temp_path); 284 SetCurrentDirectoryA(temp_path); 285 286 strcpy(CURR_DIR, temp_path); 287 len = strlen(CURR_DIR); 288 if (len && (CURR_DIR[len - 1] == '\\')) 289 CURR_DIR[len - 1] = 0; 290 291 test_SetupDiInstallClassExA(); 292 SetCurrentDirectoryA(prev_path); 293 294 } 295