2 * tests for Microsoft Installer functionality
4 * Copyright 2005 Mike McCormack for CodeWeavers
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.
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.
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
27 #include "wine/test.h"
29 typedef struct test_MSIFILEHASHINFO {
30 ULONG dwFileHashInfoSize;
32 } test_MSIFILEHASHINFO, *test_PMSIFILEHASHINFO;
34 typedef INSTALLSTATE (WINAPI *fnMsiUseFeatureExA)(LPCSTR, LPCSTR ,DWORD, DWORD );
35 fnMsiUseFeatureExA pMsiUseFeatureExA;
36 typedef UINT (WINAPI *fnMsiOpenPackageExA)(LPCSTR, DWORD, MSIHANDLE*);
37 fnMsiOpenPackageExA pMsiOpenPackageExA;
38 typedef UINT (WINAPI *fnMsiOpenPackageExW)(LPCWSTR, DWORD, MSIHANDLE*);
39 fnMsiOpenPackageExW pMsiOpenPackageExW;
40 typedef INSTALLSTATE (WINAPI *fnMsiGetComponentPathA)(LPCSTR, LPCSTR, LPSTR, DWORD*);
41 fnMsiGetComponentPathA pMsiGetComponentPathA;
42 typedef UINT (WINAPI *fnMsiGetFileHashA)(LPCSTR, DWORD, test_PMSIFILEHASHINFO);
43 fnMsiGetFileHashA pMsiGetFileHashA;
45 static void test_usefeature(void)
49 if (!pMsiUseFeatureExA)
52 r = MsiQueryFeatureState(NULL,NULL);
53 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
55 r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
56 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
58 r = pMsiUseFeatureExA(NULL,NULL,0,0);
59 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
61 r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
62 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
64 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
66 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
68 r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
69 "WORDVIEWFiles", -2, 0 );
70 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
72 r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
73 "WORDVIEWFiles", -2, 0 );
74 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
76 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
77 "WORDVIEWFiles", -2, 1 );
78 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
81 static void test_null(void)
89 r = pMsiOpenPackageExW(NULL, 0, &hpkg);
90 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
92 r = MsiQueryProductStateW(NULL);
93 ok( r == INSTALLSTATE_INVALIDARG, "wrong return\n");
95 r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
96 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
98 r = MsiConfigureFeatureW(NULL, NULL, 0);
99 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
101 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
102 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
104 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", 0);
105 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
107 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", INSTALLSTATE_DEFAULT);
108 ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
110 /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
111 * necessary registry values */
113 /* empty product string */
114 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", &hkey);
115 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
117 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
118 ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
119 if ( r == ERROR_SUCCESS )
121 lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
123 skip("Out of memory\n");
126 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
127 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
131 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
132 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
134 r = MsiGetProductInfoA("", "", NULL, NULL);
135 ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
139 r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
140 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
142 HeapFree(GetProcessHeap(), 0, lpData);
146 r = RegDeleteValueA(hkey, NULL);
147 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
150 r = RegCloseKey(hkey);
151 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
153 /* empty attribute */
154 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", &hkey);
155 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
157 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
158 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
160 r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
161 ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
163 r = RegCloseKey(hkey);
164 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
166 r = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}");
167 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
170 static void test_getcomponentpath(void)
176 if(!pMsiGetComponentPathA)
179 r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
180 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
182 r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
183 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
185 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
186 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
190 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
191 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
193 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
194 "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
195 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
197 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
198 "{00000000-0000-0000-0000-00000000}", buffer, &sz );
199 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
201 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
202 "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
203 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
205 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
206 "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
207 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
210 static void test_filehash(void)
212 const char name[] = "msitest.bin";
213 const char data[] = {'a','b','c'};
216 test_MSIFILEHASHINFO hash;
219 if (!pMsiGetFileHashA)
224 memset(&hash, 0, sizeof hash);
225 r = pMsiGetFileHashA(name, 0, &hash);
226 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
228 r = pMsiGetFileHashA(name, 0, NULL);
229 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
231 memset(&hash, 0, sizeof hash);
232 hash.dwFileHashInfoSize = sizeof hash;
233 r = pMsiGetFileHashA(name, 0, &hash);
234 ok( r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
236 handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, NULL,
237 CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
238 ok(handle != INVALID_HANDLE_VALUE, "failed to create file\n");
240 WriteFile(handle, data, sizeof data, &count, NULL);
243 memset(&hash, 0, sizeof hash);
244 r = pMsiGetFileHashA(name, 0, &hash);
245 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
247 memset(&hash, 0, sizeof hash);
248 hash.dwFileHashInfoSize = sizeof hash;
249 r = pMsiGetFileHashA(name, 1, &hash);
250 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
252 r = pMsiGetFileHashA(name, 0, &hash);
253 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
255 ok(hash.dwFileHashInfoSize == sizeof hash, "hash size changed\n");
256 ok(hash.dwData[0] == 0x98500190 &&
257 hash.dwData[1] == 0xb04fd23c &&
258 hash.dwData[2] == 0x7d3f96d6 &&
259 hash.dwData[3] == 0x727fe128, "hash of abc incorrect\n");
264 /* copied from dlls/msi/registry.c */
265 BOOL squash_guid(LPCWSTR in, LPWSTR out)
270 if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
284 out[17+i*2] = in[n++];
285 out[16+i*2] = in[n++];
290 out[17+i*2] = in[n++];
291 out[16+i*2] = in[n++];
297 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
299 WCHAR guidW[MAX_PATH];
300 WCHAR squashedW[MAX_PATH];
305 hr = CoCreateGuid(&guid);
306 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
308 size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
309 ok(size == 39, "Expected 39, got %d\n", hr);
311 WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
312 squash_guid(guidW, squashedW);
313 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
316 static void get_user_sid(LPSTR *usersid)
323 OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
325 GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
326 user = (PTOKEN_USER)buf;
327 ConvertSidToStringSid(user->User.Sid, usersid);
330 static void test_MsiQueryProductState(void)
332 CHAR prodcode[MAX_PATH];
333 CHAR prod_squashed[MAX_PATH];
334 CHAR keypath[MAX_PATH*2];
338 HKEY userkey, localkey, props;
341 create_test_guid(prodcode, prod_squashed);
342 get_user_sid(&usersid);
345 state = MsiQueryProductStateA(NULL);
346 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
349 state = MsiQueryProductStateA("");
350 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
352 /* garbage prodcode */
353 state = MsiQueryProductStateA("garbage");
354 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
356 /* guid without brackets */
357 state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
358 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
360 /* guid with brackets */
361 state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
362 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
364 /* same length as guid, but random */
365 state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
366 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
368 /* created guid cannot possibly be an installed product code */
369 state = MsiQueryProductStateA(prodcode);
370 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
372 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
373 lstrcatA(keypath, prod_squashed);
375 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
376 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
378 /* user product key exists */
379 state = MsiQueryProductStateA(prodcode);
380 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
382 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
383 lstrcatA(keypath, prodcode);
385 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
386 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
388 /* local uninstall key exists */
389 state = MsiQueryProductStateA(prodcode);
390 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
393 res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
394 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
396 /* WindowsInstaller value exists */
397 state = MsiQueryProductStateA(prodcode);
398 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
400 RegDeleteValueA(localkey, "WindowsInstaller");
401 RegDeleteKeyA(localkey, "");
403 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
404 lstrcatA(keypath, usersid);
405 lstrcatA(keypath, "\\Products\\");
406 lstrcatA(keypath, prod_squashed);
408 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
409 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
411 /* local product key exists */
412 state = MsiQueryProductStateA(prodcode);
413 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
415 res = RegCreateKeyA(localkey, "InstallProperties", &props);
416 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
418 /* install properties key exists */
419 state = MsiQueryProductStateA(prodcode);
420 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
423 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
424 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
426 /* WindowsInstaller value exists */
427 state = MsiQueryProductStateA(prodcode);
428 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
431 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
432 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
434 /* WindowsInstaller value is not 1 */
435 state = MsiQueryProductStateA(prodcode);
436 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
438 RegDeleteKeyA(userkey, "");
440 /* user product key does not exist */
441 state = MsiQueryProductStateA(prodcode);
444 ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
448 RegDeleteValueA(props, "WindowsInstaller");
449 RegDeleteKeyA(props, "");
450 RegDeleteKeyA(localkey, "");
451 RegCloseKey(userkey);
452 RegCloseKey(localkey);
458 HMODULE hmod = GetModuleHandle("msi.dll");
459 pMsiUseFeatureExA = (fnMsiUseFeatureExA)
460 GetProcAddress(hmod, "MsiUseFeatureExA");
461 pMsiOpenPackageExA = (fnMsiOpenPackageExA)
462 GetProcAddress(hmod, "MsiOpenPackageExA");
463 pMsiOpenPackageExW = (fnMsiOpenPackageExW)
464 GetProcAddress(hmod, "MsiOpenPackageExW");
465 pMsiGetComponentPathA = (fnMsiGetComponentPathA)
466 GetProcAddress(hmod, "MsiGetComponentPathA" );
467 pMsiGetFileHashA = (fnMsiGetFileHashA)
468 GetProcAddress(hmod, "MsiGetFileHashA" );
472 test_getcomponentpath();
474 test_MsiQueryProductState();