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