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
21 #define _WIN32_MSI 300
29 #include "wine/test.h"
31 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
33 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
34 (LPCSTR, LPCSTR, LPSTR, DWORD*);
35 static UINT (WINAPI *pMsiGetFileHashA)
36 (LPCSTR, DWORD, PMSIFILEHASHINFO);
37 static UINT (WINAPI *pMsiOpenPackageExA)
38 (LPCSTR, DWORD, MSIHANDLE*);
39 static UINT (WINAPI *pMsiOpenPackageExW)
40 (LPCWSTR, DWORD, MSIHANDLE*);
41 static UINT (WINAPI *pMsiQueryComponentStateA)
42 (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
43 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
44 (LPCSTR, LPCSTR ,DWORD, DWORD );
46 static void init_functionpointers(void)
48 HMODULE hmsi = GetModuleHandleA("msi.dll");
49 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
51 pMsiGetComponentPathA = (void*)GetProcAddress(hmsi, "MsiGetComponentPathA");
52 pMsiGetFileHashA = (void*)GetProcAddress(hmsi, "MsiGetFileHashA");
53 pMsiOpenPackageExA = (void*)GetProcAddress(hmsi, "MsiOpenPackageExA");
54 pMsiOpenPackageExW = (void*)GetProcAddress(hmsi, "MsiOpenPackageExW");
55 pMsiQueryComponentStateA = (void*)GetProcAddress(hmsi, "MsiQueryComponentStateA");
56 pMsiUseFeatureExA = (void*)GetProcAddress(hmsi, "MsiUseFeatureExA");
58 pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
61 static void test_usefeature(void)
65 if (!pMsiUseFeatureExA)
68 r = MsiQueryFeatureState(NULL,NULL);
69 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
71 r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
72 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
74 r = pMsiUseFeatureExA(NULL,NULL,0,0);
75 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
77 r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
78 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
80 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
82 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
84 r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
85 "WORDVIEWFiles", -2, 0 );
86 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
88 r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
89 "WORDVIEWFiles", -2, 0 );
90 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
92 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
93 "WORDVIEWFiles", -2, 1 );
94 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
97 static void test_null(void)
102 DWORD dwType, cbData;
103 LPBYTE lpData = NULL;
106 r = pMsiOpenPackageExW(NULL, 0, &hpkg);
107 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
109 state = MsiQueryProductStateW(NULL);
110 ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
112 r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
113 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
115 r = MsiConfigureFeatureW(NULL, NULL, 0);
116 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
118 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
119 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
121 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", 0);
122 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
124 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", INSTALLSTATE_DEFAULT);
125 ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
127 /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
128 * necessary registry values */
130 /* empty product string */
131 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", &hkey);
132 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
134 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
135 ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
136 if ( r == ERROR_SUCCESS )
138 lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
140 skip("Out of memory\n");
143 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
144 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
148 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
149 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
151 r = MsiGetProductInfoA("", "", NULL, NULL);
152 ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
156 r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
157 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
159 HeapFree(GetProcessHeap(), 0, lpData);
163 r = RegDeleteValueA(hkey, NULL);
164 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
167 r = RegCloseKey(hkey);
168 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
170 /* empty attribute */
171 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", &hkey);
172 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
174 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
175 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
177 r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
178 ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
180 r = RegCloseKey(hkey);
181 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
183 r = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}");
184 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
187 static void test_getcomponentpath(void)
193 if(!pMsiGetComponentPathA)
196 r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
197 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
199 r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
200 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
202 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
203 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
207 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
208 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
210 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
211 "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
212 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
214 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
215 "{00000000-0000-0000-0000-00000000}", buffer, &sz );
216 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
218 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
219 "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
220 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
222 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
223 "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
224 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
227 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
232 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
233 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
234 WriteFile(file, data, strlen(data), &written, NULL);
238 SetFilePointer(file, size, NULL, FILE_BEGIN);
245 #define HASHSIZE sizeof(MSIFILEHASHINFO)
251 MSIFILEHASHINFO hash;
256 { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
260 { "C:\\Program Files\\msitest\\caesar\n", 0,
262 { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
266 { "C:\\Program Files\\msitest\\caesar\n", 500,
268 { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
273 static void test_MsiGetFileHash(void)
275 const char name[] = "msitest.bin";
277 MSIFILEHASHINFO hash;
280 if (!pMsiGetFileHashA)
282 skip("MsiGetFileHash not implemented.");
286 hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
288 /* szFilePath is NULL */
289 r = pMsiGetFileHashA(NULL, 0, &hash);
290 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
292 /* szFilePath is empty */
293 r = pMsiGetFileHashA("", 0, &hash);
294 ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", r);
296 /* szFilePath is nonexistent */
297 r = pMsiGetFileHashA(name, 0, &hash);
298 ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
300 /* dwOptions is non-zero */
301 r = pMsiGetFileHashA(name, 1, &hash);
302 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
304 /* pHash.dwFileHashInfoSize is not correct */
305 hash.dwFileHashInfoSize = 0;
306 r = pMsiGetFileHashA(name, 0, &hash);
307 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
310 r = pMsiGetFileHashA(name, 0, NULL);
311 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
313 for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
315 create_file(name, hash_data[i].data, hash_data[i].size);
317 memset(&hash, 0, sizeof(MSIFILEHASHINFO));
318 hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
320 r = pMsiGetFileHashA(name, 0, &hash);
321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
322 ok(!memcmp(&hash, &hash_data[i].hash, HASHSIZE), "Hash incorrect\n");
328 /* copied from dlls/msi/registry.c */
329 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
334 if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
348 out[17+i*2] = in[n++];
349 out[16+i*2] = in[n++];
354 out[17+i*2] = in[n++];
355 out[16+i*2] = in[n++];
361 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
363 WCHAR guidW[MAX_PATH];
364 WCHAR squashedW[MAX_PATH];
369 hr = CoCreateGuid(&guid);
370 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
372 size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
373 ok(size == 39, "Expected 39, got %d\n", hr);
375 WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
376 squash_guid(guidW, squashedW);
377 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
380 static void get_user_sid(LPSTR *usersid)
387 OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
389 GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
390 user = (PTOKEN_USER)buf;
391 pConvertSidToStringSidA(user->User.Sid, usersid);
394 static void test_MsiQueryProductState(void)
396 CHAR prodcode[MAX_PATH];
397 CHAR prod_squashed[MAX_PATH];
398 CHAR keypath[MAX_PATH*2];
402 HKEY userkey, localkey, props;
405 create_test_guid(prodcode, prod_squashed);
406 get_user_sid(&usersid);
409 state = MsiQueryProductStateA(NULL);
410 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
413 state = MsiQueryProductStateA("");
414 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
416 /* garbage prodcode */
417 state = MsiQueryProductStateA("garbage");
418 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
420 /* guid without brackets */
421 state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
422 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
424 /* guid with brackets */
425 state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
426 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
428 /* same length as guid, but random */
429 state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
430 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
432 /* created guid cannot possibly be an installed product code */
433 state = MsiQueryProductStateA(prodcode);
434 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
436 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
437 lstrcatA(keypath, prod_squashed);
439 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
440 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
442 /* user product key exists */
443 state = MsiQueryProductStateA(prodcode);
444 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
446 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
447 lstrcatA(keypath, prodcode);
449 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
450 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
452 /* local uninstall key exists */
453 state = MsiQueryProductStateA(prodcode);
454 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
457 res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
458 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
460 /* WindowsInstaller value exists */
461 state = MsiQueryProductStateA(prodcode);
462 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
464 RegDeleteValueA(localkey, "WindowsInstaller");
465 RegDeleteKeyA(localkey, "");
467 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
468 lstrcatA(keypath, usersid);
469 lstrcatA(keypath, "\\Products\\");
470 lstrcatA(keypath, prod_squashed);
472 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
473 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
475 /* local product key exists */
476 state = MsiQueryProductStateA(prodcode);
477 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
479 res = RegCreateKeyA(localkey, "InstallProperties", &props);
480 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
482 /* install properties key exists */
483 state = MsiQueryProductStateA(prodcode);
484 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
487 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
488 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
490 /* WindowsInstaller value exists */
491 state = MsiQueryProductStateA(prodcode);
492 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
495 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
496 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
498 /* WindowsInstaller value is not 1 */
499 state = MsiQueryProductStateA(prodcode);
500 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
502 RegDeleteKeyA(userkey, "");
504 /* user product key does not exist */
505 state = MsiQueryProductStateA(prodcode);
506 ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
509 RegDeleteValueA(props, "WindowsInstaller");
510 RegDeleteKeyA(props, "");
511 RegDeleteKeyA(localkey, "");
512 RegCloseKey(userkey);
513 RegCloseKey(localkey);
517 static const char table_enc85[] =
518 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
519 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
523 * Encodes a base85 guid given a GUID pointer
524 * Caller should provide a 21 character buffer for the encoded string.
526 * returns TRUE if successful, FALSE if not
528 static BOOL encode_base85_guid( GUID *guid, LPWSTR str )
530 unsigned int x, *p, i;
532 p = (unsigned int*) guid;
536 *str++ = table_enc85[x%85];
538 *str++ = table_enc85[x%85];
540 *str++ = table_enc85[x%85];
542 *str++ = table_enc85[x%85];
544 *str++ = table_enc85[x%85];
551 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
553 WCHAR guidW[MAX_PATH];
554 WCHAR base85W[MAX_PATH];
555 WCHAR squashedW[MAX_PATH];
560 hr = CoCreateGuid(&guid);
561 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
563 size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
564 ok(size == 39, "Expected 39, got %d\n", hr);
566 WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
567 encode_base85_guid(&guid, base85W);
568 WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
569 squash_guid(guidW, squashedW);
570 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
573 static void test_MsiQueryFeatureState(void)
575 HKEY userkey, localkey, compkey;
576 CHAR prodcode[MAX_PATH];
577 CHAR prod_squashed[MAX_PATH];
578 CHAR component[MAX_PATH];
579 CHAR comp_base85[MAX_PATH];
580 CHAR comp_squashed[MAX_PATH];
581 CHAR keypath[MAX_PATH*2];
586 create_test_guid(prodcode, prod_squashed);
587 compose_base85_guid(component, comp_base85, comp_squashed);
588 get_user_sid(&usersid);
591 state = MsiQueryFeatureStateA(NULL, "feature");
592 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
595 state = MsiQueryFeatureStateA("", "feature");
596 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
598 /* garbage prodcode */
599 state = MsiQueryFeatureStateA("garbage", "feature");
600 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
602 /* guid without brackets */
603 state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
604 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
606 /* guid with brackets */
607 state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
608 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
610 /* same length as guid, but random */
611 state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
612 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
615 state = MsiQueryFeatureStateA(prodcode, NULL);
616 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
618 /* empty szFeature */
619 state = MsiQueryFeatureStateA(prodcode, "");
620 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
622 /* feature key does not exist yet */
623 state = MsiQueryFeatureStateA(prodcode, "feature");
624 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
626 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
627 lstrcatA(keypath, prod_squashed);
629 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
630 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
632 /* feature key exists */
633 state = MsiQueryFeatureStateA(prodcode, "feature");
634 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
636 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 8);
637 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
639 state = MsiQueryFeatureStateA(prodcode, "feature");
640 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
642 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
643 lstrcatA(keypath, usersid);
644 lstrcatA(keypath, "\\Products\\");
645 lstrcatA(keypath, prod_squashed);
646 lstrcatA(keypath, "\\Features");
648 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
649 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
651 state = MsiQueryFeatureStateA(prodcode, "feature");
652 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
654 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
655 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
657 state = MsiQueryFeatureStateA(prodcode, "feature");
658 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
660 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
661 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
663 state = MsiQueryFeatureStateA(prodcode, "feature");
664 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
666 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
667 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
669 state = MsiQueryFeatureStateA(prodcode, "feature");
670 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
672 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21);
673 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
675 state = MsiQueryFeatureStateA(prodcode, "feature");
676 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
678 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
679 lstrcatA(keypath, usersid);
680 lstrcatA(keypath, "\\Components\\");
681 lstrcatA(keypath, comp_squashed);
683 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
684 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
686 state = MsiQueryFeatureStateA(prodcode, "feature");
687 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
689 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
690 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
692 state = MsiQueryFeatureStateA(prodcode, "feature");
693 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
695 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1);
696 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
698 state = MsiQueryFeatureStateA(prodcode, "feature");
699 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
701 RegDeleteValueA(compkey, prod_squashed);
702 RegDeleteValueA(compkey, "");
703 RegDeleteValueA(localkey, "feature");
704 RegDeleteValueA(userkey, "feature");
705 RegDeleteKeyA(userkey, "");
706 RegCloseKey(compkey);
707 RegCloseKey(localkey);
708 RegCloseKey(userkey);
711 static void test_MsiQueryComponentState(void)
713 HKEY compkey, prodkey;
714 CHAR prodcode[MAX_PATH];
715 CHAR prod_squashed[MAX_PATH];
716 CHAR component[MAX_PATH];
717 CHAR comp_base85[MAX_PATH];
718 CHAR comp_squashed[MAX_PATH];
719 CHAR keypath[MAX_PATH];
725 static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
727 create_test_guid(prodcode, prod_squashed);
728 compose_base85_guid(component, comp_base85, comp_squashed);
729 get_user_sid(&usersid);
731 /* NULL szProductCode */
733 r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
734 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
735 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
737 /* empty szProductCode */
739 r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);\
740 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
741 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
743 /* random szProductCode */
745 r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
746 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
747 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
749 /* GUID-length szProductCode */
751 r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
752 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
753 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
755 /* GUID-length with brackets */
757 r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
758 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
759 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
763 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
764 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
765 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
768 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
769 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
770 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
772 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
773 lstrcatA(keypath, prod_squashed);
775 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
776 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
779 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
780 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
781 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
783 RegDeleteKeyA(prodkey, "");
784 RegCloseKey(prodkey);
786 /* create local system product key */
787 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
788 lstrcatA(keypath, prod_squashed);
789 lstrcatA(keypath, "\\InstallProperties");
791 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
792 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
794 /* local system product key exists */
796 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
797 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
798 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
800 res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
801 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
803 /* LocalPackage value exists */
805 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
806 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
807 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
809 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
810 lstrcatA(keypath, comp_squashed);
812 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
813 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
815 /* component key exists */
817 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
818 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
819 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
821 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
822 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
824 /* component\product exists */
826 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
827 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
828 ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
830 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
831 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
834 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
835 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
836 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
838 RegDeleteValueA(prodkey, "LocalPackage");
839 RegDeleteKeyA(prodkey, "");
840 RegDeleteValueA(compkey, prod_squashed);
841 RegDeleteKeyA(prodkey, "");
842 RegCloseKey(prodkey);
843 RegCloseKey(compkey);
845 /* MSIINSTALLCONTEXT_USERUNMANAGED */
848 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
849 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
850 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
852 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
853 lstrcatA(keypath, prod_squashed);
855 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
856 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
859 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
860 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
861 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
863 RegDeleteKeyA(prodkey, "");
864 RegCloseKey(prodkey);
866 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
867 lstrcatA(keypath, usersid);
868 lstrcatA(keypath, "\\Products\\");
869 lstrcatA(keypath, prod_squashed);
870 lstrcatA(keypath, "\\InstallProperties");
872 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
873 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
875 res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
876 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
878 RegCloseKey(prodkey);
881 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
882 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
883 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
885 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
886 lstrcatA(keypath, usersid);
887 lstrcatA(keypath, "\\Components\\");
888 lstrcatA(keypath, comp_squashed);
890 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
891 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
893 /* component key exists */
895 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
896 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
897 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
899 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
900 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
902 /* component\product exists */
904 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
905 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
906 ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
908 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
909 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
912 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
913 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
914 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
916 /* MSIINSTALLCONTEXT_USERMANAGED */
919 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
920 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
921 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
923 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
924 lstrcatA(keypath, prod_squashed);
926 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
927 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
930 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
931 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
932 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
934 RegDeleteKeyA(prodkey, "");
935 RegCloseKey(prodkey);
937 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
938 lstrcatA(keypath, usersid);
939 lstrcatA(keypath, "\\Installer\\Products\\");
940 lstrcatA(keypath, prod_squashed);
942 res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
943 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
946 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
947 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
948 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
950 RegDeleteKeyA(prodkey, "");
951 RegCloseKey(prodkey);
953 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
954 lstrcatA(keypath, usersid);
955 lstrcatA(keypath, "\\Products\\");
956 lstrcatA(keypath, prod_squashed);
957 lstrcatA(keypath, "\\InstallProperties");
959 res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
960 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
962 res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
963 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
966 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
967 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
968 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
970 RegDeleteValueA(prodkey, "LocalPackage");
971 RegDeleteValueA(prodkey, "ManagedLocalPackage");
972 RegDeleteKeyA(prodkey, "");
973 RegDeleteValueA(compkey, prod_squashed);
974 RegDeleteKeyA(compkey, "");
975 RegCloseKey(prodkey);
976 RegCloseKey(compkey);
981 init_functionpointers();
985 test_getcomponentpath();
986 test_MsiGetFileHash();
987 test_MsiQueryProductState();
988 test_MsiQueryFeatureState();
989 test_MsiQueryComponentState();