msi: Reimplement MsiGetProductInfo.
[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 #define GET_PROC(dll, func) \
52     p ## func = (void *)GetProcAddress(dll, #func); \
53     if(!p ## func) \
54       trace("GetProcAddress(%s) failed\n", #func);
55
56     GET_PROC(hmsi, MsiGetComponentPathA)
57     GET_PROC(hmsi, MsiGetFileHashA)
58     GET_PROC(hmsi, MsiOpenPackageExA)
59     GET_PROC(hmsi, MsiOpenPackageExW)
60     GET_PROC(hmsi, MsiQueryComponentStateA)
61     GET_PROC(hmsi, MsiUseFeatureExA)
62
63     GET_PROC(hadvapi32, ConvertSidToStringSidA)
64
65 #undef GET_PROC
66 }
67
68 static void test_usefeature(void)
69 {
70     INSTALLSTATE r;
71
72     if (!pMsiUseFeatureExA)
73     {
74         skip("MsiUseFeatureExA not implemented\n");
75         return;
76     }
77
78     r = MsiQueryFeatureState(NULL,NULL);
79     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
80
81     r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
82     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
83
84     r = pMsiUseFeatureExA(NULL,NULL,0,0);
85     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
86
87     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
88     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
89
90     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
91                          NULL, -2, 0 );
92     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
93
94     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}", 
95                          "WORDVIEWFiles", -2, 0 );
96     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
97
98     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}", 
99                          "WORDVIEWFiles", -2, 0 );
100     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
101
102     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
103                          "WORDVIEWFiles", -2, 1 );
104     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
105 }
106
107 static void test_null(void)
108 {
109     MSIHANDLE hpkg;
110     UINT r;
111     HKEY hkey;
112     DWORD dwType, cbData;
113     LPBYTE lpData = NULL;
114     INSTALLSTATE state;
115
116     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
117     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
118
119     state = MsiQueryProductStateW(NULL);
120     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
121
122     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
123     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
124
125     r = MsiConfigureFeatureW(NULL, NULL, 0);
126     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
127
128     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
129     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
130
131     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", 0);
132     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
133
134     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", INSTALLSTATE_DEFAULT);
135     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
136
137     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
138      * necessary registry values */
139
140     /* empty product string */
141     r = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", &hkey);
142     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
143
144     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
145     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
146     if ( r == ERROR_SUCCESS )
147     {
148         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
149         if (!lpData)
150             skip("Out of memory\n");
151         else
152         {
153             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
154             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
155         }
156     }
157
158     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
159     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
160
161     r = MsiGetProductInfoA("", "", NULL, NULL);
162     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
163
164     if (lpData)
165     {
166         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
167         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
168
169         HeapFree(GetProcessHeap(), 0, lpData);
170     }
171     else
172     {
173         r = RegDeleteValueA(hkey, NULL);
174         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
175     }
176
177     r = RegCloseKey(hkey);
178     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
179
180     /* empty attribute */
181     r = RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", &hkey);
182     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
183
184     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
185     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
186
187     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
188     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
189
190     r = RegCloseKey(hkey);
191     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
192
193     r = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}");
194     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
195 }
196
197 static void test_getcomponentpath(void)
198 {
199     INSTALLSTATE r;
200     char buffer[0x100];
201     DWORD sz;
202
203     if(!pMsiGetComponentPathA)
204         return;
205
206     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
207     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
208
209     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
210     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
211
212     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
213     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
214
215     sz = sizeof buffer;
216     buffer[0]=0;
217     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
218     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
219
220     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
221         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
222     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
223
224     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
225         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
226     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
227
228     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
229         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
230     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
231
232     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
233                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
234     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
235 }
236
237 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
238 {
239     HANDLE file;
240     DWORD written;
241
242     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
243     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
244     WriteFile(file, data, strlen(data), &written, NULL);
245
246     if (size)
247     {
248         SetFilePointer(file, size, NULL, FILE_BEGIN);
249         SetEndOfFile(file);
250     }
251
252     CloseHandle(file);
253 }
254
255 #define HASHSIZE sizeof(MSIFILEHASHINFO)
256
257 static const struct
258 {
259     LPCSTR data;
260     DWORD size;
261     MSIFILEHASHINFO hash;
262 } hash_data[] =
263 {
264     { "abc", 0,
265       { HASHSIZE,
266         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
267       },
268     },
269
270     { "C:\\Program Files\\msitest\\caesar\n", 0,
271       { HASHSIZE,
272         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
273       },
274     },
275
276     { "C:\\Program Files\\msitest\\caesar\n", 500,
277       { HASHSIZE,
278         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
279       },
280     },
281 };
282
283 static void test_MsiGetFileHash(void)
284 {
285     const char name[] = "msitest.bin";
286     UINT r;
287     MSIFILEHASHINFO hash;
288     DWORD i;
289
290     if (!pMsiGetFileHashA)
291     {
292         skip("MsiGetFileHash not implemented\n");
293         return;
294     }
295
296     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
297
298     /* szFilePath is NULL */
299     r = pMsiGetFileHashA(NULL, 0, &hash);
300     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
301
302     /* szFilePath is empty */
303     r = pMsiGetFileHashA("", 0, &hash);
304     ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", r);
305
306     /* szFilePath is nonexistent */
307     r = pMsiGetFileHashA(name, 0, &hash);
308     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
309
310     /* dwOptions is non-zero */
311     r = pMsiGetFileHashA(name, 1, &hash);
312     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
313
314     /* pHash.dwFileHashInfoSize is not correct */
315     hash.dwFileHashInfoSize = 0;
316     r = pMsiGetFileHashA(name, 0, &hash);
317     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
318
319     /* pHash is NULL */
320     r = pMsiGetFileHashA(name, 0, NULL);
321     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
322
323     for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
324     {
325         create_file(name, hash_data[i].data, hash_data[i].size);
326
327         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
328         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
329
330         r = pMsiGetFileHashA(name, 0, &hash);
331         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
332         ok(!memcmp(&hash, &hash_data[i].hash, HASHSIZE), "Hash incorrect\n");
333
334         DeleteFile(name);
335     }
336 }
337
338 /* copied from dlls/msi/registry.c */
339 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
340 {
341     DWORD i,n=1;
342     GUID guid;
343
344     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
345         return FALSE;
346
347     for(i=0; i<8; i++)
348         out[7-i] = in[n++];
349     n++;
350     for(i=0; i<4; i++)
351         out[11-i] = in[n++];
352     n++;
353     for(i=0; i<4; i++)
354         out[15-i] = in[n++];
355     n++;
356     for(i=0; i<2; i++)
357     {
358         out[17+i*2] = in[n++];
359         out[16+i*2] = in[n++];
360     }
361     n++;
362     for( ; i<8; i++)
363     {
364         out[17+i*2] = in[n++];
365         out[16+i*2] = in[n++];
366     }
367     out[32]=0;
368     return TRUE;
369 }
370
371 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
372 {
373     WCHAR guidW[MAX_PATH];
374     WCHAR squashedW[MAX_PATH];
375     GUID guid;
376     HRESULT hr;
377     int size;
378
379     hr = CoCreateGuid(&guid);
380     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
381
382     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
383     ok(size == 39, "Expected 39, got %d\n", hr);
384
385     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
386     squash_guid(guidW, squashedW);
387     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
388 }
389
390 static void get_user_sid(LPSTR *usersid)
391 {
392     HANDLE token;
393     BYTE buf[1024];
394     DWORD size;
395     PTOKEN_USER user;
396
397     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
398     size = sizeof(buf);
399     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
400     user = (PTOKEN_USER)buf;
401     pConvertSidToStringSidA(user->User.Sid, usersid);
402 }
403
404 static void test_MsiQueryProductState(void)
405 {
406     CHAR prodcode[MAX_PATH];
407     CHAR prod_squashed[MAX_PATH];
408     CHAR keypath[MAX_PATH*2];
409     LPSTR usersid;
410     INSTALLSTATE state;
411     LONG res;
412     HKEY userkey, localkey, props;
413     DWORD data;
414
415     create_test_guid(prodcode, prod_squashed);
416     get_user_sid(&usersid);
417
418     /* NULL prodcode */
419     state = MsiQueryProductStateA(NULL);
420     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
421
422     /* empty prodcode */
423     state = MsiQueryProductStateA("");
424     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
425
426     /* garbage prodcode */
427     state = MsiQueryProductStateA("garbage");
428     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
429
430     /* guid without brackets */
431     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
432     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
433
434     /* guid with brackets */
435     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
436     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
437
438     /* same length as guid, but random */
439     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
440     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
441
442     /* created guid cannot possibly be an installed product code */
443     state = MsiQueryProductStateA(prodcode);
444     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
445
446     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
447     lstrcatA(keypath, prod_squashed);
448
449     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
451
452     /* user product key exists */
453     state = MsiQueryProductStateA(prodcode);
454     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
455
456     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
457     lstrcatA(keypath, prodcode);
458
459     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
460     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
461
462     /* local uninstall key exists */
463     state = MsiQueryProductStateA(prodcode);
464     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
465
466     data = 1;
467     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
469
470     /* WindowsInstaller value exists */
471     state = MsiQueryProductStateA(prodcode);
472     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
473
474     RegDeleteValueA(localkey, "WindowsInstaller");
475     RegDeleteKeyA(localkey, "");
476
477     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
478     lstrcatA(keypath, usersid);
479     lstrcatA(keypath, "\\Products\\");
480     lstrcatA(keypath, prod_squashed);
481
482     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
483     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
484
485     /* local product key exists */
486     state = MsiQueryProductStateA(prodcode);
487     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
488
489     res = RegCreateKeyA(localkey, "InstallProperties", &props);
490     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
491
492     /* install properties key exists */
493     state = MsiQueryProductStateA(prodcode);
494     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
495
496     data = 1;
497     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
498     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
499
500     /* WindowsInstaller value exists */
501     state = MsiQueryProductStateA(prodcode);
502     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
503
504     data = 2;
505     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
506     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
507
508     /* WindowsInstaller value is not 1 */
509     state = MsiQueryProductStateA(prodcode);
510     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
511
512     RegDeleteKeyA(userkey, "");
513
514     /* user product key does not exist */
515     state = MsiQueryProductStateA(prodcode);
516     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
517
518     LocalFree(usersid);
519     RegDeleteValueA(props, "WindowsInstaller");
520     RegDeleteKeyA(props, "");
521     RegDeleteKeyA(localkey, "");
522     RegCloseKey(userkey);
523     RegCloseKey(localkey);
524     RegCloseKey(props);
525 }
526
527 static const char table_enc85[] =
528 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
529 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
530 "yz{}~";
531
532 /*
533  *  Encodes a base85 guid given a GUID pointer
534  *  Caller should provide a 21 character buffer for the encoded string.
535  *
536  *  returns TRUE if successful, FALSE if not
537  */
538 static BOOL encode_base85_guid( GUID *guid, LPWSTR str )
539 {
540     unsigned int x, *p, i;
541
542     p = (unsigned int*) guid;
543     for( i=0; i<4; i++ )
544     {
545         x = p[i];
546         *str++ = table_enc85[x%85];
547         x = x/85;
548         *str++ = table_enc85[x%85];
549         x = x/85;
550         *str++ = table_enc85[x%85];
551         x = x/85;
552         *str++ = table_enc85[x%85];
553         x = x/85;
554         *str++ = table_enc85[x%85];
555     }
556     *str = 0;
557
558     return TRUE;
559 }
560
561 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
562 {
563     WCHAR guidW[MAX_PATH];
564     WCHAR base85W[MAX_PATH];
565     WCHAR squashedW[MAX_PATH];
566     GUID guid;
567     HRESULT hr;
568     int size;
569
570     hr = CoCreateGuid(&guid);
571     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
572
573     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
574     ok(size == 39, "Expected 39, got %d\n", hr);
575
576     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
577     encode_base85_guid(&guid, base85W);
578     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
579     squash_guid(guidW, squashedW);
580     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
581 }
582
583 static void test_MsiQueryFeatureState(void)
584 {
585     HKEY userkey, localkey, compkey;
586     CHAR prodcode[MAX_PATH];
587     CHAR prod_squashed[MAX_PATH];
588     CHAR component[MAX_PATH];
589     CHAR comp_base85[MAX_PATH];
590     CHAR comp_squashed[MAX_PATH];
591     CHAR keypath[MAX_PATH*2];
592     INSTALLSTATE state;
593     LPSTR usersid;
594     LONG res;
595
596     create_test_guid(prodcode, prod_squashed);
597     compose_base85_guid(component, comp_base85, comp_squashed);
598     get_user_sid(&usersid);
599
600     /* NULL prodcode */
601     state = MsiQueryFeatureStateA(NULL, "feature");
602     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
603
604     /* empty prodcode */
605     state = MsiQueryFeatureStateA("", "feature");
606     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
607
608     /* garbage prodcode */
609     state = MsiQueryFeatureStateA("garbage", "feature");
610     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
611
612     /* guid without brackets */
613     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
614     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
615
616     /* guid with brackets */
617     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
618     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
619
620     /* same length as guid, but random */
621     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
622     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
623
624     /* NULL szFeature */
625     state = MsiQueryFeatureStateA(prodcode, NULL);
626     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
627
628     /* empty szFeature */
629     state = MsiQueryFeatureStateA(prodcode, "");
630     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
631
632     /* feature key does not exist yet */
633     state = MsiQueryFeatureStateA(prodcode, "feature");
634     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
635
636     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
637     lstrcatA(keypath, prod_squashed);
638
639     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
640     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
641
642     /* feature key exists */
643     state = MsiQueryFeatureStateA(prodcode, "feature");
644     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
645
646     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 8);
647     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
648
649     state = MsiQueryFeatureStateA(prodcode, "feature");
650     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
651
652     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
653     lstrcatA(keypath, usersid);
654     lstrcatA(keypath, "\\Products\\");
655     lstrcatA(keypath, prod_squashed);
656     lstrcatA(keypath, "\\Features");
657
658     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
659     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
660
661     state = MsiQueryFeatureStateA(prodcode, "feature");
662     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
663
664     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
665     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
666
667     state = MsiQueryFeatureStateA(prodcode, "feature");
668     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
669
670     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
671     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
672
673     state = MsiQueryFeatureStateA(prodcode, "feature");
674     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
675
676     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
677     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
678
679     state = MsiQueryFeatureStateA(prodcode, "feature");
680     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
681
682     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21);
683     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
684
685     state = MsiQueryFeatureStateA(prodcode, "feature");
686     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
687
688     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
689     lstrcatA(keypath, usersid);
690     lstrcatA(keypath, "\\Components\\");
691     lstrcatA(keypath, comp_squashed);
692
693     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
694     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
695
696     state = MsiQueryFeatureStateA(prodcode, "feature");
697     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
698
699     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
700     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
701
702     state = MsiQueryFeatureStateA(prodcode, "feature");
703     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
704
705     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1);
706     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
707
708     state = MsiQueryFeatureStateA(prodcode, "feature");
709     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
710
711     RegDeleteValueA(compkey, prod_squashed);
712     RegDeleteValueA(compkey, "");
713     RegDeleteValueA(localkey, "feature");
714     RegDeleteValueA(userkey, "feature");
715     RegDeleteKeyA(userkey, "");
716     RegCloseKey(compkey);
717     RegCloseKey(localkey);
718     RegCloseKey(userkey);
719 }
720
721 static void test_MsiQueryComponentState(void)
722 {
723     HKEY compkey, prodkey;
724     CHAR prodcode[MAX_PATH];
725     CHAR prod_squashed[MAX_PATH];
726     CHAR component[MAX_PATH];
727     CHAR comp_base85[MAX_PATH];
728     CHAR comp_squashed[MAX_PATH];
729     CHAR keypath[MAX_PATH];
730     INSTALLSTATE state;
731     LPSTR usersid;
732     LONG res;
733     UINT r;
734
735     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
736
737     if (!pMsiQueryComponentStateA)
738     {
739         skip("MsiQueryComponentStateA not implemented\n");
740         return;
741     }
742
743     create_test_guid(prodcode, prod_squashed);
744     compose_base85_guid(component, comp_base85, comp_squashed);
745     get_user_sid(&usersid);
746
747     /* NULL szProductCode */
748     state = MAGIC_ERROR;
749     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
750     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
751     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
752
753     /* empty szProductCode */
754     state = MAGIC_ERROR;
755     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
756     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
757     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
758
759     /* random szProductCode */
760     state = MAGIC_ERROR;
761     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
762     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
763     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
764
765     /* GUID-length szProductCode */
766     state = MAGIC_ERROR;
767     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
768     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
769     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
770
771     /* GUID-length with brackets */
772     state = MAGIC_ERROR;
773     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
774     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
775     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
776
777     /* actual GUID */
778     state = MAGIC_ERROR;
779     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
780     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
781     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
782
783     state = MAGIC_ERROR;
784     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
785     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
786     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
787
788     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
789     lstrcatA(keypath, prod_squashed);
790
791     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
792     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
793
794     state = MAGIC_ERROR;
795     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
796     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
797     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
798
799     RegDeleteKeyA(prodkey, "");
800     RegCloseKey(prodkey);
801
802     /* create local system product key */
803     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
804     lstrcatA(keypath, prod_squashed);
805     lstrcatA(keypath, "\\InstallProperties");
806
807     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
808     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
809
810     /* local system product key exists */
811     state = MAGIC_ERROR;
812     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
813     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
814     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
815
816     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
818
819     /* LocalPackage value exists */
820     state = MAGIC_ERROR;
821     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
822     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
823     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
824
825     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
826     lstrcatA(keypath, comp_squashed);
827
828     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
829     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
830
831     /* component key exists */
832     state = MAGIC_ERROR;
833     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
834     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
835     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
836
837     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
838     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
839
840     /* component\product exists */
841     state = MAGIC_ERROR;
842     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
844     ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
845
846     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
847     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
848
849     state = MAGIC_ERROR;
850     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
852     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
853
854     RegDeleteValueA(prodkey, "LocalPackage");
855     RegDeleteKeyA(prodkey, "");
856     RegDeleteValueA(compkey, prod_squashed);
857     RegDeleteKeyA(prodkey, "");
858     RegCloseKey(prodkey);
859     RegCloseKey(compkey);
860
861     /* MSIINSTALLCONTEXT_USERUNMANAGED */
862
863     state = MAGIC_ERROR;
864     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
865     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
866     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
867
868     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
869     lstrcatA(keypath, prod_squashed);
870
871     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
873
874     state = MAGIC_ERROR;
875     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
876     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
877     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
878
879     RegDeleteKeyA(prodkey, "");
880     RegCloseKey(prodkey);
881
882     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
883     lstrcatA(keypath, usersid);
884     lstrcatA(keypath, "\\Products\\");
885     lstrcatA(keypath, prod_squashed);
886     lstrcatA(keypath, "\\InstallProperties");
887
888     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
889     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
890
891     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
892     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
893
894     RegCloseKey(prodkey);
895
896     state = MAGIC_ERROR;
897     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
898     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
899     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
900
901     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
902     lstrcatA(keypath, usersid);
903     lstrcatA(keypath, "\\Components\\");
904     lstrcatA(keypath, comp_squashed);
905
906     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
907     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
908
909     /* component key exists */
910     state = MAGIC_ERROR;
911     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
912     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
913     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
914
915     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
916     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
917
918     /* component\product exists */
919     state = MAGIC_ERROR;
920     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
922     ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
923
924     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
925     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
926
927     state = MAGIC_ERROR;
928     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
930     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
931
932     /* MSIINSTALLCONTEXT_USERMANAGED */
933
934     state = MAGIC_ERROR;
935     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
936     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
937     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
938
939     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
940     lstrcatA(keypath, prod_squashed);
941
942     res = RegCreateKeyA(HKEY_CURRENT_USER, 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_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
948     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
949
950     RegDeleteKeyA(prodkey, "");
951     RegCloseKey(prodkey);
952
953     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
954     lstrcatA(keypath, usersid);
955     lstrcatA(keypath, "\\Installer\\Products\\");
956     lstrcatA(keypath, prod_squashed);
957
958     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
959     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
960
961     state = MAGIC_ERROR;
962     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
963     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
964     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
965
966     RegDeleteKeyA(prodkey, "");
967     RegCloseKey(prodkey);
968
969     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
970     lstrcatA(keypath, usersid);
971     lstrcatA(keypath, "\\Products\\");
972     lstrcatA(keypath, prod_squashed);
973     lstrcatA(keypath, "\\InstallProperties");
974
975     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
977
978     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
979     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
980
981     state = MAGIC_ERROR;
982     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
984     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
985
986     RegDeleteValueA(prodkey, "LocalPackage");
987     RegDeleteValueA(prodkey, "ManagedLocalPackage");
988     RegDeleteKeyA(prodkey, "");
989     RegDeleteValueA(compkey, prod_squashed);
990     RegDeleteKeyA(compkey, "");
991     RegCloseKey(prodkey);
992     RegCloseKey(compkey);
993 }
994
995 static void test_MsiGetComponentPath(void)
996 {
997     HKEY compkey, prodkey, installprop;
998     CHAR prodcode[MAX_PATH];
999     CHAR prod_squashed[MAX_PATH];
1000     CHAR component[MAX_PATH];
1001     CHAR comp_base85[MAX_PATH];
1002     CHAR comp_squashed[MAX_PATH];
1003     CHAR keypath[MAX_PATH];
1004     CHAR path[MAX_PATH];
1005     INSTALLSTATE state;
1006     LPSTR usersid;
1007     DWORD size, val;
1008     LONG res;
1009
1010     create_test_guid(prodcode, prod_squashed);
1011     compose_base85_guid(component, comp_base85, comp_squashed);
1012     get_user_sid(&usersid);
1013
1014     /* NULL szProduct */
1015     size = MAX_PATH;
1016     state = MsiGetComponentPathA(NULL, component, path, &size);
1017     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1018     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1019
1020     /* NULL szComponent */
1021     size = MAX_PATH;
1022     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
1023     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1024     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1025
1026     /* NULL lpPathBuf */
1027     size = MAX_PATH;
1028     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
1029     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1030     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1031
1032     /* NULL pcchBuf */
1033     size = MAX_PATH;
1034     state = MsiGetComponentPathA(prodcode, component, path, NULL);
1035     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1036     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1037
1038     /* all params valid */
1039     size = MAX_PATH;
1040     state = MsiGetComponentPathA(prodcode, component, path, &size);
1041     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1042     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1043
1044     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1045     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1046     lstrcatA(keypath, comp_squashed);
1047
1048     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1049     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1050
1051     /* local system component key exists */
1052     size = MAX_PATH;
1053     state = MsiGetComponentPathA(prodcode, component, path, &size);
1054     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1055     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1056
1057     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1058     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1059
1060     /* product value exists */
1061     size = MAX_PATH;
1062     state = MsiGetComponentPathA(prodcode, component, path, &size);
1063     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1064     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1065     ok(size == 10, "Expected 10, got %d\n", size);
1066
1067     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1068     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
1069     lstrcatA(keypath, prod_squashed);
1070     lstrcatA(keypath, "\\InstallProperties");
1071
1072     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &installprop);
1073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1074
1075     val = 1;
1076     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
1077     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1078
1079     /* install properties key exists */
1080     size = MAX_PATH;
1081     state = MsiGetComponentPathA(prodcode, component, path, &size);
1082     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1083     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1084     ok(size == 10, "Expected 10, got %d\n", size);
1085
1086     create_file("C:\\imapath", "C:\\imapath", 11);
1087
1088     /* file exists */
1089     size = MAX_PATH;
1090     state = MsiGetComponentPathA(prodcode, component, path, &size);
1091     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1092     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1093     ok(size == 10, "Expected 10, got %d\n", size);
1094
1095     RegDeleteValueA(compkey, prod_squashed);
1096     RegDeleteKeyA(compkey, "");
1097     RegDeleteValueA(installprop, "WindowsInstaller");
1098     RegDeleteKeyA(installprop, "");
1099     RegCloseKey(compkey);
1100     RegCloseKey(installprop);
1101     DeleteFileA("C:\\imapath");
1102
1103     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1104     lstrcatA(keypath, "Installer\\UserData\\");
1105     lstrcatA(keypath, usersid);
1106     lstrcatA(keypath, "\\Components\\");
1107     lstrcatA(keypath, comp_squashed);
1108
1109     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1110     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1111
1112     /* user managed component key exists */
1113     size = MAX_PATH;
1114     state = MsiGetComponentPathA(prodcode, component, path, &size);
1115     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1116     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1117
1118     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1119     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1120
1121     /* product value exists */
1122     size = MAX_PATH;
1123     state = MsiGetComponentPathA(prodcode, component, path, &size);
1124     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1125     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1126     ok(size == 10, "Expected 10, got %d\n", size);
1127
1128     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1129     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
1130     lstrcatA(keypath, prod_squashed);
1131     lstrcatA(keypath, "\\InstallProperties");
1132
1133     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &installprop);
1134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1135
1136     val = 1;
1137     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
1138     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1139
1140     /* install properties key exists */
1141     size = MAX_PATH;
1142     state = MsiGetComponentPathA(prodcode, component, path, &size);
1143     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1144     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1145     ok(size == 10, "Expected 10, got %d\n", size);
1146
1147     create_file("C:\\imapath", "C:\\imapath", 11);
1148
1149     /* file exists */
1150     size = MAX_PATH;
1151     state = MsiGetComponentPathA(prodcode, component, path, &size);
1152     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1153     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1154     ok(size == 10, "Expected 10, got %d\n", size);
1155
1156     RegDeleteValueA(compkey, prod_squashed);
1157     RegDeleteKeyA(compkey, "");
1158     RegDeleteValueA(installprop, "WindowsInstaller");
1159     RegDeleteKeyA(installprop, "");
1160     RegCloseKey(compkey);
1161     RegCloseKey(installprop);
1162     DeleteFileA("C:\\imapath");
1163
1164     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1165     lstrcatA(keypath, "Installer\\Managed\\");
1166     lstrcatA(keypath, usersid);
1167     lstrcatA(keypath, "\\Installer\\Products\\");
1168     lstrcatA(keypath, prod_squashed);
1169
1170     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1171     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1172
1173     /* user managed product key exists */
1174     size = MAX_PATH;
1175     state = MsiGetComponentPathA(prodcode, component, path, &size);
1176     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1177     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1178
1179     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1180     lstrcatA(keypath, "Installer\\UserData\\");
1181     lstrcatA(keypath, usersid);
1182     lstrcatA(keypath, "\\Components\\");
1183     lstrcatA(keypath, comp_squashed);
1184
1185     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1186     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1187
1188     /* user managed component key exists */
1189     size = MAX_PATH;
1190     state = MsiGetComponentPathA(prodcode, component, path, &size);
1191     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1192     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1193
1194     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1195     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1196
1197     /* product value exists */
1198     size = MAX_PATH;
1199     state = MsiGetComponentPathA(prodcode, component, path, &size);
1200     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1201     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1202     ok(size == 10, "Expected 10, got %d\n", size);
1203
1204     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1205     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
1206     lstrcatA(keypath, prod_squashed);
1207     lstrcatA(keypath, "\\InstallProperties");
1208
1209     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &installprop);
1210     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1211
1212     val = 1;
1213     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
1214     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1215
1216     /* install properties key exists */
1217     size = MAX_PATH;
1218     state = MsiGetComponentPathA(prodcode, component, path, &size);
1219     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1220     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1221     ok(size == 10, "Expected 10, got %d\n", size);
1222
1223     create_file("C:\\imapath", "C:\\imapath", 11);
1224
1225     /* file exists */
1226     size = MAX_PATH;
1227     state = MsiGetComponentPathA(prodcode, component, path, &size);
1228     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1229     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1230     ok(size == 10, "Expected 10, got %d\n", size);
1231
1232     RegDeleteValueA(compkey, prod_squashed);
1233     RegDeleteKeyA(prodkey, "");
1234     RegDeleteKeyA(compkey, "");
1235     RegDeleteValueA(installprop, "WindowsInstaller");
1236     RegDeleteKeyA(installprop, "");
1237     RegCloseKey(prodkey);
1238     RegCloseKey(compkey);
1239     RegCloseKey(installprop);
1240     DeleteFileA("C:\\imapath");
1241
1242     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1243     lstrcatA(keypath, prod_squashed);
1244
1245     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
1246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1247
1248     /* user unmanaged product key exists */
1249     size = MAX_PATH;
1250     state = MsiGetComponentPathA(prodcode, component, path, &size);
1251     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1252     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1253
1254     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1255     lstrcatA(keypath, "Installer\\UserData\\");
1256     lstrcatA(keypath, usersid);
1257     lstrcatA(keypath, "\\Components\\");
1258     lstrcatA(keypath, comp_squashed);
1259
1260     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1261     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1262
1263     /* user unmanaged component key exists */
1264     size = MAX_PATH;
1265     state = MsiGetComponentPathA(prodcode, component, path, &size);
1266     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1267     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1268
1269     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1270     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1271
1272     /* product value exists */
1273     size = MAX_PATH;
1274     state = MsiGetComponentPathA(prodcode, component, path, &size);
1275     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1276     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1277     ok(size == 10, "Expected 10, got %d\n", size);
1278
1279     create_file("C:\\imapath", "C:\\imapath", 11);
1280
1281     /* file exists */
1282     size = MAX_PATH;
1283     state = MsiGetComponentPathA(prodcode, component, path, &size);
1284     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1285     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1286     ok(size == 10, "Expected 10, got %d\n", size);
1287
1288     RegDeleteValueA(compkey, prod_squashed);
1289     RegDeleteKeyA(prodkey, "");
1290     RegDeleteKeyA(compkey, "");
1291     RegCloseKey(prodkey);
1292     RegCloseKey(compkey);
1293     RegCloseKey(installprop);
1294     DeleteFileA("C:\\imapath");
1295
1296     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1297     lstrcatA(keypath, prod_squashed);
1298
1299     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1300     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1301
1302     /* local classes product key exists */
1303     size = MAX_PATH;
1304     state = MsiGetComponentPathA(prodcode, component, path, &size);
1305     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1306     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1307
1308     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1309     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1310     lstrcatA(keypath, comp_squashed);
1311
1312     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1313     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1314
1315     /* local user component key exists */
1316     size = MAX_PATH;
1317     state = MsiGetComponentPathA(prodcode, component, path, &size);
1318     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1319     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1320
1321     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1322     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1323
1324     /* product value exists */
1325     size = MAX_PATH;
1326     state = MsiGetComponentPathA(prodcode, component, path, &size);
1327     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1328     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1329     ok(size == 10, "Expected 10, got %d\n", size);
1330
1331     create_file("C:\\imapath", "C:\\imapath", 11);
1332
1333     /* file exists */
1334     size = MAX_PATH;
1335     state = MsiGetComponentPathA(prodcode, component, path, &size);
1336     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1337     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1338     ok(size == 10, "Expected 10, got %d\n", size);
1339
1340     RegDeleteValueA(compkey, prod_squashed);
1341     RegDeleteKeyA(prodkey, "");
1342     RegDeleteKeyA(compkey, "");
1343     RegCloseKey(prodkey);
1344     RegCloseKey(compkey);
1345     DeleteFileA("C:\\imapath");
1346 }
1347
1348 static void test_MsiGetProductCode(void)
1349 {
1350     HKEY compkey, prodkey;
1351     CHAR prodcode[MAX_PATH];
1352     CHAR prod_squashed[MAX_PATH];
1353     CHAR prodcode2[MAX_PATH];
1354     CHAR prod2_squashed[MAX_PATH];
1355     CHAR component[MAX_PATH];
1356     CHAR comp_base85[MAX_PATH];
1357     CHAR comp_squashed[MAX_PATH];
1358     CHAR keypath[MAX_PATH];
1359     CHAR product[MAX_PATH];
1360     LPSTR usersid;
1361     LONG res;
1362     UINT r;
1363
1364     create_test_guid(prodcode, prod_squashed);
1365     create_test_guid(prodcode2, prod2_squashed);
1366     compose_base85_guid(component, comp_base85, comp_squashed);
1367     get_user_sid(&usersid);
1368
1369     /* szComponent is NULL */
1370     lstrcpyA(product, "prod");
1371     r = MsiGetProductCodeA(NULL, product);
1372     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1373     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1374
1375     /* szComponent is empty */
1376     lstrcpyA(product, "prod");
1377     r = MsiGetProductCodeA("", product);
1378     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1379     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1380
1381     /* garbage szComponent */
1382     lstrcpyA(product, "prod");
1383     r = MsiGetProductCodeA("garbage", product);
1384     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1385     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1386
1387     /* guid without brackets */
1388     lstrcpyA(product, "prod");
1389     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
1390     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1391     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1392
1393     /* guid with brackets */
1394     lstrcpyA(product, "prod");
1395     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
1396     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1397     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1398
1399     /* same length as guid, but random */
1400     lstrcpyA(product, "prod");
1401     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
1402     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1403     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1404
1405     /* all params correct, szComponent not published */
1406     lstrcpyA(product, "prod");
1407     r = MsiGetProductCodeA(component, product);
1408     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1409     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1410
1411     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1412     lstrcatA(keypath, "Installer\\UserData\\");
1413     lstrcatA(keypath, usersid);
1414     lstrcatA(keypath, "\\Components\\");
1415     lstrcatA(keypath, comp_squashed);
1416
1417     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1418     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1419
1420     /* user unmanaged component key exists */
1421     lstrcpyA(product, "prod");
1422     r = MsiGetProductCodeA(component, product);
1423     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1424     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1425
1426     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1428
1429     /* product value exists */
1430     lstrcpyA(product, "prod");
1431     r = MsiGetProductCodeA(component, product);
1432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1433     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1434
1435     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1436     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1437
1438     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1439     lstrcatA(keypath, "Installer\\Managed\\");
1440     lstrcatA(keypath, usersid);
1441     lstrcatA(keypath, "\\Installer\\Products\\");
1442     lstrcatA(keypath, prod_squashed);
1443
1444     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1445     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1446
1447     /* user managed product key of first product exists */
1448     lstrcpyA(product, "prod");
1449     r = MsiGetProductCodeA(component, product);
1450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1451     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1452
1453     RegDeleteKeyA(prodkey, "");
1454     RegCloseKey(prodkey);
1455
1456     RegDeleteKeyA(prodkey, "");
1457     RegCloseKey(prodkey);
1458
1459     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1460     lstrcatA(keypath, prod_squashed);
1461
1462     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
1463     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1464
1465     /* user unmanaged product key exists */
1466     lstrcpyA(product, "prod");
1467     r = MsiGetProductCodeA(component, product);
1468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1469     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1470
1471     RegDeleteKeyA(prodkey, "");
1472     RegCloseKey(prodkey);
1473
1474     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1475     lstrcatA(keypath, prod_squashed);
1476
1477     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1478     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1479
1480     /* local classes product key exists */
1481     lstrcpyA(product, "prod");
1482     r = MsiGetProductCodeA(component, product);
1483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1484     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1485
1486     RegDeleteKeyA(prodkey, "");
1487     RegCloseKey(prodkey);
1488
1489     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1490     lstrcatA(keypath, "Installer\\Managed\\");
1491     lstrcatA(keypath, usersid);
1492     lstrcatA(keypath, "\\Installer\\Products\\");
1493     lstrcatA(keypath, prod2_squashed);
1494
1495     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1496     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1497
1498     /* user managed product key of second product exists */
1499     lstrcpyA(product, "prod");
1500     r = MsiGetProductCodeA(component, product);
1501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1502     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
1503
1504     RegDeleteKeyA(prodkey, "");
1505     RegCloseKey(prodkey);
1506     RegDeleteValueA(compkey, prod_squashed);
1507     RegDeleteValueA(compkey, prod2_squashed);
1508     RegDeleteKeyA(compkey, "");
1509     RegCloseKey(compkey);
1510
1511     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1512     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1513     lstrcatA(keypath, comp_squashed);
1514
1515     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1517
1518     /* local user component key exists */
1519     lstrcpyA(product, "prod");
1520     r = MsiGetProductCodeA(component, product);
1521     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1522     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1523
1524     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1526
1527     /* product value exists */
1528     lstrcpyA(product, "prod");
1529     r = MsiGetProductCodeA(component, product);
1530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1531     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1532
1533     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1534     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1535
1536     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1537     lstrcatA(keypath, "Installer\\Managed\\");
1538     lstrcatA(keypath, usersid);
1539     lstrcatA(keypath, "\\Installer\\Products\\");
1540     lstrcatA(keypath, prod_squashed);
1541
1542     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1543     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1544
1545     /* user managed product key of first product exists */
1546     lstrcpyA(product, "prod");
1547     r = MsiGetProductCodeA(component, product);
1548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1549     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1550
1551     RegDeleteKeyA(prodkey, "");
1552     RegCloseKey(prodkey);
1553
1554     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1555     lstrcatA(keypath, prod_squashed);
1556
1557     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
1558     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1559
1560     /* user unmanaged product key exists */
1561     lstrcpyA(product, "prod");
1562     r = MsiGetProductCodeA(component, product);
1563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1564     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1565
1566     RegDeleteKeyA(prodkey, "");
1567     RegCloseKey(prodkey);
1568
1569     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1570     lstrcatA(keypath, prod_squashed);
1571
1572     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1573     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1574
1575     /* local classes product key exists */
1576     lstrcpyA(product, "prod");
1577     r = MsiGetProductCodeA(component, product);
1578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1579     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1580
1581     RegDeleteKeyA(prodkey, "");
1582     RegCloseKey(prodkey);
1583
1584     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1585     lstrcatA(keypath, "Installer\\Managed\\");
1586     lstrcatA(keypath, usersid);
1587     lstrcatA(keypath, "\\Installer\\Products\\");
1588     lstrcatA(keypath, prod2_squashed);
1589
1590     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1591     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1592
1593     /* user managed product key of second product exists */
1594     lstrcpyA(product, "prod");
1595     r = MsiGetProductCodeA(component, product);
1596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1597     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
1598
1599     RegDeleteKeyA(prodkey, "");
1600     RegCloseKey(prodkey);
1601     RegDeleteValueA(compkey, prod_squashed);
1602     RegDeleteValueA(compkey, prod2_squashed);
1603     RegDeleteKeyA(compkey, "");
1604     RegCloseKey(compkey);
1605 }
1606
1607 static void test_MsiEnumClients(void)
1608 {
1609     HKEY compkey;
1610     CHAR prodcode[MAX_PATH];
1611     CHAR prod_squashed[MAX_PATH];
1612     CHAR prodcode2[MAX_PATH];
1613     CHAR prod2_squashed[MAX_PATH];
1614     CHAR component[MAX_PATH];
1615     CHAR comp_base85[MAX_PATH];
1616     CHAR comp_squashed[MAX_PATH];
1617     CHAR product[MAX_PATH];
1618     CHAR keypath[MAX_PATH];
1619     LPSTR usersid;
1620     LONG res;
1621     UINT r;
1622
1623     create_test_guid(prodcode, prod_squashed);
1624     create_test_guid(prodcode2, prod2_squashed);
1625     compose_base85_guid(component, comp_base85, comp_squashed);
1626     get_user_sid(&usersid);
1627
1628     /* NULL szComponent */
1629     product[0] = '\0';
1630     r = MsiEnumClientsA(NULL, 0, product);
1631     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1632     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1633
1634     /* empty szComponent */
1635     product[0] = '\0';
1636     r = MsiEnumClientsA("", 0, product);
1637     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1638     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1639
1640     /* NULL lpProductBuf */
1641     r = MsiEnumClientsA(component, 0, NULL);
1642     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1643
1644     /* all params correct, component missing */
1645     product[0] = '\0';
1646     r = MsiEnumClientsA(component, 0, product);
1647     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1648     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1649
1650     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1651     lstrcatA(keypath, "Installer\\UserData\\");
1652     lstrcatA(keypath, usersid);
1653     lstrcatA(keypath, "\\Components\\");
1654     lstrcatA(keypath, comp_squashed);
1655
1656     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1657     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1658
1659     /* user unmanaged component key exists */
1660     product[0] = '\0';
1661     r = MsiEnumClientsA(component, 0, product);
1662     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1663     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1664
1665     /* index > 0, no products exist */
1666     product[0] = '\0';
1667     r = MsiEnumClientsA(component, 1, product);
1668     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1669     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1670
1671     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1672     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1673
1674     /* product value exists */
1675     r = MsiEnumClientsA(component, 0, product);
1676     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1677     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1678
1679     /* try index 0 again */
1680     product[0] = '\0';
1681     r = MsiEnumClientsA(component, 0, product);
1682     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1683     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1684
1685     /* try index 1, second product value does not exist */
1686     product[0] = '\0';
1687     r = MsiEnumClientsA(component, 1, product);
1688     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1689     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1690
1691     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1692     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1693
1694     /* try index 1, second product value does exist */
1695     product[0] = '\0';
1696     r = MsiEnumClientsA(component, 1, product);
1697     todo_wine
1698     {
1699         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1700         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1701     }
1702
1703     /* start the enumeration over */
1704     product[0] = '\0';
1705     r = MsiEnumClientsA(component, 0, product);
1706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1707     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1708        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1709
1710     /* correctly query second product */
1711     product[0] = '\0';
1712     r = MsiEnumClientsA(component, 1, product);
1713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1714     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1715        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1716
1717     RegDeleteValueA(compkey, prod_squashed);
1718     RegDeleteValueA(compkey, prod2_squashed);
1719     RegDeleteKeyA(compkey, "");
1720     RegCloseKey(compkey);
1721
1722     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1723     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1724     lstrcatA(keypath, comp_squashed);
1725
1726     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1727     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1728
1729     /* user local component key exists */
1730     product[0] = '\0';
1731     r = MsiEnumClientsA(component, 0, product);
1732     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1733     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1734
1735     /* index > 0, no products exist */
1736     product[0] = '\0';
1737     r = MsiEnumClientsA(component, 1, product);
1738     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1739     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1740
1741     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1743
1744     /* product value exists */
1745     product[0] = '\0';
1746     r = MsiEnumClientsA(component, 0, product);
1747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1748     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1749
1750     /* try index 0 again */
1751     product[0] = '\0';
1752     r = MsiEnumClientsA(component, 0, product);
1753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1754
1755     /* try index 1, second product value does not exist */
1756     product[0] = '\0';
1757     r = MsiEnumClientsA(component, 1, product);
1758     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1759     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1760
1761     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1762     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1763
1764     /* try index 1, second product value does exist */
1765     product[0] = '\0';
1766     r = MsiEnumClientsA(component, 1, product);
1767     todo_wine
1768     {
1769         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1770         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1771     }
1772
1773     /* start the enumeration over */
1774     product[0] = '\0';
1775     r = MsiEnumClientsA(component, 0, product);
1776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1777     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1778        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1779
1780     /* correctly query second product */
1781     product[0] = '\0';
1782     r = MsiEnumClientsA(component, 1, product);
1783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1784     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1785        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1786
1787     RegDeleteValueA(compkey, prod_squashed);
1788     RegDeleteValueA(compkey, prod2_squashed);
1789     RegDeleteKeyA(compkey, "");
1790     RegCloseKey(compkey);
1791 }
1792
1793 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
1794                              LPSTR *langcheck, LPDWORD langchecksz)
1795 {
1796     LPSTR version;
1797     VS_FIXEDFILEINFO *ffi;
1798     DWORD size = GetFileVersionInfoSizeA(path, NULL);
1799     USHORT *lang;
1800
1801     version = HeapAlloc(GetProcessHeap(), 0, size);
1802     GetFileVersionInfoA(path, 0, size, version);
1803
1804     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size);
1805     *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1806     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
1807             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
1808             LOWORD(ffi->dwFileVersionLS));
1809     *verchecksz = lstrlenA(*vercheck);
1810
1811     VerQueryValue(version, "\\VarFileInfo\\Translation", (void **)&lang, &size);
1812     *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1813     sprintf(*langcheck, "%d", *lang);
1814     *langchecksz = lstrlenA(*langcheck);
1815
1816     HeapFree(GetProcessHeap(), 0, version);
1817 }
1818
1819 static void test_MsiGetFileVersion(void)
1820 {
1821     UINT r;
1822     DWORD versz, langsz;
1823     char version[MAX_PATH];
1824     char lang[MAX_PATH];
1825     char path[MAX_PATH];
1826     LPSTR vercheck, langcheck;
1827     DWORD verchecksz, langchecksz;
1828
1829     /* NULL szFilePath */
1830     versz = MAX_PATH;
1831     langsz = MAX_PATH;
1832     lstrcpyA(version, "version");
1833     lstrcpyA(lang, "lang");
1834     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
1835     ok(r == ERROR_INVALID_PARAMETER,
1836        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1837     ok(!lstrcmpA(version, "version"),
1838        "Expected version to be unchanged, got %s\n", version);
1839     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1840     ok(!lstrcmpA(lang, "lang"),
1841        "Expected lang to be unchanged, got %s\n", lang);
1842     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1843
1844     /* empty szFilePath */
1845     versz = MAX_PATH;
1846     langsz = MAX_PATH;
1847     lstrcpyA(version, "version");
1848     lstrcpyA(lang, "lang");
1849     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
1850     ok(r == ERROR_FILE_NOT_FOUND,
1851        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1852     ok(!lstrcmpA(version, "version"),
1853        "Expected version to be unchanged, got %s\n", version);
1854     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1855     ok(!lstrcmpA(lang, "lang"),
1856        "Expected lang to be unchanged, got %s\n", lang);
1857     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1858
1859     /* nonexistent szFilePath */
1860     versz = MAX_PATH;
1861     langsz = MAX_PATH;
1862     lstrcpyA(version, "version");
1863     lstrcpyA(lang, "lang");
1864     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
1865     ok(r == ERROR_FILE_NOT_FOUND,
1866        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1867     ok(!lstrcmpA(version, "version"),
1868        "Expected version to be unchanged, got %s\n", version);
1869     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1870     ok(!lstrcmpA(lang, "lang"),
1871        "Expected lang to be unchanged, got %s\n", lang);
1872     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1873
1874     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
1875     versz = MAX_PATH;
1876     langsz = MAX_PATH;
1877     lstrcpyA(version, "version");
1878     lstrcpyA(lang, "lang");
1879     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
1880     ok(r == ERROR_INVALID_PARAMETER,
1881        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1882     ok(!lstrcmpA(version, "version"),
1883        "Expected version to be unchanged, got %s\n", version);
1884     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1885     ok(!lstrcmpA(lang, "lang"),
1886        "Expected lang to be unchanged, got %s\n", lang);
1887     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1888
1889     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
1890     versz = MAX_PATH;
1891     langsz = MAX_PATH;
1892     lstrcpyA(version, "version");
1893     lstrcpyA(lang, "lang");
1894     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
1895     ok(r == ERROR_INVALID_PARAMETER,
1896        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1897     ok(!lstrcmpA(version, "version"),
1898        "Expected version to be unchanged, got %s\n", version);
1899     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1900     ok(!lstrcmpA(lang, "lang"),
1901        "Expected lang to be unchanged, got %s\n", lang);
1902     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1903
1904     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
1905     versz = 0;
1906     langsz = MAX_PATH;
1907     lstrcpyA(version, "version");
1908     lstrcpyA(lang, "lang");
1909     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
1910     ok(r == ERROR_FILE_NOT_FOUND,
1911        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1912     ok(!lstrcmpA(version, "version"),
1913        "Expected version to be unchanged, got %s\n", version);
1914     ok(versz == 0, "Expected 0, got %d\n", versz);
1915     ok(!lstrcmpA(lang, "lang"),
1916        "Expected lang to be unchanged, got %s\n", lang);
1917     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1918
1919     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
1920     versz = MAX_PATH;
1921     langsz = 0;
1922     lstrcpyA(version, "version");
1923     lstrcpyA(lang, "lang");
1924     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
1925     ok(r == ERROR_FILE_NOT_FOUND,
1926        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1927     ok(!lstrcmpA(version, "version"),
1928        "Expected version to be unchanged, got %s\n", version);
1929     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1930     ok(!lstrcmpA(lang, "lang"),
1931        "Expected lang to be unchanged, got %s\n", lang);
1932     ok(langsz == 0, "Expected 0, got %d\n", langsz);
1933
1934     /* nonexistent szFilePath, rest NULL */
1935     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
1936     ok(r == ERROR_FILE_NOT_FOUND,
1937        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1938
1939     create_file("ver.txt", "ver.txt", 20);
1940
1941     /* file exists, no version information */
1942     versz = MAX_PATH;
1943     langsz = MAX_PATH;
1944     lstrcpyA(version, "version");
1945     lstrcpyA(lang, "lang");
1946     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
1947     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1948     ok(!lstrcmpA(version, "version"),
1949        "Expected version to be unchanged, got %s\n", version);
1950     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1951     ok(!lstrcmpA(lang, "lang"),
1952        "Expected lang to be unchanged, got %s\n", lang);
1953     ok(r == ERROR_FILE_INVALID,
1954        "Expected ERROR_FILE_INVALID, got %d\n", r);
1955
1956     DeleteFileA("ver.txt");
1957
1958     /* relative path, has version information */
1959     versz = MAX_PATH;
1960     langsz = MAX_PATH;
1961     lstrcpyA(version, "version");
1962     lstrcpyA(lang, "lang");
1963     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
1964     todo_wine
1965     {
1966         ok(r == ERROR_FILE_NOT_FOUND,
1967            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1968         ok(!lstrcmpA(version, "version"),
1969            "Expected version to be unchanged, got %s\n", version);
1970         ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
1971         ok(!lstrcmpA(lang, "lang"),
1972            "Expected lang to be unchanged, got %s\n", lang);
1973         ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
1974     }
1975
1976     GetSystemDirectoryA(path, MAX_PATH);
1977     lstrcatA(path, "\\kernel32.dll");
1978
1979     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
1980
1981     /* absolute path, has version information */
1982     versz = MAX_PATH;
1983     langsz = MAX_PATH;
1984     lstrcpyA(version, "version");
1985     lstrcpyA(lang, "lang");
1986     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
1987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1988     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
1989     ok(!lstrcmpA(lang, langcheck), "Expected %s, got %s\n", langcheck, lang);
1990     ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
1991     ok(!lstrcmpA(version, vercheck),
1992         "Expected %s, got %s\n", vercheck, version);
1993
1994     /* only check version */
1995     versz = MAX_PATH;
1996     lstrcpyA(version, "version");
1997     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
1998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1999     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
2000     ok(!lstrcmpA(version, vercheck),
2001        "Expected %s, got %s\n", vercheck, version);
2002
2003     /* only check language */
2004     langsz = MAX_PATH;
2005     lstrcpyA(lang, "lang");
2006     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
2007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2008     ok(!lstrcmpA(lang, langcheck), "Expected %s, got %s\n", langcheck, lang);
2009     ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
2010
2011     /* get pcchVersionBuf */
2012     versz = MAX_PATH;
2013     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
2014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2015     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
2016
2017     /* get pcchLangBuf */
2018     langsz = MAX_PATH;
2019     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
2020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2021     ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
2022
2023     /* pcchVersionBuf not big enough */
2024     versz = 5;
2025     lstrcpyA(version, "version");
2026     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
2027     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2028     ok(!strncmp(version, vercheck, 4),
2029        "Expected first 4 characters of %s, got %s\n", vercheck, version);
2030     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
2031
2032     /* pcchLangBuf not big enough */
2033     langsz = 3;
2034     lstrcpyA(lang, "lang");
2035     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
2036     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2037     ok(!strncmp(lang, langcheck, 2),
2038        "Expected first character of %s, got %s\n", langcheck, lang);
2039     ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
2040
2041     HeapFree(GetProcessHeap(), 0, vercheck);
2042     HeapFree(GetProcessHeap(), 0, langcheck);
2043 }
2044
2045 static void test_MsiGetProductInfo(void)
2046 {
2047     UINT r;
2048     LONG res;
2049     HKEY propkey, source;
2050     HKEY prodkey, localkey;
2051     CHAR prodcode[MAX_PATH];
2052     CHAR prod_squashed[MAX_PATH];
2053     CHAR packcode[MAX_PATH];
2054     CHAR pack_squashed[MAX_PATH];
2055     CHAR buf[MAX_PATH];
2056     CHAR keypath[MAX_PATH];
2057     LPSTR usersid;
2058     DWORD sz;
2059
2060     create_test_guid(prodcode, prod_squashed);
2061     create_test_guid(packcode, pack_squashed);
2062     get_user_sid(&usersid);
2063
2064     /* NULL szProduct */
2065     sz = MAX_PATH;
2066     lstrcpyA(buf, "apple");
2067     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINK, buf, &sz);
2068     ok(r == ERROR_INVALID_PARAMETER,
2069        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2070     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2071     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2072
2073     /* empty szProduct */
2074     sz = MAX_PATH;
2075     lstrcpyA(buf, "apple");
2076     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINK, buf, &sz);
2077     ok(r == ERROR_INVALID_PARAMETER,
2078        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2079     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2080     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2081
2082     /* garbage szProduct */
2083     sz = MAX_PATH;
2084     lstrcpyA(buf, "apple");
2085     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINK, buf, &sz);
2086     ok(r == ERROR_INVALID_PARAMETER,
2087        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2088     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2089     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2090
2091     /* guid without brackets */
2092     sz = MAX_PATH;
2093     lstrcpyA(buf, "apple");
2094     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
2095                            INSTALLPROPERTY_HELPLINK, buf, &sz);
2096     ok(r == ERROR_INVALID_PARAMETER,
2097        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2098     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2099     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2100
2101     /* guid with brackets */
2102     sz = MAX_PATH;
2103     lstrcpyA(buf, "apple");
2104     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
2105                            INSTALLPROPERTY_HELPLINK, buf, &sz);
2106     ok(r == ERROR_UNKNOWN_PRODUCT,
2107        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2108     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2109     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2110
2111     /* same length as guid, but random */
2112     sz = MAX_PATH;
2113     lstrcpyA(buf, "apple");
2114     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
2115                            INSTALLPROPERTY_HELPLINK, buf, &sz);
2116     ok(r == ERROR_INVALID_PARAMETER,
2117        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2118     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2119     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2120
2121     /* not installed, NULL szAttribute */
2122     sz = MAX_PATH;
2123     lstrcpyA(buf, "apple");
2124     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
2125     ok(r == ERROR_INVALID_PARAMETER,
2126        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2127     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2128     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2129
2130     /* not installed, NULL lpValueBuf */
2131     sz = MAX_PATH;
2132     lstrcpyA(buf, "apple");
2133     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, NULL, &sz);
2134     ok(r == ERROR_UNKNOWN_PRODUCT,
2135        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2136     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2137     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2138
2139     /* not installed, NULL pcchValueBuf */
2140     sz = MAX_PATH;
2141     lstrcpyA(buf, "apple");
2142     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, NULL);
2143     ok(r == ERROR_INVALID_PARAMETER,
2144        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2145     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2146     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2147
2148     /* created guid cannot possibly be an installed product code */
2149     sz = MAX_PATH;
2150     lstrcpyA(buf, "apple");
2151     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2152     ok(r == ERROR_UNKNOWN_PRODUCT,
2153        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2154     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2155     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2156
2157     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2158     lstrcatA(keypath, usersid);
2159     lstrcatA(keypath, "\\Installer\\Products\\");
2160     lstrcatA(keypath, prod_squashed);
2161
2162     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
2163     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2164
2165     /* managed product code exists */
2166     sz = MAX_PATH;
2167     lstrcpyA(buf, "apple");
2168     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2169     ok(r == ERROR_UNKNOWN_PROPERTY,
2170        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2171     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2172     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2173
2174     RegDeleteKeyA(prodkey, "");
2175     RegCloseKey(prodkey);
2176
2177     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2178     lstrcatA(keypath, usersid);
2179     lstrcatA(keypath, "\\Products\\");
2180     lstrcatA(keypath, prod_squashed);
2181
2182     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
2183     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2184
2185     /* local user product code exists */
2186     sz = MAX_PATH;
2187     lstrcpyA(buf, "apple");
2188     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2189     ok(r == ERROR_UNKNOWN_PRODUCT,
2190        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2191     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2192     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2193
2194     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2195     lstrcatA(keypath, usersid);
2196     lstrcatA(keypath, "\\Installer\\Products\\");
2197     lstrcatA(keypath, prod_squashed);
2198
2199     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
2200     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2201
2202     /* both local and managed product code exist */
2203     sz = MAX_PATH;
2204     lstrcpyA(buf, "apple");
2205     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2206     ok(r == ERROR_UNKNOWN_PROPERTY,
2207        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2208     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
2209     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2210
2211     res = RegCreateKeyA(localkey, "InstallProperties", &propkey);
2212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2213
2214     /* InstallProperties key exists */
2215     sz = MAX_PATH;
2216     lstrcpyA(buf, "apple");
2217     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2218     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2219     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2220     ok(sz == 0, "Expected 0, got %d\n", sz);
2221
2222     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
2223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2224
2225     /* HelpLink value exists */
2226     sz = MAX_PATH;
2227     lstrcpyA(buf, "apple");
2228     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2230     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
2231     ok(sz == 4, "Expected 4, got %d\n", sz);
2232
2233     /* lpValueBuf is NULL */
2234     sz = MAX_PATH;
2235     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, NULL, &sz);
2236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2237     ok(sz == 4, "Expected 4, got %d\n", sz);
2238
2239     /* lpValueBuf is NULL, pcchValueBuf is too small */
2240     sz = 2;
2241     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, NULL, &sz);
2242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2243     ok(sz == 4, "Expected 4, got %d\n", sz);
2244
2245     /* lpValueBuf is NULL, pcchValueBuf is too small */
2246     sz = 2;
2247     lstrcpyA(buf, "apple");
2248     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2249     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
2250     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2251     ok(sz == 4, "Expected 4, got %d\n", sz);
2252
2253     /* lpValueBuf is NULL, pcchValueBuf is exactly 4 */
2254     sz = 4;
2255     lstrcpyA(buf, "apple");
2256     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2257     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2258     ok(!lstrcmpA(buf, "apple"),
2259        "Expected buf to remain unchanged, got \"%s\"\n", buf);
2260     ok(sz == 4, "Expected 4, got %d\n", sz);
2261
2262     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
2263     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2264
2265     /* random property not supported by MSI, value exists */
2266     sz = MAX_PATH;
2267     lstrcpyA(buf, "apple");
2268     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
2269     ok(r == ERROR_UNKNOWN_PROPERTY,
2270        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2271     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
2272     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2273
2274     RegDeleteValueA(propkey, "IMadeThis");
2275     RegDeleteValueA(propkey, "HelpLink");
2276     RegDeleteKeyA(propkey, "");
2277     RegDeleteKeyA(localkey, "");
2278     RegDeleteKeyA(prodkey, "");
2279     RegCloseKey(propkey);
2280     RegCloseKey(localkey);
2281     RegCloseKey(prodkey);
2282
2283     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2284     lstrcatA(keypath, prod_squashed);
2285
2286     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2287     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2288
2289     /* user product key exists */
2290     sz = MAX_PATH;
2291     lstrcpyA(buf, "apple");
2292     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2293     ok(r == ERROR_UNKNOWN_PROPERTY,
2294        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2295     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
2296     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2297
2298     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2299     lstrcatA(keypath, usersid);
2300     lstrcatA(keypath, "\\Products\\");
2301     lstrcatA(keypath, prod_squashed);
2302
2303     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
2304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2305
2306     /* local user product key exists */
2307     sz = MAX_PATH;
2308     lstrcpyA(buf, "apple");
2309     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2310     ok(r == ERROR_UNKNOWN_PROPERTY,
2311        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2312     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
2313     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2314
2315     res = RegCreateKeyA(localkey, "InstallProperties", &propkey);
2316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2317
2318     /* InstallProperties key exists */
2319     sz = MAX_PATH;
2320     lstrcpyA(buf, "apple");
2321     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2323     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2324     ok(sz == 0, "Expected 0, got %d\n", sz);
2325
2326     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
2327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2328
2329     /* HelpLink value exists */
2330     sz = MAX_PATH;
2331     lstrcpyA(buf, "apple");
2332     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2334     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
2335     ok(sz == 4, "Expected 4, got %d\n", sz);
2336
2337     RegDeleteValueA(propkey, "HelpLink");
2338     RegDeleteKeyA(propkey, "");
2339     RegDeleteKeyA(localkey, "");
2340     RegDeleteKeyA(prodkey, "");
2341     RegCloseKey(propkey);
2342     RegCloseKey(localkey);
2343     RegCloseKey(prodkey);
2344
2345     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2346     lstrcatA(keypath, prod_squashed);
2347
2348     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
2349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2350
2351     /* classes product key exists */
2352     sz = MAX_PATH;
2353     lstrcpyA(buf, "apple");
2354     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2355     ok(r == ERROR_UNKNOWN_PROPERTY,
2356        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2357     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
2358     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2359
2360     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2361     lstrcatA(keypath, usersid);
2362     lstrcatA(keypath, "\\Products\\");
2363     lstrcatA(keypath, prod_squashed);
2364
2365     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
2366     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2367
2368     /* local user product key exists */
2369     sz = MAX_PATH;
2370     lstrcpyA(buf, "apple");
2371     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2372     ok(r == ERROR_UNKNOWN_PROPERTY,
2373        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2374     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
2375     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2376
2377     res = RegCreateKeyA(localkey, "InstallProperties", &propkey);
2378     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2379
2380     /* InstallProperties key exists */
2381     sz = MAX_PATH;
2382     lstrcpyA(buf, "apple");
2383     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2384     ok(r == ERROR_UNKNOWN_PROPERTY,
2385        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2386     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
2387     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2388
2389     RegDeleteKeyA(propkey, "");
2390     RegDeleteKeyA(localkey, "");
2391     RegCloseKey(propkey);
2392     RegCloseKey(localkey);
2393
2394     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2395     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
2396     lstrcatA(keypath, prod_squashed);
2397
2398     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
2399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2400
2401     /* Local System product key exists */
2402     sz = MAX_PATH;
2403     lstrcpyA(buf, "apple");
2404     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2405     ok(r == ERROR_UNKNOWN_PROPERTY,
2406         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
2407     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
2408     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2409
2410     res = RegCreateKeyA(localkey, "InstallProperties", &propkey);
2411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2412
2413     /* InstallProperties key exists */
2414     sz = MAX_PATH;
2415     lstrcpyA(buf, "apple");
2416     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2418     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2419     ok(sz == 0, "Expected 0, got %d\n", sz);
2420
2421     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
2422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2423
2424     /* HelpLink value exists */
2425     sz = MAX_PATH;
2426     lstrcpyA(buf, "apple");
2427     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
2428     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2429     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
2430     ok(sz == 4, "Expected 4, got %d\n", sz);
2431
2432     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
2433     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2434
2435     /* DisplayName value exists */
2436     sz = MAX_PATH;
2437     lstrcpyA(buf, "apple");
2438     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
2439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2440     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
2441     ok(sz == 4, "Expected 4, got %d\n", sz);
2442
2443     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
2444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2445
2446     /* DisplayVersion value exists */
2447     sz = MAX_PATH;
2448     lstrcpyA(buf, "apple");
2449     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
2450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2451     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
2452     ok(sz == 5, "Expected 5, got %d\n", sz);
2453
2454     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
2455     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2456
2457     /* HelpTelephone value exists */
2458     sz = MAX_PATH;
2459     lstrcpyA(buf, "apple");
2460     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
2461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2462     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
2463     ok(sz == 4, "Expected 4, got %d\n", sz);
2464
2465     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
2466     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2467
2468     /* InstallLocation value exists */
2469     sz = MAX_PATH;
2470     lstrcpyA(buf, "apple");
2471     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
2472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2473     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
2474     ok(sz == 3, "Expected 3, got %d\n", sz);
2475
2476     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
2477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2478
2479     /* InstallSource value exists */
2480     sz = MAX_PATH;
2481     lstrcpyA(buf, "apple");
2482     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
2483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2484     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
2485     ok(sz == 6, "Expected 6, got %d\n", sz);
2486
2487     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
2488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2489
2490     /* InstallDate value exists */
2491     sz = MAX_PATH;
2492     lstrcpyA(buf, "apple");
2493     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATE, buf, &sz);
2494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2495     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
2496     ok(sz == 4, "Expected 4, got %d\n", sz);
2497
2498     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
2499     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2500
2501     /* Publisher value exists */
2502     sz = MAX_PATH;
2503     lstrcpyA(buf, "apple");
2504     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHER, buf, &sz);
2505     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2506     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
2507     ok(sz == 3, "Expected 3, got %d\n", sz);
2508
2509     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
2510     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2511
2512     /* LocalPackage value exists */
2513     sz = MAX_PATH;
2514     lstrcpyA(buf, "apple");
2515     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
2516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2517     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
2518     ok(sz == 4, "Expected 4, got %d\n", sz);
2519
2520     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
2521     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2522
2523     /* UrlInfoAbout value exists */
2524     sz = MAX_PATH;
2525     lstrcpyA(buf, "apple");
2526     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
2527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2528     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
2529     ok(sz == 5, "Expected 5, got %d\n", sz);
2530
2531     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
2532     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2533
2534     /* UrlUpdateInfo value exists */
2535     sz = MAX_PATH;
2536     lstrcpyA(buf, "apple");
2537     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
2538     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2539     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
2540     ok(sz == 4, "Expected 4, got %d\n", sz);
2541
2542     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
2543     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2544
2545     /* VersionMinor value exists */
2546     sz = MAX_PATH;
2547     lstrcpyA(buf, "apple");
2548     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
2549     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2550     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
2551     ok(sz == 1, "Expected 1, got %d\n", sz);
2552
2553     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
2554     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2555
2556     /* VersionMajor value exists */
2557     sz = MAX_PATH;
2558     lstrcpyA(buf, "apple");
2559     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
2560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2561     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
2562     ok(sz == 1, "Expected 1, got %d\n", sz);
2563
2564     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
2565     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2566
2567     /* ProductID value exists */
2568     sz = MAX_PATH;
2569     lstrcpyA(buf, "apple");
2570     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTID, buf, &sz);
2571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2572     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
2573     ok(sz == 2, "Expected 2, got %d\n", sz);
2574
2575     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
2576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2577
2578     /* RegCompany value exists */
2579     sz = MAX_PATH;
2580     lstrcpyA(buf, "apple");
2581     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANY, buf, &sz);
2582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2583     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
2584     ok(sz == 4, "Expected 4, got %d\n", sz);
2585
2586     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
2587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2588
2589     /* RegOwner value exists */
2590     sz = MAX_PATH;
2591     lstrcpyA(buf, "apple");
2592     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNER, buf, &sz);
2593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2594     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
2595     ok(sz == 3, "Expected 3, got %d\n", sz);
2596
2597     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
2598     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2599
2600     /* InstanceType value exists */
2601     sz = MAX_PATH;
2602     lstrcpyA(buf, "apple");
2603     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPE, buf, &sz);
2604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2605     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2606     ok(sz == 0, "Expected 0, got %d\n", sz);
2607
2608     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
2609     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2610
2611     /* InstanceType value exists */
2612     sz = MAX_PATH;
2613     lstrcpyA(buf, "apple");
2614     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPE, buf, &sz);
2615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2616     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
2617     ok(sz == 4, "Expected 4, got %d\n", sz);
2618
2619     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
2620     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2621
2622     /* Transforms value exists */
2623     sz = MAX_PATH;
2624     lstrcpyA(buf, "apple");
2625     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMS, buf, &sz);
2626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2627     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2628     ok(sz == 0, "Expected 0, got %d\n", sz);
2629
2630     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
2631     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2632
2633     /* Transforms value exists */
2634     sz = MAX_PATH;
2635     lstrcpyA(buf, "apple");
2636     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMS, buf, &sz);
2637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2638     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
2639     ok(sz == 6, "Expected 6, got %d\n", sz);
2640
2641     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
2642     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2643
2644     /* Language value exists */
2645     sz = MAX_PATH;
2646     lstrcpyA(buf, "apple");
2647     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGE, buf, &sz);
2648     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2649     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2650     ok(sz == 0, "Expected 0, got %d\n", sz);
2651
2652     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
2653     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2654
2655     /* Language value exists */
2656     sz = MAX_PATH;
2657     lstrcpyA(buf, "apple");
2658     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGE, buf, &sz);
2659     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2660     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
2661     ok(sz == 4, "Expected 4, got %d\n", sz);
2662
2663     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
2664     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2665
2666     /* ProductName value exists */
2667     sz = MAX_PATH;
2668     lstrcpyA(buf, "apple");
2669     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
2670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2671     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2672     ok(sz == 0, "Expected 0, got %d\n", sz);
2673
2674     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
2675     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2676
2677     /* ProductName value exists */
2678     sz = MAX_PATH;
2679     lstrcpyA(buf, "apple");
2680     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
2681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2682     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
2683     ok(sz == 4, "Expected 4, got %d\n", sz);
2684
2685     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
2686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2687
2688     /* AssignmentType value exists */
2689     sz = MAX_PATH;
2690     lstrcpyA(buf, "apple");
2691     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
2692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2693     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2694     ok(sz == 0, "Expected 0, got %d\n", sz);
2695
2696     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
2697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2698
2699     /* AssignmentType value exists */
2700     sz = MAX_PATH;
2701     lstrcpyA(buf, "apple");
2702     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
2703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2704     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
2705     ok(sz == 2, "Expected 2, got %d\n", sz);
2706
2707     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
2708     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2709
2710     /* PackageCode value exists */
2711     sz = MAX_PATH;
2712     lstrcpyA(buf, "apple");
2713     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
2714     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2715     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2716     ok(sz == 0, "Expected 0, got %d\n", sz);
2717
2718     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
2719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2720
2721     /* PackageCode value exists */
2722     sz = MAX_PATH;
2723     lstrcpyA(buf, "apple");
2724     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
2725     ok(r == ERROR_BAD_CONFIGURATION,
2726        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2727     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
2728     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
2729
2730     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
2731     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2732
2733     /* PackageCode value exists */
2734     sz = MAX_PATH;
2735     lstrcpyA(buf, "apple");
2736     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
2737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2738     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
2739     ok(sz == 38, "Expected 38, got %d\n", sz);
2740
2741     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
2742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2743
2744     /* Version value exists */
2745     sz = MAX_PATH;
2746     lstrcpyA(buf, "apple");
2747     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSION, buf, &sz);
2748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2749     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2750     ok(sz == 0, "Expected 0, got %d\n", sz);
2751
2752     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
2753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2754
2755     /* Version value exists */
2756     sz = MAX_PATH;
2757     lstrcpyA(buf, "apple");
2758     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSION, buf, &sz);
2759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2760     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
2761     ok(sz == 3, "Expected 3, got %d\n", sz);
2762
2763     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
2764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2765
2766     /* ProductIcon value exists */
2767     sz = MAX_PATH;
2768     lstrcpyA(buf, "apple");
2769     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICON, buf, &sz);
2770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2771     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2772     ok(sz == 0, "Expected 0, got %d\n", sz);
2773
2774     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
2775     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2776
2777     /* ProductIcon value exists */
2778     sz = MAX_PATH;
2779     lstrcpyA(buf, "apple");
2780     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICON, buf, &sz);
2781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2782     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
2783     ok(sz == 3, "Expected 3, got %d\n", sz);
2784
2785     res = RegCreateKeyA(prodkey, "SourceList", &source);
2786     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2787
2788     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
2789     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2790
2791     sz = MAX_PATH;
2792     lstrcpyA(buf, "apple");
2793     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAME, buf, &sz);
2794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2795     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
2796     ok(sz == 8, "Expected 8, got %d\n", sz);
2797
2798     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
2799     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2800
2801     /* Authorized value exists */
2802     sz = MAX_PATH;
2803     lstrcpyA(buf, "apple");
2804     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
2805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2806     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
2807     ok(sz == 0, "Expected 0, got %d\n", sz);
2808
2809     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
2810     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2811
2812     /* Authorized value exists */
2813     sz = MAX_PATH;
2814     lstrcpyA(buf, "apple");
2815     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
2816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2817     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
2818     ok(sz == 4, "Expected 4, got %d\n", sz);
2819
2820     RegDeleteValueA(propkey, "HelpLink");
2821     RegDeleteValueA(propkey, "DisplayName");
2822     RegDeleteValueA(propkey, "DisplayVersion");
2823     RegDeleteValueA(propkey, "HelpTelephone");
2824     RegDeleteValueA(propkey, "InstallLocation");
2825     RegDeleteValueA(propkey, "InstallSource");
2826     RegDeleteValueA(propkey, "InstallDate");
2827     RegDeleteValueA(propkey, "Publisher");
2828     RegDeleteValueA(propkey, "LocalPackage");
2829     RegDeleteValueA(propkey, "UrlInfoAbout");
2830     RegDeleteValueA(propkey, "UrlUpdateInfo");
2831     RegDeleteValueA(propkey, "VersionMinor");
2832     RegDeleteValueA(propkey, "VersionMajor");
2833     RegDeleteValueA(propkey, "ProductID");
2834     RegDeleteValueA(propkey, "RegCompany");
2835     RegDeleteValueA(propkey, "RegOwner");
2836     RegDeleteValueA(propkey, "InstanceType");
2837     RegDeleteValueA(propkey, "Transforms");
2838     RegDeleteValueA(propkey, "Language");
2839     RegDeleteValueA(propkey, "ProductName");
2840     RegDeleteValueA(propkey, "Assignment");
2841     RegDeleteValueA(propkey, "PackageCode");
2842     RegDeleteValueA(propkey, "Version");
2843     RegDeleteValueA(propkey, "ProductIcon");
2844     RegDeleteValueA(propkey, "AuthorizedLUAApp");
2845     RegDeleteKeyA(propkey, "");
2846     RegDeleteKeyA(localkey, "");
2847     RegDeleteValueA(prodkey, "InstanceType");
2848     RegDeleteValueA(prodkey, "Transforms");
2849     RegDeleteValueA(prodkey, "Language");
2850     RegDeleteValueA(prodkey, "ProductName");
2851     RegDeleteValueA(prodkey, "Assignment");
2852     RegDeleteValueA(prodkey, "PackageCode");
2853     RegDeleteValueA(prodkey, "Version");
2854     RegDeleteValueA(prodkey, "ProductIcon");
2855     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
2856     RegDeleteValueA(source, "PackageName");
2857     RegDeleteKeyA(source, "");
2858     RegDeleteKeyA(prodkey, "");
2859     RegCloseKey(propkey);
2860     RegCloseKey(localkey);
2861     RegCloseKey(source);
2862     RegCloseKey(prodkey);
2863 }
2864
2865 START_TEST(msi)
2866 {
2867     init_functionpointers();
2868
2869     test_usefeature();
2870     test_null();
2871     test_getcomponentpath();
2872     test_MsiGetFileHash();
2873
2874     if (!pConvertSidToStringSidA)
2875         skip("ConvertSidToStringSidA not implemented\n");
2876     else
2877     {
2878         /* These tests rely on get_user_sid that needs ConvertSidToStringSidA */
2879         test_MsiQueryProductState();
2880         test_MsiQueryFeatureState();
2881         test_MsiQueryComponentState();
2882         test_MsiGetComponentPath();
2883         test_MsiGetProductCode();
2884         test_MsiEnumClients();
2885         test_MsiGetProductInfo();
2886     }
2887
2888     test_MsiGetFileVersion();
2889 }