mshtml: Fixed handling channels without container and necko channel.
[wine] / dlls / msi / tests / msi.c
1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
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 #define _WIN32_MSI 300
22
23 #include <stdio.h>
24 #include <windows.h>
25 #include <msi.h>
26 #include <msiquery.h>
27 #include <sddl.h>
28
29 #include "wine/test.h"
30
31 typedef struct test_MSIFILEHASHINFO {
32     ULONG dwFileHashInfoSize;
33     ULONG dwData[4];
34 } test_MSIFILEHASHINFO, *test_PMSIFILEHASHINFO;
35
36 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
37
38 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
39     (LPCSTR, LPCSTR, LPSTR, DWORD*);
40 static UINT (WINAPI *pMsiGetFileHashA)
41     (LPCSTR, DWORD, test_PMSIFILEHASHINFO);
42 static UINT (WINAPI *pMsiOpenPackageExA)
43     (LPCSTR, DWORD, MSIHANDLE*);
44 static UINT (WINAPI *pMsiOpenPackageExW)
45     (LPCWSTR, DWORD, MSIHANDLE*);
46 static UINT (WINAPI *pMsiQueryComponentStateA)
47     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
48 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
49     (LPCSTR, LPCSTR ,DWORD, DWORD );
50
51 static void init_functionpointers(void)
52 {
53     HMODULE hmsi = GetModuleHandleA("msi.dll");
54     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
55
56     pMsiGetComponentPathA = (void*)GetProcAddress(hmsi, "MsiGetComponentPathA");
57     pMsiGetFileHashA = (void*)GetProcAddress(hmsi, "MsiGetFileHashA");
58     pMsiOpenPackageExA = (void*)GetProcAddress(hmsi, "MsiOpenPackageExA");
59     pMsiOpenPackageExW = (void*)GetProcAddress(hmsi, "MsiOpenPackageExW");
60     pMsiQueryComponentStateA = (void*)GetProcAddress(hmsi, "MsiQueryComponentStateA");
61     pMsiUseFeatureExA = (void*)GetProcAddress(hmsi, "MsiUseFeatureExA");
62
63     pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
64 }
65
66 static void test_usefeature(void)
67 {
68     INSTALLSTATE r;
69
70     if (!pMsiUseFeatureExA)
71         return;
72
73     r = MsiQueryFeatureState(NULL,NULL);
74     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
75
76     r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
77     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
78
79     r = pMsiUseFeatureExA(NULL,NULL,0,0);
80     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
81
82     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
83     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
84
85     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
86                          NULL, -2, 0 );
87     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
88
89     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}", 
90                          "WORDVIEWFiles", -2, 0 );
91     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
92
93     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}", 
94                          "WORDVIEWFiles", -2, 0 );
95     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
96
97     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
98                          "WORDVIEWFiles", -2, 1 );
99     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
100 }
101
102 static void test_null(void)
103 {
104     MSIHANDLE hpkg;
105     UINT r;
106     HKEY hkey;
107     DWORD dwType, cbData;
108     LPBYTE lpData = NULL;
109     INSTALLSTATE state;
110
111     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
112     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
113
114     state = MsiQueryProductStateW(NULL);
115     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
116
117     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
118     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
119
120     r = MsiConfigureFeatureW(NULL, NULL, 0);
121     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
122
123     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
124     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
125
126     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", 0);
127     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
128
129     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", INSTALLSTATE_DEFAULT);
130     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
131
132     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
133      * necessary registry values */
134
135     /* empty product string */
136     r = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", &hkey);
137     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
138
139     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
140     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
141     if ( r == ERROR_SUCCESS )
142     {
143         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
144         if (!lpData)
145             skip("Out of memory\n");
146         else
147         {
148             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
149             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
150         }
151     }
152
153     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
154     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
155
156     r = MsiGetProductInfoA("", "", NULL, NULL);
157     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
158
159     if (lpData)
160     {
161         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
162         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
163
164         HeapFree(GetProcessHeap(), 0, lpData);
165     }
166     else
167     {
168         r = RegDeleteValueA(hkey, NULL);
169         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
170     }
171
172     r = RegCloseKey(hkey);
173     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
174
175     /* empty attribute */
176     r = RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", &hkey);
177     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
178
179     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
180     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
181
182     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
183     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
184
185     r = RegCloseKey(hkey);
186     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
187
188     r = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}");
189     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
190 }
191
192 static void test_getcomponentpath(void)
193 {
194     INSTALLSTATE r;
195     char buffer[0x100];
196     DWORD sz;
197
198     if(!pMsiGetComponentPathA)
199         return;
200
201     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
202     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
203
204     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
205     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
206
207     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
208     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
209
210     sz = sizeof buffer;
211     buffer[0]=0;
212     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
213     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
214
215     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
216         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
217     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
218
219     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
220         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
221     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
222
223     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
224         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
225     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
226
227     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
228                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
229     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
230 }
231
232 static void test_filehash(void)
233 {
234     const char name[] = "msitest.bin";
235     const char data[] = {'a','b','c'};
236     HANDLE handle;
237     UINT r;
238     test_MSIFILEHASHINFO hash;
239     DWORD count = 0;
240
241     if (!pMsiGetFileHashA)
242         return;
243
244     DeleteFile(name);
245
246     memset(&hash, 0, sizeof hash);
247     r = pMsiGetFileHashA(name, 0, &hash);
248     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
249
250     r = pMsiGetFileHashA(name, 0, NULL);
251     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
252
253     memset(&hash, 0, sizeof hash);
254     hash.dwFileHashInfoSize = sizeof hash;
255     r = pMsiGetFileHashA(name, 0, &hash);
256     ok( r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
257
258     handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, NULL, 
259                 CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
260     ok(handle != INVALID_HANDLE_VALUE, "failed to create file\n");
261
262     WriteFile(handle, data, sizeof data, &count, NULL);
263     CloseHandle(handle);
264
265     memset(&hash, 0, sizeof hash);
266     r = pMsiGetFileHashA(name, 0, &hash);
267     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
268
269     memset(&hash, 0, sizeof hash);
270     hash.dwFileHashInfoSize = sizeof hash;
271     r = pMsiGetFileHashA(name, 1, &hash);
272     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
273
274     r = pMsiGetFileHashA(name, 0, &hash);
275     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
276
277     ok(hash.dwFileHashInfoSize == sizeof hash, "hash size changed\n");
278     ok(hash.dwData[0] == 0x98500190 &&
279        hash.dwData[1] == 0xb04fd23c &&
280        hash.dwData[2] == 0x7d3f96d6 &&
281        hash.dwData[3] == 0x727fe128, "hash of abc incorrect\n");
282
283     DeleteFile(name);
284 }
285
286 /* copied from dlls/msi/registry.c */
287 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
288 {
289     DWORD i,n=1;
290     GUID guid;
291
292     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
293         return FALSE;
294
295     for(i=0; i<8; i++)
296         out[7-i] = in[n++];
297     n++;
298     for(i=0; i<4; i++)
299         out[11-i] = in[n++];
300     n++;
301     for(i=0; i<4; i++)
302         out[15-i] = in[n++];
303     n++;
304     for(i=0; i<2; i++)
305     {
306         out[17+i*2] = in[n++];
307         out[16+i*2] = in[n++];
308     }
309     n++;
310     for( ; i<8; i++)
311     {
312         out[17+i*2] = in[n++];
313         out[16+i*2] = in[n++];
314     }
315     out[32]=0;
316     return TRUE;
317 }
318
319 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
320 {
321     WCHAR guidW[MAX_PATH];
322     WCHAR squashedW[MAX_PATH];
323     GUID guid;
324     HRESULT hr;
325     int size;
326
327     hr = CoCreateGuid(&guid);
328     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
329
330     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
331     ok(size == 39, "Expected 39, got %d\n", hr);
332
333     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
334     squash_guid(guidW, squashedW);
335     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
336 }
337
338 static void get_user_sid(LPSTR *usersid)
339 {
340     HANDLE token;
341     BYTE buf[1024];
342     DWORD size;
343     PTOKEN_USER user;
344
345     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
346     size = sizeof(buf);
347     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
348     user = (PTOKEN_USER)buf;
349     pConvertSidToStringSidA(user->User.Sid, usersid);
350 }
351
352 static void test_MsiQueryProductState(void)
353 {
354     CHAR prodcode[MAX_PATH];
355     CHAR prod_squashed[MAX_PATH];
356     CHAR keypath[MAX_PATH*2];
357     LPSTR usersid;
358     INSTALLSTATE state;
359     LONG res;
360     HKEY userkey, localkey, props;
361     DWORD data;
362
363     create_test_guid(prodcode, prod_squashed);
364     get_user_sid(&usersid);
365
366     /* NULL prodcode */
367     state = MsiQueryProductStateA(NULL);
368     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
369
370     /* empty prodcode */
371     state = MsiQueryProductStateA("");
372     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
373
374     /* garbage prodcode */
375     state = MsiQueryProductStateA("garbage");
376     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
377
378     /* guid without brackets */
379     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
380     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
381
382     /* guid with brackets */
383     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
384     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
385
386     /* same length as guid, but random */
387     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
388     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
389
390     /* created guid cannot possibly be an installed product code */
391     state = MsiQueryProductStateA(prodcode);
392     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
393
394     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
395     lstrcatA(keypath, prod_squashed);
396
397     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
399
400     /* user product key exists */
401     state = MsiQueryProductStateA(prodcode);
402     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
403
404     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
405     lstrcatA(keypath, prodcode);
406
407     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
409
410     /* local uninstall key exists */
411     state = MsiQueryProductStateA(prodcode);
412     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
413
414     data = 1;
415     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
417
418     /* WindowsInstaller value exists */
419     state = MsiQueryProductStateA(prodcode);
420     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
421
422     RegDeleteValueA(localkey, "WindowsInstaller");
423     RegDeleteKeyA(localkey, "");
424
425     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
426     lstrcatA(keypath, usersid);
427     lstrcatA(keypath, "\\Products\\");
428     lstrcatA(keypath, prod_squashed);
429
430     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
431     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
432
433     /* local product key exists */
434     state = MsiQueryProductStateA(prodcode);
435     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
436
437     res = RegCreateKeyA(localkey, "InstallProperties", &props);
438     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
439
440     /* install properties key exists */
441     state = MsiQueryProductStateA(prodcode);
442     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
443
444     data = 1;
445     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
446     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
447
448     /* WindowsInstaller value exists */
449     state = MsiQueryProductStateA(prodcode);
450     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
451
452     data = 2;
453     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
455
456     /* WindowsInstaller value is not 1 */
457     state = MsiQueryProductStateA(prodcode);
458     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
459
460     RegDeleteKeyA(userkey, "");
461
462     /* user product key does not exist */
463     state = MsiQueryProductStateA(prodcode);
464     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
465
466     LocalFree(usersid);
467     RegDeleteValueA(props, "WindowsInstaller");
468     RegDeleteKeyA(props, "");
469     RegDeleteKeyA(localkey, "");
470     RegCloseKey(userkey);
471     RegCloseKey(localkey);
472     RegCloseKey(props);
473 }
474
475 static const char table_enc85[] =
476 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
477 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
478 "yz{}~";
479
480 /*
481  *  Encodes a base85 guid given a GUID pointer
482  *  Caller should provide a 21 character buffer for the encoded string.
483  *
484  *  returns TRUE if successful, FALSE if not
485  */
486 static BOOL encode_base85_guid( GUID *guid, LPWSTR str )
487 {
488     unsigned int x, *p, i;
489
490     p = (unsigned int*) guid;
491     for( i=0; i<4; i++ )
492     {
493         x = p[i];
494         *str++ = table_enc85[x%85];
495         x = x/85;
496         *str++ = table_enc85[x%85];
497         x = x/85;
498         *str++ = table_enc85[x%85];
499         x = x/85;
500         *str++ = table_enc85[x%85];
501         x = x/85;
502         *str++ = table_enc85[x%85];
503     }
504     *str = 0;
505
506     return TRUE;
507 }
508
509 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
510 {
511     WCHAR guidW[MAX_PATH];
512     WCHAR base85W[MAX_PATH];
513     WCHAR squashedW[MAX_PATH];
514     GUID guid;
515     HRESULT hr;
516     int size;
517
518     hr = CoCreateGuid(&guid);
519     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
520
521     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
522     ok(size == 39, "Expected 39, got %d\n", hr);
523
524     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
525     encode_base85_guid(&guid, base85W);
526     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
527     squash_guid(guidW, squashedW);
528     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
529 }
530
531 static void test_MsiQueryFeatureState(void)
532 {
533     HKEY userkey, localkey, compkey;
534     CHAR prodcode[MAX_PATH];
535     CHAR prod_squashed[MAX_PATH];
536     CHAR component[MAX_PATH];
537     CHAR comp_base85[MAX_PATH];
538     CHAR comp_squashed[MAX_PATH];
539     CHAR keypath[MAX_PATH*2];
540     INSTALLSTATE state;
541     LPSTR usersid;
542     LONG res;
543
544     create_test_guid(prodcode, prod_squashed);
545     compose_base85_guid(component, comp_base85, comp_squashed);
546     get_user_sid(&usersid);
547
548     /* NULL prodcode */
549     state = MsiQueryFeatureStateA(NULL, "feature");
550     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
551
552     /* empty prodcode */
553     state = MsiQueryFeatureStateA("", "feature");
554     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
555
556     /* garbage prodcode */
557     state = MsiQueryFeatureStateA("garbage", "feature");
558     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
559
560     /* guid without brackets */
561     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
562     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
563
564     /* guid with brackets */
565     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
566     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
567
568     /* same length as guid, but random */
569     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
570     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
571
572     /* NULL szFeature */
573     state = MsiQueryFeatureStateA(prodcode, NULL);
574     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
575
576     /* empty szFeature */
577     state = MsiQueryFeatureStateA(prodcode, "");
578     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
579
580     /* feature key does not exist yet */
581     state = MsiQueryFeatureStateA(prodcode, "feature");
582     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
583
584     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
585     lstrcatA(keypath, prod_squashed);
586
587     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
588     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
589
590     /* feature key exists */
591     state = MsiQueryFeatureStateA(prodcode, "feature");
592     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
593
594     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 8);
595     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
596
597     state = MsiQueryFeatureStateA(prodcode, "feature");
598     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
599
600     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
601     lstrcatA(keypath, usersid);
602     lstrcatA(keypath, "\\Products\\");
603     lstrcatA(keypath, prod_squashed);
604     lstrcatA(keypath, "\\Features");
605
606     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
607     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
608
609     state = MsiQueryFeatureStateA(prodcode, "feature");
610     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
611
612     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
613     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
614
615     state = MsiQueryFeatureStateA(prodcode, "feature");
616     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
617
618     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
619     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
620
621     state = MsiQueryFeatureStateA(prodcode, "feature");
622     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
623
624     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
625     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
626
627     state = MsiQueryFeatureStateA(prodcode, "feature");
628     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
629
630     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21);
631     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
632
633     state = MsiQueryFeatureStateA(prodcode, "feature");
634     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
635
636     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
637     lstrcatA(keypath, usersid);
638     lstrcatA(keypath, "\\Components\\");
639     lstrcatA(keypath, comp_squashed);
640
641     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
642     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
643
644     state = MsiQueryFeatureStateA(prodcode, "feature");
645     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
646
647     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
648     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
649
650     state = MsiQueryFeatureStateA(prodcode, "feature");
651     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
652
653     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1);
654     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
655
656     state = MsiQueryFeatureStateA(prodcode, "feature");
657     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
658
659     RegDeleteValueA(compkey, prod_squashed);
660     RegDeleteValueA(compkey, "");
661     RegDeleteValueA(localkey, "feature");
662     RegDeleteValueA(userkey, "feature");
663     RegDeleteKeyA(userkey, "");
664     RegCloseKey(compkey);
665     RegCloseKey(localkey);
666     RegCloseKey(userkey);
667 }
668
669 static void test_MsiQueryComponentState(void)
670 {
671     HKEY compkey, prodkey;
672     CHAR prodcode[MAX_PATH];
673     CHAR prod_squashed[MAX_PATH];
674     CHAR component[MAX_PATH];
675     CHAR comp_base85[MAX_PATH];
676     CHAR comp_squashed[MAX_PATH];
677     CHAR keypath[MAX_PATH];
678     INSTALLSTATE state;
679     LPSTR usersid;
680     LONG res;
681     UINT r;
682
683     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
684
685     create_test_guid(prodcode, prod_squashed);
686     compose_base85_guid(component, comp_base85, comp_squashed);
687     get_user_sid(&usersid);
688
689     /* NULL szProductCode */
690     state = MAGIC_ERROR;
691     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
692     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
693     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
694
695     /* empty szProductCode */
696     state = MAGIC_ERROR;
697     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);\
698     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
699     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
700
701     /* random szProductCode */
702     state = MAGIC_ERROR;
703     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
704     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
705     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
706
707     /* GUID-length szProductCode */
708     state = MAGIC_ERROR;
709     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
710     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
711     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
712
713     /* GUID-length with brackets */
714     state = MAGIC_ERROR;
715     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
716     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
717     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
718
719     /* actual GUID */
720     state = MAGIC_ERROR;
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 == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
724
725     state = MAGIC_ERROR;
726     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
727     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
728     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
729
730     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
731     lstrcatA(keypath, prod_squashed);
732
733     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
734     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
735
736     state = MAGIC_ERROR;
737     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
738     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
739     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
740
741     RegDeleteKeyA(prodkey, "");
742     RegCloseKey(prodkey);
743
744     /* create local system product key */
745     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
746     lstrcatA(keypath, prod_squashed);
747     lstrcatA(keypath, "\\InstallProperties");
748
749     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
750     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
751
752     /* local system product key exists */
753     state = MAGIC_ERROR;
754     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
755     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
756     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
757
758     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
760
761     /* LocalPackage value exists */
762     state = MAGIC_ERROR;
763     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
764     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
765     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
766
767     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
768     lstrcatA(keypath, comp_squashed);
769
770     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
771     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
772
773     /* component key exists */
774     state = MAGIC_ERROR;
775     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
776     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
777     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
778
779     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
780     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
781
782     /* component\product exists */
783     state = MAGIC_ERROR;
784     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
786     ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
787
788     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
789     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
790
791     state = MAGIC_ERROR;
792     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
794     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
795
796     RegDeleteValueA(prodkey, "LocalPackage");
797     RegDeleteKeyA(prodkey, "");
798     RegDeleteValueA(compkey, prod_squashed);
799     RegDeleteKeyA(prodkey, "");
800     RegCloseKey(prodkey);
801     RegCloseKey(compkey);
802
803     /* MSIINSTALLCONTEXT_USERUNMANAGED */
804
805     state = MAGIC_ERROR;
806     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
807     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
808     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
809
810     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
811     lstrcatA(keypath, prod_squashed);
812
813     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
814     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
815
816     state = MAGIC_ERROR;
817     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 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);
820
821     RegDeleteKeyA(prodkey, "");
822     RegCloseKey(prodkey);
823
824     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
825     lstrcatA(keypath, usersid);
826     lstrcatA(keypath, "\\Products\\");
827     lstrcatA(keypath, prod_squashed);
828     lstrcatA(keypath, "\\InstallProperties");
829
830     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
831     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
832
833     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
834     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
835
836     RegCloseKey(prodkey);
837
838     state = MAGIC_ERROR;
839     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
840     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
841     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
842
843     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
844     lstrcatA(keypath, usersid);
845     lstrcatA(keypath, "\\Components\\");
846     lstrcatA(keypath, comp_squashed);
847
848     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
849     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
850
851     /* component key exists */
852     state = MAGIC_ERROR;
853     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
854     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
855     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
856
857     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
858     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
859
860     /* component\product exists */
861     state = MAGIC_ERROR;
862     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
864     ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
865
866     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
867     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
868
869     state = MAGIC_ERROR;
870     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
872     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
873
874     /* MSIINSTALLCONTEXT_USERMANAGED */
875
876     state = MAGIC_ERROR;
877     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
878     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
879     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
880
881     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
882     lstrcatA(keypath, prod_squashed);
883
884     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
886
887     state = MAGIC_ERROR;
888     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
889     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
890     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
891
892     RegDeleteKeyA(prodkey, "");
893     RegCloseKey(prodkey);
894
895     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
896     lstrcatA(keypath, usersid);
897     lstrcatA(keypath, "\\Installer\\Products\\");
898     lstrcatA(keypath, prod_squashed);
899
900     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
902
903     state = MAGIC_ERROR;
904     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
905     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
906     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
907
908     RegDeleteKeyA(prodkey, "");
909     RegCloseKey(prodkey);
910
911     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
912     lstrcatA(keypath, usersid);
913     lstrcatA(keypath, "\\Products\\");
914     lstrcatA(keypath, prod_squashed);
915     lstrcatA(keypath, "\\InstallProperties");
916
917     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
918     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
919
920     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
921     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
922
923     state = MAGIC_ERROR;
924     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
925     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
926     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
927
928     RegDeleteValueA(prodkey, "LocalPackage");
929     RegDeleteValueA(prodkey, "ManagedLocalPackage");
930     RegDeleteKeyA(prodkey, "");
931     RegDeleteValueA(compkey, prod_squashed);
932     RegDeleteKeyA(compkey, "");
933     RegCloseKey(prodkey);
934     RegCloseKey(compkey);
935 }
936
937 START_TEST(msi)
938 {
939     init_functionpointers();
940
941     test_usefeature();
942     test_null();
943     test_getcomponentpath();
944     test_filehash();
945     test_MsiQueryProductState();
946     test_MsiQueryFeatureState();
947     test_MsiQueryComponentState();
948 }