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