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 hexe = (HANDLE)0xdeadbeef; 95 hr = pRunSetupCommand(NULL, "idontexist.exe", "Install", systemdir, "Title", &hexe, 0, NULL); 96 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 97 "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 98 ok(hexe == NULL, "Expected hexe to be NULL\n"); 99 ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n"); 100 101 /* try a bad directory */ 102 hexe = (HANDLE)0xdeadbeef; 103 hr = pRunSetupCommand(NULL, "winver.exe", "Install", "non\\existent\\directory", "Title", &hexe, 0, NULL); 104 ok(hr == HRESULT_FROM_WIN32(ERROR_DIRECTORY), 105 "Expected HRESULT_FROM_WIN32(ERROR_DIRECTORY), got %d\n", hr); 106 ok(hexe == NULL, "Expected hexe to be NULL\n"); 107 ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n"); 108 109 /* try to run an exe with the RSC_FLAG_INF flag */ 110 hexe = (HANDLE)0xdeadbeef; 111 hr = pRunSetupCommand(NULL, "winver.exe", "Install", systemdir, "Title", &hexe, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 112 ok(is_spapi_err(hr), "Expected a setupapi error, got %d\n", hr); 113 ok(hexe == (HANDLE)0xdeadbeef, "Expected hexe to be 0xdeadbeef\n"); 114 ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n"); 115 116 /* run winver.exe */ 117 hexe = (HANDLE)0xdeadbeef; 118 hr = pRunSetupCommand(NULL, "winver.exe", "Install", systemdir, "Title", &hexe, 0, NULL); 119 ok(hr == S_ASYNCHRONOUS, "Expected S_ASYNCHRONOUS, got %d\n", hr); 120 ok(hexe != NULL, "Expected hexe to be non-NULL\n"); 121 ok(TerminateProcess(hexe, 0), "Expected TerminateProcess to succeed\n"); 122 123 CreateDirectoryA("one", NULL); 124 create_inf_file("one\\test.inf"); 125 126 /* try a full path to the INF, with working dir provided */ 127 lstrcpyA(path, CURR_DIR); 128 lstrcatA(path, "\\one\\test.inf"); 129 lstrcpyA(dir, CURR_DIR); 130 lstrcatA(dir, "\\one"); 131 hr = pRunSetupCommand(NULL, path, "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 132 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 133 134 /* try a full path to the INF, NULL working dir */ 135 hr = pRunSetupCommand(NULL, path, "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 136 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 137 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 138 139 /* try a full path to the INF, empty working dir */ 140 hr = pRunSetupCommand(NULL, path, "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 141 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 142 143 /* try a relative path to the INF, with working dir provided */ 144 hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 145 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 146 147 /* try a relative path to the INF, NULL working dir */ 148 hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 149 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 150 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 151 152 /* try a relative path to the INF, empty working dir */ 153 hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 154 ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr); 155 156 /* try only the INF filename, with working dir provided */ 157 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 158 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 159 160 /* try only the INF filename, NULL working dir */ 161 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 162 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 163 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 164 165 /* try only the INF filename, empty working dir */ 166 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 167 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 168 169 DeleteFileA("one\\test.inf"); 170 RemoveDirectoryA("one"); 171 172 create_inf_file("test.inf"); 173 174 /* try INF file in the current directory, working directory provided */ 175 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", CURR_DIR, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 176 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 177 178 /* try INF file in the current directory, NULL working directory */ 179 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 180 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), 181 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr); 182 183 /* try INF file in the current directory, empty working directory */ 184 hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", CURR_DIR, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL); 185 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr); 186 } 187 188 static void test_LaunchINFSection(void) 189 { 190 HRESULT hr; 191 char cmdline[MAX_PATH]; 192 static char file[] = "test.inf,DefaultInstall,4,0"; 193 static char file2[] = "test.inf,,1,0"; 194 195 /* The 'No UI' flag seems to have no effect whatsoever on Windows. 196 * So only do this test in interactive mode. 197 */ 198 if (winetest_interactive) 199 { 200 /* try an invalid cmdline */ 201 hr = pLaunchINFSection(NULL, NULL, NULL, 0); 202 ok(hr == 1, "Expected 1, got %d\n", hr); 203 } 204 205 CreateDirectoryA("one", NULL); 206 create_inf_file("one\\test.inf"); 207 208 /* try a full path to the INF */ 209 lstrcpyA(cmdline, CURR_DIR); 210 lstrcatA(cmdline, "\\"); 211 lstrcatA(cmdline, "one\\test.inf,DefaultInstall,,4"); 212 hr = pLaunchINFSection(NULL, NULL, cmdline, 0); 213 ok(hr == 0, "Expected 0, got %d\n", hr); 214 215 DeleteFileA("one\\test.inf"); 216 RemoveDirectoryA("one"); 217 218 create_inf_file("test.inf"); 219 220 /* try just the INF filename */ 221 hr = pLaunchINFSection(NULL, NULL, file, 0); 222 ok(hr == 0, "Expected 0, got %d\n", hr); 223 224 hr = pLaunchINFSection(NULL, NULL, file2, 0); 225 ok(hr == 0, "Expected 0, got %d\n", hr); 226 227 DeleteFileA("test.inf"); 228 } 229 230 static void test_LaunchINFSectionEx(void) 231 { 232 HRESULT hr; 233 char cmdline[MAX_PATH]; 234 235 create_inf_file("test.inf"); 236 237 /* try an invalid CAB filename with an absolute INF name */ 238 lstrcpyA(cmdline, CURR_DIR); 239 lstrcatA(cmdline, "\\"); 240 lstrcatA(cmdline, "test.inf,DefaultInstall,c:imacab.cab,4"); 241 hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0); 242 ok(hr == 0, "Expected 0, got %d\n", hr); 243 244 /* try quoting the parameters */ 245 lstrcpyA(cmdline, "\""); 246 lstrcatA(cmdline, CURR_DIR); 247 lstrcatA(cmdline, "\\test.inf\",\"DefaultInstall\",\"c:,imacab.cab\",\"4\""); 248 hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0); 249 ok(hr == 0, "Expected 0, got %d\n", hr); 250 251 /* The 'No UI' flag seems to have no effect whatsoever on Windows. 252 * So only do this test in interactive mode. 253 */ 254 if (winetest_interactive) 255 { 256 /* try an invalid CAB filename with a relative INF name */ 257 lstrcpyA(cmdline, "test.inf,DefaultInstall,c:imacab.cab,4"); 258 hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0); 259 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr); 260 } 261 262 DeleteFileA("test.inf"); 263 } 264 265 START_TEST(install) 266 { 267 DWORD len; 268 char temp_path[MAX_PATH], prev_path[MAX_PATH]; 269 270 if (!init_function_pointers()) 271 return; 272 273 if (!IsNTAdmin(0, NULL)) 274 { 275 skip("Most tests need admin rights\n"); 276 return; 277 } 278 279 GetCurrentDirectoryA(MAX_PATH, prev_path); 280 GetTempPathA(MAX_PATH, temp_path); 281 SetCurrentDirectoryA(temp_path); 282 283 lstrcpyA(CURR_DIR, temp_path); 284 len = lstrlenA(CURR_DIR); 285 286 if(len && (CURR_DIR[len - 1] == '\\')) 287 CURR_DIR[len - 1] = 0; 288 289 test_RunSetupCommand(); 290 test_LaunchINFSection(); 291 test_LaunchINFSectionEx(); 292 293 FreeLibrary(hAdvPack); 294 SetCurrentDirectoryA(prev_path); 295 } 296