msi/tests: Make tests run on win9x/NT4 again.
[wine] / dlls / msi / tests / source.c
1 /*
2  * Tests for MSI Source functions
3  *
4  * Copyright (C) 2006 James Hawkins
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define _WIN32_MSI 300
22
23 #include <stdio.h>
24
25 #include <windows.h>
26 #include <msiquery.h>
27 #include <msidefs.h>
28 #include <msi.h>
29 #include <sddl.h>
30
31 #include "wine/test.h"
32
33 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
34 static UINT (WINAPI *pMsiSourceListAddMediaDiskA)
35     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPCSTR, LPCSTR);
36 static UINT (WINAPI *pMsiSourceListAddSourceExA)
37     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, DWORD);
38 static UINT (WINAPI *pMsiSourceListEnumSourcesA)
39     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
40 static UINT (WINAPI *pMsiSourceListGetInfoA)
41     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
42 static UINT (WINAPI *pMsiSourceListSetInfoA)
43     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT,  DWORD,LPCSTR,  LPCSTR);
44
45 static void init_functionpointers(void)
46 {
47     HMODULE hmsi = GetModuleHandleA("msi.dll");
48     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
49
50 #define GET_PROC(dll, func) \
51     p ## func = (void *)GetProcAddress(dll, #func); \
52     if(!p ## func) \
53       trace("GetProcAddress(%s) failed\n", #func);
54
55     GET_PROC(hmsi, MsiSourceListAddMediaDiskA)
56     GET_PROC(hmsi, MsiSourceListAddSourceExA)
57     GET_PROC(hmsi, MsiSourceListEnumSourcesA)
58     GET_PROC(hmsi, MsiSourceListGetInfoA)
59     GET_PROC(hmsi, MsiSourceListSetInfoA)
60
61     GET_PROC(hadvapi32, ConvertSidToStringSidA)
62
63 #undef GET_PROC
64 }
65
66 /* copied from dlls/msi/registry.c */
67 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
68 {
69     DWORD i,n=1;
70     GUID guid;
71
72     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
73         return FALSE;
74
75     for(i=0; i<8; i++)
76         out[7-i] = in[n++];
77     n++;
78     for(i=0; i<4; i++)
79         out[11-i] = in[n++];
80     n++;
81     for(i=0; i<4; i++)
82         out[15-i] = in[n++];
83     n++;
84     for(i=0; i<2; i++)
85     {
86         out[17+i*2] = in[n++];
87         out[16+i*2] = in[n++];
88     }
89     n++;
90     for( ; i<8; i++)
91     {
92         out[17+i*2] = in[n++];
93         out[16+i*2] = in[n++];
94     }
95     out[32]=0;
96     return TRUE;
97 }
98
99 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
100 {
101     WCHAR guidW[MAX_PATH];
102     WCHAR squashedW[MAX_PATH];
103     GUID guid;
104     HRESULT hr;
105     int size;
106
107     hr = CoCreateGuid(&guid);
108     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
109
110     size = StringFromGUID2(&guid, (LPOLESTR)guidW, MAX_PATH);
111     ok(size == 39, "Expected 39, got %d\n", hr);
112
113     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
114     squash_guid(guidW, squashedW);
115     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
116 }
117
118 static void get_user_sid(LPSTR *usersid)
119 {
120     HANDLE token;
121     BYTE buf[1024];
122     DWORD size;
123     PTOKEN_USER user;
124
125     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
126     size = sizeof(buf);
127     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
128     user = (PTOKEN_USER)buf;
129     pConvertSidToStringSidA(user->User.Sid, usersid);
130 }
131
132 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
133 {
134     char val[MAX_PATH];
135     DWORD size, type;
136     LONG res;
137
138     size = MAX_PATH;
139     val[0] = '\0';
140     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
141
142     if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
143     {
144         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
145         return;
146     }
147
148     if (!expected)
149         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
150     else
151     {
152         if (bcase)
153             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
154         else
155             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
156     }
157 }
158
159 #define CHECK_REG_STR(prodkey, name, expected) \
160     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
161
162 static void test_MsiSourceListGetInfo(void)
163 {
164     CHAR prodcode[MAX_PATH];
165     CHAR prod_squashed[MAX_PATH];
166     CHAR keypath[MAX_PATH*2];
167     CHAR value[MAX_PATH];
168     LPSTR usersid;
169     LPCSTR data;
170     LONG res;
171     UINT r;
172     HKEY userkey, hkey, media;
173     DWORD size;
174
175     if (!pMsiSourceListGetInfoA)
176     {
177         skip("Skipping MsiSourceListGetInfoA tests\n");
178         return;
179     }
180
181     create_test_guid(prodcode, prod_squashed);
182     get_user_sid(&usersid);
183
184     /* NULL szProductCodeOrPatchCode */
185     r = pMsiSourceListGetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
186                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
187     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
188
189     /* empty szProductCodeOrPatchCode */
190     r = pMsiSourceListGetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
191                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
192     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
193
194     /* garbage szProductCodeOrPatchCode */
195     r = pMsiSourceListGetInfoA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
196                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
197     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
198
199     /*  szProductCodeOrPatchCode */
200     r = pMsiSourceListGetInfoA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
201                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
202     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
203
204     /* guid without brackets */
205     r = pMsiSourceListGetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
206                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
207     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
208
209     /* guid with brackets */
210     r = pMsiSourceListGetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
211                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
212     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
213
214     /* same length as guid, but random */
215     r = pMsiSourceListGetInfoA("ADKD-2KSDFF2-DKK1KNFJASD9GLKWME-1I3KAD", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
216                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
217     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
218
219     /* invalid context */
220     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_NONE,
221                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
222     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
223
224     /* another invalid context */
225     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALLUSERMANAGED,
226                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
227     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
228
229     /* yet another invalid context */
230     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALL,
231                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
232     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
233
234     /* mix two valid contexts */
235     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED | MSIINSTALLCONTEXT_USERUNMANAGED,
236                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
237     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
238
239     /* invalid option */
240     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
241                               4, INSTALLPROPERTY_PACKAGENAME, NULL, NULL);
242     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
243
244     /* NULL property */
245     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
246                               MSICODE_PRODUCT, NULL, NULL, NULL);
247     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
248
249     /* empty property */
250     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
251                               MSICODE_PRODUCT, "", NULL, NULL);
252     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
253
254     /* value is non-NULL while size is NULL */
255     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
256                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, NULL);
257     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
258
259     /* size is non-NULL while value is NULL */
260     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
261                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
262     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
263
264     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
265     lstrcatA(keypath, prod_squashed);
266
267     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
268     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
269
270     /* user product key exists */
271     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
272                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
273     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
274
275     res = RegCreateKeyA(userkey, "SourceList", &hkey);
276     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
277
278     /* SourceList key exists */
279     size = 0xdeadbeef;
280     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
281                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
283     ok(size == 0, "Expected 0, got %d\n", size);
284
285     data = "msitest.msi";
286     res = RegSetValueExA(hkey, "PackageName", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1);
287     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
288
289     /* PackageName value exists */
290     size = 0xdeadbeef;
291     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
292                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
294     ok(size == 11, "Expected 11, got %d\n", size);
295
296     /* read the value, don't change size */
297     lstrcpyA(value, "aaa");
298     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
299                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
300     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
301     ok(!lstrcmpA(value, "aaa"), "Expected 'aaa', got %s\n", value);
302     ok(size == 11, "Expected 11, got %d\n", size);
303
304     /* read the value, fix size */
305     size++;
306     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
307                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
309     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
310     ok(size == 11, "Expected 11, got %d\n", size);
311
312     /* empty property now that product key exists */
313     size = 0xdeadbeef;
314     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
315                               MSICODE_PRODUCT, "", NULL, &size);
316     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
317     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
318
319     /* nonexistent property now that product key exists */
320     size = 0xdeadbeef;
321     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
322                               MSICODE_PRODUCT, "nonexistent", NULL, &size);
323     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
324     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
325
326     data = "tester";
327     res = RegSetValueExA(hkey, "nonexistent", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1);
328     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
329
330     /* nonexistent property now that nonexistent value exists */
331     size = 0xdeadbeef;
332     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
333                               MSICODE_PRODUCT, "nonexistent", NULL, &size);
334     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
335     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
336
337     /* invalid option now that product key exists */
338     size = 0xdeadbeef;
339     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
340                               4, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
342     ok(size == 11, "Expected 11, got %d\n", size);
343
344     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, media key does not exist */
345     size = MAX_PATH;
346     lstrcpyA(value, "aaa");
347     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
348                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH,
349                                value, &size);
350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
351     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
352     ok(size == 0, "Expected 0, got %d\n", size);
353
354     res = RegCreateKeyA(hkey, "Media", &media);
355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
356
357     data = "path";
358     res = RegSetValueExA(media, "MediaPackage", 0, REG_SZ,
359                          (const BYTE *)data, lstrlenA(data) + 1);
360     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
361
362     /* INSTALLPROPERTY_MEDIAPACKAGEPATH */
363     size = MAX_PATH;
364     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
365                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH,
366                                value, &size);
367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
368     ok(!lstrcmpA(value, "path"), "Expected \"path\", got \"%s\"\n", value);
369     ok(size == 4, "Expected 4, got %d\n", size);
370
371     /* INSTALLPROPERTY_DISKPROMPT */
372     data = "prompt";
373     res = RegSetValueExA(media, "DiskPrompt", 0, REG_SZ,
374                          (const BYTE *)data, lstrlenA(data) + 1);
375     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
376
377     size = MAX_PATH;
378     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
379                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT,
380                                value, &size);
381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
382     ok(!lstrcmpA(value, "prompt"), "Expected \"prompt\", got \"%s\"\n", value);
383     ok(size == 6, "Expected 6, got %d\n", size);
384
385     data = "";
386     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
387                          (const BYTE *)data, lstrlenA(data) + 1);
388     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
389
390     /* INSTALLPROPERTY_LASTUSEDSOURCE, source is empty */
391     size = MAX_PATH;
392     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
393                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
394                                value, &size);
395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
396     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
397     ok(size == 0, "Expected 0, got %d\n", size);
398
399     data = "source";
400     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
401                          (const BYTE *)data, lstrlenA(data) + 1);
402     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
403
404     /* INSTALLPROPERTY_LASTUSEDSOURCE */
405     size = MAX_PATH;
406     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
407                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
408                                value, &size);
409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
410     ok(!lstrcmpA(value, "source"), "Expected \"source\", got \"%s\"\n", value);
411     ok(size == 6, "Expected 6, got %d\n", size);
412
413     /* INSTALLPROPERTY_LASTUSEDSOURCE, size is too short */
414     size = 4;
415     lstrcpyA(value, "aaa");
416     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
417                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
418                                value, &size);
419     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
420     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got \"%s\"\n", value);
421     ok(size == 6, "Expected 6, got %d\n", size);
422
423     /* INSTALLPROPERTY_LASTUSEDSOURCE, size is exactly 6 */
424     size = 6;
425     lstrcpyA(value, "aaa");
426     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
427                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
428                                value, &size);
429     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
430     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got \"%s\"\n", value);
431     ok(size == 6, "Expected 6, got %d\n", size);
432
433     data = "a;source";
434     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
435                          (const BYTE *)data, lstrlenA(data) + 1);
436     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
437
438     /* INSTALLPROPERTY_LASTUSEDSOURCE, one semi-colon */
439     size = MAX_PATH;
440     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
441                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
442                                value, &size);
443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
444     ok(!lstrcmpA(value, "source"), "Expected \"source\", got \"%s\"\n", value);
445     ok(size == 6, "Expected 6, got %d\n", size);
446
447     data = "a:source";
448     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
449                          (const BYTE *)data, lstrlenA(data) + 1);
450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
451
452     /* INSTALLPROPERTY_LASTUSEDSOURCE, one colon */
453     size = MAX_PATH;
454     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
455                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE,
456                                value, &size);
457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
458     ok(!lstrcmpA(value, "a:source"), "Expected \"a:source\", got \"%s\"\n", value);
459     ok(size == 8, "Expected 8, got %d\n", size);
460
461     /* INSTALLPROPERTY_LASTUSEDTYPE, invalid source format */
462     size = MAX_PATH;
463     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
464                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
465                                value, &size);
466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
467     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
468     ok(size == 0, "Expected 0, got %d\n", size);
469
470     data = "x;y;z";
471     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
472                          (const BYTE *)data, lstrlenA(data) + 1);
473     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
474
475     /* INSTALLPROPERTY_LASTUSEDTYPE, invalid source format */
476     size = MAX_PATH;
477     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
478                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
479                                value, &size);
480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
481     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
482     ok(size == 0, "Expected 0, got %d\n", size);
483
484     data = "n;y;z";
485     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
486                          (const BYTE *)data, lstrlenA(data) + 1);
487     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
488
489     /* INSTALLPROPERTY_LASTUSEDTYPE */
490     size = MAX_PATH;
491     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
492                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
493                                value, &size);
494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
495     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
496     ok(size == 1, "Expected 1, got %d\n", size);
497
498     data = "negatory";
499     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
500                          (const BYTE *)data, lstrlenA(data) + 1);
501     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
502
503     /* INSTALLPROPERTY_LASTUSEDTYPE */
504     size = MAX_PATH;
505     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
506                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
507                                value, &size);
508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
509     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
510     ok(size == 1, "Expected 1, got %d\n", size);
511
512     data = "megatron";
513     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
514                          (const BYTE *)data, lstrlenA(data) + 1);
515     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
516
517     /* INSTALLPROPERTY_LASTUSEDTYPE */
518     size = MAX_PATH;
519     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
520                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
521                                value, &size);
522     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
523     ok(!lstrcmpA(value, "m"), "Expected \"m\", got \"%s\"\n", value);
524     ok(size == 1, "Expected 1, got %d\n", size);
525
526     data = "useless";
527     res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ,
528                          (const BYTE *)data, lstrlenA(data) + 1);
529     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
530
531     /* INSTALLPROPERTY_LASTUSEDTYPE */
532     size = MAX_PATH;
533     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
534                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE,
535                                value, &size);
536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
537     ok(!lstrcmpA(value, "u"), "Expected \"u\", got \"%s\"\n", value);
538     ok(size == 1, "Expected 1, got %d\n", size);
539
540     RegDeleteValueA(media, "MediaPackage");
541     RegDeleteValueA(media, "DiskPrompt");
542     RegDeleteKeyA(media, "");
543     RegDeleteValueA(hkey, "LastUsedSource");
544     RegDeleteValueA(hkey, "nonexistent");
545     RegDeleteValueA(hkey, "PackageName");
546     RegDeleteKeyA(hkey, "");
547     RegDeleteKeyA(userkey, "");
548     RegCloseKey(hkey);
549     RegCloseKey(userkey);
550
551     /* try a patch */
552     size = 0xdeadbeef;
553     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
554                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
555     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
556     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
557
558     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Patches\\");
559     lstrcatA(keypath, prod_squashed);
560
561     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
562     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
563
564     /* patch key exists
565      * NOTE: using prodcode guid, but it really doesn't matter
566      */
567     size = 0xdeadbeef;
568     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
569                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
570     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
571     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
572
573     res = RegCreateKeyA(userkey, "SourceList", &hkey);
574     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
575
576     /* SourceList key exists */
577     size = 0xdeadbeef;
578     r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
579                               MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
581     ok(size == 0, "Expected 0, got %d\n", size);
582
583     RegDeleteKeyA(hkey, "");
584     RegDeleteKeyA(userkey, "");
585     RegCloseKey(hkey);
586     RegCloseKey(userkey);
587 }
588
589 static void test_MsiSourceListAddSourceEx(void)
590 {
591     CHAR prodcode[MAX_PATH];
592     CHAR prod_squashed[MAX_PATH];
593     CHAR keypath[MAX_PATH*2];
594     CHAR value[MAX_PATH];
595     LPSTR usersid;
596     LONG res;
597     UINT r;
598     HKEY prodkey, userkey, hkey;
599     HKEY url, net;
600     DWORD size;
601
602     if (!pMsiSourceListAddSourceExA)
603     {
604         skip("Skipping MsiSourceListAddSourceExA tests\n");
605         return;
606     }
607
608     create_test_guid(prodcode, prod_squashed);
609     get_user_sid(&usersid);
610
611     /* GetLastError is not set by the function */
612
613     /* NULL szProductCodeOrPatchCode */
614     r = pMsiSourceListAddSourceExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
615                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
616     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
617
618     /* empty szProductCodeOrPatchCode */
619     r = pMsiSourceListAddSourceExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
620                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
621     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
622
623     /* garbage szProductCodeOrPatchCode */
624     r = pMsiSourceListAddSourceExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
625                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
626     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
627
628     /* guid without brackets */
629     r = pMsiSourceListAddSourceExA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid,
630                                   MSIINSTALLCONTEXT_USERUNMANAGED,
631                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
632     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
633
634     /* guid with brackets */
635     r = pMsiSourceListAddSourceExA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid,
636                                   MSIINSTALLCONTEXT_USERUNMANAGED,
637                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
638     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
639
640     /* MSIINSTALLCONTEXT_USERUNMANAGED */
641
642     r = pMsiSourceListAddSourceExA(prodcode, usersid,
643                                   MSIINSTALLCONTEXT_USERUNMANAGED,
644                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
645     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
646
647     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
648     lstrcatA(keypath, prod_squashed);
649
650     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
651     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
652
653     /* user product key exists */
654     r = pMsiSourceListAddSourceExA(prodcode, usersid,
655                                   MSIINSTALLCONTEXT_USERUNMANAGED,
656                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
657     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
658
659     res = RegCreateKeyA(userkey, "SourceList", &url);
660     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
661     RegCloseKey(url);
662
663     /* SourceList key exists */
664     r = pMsiSourceListAddSourceExA(prodcode, usersid,
665                                   MSIINSTALLCONTEXT_USERUNMANAGED,
666                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
668
669     res = RegOpenKeyA(userkey, "SourceList\\URL", &url);
670     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
671
672     size = MAX_PATH;
673     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
675     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
676     ok(size == 11, "Expected 11, got %d\n", size);
677
678     /* add another source, index 0 */
679     r = pMsiSourceListAddSourceExA(prodcode, usersid,
680                                   MSIINSTALLCONTEXT_USERUNMANAGED,
681                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0);
682     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
683
684     size = MAX_PATH;
685     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
687     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
688     ok(size == 11, "Expected 11, got %d\n", size);
689
690     size = MAX_PATH;
691     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
692     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
693     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
694     ok(size == 9, "Expected 9, got %d\n", size);
695
696     /* add another source, index 1 */
697     r = pMsiSourceListAddSourceExA(prodcode, usersid,
698                                   MSIINSTALLCONTEXT_USERUNMANAGED,
699                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "third/", 1);
700     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
701
702     size = MAX_PATH;
703     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
704     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
705     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
706     ok(size == 7, "Expected 7, got %d\n", size);
707
708     size = MAX_PATH;
709     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
711     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
712     ok(size == 11, "Expected 11, got %d\n", size);
713
714     size = MAX_PATH;
715     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
716     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
717     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
718     ok(size == 9, "Expected 9, got %d\n", size);
719
720     /* add another source, index > N */
721     r = pMsiSourceListAddSourceExA(prodcode, usersid,
722                                   MSIINSTALLCONTEXT_USERUNMANAGED,
723                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "last/", 5);
724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
725
726     size = MAX_PATH;
727     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
729     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
730     ok(size == 7, "Expected 7, got %d\n", size);
731
732     size = MAX_PATH;
733     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
734     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
735     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
736     ok(size == 11, "Expected 11, got %d\n", size);
737
738     size = MAX_PATH;
739     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
740     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
741     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
742     ok(size == 9, "Expected 9, got %d\n", size);
743
744     size = MAX_PATH;
745     res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
746     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
747     ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value);
748     ok(size == 6, "Expected 6, got %d\n", size);
749
750     /* just MSISOURCETYPE_NETWORK */
751     r = pMsiSourceListAddSourceExA(prodcode, usersid,
752                                   MSIINSTALLCONTEXT_USERUNMANAGED,
753                                   MSISOURCETYPE_NETWORK, "source", 0);
754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
755
756     res = RegOpenKeyA(userkey, "SourceList\\Net", &net);
757     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
758
759     size = MAX_PATH;
760     res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size);
761     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
762     ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value);
763     ok(size == 8, "Expected 8, got %d\n", size);
764
765     /* just MSISOURCETYPE_URL */
766     r = pMsiSourceListAddSourceExA(prodcode, usersid,
767                                   MSIINSTALLCONTEXT_USERUNMANAGED,
768                                   MSISOURCETYPE_URL, "source", 0);
769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
770
771     size = MAX_PATH;
772     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
773     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
774     ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
775     ok(size == 7, "Expected 7, got %d\n", size);
776
777     size = MAX_PATH;
778     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
779     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
780     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
781     ok(size == 11, "Expected 11, got %d\n", size);
782
783     size = MAX_PATH;
784     res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
785     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
786     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
787     ok(size == 9, "Expected 9, got %d\n", size);
788
789     size = MAX_PATH;
790     res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
792     ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value);
793     ok(size == 6, "Expected 6, got %d\n", size);
794
795     size = MAX_PATH;
796     res = RegQueryValueExA(url, "5", NULL, NULL, (LPBYTE)value, &size);
797     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
798     ok(!lstrcmpA(value, "source/"), "Expected 'source/', got %s\n", value);
799     ok(size == 8, "Expected 8, got %d\n", size);
800
801     /* NULL szUserSid */
802     r = pMsiSourceListAddSourceExA(prodcode, NULL,
803                                   MSIINSTALLCONTEXT_USERUNMANAGED,
804                                   MSISOURCETYPE_NETWORK, "nousersid", 0);
805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
806
807     size = MAX_PATH;
808     res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size);
809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
810     ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value);
811     ok(size == 8, "Expected 8, got %d\n", size);
812
813     size = MAX_PATH;
814     res = RegQueryValueExA(net, "2", NULL, NULL, (LPBYTE)value, &size);
815     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
816     ok(!lstrcmpA(value, "nousersid\\"), "Expected 'nousersid\\', got %s\n", value);
817     ok(size == 11, "Expected 11, got %d\n", size);
818
819     /* invalid options, must have source type */
820     r = pMsiSourceListAddSourceExA(prodcode, usersid,
821                                   MSIINSTALLCONTEXT_USERUNMANAGED,
822                                   MSICODE_PRODUCT, "source", 0);
823     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
824
825     r = pMsiSourceListAddSourceExA(prodcode, usersid,
826                                   MSIINSTALLCONTEXT_USERUNMANAGED,
827                                   MSICODE_PATCH, "source", 0);
828     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
829
830     /* NULL szSource */
831     r = pMsiSourceListAddSourceExA(prodcode, usersid,
832                                   MSIINSTALLCONTEXT_USERUNMANAGED,
833                                   MSISOURCETYPE_URL, NULL, 1);
834     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
835
836     /* empty szSource */
837     r = pMsiSourceListAddSourceExA(prodcode, usersid,
838                                   MSIINSTALLCONTEXT_USERUNMANAGED,
839                                   MSISOURCETYPE_URL, "", 1);
840     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
841
842     /* MSIINSTALLCONTEXT_USERMANAGED, non-NULL szUserSid */
843
844     r = pMsiSourceListAddSourceExA(prodcode, usersid,
845                                   MSIINSTALLCONTEXT_USERMANAGED,
846                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
847     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
848
849     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
850     lstrcatA(keypath, usersid);
851     lstrcatA(keypath, "\\Installer\\Products\\");
852     lstrcatA(keypath, prod_squashed);
853
854     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
856
857     /* product key exists */
858     r = pMsiSourceListAddSourceExA(prodcode, usersid,
859                                   MSIINSTALLCONTEXT_USERMANAGED,
860                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
861     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
862
863     res = RegCreateKeyA(prodkey, "SourceList", &hkey);
864     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
865     RegCloseKey(hkey);
866
867     /* SourceList exists */
868     r = pMsiSourceListAddSourceExA(prodcode, usersid,
869                                   MSIINSTALLCONTEXT_USERMANAGED,
870                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
872
873     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
875
876     size = MAX_PATH;
877     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
878     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
879     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
880     ok(size == 11, "Expected 11, got %d\n", size);
881
882     RegCloseKey(url);
883
884     /* MSIINSTALLCONTEXT_USERMANAGED, NULL szUserSid */
885
886     r = pMsiSourceListAddSourceExA(prodcode, NULL,
887                                   MSIINSTALLCONTEXT_USERMANAGED,
888                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0);
889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
890
891     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
892     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
893
894     size = MAX_PATH;
895     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
896     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
897     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
898     ok(size == 11, "Expected 11, got %d\n", size);
899
900     size = MAX_PATH;
901     res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
902     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
903     ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
904     ok(size == 9, "Expected 9, got %d\n", size);
905
906     RegCloseKey(url);
907     RegCloseKey(prodkey);
908
909     /* MSIINSTALLCONTEXT_MACHINE */
910
911     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
912     r = pMsiSourceListAddSourceExA(prodcode, usersid,
913                                   MSIINSTALLCONTEXT_MACHINE,
914                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
915     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
916
917     r = pMsiSourceListAddSourceExA(prodcode, NULL,
918                                   MSIINSTALLCONTEXT_MACHINE,
919                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
920     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
921
922     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
923     lstrcatA(keypath, prod_squashed);
924
925     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
927
928     /* product key exists */
929     r = pMsiSourceListAddSourceExA(prodcode, NULL,
930                                   MSIINSTALLCONTEXT_MACHINE,
931                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
932     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
933
934     res = RegCreateKeyA(prodkey, "SourceList", &hkey);
935     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
936     RegCloseKey(hkey);
937
938     /* SourceList exists */
939     r = pMsiSourceListAddSourceExA(prodcode, NULL,
940                                   MSIINSTALLCONTEXT_MACHINE,
941                                   MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0);
942     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
943
944     res = RegOpenKeyA(prodkey, "SourceList\\URL", &url);
945     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
946
947     size = MAX_PATH;
948     res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
949     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
950     ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
951     ok(size == 11, "Expected 11, got %d\n", size);
952
953     RegCloseKey(url);
954     RegCloseKey(prodkey);
955     HeapFree(GetProcessHeap(), 0, usersid);
956 }
957
958 static void test_MsiSourceListEnumSources(void)
959 {
960     CHAR prodcode[MAX_PATH];
961     CHAR prod_squashed[MAX_PATH];
962     CHAR keypath[MAX_PATH*2];
963     CHAR value[MAX_PATH];
964     LPSTR usersid;
965     LONG res;
966     UINT r;
967     HKEY prodkey, userkey;
968     HKEY url, net, source;
969     DWORD size;
970
971     create_test_guid(prodcode, prod_squashed);
972     get_user_sid(&usersid);
973
974     /* GetLastError is not set by the function */
975
976     /* NULL szProductCodeOrPatchCode */
977     size = 0xdeadbeef;
978     r = pMsiSourceListEnumSourcesA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
979                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
980     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
981     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
982
983     /* empty szProductCodeOrPatchCode */
984     size = 0xdeadbeef;
985     r = pMsiSourceListEnumSourcesA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
986                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
987     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
988     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
989
990     /* garbage szProductCodeOrPatchCode */
991     size = 0xdeadbeef;
992     r = pMsiSourceListEnumSourcesA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
993                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
994     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
995     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
996
997     /* guid without brackets */
998     size = 0xdeadbeef;
999     r = pMsiSourceListEnumSourcesA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
1000                                    usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1001                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1002     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1003     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
1004
1005     /* guid with brackets */
1006     size = 0xdeadbeef;
1007     r = pMsiSourceListEnumSourcesA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
1008                                    usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1009                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1010     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1011     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
1012
1013     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1014
1015     size = MAX_PATH;
1016     lstrcpyA(value, "aaa");
1017     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1018                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1019                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1020     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1021     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1022     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1023
1024     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1025     lstrcatA(keypath, prod_squashed);
1026
1027     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1028     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1029
1030     /* user product key exists */
1031     size = MAX_PATH;
1032     lstrcpyA(value, "aaa");
1033     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1034                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1035                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1036     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1037     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1038     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1039
1040     res = RegCreateKeyA(userkey, "SourceList", &source);
1041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1042
1043     /* SourceList key exists */
1044     size = MAX_PATH;
1045     lstrcpyA(value, "aaa");
1046     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1047                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1048                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1049     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1050     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1051     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1052
1053     res = RegCreateKeyA(source, "URL", &url);
1054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1055
1056     /* URL key exists */
1057     size = MAX_PATH;
1058     lstrcpyA(value, "aaa");
1059     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1060                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1061                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1062     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1063     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1064     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1065
1066     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1067     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1068
1069     res = RegSetValueExA(url, "2", 0, REG_SZ, (LPBYTE)"second", 7);
1070     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1071
1072     res = RegSetValueExA(url, "4", 0, REG_SZ, (LPBYTE)"fourth", 7);
1073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1074
1075     /* sources exist */
1076     size = MAX_PATH;
1077     lstrcpyA(value, "aaa");
1078     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1079                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1080                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1082     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1083     ok(size == 5, "Expected 5, got %d\n", size);
1084
1085     /* try index 0 again */
1086     size = MAX_PATH;
1087     lstrcpyA(value, "aaa");
1088     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1089                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1090                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1092     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1093     ok(size == 5, "Expected 5, got %d\n", size);
1094
1095     /* both szSource and pcchSource are NULL, index 0 */
1096     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1097                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1098                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, NULL);
1099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1100
1101     /* both szSource and pcchSource are NULL, index 1 */
1102     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1103                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1104                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, NULL, NULL);
1105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1106
1107     /* size is exactly 5 */
1108     size = 5;
1109     lstrcpyA(value, "aaa");
1110     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1111                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1112                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1113     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
1114     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value);
1115     ok(size == 5, "Expected 5, got %d\n", size);
1116
1117     /* szSource is non-NULL while pcchSource is NULL */
1118     lstrcpyA(value, "aaa");
1119     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1120                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1121                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, NULL);
1122     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1123     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value);
1124
1125     /* try index 1 after failure */
1126     size = MAX_PATH;
1127     lstrcpyA(value, "aaa");
1128     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1129                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1130                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size);
1131     ok(r == ERROR_INVALID_PARAMETER,
1132        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1133     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value);
1134     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1135
1136     /* reset the enumeration */
1137     size = MAX_PATH;
1138     lstrcpyA(value, "aaa");
1139     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1140                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1141                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1143     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1144     ok(size == 5, "Expected 5, got %d\n", size);
1145
1146     /* try index 1 */
1147     size = MAX_PATH;
1148     lstrcpyA(value, "aaa");
1149     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1150                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1151                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size);
1152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1153     ok(!lstrcmpA(value, "second"), "Expected \"second\", got %s\n", value);
1154     ok(size == 6, "Expected 6, got %d\n", size);
1155
1156     /* try index 1 again */
1157     size = MAX_PATH;
1158     lstrcpyA(value, "aaa");
1159     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1160                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1161                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size);
1162     ok(r == ERROR_INVALID_PARAMETER,
1163        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1164     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1165     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1166
1167     /* try index 2 */
1168     size = MAX_PATH;
1169     lstrcpyA(value, "aaa");
1170     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1171                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1172                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 2, value, &size);
1173     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1174     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1175     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1176
1177     /* try index < 0 */
1178     size = MAX_PATH;
1179     lstrcpyA(value, "aaa");
1180     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1181                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1182                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, -1, value, &size);
1183     ok(r == ERROR_INVALID_PARAMETER,
1184        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1185     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1186     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1187
1188     /* NULL szUserSid */
1189     size = MAX_PATH;
1190     lstrcpyA(value, "aaa");
1191     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1192                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1193                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1195     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1196     ok(size == 5, "Expected 5, got %d\n", size);
1197
1198     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1199     size = MAX_PATH;
1200     lstrcpyA(value, "aaa");
1201     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1202                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1203                                    MSICODE_PRODUCT, 0, value, &size);
1204     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1205     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1206     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1207
1208     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1209     size = MAX_PATH;
1210     lstrcpyA(value, "aaa");
1211     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1212                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1213                                    MSICODE_PATCH, 0, value, &size);
1214     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1215     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1216     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1217
1218     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1219     size = MAX_PATH;
1220     lstrcpyA(value, "aaa");
1221     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1222                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1223                                    MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL,
1224                                    0, value, &size);
1225     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_SUCCESS, got %d\n", r);
1226     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1227     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1228
1229     /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */
1230     size = MAX_PATH;
1231     lstrcpyA(value, "aaa");
1232     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1233                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1234                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1235                                    0, value, &size);
1236     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1237     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1238     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1239
1240     RegDeleteValueA(url, "1");
1241     RegDeleteValueA(url, "2");
1242     RegDeleteValueA(url, "4");
1243     RegDeleteKeyA(url, "");
1244     RegCloseKey(url);
1245
1246     /* SourceList key exists */
1247     size = MAX_PATH;
1248     lstrcpyA(value, "aaa");
1249     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1250                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1251                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1252     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1253     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1254     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1255
1256     res = RegCreateKeyA(source, "Net", &net);
1257     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1258
1259     /* Net key exists */
1260     size = MAX_PATH;
1261     lstrcpyA(value, "aaa");
1262     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1263                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1264                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1265     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1266     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1267     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1268
1269     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1270     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1271
1272     /* sources exist */
1273     size = MAX_PATH;
1274     lstrcpyA(value, "aaa");
1275     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1276                                    MSIINSTALLCONTEXT_USERUNMANAGED,
1277                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1279     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1280     ok(size == 5, "Expected 5, got %d\n", size);
1281
1282     RegDeleteValueA(net, "1");
1283     RegDeleteKeyA(net, "");
1284     RegCloseKey(net);
1285     RegDeleteKeyA(source, "");
1286     RegCloseKey(source);
1287     RegDeleteKeyA(userkey, "");
1288     RegCloseKey(userkey);
1289
1290     /* MSIINSTALLCONTEXT_USERMANAGED */
1291
1292     size = MAX_PATH;
1293     lstrcpyA(value, "aaa");
1294     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1295                                    MSIINSTALLCONTEXT_USERMANAGED,
1296                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1297     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1298     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1299     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1300
1301     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1302     lstrcatA(keypath, usersid);
1303     lstrcatA(keypath, "\\Installer\\Products\\");
1304     lstrcatA(keypath, prod_squashed);
1305
1306     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
1307     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1308
1309     /* user product key exists */
1310     size = MAX_PATH;
1311     lstrcpyA(value, "aaa");
1312     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1313                                    MSIINSTALLCONTEXT_USERMANAGED,
1314                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1315     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1316     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1317     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1318
1319     res = RegCreateKeyA(userkey, "SourceList", &source);
1320     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1321
1322     /* SourceList key exists */
1323     size = MAX_PATH;
1324     lstrcpyA(value, "aaa");
1325     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1326                                    MSIINSTALLCONTEXT_USERMANAGED,
1327                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1328     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1329     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1330     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1331
1332     res = RegCreateKeyA(source, "URL", &url);
1333     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1334
1335     /* URL key exists */
1336     size = MAX_PATH;
1337     lstrcpyA(value, "aaa");
1338     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1339                                    MSIINSTALLCONTEXT_USERMANAGED,
1340                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1341     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1342     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1343     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1344
1345     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1346     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1347
1348     /* sources exist */
1349     size = MAX_PATH;
1350     lstrcpyA(value, "aaa");
1351     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1352                                    MSIINSTALLCONTEXT_USERMANAGED,
1353                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1355     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1356     ok(size == 5, "Expected 5, got %d\n", size);
1357
1358     /* NULL szUserSid */
1359     size = MAX_PATH;
1360     lstrcpyA(value, "aaa");
1361     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1362                                    MSIINSTALLCONTEXT_USERMANAGED,
1363                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1365     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1366     ok(size == 5, "Expected 5, got %d\n", size);
1367
1368     RegDeleteValueA(url, "1");
1369     RegDeleteKeyA(url, "");
1370     RegCloseKey(url);
1371
1372     /* SourceList key exists */
1373     size = MAX_PATH;
1374     lstrcpyA(value, "aaa");
1375     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1376                                    MSIINSTALLCONTEXT_USERMANAGED,
1377                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1378     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1379     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1380     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1381
1382     res = RegCreateKeyA(source, "Net", &net);
1383     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1384
1385     /* Net key exists */
1386     size = MAX_PATH;
1387     lstrcpyA(value, "aaa");
1388     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1389                                    MSIINSTALLCONTEXT_USERMANAGED,
1390                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1391     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1392     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1393     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1394
1395     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1396     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1397
1398     /* sources exist */
1399     size = MAX_PATH;
1400     lstrcpyA(value, "aaa");
1401     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1402                                    MSIINSTALLCONTEXT_USERMANAGED,
1403                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1405     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1406     ok(size == 5, "Expected 5, got %d\n", size);
1407
1408     RegDeleteValueA(net, "1");
1409     RegDeleteKeyA(net, "");
1410     RegCloseKey(net);
1411     RegDeleteKeyA(source, "");
1412     RegCloseKey(source);
1413     RegDeleteKeyA(userkey, "");
1414     RegCloseKey(userkey);
1415
1416     /* MSIINSTALLCONTEXT_MACHINE */
1417
1418     /* szUserSid is non-NULL */
1419     size = MAX_PATH;
1420     lstrcpyA(value, "aaa");
1421     r = pMsiSourceListEnumSourcesA(prodcode, usersid,
1422                                    MSIINSTALLCONTEXT_MACHINE,
1423                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1424     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1425     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1426     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1427
1428     /* szUserSid is non-NULL */
1429     size = MAX_PATH;
1430     lstrcpyA(value, "aaa");
1431     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1432                                    MSIINSTALLCONTEXT_MACHINE,
1433                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1434     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1435     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1436     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1437
1438     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1439     lstrcatA(keypath, prod_squashed);
1440
1441     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1443
1444     /* user product key exists */
1445     size = MAX_PATH;
1446     lstrcpyA(value, "aaa");
1447     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1448                                    MSIINSTALLCONTEXT_MACHINE,
1449                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1450     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1451     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1452     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1453
1454     res = RegCreateKeyA(prodkey, "SourceList", &source);
1455     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1456
1457     /* SourceList key exists */
1458     size = MAX_PATH;
1459     lstrcpyA(value, "aaa");
1460     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1461                                    MSIINSTALLCONTEXT_MACHINE,
1462                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1463     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1464     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1465     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1466
1467     res = RegCreateKeyA(source, "URL", &url);
1468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1469
1470     /* URL key exists */
1471     size = MAX_PATH;
1472     lstrcpyA(value, "aaa");
1473     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1474                                    MSIINSTALLCONTEXT_MACHINE,
1475                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1476     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1477     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1478     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1479
1480     res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1482
1483     /* sources exist */
1484     size = MAX_PATH;
1485     lstrcpyA(value, "aaa");
1486     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1487                                    MSIINSTALLCONTEXT_MACHINE,
1488                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1490     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1491     ok(size == 5, "Expected 5, got %d\n", size);
1492
1493     /* NULL szUserSid */
1494     size = MAX_PATH;
1495     lstrcpyA(value, "aaa");
1496     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1497                                    MSIINSTALLCONTEXT_MACHINE,
1498                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
1499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1500     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1501     ok(size == 5, "Expected 5, got %d\n", size);
1502
1503     RegDeleteValueA(url, "1");
1504     RegDeleteKeyA(url, "");
1505     RegCloseKey(url);
1506
1507     /* SourceList key exists */
1508     size = MAX_PATH;
1509     lstrcpyA(value, "aaa");
1510     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1511                                    MSIINSTALLCONTEXT_MACHINE,
1512                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1513     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1514     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1515     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1516
1517     res = RegCreateKeyA(source, "Net", &net);
1518     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1519
1520     /* Net key exists */
1521     size = MAX_PATH;
1522     lstrcpyA(value, "aaa");
1523     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1524                                    MSIINSTALLCONTEXT_MACHINE,
1525                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1526     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
1527     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
1528     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
1529
1530     res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6);
1531     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1532
1533     /* sources exist */
1534     size = MAX_PATH;
1535     lstrcpyA(value, "aaa");
1536     r = pMsiSourceListEnumSourcesA(prodcode, NULL,
1537                                    MSIINSTALLCONTEXT_MACHINE,
1538                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
1539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1540     ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value);
1541     ok(size == 5, "Expected 5, got %d\n", size);
1542
1543     RegDeleteValueA(net, "1");
1544     RegDeleteKeyA(net, "");
1545     RegCloseKey(net);
1546     RegDeleteKeyA(source, "");
1547     RegCloseKey(source);
1548     RegDeleteKeyA(prodkey, "");
1549     RegCloseKey(prodkey);
1550 }
1551
1552 static void test_MsiSourceListSetInfo(void)
1553 {
1554     CHAR prodcode[MAX_PATH];
1555     CHAR prod_squashed[MAX_PATH];
1556     CHAR keypath[MAX_PATH*2];
1557     HKEY prodkey, userkey;
1558     HKEY net, url, media, source;
1559     LPSTR usersid;
1560     LONG res;
1561     UINT r;
1562
1563     create_test_guid(prodcode, prod_squashed);
1564     get_user_sid(&usersid);
1565
1566     /* GetLastError is not set by the function */
1567
1568     /* NULL szProductCodeOrPatchCode */
1569     r = pMsiSourceListSetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1570                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1571                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1572     ok(r == ERROR_INVALID_PARAMETER,
1573        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1574
1575     /* empty szProductCodeOrPatchCode */
1576     r = pMsiSourceListSetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1577                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1578                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1579     ok(r == ERROR_INVALID_PARAMETER,
1580        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1581
1582     /* garbage szProductCodeOrPatchCode */
1583     r = pMsiSourceListSetInfoA("garbage", usersid,
1584                                MSIINSTALLCONTEXT_USERUNMANAGED,
1585                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1586                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1587     ok(r == ERROR_INVALID_PARAMETER,
1588        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1589
1590     /* guid without brackets */
1591     r = pMsiSourceListSetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
1592                                usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1593                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1594                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1595     ok(r == ERROR_INVALID_PARAMETER,
1596        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1597
1598     /* guid with brackets */
1599     r = pMsiSourceListSetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
1600                                usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1601                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1602                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1603     ok(r == ERROR_UNKNOWN_PRODUCT,
1604        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1605
1606     /* dwOptions is MSICODE_PRODUCT */
1607     r = pMsiSourceListSetInfoA(prodcode, usersid,
1608                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1609                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1610     ok(r == ERROR_UNKNOWN_PRODUCT,
1611        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1612
1613     /* dwOptions is MSICODE_PATCH */
1614     r = pMsiSourceListSetInfoA(prodcode, usersid,
1615                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH,
1616                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1617     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
1618
1619     /* dwOptions is both MSICODE_PRODUCT and MSICODE_PATCH */
1620     r = pMsiSourceListSetInfoA(prodcode, usersid,
1621                                MSIINSTALLCONTEXT_USERUNMANAGED,
1622                                MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL,
1623                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1624     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
1625
1626     /* dwOptions has both MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL */
1627     r = pMsiSourceListSetInfoA(prodcode, NULL,
1628                                MSIINSTALLCONTEXT_USERUNMANAGED,
1629                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1630                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1631     ok(r == ERROR_UNKNOWN_PRODUCT,
1632        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1633
1634     /* LastUsedSource and dwOptions has both
1635      * MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL
1636      */
1637     r = pMsiSourceListSetInfoA(prodcode, NULL,
1638                                MSIINSTALLCONTEXT_USERUNMANAGED,
1639                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL,
1640                                INSTALLPROPERTY_LASTUSEDSOURCE, "path");
1641     ok(r == ERROR_UNKNOWN_PRODUCT,
1642        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1643
1644     /* LastUsedSource and dwOptions has no source type */
1645     r = pMsiSourceListSetInfoA(prodcode, NULL,
1646                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1647                                INSTALLPROPERTY_LASTUSEDSOURCE, "path");
1648     ok(r == ERROR_UNKNOWN_PRODUCT,
1649        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1650
1651     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1652
1653     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1654     lstrcatA(keypath, prod_squashed);
1655
1656     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1657     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1658
1659     /* user product key exists */
1660     r = pMsiSourceListSetInfoA(prodcode, NULL,
1661                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1662                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1663     ok(r == ERROR_BAD_CONFIGURATION,
1664        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1665
1666     res = RegCreateKeyA(userkey, "SourceList", &source);
1667     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1668
1669     /* SourceList key exists, no source type */
1670     r = pMsiSourceListSetInfoA(prodcode, NULL,
1671                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1672                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1674
1675     /* Media key is created by MsiSourceListSetInfo */
1676     res = RegOpenKeyA(source, "Media", &media);
1677     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1678     CHECK_REG_STR(media, "MediaPackage", "path");
1679
1680     /* set the info again */
1681     r = pMsiSourceListSetInfoA(prodcode, NULL,
1682                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1683                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path2");
1684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1685     CHECK_REG_STR(media, "MediaPackage", "path2");
1686
1687     /* NULL szProperty */
1688     r = pMsiSourceListSetInfoA(prodcode, NULL,
1689                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1690                                NULL, "path");
1691     ok(r == ERROR_INVALID_PARAMETER,
1692        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1693
1694     /* empty szProperty */
1695     r = pMsiSourceListSetInfoA(prodcode, NULL,
1696                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1697                                "", "path");
1698     ok(r == ERROR_UNKNOWN_PROPERTY,
1699        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1700
1701     /* NULL szValue */
1702     r = pMsiSourceListSetInfoA(prodcode, NULL,
1703                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1704                                INSTALLPROPERTY_MEDIAPACKAGEPATH, NULL);
1705     ok(r == ERROR_UNKNOWN_PROPERTY,
1706        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1707
1708     /* empty szValue */
1709     r = pMsiSourceListSetInfoA(prodcode, NULL,
1710                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1711                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "");
1712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1713     CHECK_REG_STR(media, "MediaPackage", "");
1714
1715     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_NETWORK */
1716     r = pMsiSourceListSetInfoA(prodcode, NULL,
1717                                MSIINSTALLCONTEXT_USERUNMANAGED,
1718                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1719                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1720     ok(r == ERROR_INVALID_PARAMETER,
1721        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1722
1723     /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_URL */
1724     r = pMsiSourceListSetInfoA(prodcode, NULL,
1725                                MSIINSTALLCONTEXT_USERUNMANAGED,
1726                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1727                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1728     ok(r == ERROR_INVALID_PARAMETER,
1729        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1730
1731     /* INSTALLPROPERTY_DISKPROMPT */
1732     r = pMsiSourceListSetInfoA(prodcode, NULL,
1733                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1734                                INSTALLPROPERTY_DISKPROMPT, "prompt");
1735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1736     CHECK_REG_STR(media, "DiskPrompt", "prompt");
1737
1738     /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_NETWORK */
1739     r = pMsiSourceListSetInfoA(prodcode, NULL,
1740                                MSIINSTALLCONTEXT_USERUNMANAGED,
1741                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1742                                INSTALLPROPERTY_DISKPROMPT, "prompt");
1743     ok(r == ERROR_INVALID_PARAMETER,
1744        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1745
1746     /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_URL */
1747     r = pMsiSourceListSetInfoA(prodcode, NULL,
1748                                MSIINSTALLCONTEXT_USERUNMANAGED,
1749                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1750                                INSTALLPROPERTY_DISKPROMPT, "prompt");
1751     ok(r == ERROR_INVALID_PARAMETER,
1752        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1753
1754     /* INSTALLPROPERTY_LASTUSEDSOURCE */
1755     r = pMsiSourceListSetInfoA(prodcode, NULL,
1756                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1757                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1758     ok(r == ERROR_INVALID_PARAMETER,
1759        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1760
1761     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_NETWORK */
1762     r = pMsiSourceListSetInfoA(prodcode, NULL,
1763                                MSIINSTALLCONTEXT_USERUNMANAGED,
1764                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1765                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1766     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1767
1768     /* Net key is created by MsiSourceListSetInfo */
1769     res = RegOpenKeyA(source, "Net", &net);
1770     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1771     CHECK_REG_STR(net, "1", "source\\")
1772     CHECK_REG_STR(source, "LastUsedSource", "n;1;source");
1773
1774     /* source has forward slash */
1775     r = pMsiSourceListSetInfoA(prodcode, NULL,
1776                                MSIINSTALLCONTEXT_USERUNMANAGED,
1777                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1778                                INSTALLPROPERTY_LASTUSEDSOURCE, "source/");
1779     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1780     CHECK_REG_STR(net, "1", "source\\");
1781     CHECK_REG_STR(net, "2", "source/\\");
1782     CHECK_REG_STR(source, "LastUsedSource", "n;2;source/");
1783
1784     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_URL */
1785     r = pMsiSourceListSetInfoA(prodcode, NULL,
1786                                MSIINSTALLCONTEXT_USERUNMANAGED,
1787                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1788                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1790
1791     /* URL key is created by MsiSourceListSetInfo */
1792     res = RegOpenKeyA(source, "URL", &url);
1793     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1794     CHECK_REG_STR(url, "1", "source/");
1795     CHECK_REG_STR(source, "LastUsedSource", "u;1;source");
1796
1797     /* source has backslash */
1798     r = pMsiSourceListSetInfoA(prodcode, NULL,
1799                                MSIINSTALLCONTEXT_USERUNMANAGED,
1800                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1801                                INSTALLPROPERTY_LASTUSEDSOURCE, "source\\");
1802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1803     CHECK_REG_STR(url, "1", "source/");
1804     CHECK_REG_STR(url, "2", "source\\/");
1805     CHECK_REG_STR(source, "LastUsedSource", "u;2;source\\");
1806
1807     /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_MEDIA */
1808     r = pMsiSourceListSetInfoA(prodcode, NULL,
1809                                MSIINSTALLCONTEXT_USERUNMANAGED,
1810                                MSICODE_PRODUCT | MSISOURCETYPE_MEDIA,
1811                                INSTALLPROPERTY_LASTUSEDSOURCE, "source");
1812     ok(r == ERROR_INVALID_PARAMETER,
1813        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1814
1815     /* INSTALLPROPERTY_PACKAGENAME */
1816     r = pMsiSourceListSetInfoA(prodcode, NULL,
1817                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1818                                INSTALLPROPERTY_PACKAGENAME, "name");
1819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1820     CHECK_REG_STR(source, "PackageName", "name");
1821
1822     /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_NETWORK */
1823     r = pMsiSourceListSetInfoA(prodcode, NULL,
1824                                MSIINSTALLCONTEXT_USERUNMANAGED,
1825                                MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
1826                                INSTALLPROPERTY_PACKAGENAME, "name");
1827     ok(r == ERROR_INVALID_PARAMETER,
1828        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1829
1830     /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_URL */
1831     r = pMsiSourceListSetInfoA(prodcode, NULL,
1832                                MSIINSTALLCONTEXT_USERUNMANAGED,
1833                                MSICODE_PRODUCT | MSISOURCETYPE_URL,
1834                                INSTALLPROPERTY_PACKAGENAME, "name");
1835     ok(r == ERROR_INVALID_PARAMETER,
1836        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1837
1838     /* INSTALLPROPERTY_LASTUSEDTYPE */
1839     r = pMsiSourceListSetInfoA(prodcode, NULL,
1840                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1841                                INSTALLPROPERTY_LASTUSEDTYPE, "type");
1842     ok(r == ERROR_UNKNOWN_PROPERTY,
1843        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1844
1845     /* definitely unknown property */
1846     r = pMsiSourceListSetInfoA(prodcode, NULL,
1847                                MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT,
1848                                "unknown", "val");
1849     ok(r == ERROR_UNKNOWN_PROPERTY,
1850        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
1851
1852     RegDeleteValueA(net, "1");
1853     RegDeleteKeyA(net, "");
1854     RegCloseKey(net);
1855     RegDeleteValueA(url, "1");
1856     RegDeleteKeyA(url, "");
1857     RegCloseKey(url);
1858     RegDeleteValueA(media, "MediaPackage");
1859     RegDeleteValueA(media, "DiskPrompt");
1860     RegDeleteKeyA(media, "");
1861     RegCloseKey(media);
1862     RegDeleteValueA(source, "PackageName");
1863     RegDeleteKeyA(source, "");
1864     RegCloseKey(source);
1865     RegDeleteKeyA(userkey, "");
1866     RegCloseKey(userkey);
1867
1868     /* MSIINSTALLCONTEXT_USERMANAGED */
1869
1870     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1871     lstrcatA(keypath, usersid);
1872     lstrcatA(keypath, "\\Installer\\Products\\");
1873     lstrcatA(keypath, prod_squashed);
1874
1875     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
1876     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1877
1878     /* user product key exists */
1879     r = pMsiSourceListSetInfoA(prodcode, NULL,
1880                                MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
1881                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1882     ok(r == ERROR_BAD_CONFIGURATION,
1883        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1884
1885     res = RegCreateKeyA(userkey, "SourceList", &source);
1886     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1887
1888     /* SourceList key exists, no source type */
1889     r = pMsiSourceListSetInfoA(prodcode, NULL,
1890                                MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
1891                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1893
1894     /* Media key is created by MsiSourceListSetInfo */
1895     res = RegOpenKeyA(source, "Media", &media);
1896     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1897     CHECK_REG_STR(media, "MediaPackage", "path");
1898
1899     RegDeleteValueA(media, "MediaPackage");
1900     RegDeleteKeyA(media, "");
1901     RegCloseKey(media);
1902     RegDeleteKeyA(source, "");
1903     RegCloseKey(source);
1904     RegDeleteKeyA(userkey, "");
1905     RegCloseKey(userkey);
1906
1907     /* MSIINSTALLCONTEXT_MACHINE */
1908
1909     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1910     lstrcatA(keypath, prod_squashed);
1911
1912     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
1913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1914
1915     /* user product key exists */
1916     r = pMsiSourceListSetInfoA(prodcode, NULL,
1917                                MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
1918                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1919     ok(r == ERROR_BAD_CONFIGURATION,
1920        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
1921
1922     res = RegCreateKeyA(prodkey, "SourceList", &source);
1923     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1924
1925     /* SourceList key exists, no source type */
1926     r = pMsiSourceListSetInfoA(prodcode, NULL,
1927                                MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
1928                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1930
1931     /* Media key is created by MsiSourceListSetInfo */
1932     res = RegOpenKeyA(source, "Media", &media);
1933     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1934     CHECK_REG_STR(media, "MediaPackage", "path");
1935
1936     /* szUserSid is non-NULL */
1937     r = pMsiSourceListSetInfoA(prodcode, usersid,
1938                                MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT,
1939                                INSTALLPROPERTY_MEDIAPACKAGEPATH, "path");
1940     ok(r == ERROR_INVALID_PARAMETER,
1941        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1942
1943     RegDeleteValueA(media, "MediaPackage");
1944     RegDeleteKeyA(media, "");
1945     RegCloseKey(media);
1946     RegDeleteKeyA(source, "");
1947     RegCloseKey(source);
1948     RegDeleteKeyA(prodkey, "");
1949     RegCloseKey(prodkey);
1950 }
1951
1952 static void test_MsiSourceListAddMediaDisk(void)
1953 {
1954     CHAR prodcode[MAX_PATH];
1955     CHAR prod_squashed[MAX_PATH];
1956     CHAR keypath[MAX_PATH*2];
1957     HKEY prodkey, userkey;
1958     HKEY media, source;
1959     LPSTR usersid;
1960     LONG res;
1961     UINT r;
1962
1963     create_test_guid(prodcode, prod_squashed);
1964     get_user_sid(&usersid);
1965
1966     /* GetLastError is not set by the function */
1967
1968     /* NULL szProductCodeOrPatchCode */
1969     r = pMsiSourceListAddMediaDiskA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1970                                     MSICODE_PRODUCT, 1, "label", "prompt");
1971     ok(r == ERROR_INVALID_PARAMETER,
1972        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1973
1974     /* empty szProductCodeOrPatchCode */
1975     r = pMsiSourceListAddMediaDiskA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1976                                     MSICODE_PRODUCT, 1, "label", "prompt");
1977     ok(r == ERROR_INVALID_PARAMETER,
1978        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1979
1980     /* garbage szProductCodeOrPatchCode */
1981     r = pMsiSourceListAddMediaDiskA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1982                                     MSICODE_PRODUCT, 1, "label", "prompt");
1983     ok(r == ERROR_INVALID_PARAMETER,
1984        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1985
1986     /* guid without brackets */
1987     r = pMsiSourceListAddMediaDiskA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA",
1988                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1989                                     MSICODE_PRODUCT, 1, "label", "prompt");
1990     ok(r == ERROR_INVALID_PARAMETER,
1991        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1992
1993     /* guid with brackets */
1994     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
1995                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
1996                                     MSICODE_PRODUCT, 1, "label", "prompt");
1997     ok(r == ERROR_UNKNOWN_PRODUCT,
1998        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1999
2000     /* dwOptions has MSISOURCETYPE_NETWORK */
2001     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2002                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2003                                     MSICODE_PRODUCT | MSISOURCETYPE_NETWORK,
2004                                     1, "label", "prompt");
2005     ok(r == ERROR_INVALID_PARAMETER,
2006        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2007
2008     /* dwOptions has MSISOURCETYPE_URL */
2009     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2010                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2011                                     MSICODE_PRODUCT | MSISOURCETYPE_URL,
2012                                     1, "label", "prompt");
2013     ok(r == ERROR_INVALID_PARAMETER,
2014        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2015
2016     /* dwOptions has MSISOURCETYPE_MEDIA */
2017     r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}",
2018                                     usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
2019                                     MSICODE_PRODUCT | MSISOURCETYPE_MEDIA,
2020                                     1, "label", "prompt");
2021     ok(r == ERROR_INVALID_PARAMETER,
2022        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2023
2024     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2025
2026     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2027     lstrcatA(keypath, prod_squashed);
2028
2029     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2030     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2031
2032     /* user product key exists */
2033     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2034                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2035                                     MSICODE_PRODUCT, 1, "label", "prompt");
2036     ok(r == ERROR_BAD_CONFIGURATION,
2037        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2038
2039     res = RegCreateKeyA(userkey, "SourceList", &source);
2040     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2041
2042     /* SourceList key exists */
2043     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2044                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2045                                     MSICODE_PRODUCT, 1, "label", "prompt");
2046     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2047
2048     /* Media subkey is created by MsiSourceListAddMediaDisk */
2049     res = RegOpenKeyA(source, "Media", &media);
2050     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2051
2052     CHECK_REG_STR(media, "1", "label;prompt");
2053
2054     /* dwDiskId is random */
2055     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2056                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2057                                     MSICODE_PRODUCT, 42, "label42", "prompt42");
2058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2059
2060     CHECK_REG_STR(media, "1", "label;prompt");
2061     CHECK_REG_STR(media, "42", "label42;prompt42");
2062
2063     /* dwDiskId is 0 */
2064     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2065                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2066                                     MSICODE_PRODUCT, 0, "label0", "prompt0");
2067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2068
2069     CHECK_REG_STR(media, "0", "label0;prompt0");
2070     CHECK_REG_STR(media, "1", "label;prompt");
2071     CHECK_REG_STR(media, "42", "label42;prompt42");
2072
2073     /* dwDiskId is < 0 */
2074     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2075                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2076                                     MSICODE_PRODUCT, -1, "label-1", "prompt-1");
2077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2078
2079     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2080     CHECK_REG_STR(media, "0", "label0;prompt0");
2081     CHECK_REG_STR(media, "1", "label;prompt");
2082     CHECK_REG_STR(media, "42", "label42;prompt42");
2083
2084     /* update dwDiskId 1 */
2085     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2086                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2087                                     MSICODE_PRODUCT, 1, "newlabel", "newprompt");
2088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2089
2090     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2091     CHECK_REG_STR(media, "0", "label0;prompt0");
2092     CHECK_REG_STR(media, "1", "newlabel;newprompt");
2093     CHECK_REG_STR(media, "42", "label42;prompt42");
2094
2095     /* update dwDiskId 1, szPrompt is NULL */
2096     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2097                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2098                                     MSICODE_PRODUCT, 1, "etiqueta", NULL);
2099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2100
2101     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2102     CHECK_REG_STR(media, "0", "label0;prompt0");
2103     CHECK_REG_STR(media, "1", "etiqueta;");
2104     CHECK_REG_STR(media, "42", "label42;prompt42");
2105
2106     /* update dwDiskId 1, szPrompt is empty */
2107     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2108                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2109                                     MSICODE_PRODUCT, 1, "etikett", "");
2110     ok(r == ERROR_INVALID_PARAMETER,
2111        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2112
2113     /* update dwDiskId 1, szVolumeLable is NULL */
2114     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2115                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2116                                     MSICODE_PRODUCT, 1, NULL, "provocar");
2117     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2118
2119     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2120     CHECK_REG_STR(media, "0", "label0;prompt0");
2121     CHECK_REG_STR(media, "1", ";provocar");
2122     CHECK_REG_STR(media, "42", "label42;prompt42");
2123
2124     /* update dwDiskId 1, szVolumeLable is empty */
2125     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2126                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2127                                     MSICODE_PRODUCT, 1, "", "provoquer");
2128     ok(r == ERROR_INVALID_PARAMETER,
2129        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2130
2131     /* szUserSid is NULL */
2132     r = pMsiSourceListAddMediaDiskA(prodcode, NULL,
2133                                     MSIINSTALLCONTEXT_USERUNMANAGED,
2134                                     MSICODE_PRODUCT, 1, NULL, "provoquer");
2135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2136
2137     CHECK_REG_STR(media, "-1", "label-1;prompt-1");
2138     CHECK_REG_STR(media, "0", "label0;prompt0");
2139     CHECK_REG_STR(media, "1", ";provoquer");
2140     CHECK_REG_STR(media, "42", "label42;prompt42");
2141
2142     RegDeleteValueA(media, "-1");
2143     RegDeleteValueA(media, "0");
2144     RegDeleteValueA(media, "1");
2145     RegDeleteValueA(media, "42");
2146     RegDeleteKeyA(media, "");
2147     RegCloseKey(media);
2148     RegDeleteKeyA(source, "");
2149     RegCloseKey(source);
2150     RegDeleteKeyA(userkey, "");
2151     RegCloseKey(userkey);
2152
2153     /* MSIINSTALLCONTEXT_USERMANAGED */
2154
2155     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2156     lstrcatA(keypath, usersid);
2157     lstrcatA(keypath, "\\Installer\\Products\\");
2158     lstrcatA(keypath, prod_squashed);
2159
2160     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey);
2161     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2162
2163     /* user product key exists */
2164     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2165                                     MSIINSTALLCONTEXT_USERMANAGED,
2166                                     MSICODE_PRODUCT, 1, "label", "prompt");
2167     ok(r == ERROR_BAD_CONFIGURATION,
2168        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2169
2170     res = RegCreateKeyA(userkey, "SourceList", &source);
2171     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2172
2173     /* SourceList key exists */
2174     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2175                                     MSIINSTALLCONTEXT_USERMANAGED,
2176                                     MSICODE_PRODUCT, 1, "label", "prompt");
2177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2178
2179     /* Media subkey is created by MsiSourceListAddMediaDisk */
2180     res = RegOpenKeyA(source, "Media", &media);
2181     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2182
2183     CHECK_REG_STR(media, "1", "label;prompt");
2184
2185     RegDeleteValueA(media, "1");
2186     RegDeleteKeyA(media, "");
2187     RegCloseKey(media);
2188     RegDeleteKeyA(source, "");
2189     RegCloseKey(source);
2190     RegDeleteKeyA(userkey, "");
2191     RegCloseKey(userkey);
2192
2193     /* MSIINSTALLCONTEXT_MACHINE */
2194
2195     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2196     lstrcatA(keypath, prod_squashed);
2197
2198     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
2199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2200
2201     /* machine product key exists */
2202     r = pMsiSourceListAddMediaDiskA(prodcode, NULL,
2203                                     MSIINSTALLCONTEXT_MACHINE,
2204                                     MSICODE_PRODUCT, 1, "label", "prompt");
2205     ok(r == ERROR_BAD_CONFIGURATION,
2206        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
2207
2208     res = RegCreateKeyA(prodkey, "SourceList", &source);
2209     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2210
2211     /* SourceList key exists */
2212     r = pMsiSourceListAddMediaDiskA(prodcode, NULL,
2213                                     MSIINSTALLCONTEXT_MACHINE,
2214                                     MSICODE_PRODUCT, 1, "label", "prompt");
2215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2216
2217     /* Media subkey is created by MsiSourceListAddMediaDisk */
2218     res = RegOpenKeyA(source, "Media", &media);
2219     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2220
2221     CHECK_REG_STR(media, "1", "label;prompt");
2222
2223     /* szUserSid is non-NULL */
2224     r = pMsiSourceListAddMediaDiskA(prodcode, usersid,
2225                                     MSIINSTALLCONTEXT_MACHINE,
2226                                     MSICODE_PRODUCT, 1, "label", "prompt");
2227     ok(r == ERROR_INVALID_PARAMETER,
2228        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2229
2230     RegDeleteValueA(media, "1");
2231     RegDeleteKeyA(media, "");
2232     RegCloseKey(media);
2233     RegDeleteKeyA(source, "");
2234     RegCloseKey(source);
2235     RegDeleteKeyA(prodkey, "");
2236     RegCloseKey(prodkey);
2237 }
2238
2239 START_TEST(source)
2240 {
2241     init_functionpointers();
2242
2243     test_MsiSourceListGetInfo();
2244     test_MsiSourceListAddSourceEx();
2245     test_MsiSourceListEnumSources();
2246     test_MsiSourceListSetInfo();
2247     test_MsiSourceListAddMediaDisk();
2248 }