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