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