msi: Validate the szProduct parameter of MsiSourceListSetInfo.
[wine] / dlls / msi / tests / source.c
1 /*
2  * Tests for MSI Source functions
3  *
4  * Copyright (C) 2006 James Hawkins
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
25 #include <windows.h>
26 #include <msiquery.h>
27 #include <msidefs.h>
28 #include <msi.h>
29 #include <sddl.h>
30
31 #include "wine/test.h"
32
33 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
34 static UINT (WINAPI *pMsiSourceListGetInfoA)
35     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
36 static UINT (WINAPI *pMsiSourceListAddSourceExA)
37     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, DWORD);
38
39 static void init_functionpointers(void)
40 {
41     HMODULE hmsi = GetModuleHandleA("msi.dll");
42     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
43
44 #define GET_PROC(dll, func) \
45     p ## func = (void *)GetProcAddress(dll, #func); \
46     if(!p ## func) \
47       trace("GetProcAddress(%s) failed\n", #func);
48
49     GET_PROC(hmsi, MsiSourceListAddSourceExA)
50     GET_PROC(hmsi, MsiSourceListGetInfoA)
51
52     GET_PROC(hadvapi32, ConvertSidToStringSidA)
53
54 #undef GET_PROC
55 }
56
57 /* copied from dlls/msi/registry.c */
58 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
59 {
60     DWORD i,n=1;
61     GUID guid;
62
63     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
64         return FALSE;
65
66     for(i=0; i<8; i++)
67         out[7-i] = in[n++];
68     n++;
69     for(i=0; i<4; i++)
70         out[11-i] = in[n++];
71     n++;
72     for(i=0; i<4; i++)
73         out[15-i] = in[n++];
74     n++;
75     for(i=0; i<2; i++)
76     {
77         out[17+i*2] = in[n++];
78         out[16+i*2] = in[n++];
79     }
80     n++;
81     for( ; i<8; i++)
82     {
83         out[17+i*2] = in[n++];
84         out[16+i*2] = in[n++];
85     }
86     out[32]=0;
87     return TRUE;
88 }
89
90 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
91 {
92     WCHAR guidW[MAX_PATH];
93     WCHAR squashedW[MAX_PATH];
94     GUID guid;
95     HRESULT hr;
96     int size;
97
98     hr = CoCreateGuid(&guid);
99     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
100
101     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
102     ok(size == 39, "Expected 39, got %d\n", hr);
103
104     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
105     squash_guid(guidW, squashedW);
106     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
107 }
108
109 static void get_user_sid(LPSTR *usersid)
110 {
111     HANDLE token;
112     BYTE buf[1024];
113     DWORD size;
114     PTOKEN_USER user;
115
116     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
117     size = sizeof(buf);
118     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
119     user = (PTOKEN_USER)buf;
120     pConvertSidToStringSidA(user->User.Sid, usersid);
121 }
122
123 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
124 {
125     char val[MAX_PATH];
126     DWORD size, type;
127     LONG res;
128
129     size = MAX_PATH;
130     val[0] = '\0';
131     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
132
133     if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
134     {
135         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
136         return;
137     }
138
139     if (!expected)
140         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
141     else
142     {
143         if (bcase)
144             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
145         else
146             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
147     }
148 }
149
150 #define CHECK_REG_STR(prodkey, name, expected) \
151     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
152
153 static void test_MsiSourceListGetInfo(void)
154 {
155     CHAR prodcode[MAX_PATH];
156     CHAR prod_squashed[MAX_PATH];
157     CHAR keypath[MAX_PATH*2];
158     CHAR value[MAX_PATH];
159     LPSTR usersid;
160     LPCSTR data;
161     LONG res;
162     UINT r;
163     HKEY userkey, hkey;
164     DWORD size;
165
166     if (!pMsiSourceListGetInfoA)
167     {
168         skip("Skipping MsiSourceListGetInfoA tests\n");
169         return;
170     }
171
172     create_test_guid(prodcode, prod_squashed);
173     get_user_sid(&usersid);
174
175     /* NULL szProductCodeOrPatchCode */
176     r = pMsiSourceListGetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
177                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
178     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
179
180     /* empty szProductCodeOrPatchCode */
181     r = pMsiSourceListGetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
182                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
183     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
184
185     /* garbage szProductCodeOrPatchCode */
186     r = pMsiSourceListGetInfoA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
187                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
188     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
189
190     /*  szProductCodeOrPatchCode */
191     r = pMsiSourceListGetInfoA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
192                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
193     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
194
195     /* guid without brackets */
196     r = pMsiSourceListGetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
197                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
198     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
199
200     /* guid with brackets */
201     r = pMsiSourceListGetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
202                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
203     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
204
205     /* same length as guid, but random */
206     r = pMsiSourceListGetInfoA("ADKD-2KSDFF2-DKK1KNFJASD9GLKWME-1I3KAD", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
207                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
208     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
209
210     /* invalid context */
211     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_NONE,
212                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
213     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
214
215     /* another invalid context */
216     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALLUSERMANAGED,
217                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
218     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
219
220     /* yet another invalid context */
221     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALL,
222                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
223     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
224
225     /* mix two valid contexts */
226     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED | MSIINSTALLCONTEXT_USERUNMANAGED,
227                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
228     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
229
230     /* invalid option */
231     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
232                               4, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
233     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
234
235     /* NULL property */
236     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
237                               MSICODE_PRODUCT, NULL, NULL, NULL);
238     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
239
240     /* empty property */
241     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
242                               MSICODE_PRODUCT, "", NULL, NULL);
243     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
244
245     /* value is non-NULL while size is NULL */
246     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
247                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, NULL);
248     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
249
250     /* size is non-NULL while value is NULL */
251     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
252                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
253     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
254
255     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
256     lstrcatA(keypath, prod_squashed);
257
258     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
259     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
260
261     /* user product key exists */
262     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
263                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
264     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
265
266     res = RegCreateKeyA(userkey, "SourceList", &hkey);
267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
268
269     /* SourceList key exists */
270     size = 0xdeadbeef;
271     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
272                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
274     ok(size == 0, "Expected 0, got %d\n", size);
275
276     data = "msitest.msi";
277     res = RegSetValueExA(hkey, "PackageName", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1);
278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
279
280     /* PackageName value exists */
281     size = 0xdeadbeef;
282     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
283                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
285     ok(size == 11, "Expected 11, got %d\n", size);
286
287     /* read the value, don't change size */
288     lstrcpyA(value, "aaa");
289     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
290                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
291     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
292     ok(!lstrcmpA(value, "aaa"), "Expected 'aaa', got %s\n", value);
293     ok(size == 11, "Expected 11, got %d\n", size);
294
295     /* read the value, fix size */
296     size++;
297     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
298                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
300     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
301     ok(size == 11, "Expected 11, got %d\n", size);
302
303     /* empty property now that product key exists */
304     size = 0xdeadbeef;
305     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
306                               MSICODE_PRODUCT, "", NULL, &size);
307     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
308     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
309
310     /* nonexistent property now that product key exists */
311     size = 0xdeadbeef;
312     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
313                               MSICODE_PRODUCT, "nonexistent", NULL, &size);
314     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
315     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
316
317     data = "tester";
318     res = RegSetValueExA(hkey, "nonexistent", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1);
319     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
320
321     /* nonexistent property now that nonexistent value exists */
322     size = 0xdeadbeef;
323     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
324                               MSICODE_PRODUCT, "nonexistent", NULL, &size);
325     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
326     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
327
328     /* invalid option now that product key exists */
329     size = 0xdeadbeef;
330     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
331                               4, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
333     ok(size == 11, "Expected 11, got %d\n", size);
334
335     RegDeleteValueA(hkey, "nonexistent");
336     RegDeleteValueA(hkey, "PackageName");
337     RegDeleteKeyA(hkey, "");
338     RegDeleteKeyA(userkey, "");
339     RegCloseKey(hkey);
340     RegCloseKey(userkey);
341
342     /* try a patch */
343     size = 0xdeadbeef;
344     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
345                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
346     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
347     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
348
349     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Patches\\");
350     lstrcatA(keypath, prod_squashed);
351
352     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
353     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
354
355     /* patch key exists
356      * NOTE: using prodcode guid, but it really doesn't matter
357      */
358     size = 0xdeadbeef;
359     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
360                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
361     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
362     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
363
364     res = RegCreateKeyA(userkey, "SourceList", &hkey);
365     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
366
367     /* SourceList key exists */
368     size = 0xdeadbeef;
369     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
370                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
372     ok(size == 0, "Expected 0, got %d\n", size);
373
374     RegDeleteKeyA(hkey, "");
375     RegDeleteKeyA(userkey, "");
376     RegCloseKey(hkey);
377     RegCloseKey(userkey);
378 }
379
380 static void test_MsiSourceListAddSourceEx(void)
381 {
382     CHAR prodcode[MAX_PATH];
383     CHAR prod_squashed[MAX_PATH];
384     CHAR keypath[MAX_PATH*2];
385     CHAR value[MAX_PATH];
386     LPSTR usersid;
387     LONG res;
388     UINT r;
389     HKEY prodkey, userkey, hkey;
390     HKEY url, net;
391     DWORD size;
392
393     if (!pMsiSourceListAddSourceExA)
394     {
395         skip("Skipping MsiSourceListAddSourceExA tests\n");
396         return;
397     }
398
399     create_test_guid(prodcode, prod_squashed);
400     get_user_sid(&usersid);
401
402     /* GetLastError is not set by the function */
403
404     /* NULL szProductCodeOrPatchCode */
405     r = pMsiSourceListAddSourceExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
406                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
407     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
408
409     /* empty szProductCodeOrPatchCode */
410     r = pMsiSourceListAddSourceExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
411                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
412     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
413
414     /* garbage szProductCodeOrPatchCode */
415     r = pMsiSourceListAddSourceExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
416                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
417     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
418
419     /* guid without brackets */
420     r = pMsiSourceListAddSourceExA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid,
421                                   MSIINSTALLCONTEXT_USERUNMANAGED,
422                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
423     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
424
425     /* guid with brackets */
426     r = pMsiSourceListAddSourceExA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid,
427                                   MSIINSTALLCONTEXT_USERUNMANAGED,
428                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
429     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
430
431     /* MSIINSTALLCONTEXT_USERUNMANAGED */
432
433     r = pMsiSourceListAddSourceExA(prodcode, usersid,
434                                   MSIINSTALLCONTEXT_USERUNMANAGED,
435                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
436     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
437
438     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
439     lstrcatA(keypath, prod_squashed);
440
441     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
443
444     /* user product key exists */
445     r = pMsiSourceListAddSourceExA(prodcode, usersid,
446                                   MSIINSTALLCONTEXT_USERUNMANAGED,
447                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
448     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
449
450     res = RegCreateKeyA(userkey, "SourceList", &url);
451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
452     RegCloseKey(url);
453
454     /* SourceList key exists */
455     r = pMsiSourceListAddSourceExA(prodcode, usersid,
456                                   MSIINSTALLCONTEXT_USERUNMANAGED,
457                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
459
460     res = RegOpenKeyA(userkey, "SourceList\\URL", &url);
461     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
462
463     size = MAX_PATH;
464     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
465     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
466     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
467     ok(size == 11, "Expected 11, got %d\n", size);
468
469     /* add another source, index 0 */
470     r = pMsiSourceListAddSourceExA(prodcode, usersid,
471                                   MSIINSTALLCONTEXT_USERUNMANAGED,
472                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0);
473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
474
475     size = MAX_PATH;
476     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
478     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
479     ok(size == 11, "Expected 11, got %d\n", size);
480
481     size = MAX_PATH;
482     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
483     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
484     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
485     ok(size == 9, "Expected 9, got %d\n", size);
486
487     /* add another source, index 1 */
488     r = pMsiSourceListAddSourceExA(prodcode, usersid,
489                                   MSIINSTALLCONTEXT_USERUNMANAGED,
490                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "third/", 1);
491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
492
493     size = MAX_PATH;
494     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
495     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
496     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
497     ok(size == 7, "Expected 7, got %d\n", size);
498
499     size = MAX_PATH;
500     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
501     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
502     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
503     ok(size == 11, "Expected 11, got %d\n", size);
504
505     size = MAX_PATH;
506     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
507     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
508     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
509     ok(size == 9, "Expected 9, got %d\n", size);
510
511     /* add another source, index > N */
512     r = pMsiSourceListAddSourceExA(prodcode, usersid,
513                                   MSIINSTALLCONTEXT_USERUNMANAGED,
514                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "last/", 5);
515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
516
517     size = MAX_PATH;
518     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
519     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
520     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
521     ok(size == 7, "Expected 7, got %d\n", size);
522
523     size = MAX_PATH;
524     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
526     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
527     ok(size == 11, "Expected 11, got %d\n", size);
528
529     size = MAX_PATH;
530     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
531     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
532     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
533     ok(size == 9, "Expected 9, got %d\n", size);
534
535     size = MAX_PATH;
536     res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
537     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
538     ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value);
539     ok(size == 6, "Expected 6, got %d\n", size);
540
541     /* just MSISOURCETYPE_NETWORK */
542     r = pMsiSourceListAddSourceExA(prodcode, usersid,
543                                   MSIINSTALLCONTEXT_USERUNMANAGED,
544                                   MSISOURCETYPE_NETWORK, "source", 0);
545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
546
547     res = RegOpenKeyA(userkey, "SourceList\\Net", &net);
548     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
549
550     size = MAX_PATH;
551     res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size);
552     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
553     ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value);
554     ok(size == 8, "Expected 8, got %d\n", size);
555
556     /* just MSISOURCETYPE_URL */
557     r = pMsiSourceListAddSourceExA(prodcode, usersid,
558                                   MSIINSTALLCONTEXT_USERUNMANAGED,
559                                   MSISOURCETYPE_URL, "source", 0);
560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
561
562     size = MAX_PATH;
563     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
564     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
565     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
566     ok(size == 7, "Expected 7, got %d\n", size);
567
568     size = MAX_PATH;
569     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
570     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
571     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
572     ok(size == 11, "Expected 11, got %d\n", size);
573
574     size = MAX_PATH;
575     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
577     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
578     ok(size == 9, "Expected 9, got %d\n", size);
579
580     size = MAX_PATH;
581     res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
582     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
583     ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value);
584     ok(size == 6, "Expected 6, got %d\n", size);
585
586     size = MAX_PATH;
587     res = RegQueryValueExA(url, "5", NULL, NULL, (LPBYTE)value, &size);
588     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
589     ok(!lstrcmpA(value, "source/"), "Expected 'source/', got %s\n", value);
590     ok(size == 8, "Expected 8, got %d\n", size);
591
592     /* NULL szUserSid */
593     r = pMsiSourceListAddSourceExA(prodcode, NULL,
594                                   MSIINSTALLCONTEXT_USERUNMANAGED,
595                                   MSISOURCETYPE_NETWORK, "nousersid", 0);
596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
597
598     size = MAX_PATH;
599     res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size);
600     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
601     ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value);
602     ok(size == 8, "Expected 8, got %d\n", size);
603
604     size = MAX_PATH;
605     res = RegQueryValueExA(net, "2", NULL, NULL, (LPBYTE)value, &size);
606     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
607     ok(!lstrcmpA(value, "nousersid\\"), "Expected 'nousersid\\', got %s\n", value);
608     ok(size == 11, "Expected 11, got %d\n", size);
609
610     /* invalid options, must have source type */
611     r = pMsiSourceListAddSourceExA(prodcode, usersid,
612                                   MSIINSTALLCONTEXT_USERUNMANAGED,
613                                   MSICODE_PRODUCT, "source", 0);
614     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
615
616     r = pMsiSourceListAddSourceExA(prodcode, usersid,
617                                   MSIINSTALLCONTEXT_USERUNMANAGED,
618                                   MSICODE_PATCH, "source", 0);
619     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
620
621     /* NULL szSource */
622     r = pMsiSourceListAddSourceExA(prodcode, usersid,
623                                   MSIINSTALLCONTEXT_USERUNMANAGED,
624                                   MSISOURCETYPE_URL, NULL, 1);
625     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
626
627     /* empty szSource */
628     r = pMsiSourceListAddSourceExA(prodcode, usersid,
629                                   MSIINSTALLCONTEXT_USERUNMANAGED,
630                                   MSISOURCETYPE_URL, "", 1);
631     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
632
633     /* MSIINSTALLCONTEXT_USERMANAGED, non-NULL szUserSid */
634
635     r = pMsiSourceListAddSourceExA(prodcode, usersid,
636                                   MSIINSTALLCONTEXT_USERMANAGED,
637                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
638     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
639
640     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
641     lstrcatA(keypath, usersid);
642     lstrcatA(keypath, "\\Installer\\Products\\");
643     lstrcatA(keypath, prod_squashed);
644
645     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
647
648     /* product key exists */
649     r = pMsiSourceListAddSourceExA(prodcode, usersid,
650                                   MSIINSTALLCONTEXT_USERMANAGED,
651                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
652     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
653
654     res = RegCreateKeyA(prodkey, "SourceList", &hkey);
655     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
656     RegCloseKey(hkey);
657
658     /* SourceList exists */
659     r = pMsiSourceListAddSourceExA(prodcode, usersid,
660                                   MSIINSTALLCONTEXT_USERMANAGED,
661                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
663
664     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
665     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
666
667     size = MAX_PATH;
668     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
669     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
670     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
671     ok(size == 11, "Expected 11, got %d\n", size);
672
673     RegCloseKey(url);
674
675     /* MSIINSTALLCONTEXT_USERMANAGED, NULL szUserSid */
676
677     r = pMsiSourceListAddSourceExA(prodcode, NULL,
678                                   MSIINSTALLCONTEXT_USERMANAGED,
679                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0);
680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
681
682     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
683     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
684
685     size = MAX_PATH;
686     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
687     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
688     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
689     ok(size == 11, "Expected 11, got %d\n", size);
690
691     size = MAX_PATH;
692     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
693     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
694     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
695     ok(size == 9, "Expected 9, got %d\n", size);
696
697     RegCloseKey(url);
698     RegCloseKey(prodkey);
699
700     /* MSIINSTALLCONTEXT_MACHINE */
701
702     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
703     r = pMsiSourceListAddSourceExA(prodcode, usersid,
704                                   MSIINSTALLCONTEXT_MACHINE,
705                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
706     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
707
708     r = pMsiSourceListAddSourceExA(prodcode, NULL,
709                                   MSIINSTALLCONTEXT_MACHINE,
710                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
711     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
712
713     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
714     lstrcatA(keypath, prod_squashed);
715
716     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
717     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
718
719     /* product key exists */
720     r = pMsiSourceListAddSourceExA(prodcode, NULL,
721                                   MSIINSTALLCONTEXT_MACHINE,
722                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
723     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
724
725     res = RegCreateKeyA(prodkey, "SourceList", &hkey);
726     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
727     RegCloseKey(hkey);
728
729     /* SourceList exists */
730     r = pMsiSourceListAddSourceExA(prodcode, NULL,
731                                   MSIINSTALLCONTEXT_MACHINE,
732                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
734
735     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
736     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
737
738     size = MAX_PATH;
739     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
740     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
741     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
742     ok(size == 11, "Expected 11, got %d\n", size);
743
744     RegCloseKey(url);
745     RegCloseKey(prodkey);
746     HeapFree(GetProcessHeap(), 0, usersid);
747 }
748
749 static void test_MsiSourceListEnumSources(void)
750 {
751     CHAR prodcode[MAX_PATH];
752     CHAR prod_squashed[MAX_PATH];
753     CHAR keypath[MAX_PATH*2];
754     CHAR value[MAX_PATH];
755     LPSTR usersid;
756     LONG res;
757     UINT r;
758     HKEY prodkey, userkey;
759     HKEY url, net, source;
760     DWORD size;
761
762     create_test_guid(prodcode, prod_squashed);
763     get_user_sid(&usersid);
764
765     /* GetLastError is not set by the function */
766
767     /* NULL szProductCodeOrPatchCode */
768     size = 0xdeadbeef;
769     r = MsiSourceListEnumSourcesA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
770                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
771     todo_wine
772     {
773         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
774     }
775     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
776
777     /* empty szProductCodeOrPatchCode */
778     size = 0xdeadbeef;
779     r = MsiSourceListEnumSourcesA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
780                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
781     todo_wine
782     {
783         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
784     }
785     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
786
787     /* garbage szProductCodeOrPatchCode */
788     size = 0xdeadbeef;
789     r = MsiSourceListEnumSourcesA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
790                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
791     todo_wine
792     {
793         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
794     }
795     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
796
797     /* guid without brackets */
798     size = 0xdeadbeef;
799     r = MsiSourceListEnumSourcesA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
800                                   usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
801                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
802     todo_wine
803     {
804         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
805     }
806     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
807
808     /* guid with brackets */
809     size = 0xdeadbeef;
810     r = MsiSourceListEnumSourcesA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
811                                   usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
812                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
813     todo_wine
814     {
815         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
816     }
817     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
818
819     /* MSIINSTALLCONTEXT_USERUNMANAGED */
820
821     size = MAX_PATH;
822     lstrcpyA(value, "aaa");
823     r = MsiSourceListEnumSourcesA(prodcode, usersid,
824                                   MSIINSTALLCONTEXT_USERUNMANAGED,
825                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
826     todo_wine
827     {
828         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
829     }
830     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
831     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
832
833     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
834     lstrcatA(keypath, prod_squashed);
835
836     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
838
839     /* user product key exists */
840     size = MAX_PATH;
841     lstrcpyA(value, "aaa");
842     r = MsiSourceListEnumSourcesA(prodcode, usersid,
843                                   MSIINSTALLCONTEXT_USERUNMANAGED,
844                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
845     todo_wine
846     {
847         ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
848     }
849     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
850     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
851
852     res = RegCreateKeyA(userkey, "SourceList", &source);
853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
854
855     /* SourceList key exists */
856     size = MAX_PATH;
857     lstrcpyA(value, "aaa");
858     r = MsiSourceListEnumSourcesA(prodcode, usersid,
859                                   MSIINSTALLCONTEXT_USERUNMANAGED,
860                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
861     todo_wine
862     {
863         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
864     }
865     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
866     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
867
868     res = RegCreateKeyA(source, "URL", &url);
869     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
870
871     /* URL key exists */
872     size = MAX_PATH;
873     lstrcpyA(value, "aaa");
874     r = MsiSourceListEnumSourcesA(prodcode, usersid,
875                                   MSIINSTALLCONTEXT_USERUNMANAGED,
876                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
877     todo_wine
878     {
879         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
880     }
881     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
882     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
883
884     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
886
887     res = RegSetValueExA(url, "2", 0, REG_SZ, (LPBYTE)"second", 7);
888     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
889
890     res = RegSetValueExA(url, "4", 0, REG_SZ, (LPBYTE)"fourth", 7);
891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
892
893     /* sources exist */
894     size = MAX_PATH;
895     lstrcpyA(value, "aaa");
896     r = MsiSourceListEnumSourcesA(prodcode, usersid,
897                                   MSIINSTALLCONTEXT_USERUNMANAGED,
898                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
899     todo_wine
900     {
901         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
902         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
903         ok(size == 5, "Expected 5, got %d\n", size);
904     }
905
906     /* try index 0 again */
907     size = MAX_PATH;
908     lstrcpyA(value, "aaa");
909     r = MsiSourceListEnumSourcesA(prodcode, usersid,
910                                   MSIINSTALLCONTEXT_USERUNMANAGED,
911                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
912     todo_wine
913     {
914         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
915         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
916         ok(size == 5, "Expected 5, got %d\n", size);
917     }
918
919     /* try index 1 */
920     size = MAX_PATH;
921     lstrcpyA(value, "aaa");
922     r = MsiSourceListEnumSourcesA(prodcode, usersid,
923                                   MSIINSTALLCONTEXT_USERUNMANAGED,
924                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size);
925     todo_wine
926     {
927         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
928         ok(!lstrcmpA(value, "second"), "Expected \"second\", got %s\n", value);
929         ok(size == 6, "Expected 6, got %d\n", size);
930     }
931
932     /* try index 2 */
933     size = MAX_PATH;
934     lstrcpyA(value, "aaa");
935     r = MsiSourceListEnumSourcesA(prodcode, usersid,
936                                   MSIINSTALLCONTEXT_USERUNMANAGED,
937                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 2, value, &size);
938     todo_wine
939     {
940         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
941     }
942     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
943     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
944
945     /* NULL szUserSid */
946     size = MAX_PATH;
947     lstrcpyA(value, "aaa");
948     r = MsiSourceListEnumSourcesA(prodcode, NULL,
949                                   MSIINSTALLCONTEXT_USERUNMANAGED,
950                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
951     todo_wine
952     {
953         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
954         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
955         ok(size == 5, "Expected 5, got %d\n", size);
956     }
957
958     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
959     size = MAX_PATH;
960     lstrcpyA(value, "aaa");
961     r = MsiSourceListEnumSourcesA(prodcode, NULL,
962                                   MSIINSTALLCONTEXT_USERUNMANAGED,
963                                   MSICODE_PRODUCT, 0, value, &size);
964     todo_wine
965     {
966         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
967     }
968     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
969     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
970
971     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
972     size = MAX_PATH;
973     lstrcpyA(value, "aaa");
974     r = MsiSourceListEnumSourcesA(prodcode, NULL,
975                                   MSIINSTALLCONTEXT_USERUNMANAGED,
976                                   MSICODE_PATCH, 0, value, &size);
977     todo_wine
978     {
979         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
980     }
981     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
982     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
983
984     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
985     size = MAX_PATH;
986     lstrcpyA(value, "aaa");
987     r = MsiSourceListEnumSourcesA(prodcode, NULL,
988                                   MSIINSTALLCONTEXT_USERUNMANAGED,
989                                   MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL,
990                                   0, value, &size);
991     todo_wine
992     {
993         ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_SUCCESS, got %d\n", r);
994     }
995     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
996     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
997
998     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
999     size = MAX_PATH;
1000     lstrcpyA(value, "aaa");
1001     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1002                                   MSIINSTALLCONTEXT_USERUNMANAGED,
1003                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1004                                   0, value, &size);
1005     todo_wine
1006     {
1007         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1008     }
1009     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1010     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1011
1012     RegDeleteValueA(url, "1");
1013     RegDeleteValueA(url, "2");
1014     RegDeleteValueA(url, "4");
1015     RegDeleteKeyA(url, "");
1016     RegCloseKey(url);
1017
1018     /* SourceList key exists */
1019     size = MAX_PATH;
1020     lstrcpyA(value, "aaa");
1021     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1022                                   MSIINSTALLCONTEXT_USERUNMANAGED,
1023                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1024     todo_wine
1025     {
1026         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1027     }
1028     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1029     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1030
1031     res = RegCreateKeyA(source, "Net", &net);
1032     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1033
1034     /* Net key exists */
1035     size = MAX_PATH;
1036     lstrcpyA(value, "aaa");
1037     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1038                                   MSIINSTALLCONTEXT_USERUNMANAGED,
1039                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1040     todo_wine
1041     {
1042         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1043     }
1044     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1045     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1046
1047     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1048     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1049
1050     /* sources exist */
1051     size = MAX_PATH;
1052     lstrcpyA(value, "aaa");
1053     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1054                                   MSIINSTALLCONTEXT_USERUNMANAGED,
1055                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1056     todo_wine
1057     {
1058         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1059         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1060         ok(size == 5, "Expected 5, got %d\n", size);
1061     }
1062
1063     RegDeleteValueA(net, "1");
1064     RegDeleteKeyA(net, "");
1065     RegCloseKey(net);
1066     RegDeleteKeyA(source, "");
1067     RegCloseKey(source);
1068     RegDeleteKeyA(userkey, "");
1069     RegCloseKey(userkey);
1070
1071     /* MSIINSTALLCONTEXT_USERMANAGED */
1072
1073     size = MAX_PATH;
1074     lstrcpyA(value, "aaa");
1075     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1076                                   MSIINSTALLCONTEXT_USERMANAGED,
1077                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1078     todo_wine
1079     {
1080         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1081     }
1082     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1083     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1084
1085     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1086     lstrcatA(keypath, usersid);
1087     lstrcatA(keypath, "\\Installer\\Products\\");
1088     lstrcatA(keypath, prod_squashed);
1089
1090     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
1091     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1092
1093     /* user product key exists */
1094     size = MAX_PATH;
1095     lstrcpyA(value, "aaa");
1096     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1097                                   MSIINSTALLCONTEXT_USERMANAGED,
1098                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1099     todo_wine
1100     {
1101         ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1102     }
1103     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1104     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1105
1106     res = RegCreateKeyA(userkey, "SourceList", &source);
1107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1108
1109     /* SourceList key exists */
1110     size = MAX_PATH;
1111     lstrcpyA(value, "aaa");
1112     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1113                                   MSIINSTALLCONTEXT_USERMANAGED,
1114                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1115     todo_wine
1116     {
1117         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1118     }
1119     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1120     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1121
1122     res = RegCreateKeyA(source, "URL", &url);
1123     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1124
1125     /* URL key exists */
1126     size = MAX_PATH;
1127     lstrcpyA(value, "aaa");
1128     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1129                                   MSIINSTALLCONTEXT_USERMANAGED,
1130                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1131     todo_wine
1132     {
1133         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1134     }
1135     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1136     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1137
1138     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1139     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1140
1141     /* sources exist */
1142     size = MAX_PATH;
1143     lstrcpyA(value, "aaa");
1144     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1145                                   MSIINSTALLCONTEXT_USERMANAGED,
1146                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1147     todo_wine
1148     {
1149         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1150         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1151         ok(size == 5, "Expected 5, got %d\n", size);
1152     }
1153
1154     /* NULL szUserSid */
1155     size = MAX_PATH;
1156     lstrcpyA(value, "aaa");
1157     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1158                                   MSIINSTALLCONTEXT_USERMANAGED,
1159                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1160     todo_wine
1161     {
1162         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1163         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1164         ok(size == 5, "Expected 5, got %d\n", size);
1165     }
1166
1167     RegDeleteValueA(url, "1");
1168     RegDeleteKeyA(url, "");
1169     RegCloseKey(url);
1170
1171     /* SourceList key exists */
1172     size = MAX_PATH;
1173     lstrcpyA(value, "aaa");
1174     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1175                                   MSIINSTALLCONTEXT_USERMANAGED,
1176                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1177     todo_wine
1178     {
1179         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1180     }
1181     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1182     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1183
1184     res = RegCreateKeyA(source, "Net", &net);
1185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1186
1187     /* Net key exists */
1188     size = MAX_PATH;
1189     lstrcpyA(value, "aaa");
1190     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1191                                   MSIINSTALLCONTEXT_USERMANAGED,
1192                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1193     todo_wine
1194     {
1195         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1196     }
1197     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1198     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1199
1200     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1202
1203     /* sources exist */
1204     size = MAX_PATH;
1205     lstrcpyA(value, "aaa");
1206     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1207                                   MSIINSTALLCONTEXT_USERMANAGED,
1208                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1209     todo_wine
1210     {
1211         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1212         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1213         ok(size == 5, "Expected 5, got %d\n", size);
1214     }
1215
1216     RegDeleteValueA(net, "1");
1217     RegDeleteKeyA(net, "");
1218     RegCloseKey(net);
1219     RegDeleteKeyA(source, "");
1220     RegCloseKey(source);
1221     RegDeleteKeyA(userkey, "");
1222     RegCloseKey(userkey);
1223
1224     /* MSIINSTALLCONTEXT_MACHINE */
1225
1226     /* szUserSid is non-NULL */
1227     size = MAX_PATH;
1228     lstrcpyA(value, "aaa");
1229     r = MsiSourceListEnumSourcesA(prodcode, usersid,
1230                                   MSIINSTALLCONTEXT_MACHINE,
1231                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1232     todo_wine
1233     {
1234         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1235     }
1236     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1237     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1238
1239     /* szUserSid is non-NULL */
1240     size = MAX_PATH;
1241     lstrcpyA(value, "aaa");
1242     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1243                                   MSIINSTALLCONTEXT_MACHINE,
1244                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1245     todo_wine
1246     {
1247         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1248     }
1249     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1250     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1251
1252     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1253     lstrcatA(keypath, prod_squashed);
1254
1255     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1256     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1257
1258     /* user product key exists */
1259     size = MAX_PATH;
1260     lstrcpyA(value, "aaa");
1261     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1262                                   MSIINSTALLCONTEXT_MACHINE,
1263                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1264     todo_wine
1265     {
1266         ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1267     }
1268     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1269     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1270
1271     res = RegCreateKeyA(prodkey, "SourceList", &source);
1272     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1273
1274     /* SourceList key exists */
1275     size = MAX_PATH;
1276     lstrcpyA(value, "aaa");
1277     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1278                                   MSIINSTALLCONTEXT_MACHINE,
1279                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1280     todo_wine
1281     {
1282         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1283     }
1284     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1285     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1286
1287     res = RegCreateKeyA(source, "URL", &url);
1288     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1289
1290     /* URL key exists */
1291     size = MAX_PATH;
1292     lstrcpyA(value, "aaa");
1293     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1294                                   MSIINSTALLCONTEXT_MACHINE,
1295                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1296     todo_wine
1297     {
1298         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1299     }
1300     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1301     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1302
1303     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1305
1306     /* sources exist */
1307     size = MAX_PATH;
1308     lstrcpyA(value, "aaa");
1309     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1310                                   MSIINSTALLCONTEXT_MACHINE,
1311                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1312     todo_wine
1313     {
1314         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1315         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1316         ok(size == 5, "Expected 5, got %d\n", size);
1317     }
1318
1319     /* NULL szUserSid */
1320     size = MAX_PATH;
1321     lstrcpyA(value, "aaa");
1322     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1323                                   MSIINSTALLCONTEXT_MACHINE,
1324                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1325     todo_wine
1326     {
1327         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1328         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1329         ok(size == 5, "Expected 5, got %d\n", size);
1330     }
1331
1332     RegDeleteValueA(url, "1");
1333     RegDeleteKeyA(url, "");
1334     RegCloseKey(url);
1335
1336     /* SourceList key exists */
1337     size = MAX_PATH;
1338     lstrcpyA(value, "aaa");
1339     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1340                                   MSIINSTALLCONTEXT_MACHINE,
1341                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1342     todo_wine
1343     {
1344         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1345     }
1346     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1347     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1348
1349     res = RegCreateKeyA(source, "Net", &net);
1350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1351
1352     /* Net key exists */
1353     size = MAX_PATH;
1354     lstrcpyA(value, "aaa");
1355     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1356                                   MSIINSTALLCONTEXT_MACHINE,
1357                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1358     todo_wine
1359     {
1360         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1361     }
1362     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1363     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1364
1365     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1366     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1367
1368     /* sources exist */
1369     size = MAX_PATH;
1370     lstrcpyA(value, "aaa");
1371     r = MsiSourceListEnumSourcesA(prodcode, NULL,
1372                                   MSIINSTALLCONTEXT_MACHINE,
1373                                   MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1374     todo_wine
1375     {
1376         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1377         ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1378         ok(size == 5, "Expected 5, got %d\n", size);
1379     }
1380
1381     RegDeleteValueA(net, "1");
1382     RegDeleteKeyA(net, "");
1383     RegCloseKey(net);
1384     RegDeleteKeyA(source, "");
1385     RegCloseKey(source);
1386     RegDeleteKeyA(prodkey, "");
1387     RegCloseKey(prodkey);
1388 }
1389
1390 static void test_MsiSourceListSetInfo(void)
1391 {
1392     CHAR prodcode[MAX_PATH];
1393     CHAR prod_squashed[MAX_PATH];
1394     CHAR keypath[MAX_PATH*2];
1395     HKEY prodkey, userkey;
1396     HKEY net, url, media, source;
1397     LPSTR usersid;
1398     LONG res;
1399     UINT r;
1400
1401     create_test_guid(prodcode, prod_squashed);
1402     get_user_sid(&usersid);
1403
1404     /* GetLastError is not set by the function */
1405
1406     /* NULL szProductCodeOrPatchCode */
1407     r = MsiSourceListSetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1408                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1409                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1410     ok(r == ERROR_INVALID_PARAMETER,
1411        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1412
1413     /* empty szProductCodeOrPatchCode */
1414     r = MsiSourceListSetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1415                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1416                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1417     ok(r == ERROR_INVALID_PARAMETER,
1418        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1419
1420     /* garbage szProductCodeOrPatchCode */
1421     r = MsiSourceListSetInfoA("garbage", usersid,
1422                               MSIINSTALLCONTEXT_USERUNMANAGED,
1423                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1424                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1425     ok(r == ERROR_INVALID_PARAMETER,
1426        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1427
1428     /* guid without brackets */
1429     r = MsiSourceListSetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
1430                               usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1431                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1432                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1433     ok(r == ERROR_INVALID_PARAMETER,
1434        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1435
1436     /* guid with brackets */
1437     r = MsiSourceListSetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
1438                               usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1439                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1440                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1441     ok(r == ERROR_UNKNOWN_PRODUCT,
1442        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1443
1444     /* dwOptions is MSICODE_PRODUCT */
1445     r = MsiSourceListSetInfoA(prodcode, usersid,
1446                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1447                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1448     ok(r == ERROR_UNKNOWN_PRODUCT,
1449        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1450
1451     /* dwOptions is MSICODE_PATCH */
1452     r = MsiSourceListSetInfoA(prodcode, usersid,
1453                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH,
1454                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1455     todo_wine
1456     {
1457         ok(r == ERROR_UNKNOWN_PATCH,
1458            "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
1459     }
1460
1461     /* dwOptions is both MSICODE_PRODUCT and MSICODE_PATCH */
1462     r = MsiSourceListSetInfoA(prodcode, usersid,
1463                               MSIINSTALLCONTEXT_USERUNMANAGED,
1464                               MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL,
1465                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1466     todo_wine
1467     {
1468         ok(r == ERROR_UNKNOWN_PATCH,
1469            "Expected ERROR_SUCCESS, got %d\n", r);
1470     }
1471
1472     /* dwOptions has both MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL */
1473     r = MsiSourceListSetInfoA(prodcode, NULL,
1474                               MSIINSTALLCONTEXT_USERUNMANAGED,
1475                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1476                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1477     ok(r == ERROR_UNKNOWN_PRODUCT,
1478        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1479
1480     /* LastUsedSource and dwOptions has both
1481      * MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL
1482      */
1483     r = MsiSourceListSetInfoA(prodcode, NULL,
1484                               MSIINSTALLCONTEXT_USERUNMANAGED,
1485                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1486                               INSTALLPROPERTY_LASTUSEDSOURCE, "path");
1487     ok(r == ERROR_UNKNOWN_PRODUCT,
1488        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1489
1490     /* LastUsedSource and dwOptions has no source type */
1491     r = MsiSourceListSetInfoA(prodcode, NULL,
1492                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1493                               INSTALLPROPERTY_LASTUSEDSOURCE, "path");
1494     ok(r == ERROR_UNKNOWN_PRODUCT,
1495        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1496
1497     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1498
1499     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1500     lstrcatA(keypath, prod_squashed);
1501
1502     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1503     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1504
1505     /* user product key exists */
1506     r = MsiSourceListSetInfoA(prodcode, NULL,
1507                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1508                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1509     todo_wine
1510     {
1511         ok(r == ERROR_BAD_CONFIGURATION,
1512            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1513     }
1514
1515     res = RegCreateKeyA(userkey, "SourceList", &source);
1516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1517
1518     /* SourceList key exists, no source type */
1519     r = MsiSourceListSetInfoA(prodcode, NULL,
1520                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1521                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1522     todo_wine
1523     {
1524         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1525     }
1526
1527     /* Media key is created by MsiSourceListSetInfo */
1528     res = RegOpenKeyA(source, "Media", &media);
1529     todo_wine
1530     {
1531         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1532         CHECK_REG_STR(media, "MediaPackage", "path");
1533     }
1534
1535     /* set the info again */
1536     r = MsiSourceListSetInfoA(prodcode, NULL,
1537                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1538                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path2");
1539     todo_wine
1540     {
1541         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1542         CHECK_REG_STR(media, "MediaPackage", "path2");
1543     }
1544
1545     /* NULL szProperty */
1546     r = MsiSourceListSetInfoA(prodcode, NULL,
1547                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1548                               NULL, "path");
1549     ok(r == ERROR_INVALID_PARAMETER,
1550        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1551
1552     /* empty szProperty */
1553     r = MsiSourceListSetInfoA(prodcode, NULL,
1554                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1555                               "", "path");
1556     ok(r == ERROR_UNKNOWN_PROPERTY,
1557        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1558
1559     /* NULL szValue */
1560     r = MsiSourceListSetInfoA(prodcode, NULL,
1561                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1562                               INSTALLPROPERTY_MEDIAPACKAGEPATH, NULL);
1563     ok(r == ERROR_UNKNOWN_PROPERTY,
1564        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1565
1566     /* empty szValue */
1567     r = MsiSourceListSetInfoA(prodcode, NULL,
1568                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1569                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "");
1570     todo_wine
1571     {
1572         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1573         CHECK_REG_STR(media, "MediaPackage", "");
1574     }
1575
1576     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_NETWORK */
1577     r = MsiSourceListSetInfoA(prodcode, NULL,
1578                               MSIINSTALLCONTEXT_USERUNMANAGED,
1579                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1580                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1581     todo_wine
1582     {
1583         ok(r == ERROR_INVALID_PARAMETER,
1584            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1585     }
1586
1587     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_URL */
1588     r = MsiSourceListSetInfoA(prodcode, NULL,
1589                               MSIINSTALLCONTEXT_USERUNMANAGED,
1590                               MSICODE_PRODUCT | MSISOURCETYPE_URL,
1591                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1592     todo_wine
1593     {
1594         ok(r == ERROR_INVALID_PARAMETER,
1595            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1596     }
1597
1598     /* INSTALLPROPERTY_DISKPROMPT */
1599     r = MsiSourceListSetInfoA(prodcode, NULL,
1600                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1601                               INSTALLPROPERTY_DISKPROMPT, "prompt");
1602     todo_wine
1603     {
1604         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1605         CHECK_REG_STR(media, "DiskPrompt", "prompt");
1606     }
1607
1608     /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_NETWORK */
1609     r = MsiSourceListSetInfoA(prodcode, NULL,
1610                               MSIINSTALLCONTEXT_USERUNMANAGED,
1611                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1612                               INSTALLPROPERTY_DISKPROMPT, "prompt");
1613     todo_wine
1614     {
1615         ok(r == ERROR_INVALID_PARAMETER,
1616            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1617     }
1618
1619     /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_URL */
1620     r = MsiSourceListSetInfoA(prodcode, NULL,
1621                               MSIINSTALLCONTEXT_USERUNMANAGED,
1622                               MSICODE_PRODUCT | MSISOURCETYPE_URL,
1623                               INSTALLPROPERTY_DISKPROMPT, "prompt");
1624     todo_wine
1625     {
1626         ok(r == ERROR_INVALID_PARAMETER,
1627            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1628     }
1629
1630     /* INSTALLPROPERTY_LASTUSEDSOURCE */
1631     r = MsiSourceListSetInfoA(prodcode, NULL,
1632                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1633                               INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1634     todo_wine
1635     {
1636         ok(r == ERROR_INVALID_PARAMETER,
1637            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1638     }
1639
1640     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_NETWORK */
1641     r = MsiSourceListSetInfoA(prodcode, NULL,
1642                               MSIINSTALLCONTEXT_USERUNMANAGED,
1643                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1644                               INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1646
1647     /* Net key is created by MsiSourceListSetInfo */
1648     res = RegOpenKeyA(source, "Net", &net);
1649     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1650     CHECK_REG_STR(net, "1", "source\\")
1651
1652     /* source has forward slash */
1653     r = MsiSourceListSetInfoA(prodcode, NULL,
1654                               MSIINSTALLCONTEXT_USERUNMANAGED,
1655                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1656                               INSTALLPROPERTY_LASTUSEDSOURCE, "source/");
1657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1658     CHECK_REG_STR(net, "1", "source\\")
1659
1660     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_URL */
1661     r = MsiSourceListSetInfoA(prodcode, NULL,
1662                               MSIINSTALLCONTEXT_USERUNMANAGED,
1663                               MSICODE_PRODUCT | MSISOURCETYPE_URL,
1664                               INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1666
1667     /* URL key is created by MsiSourceListSetInfo */
1668     res = RegOpenKeyA(source, "URL", &url);
1669     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1670     CHECK_REG_STR(url, "1", "source/");
1671
1672     /* source has backslash */
1673     r = MsiSourceListSetInfoA(prodcode, NULL,
1674                               MSIINSTALLCONTEXT_USERUNMANAGED,
1675                               MSICODE_PRODUCT | MSISOURCETYPE_URL,
1676                               INSTALLPROPERTY_LASTUSEDSOURCE, "source\\");
1677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1678     CHECK_REG_STR(url, "1", "source/");
1679
1680     /* INSTALLPROPERTY_PACKAGENAME */
1681     r = MsiSourceListSetInfoA(prodcode, NULL,
1682                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1683                               INSTALLPROPERTY_PACKAGENAME, "name");
1684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1685     CHECK_REG_STR(source, "PackageName", "name");
1686
1687     /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_NETWORK */
1688     r = MsiSourceListSetInfoA(prodcode, NULL,
1689                               MSIINSTALLCONTEXT_USERUNMANAGED,
1690                               MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1691                               INSTALLPROPERTY_PACKAGENAME, "name");
1692     todo_wine
1693     {
1694         ok(r == ERROR_INVALID_PARAMETER,
1695            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1696     }
1697
1698     /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_URL */
1699     r = MsiSourceListSetInfoA(prodcode, NULL,
1700                               MSIINSTALLCONTEXT_USERUNMANAGED,
1701                               MSICODE_PRODUCT | MSISOURCETYPE_URL,
1702                               INSTALLPROPERTY_PACKAGENAME, "name");
1703     todo_wine
1704     {
1705         ok(r == ERROR_INVALID_PARAMETER,
1706            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1707     }
1708
1709     /* INSTALLPROPERTY_LASTUSEDTYPE */
1710     r = MsiSourceListSetInfoA(prodcode, NULL,
1711                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1712                               INSTALLPROPERTY_LASTUSEDTYPE, "type");
1713     ok(r == ERROR_UNKNOWN_PROPERTY,
1714        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1715
1716     /* definitely unknown property */
1717     r = MsiSourceListSetInfoA(prodcode, NULL,
1718                               MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1719                               "unknown", "val");
1720     ok(r == ERROR_UNKNOWN_PROPERTY,
1721        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1722
1723     RegDeleteValueA(net, "1");
1724     RegDeleteKeyA(net, "");
1725     RegCloseKey(net);
1726     RegDeleteValueA(url, "1");
1727     RegDeleteKeyA(url, "");
1728     RegCloseKey(url);
1729     RegDeleteValueA(media, "MediaPackage");
1730     RegDeleteValueA(media, "DiskPrompt");
1731     RegDeleteKeyA(media, "");
1732     RegCloseKey(media);
1733     RegDeleteValueA(source, "PackageName");
1734     RegDeleteKeyA(source, "");
1735     RegCloseKey(source);
1736     RegDeleteKeyA(userkey, "");
1737     RegCloseKey(userkey);
1738
1739     /* MSIINSTALLCONTEXT_USERMANAGED */
1740
1741     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1742     lstrcatA(keypath, usersid);
1743     lstrcatA(keypath, "\\Installer\\Products\\");
1744     lstrcatA(keypath, prod_squashed);
1745
1746     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
1747     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1748
1749     /* user product key exists */
1750     r = MsiSourceListSetInfoA(prodcode, NULL,
1751                               MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
1752                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1753     todo_wine
1754     {
1755         ok(r == ERROR_BAD_CONFIGURATION,
1756            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1757     }
1758
1759     res = RegCreateKeyA(userkey, "SourceList", &source);
1760     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1761
1762     /* SourceList key exists, no source type */
1763     r = MsiSourceListSetInfoA(prodcode, NULL,
1764                               MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
1765                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1766     todo_wine
1767     {
1768         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1769     }
1770
1771     /* Media key is created by MsiSourceListSetInfo */
1772     res = RegOpenKeyA(source, "Media", &media);
1773     todo_wine
1774     {
1775         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1776         CHECK_REG_STR(media, "MediaPackage", "path");
1777     }
1778
1779     RegDeleteValueA(media, "MediaPackage");
1780     RegDeleteKeyA(media, "");
1781     RegCloseKey(media);
1782     RegDeleteKeyA(source, "");
1783     RegCloseKey(source);
1784     RegDeleteKeyA(userkey, "");
1785     RegCloseKey(userkey);
1786
1787     /* MSIINSTALLCONTEXT_MACHINE */
1788
1789     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1790     lstrcatA(keypath, prod_squashed);
1791
1792     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1793     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1794
1795     /* user product key exists */
1796     r = MsiSourceListSetInfoA(prodcode, NULL,
1797                               MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
1798                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1799     todo_wine
1800     {
1801         ok(r == ERROR_BAD_CONFIGURATION,
1802            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1803     }
1804
1805     res = RegCreateKeyA(prodkey, "SourceList", &source);
1806     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1807
1808     /* SourceList key exists, no source type */
1809     r = MsiSourceListSetInfoA(prodcode, NULL,
1810                               MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
1811                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1812     todo_wine
1813     {
1814         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1815     }
1816
1817     /* Media key is created by MsiSourceListSetInfo */
1818     res = RegOpenKeyA(source, "Media", &media);
1819     todo_wine
1820     {
1821         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1822         CHECK_REG_STR(media, "MediaPackage", "path");
1823     }
1824
1825     /* szUserSid is non-NULL */
1826     r = MsiSourceListSetInfoA(prodcode, usersid,
1827                               MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
1828                               INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1829     todo_wine
1830     {
1831         ok(r == ERROR_INVALID_PARAMETER,
1832            "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1833     }
1834
1835     RegDeleteValueA(media, "MediaPackage");
1836     RegDeleteKeyA(media, "");
1837     RegCloseKey(media);
1838     RegDeleteKeyA(source, "");
1839     RegCloseKey(source);
1840     RegDeleteKeyA(prodkey, "");
1841     RegCloseKey(prodkey);
1842 }
1843
1844 START_TEST(source)
1845 {
1846     init_functionpointers();
1847
1848     test_MsiSourceListGetInfo();
1849     test_MsiSourceListAddSourceEx();
1850     test_MsiSourceListEnumSources();
1851     test_MsiSourceListSetInfo();
1852 }