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