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