dinput: Silence incorrect warning and move it to a valid place.
[wine] / dlls / msi / tests / msi.c
1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define _WIN32_MSI 300
22
23 #include <stdio.h>
24 #include <windows.h>
25 #include <msi.h>
26 #include <msiquery.h>
27 #include <sddl.h>
28
29 #include "wine/test.h"
30
31 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
32
33 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
34     (LPCSTR, LPCSTR, LPSTR, DWORD*);
35 static UINT (WINAPI *pMsiGetFileHashA)
36     (LPCSTR, DWORD, PMSIFILEHASHINFO);
37 static UINT (WINAPI *pMsiOpenPackageExA)
38     (LPCSTR, DWORD, MSIHANDLE*);
39 static UINT (WINAPI *pMsiOpenPackageExW)
40     (LPCWSTR, DWORD, MSIHANDLE*);
41 static UINT (WINAPI *pMsiQueryComponentStateA)
42     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
43 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
44     (LPCSTR, LPCSTR ,DWORD, DWORD );
45
46 static void init_functionpointers(void)
47 {
48     HMODULE hmsi = GetModuleHandleA("msi.dll");
49     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
50
51     pMsiGetComponentPathA = (void*)GetProcAddress(hmsi, "MsiGetComponentPathA");
52     pMsiGetFileHashA = (void*)GetProcAddress(hmsi, "MsiGetFileHashA");
53     pMsiOpenPackageExA = (void*)GetProcAddress(hmsi, "MsiOpenPackageExA");
54     pMsiOpenPackageExW = (void*)GetProcAddress(hmsi, "MsiOpenPackageExW");
55     pMsiQueryComponentStateA = (void*)GetProcAddress(hmsi, "MsiQueryComponentStateA");
56     pMsiUseFeatureExA = (void*)GetProcAddress(hmsi, "MsiUseFeatureExA");
57
58     pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
59 }
60
61 static void test_usefeature(void)
62 {
63     INSTALLSTATE r;
64
65     if (!pMsiUseFeatureExA)
66         return;
67
68     r = MsiQueryFeatureState(NULL,NULL);
69     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
70
71     r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
72     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
73
74     r = pMsiUseFeatureExA(NULL,NULL,0,0);
75     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
76
77     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
78     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
79
80     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
81                          NULL, -2, 0 );
82     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
83
84     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}", 
85                          "WORDVIEWFiles", -2, 0 );
86     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
87
88     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}", 
89                          "WORDVIEWFiles", -2, 0 );
90     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
91
92     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
93                          "WORDVIEWFiles", -2, 1 );
94     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
95 }
96
97 static void test_null(void)
98 {
99     MSIHANDLE hpkg;
100     UINT r;
101     HKEY hkey;
102     DWORD dwType, cbData;
103     LPBYTE lpData = NULL;
104     INSTALLSTATE state;
105
106     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
107     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
108
109     state = MsiQueryProductStateW(NULL);
110     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
111
112     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
113     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
114
115     r = MsiConfigureFeatureW(NULL, NULL, 0);
116     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
117
118     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
119     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
120
121     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", 0);
122     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
123
124     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", "foo", INSTALLSTATE_DEFAULT);
125     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
126
127     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
128      * necessary registry values */
129
130     /* empty product string */
131     r = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", &hkey);
132     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
133
134     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
135     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
136     if ( r == ERROR_SUCCESS )
137     {
138         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
139         if (!lpData)
140             skip("Out of memory\n");
141         else
142         {
143             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
144             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
145         }
146     }
147
148     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
149     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
150
151     r = MsiGetProductInfoA("", "", NULL, NULL);
152     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
153
154     if (lpData)
155     {
156         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
157         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
158
159         HeapFree(GetProcessHeap(), 0, lpData);
160     }
161     else
162     {
163         r = RegDeleteValueA(hkey, NULL);
164         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
165     }
166
167     r = RegCloseKey(hkey);
168     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
169
170     /* empty attribute */
171     r = RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", &hkey);
172     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
173
174     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
175     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
176
177     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
178     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
179
180     r = RegCloseKey(hkey);
181     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
182
183     r = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}");
184     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
185 }
186
187 static void test_getcomponentpath(void)
188 {
189     INSTALLSTATE r;
190     char buffer[0x100];
191     DWORD sz;
192
193     if(!pMsiGetComponentPathA)
194         return;
195
196     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
197     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
198
199     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
200     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
201
202     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
203     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
204
205     sz = sizeof buffer;
206     buffer[0]=0;
207     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
208     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
209
210     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
211         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
212     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
213
214     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
215         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
216     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
217
218     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
219         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
220     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
221
222     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
223                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
224     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
225 }
226
227 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
228 {
229     HANDLE file;
230     DWORD written;
231
232     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
233     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
234     WriteFile(file, data, strlen(data), &written, NULL);
235
236     if (size)
237     {
238         SetFilePointer(file, size, NULL, FILE_BEGIN);
239         SetEndOfFile(file);
240     }
241
242     CloseHandle(file);
243 }
244
245 #define HASHSIZE sizeof(MSIFILEHASHINFO)
246
247 static const struct
248 {
249     LPCSTR data;
250     DWORD size;
251     MSIFILEHASHINFO hash;
252 } hash_data[] =
253 {
254     { "abc", 0,
255       { HASHSIZE,
256         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
257       },
258     },
259
260     { "C:\\Program Files\\msitest\\caesar\n", 0,
261       { HASHSIZE,
262         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
263       },
264     },
265
266     { "C:\\Program Files\\msitest\\caesar\n", 500,
267       { HASHSIZE,
268         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
269       },
270     },
271 };
272
273 static void test_MsiGetFileHash(void)
274 {
275     const char name[] = "msitest.bin";
276     UINT r;
277     MSIFILEHASHINFO hash;
278     DWORD i;
279
280     if (!pMsiGetFileHashA)
281     {
282         skip("MsiGetFileHash not implemented.");
283         return;
284     }
285
286     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
287
288     /* szFilePath is NULL */
289     r = pMsiGetFileHashA(NULL, 0, &hash);
290     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
291
292     /* szFilePath is empty */
293     r = pMsiGetFileHashA("", 0, &hash);
294     ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", r);
295
296     /* szFilePath is nonexistent */
297     r = pMsiGetFileHashA(name, 0, &hash);
298     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
299
300     /* dwOptions is non-zero */
301     r = pMsiGetFileHashA(name, 1, &hash);
302     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
303
304     /* pHash.dwFileHashInfoSize is not correct */
305     hash.dwFileHashInfoSize = 0;
306     r = pMsiGetFileHashA(name, 0, &hash);
307     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
308
309     /* pHash is NULL */
310     r = pMsiGetFileHashA(name, 0, NULL);
311     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
312
313     for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
314     {
315         create_file(name, hash_data[i].data, hash_data[i].size);
316
317         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
318         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
319
320         r = pMsiGetFileHashA(name, 0, &hash);
321         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
322         ok(!memcmp(&hash, &hash_data[i].hash, HASHSIZE), "Hash incorrect\n");
323
324         DeleteFile(name);
325     }
326 }
327
328 /* copied from dlls/msi/registry.c */
329 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
330 {
331     DWORD i,n=1;
332     GUID guid;
333
334     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
335         return FALSE;
336
337     for(i=0; i<8; i++)
338         out[7-i] = in[n++];
339     n++;
340     for(i=0; i<4; i++)
341         out[11-i] = in[n++];
342     n++;
343     for(i=0; i<4; i++)
344         out[15-i] = in[n++];
345     n++;
346     for(i=0; i<2; i++)
347     {
348         out[17+i*2] = in[n++];
349         out[16+i*2] = in[n++];
350     }
351     n++;
352     for( ; i<8; i++)
353     {
354         out[17+i*2] = in[n++];
355         out[16+i*2] = in[n++];
356     }
357     out[32]=0;
358     return TRUE;
359 }
360
361 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
362 {
363     WCHAR guidW[MAX_PATH];
364     WCHAR squashedW[MAX_PATH];
365     GUID guid;
366     HRESULT hr;
367     int size;
368
369     hr = CoCreateGuid(&guid);
370     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
371
372     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
373     ok(size == 39, "Expected 39, got %d\n", hr);
374
375     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
376     squash_guid(guidW, squashedW);
377     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
378 }
379
380 static void get_user_sid(LPSTR *usersid)
381 {
382     HANDLE token;
383     BYTE buf[1024];
384     DWORD size;
385     PTOKEN_USER user;
386
387     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
388     size = sizeof(buf);
389     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
390     user = (PTOKEN_USER)buf;
391     pConvertSidToStringSidA(user->User.Sid, usersid);
392 }
393
394 static void test_MsiQueryProductState(void)
395 {
396     CHAR prodcode[MAX_PATH];
397     CHAR prod_squashed[MAX_PATH];
398     CHAR keypath[MAX_PATH*2];
399     LPSTR usersid;
400     INSTALLSTATE state;
401     LONG res;
402     HKEY userkey, localkey, props;
403     DWORD data;
404
405     create_test_guid(prodcode, prod_squashed);
406     get_user_sid(&usersid);
407
408     /* NULL prodcode */
409     state = MsiQueryProductStateA(NULL);
410     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
411
412     /* empty prodcode */
413     state = MsiQueryProductStateA("");
414     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
415
416     /* garbage prodcode */
417     state = MsiQueryProductStateA("garbage");
418     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
419
420     /* guid without brackets */
421     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
422     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
423
424     /* guid with brackets */
425     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
426     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
427
428     /* same length as guid, but random */
429     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
430     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
431
432     /* created guid cannot possibly be an installed product code */
433     state = MsiQueryProductStateA(prodcode);
434     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
435
436     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
437     lstrcatA(keypath, prod_squashed);
438
439     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
440     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
441
442     /* user product key exists */
443     state = MsiQueryProductStateA(prodcode);
444     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
445
446     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
447     lstrcatA(keypath, prodcode);
448
449     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
451
452     /* local uninstall key exists */
453     state = MsiQueryProductStateA(prodcode);
454     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
455
456     data = 1;
457     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
458     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
459
460     /* WindowsInstaller value exists */
461     state = MsiQueryProductStateA(prodcode);
462     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
463
464     RegDeleteValueA(localkey, "WindowsInstaller");
465     RegDeleteKeyA(localkey, "");
466
467     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
468     lstrcatA(keypath, usersid);
469     lstrcatA(keypath, "\\Products\\");
470     lstrcatA(keypath, prod_squashed);
471
472     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
473     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
474
475     /* local product key exists */
476     state = MsiQueryProductStateA(prodcode);
477     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
478
479     res = RegCreateKeyA(localkey, "InstallProperties", &props);
480     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
481
482     /* install properties key exists */
483     state = MsiQueryProductStateA(prodcode);
484     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
485
486     data = 1;
487     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
489
490     /* WindowsInstaller value exists */
491     state = MsiQueryProductStateA(prodcode);
492     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
493
494     data = 2;
495     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
496     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
497
498     /* WindowsInstaller value is not 1 */
499     state = MsiQueryProductStateA(prodcode);
500     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
501
502     RegDeleteKeyA(userkey, "");
503
504     /* user product key does not exist */
505     state = MsiQueryProductStateA(prodcode);
506     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
507
508     LocalFree(usersid);
509     RegDeleteValueA(props, "WindowsInstaller");
510     RegDeleteKeyA(props, "");
511     RegDeleteKeyA(localkey, "");
512     RegCloseKey(userkey);
513     RegCloseKey(localkey);
514     RegCloseKey(props);
515 }
516
517 static const char table_enc85[] =
518 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
519 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
520 "yz{}~";
521
522 /*
523  *  Encodes a base85 guid given a GUID pointer
524  *  Caller should provide a 21 character buffer for the encoded string.
525  *
526  *  returns TRUE if successful, FALSE if not
527  */
528 static BOOL encode_base85_guid( GUID *guid, LPWSTR str )
529 {
530     unsigned int x, *p, i;
531
532     p = (unsigned int*) guid;
533     for( i=0; i<4; i++ )
534     {
535         x = p[i];
536         *str++ = table_enc85[x%85];
537         x = x/85;
538         *str++ = table_enc85[x%85];
539         x = x/85;
540         *str++ = table_enc85[x%85];
541         x = x/85;
542         *str++ = table_enc85[x%85];
543         x = x/85;
544         *str++ = table_enc85[x%85];
545     }
546     *str = 0;
547
548     return TRUE;
549 }
550
551 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
552 {
553     WCHAR guidW[MAX_PATH];
554     WCHAR base85W[MAX_PATH];
555     WCHAR squashedW[MAX_PATH];
556     GUID guid;
557     HRESULT hr;
558     int size;
559
560     hr = CoCreateGuid(&guid);
561     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
562
563     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
564     ok(size == 39, "Expected 39, got %d\n", hr);
565
566     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
567     encode_base85_guid(&guid, base85W);
568     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
569     squash_guid(guidW, squashedW);
570     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
571 }
572
573 static void test_MsiQueryFeatureState(void)
574 {
575     HKEY userkey, localkey, compkey;
576     CHAR prodcode[MAX_PATH];
577     CHAR prod_squashed[MAX_PATH];
578     CHAR component[MAX_PATH];
579     CHAR comp_base85[MAX_PATH];
580     CHAR comp_squashed[MAX_PATH];
581     CHAR keypath[MAX_PATH*2];
582     INSTALLSTATE state;
583     LPSTR usersid;
584     LONG res;
585
586     create_test_guid(prodcode, prod_squashed);
587     compose_base85_guid(component, comp_base85, comp_squashed);
588     get_user_sid(&usersid);
589
590     /* NULL prodcode */
591     state = MsiQueryFeatureStateA(NULL, "feature");
592     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
593
594     /* empty prodcode */
595     state = MsiQueryFeatureStateA("", "feature");
596     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
597
598     /* garbage prodcode */
599     state = MsiQueryFeatureStateA("garbage", "feature");
600     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
601
602     /* guid without brackets */
603     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
604     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
605
606     /* guid with brackets */
607     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
608     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
609
610     /* same length as guid, but random */
611     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
612     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
613
614     /* NULL szFeature */
615     state = MsiQueryFeatureStateA(prodcode, NULL);
616     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
617
618     /* empty szFeature */
619     state = MsiQueryFeatureStateA(prodcode, "");
620     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
621
622     /* feature key does not exist yet */
623     state = MsiQueryFeatureStateA(prodcode, "feature");
624     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
625
626     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
627     lstrcatA(keypath, prod_squashed);
628
629     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
630     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
631
632     /* feature key exists */
633     state = MsiQueryFeatureStateA(prodcode, "feature");
634     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
635
636     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 8);
637     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
638
639     state = MsiQueryFeatureStateA(prodcode, "feature");
640     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
641
642     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
643     lstrcatA(keypath, usersid);
644     lstrcatA(keypath, "\\Products\\");
645     lstrcatA(keypath, prod_squashed);
646     lstrcatA(keypath, "\\Features");
647
648     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
649     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
650
651     state = MsiQueryFeatureStateA(prodcode, "feature");
652     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
653
654     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
655     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
656
657     state = MsiQueryFeatureStateA(prodcode, "feature");
658     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
659
660     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
662
663     state = MsiQueryFeatureStateA(prodcode, "feature");
664     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
665
666     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
667     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
668
669     state = MsiQueryFeatureStateA(prodcode, "feature");
670     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
671
672     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21);
673     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
674
675     state = MsiQueryFeatureStateA(prodcode, "feature");
676     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
677
678     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
679     lstrcatA(keypath, usersid);
680     lstrcatA(keypath, "\\Components\\");
681     lstrcatA(keypath, comp_squashed);
682
683     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
685
686     state = MsiQueryFeatureStateA(prodcode, "feature");
687     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
688
689     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
690     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
691
692     state = MsiQueryFeatureStateA(prodcode, "feature");
693     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
694
695     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1);
696     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
697
698     state = MsiQueryFeatureStateA(prodcode, "feature");
699     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
700
701     RegDeleteValueA(compkey, prod_squashed);
702     RegDeleteValueA(compkey, "");
703     RegDeleteValueA(localkey, "feature");
704     RegDeleteValueA(userkey, "feature");
705     RegDeleteKeyA(userkey, "");
706     RegCloseKey(compkey);
707     RegCloseKey(localkey);
708     RegCloseKey(userkey);
709 }
710
711 static void test_MsiQueryComponentState(void)
712 {
713     HKEY compkey, prodkey;
714     CHAR prodcode[MAX_PATH];
715     CHAR prod_squashed[MAX_PATH];
716     CHAR component[MAX_PATH];
717     CHAR comp_base85[MAX_PATH];
718     CHAR comp_squashed[MAX_PATH];
719     CHAR keypath[MAX_PATH];
720     INSTALLSTATE state;
721     LPSTR usersid;
722     LONG res;
723     UINT r;
724
725     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
726
727     create_test_guid(prodcode, prod_squashed);
728     compose_base85_guid(component, comp_base85, comp_squashed);
729     get_user_sid(&usersid);
730
731     /* NULL szProductCode */
732     state = MAGIC_ERROR;
733     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
734     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
735     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
736
737     /* empty szProductCode */
738     state = MAGIC_ERROR;
739     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
740     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
741     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
742
743     /* random szProductCode */
744     state = MAGIC_ERROR;
745     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
746     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
747     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
748
749     /* GUID-length szProductCode */
750     state = MAGIC_ERROR;
751     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
752     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
753     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
754
755     /* GUID-length with brackets */
756     state = MAGIC_ERROR;
757     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
758     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
759     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
760
761     /* actual GUID */
762     state = MAGIC_ERROR;
763     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
764     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
765     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
766
767     state = MAGIC_ERROR;
768     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
769     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
770     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
771
772     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
773     lstrcatA(keypath, prod_squashed);
774
775     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
776     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
777
778     state = MAGIC_ERROR;
779     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
780     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
781     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
782
783     RegDeleteKeyA(prodkey, "");
784     RegCloseKey(prodkey);
785
786     /* create local system product key */
787     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
788     lstrcatA(keypath, prod_squashed);
789     lstrcatA(keypath, "\\InstallProperties");
790
791     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
792     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
793
794     /* local system product key exists */
795     state = MAGIC_ERROR;
796     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
797     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
798     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
799
800     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
802
803     /* LocalPackage value exists */
804     state = MAGIC_ERROR;
805     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
806     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
807     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
808
809     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
810     lstrcatA(keypath, comp_squashed);
811
812     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
813     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
814
815     /* component key exists */
816     state = MAGIC_ERROR;
817     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
818     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
819     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
820
821     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
822     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
823
824     /* component\product exists */
825     state = MAGIC_ERROR;
826     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
828     ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
829
830     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
831     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
832
833     state = MAGIC_ERROR;
834     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
836     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
837
838     RegDeleteValueA(prodkey, "LocalPackage");
839     RegDeleteKeyA(prodkey, "");
840     RegDeleteValueA(compkey, prod_squashed);
841     RegDeleteKeyA(prodkey, "");
842     RegCloseKey(prodkey);
843     RegCloseKey(compkey);
844
845     /* MSIINSTALLCONTEXT_USERUNMANAGED */
846
847     state = MAGIC_ERROR;
848     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
849     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
850     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
851
852     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
853     lstrcatA(keypath, prod_squashed);
854
855     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
856     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
857
858     state = MAGIC_ERROR;
859     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
860     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
861     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
862
863     RegDeleteKeyA(prodkey, "");
864     RegCloseKey(prodkey);
865
866     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
867     lstrcatA(keypath, usersid);
868     lstrcatA(keypath, "\\Products\\");
869     lstrcatA(keypath, prod_squashed);
870     lstrcatA(keypath, "\\InstallProperties");
871
872     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
873     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
874
875     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
876     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
877
878     RegCloseKey(prodkey);
879
880     state = MAGIC_ERROR;
881     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
882     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
883     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
884
885     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
886     lstrcatA(keypath, usersid);
887     lstrcatA(keypath, "\\Components\\");
888     lstrcatA(keypath, comp_squashed);
889
890     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
892
893     /* component key exists */
894     state = MAGIC_ERROR;
895     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
896     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
897     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
898
899     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
900     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
901
902     /* component\product exists */
903     state = MAGIC_ERROR;
904     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
905     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
906     ok(state == INSTALLSTATE_NOTUSED, "Expected INSTALLSTATE_NOTUSED, got %d\n", state);
907
908     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
909     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
910
911     state = MAGIC_ERROR;
912     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
913     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
914     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
915
916     /* MSIINSTALLCONTEXT_USERMANAGED */
917
918     state = MAGIC_ERROR;
919     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
920     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
921     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
922
923     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
924     lstrcatA(keypath, prod_squashed);
925
926     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
927     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
928
929     state = MAGIC_ERROR;
930     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
931     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
932     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
933
934     RegDeleteKeyA(prodkey, "");
935     RegCloseKey(prodkey);
936
937     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
938     lstrcatA(keypath, usersid);
939     lstrcatA(keypath, "\\Installer\\Products\\");
940     lstrcatA(keypath, prod_squashed);
941
942     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
943     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
944
945     state = MAGIC_ERROR;
946     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
947     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
948     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
949
950     RegDeleteKeyA(prodkey, "");
951     RegCloseKey(prodkey);
952
953     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
954     lstrcatA(keypath, usersid);
955     lstrcatA(keypath, "\\Products\\");
956     lstrcatA(keypath, prod_squashed);
957     lstrcatA(keypath, "\\InstallProperties");
958
959     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
960     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
961
962     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
963     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
964
965     state = MAGIC_ERROR;
966     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
968     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
969
970     RegDeleteValueA(prodkey, "LocalPackage");
971     RegDeleteValueA(prodkey, "ManagedLocalPackage");
972     RegDeleteKeyA(prodkey, "");
973     RegDeleteValueA(compkey, prod_squashed);
974     RegDeleteKeyA(compkey, "");
975     RegCloseKey(prodkey);
976     RegCloseKey(compkey);
977 }
978
979 static void test_MsiGetComponentPath(void)
980 {
981     HKEY compkey, prodkey, installprop;
982     CHAR prodcode[MAX_PATH];
983     CHAR prod_squashed[MAX_PATH];
984     CHAR component[MAX_PATH];
985     CHAR comp_base85[MAX_PATH];
986     CHAR comp_squashed[MAX_PATH];
987     CHAR keypath[MAX_PATH];
988     CHAR path[MAX_PATH];
989     INSTALLSTATE state;
990     LPSTR usersid;
991     DWORD size, val;
992     LONG res;
993
994     create_test_guid(prodcode, prod_squashed);
995     compose_base85_guid(component, comp_base85, comp_squashed);
996     get_user_sid(&usersid);
997
998     /* NULL szProduct */
999     size = MAX_PATH;
1000     state = MsiGetComponentPathA(NULL, component, path, &size);
1001     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1002     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1003
1004     /* NULL szComponent */
1005     size = MAX_PATH;
1006     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
1007     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1008     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1009
1010     /* NULL lpPathBuf */
1011     size = MAX_PATH;
1012     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
1013     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1014     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1015
1016     /* NULL pcchBuf */
1017     size = MAX_PATH;
1018     state = MsiGetComponentPathA(prodcode, component, path, NULL);
1019     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1020     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1021
1022     /* all params valid */
1023     size = MAX_PATH;
1024     state = MsiGetComponentPathA(prodcode, component, path, &size);
1025     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1026     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1027
1028     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1029     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1030     lstrcatA(keypath, comp_squashed);
1031
1032     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1033     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1034
1035     /* local system component key exists */
1036     size = MAX_PATH;
1037     state = MsiGetComponentPathA(prodcode, component, path, &size);
1038     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1039     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1040
1041     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1042     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1043
1044     /* product value exists */
1045     size = MAX_PATH;
1046     state = MsiGetComponentPathA(prodcode, component, path, &size);
1047     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1048     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1049     ok(size == 10, "Expected 10, got %d\n", size);
1050
1051     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1052     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
1053     lstrcatA(keypath, prod_squashed);
1054     lstrcatA(keypath, "\\InstallProperties");
1055
1056     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &installprop);
1057     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1058
1059     val = 1;
1060     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
1061     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1062
1063     /* install properties key exists */
1064     size = MAX_PATH;
1065     state = MsiGetComponentPathA(prodcode, component, path, &size);
1066     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1067     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1068     ok(size == 10, "Expected 10, got %d\n", size);
1069
1070     create_file("C:\\imapath", "C:\\imapath", 11);
1071
1072     /* file exists */
1073     size = MAX_PATH;
1074     state = MsiGetComponentPathA(prodcode, component, path, &size);
1075     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1076     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1077     ok(size == 10, "Expected 10, got %d\n", size);
1078
1079     RegDeleteValueA(compkey, prod_squashed);
1080     RegDeleteKeyA(compkey, "");
1081     RegDeleteValueA(installprop, "WindowsInstaller");
1082     RegDeleteKeyA(installprop, "");
1083     RegCloseKey(compkey);
1084     RegCloseKey(installprop);
1085     DeleteFileA("C:\\imapath");
1086
1087     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1088     lstrcatA(keypath, "Installer\\UserData\\");
1089     lstrcatA(keypath, usersid);
1090     lstrcatA(keypath, "\\Components\\");
1091     lstrcatA(keypath, comp_squashed);
1092
1093     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1095
1096     /* user managed component key exists */
1097     size = MAX_PATH;
1098     state = MsiGetComponentPathA(prodcode, component, path, &size);
1099     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1100     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1101
1102     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1103     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1104
1105     /* product value exists */
1106     size = MAX_PATH;
1107     state = MsiGetComponentPathA(prodcode, component, path, &size);
1108     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1109     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1110     ok(size == 10, "Expected 10, got %d\n", size);
1111
1112     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1113     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
1114     lstrcatA(keypath, prod_squashed);
1115     lstrcatA(keypath, "\\InstallProperties");
1116
1117     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &installprop);
1118     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1119
1120     val = 1;
1121     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
1122     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1123
1124     /* install properties key exists */
1125     size = MAX_PATH;
1126     state = MsiGetComponentPathA(prodcode, component, path, &size);
1127     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1128     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1129     ok(size == 10, "Expected 10, got %d\n", size);
1130
1131     create_file("C:\\imapath", "C:\\imapath", 11);
1132
1133     /* file exists */
1134     size = MAX_PATH;
1135     state = MsiGetComponentPathA(prodcode, component, path, &size);
1136     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1137     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1138     ok(size == 10, "Expected 10, got %d\n", size);
1139
1140     RegDeleteValueA(compkey, prod_squashed);
1141     RegDeleteKeyA(compkey, "");
1142     RegDeleteValueA(installprop, "WindowsInstaller");
1143     RegDeleteKeyA(installprop, "");
1144     RegCloseKey(compkey);
1145     RegCloseKey(installprop);
1146     DeleteFileA("C:\\imapath");
1147
1148     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1149     lstrcatA(keypath, "Installer\\Managed\\");
1150     lstrcatA(keypath, usersid);
1151     lstrcatA(keypath, "\\Installer\\Products\\");
1152     lstrcatA(keypath, prod_squashed);
1153
1154     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1156
1157     /* user managed product key exists */
1158     size = MAX_PATH;
1159     state = MsiGetComponentPathA(prodcode, component, path, &size);
1160     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1161     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1162
1163     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1164     lstrcatA(keypath, "Installer\\UserData\\");
1165     lstrcatA(keypath, usersid);
1166     lstrcatA(keypath, "\\Components\\");
1167     lstrcatA(keypath, comp_squashed);
1168
1169     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1170     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1171
1172     /* user managed component key exists */
1173     size = MAX_PATH;
1174     state = MsiGetComponentPathA(prodcode, component, path, &size);
1175     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1176     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1177
1178     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1179     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1180
1181     /* product value exists */
1182     size = MAX_PATH;
1183     state = MsiGetComponentPathA(prodcode, component, path, &size);
1184     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1185     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1186     ok(size == 10, "Expected 10, got %d\n", size);
1187
1188     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1189     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
1190     lstrcatA(keypath, prod_squashed);
1191     lstrcatA(keypath, "\\InstallProperties");
1192
1193     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &installprop);
1194     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1195
1196     val = 1;
1197     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
1198     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1199
1200     /* install properties key exists */
1201     size = MAX_PATH;
1202     state = MsiGetComponentPathA(prodcode, component, path, &size);
1203     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1204     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1205     ok(size == 10, "Expected 10, got %d\n", size);
1206
1207     create_file("C:\\imapath", "C:\\imapath", 11);
1208
1209     /* file exists */
1210     size = MAX_PATH;
1211     state = MsiGetComponentPathA(prodcode, component, path, &size);
1212     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1213     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1214     ok(size == 10, "Expected 10, got %d\n", size);
1215
1216     RegDeleteValueA(compkey, prod_squashed);
1217     RegDeleteKeyA(prodkey, "");
1218     RegDeleteKeyA(compkey, "");
1219     RegDeleteValueA(installprop, "WindowsInstaller");
1220     RegDeleteKeyA(installprop, "");
1221     RegCloseKey(prodkey);
1222     RegCloseKey(compkey);
1223     RegCloseKey(installprop);
1224     DeleteFileA("C:\\imapath");
1225
1226     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1227     lstrcatA(keypath, prod_squashed);
1228
1229     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
1230     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1231
1232     /* user unmanaged product key exists */
1233     size = MAX_PATH;
1234     state = MsiGetComponentPathA(prodcode, component, path, &size);
1235     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1236     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1237
1238     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1239     lstrcatA(keypath, "Installer\\UserData\\");
1240     lstrcatA(keypath, usersid);
1241     lstrcatA(keypath, "\\Components\\");
1242     lstrcatA(keypath, comp_squashed);
1243
1244     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1245     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1246
1247     /* user unmanaged component key exists */
1248     size = MAX_PATH;
1249     state = MsiGetComponentPathA(prodcode, component, path, &size);
1250     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1251     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1252
1253     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1254     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1255
1256     /* product value exists */
1257     size = MAX_PATH;
1258     state = MsiGetComponentPathA(prodcode, component, path, &size);
1259     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1260     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1261     ok(size == 10, "Expected 10, got %d\n", size);
1262
1263     create_file("C:\\imapath", "C:\\imapath", 11);
1264
1265     /* file exists */
1266     size = MAX_PATH;
1267     state = MsiGetComponentPathA(prodcode, component, path, &size);
1268     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1269     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1270     ok(size == 10, "Expected 10, got %d\n", size);
1271
1272     RegDeleteValueA(compkey, prod_squashed);
1273     RegDeleteKeyA(prodkey, "");
1274     RegDeleteKeyA(compkey, "");
1275     RegCloseKey(prodkey);
1276     RegCloseKey(compkey);
1277     RegCloseKey(installprop);
1278     DeleteFileA("C:\\imapath");
1279
1280     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1281     lstrcatA(keypath, prod_squashed);
1282
1283     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1284     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1285
1286     /* local classes product key exists */
1287     size = MAX_PATH;
1288     state = MsiGetComponentPathA(prodcode, component, path, &size);
1289     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1290     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1291
1292     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1293     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1294     lstrcatA(keypath, comp_squashed);
1295
1296     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1297     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1298
1299     /* local user component key exists */
1300     size = MAX_PATH;
1301     state = MsiGetComponentPathA(prodcode, component, path, &size);
1302     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1303     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
1304
1305     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1306     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1307
1308     /* product value exists */
1309     size = MAX_PATH;
1310     state = MsiGetComponentPathA(prodcode, component, path, &size);
1311     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1312     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1313     ok(size == 10, "Expected 10, got %d\n", size);
1314
1315     create_file("C:\\imapath", "C:\\imapath", 11);
1316
1317     /* file exists */
1318     size = MAX_PATH;
1319     state = MsiGetComponentPathA(prodcode, component, path, &size);
1320     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1321     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
1322     ok(size == 10, "Expected 10, got %d\n", size);
1323
1324     RegDeleteValueA(compkey, prod_squashed);
1325     RegDeleteKeyA(prodkey, "");
1326     RegDeleteKeyA(compkey, "");
1327     RegCloseKey(prodkey);
1328     RegCloseKey(compkey);
1329     DeleteFileA("C:\\imapath");
1330 }
1331
1332 static void test_MsiGetProductCode(void)
1333 {
1334     HKEY compkey, prodkey;
1335     CHAR prodcode[MAX_PATH];
1336     CHAR prod_squashed[MAX_PATH];
1337     CHAR prodcode2[MAX_PATH];
1338     CHAR prod2_squashed[MAX_PATH];
1339     CHAR component[MAX_PATH];
1340     CHAR comp_base85[MAX_PATH];
1341     CHAR comp_squashed[MAX_PATH];
1342     CHAR keypath[MAX_PATH];
1343     CHAR product[MAX_PATH];
1344     LPSTR usersid;
1345     LONG res;
1346     UINT r;
1347
1348     create_test_guid(prodcode, prod_squashed);
1349     create_test_guid(prodcode2, prod2_squashed);
1350     compose_base85_guid(component, comp_base85, comp_squashed);
1351     get_user_sid(&usersid);
1352
1353     /* szComponent is NULL */
1354     lstrcpyA(product, "prod");
1355     r = MsiGetProductCodeA(NULL, product);
1356     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1357     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1358
1359     /* szComponent is empty */
1360     lstrcpyA(product, "prod");
1361     r = MsiGetProductCodeA("", product);
1362     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1363     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1364
1365     /* garbage szComponent */
1366     lstrcpyA(product, "prod");
1367     r = MsiGetProductCodeA("garbage", product);
1368     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1369     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1370
1371     /* guid without brackets */
1372     lstrcpyA(product, "prod");
1373     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
1374     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1375     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1376
1377     /* guid with brackets */
1378     lstrcpyA(product, "prod");
1379     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
1380     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1381     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1382
1383     /* same length as guid, but random */
1384     lstrcpyA(product, "prod");
1385     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
1386     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1387     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1388
1389     /* all params correct, szComponent not published */
1390     lstrcpyA(product, "prod");
1391     r = MsiGetProductCodeA(component, product);
1392     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1393     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1394
1395     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1396     lstrcatA(keypath, "Installer\\UserData\\");
1397     lstrcatA(keypath, usersid);
1398     lstrcatA(keypath, "\\Components\\");
1399     lstrcatA(keypath, comp_squashed);
1400
1401     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1402     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1403
1404     /* user unmanaged component key exists */
1405     lstrcpyA(product, "prod");
1406     r = MsiGetProductCodeA(component, product);
1407     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1408     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1409
1410     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1412
1413     /* product value exists */
1414     lstrcpyA(product, "prod");
1415     r = MsiGetProductCodeA(component, product);
1416     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1417     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1418
1419     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1420     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1421
1422     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1423     lstrcatA(keypath, "Installer\\Managed\\");
1424     lstrcatA(keypath, usersid);
1425     lstrcatA(keypath, "\\Installer\\Products\\");
1426     lstrcatA(keypath, prod_squashed);
1427
1428     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1429     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1430
1431     /* user managed product key of first product exists */
1432     lstrcpyA(product, "prod");
1433     r = MsiGetProductCodeA(component, product);
1434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1435     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1436
1437     RegDeleteKeyA(prodkey, "");
1438     RegCloseKey(prodkey);
1439
1440     RegDeleteKeyA(prodkey, "");
1441     RegCloseKey(prodkey);
1442
1443     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1444     lstrcatA(keypath, prod_squashed);
1445
1446     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
1447     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1448
1449     /* user unmanaged product key exists */
1450     lstrcpyA(product, "prod");
1451     r = MsiGetProductCodeA(component, product);
1452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1453     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1454
1455     RegDeleteKeyA(prodkey, "");
1456     RegCloseKey(prodkey);
1457
1458     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1459     lstrcatA(keypath, prod_squashed);
1460
1461     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1462     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1463
1464     /* local classes product key exists */
1465     lstrcpyA(product, "prod");
1466     r = MsiGetProductCodeA(component, product);
1467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1468     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1469
1470     RegDeleteKeyA(prodkey, "");
1471     RegCloseKey(prodkey);
1472
1473     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1474     lstrcatA(keypath, "Installer\\Managed\\");
1475     lstrcatA(keypath, usersid);
1476     lstrcatA(keypath, "\\Installer\\Products\\");
1477     lstrcatA(keypath, prod2_squashed);
1478
1479     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1480     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1481
1482     /* user managed product key of second product exists */
1483     lstrcpyA(product, "prod");
1484     r = MsiGetProductCodeA(component, product);
1485     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1486     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
1487
1488     RegDeleteKeyA(prodkey, "");
1489     RegCloseKey(prodkey);
1490     RegDeleteValueA(compkey, prod_squashed);
1491     RegDeleteValueA(compkey, prod2_squashed);
1492     RegDeleteKeyA(compkey, "");
1493     RegCloseKey(compkey);
1494
1495     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1496     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1497     lstrcatA(keypath, comp_squashed);
1498
1499     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1501
1502     /* local user component key exists */
1503     lstrcpyA(product, "prod");
1504     r = MsiGetProductCodeA(component, product);
1505     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1506     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
1507
1508     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1509     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1510
1511     /* product value exists */
1512     lstrcpyA(product, "prod");
1513     r = MsiGetProductCodeA(component, product);
1514     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1515     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1516
1517     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1518     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1519
1520     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1521     lstrcatA(keypath, "Installer\\Managed\\");
1522     lstrcatA(keypath, usersid);
1523     lstrcatA(keypath, "\\Installer\\Products\\");
1524     lstrcatA(keypath, prod_squashed);
1525
1526     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1527     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1528
1529     /* user managed product key of first product exists */
1530     lstrcpyA(product, "prod");
1531     r = MsiGetProductCodeA(component, product);
1532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1533     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1534
1535     RegDeleteKeyA(prodkey, "");
1536     RegCloseKey(prodkey);
1537
1538     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1539     lstrcatA(keypath, prod_squashed);
1540
1541     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
1542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1543
1544     /* user unmanaged product key exists */
1545     lstrcpyA(product, "prod");
1546     r = MsiGetProductCodeA(component, product);
1547     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1548     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1549
1550     RegDeleteKeyA(prodkey, "");
1551     RegCloseKey(prodkey);
1552
1553     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1554     lstrcatA(keypath, prod_squashed);
1555
1556     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1557     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1558
1559     /* local classes product key exists */
1560     lstrcpyA(product, "prod");
1561     r = MsiGetProductCodeA(component, product);
1562     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1563     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1564
1565     RegDeleteKeyA(prodkey, "");
1566     RegCloseKey(prodkey);
1567
1568     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1569     lstrcatA(keypath, "Installer\\Managed\\");
1570     lstrcatA(keypath, usersid);
1571     lstrcatA(keypath, "\\Installer\\Products\\");
1572     lstrcatA(keypath, prod2_squashed);
1573
1574     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1575     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1576
1577     /* user managed product key of second product exists */
1578     lstrcpyA(product, "prod");
1579     r = MsiGetProductCodeA(component, product);
1580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1581     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
1582
1583     RegDeleteKeyA(prodkey, "");
1584     RegCloseKey(prodkey);
1585     RegDeleteValueA(compkey, prod_squashed);
1586     RegDeleteValueA(compkey, prod2_squashed);
1587     RegDeleteKeyA(compkey, "");
1588     RegCloseKey(compkey);
1589 }
1590
1591 static void test_MsiEnumClients(void)
1592 {
1593     HKEY compkey;
1594     CHAR prodcode[MAX_PATH];
1595     CHAR prod_squashed[MAX_PATH];
1596     CHAR prodcode2[MAX_PATH];
1597     CHAR prod2_squashed[MAX_PATH];
1598     CHAR component[MAX_PATH];
1599     CHAR comp_base85[MAX_PATH];
1600     CHAR comp_squashed[MAX_PATH];
1601     CHAR product[MAX_PATH];
1602     CHAR keypath[MAX_PATH];
1603     LPSTR usersid;
1604     LONG res;
1605     UINT r;
1606
1607     create_test_guid(prodcode, prod_squashed);
1608     create_test_guid(prodcode2, prod2_squashed);
1609     compose_base85_guid(component, comp_base85, comp_squashed);
1610     get_user_sid(&usersid);
1611
1612     /* NULL szComponent */
1613     product[0] = '\0';
1614     r = MsiEnumClientsA(NULL, 0, product);
1615     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1616     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1617
1618     /* empty szComponent */
1619     product[0] = '\0';
1620     r = MsiEnumClientsA("", 0, product);
1621     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1622     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1623
1624     /* NULL lpProductBuf */
1625     r = MsiEnumClientsA(component, 0, NULL);
1626     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1627
1628     /* all params correct, component missing */
1629     product[0] = '\0';
1630     r = MsiEnumClientsA(component, 0, product);
1631     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1632     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1633
1634     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1635     lstrcatA(keypath, "Installer\\UserData\\");
1636     lstrcatA(keypath, usersid);
1637     lstrcatA(keypath, "\\Components\\");
1638     lstrcatA(keypath, comp_squashed);
1639
1640     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1641     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1642
1643     /* user unmanaged component key exists */
1644     product[0] = '\0';
1645     r = MsiEnumClientsA(component, 0, product);
1646     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1647     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1648
1649     /* index > 0, no products exist */
1650     product[0] = '\0';
1651     r = MsiEnumClientsA(component, 1, product);
1652     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1653     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1654
1655     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1657
1658     /* product value exists */
1659     r = MsiEnumClientsA(component, 0, product);
1660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1661     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1662
1663     /* try index 0 again */
1664     product[0] = '\0';
1665     r = MsiEnumClientsA(component, 0, product);
1666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1667     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1668
1669     /* try index 1, second product value does not exist */
1670     product[0] = '\0';
1671     r = MsiEnumClientsA(component, 1, product);
1672     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1673     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1674
1675     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1677
1678     /* try index 1, second product value does exist */
1679     product[0] = '\0';
1680     r = MsiEnumClientsA(component, 1, product);
1681     todo_wine
1682     {
1683         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1684         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1685     }
1686
1687     /* start the enumeration over */
1688     product[0] = '\0';
1689     r = MsiEnumClientsA(component, 0, product);
1690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1691     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1692        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1693
1694     /* correctly query second product */
1695     product[0] = '\0';
1696     r = MsiEnumClientsA(component, 1, product);
1697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1698     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1699        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1700
1701     RegDeleteValueA(compkey, prod_squashed);
1702     RegDeleteValueA(compkey, prod2_squashed);
1703     RegDeleteKeyA(compkey, "");
1704     RegCloseKey(compkey);
1705
1706     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
1707     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
1708     lstrcatA(keypath, comp_squashed);
1709
1710     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey);
1711     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1712
1713     /* user local component key exists */
1714     product[0] = '\0';
1715     r = MsiEnumClientsA(component, 0, product);
1716     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1717     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1718
1719     /* index > 0, no products exist */
1720     product[0] = '\0';
1721     r = MsiEnumClientsA(component, 1, product);
1722     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1723     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1724
1725     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
1726     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1727
1728     /* product value exists */
1729     product[0] = '\0';
1730     r = MsiEnumClientsA(component, 0, product);
1731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1732     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
1733
1734     /* try index 0 again */
1735     product[0] = '\0';
1736     r = MsiEnumClientsA(component, 0, product);
1737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1738
1739     /* try index 1, second product value does not exist */
1740     product[0] = '\0';
1741     r = MsiEnumClientsA(component, 1, product);
1742     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1743     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1744
1745     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
1746     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1747
1748     /* try index 1, second product value does exist */
1749     product[0] = '\0';
1750     r = MsiEnumClientsA(component, 1, product);
1751     todo_wine
1752     {
1753         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1754         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
1755     }
1756
1757     /* start the enumeration over */
1758     product[0] = '\0';
1759     r = MsiEnumClientsA(component, 0, product);
1760     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1761     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1762        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1763
1764     /* correctly query second product */
1765     product[0] = '\0';
1766     r = MsiEnumClientsA(component, 1, product);
1767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1768     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
1769        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
1770
1771     RegDeleteValueA(compkey, prod_squashed);
1772     RegDeleteValueA(compkey, prod2_squashed);
1773     RegDeleteKeyA(compkey, "");
1774     RegCloseKey(compkey);
1775 }
1776
1777 START_TEST(msi)
1778 {
1779     init_functionpointers();
1780
1781     test_usefeature();
1782     test_null();
1783     test_getcomponentpath();
1784     test_MsiGetFileHash();
1785     test_MsiQueryProductState();
1786     test_MsiQueryFeatureState();
1787     test_MsiQueryComponentState();
1788     test_MsiGetComponentPath();
1789     test_MsiGetProductCode();
1790     test_MsiEnumClients();
1791 }