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