1 /* 2 * Unit tests for advpack.dll install functions 3 * 4 * Copyright (C) 2006 James Hawkins 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of 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 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdio.h> 22 #include <windows.h> 23 #include <advpub.h> 24 #include "wine/test.h" 25 26 static HMODULE hAdvPack; 27 /* function pointers */ 28 static HRESULT (WINAPI *pRunSetupCommand)(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, HANDLE*, DWORD, LPVOID); 29 static HRESULT (WINAPI *pLaunchINFSection)(HWND, HINSTANCE, LPSTR, INT); 30 static HRESULT (WINAPI *pLaunchINFSectionEx)(HWND, HINSTANCE, LPSTR, INT); 31 32 static char CURR_DIR[MAX_PATH]; 33 34 static BOOL init_function_pointers(void) 35 { 36 hAdvPack = LoadLibraryA("advpack.dll"); 37 if (!hAdvPack) 38 return FALSE; 39 40 pRunSetupCommand = (void *)GetProcAddress(hAdvPack, "RunSetupCommand"); 41 pLaunchINFSection = (void *)GetProcAddress(hAdvPack, "LaunchINFSection"); 42 pLaunchINFSectionEx = (void *)GetProcAddress(hAdvPack, "LaunchINFSectionEx"); 43 44 if (!pRunSetupCommand || !pLaunchINFSection || !pLaunchINFSectionEx) 45 return FALSE; 46 47 return TRUE; 48 } 49 50 static BOOL is_spapi_err(DWORD err) 51 { 52 const DWORD SPAPI_PREFIX = 0x800F0000L; 53 const DWORD SPAPI_MASK = 0xFFFF0000L; 54 55 return (((err & SPAPI_MASK) ^ SPAPI_PREFIX) == 0); 56 } 57 58 static void create_inf_file(LPCSTR filename) 59 { 60 DWORD dwNumberOfBytesWritten; 61 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL, 62 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 63 64 static const char data[] = 65 "[Version]\n" 66 "Signature=\"$Chicago$\"\n" 67 "AdvancedINF=2.5\n" 68 "[DefaultInstall]\n" 69 "CheckAdminRights=1\n"; 70 71 WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL); 72 CloseHandle(hf); 73 } 74 75 static void test_RunSetupCommand(void) 76 { 77 HRESULT hr; 78 HANDLE hexe; 79 char path[MAX_PATH]; 80 char dir[MAX_PATH]; 81 char systemdir[MAX_PATH]; 82 83 GetSystemDirectoryA(systemdir, sizeof(systemdir)); 84 85 /* try an invalid cmd name */ 86 hr = pRunSetupCommand(NULL, NULL, "Install", "Dir", "Title", NULL, 0, NULL); 87 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr); 88 89 /* try an invalid directory */ 90 hr = pRunSetupCommand(NULL, "winver.exe", "Install", NULL, "Title", NULL, 0, NULL); 91 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr); 92 93 /* try to run a nonexistent exe */ 94 #ifdef __REACTOS__ 95 hexe = (HANDLE)(ULONG_PTR)0xdeadbeefdeadbeefull; 96 #else 97 hexe = (HANDLE)0xdeadbeef; 98 #endif 99 hr = pRunSetupCommand(NULL, "idontexist.exe", "Install", systemdir, "Title", &hexe, 0, NULL); 100 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 101 "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 102 ok(hexe == NULL, "Expected hexe to be NULL\n"); 103 ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n"); 104 105 /* try a bad directory */ 106 #ifdef __REACTOS__ 107 hexe = (HANDLE)(ULONG_PTR)0xdeadbeefdeadbeefull; 108 #else 109 hexe = (HANDLE)0xdeadbeef; 110 #endif 111 hr = pRunSetupCommand(NULL, "winver.exe", "Install", "non\\existent\\directory", "Title", &hexe, 0, NULL); 112 ok(hr == HRESULT_FROM_WIN32(ERROR_DIRECTORY), 113 "Expected HRESULT_FROM_WIN32(ERROR_DIRECTORY), got %d\n", hr); 114 ok(hexe == NULL, "Expected hexe to be NULL\n"); 115 ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n"); 116 117 /* try to run an exe with the RSC_FLAG_INF flag */ 118 #ifdef __REACTOS__ 119 hexe = (HANDLE)(ULONG_PTR)0xdeadbeefdeadbeefull; 120 #else 121 hexe = (HANDLE)0xdeadbeef; 122 #endif 123 hr = pRunSetupCommand(NULL, "winver.exe", "Install", systemdir, "Title", &hexe, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 124 ok(is_spapi_err(hr), "Expected a setupapi error, got %d\n", hr); 125 #ifdef __REACTOS__ 126 ok(hexe == (HANDLE)(ULONG_PTR)0xdeadbeefdeadbeefull, "Expected hexe to be 0xdeadbeef\n"); 127 #else 128 ok(hexe == (HANDLE)0xdeadbeef, "Expected hexe to be 0xdeadbeef\n"); 129 #endif 130 ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n"); 131 132 /* run winver.exe */ 133 #ifdef __REACTOS__ 134 hexe = (HANDLE)(ULONG_PTR)0xdeadbeefdeadbeefull; 135 #else 136 hexe = (HANDLE)0xdeadbeef; 137 #endif 138 hr = pRunSetupCommand(NULL, "winver.exe", "Install", systemdir, "Title", &hexe, 0, NULL); 139 ok(hr == S_ASYNCHRONOUS, "Expected S_ASYNCHRONOUS, got %d\n", hr); 140 ok(hexe != NULL, "Expected hexe to be non-NULL\n"); 141 ok(TerminateProcess(hexe, 0), "Expected TerminateProcess to succeed\n"); 142 143 CreateDirectoryA("one", NULL); 144 create_inf_file("one\\test.inf"); 145 146 /* try a full path to the INF, with working dir provided */ 147 lstrcpyA(path, CURR_DIR); 148 lstrcatA(path, "\\one\\test.inf"); 149 lstrcpyA(dir, CURR_DIR); 150 lstrcatA(dir, "\\one"); 151 hr = pRunSetupCommand(NULL, path, "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 152 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 153 154 /* try a full path to the INF, NULL working dir */ 155 hr = pRunSetupCommand(NULL, path, "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 156 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 157 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 158 159 /* try a full path to the INF, empty working dir */ 160 hr = pRunSetupCommand(NULL, path, "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 161 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 162 163 /* try a relative path to the INF, with working dir provided */ 164 hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 165 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 166 167 /* try a relative path to the INF, NULL working dir */ 168 hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 169 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 170 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 171 172 /* try a relative path to the INF, empty working dir */ 173 hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 174 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 175 176 /* try only the INF filename, with working dir provided */ 177 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 178 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 179 180 /* try only the INF filename, NULL working dir */ 181 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 182 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 183 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 184 185 /* try only the INF filename, empty working dir */ 186 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 187 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 188 189 DeleteFileA("one\\test.inf"); 190 RemoveDirectoryA("one"); 191 192 create_inf_file("test.inf"); 193 194 /* try INF file in the current directory, working directory provided */ 195 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", CURR_DIR, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 196 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 197 198 /* try INF file in the current directory, NULL working directory */ 199 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 200 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 201 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 202 203 /* try INF file in the current directory, empty working directory */ 204 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", CURR_DIR, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 205 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 206 } 207 208 static void test_LaunchINFSection(void) 209 { 210 HRESULT hr; 211 char cmdline[MAX_PATH]; 212 static char file[] = "test.inf,DefaultInstall,4,0"; 213 static char file2[] = "test.inf,,1,0"; 214 215 /* The 'No UI' flag seems to have no effect whatsoever on Windows. 216 * So only do this test in interactive mode. 217 */ 218 if (winetest_interactive) 219 { 220 /* try an invalid cmdline */ 221 hr = pLaunchINFSection(NULL, NULL, NULL, 0); 222 ok(hr == 1, "Expected 1, got %d\n", hr); 223 } 224 225 CreateDirectoryA("one", NULL); 226 create_inf_file("one\\test.inf"); 227 228 /* try a full path to the INF */ 229 lstrcpyA(cmdline, CURR_DIR); 230 lstrcatA(cmdline, "\\"); 231 lstrcatA(cmdline, "one\\test.inf,DefaultInstall,,4"); 232 hr = pLaunchINFSection(NULL, NULL, cmdline, 0); 233 ok(hr == 0, "Expected 0, got %d\n", hr); 234 235 DeleteFileA("one\\test.inf"); 236 RemoveDirectoryA("one"); 237 238 create_inf_file("test.inf"); 239 240 /* try just the INF filename */ 241 hr = pLaunchINFSection(NULL, NULL, file, 0); 242 ok(hr == 0, "Expected 0, got %d\n", hr); 243 244 hr = pLaunchINFSection(NULL, NULL, file2, 0); 245 ok(hr == 0, "Expected 0, got %d\n", hr); 246 247 DeleteFileA("test.inf"); 248 } 249 250 static void test_LaunchINFSectionEx(void) 251 { 252 HRESULT hr; 253 char cmdline[MAX_PATH]; 254 255 create_inf_file("test.inf"); 256 257 /* try an invalid CAB filename with an absolute INF name */ 258 lstrcpyA(cmdline, CURR_DIR); 259 lstrcatA(cmdline, "\\"); 260 lstrcatA(cmdline, "test.inf,DefaultInstall,c:imacab.cab,4"); 261 hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0); 262 ok(hr == 0, "Expected 0, got %d\n", hr); 263 264 /* try quoting the parameters */ 265 lstrcpyA(cmdline, "\""); 266 lstrcatA(cmdline, CURR_DIR); 267 lstrcatA(cmdline, "\\test.inf\",\"DefaultInstall\",\"c:,imacab.cab\",\"4\""); 268 hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0); 269 ok(hr == 0, "Expected 0, got %d\n", hr); 270 271 /* The 'No UI' flag seems to have no effect whatsoever on Windows. 272 * So only do this test in interactive mode. 273 */ 274 if (winetest_interactive) 275 { 276 /* try an invalid CAB filename with a relative INF name */ 277 lstrcpyA(cmdline, "test.inf,DefaultInstall,c:imacab.cab,4"); 278 hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0); 279 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr); 280 } 281 282 DeleteFileA("test.inf"); 283 } 284 285 START_TEST(install) 286 { 287 DWORD len; 288 char temp_path[MAX_PATH], prev_path[MAX_PATH]; 289 290 if (!init_function_pointers()) 291 return; 292 293 if (!IsNTAdmin(0, NULL)) 294 { 295 skip("Most tests need admin rights\n"); 296 return; 297 } 298 299 GetCurrentDirectoryA(MAX_PATH, prev_path); 300 GetTempPathA(MAX_PATH, temp_path); 301 SetCurrentDirectoryA(temp_path); 302 303 lstrcpyA(CURR_DIR, temp_path); 304 len = lstrlenA(CURR_DIR); 305 306 if(len && (CURR_DIR[len - 1] == '\\')) 307 CURR_DIR[len - 1] = 0; 308 309 test_RunSetupCommand(); 310 test_LaunchINFSection(); 311 test_LaunchINFSectionEx(); 312 313 FreeLibrary(hAdvPack); 314 SetCurrentDirectoryA(prev_path); 315 } 316