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