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