wintrust: Add a helper function to initialize chain creation parameters.
[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 #include <stdio.h>
22 #include <windows.h>
23 #include <msi.h>
24 #include <msiquery.h>
25 #include <sddl.h>
26
27 #include "wine/test.h"
28
29 typedef struct test_MSIFILEHASHINFO {
30     ULONG dwFileHashInfoSize;
31     ULONG dwData[4];
32 } test_MSIFILEHASHINFO, *test_PMSIFILEHASHINFO;
33
34 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
35
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 );
48
49 static void init_functionpointers(void)
50 {
51     HMODULE hmsi = GetModuleHandleA("msi.dll");
52     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
53
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");
60
61     pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
62 }
63
64 static void test_usefeature(void)
65 {
66     UINT r;
67
68     if (!pMsiUseFeatureExA)
69         return;
70
71     r = MsiQueryFeatureState(NULL,NULL);
72     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
73
74     r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
75     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
76
77     r = pMsiUseFeatureExA(NULL,NULL,0,0);
78     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
79
80     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
81     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
82
83     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
84                          NULL, -2, 0 );
85     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
86
87     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}", 
88                          "WORDVIEWFiles", -2, 0 );
89     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
90
91     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}", 
92                          "WORDVIEWFiles", -2, 0 );
93     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
94
95     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
96                          "WORDVIEWFiles", -2, 1 );
97     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
98 }
99
100 static void test_null(void)
101 {
102     MSIHANDLE hpkg;
103     UINT r;
104     HKEY hkey;
105     DWORD dwType, cbData;
106     LPBYTE lpData = NULL;
107
108     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
109     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
110
111     r = MsiQueryProductStateW(NULL);
112     ok( r == INSTALLSTATE_INVALIDARG, "wrong return\n");
113
114     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
115     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
116
117     r = MsiConfigureFeatureW(NULL, NULL, 0);
118     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
119
120     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
121     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
122
123     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", 0);
124     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
125
126     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", INSTALLSTATE_DEFAULT);
127     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
128
129     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
130      * necessary registry values */
131
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);
135
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 )
139     {
140         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
141         if (!lpData)
142             skip("Out of memory\n");
143         else
144         {
145             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
146             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
147         }
148     }
149
150     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
151     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
152
153     r = MsiGetProductInfoA("", "", NULL, NULL);
154     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
155
156     if (lpData)
157     {
158         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
159         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
160
161         HeapFree(GetProcessHeap(), 0, lpData);
162     }
163     else
164     {
165         r = RegDeleteValueA(hkey, NULL);
166         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
167     }
168
169     r = RegCloseKey(hkey);
170     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
171
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);
175
176     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
177     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
178
179     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
180     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
181
182     r = RegCloseKey(hkey);
183     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
184
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);
187 }
188
189 static void test_getcomponentpath(void)
190 {
191     INSTALLSTATE r;
192     char buffer[0x100];
193     DWORD sz;
194
195     if(!pMsiGetComponentPathA)
196         return;
197
198     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
199     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
200
201     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
202     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
203
204     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
205     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
206
207     sz = sizeof buffer;
208     buffer[0]=0;
209     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
210     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
211
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");
215
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");
219
220     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
221         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
222     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
223
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");
227 }
228
229 static void test_filehash(void)
230 {
231     const char name[] = "msitest.bin";
232     const char data[] = {'a','b','c'};
233     HANDLE handle;
234     UINT r;
235     test_MSIFILEHASHINFO hash;
236     DWORD count = 0;
237
238     if (!pMsiGetFileHashA)
239         return;
240
241     DeleteFile(name);
242
243     memset(&hash, 0, sizeof hash);
244     r = pMsiGetFileHashA(name, 0, &hash);
245     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
246
247     r = pMsiGetFileHashA(name, 0, NULL);
248     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
249
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);
254
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");
258
259     WriteFile(handle, data, sizeof data, &count, NULL);
260     CloseHandle(handle);
261
262     memset(&hash, 0, sizeof hash);
263     r = pMsiGetFileHashA(name, 0, &hash);
264     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
265
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);
270
271     r = pMsiGetFileHashA(name, 0, &hash);
272     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
273
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");
279
280     DeleteFile(name);
281 }
282
283 /* copied from dlls/msi/registry.c */
284 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
285 {
286     DWORD i,n=1;
287     GUID guid;
288
289     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
290         return FALSE;
291
292     for(i=0; i<8; i++)
293         out[7-i] = in[n++];
294     n++;
295     for(i=0; i<4; i++)
296         out[11-i] = in[n++];
297     n++;
298     for(i=0; i<4; i++)
299         out[15-i] = in[n++];
300     n++;
301     for(i=0; i<2; i++)
302     {
303         out[17+i*2] = in[n++];
304         out[16+i*2] = in[n++];
305     }
306     n++;
307     for( ; i<8; i++)
308     {
309         out[17+i*2] = in[n++];
310         out[16+i*2] = in[n++];
311     }
312     out[32]=0;
313     return TRUE;
314 }
315
316 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
317 {
318     WCHAR guidW[MAX_PATH];
319     WCHAR squashedW[MAX_PATH];
320     GUID guid;
321     HRESULT hr;
322     int size;
323
324     hr = CoCreateGuid(&guid);
325     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
326
327     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
328     ok(size == 39, "Expected 39, got %d\n", hr);
329
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);
333 }
334
335 static void get_user_sid(LPSTR *usersid)
336 {
337     HANDLE token;
338     BYTE buf[1024];
339     DWORD size;
340     PTOKEN_USER user;
341
342     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
343     size = sizeof(buf);
344     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
345     user = (PTOKEN_USER)buf;
346     pConvertSidToStringSidA(user->User.Sid, usersid);
347 }
348
349 static void test_MsiQueryProductState(void)
350 {
351     CHAR prodcode[MAX_PATH];
352     CHAR prod_squashed[MAX_PATH];
353     CHAR keypath[MAX_PATH*2];
354     LPSTR usersid;
355     INSTALLSTATE state;
356     LONG res;
357     HKEY userkey, localkey, props;
358     DWORD data;
359
360     create_test_guid(prodcode, prod_squashed);
361     get_user_sid(&usersid);
362
363     /* NULL prodcode */
364     state = MsiQueryProductStateA(NULL);
365     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
366
367     /* empty prodcode */
368     state = MsiQueryProductStateA("");
369     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
370
371     /* garbage prodcode */
372     state = MsiQueryProductStateA("garbage");
373     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
374
375     /* guid without brackets */
376     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
377     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
378
379     /* guid with brackets */
380     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
381     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
382
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);
386
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);
390
391     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
392     lstrcatA(keypath, prod_squashed);
393
394     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
395     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
396
397     /* user product key exists */
398     state = MsiQueryProductStateA(prodcode);
399     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
400
401     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
402     lstrcatA(keypath, prodcode);
403
404     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
405     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
406
407     /* local uninstall key exists */
408     state = MsiQueryProductStateA(prodcode);
409     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
410
411     data = 1;
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);
414
415     /* WindowsInstaller value exists */
416     state = MsiQueryProductStateA(prodcode);
417     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
418
419     RegDeleteValueA(localkey, "WindowsInstaller");
420     RegDeleteKeyA(localkey, "");
421
422     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
423     lstrcatA(keypath, usersid);
424     lstrcatA(keypath, "\\Products\\");
425     lstrcatA(keypath, prod_squashed);
426
427     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
429
430     /* local product key exists */
431     state = MsiQueryProductStateA(prodcode);
432     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
433
434     res = RegCreateKeyA(localkey, "InstallProperties", &props);
435     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
436
437     /* install properties key exists */
438     state = MsiQueryProductStateA(prodcode);
439     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
440
441     data = 1;
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);
444
445     /* WindowsInstaller value exists */
446     state = MsiQueryProductStateA(prodcode);
447     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
448
449     data = 2;
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);
452
453     /* WindowsInstaller value is not 1 */
454     state = MsiQueryProductStateA(prodcode);
455     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
456
457     RegDeleteKeyA(userkey, "");
458
459     /* user product key does not exist */
460     state = MsiQueryProductStateA(prodcode);
461     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
462
463     LocalFree(usersid);
464     RegDeleteValueA(props, "WindowsInstaller");
465     RegDeleteKeyA(props, "");
466     RegDeleteKeyA(localkey, "");
467     RegCloseKey(userkey);
468     RegCloseKey(localkey);
469     RegCloseKey(props);
470 }
471
472 static const char table_enc85[] =
473 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
474 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
475 "yz{}~";
476
477 /*
478  *  Encodes a base85 guid given a GUID pointer
479  *  Caller should provide a 21 character buffer for the encoded string.
480  *
481  *  returns TRUE if successful, FALSE if not
482  */
483 static BOOL encode_base85_guid( GUID *guid, LPWSTR str )
484 {
485     unsigned int x, *p, i;
486
487     p = (unsigned int*) guid;
488     for( i=0; i<4; i++ )
489     {
490         x = p[i];
491         *str++ = table_enc85[x%85];
492         x = x/85;
493         *str++ = table_enc85[x%85];
494         x = x/85;
495         *str++ = table_enc85[x%85];
496         x = x/85;
497         *str++ = table_enc85[x%85];
498         x = x/85;
499         *str++ = table_enc85[x%85];
500     }
501     *str = 0;
502
503     return TRUE;
504 }
505
506 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
507 {
508     WCHAR guidW[MAX_PATH];
509     WCHAR base85W[MAX_PATH];
510     WCHAR squashedW[MAX_PATH];
511     GUID guid;
512     HRESULT hr;
513     int size;
514
515     hr = CoCreateGuid(&guid);
516     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
517
518     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
519     ok(size == 39, "Expected 39, got %d\n", hr);
520
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);
526 }
527
528 static void test_MsiQueryFeatureState(void)
529 {
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];
537     INSTALLSTATE state;
538     LPSTR usersid;
539     LONG res;
540
541     create_test_guid(prodcode, prod_squashed);
542     compose_base85_guid(component, comp_base85, comp_squashed);
543     get_user_sid(&usersid);
544
545     /* NULL prodcode */
546     state = MsiQueryFeatureStateA(NULL, "feature");
547     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
548
549     /* empty prodcode */
550     state = MsiQueryFeatureStateA("", "feature");
551     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
552
553     /* garbage prodcode */
554     state = MsiQueryFeatureStateA("garbage", "feature");
555     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
556
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);
560
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);
564
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);
568
569     /* NULL szFeature */
570     state = MsiQueryFeatureStateA(prodcode, NULL);
571     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
572
573     /* empty szFeature */
574     state = MsiQueryFeatureStateA(prodcode, "");
575     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
576
577     /* feature key does not exist yet */
578     state = MsiQueryFeatureStateA(prodcode, "feature");
579     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
580
581     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
582     lstrcatA(keypath, prod_squashed);
583
584     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
585     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
586
587     /* feature key exists */
588     state = MsiQueryFeatureStateA(prodcode, "feature");
589     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
590
591     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 8);
592     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
593
594     state = MsiQueryFeatureStateA(prodcode, "feature");
595     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
596
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");
602
603     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
604     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
605
606     state = MsiQueryFeatureStateA(prodcode, "feature");
607     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
608
609     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
610     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
611
612     state = MsiQueryFeatureStateA(prodcode, "feature");
613     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
614
615     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
617
618     state = MsiQueryFeatureStateA(prodcode, "feature");
619     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
620
621     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
622     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
623
624     state = MsiQueryFeatureStateA(prodcode, "feature");
625     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
626
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);
629
630     state = MsiQueryFeatureStateA(prodcode, "feature");
631     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
632
633     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
634     lstrcatA(keypath, usersid);
635     lstrcatA(keypath, "\\Components\\");
636     lstrcatA(keypath, comp_squashed);
637
638     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
639     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
640
641     state = MsiQueryFeatureStateA(prodcode, "feature");
642     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
643
644     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
645     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
646
647     state = MsiQueryFeatureStateA(prodcode, "feature");
648     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
649
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);
652
653     state = MsiQueryFeatureStateA(prodcode, "feature");
654     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
655
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);
664 }
665
666 static void test_MsiQueryComponentState(void)
667 {
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];
675     INSTALLSTATE state;
676     LPSTR usersid;
677     LONG res;
678     UINT r;
679
680     create_test_guid(prodcode, prod_squashed);
681     compose_base85_guid(component, comp_base85, comp_squashed);
682     get_user_sid(&usersid);
683
684     /* NULL szProductCode */
685     state = 0xdeadbeef;
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);
689
690     /* empty szProductCode */
691     state = 0xdeadbeef;
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);
695
696     /* random szProductCode */
697     state = 0xdeadbeef;
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);
701
702     /* GUID-length szProductCode */
703     state = 0xdeadbeef;
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);
707
708     /* GUID-length with brackets */
709     state = 0xdeadbeef;
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);
713
714     /* actual GUID */
715     state = 0xdeadbeef;
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);
719
720     state = 0xdeadbeef;
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);
724
725     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
726     lstrcatA(keypath, prod_squashed);
727
728     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
730
731     state = 0xdeadbeef;
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);
735
736     RegDeleteKeyA(prodkey, "");
737     RegCloseKey(prodkey);
738
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");
743
744     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
745     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
746
747     /* local system product key exists */
748     state = 0xdeadbeef;
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);
752
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);
755
756     /* LocalPackage value exists */
757     state = 0xdeadbeef;
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);
761
762     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
763     lstrcatA(keypath, comp_squashed);
764
765     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
767
768     /* component key exists */
769     state = 0xdeadbeef;
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);
773
774     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
775     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
776
777     /* component\product exists */
778     state = 0xdeadbeef;
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);
782
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);
785
786     state = 0xdeadbeef;
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);
790
791     RegDeleteValueA(prodkey, "LocalPackage");
792     RegDeleteKeyA(prodkey, "");
793     RegDeleteValueA(compkey, prod_squashed);
794     RegDeleteKeyA(prodkey, "");
795     RegCloseKey(prodkey);
796     RegCloseKey(compkey);
797
798     /* MSIINSTALLCONTEXT_USERUNMANAGED */
799
800     state = 0xdeadbeef;
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);
804
805     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
806     lstrcatA(keypath, prod_squashed);
807
808     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
810
811     state = 0xdeadbeef;
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);
815
816     RegDeleteKeyA(prodkey, "");
817     RegCloseKey(prodkey);
818
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");
824
825     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
826     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
827
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);
830
831     RegCloseKey(prodkey);
832
833     state = 0xdeadbeef;
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);
837
838     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
839     lstrcatA(keypath, usersid);
840     lstrcatA(keypath, "\\Components\\");
841     lstrcatA(keypath, comp_squashed);
842
843     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
844     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
845
846     /* component key exists */
847     state = 0xdeadbeef;
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);
851
852     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
854
855     /* component\product exists */
856     state = 0xdeadbeef;
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);
860
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);
863
864     state = 0xdeadbeef;
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);
868
869     /* MSIINSTALLCONTEXT_USERMANAGED */
870
871     state = 0xdeadbeef;
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);
875
876     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
877     lstrcatA(keypath, prod_squashed);
878
879     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
880     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
881
882     state = 0xdeadbeef;
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);
886
887     RegDeleteKeyA(prodkey, "");
888     RegCloseKey(prodkey);
889
890     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
891     lstrcatA(keypath, usersid);
892     lstrcatA(keypath, "\\Installer\\Products\\");
893     lstrcatA(keypath, prod_squashed);
894
895     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
896     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
897
898     state = 0xdeadbeef;
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);
902
903     RegDeleteKeyA(prodkey, "");
904     RegCloseKey(prodkey);
905
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");
911
912     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
914
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);
917
918     state = 0xdeadbeef;
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);
922
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);
930 }
931
932 START_TEST(msi)
933 {
934     init_functionpointers();
935
936     test_usefeature();
937     test_null();
938     test_getcomponentpath();
939     test_filehash();
940     test_MsiQueryProductState();
941     test_MsiQueryFeatureState();
942     test_MsiQueryComponentState();
943 }