msi: Add a test for MsiSetFeatureState.
[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 #include <secext.h>
31
32 #include "wine/test.h"
33
34 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
35 static BOOLEAN (WINAPI *pGetUserNameExA)(EXTENDED_NAME_FORMAT, LPSTR, PULONG);
36 static UINT (WINAPI *pMsiSourceListAddMediaDiskA)
37     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPCSTR, LPCSTR);
38 static UINT (WINAPI *pMsiSourceListAddSourceExA)
39     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, DWORD);
40 static UINT (WINAPI *pMsiSourceListEnumMediaDisksA)
41     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPDWORD, LPSTR,
42     LPDWORD, LPSTR, LPDWORD);
43 static UINT (WINAPI *pMsiSourceListEnumSourcesA)
44     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
45 static UINT (WINAPI *pMsiSourceListGetInfoA)
46     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
47 static UINT (WINAPI *pMsiSourceListSetInfoA)
48     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT,  DWORD,LPCSTR,  LPCSTR);
49 static UINT (WINAPI *pMsiSourceListAddSourceA)
50     (LPCSTR, LPCSTR, DWORD, LPCSTR);
51
52 static void init_functionpointers(void)
53 {
54     HMODULE hmsi = GetModuleHandleA("msi.dll");
55     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
56     HMODULE hsecur32 = LoadLibraryA("secur32.dll");
57
58 #define GET_PROC(dll, func) \
59     p ## func = (void *)GetProcAddress(dll, #func); \
60     if(!p ## func) \
61       trace("GetProcAddress(%s) failed\n", #func);
62
63     GET_PROC(hmsi, MsiSourceListAddMediaDiskA)
64     GET_PROC(hmsi, MsiSourceListAddSourceExA)
65     GET_PROC(hmsi, MsiSourceListEnumMediaDisksA)
66     GET_PROC(hmsi, MsiSourceListEnumSourcesA)
67     GET_PROC(hmsi, MsiSourceListGetInfoA)
68     GET_PROC(hmsi, MsiSourceListSetInfoA)
69     GET_PROC(hmsi, MsiSourceListAddSourceA)
70
71     GET_PROC(hadvapi32, ConvertSidToStringSidA)
72
73     GET_PROC(hsecur32, GetUserNameExA)
74
75 #undef GET_PROC
76 }
77
78 /* copied from dlls/msi/registry.c */
79 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
80 {
81     DWORD i,n=1;
82     GUID guid;
83
84     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
85         return FALSE;
86
87     for(i=0; i<8; i++)
88         out[7-i] = in[n++];
89     n++;
90     for(i=0; i<4; i++)
91         out[11-i] = in[n++];
92     n++;
93     for(i=0; i<4; i++)
94         out[15-i] = in[n++];
95     n++;
96     for(i=0; i<2; i++)
97     {
98         out[17+i*2] = in[n++];
99         out[16+i*2] = in[n++];
100     }
101     n++;
102     for( ; i<8; i++)
103     {
104         out[17+i*2] = in[n++];
105         out[16+i*2] = in[n++];
106     }
107     out[32]=0;
108     return TRUE;
109 }
110
111 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
112 {
113     WCHAR guidW[MAX_PATH];
114     WCHAR squashedW[MAX_PATH];
115     GUID guid;
116     HRESULT hr;
117     int size;
118
119     hr = CoCreateGuid(&guid);
120     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
121
122     size = StringFromGUID2(&guid, guidW, MAX_PATH);
123     ok(size == 39, "Expected 39, got %d\n", hr);
124
125     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
126     squash_guid(guidW, squashedW);
127     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
128 }
129
130 static int get_user_sid(LPSTR *usersid)
131 {
132     HANDLE token;
133     BYTE buf[1024];
134     DWORD size;
135     PTOKEN_USER user;
136     BOOL rc;
137
138     if (!pConvertSidToStringSidA)
139         return 0;
140     rc=OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
141     if (!rc && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
142         return 0;
143     size = sizeof(buf);
144     GetTokenInformation(token, TokenUser, buf, size, &size);
145     user = (PTOKEN_USER)buf;
146     pConvertSidToStringSidA(user->User.Sid, usersid);
147     CloseHandle(token);
148     return 1;
149 }
150
151 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
152 {
153     char val[MAX_PATH];
154     DWORD size, type;
155     LONG res;
156
157     size = MAX_PATH;
158     val[0] = '\0';
159     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
160
161     if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
162     {
163         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
164         return;
165     }
166
167     if (!expected)
168         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
169     else
170     {
171         if (bcase)
172             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
173         else
174             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
175     }
176 }
177
178 #define CHECK_REG_STR(prodkey, name, expected) \
179     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
180
181 static void test_MsiSourceListGetInfo(void)
182 {
183     CHAR prodcode[MAX_PATH];
184     CHAR prod_squashed[MAX_PATH];
185     CHAR keypath[MAX_PATH*2];
186     CHAR value[MAX_PATH];
187     LPSTR usersid;
188     LPCSTR data;
189     LONG res;
190     UINT r;
191     HKEY userkey, hkey, media;
192     DWORD size;
193
194     if (!pMsiSourceListGetInfoA)
195     {
196         win_skip("Skipping MsiSourceListGetInfoA tests\n");
197         return;
198     }
199
200     create_test_guid(prodcode, prod_squashed);
201     if (!get_user_sid(&usersid))
202     {
203         skip("User SID not available -> skipping MsiSourceListGetInfoA tests\n");
204         return;
205     }
206
207     /* NULL szProductCodeOrPatchCode */
208     r = pMsiSourceListGetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
209                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
210     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
211
212     /* empty szProductCodeOrPatchCode */
213     r = pMsiSourceListGetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
214                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
215     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
216
217     /* garbage szProductCodeOrPatchCode */
218     r = pMsiSourceListGetInfoA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
219                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
220     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
221
222     /* guid without brackets */
223     r = pMsiSourceListGetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
224                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
225     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
226
227     /* guid with brackets */
228     r = pMsiSourceListGetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
229                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
230     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
231
232     /* same length as guid, but random */
233     r = pMsiSourceListGetInfoA("ADKD-2KSDFF2-DKK1KNFJASD9GLKWME-1I3KAD", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
234                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
235     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
236
237     /* invalid context */
238     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_NONE,
239                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
240     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
241
242     /* another invalid context */
243     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALLUSERMANAGED,
244                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
245     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
246
247     /* yet another invalid context */
248     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALL,
249                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
250     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
251
252     /* mix two valid contexts */
253     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED | MSIINSTALLCONTEXT_USERUNMANAGED,
254                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
255     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
256
257     /* invalid option */
258     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
259                               4, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
260     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
261
262     /* NULL property */
263     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
264                               MSICODE_PRODUCT, NULL, NULL, NULL);
265     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
266
267     /* empty property */
268     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
269                               MSICODE_PRODUCT, "", NULL, NULL);
270     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
271
272     /* value is non-NULL while size is NULL */
273     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
274                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, NULL);
275     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
276
277     /* size is non-NULL while value is NULL */
278     size = MAX_PATH;
279     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
280                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
281     ok(r == ERROR_UNKNOWN_PRODUCT || r == ERROR_INVALID_PARAMETER,
282       "Expected ERROR_UNKNOWN_PRODUCT or ERROR_INVALID_PARAMETER, got %d\n", r);
283
284     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
285     lstrcatA(keypath, prod_squashed);
286
287     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
288     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
289
290     /* user product key exists */
291     size = MAX_PATH;
292     lstrcpyA(value, "aaa");
293     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
294                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
295     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
296     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
297
298     res = RegCreateKeyA(userkey, "SourceList", &hkey);
299     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
300
301     /* SourceList key exists */
302     size = MAX_PATH;
303     lstrcpyA(value, "aaa");
304     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
305                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
306     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
307     ok(size == 0, "Expected 0, got %d\n", size);
308     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
309
310     data = "msitest.msi";
311     res = RegSetValueExA(hkey, "PackageName", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1);
312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
313
314     /* PackageName value exists */
315     size = 0xdeadbeef;
316     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
317                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
318     ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER,
319            "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r);
320     ok(size == 11 || r != ERROR_SUCCESS, "Expected 11, got %d\n", size);
321
322     /* read the value, don't change size */
323         size = 11;
324     lstrcpyA(value, "aaa");
325     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
326                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
327     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
328     ok(!lstrcmpA(value, "aaa"), "Expected 'aaa', got %s\n", value);
329     ok(size == 11, "Expected 11, got %d\n", size);
330
331     /* read the value, fix size */
332     size++;
333     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
334                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
336     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
337     ok(size == 11, "Expected 11, got %d\n", size);
338
339     /* empty property now that product key exists */
340     size = MAX_PATH;
341     lstrcpyA(value, "aaa");
342     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
343                               MSICODE_PRODUCT, "", value, &size);
344     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
345     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
346     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
347
348     /* nonexistent property now that product key exists */
349     size = MAX_PATH;
350     lstrcpyA(value, "aaa");
351     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
352                               MSICODE_PRODUCT, "nonexistent", value, &size);
353     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
354     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
355     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
356
357     data = "tester";
358     res = RegSetValueExA(hkey, "nonexistent", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1);
359     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
360
361     /* nonexistent property now that nonexistent value exists */
362     size = MAX_PATH;
363     lstrcpyA(value, "aaa");
364     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
365                               MSICODE_PRODUCT, "nonexistent", value, &size);
366     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
367     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
368     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
369
370     /* invalid option now that product key exists */
371     size = MAX_PATH;
372     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
373                               4, INSTALLPROPERTY_PACKAGENAME, value, &size);
374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
375     ok(size == 11, "Expected 11, got %d\n", size);
376
377     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, media key does not exist */
378     size = MAX_PATH;
379     lstrcpyA(value, "aaa");
380     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
381                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH,
382                                value, &size);
383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
384     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
385     ok(size == 0, "Expected 0, got %d\n", size);
386
387     res = RegCreateKeyA(hkey, "Media", &media);
388     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
389
390     data = "path";
391     res = RegSetValueExA(media, "MediaPackage", 0, REG_SZ,
392                          (const BYTE *)data, lstrlenA(data) + 1);
393     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
394
395     /* INSTALLPROPERTY_MEDIAPACKAGEPATH */
396     size = MAX_PATH;
397     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
398                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH,
399                                value, &size);
400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
401     ok(!lstrcmpA(value, "path"), "Expected \"path\", got \"%s\"\n", value);
402     ok(size == 4, "Expected 4, got %d\n", size);
403
404     /* INSTALLPROPERTY_DISKPROMPT */
405     data = "prompt";
406     res = RegSetValueExA(media, "DiskPrompt", 0, REG_SZ,
407                          (const BYTE *)data, lstrlenA(data) + 1);
408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
409
410     size = MAX_PATH;
411     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
412                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT,
413                                value, &size);
414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
415     ok(!lstrcmpA(value, "prompt"), "Expected \"prompt\", got \"%s\"\n", value);
416     ok(size == 6, "Expected 6, got %d\n", size);
417
418     data = "";
419     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
420                          (const BYTE *)data, lstrlenA(data) + 1);
421     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
422
423     /* INSTALLPROPERTY_LASTUSEDSOURCE, source is empty */
424     size = MAX_PATH;
425     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
426                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
427                                value, &size);
428     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
429     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
430     ok(size == 0, "Expected 0, got %d\n", size);
431
432     data = "source";
433     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
434                          (const BYTE *)data, lstrlenA(data) + 1);
435     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
436
437     /* INSTALLPROPERTY_LASTUSEDSOURCE */
438     size = MAX_PATH;
439     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
440                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
441                                value, &size);
442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
443     ok(!lstrcmpA(value, "source"), "Expected \"source\", got \"%s\"\n", value);
444     ok(size == 6, "Expected 6, got %d\n", size);
445
446     /* INSTALLPROPERTY_LASTUSEDSOURCE, size is too short */
447     size = 4;
448     lstrcpyA(value, "aaa");
449     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
450                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
451                                value, &size);
452     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
453     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got \"%s\"\n", value);
454     ok(size == 6, "Expected 6, got %d\n", size);
455
456     /* INSTALLPROPERTY_LASTUSEDSOURCE, size is exactly 6 */
457     size = 6;
458     lstrcpyA(value, "aaa");
459     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
460                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
461                                value, &size);
462     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
463     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got \"%s\"\n", value);
464     ok(size == 6, "Expected 6, got %d\n", size);
465
466     data = "a;source";
467     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
468                          (const BYTE *)data, lstrlenA(data) + 1);
469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
470
471     /* INSTALLPROPERTY_LASTUSEDSOURCE, one semi-colon */
472     size = MAX_PATH;
473     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
474                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
475                                value, &size);
476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
477     ok(!lstrcmpA(value, "source"), "Expected \"source\", got \"%s\"\n", value);
478     ok(size == 6, "Expected 6, got %d\n", size);
479
480     data = "a:source";
481     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
482                          (const BYTE *)data, lstrlenA(data) + 1);
483     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
484
485     /* INSTALLPROPERTY_LASTUSEDSOURCE, one colon */
486     size = MAX_PATH;
487     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
488                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
489                                value, &size);
490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
491     ok(!lstrcmpA(value, "a:source"), "Expected \"a:source\", got \"%s\"\n", value);
492     ok(size == 8, "Expected 8, got %d\n", size);
493
494     /* INSTALLPROPERTY_LASTUSEDTYPE, invalid source format */
495     size = MAX_PATH;
496     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
497                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
498                                value, &size);
499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
500     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
501     ok(size == 0, "Expected 0, got %d\n", size);
502
503     data = "x;y;z";
504     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
505                          (const BYTE *)data, lstrlenA(data) + 1);
506     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
507
508     /* INSTALLPROPERTY_LASTUSEDTYPE, invalid source format */
509     size = MAX_PATH;
510     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
511                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
512                                value, &size);
513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
514     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
515     ok(size == 0, "Expected 0, got %d\n", size);
516
517     data = "n;y;z";
518     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
519                          (const BYTE *)data, lstrlenA(data) + 1);
520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
521
522     /* INSTALLPROPERTY_LASTUSEDTYPE */
523     size = MAX_PATH;
524     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
525                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
526                                value, &size);
527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
528     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
529     ok(size == 1, "Expected 1, got %d\n", size);
530
531     data = "negatory";
532     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
533                          (const BYTE *)data, lstrlenA(data) + 1);
534     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
535
536     /* INSTALLPROPERTY_LASTUSEDTYPE */
537     size = MAX_PATH;
538     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
539                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
540                                value, &size);
541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
542     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
543     ok(size == 1, "Expected 1, got %d\n", size);
544
545     data = "megatron";
546     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
547                          (const BYTE *)data, lstrlenA(data) + 1);
548     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
549
550     /* INSTALLPROPERTY_LASTUSEDTYPE */
551     size = MAX_PATH;
552     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
553                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
554                                value, &size);
555     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
556     ok(!lstrcmpA(value, "m"), "Expected \"m\", got \"%s\"\n", value);
557     ok(size == 1, "Expected 1, got %d\n", size);
558
559     data = "useless";
560     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
561                          (const BYTE *)data, lstrlenA(data) + 1);
562     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
563
564     /* INSTALLPROPERTY_LASTUSEDTYPE */
565     size = MAX_PATH;
566     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
567                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
568                                value, &size);
569     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
570     ok(!lstrcmpA(value, "u"), "Expected \"u\", got \"%s\"\n", value);
571     ok(size == 1, "Expected 1, got %d\n", size);
572
573     RegDeleteValueA(media, "MediaPackage");
574     RegDeleteValueA(media, "DiskPrompt");
575     RegDeleteKeyA(media, "");
576     RegDeleteValueA(hkey, "LastUsedSource");
577     RegDeleteValueA(hkey, "nonexistent");
578     RegDeleteValueA(hkey, "PackageName");
579     RegDeleteKeyA(hkey, "");
580     RegDeleteKeyA(userkey, "");
581     RegCloseKey(hkey);
582     RegCloseKey(userkey);
583
584     /* try a patch */
585     size = MAX_PATH;
586     lstrcpyA(value, "aaa");
587     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
588                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, value, &size);
589     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
590     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
591     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
592
593     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Patches\\");
594     lstrcatA(keypath, prod_squashed);
595
596     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
597     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
598
599     /* patch key exists
600      * NOTE: using prodcode guid, but it really doesn't matter
601      */
602     size = MAX_PATH;
603     lstrcpyA(value, "aaa");
604     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
605                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, value, &size);
606     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
607     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
608     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
609
610     res = RegCreateKeyA(userkey, "SourceList", &hkey);
611     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
612
613     /* SourceList key exists */
614     size = MAX_PATH;
615     lstrcpyA(value, "aaa");
616     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
617                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, value, &size);
618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
619     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
620     ok(size == 0, "Expected 0, got %d\n", size);
621
622     RegDeleteKeyA(hkey, "");
623     RegDeleteKeyA(userkey, "");
624     RegCloseKey(hkey);
625     RegCloseKey(userkey);
626     LocalFree(usersid);
627 }
628
629 static void test_MsiSourceListAddSourceEx(void)
630 {
631     CHAR prodcode[MAX_PATH];
632     CHAR prod_squashed[MAX_PATH];
633     CHAR keypath[MAX_PATH*2];
634     CHAR value[MAX_PATH];
635     LPSTR usersid;
636     LONG res;
637     UINT r;
638     HKEY prodkey, userkey, hkey;
639     HKEY url, net;
640     DWORD size;
641
642     if (!pMsiSourceListAddSourceExA)
643     {
644         win_skip("Skipping MsiSourceListAddSourceExA tests\n");
645         return;
646     }
647
648     create_test_guid(prodcode, prod_squashed);
649     if (!get_user_sid(&usersid))
650     {
651         skip("User SID not available -> skipping MsiSourceListAddSourceExA tests\n");
652         return;
653     }
654
655     /* GetLastError is not set by the function */
656
657     /* NULL szProductCodeOrPatchCode */
658     r = pMsiSourceListAddSourceExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
659                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
660     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
661
662     /* empty szProductCodeOrPatchCode */
663     r = pMsiSourceListAddSourceExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
664                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
665     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
666
667     /* garbage szProductCodeOrPatchCode */
668     r = pMsiSourceListAddSourceExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
669                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
670     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
671
672     /* guid without brackets */
673     r = pMsiSourceListAddSourceExA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid,
674                                   MSIINSTALLCONTEXT_USERUNMANAGED,
675                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
676     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
677
678     /* guid with brackets */
679     r = pMsiSourceListAddSourceExA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid,
680                                   MSIINSTALLCONTEXT_USERUNMANAGED,
681                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
682     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
683
684     /* MSIINSTALLCONTEXT_USERUNMANAGED */
685
686     r = pMsiSourceListAddSourceExA(prodcode, usersid,
687                                   MSIINSTALLCONTEXT_USERUNMANAGED,
688                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
689     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
690
691     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
692     lstrcatA(keypath, prod_squashed);
693
694     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
695     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
696
697     /* user product key exists */
698     r = pMsiSourceListAddSourceExA(prodcode, usersid,
699                                   MSIINSTALLCONTEXT_USERUNMANAGED,
700                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
701     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
702
703     res = RegCreateKeyA(userkey, "SourceList", &url);
704     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
705     RegCloseKey(url);
706
707     /* SourceList key exists */
708     r = pMsiSourceListAddSourceExA(prodcode, usersid,
709                                   MSIINSTALLCONTEXT_USERUNMANAGED,
710                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
712
713     res = RegOpenKeyA(userkey, "SourceList\\URL", &url);
714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
715
716     size = MAX_PATH;
717     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
718     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
719     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
720     ok(size == 11, "Expected 11, got %d\n", size);
721
722     /* add another source, index 0 */
723     r = pMsiSourceListAddSourceExA(prodcode, usersid,
724                                   MSIINSTALLCONTEXT_USERUNMANAGED,
725                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0);
726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
727
728     size = MAX_PATH;
729     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
731     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
732     ok(size == 11, "Expected 11, got %d\n", size);
733
734     size = MAX_PATH;
735     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
736     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
737     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
738     ok(size == 9, "Expected 9, got %d\n", size);
739
740     /* add another source, index 1 */
741     r = pMsiSourceListAddSourceExA(prodcode, usersid,
742                                   MSIINSTALLCONTEXT_USERUNMANAGED,
743                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "third/", 1);
744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
745
746     size = MAX_PATH;
747     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
748     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
749     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
750     ok(size == 7, "Expected 7, got %d\n", size);
751
752     size = MAX_PATH;
753     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
754     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
755     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
756     ok(size == 11, "Expected 11, got %d\n", size);
757
758     size = MAX_PATH;
759     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
760     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
761     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
762     ok(size == 9, "Expected 9, got %d\n", size);
763
764     /* add another source, index > N */
765     r = pMsiSourceListAddSourceExA(prodcode, usersid,
766                                   MSIINSTALLCONTEXT_USERUNMANAGED,
767                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "last/", 5);
768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
769
770     size = MAX_PATH;
771     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
772     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
773     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
774     ok(size == 7, "Expected 7, got %d\n", size);
775
776     size = MAX_PATH;
777     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
778     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
779     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
780     ok(size == 11, "Expected 11, got %d\n", size);
781
782     size = MAX_PATH;
783     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
784     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
785     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
786     ok(size == 9, "Expected 9, got %d\n", size);
787
788     size = MAX_PATH;
789     res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
790     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
791     ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value);
792     ok(size == 6, "Expected 6, got %d\n", size);
793
794     /* just MSISOURCETYPE_NETWORK */
795     r = pMsiSourceListAddSourceExA(prodcode, usersid,
796                                   MSIINSTALLCONTEXT_USERUNMANAGED,
797                                   MSISOURCETYPE_NETWORK, "source", 0);
798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
799
800     res = RegOpenKeyA(userkey, "SourceList\\Net", &net);
801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
802
803     size = MAX_PATH;
804     res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size);
805     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
806     ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value);
807     ok(size == 8, "Expected 8, got %d\n", size);
808
809     /* just MSISOURCETYPE_URL */
810     r = pMsiSourceListAddSourceExA(prodcode, usersid,
811                                   MSIINSTALLCONTEXT_USERUNMANAGED,
812                                   MSISOURCETYPE_URL, "source", 0);
813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
814
815     size = MAX_PATH;
816     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
818     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
819     ok(size == 7, "Expected 7, got %d\n", size);
820
821     size = MAX_PATH;
822     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
823     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
824     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
825     ok(size == 11, "Expected 11, got %d\n", size);
826
827     size = MAX_PATH;
828     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
829     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
830     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
831     ok(size == 9, "Expected 9, got %d\n", size);
832
833     size = MAX_PATH;
834     res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
835     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
836     ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value);
837     ok(size == 6, "Expected 6, got %d\n", size);
838
839     size = MAX_PATH;
840     res = RegQueryValueExA(url, "5", NULL, NULL, (LPBYTE)value, &size);
841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
842     ok(!lstrcmpA(value, "source/"), "Expected 'source/', got %s\n", value);
843     ok(size == 8, "Expected 8, got %d\n", size);
844
845     /* NULL szUserSid */
846     r = pMsiSourceListAddSourceExA(prodcode, NULL,
847                                   MSIINSTALLCONTEXT_USERUNMANAGED,
848                                   MSISOURCETYPE_NETWORK, "nousersid", 0);
849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
850
851     size = MAX_PATH;
852     res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size);
853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
854     ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value);
855     ok(size == 8, "Expected 8, got %d\n", size);
856
857     size = MAX_PATH;
858     res = RegQueryValueExA(net, "2", NULL, NULL, (LPBYTE)value, &size);
859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
860     ok(!lstrcmpA(value, "nousersid\\"), "Expected 'nousersid\\', got %s\n", value);
861     ok(size == 11, "Expected 11, got %d\n", size);
862
863     /* invalid options, must have source type */
864     r = pMsiSourceListAddSourceExA(prodcode, usersid,
865                                   MSIINSTALLCONTEXT_USERUNMANAGED,
866                                   MSICODE_PRODUCT, "source", 0);
867     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
868
869     r = pMsiSourceListAddSourceExA(prodcode, usersid,
870                                   MSIINSTALLCONTEXT_USERUNMANAGED,
871                                   MSICODE_PATCH, "source", 0);
872     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
873
874     /* NULL szSource */
875     r = pMsiSourceListAddSourceExA(prodcode, usersid,
876                                   MSIINSTALLCONTEXT_USERUNMANAGED,
877                                   MSISOURCETYPE_URL, NULL, 1);
878     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
879
880     /* empty szSource */
881     r = pMsiSourceListAddSourceExA(prodcode, usersid,
882                                   MSIINSTALLCONTEXT_USERUNMANAGED,
883                                   MSISOURCETYPE_URL, "", 1);
884     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
885
886     /* MSIINSTALLCONTEXT_USERMANAGED, non-NULL szUserSid */
887
888     r = pMsiSourceListAddSourceExA(prodcode, usersid,
889                                   MSIINSTALLCONTEXT_USERMANAGED,
890                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
891     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
892
893     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
894     lstrcatA(keypath, usersid);
895     lstrcatA(keypath, "\\Installer\\Products\\");
896     lstrcatA(keypath, prod_squashed);
897
898     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
899     if (res != ERROR_SUCCESS)
900     {
901         skip("Product key creation failed with error code %u\n", res);
902         goto machine_tests;
903     }
904
905     /* product key exists */
906     r = pMsiSourceListAddSourceExA(prodcode, usersid,
907                                   MSIINSTALLCONTEXT_USERMANAGED,
908                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
909     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
910
911     res = RegCreateKeyA(prodkey, "SourceList", &hkey);
912     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
913     RegCloseKey(hkey);
914
915     /* SourceList exists */
916     r = pMsiSourceListAddSourceExA(prodcode, usersid,
917                                   MSIINSTALLCONTEXT_USERMANAGED,
918                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
920
921     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
922     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
923
924     size = MAX_PATH;
925     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
927     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
928     ok(size == 11, "Expected 11, got %d\n", size);
929
930     RegCloseKey(url);
931
932     /* MSIINSTALLCONTEXT_USERMANAGED, NULL szUserSid */
933
934     r = pMsiSourceListAddSourceExA(prodcode, NULL,
935                                   MSIINSTALLCONTEXT_USERMANAGED,
936                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0);
937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
938
939     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
940     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
941
942     size = MAX_PATH;
943     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
944     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
945     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
946     ok(size == 11, "Expected 11, got %d\n", size);
947
948     size = MAX_PATH;
949     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
950     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
951     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
952     ok(size == 9, "Expected 9, got %d\n", size);
953
954     RegCloseKey(url);
955     RegCloseKey(prodkey);
956
957     /* MSIINSTALLCONTEXT_MACHINE */
958
959 machine_tests:
960     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
961     r = pMsiSourceListAddSourceExA(prodcode, usersid,
962                                   MSIINSTALLCONTEXT_MACHINE,
963                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
964     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
965
966     r = pMsiSourceListAddSourceExA(prodcode, NULL,
967                                   MSIINSTALLCONTEXT_MACHINE,
968                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
969     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
970
971     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
972     lstrcatA(keypath, prod_squashed);
973
974     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
975     if (res != ERROR_SUCCESS)
976     {
977         skip("Product key creation failed with error code %u\n", res);
978         LocalFree(usersid);
979         return;
980     }
981
982     /* product key exists */
983     r = pMsiSourceListAddSourceExA(prodcode, NULL,
984                                   MSIINSTALLCONTEXT_MACHINE,
985                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
986     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
987
988     res = RegCreateKeyA(prodkey, "SourceList", &hkey);
989     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
990     RegCloseKey(hkey);
991
992     /* SourceList exists */
993     r = pMsiSourceListAddSourceExA(prodcode, NULL,
994                                   MSIINSTALLCONTEXT_MACHINE,
995                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
996     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
997
998     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
999     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1000
1001     size = MAX_PATH;
1002     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
1003     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1004     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
1005     ok(size == 11, "Expected 11, got %d\n", size);
1006
1007     RegCloseKey(url);
1008     RegCloseKey(prodkey);
1009     LocalFree(usersid);
1010 }
1011
1012 static void test_MsiSourceListEnumSources(void)
1013 {
1014     CHAR prodcode[MAX_PATH];
1015     CHAR prod_squashed[MAX_PATH];
1016     CHAR keypath[MAX_PATH*2];
1017     CHAR value[MAX_PATH];
1018     LPSTR usersid;
1019     LONG res;
1020     UINT r;
1021     HKEY prodkey, userkey;
1022     HKEY url, net, source;
1023     DWORD size;
1024
1025     if (!pMsiSourceListEnumSourcesA)
1026     {
1027         win_skip("MsiSourceListEnumSourcesA is not available\n");
1028         return;
1029     }
1030
1031     create_test_guid(prodcode, prod_squashed);
1032     if (!get_user_sid(&usersid))
1033     {
1034         skip("User SID not available -> skipping MsiSourceListEnumSourcesA tests\n");
1035         return;
1036     }
1037
1038     /* GetLastError is not set by the function */
1039
1040     /* NULL szProductCodeOrPatchCode */
1041     size = 0xdeadbeef;
1042     r = pMsiSourceListEnumSourcesA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1043                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1044     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1045     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
1046
1047     /* empty szProductCodeOrPatchCode */
1048     size = 0xdeadbeef;
1049     r = pMsiSourceListEnumSourcesA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1050                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1051     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1052     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
1053
1054     /* garbage szProductCodeOrPatchCode */
1055     size = 0xdeadbeef;
1056     r = pMsiSourceListEnumSourcesA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1057                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1058     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1059     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
1060
1061     /* guid without brackets */
1062     size = 0xdeadbeef;
1063     r = pMsiSourceListEnumSourcesA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
1064                                    usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1065                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1066     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1067     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
1068
1069     /* guid with brackets */
1070     size = 0xdeadbeef;
1071     r = pMsiSourceListEnumSourcesA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
1072                                    usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1073                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1074     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1075     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
1076
1077     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1078
1079     size = MAX_PATH;
1080     lstrcpyA(value, "aaa");
1081     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1082                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1083                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1084     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1085     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1086     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1087
1088     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1089     lstrcatA(keypath, prod_squashed);
1090
1091     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1093
1094     /* user product key exists */
1095     size = MAX_PATH;
1096     lstrcpyA(value, "aaa");
1097     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1098                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1099                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1100     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1101     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1102     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1103
1104     res = RegCreateKeyA(userkey, "SourceList", &source);
1105     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1106
1107     /* SourceList key exists */
1108     size = MAX_PATH;
1109     lstrcpyA(value, "aaa");
1110     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1111                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1112                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1113     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1114     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1115     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1116
1117     res = RegCreateKeyA(source, "URL", &url);
1118     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1119
1120     /* URL key exists */
1121     size = MAX_PATH;
1122     lstrcpyA(value, "aaa");
1123     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1124                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1125                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1126     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1127     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1128     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1129
1130     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1131     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1132
1133     res = RegSetValueExA(url, "2", 0, REG_SZ, (LPBYTE)"second", 7);
1134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1135
1136     res = RegSetValueExA(url, "4", 0, REG_SZ, (LPBYTE)"fourth", 7);
1137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1138
1139     /* sources exist */
1140     size = MAX_PATH;
1141     lstrcpyA(value, "aaa");
1142     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1143                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1144                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1146     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1147     ok(size == 5, "Expected 5, got %d\n", size);
1148
1149     /* try index 0 again */
1150     size = MAX_PATH;
1151     lstrcpyA(value, "aaa");
1152     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1153                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1154                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1156     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1157     ok(size == 5, "Expected 5, got %d\n", size);
1158
1159     /* both szSource and pcchSource are NULL, index 0 */
1160     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1161                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1162                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, NULL);
1163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1164
1165     /* both szSource and pcchSource are NULL, index 1 */
1166     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1167                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1168                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, NULL, NULL);
1169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1170
1171     /* size is exactly 5 */
1172     size = 5;
1173     lstrcpyA(value, "aaa");
1174     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1175                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1176                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1177     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
1178     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value);
1179     ok(size == 5, "Expected 5, got %d\n", size);
1180
1181     /* szSource is non-NULL while pcchSource is NULL */
1182     lstrcpyA(value, "aaa");
1183     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1184                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1185                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, NULL);
1186     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1187     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value);
1188
1189     /* try index 1 after failure */
1190     size = MAX_PATH;
1191     lstrcpyA(value, "aaa");
1192     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1193                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1194                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size);
1195     ok(r == ERROR_INVALID_PARAMETER,
1196        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1197     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value);
1198     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1199
1200     /* reset the enumeration */
1201     size = MAX_PATH;
1202     lstrcpyA(value, "aaa");
1203     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1204                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1205                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1207     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1208     ok(size == 5, "Expected 5, got %d\n", size);
1209
1210     /* try index 1 */
1211     size = MAX_PATH;
1212     lstrcpyA(value, "aaa");
1213     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1214                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1215                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size);
1216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1217     ok(!lstrcmpA(value, "second"), "Expected \"second\", got %s\n", value);
1218     ok(size == 6, "Expected 6, got %d\n", size);
1219
1220     /* try index 1 again */
1221     size = MAX_PATH;
1222     lstrcpyA(value, "aaa");
1223     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1224                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1225                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size);
1226     ok(r == ERROR_INVALID_PARAMETER,
1227        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1228     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1229     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1230
1231     /* try index 2 */
1232     size = MAX_PATH;
1233     lstrcpyA(value, "aaa");
1234     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1235                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1236                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 2, value, &size);
1237     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1238     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1239     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1240
1241     /* try index < 0 */
1242     size = MAX_PATH;
1243     lstrcpyA(value, "aaa");
1244     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1245                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1246                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, -1, value, &size);
1247     ok(r == ERROR_INVALID_PARAMETER,
1248        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
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     /* NULL szUserSid */
1253     size = MAX_PATH;
1254     lstrcpyA(value, "aaa");
1255     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1256                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1257                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1259     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1260     ok(size == 5, "Expected 5, got %d\n", size);
1261
1262     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1263     size = MAX_PATH;
1264     lstrcpyA(value, "aaa");
1265     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1266                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1267                                    MSICODE_PRODUCT, 0, value, &size);
1268     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1269     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1270     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1271
1272     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1273     size = MAX_PATH;
1274     lstrcpyA(value, "aaa");
1275     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1276                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1277                                    MSICODE_PATCH, 0, value, &size);
1278     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1279     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1280     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1281
1282     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1283     size = MAX_PATH;
1284     lstrcpyA(value, "aaa");
1285     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1286                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1287                                    MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL,
1288                                    0, value, &size);
1289     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_SUCCESS, got %d\n", r);
1290     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1291     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1292
1293     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1294     size = MAX_PATH;
1295     lstrcpyA(value, "aaa");
1296     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1297                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1298                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1299                                    0, value, &size);
1300     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1301     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1302     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1303
1304     RegDeleteValueA(url, "1");
1305     RegDeleteValueA(url, "2");
1306     RegDeleteValueA(url, "4");
1307     RegDeleteKeyA(url, "");
1308     RegCloseKey(url);
1309
1310     /* SourceList key exists */
1311     size = MAX_PATH;
1312     lstrcpyA(value, "aaa");
1313     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1314                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1315                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1316     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1317     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1318     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1319
1320     res = RegCreateKeyA(source, "Net", &net);
1321     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1322
1323     /* Net key exists */
1324     size = MAX_PATH;
1325     lstrcpyA(value, "aaa");
1326     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1327                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1328                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1329     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1330     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1331     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1332
1333     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1334     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1335
1336     /* sources exist */
1337     size = MAX_PATH;
1338     lstrcpyA(value, "aaa");
1339     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1340                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1341                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1343     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1344     ok(size == 5, "Expected 5, got %d\n", size);
1345
1346     RegDeleteValueA(net, "1");
1347     RegDeleteKeyA(net, "");
1348     RegCloseKey(net);
1349     RegDeleteKeyA(source, "");
1350     RegCloseKey(source);
1351     RegDeleteKeyA(userkey, "");
1352     RegCloseKey(userkey);
1353
1354     /* MSIINSTALLCONTEXT_USERMANAGED */
1355
1356     size = MAX_PATH;
1357     lstrcpyA(value, "aaa");
1358     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1359                                    MSIINSTALLCONTEXT_USERMANAGED,
1360                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1361     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
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     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1366     lstrcatA(keypath, usersid);
1367     lstrcatA(keypath, "\\Installer\\Products\\");
1368     lstrcatA(keypath, prod_squashed);
1369
1370     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
1371     if (res != ERROR_SUCCESS)
1372     {
1373         skip("Product key creation failed with error code %u\n", res);
1374         goto machine_tests;
1375     }
1376
1377     /* user product key exists */
1378     size = MAX_PATH;
1379     lstrcpyA(value, "aaa");
1380     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1381                                    MSIINSTALLCONTEXT_USERMANAGED,
1382                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1383     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1384     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1385     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1386
1387     res = RegCreateKeyA(userkey, "SourceList", &source);
1388     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1389
1390     /* SourceList key exists */
1391     size = MAX_PATH;
1392     lstrcpyA(value, "aaa");
1393     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1394                                    MSIINSTALLCONTEXT_USERMANAGED,
1395                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1396     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1397     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1398     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1399
1400     res = RegCreateKeyA(source, "URL", &url);
1401     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1402
1403     /* URL key exists */
1404     size = MAX_PATH;
1405     lstrcpyA(value, "aaa");
1406     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1407                                    MSIINSTALLCONTEXT_USERMANAGED,
1408                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1409     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1410     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1411     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1412
1413     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1414     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1415
1416     /* sources exist */
1417     size = MAX_PATH;
1418     lstrcpyA(value, "aaa");
1419     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1420                                    MSIINSTALLCONTEXT_USERMANAGED,
1421                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1423     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1424     ok(size == 5, "Expected 5, got %d\n", size);
1425
1426     /* NULL szUserSid */
1427     size = MAX_PATH;
1428     lstrcpyA(value, "aaa");
1429     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1430                                    MSIINSTALLCONTEXT_USERMANAGED,
1431                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1433     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1434     ok(size == 5, "Expected 5, got %d\n", size);
1435
1436     RegDeleteValueA(url, "1");
1437     RegDeleteKeyA(url, "");
1438     RegCloseKey(url);
1439
1440     /* SourceList key exists */
1441     size = MAX_PATH;
1442     lstrcpyA(value, "aaa");
1443     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1444                                    MSIINSTALLCONTEXT_USERMANAGED,
1445                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1446     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1447     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1448     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1449
1450     res = RegCreateKeyA(source, "Net", &net);
1451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1452
1453     /* Net key exists */
1454     size = MAX_PATH;
1455     lstrcpyA(value, "aaa");
1456     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1457                                    MSIINSTALLCONTEXT_USERMANAGED,
1458                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1459     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1460     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1461     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1462
1463     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1464     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1465
1466     /* sources exist */
1467     size = MAX_PATH;
1468     lstrcpyA(value, "aaa");
1469     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1470                                    MSIINSTALLCONTEXT_USERMANAGED,
1471                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1473     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1474     ok(size == 5, "Expected 5, got %d\n", size);
1475
1476     RegDeleteValueA(net, "1");
1477     RegDeleteKeyA(net, "");
1478     RegCloseKey(net);
1479     RegDeleteKeyA(source, "");
1480     RegCloseKey(source);
1481     RegDeleteKeyA(userkey, "");
1482     RegCloseKey(userkey);
1483
1484     /* MSIINSTALLCONTEXT_MACHINE */
1485
1486 machine_tests:
1487     /* szUserSid is non-NULL */
1488     size = MAX_PATH;
1489     lstrcpyA(value, "aaa");
1490     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1491                                    MSIINSTALLCONTEXT_MACHINE,
1492                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1493     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1494     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1495     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1496
1497     /* szUserSid is NULL */
1498     size = MAX_PATH;
1499     lstrcpyA(value, "aaa");
1500     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1501                                    MSIINSTALLCONTEXT_MACHINE,
1502                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1503     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1504     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1505     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1506
1507     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1508     lstrcatA(keypath, prod_squashed);
1509
1510     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1511     if (res != ERROR_SUCCESS)
1512     {
1513         skip("Product key creation failed with error code %u\n", res);
1514         LocalFree(usersid);
1515         return;
1516     }
1517
1518     /* user product key exists */
1519     size = MAX_PATH;
1520     lstrcpyA(value, "aaa");
1521     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1522                                    MSIINSTALLCONTEXT_MACHINE,
1523                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1524     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1525     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1526     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1527
1528     res = RegCreateKeyA(prodkey, "SourceList", &source);
1529     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1530
1531     /* SourceList key exists */
1532     size = MAX_PATH;
1533     lstrcpyA(value, "aaa");
1534     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1535                                    MSIINSTALLCONTEXT_MACHINE,
1536                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1537     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1538     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1539     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1540
1541     res = RegCreateKeyA(source, "URL", &url);
1542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1543
1544     /* URL key exists */
1545     size = MAX_PATH;
1546     lstrcpyA(value, "aaa");
1547     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1548                                    MSIINSTALLCONTEXT_MACHINE,
1549                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1550     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1551     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1552     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1553
1554     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1555     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1556
1557     /* sources exist */
1558     size = MAX_PATH;
1559     lstrcpyA(value, "aaa");
1560     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1561                                    MSIINSTALLCONTEXT_MACHINE,
1562                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1564     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1565     ok(size == 5, "Expected 5, got %d\n", size);
1566
1567     /* NULL szUserSid */
1568     size = MAX_PATH;
1569     lstrcpyA(value, "aaa");
1570     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1571                                    MSIINSTALLCONTEXT_MACHINE,
1572                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1573     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1574     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1575     ok(size == 5, "Expected 5, got %d\n", size);
1576
1577     RegDeleteValueA(url, "1");
1578     RegDeleteKeyA(url, "");
1579     RegCloseKey(url);
1580
1581     /* SourceList key exists */
1582     size = MAX_PATH;
1583     lstrcpyA(value, "aaa");
1584     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1585                                    MSIINSTALLCONTEXT_MACHINE,
1586                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1587     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1588     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1589     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1590
1591     res = RegCreateKeyA(source, "Net", &net);
1592     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1593
1594     /* Net key exists */
1595     size = MAX_PATH;
1596     lstrcpyA(value, "aaa");
1597     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1598                                    MSIINSTALLCONTEXT_MACHINE,
1599                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1600     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1601     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1602     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1603
1604     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1605     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1606
1607     /* sources exist */
1608     size = MAX_PATH;
1609     lstrcpyA(value, "aaa");
1610     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1611                                    MSIINSTALLCONTEXT_MACHINE,
1612                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1613     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1614     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1615     ok(size == 5, "Expected 5, got %d\n", size);
1616
1617     RegDeleteValueA(net, "1");
1618     RegDeleteKeyA(net, "");
1619     RegCloseKey(net);
1620     RegDeleteKeyA(source, "");
1621     RegCloseKey(source);
1622     RegDeleteKeyA(prodkey, "");
1623     RegCloseKey(prodkey);
1624     LocalFree(usersid);
1625 }
1626
1627 static void test_MsiSourceListSetInfo(void)
1628 {
1629     CHAR prodcode[MAX_PATH];
1630     CHAR prod_squashed[MAX_PATH];
1631     CHAR keypath[MAX_PATH*2];
1632     HKEY prodkey, userkey;
1633     HKEY net, url, media, source;
1634     LPSTR usersid;
1635     LONG res;
1636     UINT r;
1637
1638     if (!pMsiSourceListSetInfoA)
1639     {
1640         win_skip("MsiSourceListSetInfoA is not available\n");
1641         return;
1642     }
1643
1644     create_test_guid(prodcode, prod_squashed);
1645     if (!get_user_sid(&usersid))
1646     {
1647         skip("User SID not available -> skipping MsiSourceListSetInfoA tests\n");
1648         return;
1649     }
1650
1651     /* GetLastError is not set by the function */
1652
1653     /* NULL szProductCodeOrPatchCode */
1654     r = pMsiSourceListSetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1655                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1656                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1657     ok(r == ERROR_INVALID_PARAMETER,
1658        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1659
1660     /* empty szProductCodeOrPatchCode */
1661     r = pMsiSourceListSetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1662                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1663                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1664     ok(r == ERROR_INVALID_PARAMETER,
1665        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1666
1667     /* garbage szProductCodeOrPatchCode */
1668     r = pMsiSourceListSetInfoA("garbage", usersid,
1669                                MSIINSTALLCONTEXT_USERUNMANAGED,
1670                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1671                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1672     ok(r == ERROR_INVALID_PARAMETER,
1673        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1674
1675     /* guid without brackets */
1676     r = pMsiSourceListSetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
1677                                usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1678                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1679                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1680     ok(r == ERROR_INVALID_PARAMETER,
1681        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1682
1683     /* guid with brackets */
1684     r = pMsiSourceListSetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
1685                                usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1686                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1687                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1688     ok(r == ERROR_UNKNOWN_PRODUCT,
1689        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1690
1691     /* dwOptions is MSICODE_PRODUCT */
1692     r = pMsiSourceListSetInfoA(prodcode, usersid,
1693                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1694                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1695     ok(r == ERROR_UNKNOWN_PRODUCT,
1696        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1697
1698     /* dwOptions is MSICODE_PATCH */
1699     r = pMsiSourceListSetInfoA(prodcode, usersid,
1700                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH,
1701                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1702     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
1703
1704     /* dwOptions is both MSICODE_PRODUCT and MSICODE_PATCH */
1705     r = pMsiSourceListSetInfoA(prodcode, usersid,
1706                                MSIINSTALLCONTEXT_USERUNMANAGED,
1707                                MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL,
1708                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1709     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
1710
1711     /* dwOptions has both MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL */
1712     r = pMsiSourceListSetInfoA(prodcode, NULL,
1713                                MSIINSTALLCONTEXT_USERUNMANAGED,
1714                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1715                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1716     ok(r == ERROR_UNKNOWN_PRODUCT,
1717        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1718
1719     /* LastUsedSource and dwOptions has both
1720      * MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL
1721      */
1722     r = pMsiSourceListSetInfoA(prodcode, NULL,
1723                                MSIINSTALLCONTEXT_USERUNMANAGED,
1724                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1725                                INSTALLPROPERTY_LASTUSEDSOURCE, "path");
1726     ok(r == ERROR_UNKNOWN_PRODUCT,
1727        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1728
1729     /* LastUsedSource and dwOptions has no source type */
1730     r = pMsiSourceListSetInfoA(prodcode, NULL,
1731                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1732                                INSTALLPROPERTY_LASTUSEDSOURCE, "path");
1733     ok(r == ERROR_UNKNOWN_PRODUCT,
1734        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1735
1736     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1737
1738     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1739     lstrcatA(keypath, prod_squashed);
1740
1741     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1743
1744     /* user product key exists */
1745     r = pMsiSourceListSetInfoA(prodcode, NULL,
1746                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1747                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1748     ok(r == ERROR_BAD_CONFIGURATION,
1749        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1750
1751     res = RegCreateKeyA(userkey, "SourceList", &source);
1752     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1753
1754     /* SourceList key exists, no source type */
1755     r = pMsiSourceListSetInfoA(prodcode, NULL,
1756                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1757                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1759
1760     /* Media key is created by MsiSourceListSetInfo */
1761     res = RegOpenKeyA(source, "Media", &media);
1762     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1763     CHECK_REG_STR(media, "MediaPackage", "path");
1764
1765     /* set the info again */
1766     r = pMsiSourceListSetInfoA(prodcode, NULL,
1767                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1768                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path2");
1769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1770     CHECK_REG_STR(media, "MediaPackage", "path2");
1771
1772     /* NULL szProperty */
1773     r = pMsiSourceListSetInfoA(prodcode, NULL,
1774                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1775                                NULL, "path");
1776     ok(r == ERROR_INVALID_PARAMETER,
1777        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1778
1779     /* empty szProperty */
1780     r = pMsiSourceListSetInfoA(prodcode, NULL,
1781                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1782                                "", "path");
1783     ok(r == ERROR_UNKNOWN_PROPERTY,
1784        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1785
1786     /* NULL szValue */
1787     r = pMsiSourceListSetInfoA(prodcode, NULL,
1788                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1789                                INSTALLPROPERTY_MEDIAPACKAGEPATH, NULL);
1790     ok(r == ERROR_UNKNOWN_PROPERTY,
1791        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1792
1793     /* empty szValue */
1794     r = pMsiSourceListSetInfoA(prodcode, NULL,
1795                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1796                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "");
1797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1798     CHECK_REG_STR(media, "MediaPackage", "");
1799
1800     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_NETWORK */
1801     r = pMsiSourceListSetInfoA(prodcode, NULL,
1802                                MSIINSTALLCONTEXT_USERUNMANAGED,
1803                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1804                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1805     ok(r == ERROR_INVALID_PARAMETER,
1806        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1807
1808     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_URL */
1809     r = pMsiSourceListSetInfoA(prodcode, NULL,
1810                                MSIINSTALLCONTEXT_USERUNMANAGED,
1811                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1812                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1813     ok(r == ERROR_INVALID_PARAMETER,
1814        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1815
1816     /* INSTALLPROPERTY_DISKPROMPT */
1817     r = pMsiSourceListSetInfoA(prodcode, NULL,
1818                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1819                                INSTALLPROPERTY_DISKPROMPT, "prompt");
1820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1821     CHECK_REG_STR(media, "DiskPrompt", "prompt");
1822
1823     /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_NETWORK */
1824     r = pMsiSourceListSetInfoA(prodcode, NULL,
1825                                MSIINSTALLCONTEXT_USERUNMANAGED,
1826                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1827                                INSTALLPROPERTY_DISKPROMPT, "prompt");
1828     ok(r == ERROR_INVALID_PARAMETER,
1829        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1830
1831     /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_URL */
1832     r = pMsiSourceListSetInfoA(prodcode, NULL,
1833                                MSIINSTALLCONTEXT_USERUNMANAGED,
1834                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1835                                INSTALLPROPERTY_DISKPROMPT, "prompt");
1836     ok(r == ERROR_INVALID_PARAMETER,
1837        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1838
1839     /* INSTALLPROPERTY_LASTUSEDSOURCE */
1840     r = pMsiSourceListSetInfoA(prodcode, NULL,
1841                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1842                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1843     ok(r == ERROR_INVALID_PARAMETER,
1844        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1845
1846     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_NETWORK */
1847     r = pMsiSourceListSetInfoA(prodcode, NULL,
1848                                MSIINSTALLCONTEXT_USERUNMANAGED,
1849                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1850                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1852
1853     /* Net key is created by MsiSourceListSetInfo */
1854     res = RegOpenKeyA(source, "Net", &net);
1855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1856     CHECK_REG_STR(net, "1", "source\\")
1857     CHECK_REG_STR(source, "LastUsedSource", "n;1;source");
1858
1859     /* source has forward slash */
1860     r = pMsiSourceListSetInfoA(prodcode, NULL,
1861                                MSIINSTALLCONTEXT_USERUNMANAGED,
1862                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1863                                INSTALLPROPERTY_LASTUSEDSOURCE, "source/");
1864     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1865     CHECK_REG_STR(net, "1", "source\\");
1866     CHECK_REG_STR(net, "2", "source/\\");
1867     CHECK_REG_STR(source, "LastUsedSource", "n;2;source/");
1868
1869     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_URL */
1870     r = pMsiSourceListSetInfoA(prodcode, NULL,
1871                                MSIINSTALLCONTEXT_USERUNMANAGED,
1872                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1873                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1874     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1875
1876     /* URL key is created by MsiSourceListSetInfo */
1877     res = RegOpenKeyA(source, "URL", &url);
1878     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1879     CHECK_REG_STR(url, "1", "source/");
1880     CHECK_REG_STR(source, "LastUsedSource", "u;1;source");
1881
1882     /* source has backslash */
1883     r = pMsiSourceListSetInfoA(prodcode, NULL,
1884                                MSIINSTALLCONTEXT_USERUNMANAGED,
1885                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1886                                INSTALLPROPERTY_LASTUSEDSOURCE, "source\\");
1887     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1888     CHECK_REG_STR(url, "1", "source/");
1889     CHECK_REG_STR(url, "2", "source\\/");
1890     CHECK_REG_STR(source, "LastUsedSource", "u;2;source\\");
1891
1892     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_MEDIA */
1893     r = pMsiSourceListSetInfoA(prodcode, NULL,
1894                                MSIINSTALLCONTEXT_USERUNMANAGED,
1895                                MSICODE_PRODUCT | MSISOURCETYPE_MEDIA,
1896                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1897     ok(r == ERROR_INVALID_PARAMETER,
1898        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1899
1900     /* INSTALLPROPERTY_PACKAGENAME */
1901     r = pMsiSourceListSetInfoA(prodcode, NULL,
1902                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1903                                INSTALLPROPERTY_PACKAGENAME, "name");
1904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1905     CHECK_REG_STR(source, "PackageName", "name");
1906
1907     /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_NETWORK */
1908     r = pMsiSourceListSetInfoA(prodcode, NULL,
1909                                MSIINSTALLCONTEXT_USERUNMANAGED,
1910                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1911                                INSTALLPROPERTY_PACKAGENAME, "name");
1912     ok(r == ERROR_INVALID_PARAMETER,
1913        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1914
1915     /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_URL */
1916     r = pMsiSourceListSetInfoA(prodcode, NULL,
1917                                MSIINSTALLCONTEXT_USERUNMANAGED,
1918                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1919                                INSTALLPROPERTY_PACKAGENAME, "name");
1920     ok(r == ERROR_INVALID_PARAMETER,
1921        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1922
1923     /* INSTALLPROPERTY_LASTUSEDTYPE */
1924     r = pMsiSourceListSetInfoA(prodcode, NULL,
1925                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1926                                INSTALLPROPERTY_LASTUSEDTYPE, "type");
1927     ok(r == ERROR_UNKNOWN_PROPERTY,
1928        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1929
1930     /* definitely unknown property */
1931     r = pMsiSourceListSetInfoA(prodcode, NULL,
1932                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1933                                "unknown", "val");
1934     ok(r == ERROR_UNKNOWN_PROPERTY,
1935        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1936
1937     RegDeleteValueA(net, "1");
1938     RegDeleteKeyA(net, "");
1939     RegCloseKey(net);
1940     RegDeleteValueA(url, "1");
1941     RegDeleteKeyA(url, "");
1942     RegCloseKey(url);
1943     RegDeleteValueA(media, "MediaPackage");
1944     RegDeleteValueA(media, "DiskPrompt");
1945     RegDeleteKeyA(media, "");
1946     RegCloseKey(media);
1947     RegDeleteValueA(source, "PackageName");
1948     RegDeleteKeyA(source, "");
1949     RegCloseKey(source);
1950     RegDeleteKeyA(userkey, "");
1951     RegCloseKey(userkey);
1952
1953     /* MSIINSTALLCONTEXT_USERMANAGED */
1954
1955     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1956     lstrcatA(keypath, usersid);
1957     lstrcatA(keypath, "\\Installer\\Products\\");
1958     lstrcatA(keypath, prod_squashed);
1959
1960     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
1961     if (res != ERROR_SUCCESS)
1962     {
1963         skip("Product key creation failed with error code %u\n", res);
1964         goto machine_tests;
1965     }
1966
1967     /* user product key exists */
1968     r = pMsiSourceListSetInfoA(prodcode, NULL,
1969                                MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
1970                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1971     ok(r == ERROR_BAD_CONFIGURATION,
1972        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1973
1974     res = RegCreateKeyA(userkey, "SourceList", &source);
1975     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1976
1977     /* SourceList key exists, no source type */
1978     r = pMsiSourceListSetInfoA(prodcode, NULL,
1979                                MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
1980                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1982
1983     /* Media key is created by MsiSourceListSetInfo */
1984     res = RegOpenKeyA(source, "Media", &media);
1985     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1986     CHECK_REG_STR(media, "MediaPackage", "path");
1987
1988     RegDeleteValueA(media, "MediaPackage");
1989     RegDeleteKeyA(media, "");
1990     RegCloseKey(media);
1991     RegDeleteKeyA(source, "");
1992     RegCloseKey(source);
1993     RegDeleteKeyA(userkey, "");
1994     RegCloseKey(userkey);
1995
1996     /* MSIINSTALLCONTEXT_MACHINE */
1997
1998 machine_tests:
1999     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2000     lstrcatA(keypath, prod_squashed);
2001
2002     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
2003     if (res != ERROR_SUCCESS)
2004     {
2005         skip("Product key creation failed with error code %u\n", res);
2006         LocalFree(usersid);
2007         return;
2008     }
2009
2010     /* user product key exists */
2011     r = pMsiSourceListSetInfoA(prodcode, NULL,
2012                                MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
2013                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
2014     ok(r == ERROR_BAD_CONFIGURATION,
2015        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2016
2017     res = RegCreateKeyA(prodkey, "SourceList", &source);
2018     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2019
2020     /* SourceList key exists, no source type */
2021     r = pMsiSourceListSetInfoA(prodcode, NULL,
2022                                MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
2023                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
2024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2025
2026     /* Media key is created by MsiSourceListSetInfo */
2027     res = RegOpenKeyA(source, "Media", &media);
2028     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2029     CHECK_REG_STR(media, "MediaPackage", "path");
2030
2031     /* szUserSid is non-NULL */
2032     r = pMsiSourceListSetInfoA(prodcode, usersid,
2033                                MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
2034                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
2035     ok(r == ERROR_INVALID_PARAMETER,
2036        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2037
2038     RegDeleteValueA(media, "MediaPackage");
2039     RegDeleteKeyA(media, "");
2040     RegCloseKey(media);
2041     RegDeleteKeyA(source, "");
2042     RegCloseKey(source);
2043     RegDeleteKeyA(prodkey, "");
2044     RegCloseKey(prodkey);
2045     LocalFree(usersid);
2046 }
2047
2048 static void test_MsiSourceListAddMediaDisk(void)
2049 {
2050     CHAR prodcode[MAX_PATH];
2051     CHAR prod_squashed[MAX_PATH];
2052     CHAR keypath[MAX_PATH*2];
2053     HKEY prodkey, userkey;
2054     HKEY media, source;
2055     LPSTR usersid;
2056     LONG res;
2057     UINT r;
2058
2059     if (!pMsiSourceListAddMediaDiskA)
2060     {
2061         win_skip("MsiSourceListAddMediaDiskA is not available\n");
2062         return;
2063     }
2064
2065     create_test_guid(prodcode, prod_squashed);
2066     if (!get_user_sid(&usersid))
2067     {
2068         skip("User SID not available -> skipping MsiSourceListAddMediaDiskA tests\n");
2069         return;
2070     }
2071
2072     /* GetLastError is not set by the function */
2073
2074     /* NULL szProductCodeOrPatchCode */
2075     r = pMsiSourceListAddMediaDiskA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2076                                     MSICODE_PRODUCT, 1, "label", "prompt");
2077     ok(r == ERROR_INVALID_PARAMETER,
2078        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2079
2080     /* empty szProductCodeOrPatchCode */
2081     r = pMsiSourceListAddMediaDiskA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2082                                     MSICODE_PRODUCT, 1, "label", "prompt");
2083     ok(r == ERROR_INVALID_PARAMETER,
2084        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2085
2086     /* garbage szProductCodeOrPatchCode */
2087     r = pMsiSourceListAddMediaDiskA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2088                                     MSICODE_PRODUCT, 1, "label", "prompt");
2089     ok(r == ERROR_INVALID_PARAMETER,
2090        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2091
2092     /* guid without brackets */
2093     r = pMsiSourceListAddMediaDiskA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
2094                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2095                                     MSICODE_PRODUCT, 1, "label", "prompt");
2096     ok(r == ERROR_INVALID_PARAMETER,
2097        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2098
2099     /* guid with brackets */
2100     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2101                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2102                                     MSICODE_PRODUCT, 1, "label", "prompt");
2103     ok(r == ERROR_UNKNOWN_PRODUCT,
2104        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2105
2106     /* dwOptions has MSISOURCETYPE_NETWORK */
2107     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2108                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2109                                     MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
2110                                     1, "label", "prompt");
2111     ok(r == ERROR_INVALID_PARAMETER,
2112        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2113
2114     /* dwOptions has MSISOURCETYPE_URL */
2115     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2116                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2117                                     MSICODE_PRODUCT | MSISOURCETYPE_URL,
2118                                     1, "label", "prompt");
2119     ok(r == ERROR_INVALID_PARAMETER,
2120        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2121
2122     /* dwOptions has MSISOURCETYPE_MEDIA */
2123     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2124                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2125                                     MSICODE_PRODUCT | MSISOURCETYPE_MEDIA,
2126                                     1, "label", "prompt");
2127     ok(r == ERROR_INVALID_PARAMETER,
2128        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2129
2130     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2131
2132     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2133     lstrcatA(keypath, prod_squashed);
2134
2135     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2136     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2137
2138     /* user product key exists */
2139     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2140                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2141                                     MSICODE_PRODUCT, 1, "label", "prompt");
2142     ok(r == ERROR_BAD_CONFIGURATION,
2143        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2144
2145     res = RegCreateKeyA(userkey, "SourceList", &source);
2146     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2147
2148     /* SourceList key exists */
2149     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2150                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2151                                     MSICODE_PRODUCT, 1, "label", "prompt");
2152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2153
2154     /* Media subkey is created by MsiSourceListAddMediaDisk */
2155     res = RegOpenKeyA(source, "Media", &media);
2156     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2157
2158     CHECK_REG_STR(media, "1", "label;prompt");
2159
2160     /* dwDiskId is random */
2161     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2162                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2163                                     MSICODE_PRODUCT, 42, "label42", "prompt42");
2164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2165
2166     CHECK_REG_STR(media, "1", "label;prompt");
2167     CHECK_REG_STR(media, "42", "label42;prompt42");
2168
2169     /* dwDiskId is 0 */
2170     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2171                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2172                                     MSICODE_PRODUCT, 0, "label0", "prompt0");
2173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2174
2175     CHECK_REG_STR(media, "0", "label0;prompt0");
2176     CHECK_REG_STR(media, "1", "label;prompt");
2177     CHECK_REG_STR(media, "42", "label42;prompt42");
2178
2179     /* dwDiskId is < 0 */
2180     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2181                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2182                                     MSICODE_PRODUCT, -1, "label-1", "prompt-1");
2183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2184
2185     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2186     CHECK_REG_STR(media, "0", "label0;prompt0");
2187     CHECK_REG_STR(media, "1", "label;prompt");
2188     CHECK_REG_STR(media, "42", "label42;prompt42");
2189
2190     /* update dwDiskId 1 */
2191     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2192                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2193                                     MSICODE_PRODUCT, 1, "newlabel", "newprompt");
2194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2195
2196     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2197     CHECK_REG_STR(media, "0", "label0;prompt0");
2198     CHECK_REG_STR(media, "1", "newlabel;newprompt");
2199     CHECK_REG_STR(media, "42", "label42;prompt42");
2200
2201     /* update dwDiskId 1, szPrompt is NULL */
2202     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2203                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2204                                     MSICODE_PRODUCT, 1, "etiqueta", NULL);
2205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2206
2207     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2208     CHECK_REG_STR(media, "0", "label0;prompt0");
2209     CHECK_REG_STR(media, "1", "etiqueta;");
2210     CHECK_REG_STR(media, "42", "label42;prompt42");
2211
2212     /* update dwDiskId 1, szPrompt is empty */
2213     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2214                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2215                                     MSICODE_PRODUCT, 1, "etikett", "");
2216     ok(r == ERROR_INVALID_PARAMETER,
2217        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2218
2219     /* update dwDiskId 1, szVolumeLabel is NULL */
2220     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2221                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2222                                     MSICODE_PRODUCT, 1, NULL, "provocar");
2223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2224
2225     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2226     CHECK_REG_STR(media, "0", "label0;prompt0");
2227     CHECK_REG_STR(media, "1", ";provocar");
2228     CHECK_REG_STR(media, "42", "label42;prompt42");
2229
2230     /* update dwDiskId 1, szVolumeLabel is empty */
2231     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2232                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2233                                     MSICODE_PRODUCT, 1, "", "provoquer");
2234     ok(r == ERROR_INVALID_PARAMETER,
2235        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2236
2237     /* szUserSid is NULL */
2238     r = pMsiSourceListAddMediaDiskA(prodcode, NULL,
2239                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2240                                     MSICODE_PRODUCT, 1, NULL, "provoquer");
2241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2242
2243     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2244     CHECK_REG_STR(media, "0", "label0;prompt0");
2245     CHECK_REG_STR(media, "1", ";provoquer");
2246     CHECK_REG_STR(media, "42", "label42;prompt42");
2247
2248     RegDeleteValueA(media, "-1");
2249     RegDeleteValueA(media, "0");
2250     RegDeleteValueA(media, "1");
2251     RegDeleteValueA(media, "42");
2252     RegDeleteKeyA(media, "");
2253     RegCloseKey(media);
2254     RegDeleteKeyA(source, "");
2255     RegCloseKey(source);
2256     RegDeleteKeyA(userkey, "");
2257     RegCloseKey(userkey);
2258
2259     /* MSIINSTALLCONTEXT_USERMANAGED */
2260
2261     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2262     lstrcatA(keypath, usersid);
2263     lstrcatA(keypath, "\\Installer\\Products\\");
2264     lstrcatA(keypath, prod_squashed);
2265
2266     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
2267     if (res != ERROR_SUCCESS)
2268     {
2269         skip("Product key creation failed with error code %u\n", res);
2270         goto machine_tests;
2271     }
2272
2273     /* user product key exists */
2274     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2275                                     MSIINSTALLCONTEXT_USERMANAGED,
2276                                     MSICODE_PRODUCT, 1, "label", "prompt");
2277     ok(r == ERROR_BAD_CONFIGURATION,
2278        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2279
2280     res = RegCreateKeyA(userkey, "SourceList", &source);
2281     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2282
2283     /* SourceList key exists */
2284     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2285                                     MSIINSTALLCONTEXT_USERMANAGED,
2286                                     MSICODE_PRODUCT, 1, "label", "prompt");
2287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2288
2289     /* Media subkey is created by MsiSourceListAddMediaDisk */
2290     res = RegOpenKeyA(source, "Media", &media);
2291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2292
2293     CHECK_REG_STR(media, "1", "label;prompt");
2294
2295     RegDeleteValueA(media, "1");
2296     RegDeleteKeyA(media, "");
2297     RegCloseKey(media);
2298     RegDeleteKeyA(source, "");
2299     RegCloseKey(source);
2300     RegDeleteKeyA(userkey, "");
2301     RegCloseKey(userkey);
2302
2303     /* MSIINSTALLCONTEXT_MACHINE */
2304
2305 machine_tests:
2306     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2307     lstrcatA(keypath, prod_squashed);
2308
2309     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
2310     if (res != ERROR_SUCCESS)
2311     {
2312         skip("Product key creation failed with error code %u\n", res);
2313         LocalFree(usersid);
2314         return;
2315     }
2316
2317     /* machine product key exists */
2318     r = pMsiSourceListAddMediaDiskA(prodcode, NULL,
2319                                     MSIINSTALLCONTEXT_MACHINE,
2320                                     MSICODE_PRODUCT, 1, "label", "prompt");
2321     ok(r == ERROR_BAD_CONFIGURATION,
2322        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2323
2324     res = RegCreateKeyA(prodkey, "SourceList", &source);
2325     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2326
2327     /* SourceList key exists */
2328     r = pMsiSourceListAddMediaDiskA(prodcode, NULL,
2329                                     MSIINSTALLCONTEXT_MACHINE,
2330                                     MSICODE_PRODUCT, 1, "label", "prompt");
2331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2332
2333     /* Media subkey is created by MsiSourceListAddMediaDisk */
2334     res = RegOpenKeyA(source, "Media", &media);
2335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2336
2337     CHECK_REG_STR(media, "1", "label;prompt");
2338
2339     /* szUserSid is non-NULL */
2340     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2341                                     MSIINSTALLCONTEXT_MACHINE,
2342                                     MSICODE_PRODUCT, 1, "label", "prompt");
2343     ok(r == ERROR_INVALID_PARAMETER,
2344        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2345
2346     RegDeleteValueA(media, "1");
2347     RegDeleteKeyA(media, "");
2348     RegCloseKey(media);
2349     RegDeleteKeyA(source, "");
2350     RegCloseKey(source);
2351     RegDeleteKeyA(prodkey, "");
2352     RegCloseKey(prodkey);
2353     LocalFree(usersid);
2354 }
2355
2356 static void test_MsiSourceListEnumMediaDisks(void)
2357 {
2358     CHAR prodcode[MAX_PATH];
2359     CHAR prod_squashed[MAX_PATH];
2360     CHAR keypath[MAX_PATH*2];
2361     CHAR label[MAX_PATH];
2362     CHAR prompt[MAX_PATH];
2363     HKEY prodkey, userkey;
2364     HKEY media, source;
2365     DWORD labelsz, promptsz;
2366     LPSTR usersid;
2367     DWORD val;
2368     DWORD id;
2369     LONG res;
2370     UINT r;
2371
2372     if (!pMsiSourceListEnumMediaDisksA)
2373     {
2374         win_skip("MsiSourceListEnumMediaDisksA is not available\n");
2375         return;
2376     }
2377
2378     create_test_guid(prodcode, prod_squashed);
2379     if (!get_user_sid(&usersid))
2380     {
2381         skip("User SID not available -> skipping MsiSourceListEnumMediaDisksA tests\n");
2382         return;
2383     }
2384
2385     /* GetLastError is not set by the function */
2386
2387     /* NULL szProductCodeOrPatchCode */
2388     labelsz = sizeof(label);
2389     promptsz = sizeof(prompt);
2390     r = pMsiSourceListEnumMediaDisksA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2391                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2392                                       prompt, &promptsz);
2393     ok(r == ERROR_INVALID_PARAMETER,
2394        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2395
2396     /* empty szProductCodeOrPatchCode */
2397     labelsz = sizeof(label);
2398     promptsz = sizeof(prompt);
2399     r = pMsiSourceListEnumMediaDisksA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2400                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2401                                       prompt, &promptsz);
2402     ok(r == ERROR_INVALID_PARAMETER,
2403        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2404
2405     /* garbage szProductCodeOrPatchCode */
2406     labelsz = sizeof(label);
2407     promptsz = sizeof(prompt);
2408     r = pMsiSourceListEnumMediaDisksA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2409                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2410                                       prompt, &promptsz);
2411     ok(r == ERROR_INVALID_PARAMETER,
2412        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2413
2414     /* guid without brackets */
2415     labelsz = sizeof(label);
2416     promptsz = sizeof(prompt);
2417     r = pMsiSourceListEnumMediaDisksA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
2418                                       usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2419                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2420                                       prompt, &promptsz);
2421     ok(r == ERROR_INVALID_PARAMETER,
2422        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2423
2424     /* guid with brackets */
2425     labelsz = sizeof(label);
2426     promptsz = sizeof(prompt);
2427     r = pMsiSourceListEnumMediaDisksA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2428                                       usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2429                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2430                                       prompt, &promptsz);
2431     ok(r == ERROR_UNKNOWN_PRODUCT,
2432        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2433
2434     /* dwOptions has MSISOURCETYPE_NETWORK */
2435     labelsz = sizeof(label);
2436     promptsz = sizeof(prompt);
2437     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2438                                       MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
2439                                       0, &id, label, &labelsz,
2440                                       prompt, &promptsz);
2441     ok(r == ERROR_INVALID_PARAMETER,
2442        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2443
2444     /* dwOptions has MSISOURCETYPE_URL */
2445     labelsz = sizeof(label);
2446     promptsz = sizeof(prompt);
2447     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2448                                       MSICODE_PRODUCT | MSISOURCETYPE_URL,
2449                                       0, &id, label, &labelsz,
2450                                       prompt, &promptsz);
2451     ok(r == ERROR_INVALID_PARAMETER,
2452        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2453
2454     /* dwIndex is non-zero */
2455     labelsz = sizeof(label);
2456     promptsz = sizeof(prompt);
2457     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2458                                       MSICODE_PRODUCT, 1, &id, label, &labelsz,
2459                                       prompt, &promptsz);
2460     ok(r == ERROR_INVALID_PARAMETER,
2461        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2462
2463     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2464
2465     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2466     lstrcatA(keypath, prod_squashed);
2467
2468     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2470
2471     /* user product key exists */
2472     labelsz = sizeof(label);
2473     promptsz = sizeof(prompt);
2474     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2475                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2476                                       prompt, &promptsz);
2477     ok(r == ERROR_BAD_CONFIGURATION,
2478        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2479
2480     res = RegCreateKeyA(userkey, "SourceList", &source);
2481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2482
2483     /* SourceList key exists */
2484     id = 0xbeef;
2485     lstrcpyA(label, "aaa");
2486     labelsz = 0xdeadbeef;
2487     lstrcpyA(prompt, "bbb");
2488     promptsz = 0xdeadbeef;
2489     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2490                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2491                                       prompt, &promptsz);
2492     ok(r == ERROR_NO_MORE_ITEMS,
2493        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2494     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
2495     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2496     ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz);
2497     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2498     ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz);
2499
2500     res = RegCreateKeyA(source, "Media", &media);
2501     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2502
2503     /* Media key exists */
2504     id = 0xbeef;
2505     lstrcpyA(label, "aaa");
2506     labelsz = 0xdeadbeef;
2507     lstrcpyA(prompt, "bbb");
2508     promptsz = 0xdeadbeef;
2509     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2510                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2511                                       prompt, &promptsz);
2512     ok(r == ERROR_NO_MORE_ITEMS,
2513        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2514     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
2515     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2516     ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz);
2517     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2518     ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz);
2519
2520     res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)"label;prompt", 13);
2521     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2522
2523     /* disk exists */
2524     id = 0;
2525     lstrcpyA(label, "aaa");
2526     labelsz = MAX_PATH;
2527     lstrcpyA(prompt, "bbb");
2528     promptsz = MAX_PATH;
2529     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2530                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2531                                       prompt, &promptsz);
2532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2533     ok(id == 1, "Expected 1, got %d\n", id);
2534     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2535     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2536     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2537     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2538
2539     res = RegSetValueExA(media, "2", 0, REG_SZ, (LPBYTE)"one;two", 8);
2540     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2541
2542     /* now disk 2 exists, get the sizes */
2543     id = 0;
2544     labelsz = MAX_PATH;
2545     promptsz = MAX_PATH;
2546     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2547                                       MSICODE_PRODUCT, 1, &id, NULL, &labelsz,
2548                                       NULL, &promptsz);
2549     ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER,
2550       "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r);
2551     if (r == ERROR_SUCCESS)
2552     {
2553         ok(id == 2, "Expected 2, got %d\n", id);
2554         ok(labelsz == 3, "Expected 3, got %d\n", labelsz);
2555         ok(promptsz == 3, "Expected 3, got %d\n", promptsz);
2556     }
2557
2558     /* now fill in the values */
2559     id = 0xbeef;
2560     lstrcpyA(label, "aaa");
2561     labelsz = MAX_PATH;
2562     lstrcpyA(prompt, "bbb");
2563     promptsz = MAX_PATH;
2564     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2565                                       MSICODE_PRODUCT, 1, &id, label, &labelsz,
2566                                       prompt, &promptsz);
2567     ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER,
2568        "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r);
2569     if (r == ERROR_SUCCESS)
2570     {
2571         ok(id == 2, "Expected 2, got %d\n", id);
2572         ok(!lstrcmpA(label, "one"), "Expected \"one\", got \"%s\"\n", label);
2573         ok(labelsz == 3, "Expected 3, got %d\n", labelsz);
2574         ok(!lstrcmpA(prompt, "two"), "Expected \"two\", got \"%s\"\n", prompt);
2575         ok(promptsz == 3, "Expected 3, got %d\n", promptsz);
2576     }
2577     else if (r == ERROR_INVALID_PARAMETER)
2578     {
2579         ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
2580         ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2581         ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz);
2582         ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2583         ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz);
2584     }
2585
2586     res = RegSetValueExA(media, "4", 0, REG_SZ, (LPBYTE)"three;four", 11);
2587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2588
2589     /* disks 1, 2, 4 exist, reset the enumeration */
2590     id = 0;
2591     lstrcpyA(label, "aaa");
2592     labelsz = MAX_PATH;
2593     lstrcpyA(prompt, "bbb");
2594     promptsz = MAX_PATH;
2595     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2596                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2597                                       prompt, &promptsz);
2598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2599     ok(id == 1, "Expected 1, got %d\n", id);
2600     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2601     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2602     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2603     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2604
2605     /* disks 1, 2, 4 exist, index 1 */
2606     id = 0;
2607     lstrcpyA(label, "aaa");
2608     labelsz = MAX_PATH;
2609     lstrcpyA(prompt, "bbb");
2610     promptsz = MAX_PATH;
2611     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2612                                       MSICODE_PRODUCT, 1, &id, label, &labelsz,
2613                                       prompt, &promptsz);
2614     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2615     ok(id == 2, "Expected 2, got %d\n", id);
2616     ok(!lstrcmpA(label, "one"), "Expected \"one\", got \"%s\"\n", label);
2617     ok(labelsz == 3, "Expected 3, got %d\n", labelsz);
2618     ok(!lstrcmpA(prompt, "two"), "Expected \"two\", got \"%s\"\n", prompt);
2619     ok(promptsz == 3, "Expected 3, got %d\n", promptsz);
2620
2621     /* disks 1, 2, 4 exist, index 2 */
2622     id = 0;
2623     lstrcpyA(label, "aaa");
2624     labelsz = MAX_PATH;
2625     lstrcpyA(prompt, "bbb");
2626     promptsz = MAX_PATH;
2627     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2628                                       MSICODE_PRODUCT, 2, &id, label, &labelsz,
2629                                       prompt, &promptsz);
2630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2631     ok(id == 4, "Expected 4, got %d\n", id);
2632     ok(!lstrcmpA(label, "three"), "Expected \"three\", got \"%s\"\n", label);
2633     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2634     ok(!lstrcmpA(prompt, "four"), "Expected \"four\", got \"%s\"\n", prompt);
2635     ok(promptsz == 4, "Expected 4, got %d\n", promptsz);
2636
2637     /* disks 1, 2, 4 exist, index 3, invalid */
2638     id = 0xbeef;
2639     lstrcpyA(label, "aaa");
2640     labelsz = MAX_PATH;
2641     lstrcpyA(prompt, "bbb");
2642     promptsz = MAX_PATH;
2643     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2644                                       MSICODE_PRODUCT, 3, &id, label, &labelsz,
2645                                       prompt, &promptsz);
2646     ok(r == ERROR_NO_MORE_ITEMS,
2647        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2648     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
2649     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2650     ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz);
2651     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2652     ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz);
2653
2654     /* disks 1, 2, 4 exist, reset the enumeration */
2655     id = 0;
2656     lstrcpyA(label, "aaa");
2657     labelsz = MAX_PATH;
2658     lstrcpyA(prompt, "bbb");
2659     promptsz = MAX_PATH;
2660     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2661                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2662                                       prompt, &promptsz);
2663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2664     ok(id == 1, "Expected 1, got %d\n", id);
2665     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2666     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2667     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2668     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2669
2670     /* try index 0 again */
2671     id = 0;
2672     lstrcpyA(label, "aaa");
2673     labelsz = MAX_PATH;
2674     lstrcpyA(prompt, "bbb");
2675     promptsz = MAX_PATH;
2676     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2677                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2678                                       prompt, &promptsz);
2679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2680     ok(id == 1, "Expected 1, got %d\n", id);
2681     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2682     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2683     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2684     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2685
2686     /* jump to index 2 */
2687     id = 0xbeef;
2688     lstrcpyA(label, "aaa");
2689     labelsz = MAX_PATH;
2690     lstrcpyA(prompt, "bbb");
2691     promptsz = MAX_PATH;
2692     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2693                                       MSICODE_PRODUCT, 2, &id, label, &labelsz,
2694                                       prompt, &promptsz);
2695     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2696     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
2697     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2698     ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz);
2699     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2700     ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz);
2701
2702     /* after error, try index 1 */
2703     id = 0xbeef;
2704     lstrcpyA(label, "aaa");
2705     labelsz = MAX_PATH;
2706     lstrcpyA(prompt, "bbb");
2707     promptsz = MAX_PATH;
2708     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2709                                       MSICODE_PRODUCT, 1, &id, label, &labelsz,
2710                                       prompt, &promptsz);
2711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2712     ok(id == 2, "Expected 2, got %d\n", id);
2713     ok(!lstrcmpA(label, "one"), "Expected \"one\", got \"%s\"\n", label);
2714     ok(labelsz == 3, "Expected 3, got %d\n", labelsz);
2715     ok(!lstrcmpA(prompt, "two"), "Expected \"two\", got \"%s\"\n", prompt);
2716     ok(promptsz == 3, "Expected 3, got %d\n", promptsz);
2717
2718     /* try index 1 again */
2719     id = 0xbeef;
2720     lstrcpyA(label, "aaa");
2721     labelsz = MAX_PATH;
2722     lstrcpyA(prompt, "bbb");
2723     promptsz = MAX_PATH;
2724     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2725                                       MSICODE_PRODUCT, 1, &id, label, &labelsz,
2726                                       prompt, &promptsz);
2727     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2728     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
2729     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2730     ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz);
2731     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2732     ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz);
2733
2734     /* NULL pdwDiskId */
2735     lstrcpyA(label, "aaa");
2736     labelsz = MAX_PATH;
2737     lstrcpyA(prompt, "bbb");
2738     promptsz = MAX_PATH;
2739     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2740                                       MSICODE_PRODUCT, 0, NULL, label, &labelsz,
2741                                       prompt, &promptsz);
2742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2743     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2744     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2745     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2746     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2747
2748     /* szVolumeLabel is NULL */
2749     id = 0;
2750     labelsz = MAX_PATH;
2751     lstrcpyA(prompt, "bbb");
2752     promptsz = MAX_PATH;
2753     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2754                                       MSICODE_PRODUCT, 0, &id, NULL, &labelsz,
2755                                       prompt, &promptsz);
2756     ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER,
2757       "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r);
2758     if (r == ERROR_SUCCESS)
2759     {
2760         ok(id == 1, "Expected 1, got %d\n", id);
2761         ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2762         ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2763         ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2764     }
2765
2766     /* szVolumeLabel and pcchVolumeLabel are NULL */
2767     id = 0;
2768     lstrcpyA(prompt, "bbb");
2769     promptsz = MAX_PATH;
2770     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2771                                       MSICODE_PRODUCT, 0, &id, NULL, NULL,
2772                                       prompt, &promptsz);
2773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2774     ok(id == 1, "Expected 1, got %d\n", id);
2775     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2776     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2777
2778     /* szVolumeLabel is non-NULL while pcchVolumeLabel is NULL */
2779     id = 0xbeef;
2780     lstrcpyA(label, "aaa");
2781     lstrcpyA(prompt, "bbb");
2782     promptsz = MAX_PATH;
2783     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2784                                       MSICODE_PRODUCT, 0, &id, label, NULL,
2785                                       prompt, &promptsz);
2786     ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER,
2787       "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r);
2788     if (r == ERROR_SUCCESS)
2789     {
2790         ok(id == 1, "Expected 1, got %d\n", id);
2791         ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2792         ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2793         ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2794     }
2795
2796     /* szDiskPrompt is NULL */
2797     id = 0;
2798     lstrcpyA(label, "aaa");
2799     labelsz = MAX_PATH;
2800     promptsz = MAX_PATH;
2801     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2802                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2803                                       NULL, &promptsz);
2804     ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER, "Expected ERROR_SUCCESS, got %d\n", r);
2805     if (r == ERROR_SUCCESS)
2806     {
2807         ok(id == 1, "Expected 1, got %d\n", id);
2808         ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2809         ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2810         ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2811     }
2812
2813     /* szDiskPrompt and pcchDiskPrompt are NULL */
2814     id = 0;
2815     lstrcpyA(label, "aaa");
2816     labelsz = MAX_PATH;
2817     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2818                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2819                                       NULL, NULL);
2820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2821     ok(id == 1, "Expected 1, got %d\n", id);
2822     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2823     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2824
2825     /* szDiskPrompt is non-NULL while pcchDiskPrompt is NULL */
2826     id = 0xbeef;
2827     lstrcpyA(label, "aaa");
2828     labelsz = MAX_PATH;
2829     lstrcpyA(prompt, "bbb");
2830     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2831                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2832                                       prompt, NULL);
2833     ok(r == ERROR_INVALID_PARAMETER,
2834        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2835     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
2836     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2837     ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz);
2838     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2839
2840     /* pcchVolumeLabel is exactly 5 */
2841     lstrcpyA(label, "aaa");
2842     labelsz = 5;
2843     lstrcpyA(prompt, "bbb");
2844     promptsz = MAX_PATH;
2845     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2846                                       MSICODE_PRODUCT, 0, NULL, label, &labelsz,
2847                                       prompt, &promptsz);
2848     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2849     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2850     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2851     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2852     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2853
2854     /* pcchDiskPrompt is exactly 6 */
2855     lstrcpyA(label, "aaa");
2856     labelsz = MAX_PATH;
2857     lstrcpyA(prompt, "bbb");
2858     promptsz = 6;
2859     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2860                                       MSICODE_PRODUCT, 0, NULL, label, &labelsz,
2861                                       prompt, &promptsz);
2862     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2863     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
2864     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2865     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
2866     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2867
2868     res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)"label", 13);
2869     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2870
2871     /* no semicolon */
2872     id = 0;
2873     lstrcpyA(label, "aaa");
2874     labelsz = MAX_PATH;
2875     lstrcpyA(prompt, "bbb");
2876     promptsz = MAX_PATH;
2877     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2878                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2879                                       prompt, &promptsz);
2880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2881     ok(id == 1, "Expected 1, got %d\n", id);
2882     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2883     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2884     ok(!lstrcmpA(prompt, "label"), "Expected \"label\", got \"%s\"\n", prompt);
2885     ok(promptsz == 5, "Expected 5, got %d\n", promptsz);
2886
2887     res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)"label;", 13);
2888     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2889
2890     /* semicolon, no disk prompt */
2891     id = 0;
2892     lstrcpyA(label, "aaa");
2893     labelsz = MAX_PATH;
2894     lstrcpyA(prompt, "bbb");
2895     promptsz = MAX_PATH;
2896     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2897                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2898                                       prompt, &promptsz);
2899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2900     ok(id == 1, "Expected 1, got %d\n", id);
2901     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
2902     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
2903     ok(!lstrcmpA(prompt, ""), "Expected \"\", got \"%s\"\n", prompt);
2904     ok(promptsz == 0, "Expected 0, got %d\n", promptsz);
2905
2906     res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)";prompt", 13);
2907     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2908
2909     /* semicolon, label doesn't exist */
2910     id = 0;
2911     lstrcpyA(label, "aaa");
2912     labelsz = MAX_PATH;
2913     lstrcpyA(prompt, "bbb");
2914     promptsz = MAX_PATH;
2915     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2916                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2917                                       prompt, &promptsz);
2918     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2919     ok(id == 1, "Expected 1, got %d\n", id);
2920     ok(!lstrcmpA(label, ""), "Expected \"\", got \"%s\"\n", label);
2921     ok(labelsz == 0, "Expected 0, got %d\n", labelsz);
2922     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
2923     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
2924
2925     res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)";", 13);
2926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2927
2928     /* semicolon, neither label nor disk prompt exist */
2929     id = 0;
2930     lstrcpyA(label, "aaa");
2931     labelsz = MAX_PATH;
2932     lstrcpyA(prompt, "bbb");
2933     promptsz = MAX_PATH;
2934     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2935                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2936                                       prompt, &promptsz);
2937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2938     ok(id == 1, "Expected 1, got %d\n", id);
2939     ok(!lstrcmpA(label, ""), "Expected \"\", got \"%s\"\n", label);
2940     ok(labelsz == 0, "Expected 0, got %d\n", labelsz);
2941     ok(!lstrcmpA(prompt, ""), "Expected \"\", got \"%s\"\n", prompt);
2942     ok(promptsz == 0, "Expected 0, got %d\n", promptsz);
2943
2944     val = 42;
2945     res = RegSetValueExA(media, "1", 0, REG_DWORD, (LPBYTE)&val, sizeof(DWORD));
2946     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2947
2948     /* type is REG_DWORD */
2949     id = 0;
2950     lstrcpyA(label, "aaa");
2951     labelsz = MAX_PATH;
2952     lstrcpyA(prompt, "bbb");
2953     promptsz = MAX_PATH;
2954     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2955                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2956                                       prompt, &promptsz);
2957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2958     ok(id == 1, "Expected 1, got %d\n", id);
2959     ok(!lstrcmpA(label, "#42"), "Expected \"#42\", got \"%s\"\n", label);
2960     ok(labelsz == 3, "Expected 3, got %d\n", labelsz);
2961     ok(!lstrcmpA(prompt, "#42"), "Expected \"#42\", got \"%s\"\n", prompt);
2962     ok(promptsz == 3, "Expected 3, got %d\n", promptsz);
2963
2964     RegDeleteValueA(media, "1");
2965     RegDeleteValueA(media, "2");
2966     RegDeleteValueA(media, "4");
2967     RegDeleteKeyA(media, "");
2968     RegCloseKey(media);
2969     RegDeleteKeyA(source, "");
2970     RegCloseKey(source);
2971     RegDeleteKeyA(userkey, "");
2972     RegCloseKey(userkey);
2973
2974     /* MSIINSTALLCONTEXT_USERMANAGED */
2975
2976     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2977     lstrcatA(keypath, usersid);
2978     lstrcatA(keypath, "\\Installer\\Products\\");
2979     lstrcatA(keypath, prod_squashed);
2980
2981     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
2982     if (res != ERROR_SUCCESS)
2983     {
2984         skip("Product key creation failed with error code %u\n", res);
2985         goto machine_tests;
2986     }
2987
2988     /* user product key exists */
2989     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
2990                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
2991                                       prompt, &promptsz);
2992     ok(r == ERROR_BAD_CONFIGURATION,
2993        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2994
2995     res = RegCreateKeyA(userkey, "SourceList", &source);
2996     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2997
2998     /* SourceList key exists */
2999     id = 0xbeef;
3000     lstrcpyA(label, "aaa");
3001     labelsz = 0xdeadbeef;
3002     lstrcpyA(prompt, "bbb");
3003     promptsz = 0xdeadbeef;
3004     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
3005                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3006                                       prompt, &promptsz);
3007     ok(r == ERROR_NO_MORE_ITEMS,
3008        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3009     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
3010     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
3011     ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz);
3012     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
3013     ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz);
3014
3015     res = RegCreateKeyA(source, "Media", &media);
3016     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3017
3018     /* Media key exists */
3019     id = 0xbeef;
3020     lstrcpyA(label, "aaa");
3021     labelsz = 0xdeadbeef;
3022     lstrcpyA(prompt, "bbb");
3023     promptsz = 0xdeadbeef;
3024     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
3025                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3026                                       prompt, &promptsz);
3027     ok(r == ERROR_NO_MORE_ITEMS,
3028        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3029     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
3030     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
3031     ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz);
3032     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
3033     ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz);
3034
3035     res = RegSetValueExA(media, "2", 0, REG_SZ, (LPBYTE)"label;prompt", 13);
3036     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3037
3038     /* disk exists, but no id 1 */
3039     id = 0;
3040     lstrcpyA(label, "aaa");
3041     labelsz = MAX_PATH;
3042     lstrcpyA(prompt, "bbb");
3043     promptsz = MAX_PATH;
3044     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
3045                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3046                                       prompt, &promptsz);
3047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3048     ok(id == 2, "Expected 2, got %d\n", id);
3049     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
3050     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
3051     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
3052     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
3053
3054     RegDeleteValueA(media, "2");
3055     RegDeleteKeyA(media, "");
3056     RegCloseKey(media);
3057     RegDeleteKeyA(source, "");
3058     RegCloseKey(source);
3059     RegDeleteKeyA(userkey, "");
3060     RegCloseKey(userkey);
3061
3062     /* MSIINSTALLCONTEXT_MACHINE */
3063
3064 machine_tests:
3065     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3066     lstrcatA(keypath, prod_squashed);
3067
3068     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
3069     if (res != ERROR_SUCCESS)
3070     {
3071         skip("Product key creation failed with error code %u\n", res);
3072         LocalFree(usersid);
3073         return;
3074     }
3075
3076     /* machine product key exists */
3077     r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
3078                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3079                                       prompt, &promptsz);
3080     ok(r == ERROR_BAD_CONFIGURATION,
3081        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
3082
3083     res = RegCreateKeyA(prodkey, "SourceList", &source);
3084     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3085
3086     /* SourceList key exists */
3087     id = 0xbeef;
3088     lstrcpyA(label, "aaa");
3089     labelsz = 0xdeadbeef;
3090     lstrcpyA(prompt, "bbb");
3091     promptsz = 0xdeadbeef;
3092     r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
3093                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3094                                       prompt, &promptsz);
3095     ok(r == ERROR_NO_MORE_ITEMS,
3096        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3097     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
3098     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
3099     ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz);
3100     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
3101     ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz);
3102
3103     res = RegCreateKeyA(source, "Media", &media);
3104     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3105
3106     /* Media key exists */
3107     id = 0xbeef;
3108     lstrcpyA(label, "aaa");
3109     labelsz = 0xdeadbeef;
3110     lstrcpyA(prompt, "bbb");
3111     promptsz = 0xdeadbeef;
3112     r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
3113                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3114                                       prompt, &promptsz);
3115     ok(r == ERROR_NO_MORE_ITEMS,
3116        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3117     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
3118     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
3119     ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz);
3120     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
3121     ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz);
3122
3123     res = RegSetValueExA(media, "2", 0, REG_SZ, (LPBYTE)"label;prompt", 13);
3124     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3125
3126     /* disk exists, but no id 1 */
3127     id = 0;
3128     lstrcpyA(label, "aaa");
3129     labelsz = MAX_PATH;
3130     lstrcpyA(prompt, "bbb");
3131     promptsz = MAX_PATH;
3132     r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
3133                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3134                                       prompt, &promptsz);
3135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3136     ok(id == 2, "Expected 2, got %d\n", id);
3137     ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label);
3138     ok(labelsz == 5, "Expected 5, got %d\n", labelsz);
3139     ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt);
3140     ok(promptsz == 6, "Expected 6, got %d\n", promptsz);
3141
3142     /* szUserSid is non-NULL */
3143     id = 0xbeef;
3144     lstrcpyA(label, "aaa");
3145     labelsz = MAX_PATH;
3146     lstrcpyA(prompt, "bbb");
3147     promptsz = MAX_PATH;
3148     r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
3149                                       MSICODE_PRODUCT, 0, &id, label, &labelsz,
3150                                       prompt, &promptsz);
3151     ok(r == ERROR_INVALID_PARAMETER,
3152        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3153     ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id);
3154     ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label);
3155     ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz);
3156     ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt);
3157     ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz);
3158
3159     RegDeleteValueA(media, "2");
3160     RegDeleteKeyA(media, "");
3161     RegCloseKey(media);
3162     RegDeleteKeyA(source, "");
3163     RegCloseKey(source);
3164     RegDeleteKeyA(prodkey, "");
3165     RegCloseKey(prodkey);
3166     LocalFree(usersid);
3167 }
3168
3169 static void test_MsiSourceListAddSource(void)
3170 {
3171     CHAR prodcode[MAX_PATH];
3172     CHAR prod_squashed[MAX_PATH];
3173     CHAR keypath[MAX_PATH*2];
3174     CHAR username[MAX_PATH];
3175     LPSTR usersid, ptr;
3176     LONG res;
3177     UINT r;
3178     HKEY prodkey, userkey;
3179     HKEY net, source;
3180     DWORD size;
3181
3182     if (!pMsiSourceListAddSourceA)
3183     {
3184         win_skip("Skipping MsiSourceListAddSourceA tests\n");
3185         return;
3186     }
3187
3188     create_test_guid(prodcode, prod_squashed);
3189     if (!get_user_sid(&usersid))
3190     {
3191         skip("User SID not available -> skipping MsiSourceListAddSourceA tests\n");
3192         return;
3193     }
3194
3195     /* MACHINENAME\username */
3196     size = MAX_PATH;
3197     if (pGetUserNameExA != NULL)
3198         pGetUserNameExA(NameSamCompatible, username, &size);
3199     else
3200     {
3201         GetComputerNameA(username, &size);
3202         lstrcatA(username, "\\");
3203         ptr = username + lstrlenA(username);
3204         size = MAX_PATH - (ptr - username);
3205         GetUserNameA(ptr, &size);
3206     }
3207     trace("username: %s\n", username);
3208
3209     /* GetLastError is not set by the function */
3210
3211     /* NULL szProduct */
3212     r = pMsiSourceListAddSourceA(NULL, username, 0, "source");
3213     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3214
3215     /* empty szProduct */
3216     r = pMsiSourceListAddSourceA("", username, 0, "source");
3217     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3218
3219     /* garbage szProduct */
3220     r = pMsiSourceListAddSourceA("garbage", username, 0, "source");
3221     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3222
3223     /* guid without brackets */
3224     r = pMsiSourceListAddSourceA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", username, 0, "source");
3225     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3226
3227     /* guid with brackets */
3228     r = pMsiSourceListAddSourceA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", username, 0, "source");
3229     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3230
3231     /* dwReserved is not 0 */
3232     r = pMsiSourceListAddSourceA(prodcode, username, 42, "source");
3233     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3234
3235     /* szSource is NULL */
3236     r = pMsiSourceListAddSourceA(prodcode, username, 0, NULL);
3237     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3238
3239     /* szSource is empty */
3240     r = pMsiSourceListAddSourceA(prodcode, username, 0, "");
3241     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3242
3243     /* MSIINSTALLCONTEXT_USERMANAGED */
3244
3245     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3246     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3247
3248     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
3249     lstrcatA(keypath, usersid);
3250     lstrcatA(keypath, "\\Installer\\Products\\");
3251     lstrcatA(keypath, prod_squashed);
3252
3253     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
3254     if (res != ERROR_SUCCESS)
3255     {
3256         skip("Product key creation failed with error code %u\n", res);
3257         goto userunmanaged_tests;
3258     }
3259
3260     /* user product key exists */
3261     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3262     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
3263
3264     res = RegCreateKeyA(userkey, "SourceList", &source);
3265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3266
3267     /* SourceList key exists */
3268     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3270
3271     /* Net key is created */
3272     res = RegOpenKeyA(source, "Net", &net);
3273     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3274
3275     /* LastUsedSource does not exist and it is not created */
3276     res = RegQueryValueExA(source, "LastUsedSource", 0, NULL, NULL, NULL);
3277     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3278
3279     CHECK_REG_STR(net, "1", "source\\");
3280
3281     RegDeleteValueA(net, "1");
3282     RegDeleteKeyA(net, "");
3283     RegCloseKey(net);
3284
3285     res = RegSetValueExA(source, "LastUsedSource", 0, REG_SZ, (LPBYTE)"blah", 5);
3286     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3287
3288     /* LastUsedSource value exists */
3289     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3291
3292     /* Net key is created */
3293     res = RegOpenKeyA(source, "Net", &net);
3294     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3295
3296     CHECK_REG_STR(source, "LastUsedSource", "blah");
3297     CHECK_REG_STR(net, "1", "source\\");
3298
3299     RegDeleteValueA(net, "1");
3300     RegDeleteKeyA(net, "");
3301     RegCloseKey(net);
3302
3303     res = RegSetValueExA(source, "LastUsedSource", 0, REG_SZ, (LPBYTE)"5", 2);
3304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3305
3306     /* LastUsedSource is an integer */
3307     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3309
3310     /* Net key is created */
3311     res = RegOpenKeyA(source, "Net", &net);
3312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3313
3314     CHECK_REG_STR(source, "LastUsedSource", "5");
3315     CHECK_REG_STR(net, "1", "source\\");
3316
3317     /* Add a second source, has trailing backslash */
3318     r = pMsiSourceListAddSourceA(prodcode, username, 0, "another\\");
3319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3320
3321     CHECK_REG_STR(source, "LastUsedSource", "5");
3322     CHECK_REG_STR(net, "1", "source\\");
3323     CHECK_REG_STR(net, "2", "another\\");
3324
3325     res = RegSetValueExA(source, "LastUsedSource", 0, REG_SZ, (LPBYTE)"2", 2);
3326     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3327
3328     /* LastUsedSource is in the source list */
3329     r = pMsiSourceListAddSourceA(prodcode, username, 0, "third/");
3330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3331
3332     CHECK_REG_STR(source, "LastUsedSource", "2");
3333     CHECK_REG_STR(net, "1", "source\\");
3334     CHECK_REG_STR(net, "2", "another\\");
3335     CHECK_REG_STR(net, "3", "third/\\");
3336
3337     RegDeleteValueA(net, "1");
3338     RegDeleteValueA(net, "2");
3339     RegDeleteValueA(net, "3");
3340     RegDeleteKeyA(net, "");
3341     RegCloseKey(net);
3342     RegDeleteKeyA(source, "");
3343     RegCloseKey(source);
3344     RegDeleteKeyA(userkey, "");
3345     RegCloseKey(userkey);
3346
3347     /* MSIINSTALLCONTEXT_USERUNMANAGED */
3348
3349 userunmanaged_tests:
3350     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3351     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3352
3353     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3354     lstrcatA(keypath, prod_squashed);
3355
3356     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
3357     if (res != ERROR_SUCCESS)
3358     {
3359         skip("Product key creation failed with error code %u\n", res);
3360         goto machine_tests;
3361     }
3362
3363     /* user product key exists */
3364     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3365     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
3366
3367     res = RegCreateKeyA(userkey, "SourceList", &source);
3368     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3369
3370     /* SourceList key exists */
3371     r = pMsiSourceListAddSourceA(prodcode, username, 0, "source");
3372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3373
3374     /* Net key is created */
3375     res = RegOpenKeyA(source, "Net", &net);
3376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3377
3378     CHECK_REG_STR(net, "1", "source\\");
3379
3380     RegDeleteValueA(net, "1");
3381     RegDeleteKeyA(net, "");
3382     RegCloseKey(net);
3383     RegDeleteKeyA(source, "");
3384     RegCloseKey(source);
3385     RegDeleteKeyA(userkey, "");
3386     RegCloseKey(userkey);
3387
3388     /* MSIINSTALLCONTEXT_MACHINE */
3389
3390 machine_tests:
3391     r = pMsiSourceListAddSourceA(prodcode, NULL, 0, "source");
3392     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3393
3394     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3395     lstrcatA(keypath, prod_squashed);
3396
3397     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
3398     if (res != ERROR_SUCCESS)
3399     {
3400         skip("Product key creation failed with error code %u\n", res);
3401         LocalFree(usersid);
3402         return;
3403     }
3404
3405     /* machine product key exists */
3406     r = pMsiSourceListAddSourceA(prodcode, NULL, 0, "source");
3407     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
3408
3409     res = RegCreateKeyA(prodkey, "SourceList", &source);
3410     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3411
3412     /* SourceList key exists */
3413     r = pMsiSourceListAddSourceA(prodcode, NULL, 0, "source");
3414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3415
3416     /* Net key is created */
3417     res = RegOpenKeyA(source, "Net", &net);
3418     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3419
3420     CHECK_REG_STR(net, "1", "source\\");
3421
3422     /* empty szUserName */
3423     r = pMsiSourceListAddSourceA(prodcode, "", 0, "another");
3424     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3425
3426     CHECK_REG_STR(net, "1", "source\\");
3427     CHECK_REG_STR(net, "2", "another\\");
3428
3429     RegDeleteValueA(net, "2");
3430     RegDeleteValueA(net, "1");
3431     RegDeleteKeyA(net, "");
3432     RegCloseKey(net);
3433     RegDeleteKeyA(source, "");
3434     RegCloseKey(source);
3435     RegDeleteKeyA(prodkey, "");
3436     RegCloseKey(prodkey);
3437     LocalFree(usersid);
3438 }
3439
3440 START_TEST(source)
3441 {
3442     init_functionpointers();
3443
3444     test_MsiSourceListGetInfo();
3445     test_MsiSourceListAddSourceEx();
3446     test_MsiSourceListEnumSources();
3447     test_MsiSourceListSetInfo();
3448     test_MsiSourceListAddMediaDisk();
3449     test_MsiSourceListEnumMediaDisks();
3450     test_MsiSourceListAddSource();
3451 }