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