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