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