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 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
36 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
37 (LPCSTR, LPCSTR, LPSTR, DWORD*);
38 static UINT (WINAPI *pMsiGetFileHashA)
39 (LPCSTR, DWORD, test_PMSIFILEHASHINFO);
40 static UINT (WINAPI *pMsiOpenPackageExA)
41 (LPCSTR, DWORD, MSIHANDLE*);
42 static UINT (WINAPI *pMsiOpenPackageExW)
43 (LPCWSTR, DWORD, MSIHANDLE*);
44 static UINT (WINAPI *pMsiQueryComponentStateA)
45 (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
46 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
47 (LPCSTR, LPCSTR ,DWORD, DWORD );
49 static void init_functionpointers(void)
51 HMODULE hmsi = GetModuleHandleA("msi.dll");
52 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
54 pMsiGetComponentPathA = (void*)GetProcAddress(hmsi, "MsiGetComponentPathA");
55 pMsiGetFileHashA = (void*)GetProcAddress(hmsi, "MsiGetFileHashA");
56 pMsiOpenPackageExA = (void*)GetProcAddress(hmsi, "MsiOpenPackageExA");
57 pMsiOpenPackageExW = (void*)GetProcAddress(hmsi, "MsiOpenPackageExW");
58 pMsiQueryComponentStateA = (void*)GetProcAddress(hmsi, "MsiQueryComponentStateA");
59 pMsiUseFeatureExA = (void*)GetProcAddress(hmsi, "MsiUseFeatureExA");
61 pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
64 static void test_usefeature(void)
68 if (!pMsiUseFeatureExA)
71 r = MsiQueryFeatureState(NULL,NULL);
72 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
74 r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
75 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
77 r = pMsiUseFeatureExA(NULL,NULL,0,0);
78 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
80 r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
81 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
83 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
85 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
87 r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
88 "WORDVIEWFiles", -2, 0 );
89 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
91 r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
92 "WORDVIEWFiles", -2, 0 );
93 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
95 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
96 "WORDVIEWFiles", -2, 1 );
97 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
100 static void test_null(void)
105 DWORD dwType, cbData;
106 LPBYTE lpData = NULL;
108 r = pMsiOpenPackageExW(NULL, 0, &hpkg);
109 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
111 r = MsiQueryProductStateW(NULL);
112 ok( r == INSTALLSTATE_INVALIDARG, "wrong return\n");
114 r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
115 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
117 r = MsiConfigureFeatureW(NULL, NULL, 0);
118 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
120 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
121 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
123 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", 0);
124 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
126 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", INSTALLSTATE_DEFAULT);
127 ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
129 /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
130 * necessary registry values */
132 /* empty product string */
133 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", &hkey);
134 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
136 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
137 ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
138 if ( r == ERROR_SUCCESS )
140 lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
142 skip("Out of memory\n");
145 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
146 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
150 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
151 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
153 r = MsiGetProductInfoA("", "", NULL, NULL);
154 ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
158 r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
159 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
161 HeapFree(GetProcessHeap(), 0, lpData);
165 r = RegDeleteValueA(hkey, NULL);
166 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
169 r = RegCloseKey(hkey);
170 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
172 /* empty attribute */
173 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", &hkey);
174 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
176 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
177 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
179 r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
180 ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
182 r = RegCloseKey(hkey);
183 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
185 r = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}");
186 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
189 static void test_getcomponentpath(void)
195 if(!pMsiGetComponentPathA)
198 r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
199 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
201 r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
202 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
204 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
205 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
209 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
210 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
212 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
213 "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
214 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
216 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
217 "{00000000-0000-0000-0000-00000000}", buffer, &sz );
218 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
220 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
221 "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
222 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
224 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
225 "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
226 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
229 static void test_filehash(void)
231 const char name[] = "msitest.bin";
232 const char data[] = {'a','b','c'};
235 test_MSIFILEHASHINFO hash;
238 if (!pMsiGetFileHashA)
243 memset(&hash, 0, sizeof hash);
244 r = pMsiGetFileHashA(name, 0, &hash);
245 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
247 r = pMsiGetFileHashA(name, 0, NULL);
248 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
250 memset(&hash, 0, sizeof hash);
251 hash.dwFileHashInfoSize = sizeof hash;
252 r = pMsiGetFileHashA(name, 0, &hash);
253 ok( r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
255 handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, NULL,
256 CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
257 ok(handle != INVALID_HANDLE_VALUE, "failed to create file\n");
259 WriteFile(handle, data, sizeof data, &count, NULL);
262 memset(&hash, 0, sizeof hash);
263 r = pMsiGetFileHashA(name, 0, &hash);
264 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
266 memset(&hash, 0, sizeof hash);
267 hash.dwFileHashInfoSize = sizeof hash;
268 r = pMsiGetFileHashA(name, 1, &hash);
269 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
271 r = pMsiGetFileHashA(name, 0, &hash);
272 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
274 ok(hash.dwFileHashInfoSize == sizeof hash, "hash size changed\n");
275 ok(hash.dwData[0] == 0x98500190 &&
276 hash.dwData[1] == 0xb04fd23c &&
277 hash.dwData[2] == 0x7d3f96d6 &&
278 hash.dwData[3] == 0x727fe128, "hash of abc incorrect\n");
283 /* copied from dlls/msi/registry.c */
284 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
289 if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
303 out[17+i*2] = in[n++];
304 out[16+i*2] = in[n++];
309 out[17+i*2] = in[n++];
310 out[16+i*2] = in[n++];
316 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
318 WCHAR guidW[MAX_PATH];
319 WCHAR squashedW[MAX_PATH];
324 hr = CoCreateGuid(&guid);
325 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
327 size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
328 ok(size == 39, "Expected 39, got %d\n", hr);
330 WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
331 squash_guid(guidW, squashedW);
332 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
335 static void get_user_sid(LPSTR *usersid)
342 OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
344 GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
345 user = (PTOKEN_USER)buf;
346 pConvertSidToStringSidA(user->User.Sid, usersid);
349 static void test_MsiQueryProductState(void)
351 CHAR prodcode[MAX_PATH];
352 CHAR prod_squashed[MAX_PATH];
353 CHAR keypath[MAX_PATH*2];
357 HKEY userkey, localkey, props;
360 create_test_guid(prodcode, prod_squashed);
361 get_user_sid(&usersid);
364 state = MsiQueryProductStateA(NULL);
365 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
368 state = MsiQueryProductStateA("");
369 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
371 /* garbage prodcode */
372 state = MsiQueryProductStateA("garbage");
373 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
375 /* guid without brackets */
376 state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
377 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
379 /* guid with brackets */
380 state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
381 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
383 /* same length as guid, but random */
384 state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
385 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
387 /* created guid cannot possibly be an installed product code */
388 state = MsiQueryProductStateA(prodcode);
389 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
391 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
392 lstrcatA(keypath, prod_squashed);
394 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
395 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
397 /* user product key exists */
398 state = MsiQueryProductStateA(prodcode);
399 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
401 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
402 lstrcatA(keypath, prodcode);
404 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
405 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
407 /* local uninstall key exists */
408 state = MsiQueryProductStateA(prodcode);
409 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
412 res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
413 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
415 /* WindowsInstaller value exists */
416 state = MsiQueryProductStateA(prodcode);
417 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
419 RegDeleteValueA(localkey, "WindowsInstaller");
420 RegDeleteKeyA(localkey, "");
422 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
423 lstrcatA(keypath, usersid);
424 lstrcatA(keypath, "\\Products\\");
425 lstrcatA(keypath, prod_squashed);
427 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
428 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
430 /* local product key exists */
431 state = MsiQueryProductStateA(prodcode);
432 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
434 res = RegCreateKeyA(localkey, "InstallProperties", &props);
435 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
437 /* install properties key exists */
438 state = MsiQueryProductStateA(prodcode);
439 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
442 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
443 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
445 /* WindowsInstaller value exists */
446 state = MsiQueryProductStateA(prodcode);
447 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
450 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
451 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
453 /* WindowsInstaller value is not 1 */
454 state = MsiQueryProductStateA(prodcode);
455 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
457 RegDeleteKeyA(userkey, "");
459 /* user product key does not exist */
460 state = MsiQueryProductStateA(prodcode);
461 ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
464 RegDeleteValueA(props, "WindowsInstaller");
465 RegDeleteKeyA(props, "");
466 RegDeleteKeyA(localkey, "");
467 RegCloseKey(userkey);
468 RegCloseKey(localkey);
472 static const char table_enc85[] =
473 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
474 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
478 * Encodes a base85 guid given a GUID pointer
479 * Caller should provide a 21 character buffer for the encoded string.
481 * returns TRUE if successful, FALSE if not
483 static BOOL encode_base85_guid( GUID *guid, LPWSTR str )
485 unsigned int x, *p, i;
487 p = (unsigned int*) guid;
491 *str++ = table_enc85[x%85];
493 *str++ = table_enc85[x%85];
495 *str++ = table_enc85[x%85];
497 *str++ = table_enc85[x%85];
499 *str++ = table_enc85[x%85];
506 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
508 WCHAR guidW[MAX_PATH];
509 WCHAR base85W[MAX_PATH];
510 WCHAR squashedW[MAX_PATH];
515 hr = CoCreateGuid(&guid);
516 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
518 size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
519 ok(size == 39, "Expected 39, got %d\n", hr);
521 WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
522 encode_base85_guid(&guid, base85W);
523 WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
524 squash_guid(guidW, squashedW);
525 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
528 static void test_MsiQueryFeatureState(void)
530 HKEY userkey, localkey, compkey;
531 CHAR prodcode[MAX_PATH];
532 CHAR prod_squashed[MAX_PATH];
533 CHAR component[MAX_PATH];
534 CHAR comp_base85[MAX_PATH];
535 CHAR comp_squashed[MAX_PATH];
536 CHAR keypath[MAX_PATH*2];
541 create_test_guid(prodcode, prod_squashed);
542 compose_base85_guid(component, comp_base85, comp_squashed);
543 get_user_sid(&usersid);
546 state = MsiQueryFeatureStateA(NULL, "feature");
547 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
550 state = MsiQueryFeatureStateA("", "feature");
551 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
553 /* garbage prodcode */
554 state = MsiQueryFeatureStateA("garbage", "feature");
555 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
557 /* guid without brackets */
558 state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
559 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
561 /* guid with brackets */
562 state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
563 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
565 /* same length as guid, but random */
566 state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
567 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
570 state = MsiQueryFeatureStateA(prodcode, NULL);
571 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
573 /* empty szFeature */
574 state = MsiQueryFeatureStateA(prodcode, "");
575 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
577 /* feature key does not exist yet */
578 state = MsiQueryFeatureStateA(prodcode, "feature");
579 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
581 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
582 lstrcatA(keypath, prod_squashed);
584 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
585 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
587 /* feature key exists */
588 state = MsiQueryFeatureStateA(prodcode, "feature");
589 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
591 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 8);
592 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
594 state = MsiQueryFeatureStateA(prodcode, "feature");
595 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
597 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
598 lstrcatA(keypath, usersid);
599 lstrcatA(keypath, "\\Products\\");
600 lstrcatA(keypath, prod_squashed);
601 lstrcatA(keypath, "\\Features");
603 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
604 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
606 state = MsiQueryFeatureStateA(prodcode, "feature");
607 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
609 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
610 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
612 state = MsiQueryFeatureStateA(prodcode, "feature");
613 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
615 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
616 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
618 state = MsiQueryFeatureStateA(prodcode, "feature");
619 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
621 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
622 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
624 state = MsiQueryFeatureStateA(prodcode, "feature");
625 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
627 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21);
628 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
630 state = MsiQueryFeatureStateA(prodcode, "feature");
631 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
633 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
634 lstrcatA(keypath, usersid);
635 lstrcatA(keypath, "\\Components\\");
636 lstrcatA(keypath, comp_squashed);
638 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
639 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
641 state = MsiQueryFeatureStateA(prodcode, "feature");
642 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
644 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
645 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
647 state = MsiQueryFeatureStateA(prodcode, "feature");
648 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
650 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1);
651 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
653 state = MsiQueryFeatureStateA(prodcode, "feature");
654 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
656 RegDeleteValueA(compkey, prod_squashed);
657 RegDeleteValueA(compkey, "");
658 RegDeleteValueA(localkey, "feature");
659 RegDeleteValueA(userkey, "feature");
660 RegDeleteKeyA(userkey, "");
661 RegCloseKey(compkey);
662 RegCloseKey(localkey);
663 RegCloseKey(userkey);
666 static void test_MsiQueryComponentState(void)
668 HKEY compkey, prodkey;
669 CHAR prodcode[MAX_PATH];
670 CHAR prod_squashed[MAX_PATH];
671 CHAR component[MAX_PATH];
672 CHAR comp_base85[MAX_PATH];
673 CHAR comp_squashed[MAX_PATH];
674 CHAR keypath[MAX_PATH];
680 create_test_guid(prodcode, prod_squashed);
681 compose_base85_guid(component, comp_base85, comp_squashed);
682 get_user_sid(&usersid);
684 /* NULL szProductCode */
686 r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
687 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
688 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
690 /* empty szProductCode */
692 r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);\
693 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
694 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
696 /* random szProductCode */
698 r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
699 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
700 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
702 /* GUID-length szProductCode */
704 r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
705 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
706 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
708 /* GUID-length with brackets */
710 r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
711 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
712 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
716 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
717 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
718 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
721 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
722 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
723 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
725 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
726 lstrcatA(keypath, prod_squashed);
728 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
729 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
732 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
733 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
734 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
736 RegDeleteKeyA(prodkey, "");
737 RegCloseKey(prodkey);
739 /* create local system product key */
740 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
741 lstrcatA(keypath, prod_squashed);
742 lstrcatA(keypath, "\\InstallProperties");
744 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
745 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
747 /* local system product key exists */
749 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
750 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
751 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
753 res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
754 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
756 /* LocalPackage value exists */
758 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
759 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
760 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
762 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
763 lstrcatA(keypath, comp_squashed);
765 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
766 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
768 /* component key exists */
770 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
771 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
772 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
774 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
775 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
777 /* component\product exists */
779 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
780 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
781 ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
783 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
784 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
787 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
788 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
789 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
791 RegDeleteValueA(prodkey, "LocalPackage");
792 RegDeleteKeyA(prodkey, "");
793 RegDeleteValueA(compkey, prod_squashed);
794 RegDeleteKeyA(prodkey, "");
795 RegCloseKey(prodkey);
796 RegCloseKey(compkey);
798 /* MSIINSTALLCONTEXT_USERUNMANAGED */
801 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
802 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
803 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
805 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
806 lstrcatA(keypath, prod_squashed);
808 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
809 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
812 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
813 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
814 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
816 RegDeleteKeyA(prodkey, "");
817 RegCloseKey(prodkey);
819 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
820 lstrcatA(keypath, usersid);
821 lstrcatA(keypath, "\\Products\\");
822 lstrcatA(keypath, prod_squashed);
823 lstrcatA(keypath, "\\InstallProperties");
825 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
826 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
828 res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
829 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
831 RegCloseKey(prodkey);
834 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
835 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
836 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
838 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
839 lstrcatA(keypath, usersid);
840 lstrcatA(keypath, "\\Components\\");
841 lstrcatA(keypath, comp_squashed);
843 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
844 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
846 /* component key exists */
848 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
849 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
850 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
852 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
853 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
855 /* component\product exists */
857 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
858 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
859 ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
861 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
862 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
865 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
866 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
867 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
869 /* MSIINSTALLCONTEXT_USERMANAGED */
872 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
873 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
874 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
876 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
877 lstrcatA(keypath, prod_squashed);
879 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
880 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
883 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
884 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
885 ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
887 RegDeleteKeyA(prodkey, "");
888 RegCloseKey(prodkey);
890 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
891 lstrcatA(keypath, usersid);
892 lstrcatA(keypath, "\\Installer\\Products\\");
893 lstrcatA(keypath, prod_squashed);
895 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
896 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
899 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
900 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
901 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
903 RegDeleteKeyA(prodkey, "");
904 RegCloseKey(prodkey);
906 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
907 lstrcatA(keypath, usersid);
908 lstrcatA(keypath, "\\Products\\");
909 lstrcatA(keypath, prod_squashed);
910 lstrcatA(keypath, "\\InstallProperties");
912 res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
913 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
915 res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
916 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
919 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
920 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
921 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
923 RegDeleteValueA(prodkey, "LocalPackage");
924 RegDeleteValueA(prodkey, "ManagedLocalPackage");
925 RegDeleteKeyA(prodkey, "");
926 RegDeleteValueA(compkey, prod_squashed);
927 RegDeleteKeyA(compkey, "");
928 RegCloseKey(prodkey);
929 RegCloseKey(compkey);
934 init_functionpointers();
938 test_getcomponentpath();
940 test_MsiQueryProductState();
941 test_MsiQueryFeatureState();
942 test_MsiQueryComponentState();