/* * Tests for MSI Source functions * * Copyright (C) 2006 James Hawkins * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define _WIN32_MSI 300 #include #include #include #include #include #include #include #include #include "wine/test.h" #include "utils.h" static BOOL is_wow64; static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); static UINT (WINAPI *pMsiSourceListAddMediaDiskA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPCSTR, LPCSTR); static UINT (WINAPI *pMsiSourceListAddSourceExA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, DWORD); static UINT (WINAPI *pMsiSourceListEnumMediaDisksA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPDWORD, LPSTR, LPDWORD, LPSTR, LPDWORD); static UINT (WINAPI *pMsiSourceListEnumSourcesA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD); static UINT (WINAPI *pMsiSourceListGetInfoA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD); static UINT (WINAPI *pMsiSourceListGetInfoW) (LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR, LPWSTR, LPDWORD); static UINT (WINAPI *pMsiSourceListSetInfoA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD,LPCSTR, LPCSTR); static UINT (WINAPI *pMsiSourceListAddSourceA) (LPCSTR, LPCSTR, DWORD, LPCSTR); static void init_functionpointers(void) { HMODULE hmsi = GetModuleHandleA("msi.dll"); HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll"); HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); #define GET_PROC(dll, func) \ p ## func = (void *)GetProcAddress(dll, #func); \ if(!p ## func) \ trace("GetProcAddress(%s) failed\n", #func); GET_PROC(hmsi, MsiSourceListAddMediaDiskA) GET_PROC(hmsi, MsiSourceListAddSourceExA) GET_PROC(hmsi, MsiSourceListEnumMediaDisksA) GET_PROC(hmsi, MsiSourceListEnumSourcesA) GET_PROC(hmsi, MsiSourceListGetInfoA) GET_PROC(hmsi, MsiSourceListGetInfoW) GET_PROC(hmsi, MsiSourceListSetInfoA) GET_PROC(hmsi, MsiSourceListAddSourceA) GET_PROC(hadvapi32, RegDeleteKeyExA) GET_PROC(hkernel32, IsWow64Process) #undef GET_PROC } /* copied from dlls/msi/registry.c */ static BOOL squash_guid(LPCWSTR in, LPWSTR out) { DWORD i,n=1; GUID guid; if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid))) return FALSE; for(i=0; i<8; i++) out[7-i] = in[n++]; n++; for(i=0; i<4; i++) out[11-i] = in[n++]; n++; for(i=0; i<4; i++) out[15-i] = in[n++]; n++; for(i=0; i<2; i++) { out[17+i*2] = in[n++]; out[16+i*2] = in[n++]; } n++; for( ; i<8; i++) { out[17+i*2] = in[n++]; out[16+i*2] = in[n++]; } out[32]=0; return TRUE; } static void create_test_guid(LPSTR prodcode, LPSTR squashed) { WCHAR guidW[MAX_PATH]; WCHAR squashedW[MAX_PATH]; GUID guid; HRESULT hr; int size; hr = CoCreateGuid(&guid); ok(hr == S_OK, "Expected S_OK, got %d\n", hr); size = StringFromGUID2(&guid, guidW, MAX_PATH); ok(size == 39, "Expected 39, got %d\n", hr); WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL); squash_guid(guidW, squashedW); WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL); } static char *get_user_sid(void) { HANDLE token; DWORD size = 0; TOKEN_USER *user; char *usersid = NULL; OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); GetTokenInformation(token, TokenUser, NULL, size, &size); user = malloc(size); GetTokenInformation(token, TokenUser, user, size, &size); ConvertSidToStringSidA(user->User.Sid, &usersid); free(user); CloseHandle(token); return usersid; } static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line) { char val[MAX_PATH]; DWORD size, type; LONG res; size = MAX_PATH; val[0] = '\0'; res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size); if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) { ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n"); return; } if (!expected) ok_(__FILE__, line)(!val[0], "Expected empty string, got %s\n", val); else { if (bcase) ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val); else ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val); } } #define CHECK_REG_STR(prodkey, name, expected) \ check_reg_str(prodkey, name, expected, TRUE, __LINE__); static inline WCHAR *strdupAW( const char *str ) { int len; WCHAR *ret; len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL; MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); return ret; } static void test_MsiSourceListGetInfo(void) { char prodcode[MAX_PATH], prod_squashed[MAX_PATH], keypath[MAX_PATH * 2], value[MAX_PATH], *usersid; WCHAR valueW[MAX_PATH], *usersidW, *prodcodeW; const char *data; LONG res; UINT r; HKEY userkey, hkey, media; DWORD size; if (!pMsiSourceListGetInfoA) { win_skip("Skipping MsiSourceListGetInfoA tests\n"); return; } create_test_guid(prodcode, prod_squashed); if (!(usersid = get_user_sid())) { skip("User SID not available -> skipping MsiSourceListGetInfoA tests\n"); return; } /* NULL szProductCodeOrPatchCode */ r = pMsiSourceListGetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szProductCodeOrPatchCode */ r = pMsiSourceListGetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* garbage szProductCodeOrPatchCode */ r = pMsiSourceListGetInfoA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid without brackets */ r = pMsiSourceListGetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid with brackets */ r = pMsiSourceListGetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* same length as guid, but random */ r = pMsiSourceListGetInfoA("ADKD-2KSDFF2-DKK1KNFJASD9GLKWME-1I3KAD", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* invalid context */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_NONE, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* another invalid context */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALLUSERMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* yet another invalid context */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_ALL, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* mix two valid contexts */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED | MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* invalid option */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 4, INSTALLPROPERTY_PACKAGENAMEA, NULL, NULL); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* NULL property */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, NULL, NULL, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty property */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, "", NULL, NULL); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* value is non-NULL while size is NULL */ r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, value, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* size is non-NULL while value is NULL */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, &size); ok(r == ERROR_UNKNOWN_PRODUCT || r == ERROR_INVALID_PARAMETER, "Expected ERROR_UNKNOWN_PRODUCT or ERROR_INVALID_PARAMETER, got %d\n", r); lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* user product key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value); res = RegCreateKeyA(userkey, "SourceList", &hkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(size == 0, "Expected 0, got %d\n", size); ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value); data = "msitest.msi"; res = RegSetValueExA(hkey, "PackageName", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* PackageName value exists */ size = 0xdeadbeef; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, NULL, &size); ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER, "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r); ok(size == 11 || r != ERROR_SUCCESS, "Expected 11, got %d\n", size); /* read the value, don't change size */ size = 11; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected 'aaa', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); /* read the value, fix size */ size++; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); /* empty property now that product key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, "", value, &size); ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r); ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value); /* nonexistent property now that product key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, "nonexistent", value, &size); ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r); ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value); data = "tester"; res = RegSetValueExA(hkey, "nonexistent", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* nonexistent property now that nonexistent value exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, "nonexistent", value, &size); ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r); ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value); /* invalid option now that product key exists */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 4, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(size == 11, "Expected 11, got %d\n", size); /* INSTALLPROPERTY_MEDIAPACKAGEPATH, media key does not exist */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value); ok(size == 0, "Expected 0, got %d\n", size); res = RegCreateKeyA(hkey, "Media", &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); data = "path"; res = RegSetValueExA(media, "MediaPackage", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_MEDIAPACKAGEPATH */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "path"), "Expected \"path\", got \"%s\"\n", value); ok(size == 4, "Expected 4, got %d\n", size); /* INSTALLPROPERTY_DISKPROMPT */ data = "prompt"; res = RegSetValueExA(media, "DiskPrompt", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPTA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "prompt"), "Expected \"prompt\", got \"%s\"\n", value); ok(size == 6, "Expected 6, got %d\n", size); /* LastUsedSource value doesn't exist */ RegDeleteValueA(hkey, "LastUsedSource"); size = MAX_PATH; memset(value, 0x55, sizeof(value)); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value); ok(size == 0, "Expected 0, got %d\n", size); size = MAX_PATH; usersidW = strdupAW(usersid); prodcodeW = strdupAW(prodcode); memset(valueW, 0x55, sizeof(valueW)); r = pMsiSourceListGetInfoW(prodcodeW, usersidW, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, valueW, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!valueW[0], "Expected \"\""); ok(size == 0, "Expected 0, got %d\n", size); free(usersidW); free(prodcodeW); data = ""; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDSOURCE, source is empty */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value); ok(size == 0, "Expected 0, got %d\n", size); data = "source"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDSOURCE */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "source"), "Expected \"source\", got \"%s\"\n", value); ok(size == 6, "Expected 6, got %d\n", size); /* INSTALLPROPERTY_LASTUSEDSOURCE, size is too short */ size = 4; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size); ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got \"%s\"\n", value); ok(size == 6, "Expected 6, got %d\n", size); /* INSTALLPROPERTY_LASTUSEDSOURCE, size is exactly 6 */ size = 6; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size); ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got \"%s\"\n", value); ok(size == 6, "Expected 6, got %d\n", size); data = "a;source"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDSOURCE, one semi-colon */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "source"), "Expected \"source\", got \"%s\"\n", value); ok(size == 6, "Expected 6, got %d\n", size); data = "a:source"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDSOURCE, one colon */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "a:source"), "Expected \"a:source\", got \"%s\"\n", value); ok(size == 8, "Expected 8, got %d\n", size); /* INSTALLPROPERTY_LASTUSEDTYPE, invalid source format */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value); ok(size == 0, "Expected 0, got %d\n", size); data = "x;y;z"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDTYPE, invalid source format */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value); ok(size == 0, "Expected 0, got %d\n", size); data = "n;y;z"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDTYPE */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value); ok(size == 1, "Expected 1, got %d\n", size); data = "negatory"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDTYPE */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value); ok(size == 1, "Expected 1, got %d\n", size); data = "megatron"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDTYPE */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "m"), "Expected \"m\", got \"%s\"\n", value); ok(size == 1, "Expected 1, got %d\n", size); data = "useless"; res = RegSetValueExA(hkey, "LastUsedSource", 0, REG_SZ, (const BYTE *)data, lstrlenA(data) + 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* INSTALLPROPERTY_LASTUSEDTYPE */ size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "u"), "Expected \"u\", got \"%s\"\n", value); ok(size == 1, "Expected 1, got %d\n", size); RegDeleteValueA(media, "MediaPackage"); RegDeleteValueA(media, "DiskPrompt"); RegDeleteKeyA(media, ""); RegDeleteValueA(hkey, "LastUsedSource"); RegDeleteValueA(hkey, "nonexistent"); RegDeleteValueA(hkey, "PackageName"); RegDeleteKeyA(hkey, ""); RegDeleteKeyA(userkey, ""); RegCloseKey(hkey); RegCloseKey(userkey); /* try a patch */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r); ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value); lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Patches\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* patch key exists * NOTE: using prodcode guid, but it really doesn't matter */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value); res = RegCreateKeyA(userkey, "SourceList", &hkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH, INSTALLPROPERTY_PACKAGENAMEA, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value); ok(size == 0, "Expected 0, got %d\n", size); RegDeleteKeyA(hkey, ""); RegDeleteKeyA(userkey, ""); RegCloseKey(hkey); RegCloseKey(userkey); LocalFree(usersid); } static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access ) { if (pRegDeleteKeyExA) return pRegDeleteKeyExA( key, subkey, access, 0 ); return RegDeleteKeyA( key, subkey ); } static void test_MsiSourceListAddSourceEx(void) { CHAR prodcode[MAX_PATH]; CHAR prod_squashed[MAX_PATH]; CHAR keypath[MAX_PATH*2]; CHAR value[MAX_PATH]; LPSTR usersid; LONG res; UINT r; HKEY prodkey, userkey, hkey, url, net; DWORD size; REGSAM access = KEY_ALL_ACCESS; if (!pMsiSourceListAddSourceExA) { win_skip("Skipping MsiSourceListAddSourceExA tests\n"); return; } if (is_process_limited()) { skip("process is limited\n"); return; } create_test_guid(prodcode, prod_squashed); if (!(usersid = get_user_sid())) { skip("User SID not available -> skipping MsiSourceListAddSourceExA tests\n"); return; } if (is_wow64) access |= KEY_WOW64_64KEY; /* GetLastError is not set by the function */ /* NULL szProductCodeOrPatchCode */ r = pMsiSourceListAddSourceExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szProductCodeOrPatchCode */ r = pMsiSourceListAddSourceExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* garbage szProductCodeOrPatchCode */ r = pMsiSourceListAddSourceExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid without brackets */ r = pMsiSourceListAddSourceExA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid with brackets */ r = pMsiSourceListAddSourceExA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* MSIINSTALLCONTEXT_USERUNMANAGED */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* user product key exists */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyA(userkey, "SourceList", &url); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); RegCloseKey(url); /* SourceList key exists */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); res = RegOpenKeyA(userkey, "SourceList\\URL", &url); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); /* add another source, index 0 */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value); ok(size == 9, "Expected 9, got %d\n", size); /* add another source, index 1 */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "third/", 1); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value); ok(size == 7, "Expected 7, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value); ok(size == 9, "Expected 9, got %d\n", size); /* add another source, index > N */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "last/", 5); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value); ok(size == 7, "Expected 7, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value); ok(size == 9, "Expected 9, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value); ok(size == 6, "Expected 6, got %d\n", size); /* just MSISOURCETYPE_NETWORK */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSISOURCETYPE_NETWORK, "source", 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); res = RegOpenKeyA(userkey, "SourceList\\Net", &net); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); size = MAX_PATH; res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value); ok(size == 8, "Expected 8, got %d\n", size); /* just MSISOURCETYPE_URL */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSISOURCETYPE_URL, "source", 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value); ok(size == 7, "Expected 7, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value); ok(size == 9, "Expected 9, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "last/"), "Expected 'last/', got %s\n", value); ok(size == 6, "Expected 6, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "5", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "source/"), "Expected 'source/', got %s\n", value); ok(size == 8, "Expected 8, got %d\n", size); /* NULL szUserSid */ r = pMsiSourceListAddSourceExA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSISOURCETYPE_NETWORK, "nousersid", 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); size = MAX_PATH; res = RegQueryValueExA(net, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "source\\"), "Expected 'source\\', got %s\n", value); ok(size == 8, "Expected 8, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(net, "2", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "nousersid\\"), "Expected 'nousersid\\', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); /* invalid options, must have source type */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, "source", 0); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH, "source", 0); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* NULL szSource */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSISOURCETYPE_URL, NULL, 1); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szSource */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSISOURCETYPE_URL, "", 1); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* MSIINSTALLCONTEXT_USERMANAGED, non-NULL szUserSid */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); lstrcatA(keypath, usersid); lstrcatA(keypath, "\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); goto machine_tests; } /* product key exists */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &hkey, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); RegCloseKey(hkey); /* SourceList exists */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); res = RegOpenKeyExA(prodkey, "SourceList\\URL", 0, access, &url); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); RegCloseKey(url); /* MSIINSTALLCONTEXT_USERMANAGED, NULL szUserSid */ r = pMsiSourceListAddSourceExA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, "another", 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); res = RegOpenKeyExA(prodkey, "SourceList\\URL", 0, access, &url); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); size = MAX_PATH; res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value); ok(size == 9, "Expected 9, got %d\n", size); RegCloseKey(url); RegCloseKey(prodkey); /* MSIINSTALLCONTEXT_MACHINE */ machine_tests: /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */ r = pMsiSourceListAddSourceExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); r = pMsiSourceListAddSourceExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); LocalFree(usersid); return; } /* product key exists */ r = pMsiSourceListAddSourceExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &hkey, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); RegCloseKey(hkey); /* SourceList exists */ r = pMsiSourceListAddSourceExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, "C:\\source", 0); if (r == ERROR_ACCESS_DENIED) skip("MsiSourceListAddSourceEx (insufficient privileges)\n"); else { ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); res = RegOpenKeyExA(prodkey, "SourceList\\URL", 0, access, &url); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); size = MAX_PATH; res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value); ok(size == 11, "Expected 11, got %d\n", size); RegCloseKey(url); RegCloseKey(prodkey); } LocalFree(usersid); } static void test_MsiSourceListEnumSources(void) { CHAR prodcode[MAX_PATH]; CHAR prod_squashed[MAX_PATH]; CHAR keypath[MAX_PATH*2]; CHAR value[MAX_PATH]; LPSTR usersid; LONG res; UINT r; HKEY prodkey, userkey; HKEY url, net, source; DWORD size; REGSAM access = KEY_ALL_ACCESS; if (!pMsiSourceListEnumSourcesA) { win_skip("MsiSourceListEnumSourcesA is not available\n"); return; } create_test_guid(prodcode, prod_squashed); if (!(usersid = get_user_sid())) { skip("User SID not available -> skipping MsiSourceListEnumSourcesA tests\n"); return; } if (is_wow64) access |= KEY_WOW64_64KEY; /* GetLastError is not set by the function */ /* NULL szProductCodeOrPatchCode */ size = 0xdeadbeef; r = pMsiSourceListEnumSourcesA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size); /* empty szProductCodeOrPatchCode */ size = 0xdeadbeef; r = pMsiSourceListEnumSourcesA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size); /* garbage szProductCodeOrPatchCode */ size = 0xdeadbeef; r = pMsiSourceListEnumSourcesA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size); /* guid without brackets */ size = 0xdeadbeef; r = pMsiSourceListEnumSourcesA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size); /* guid with brackets */ size = 0xdeadbeef; r = pMsiSourceListEnumSourcesA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size); /* MSIINSTALLCONTEXT_USERUNMANAGED */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* user product key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyA(userkey, "SourceList", &source); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyA(source, "URL", &url); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* URL key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); res = RegSetValueExA(url, "2", 0, REG_SZ, (LPBYTE)"second", 7); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); res = RegSetValueExA(url, "4", 0, REG_SZ, (LPBYTE)"fourth", 7); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* sources exist */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); /* try index 0 again */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); /* both szSource and pcchSource are NULL, index 0 */ r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, NULL); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* both szSource and pcchSource are NULL, index 1 */ r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, NULL, NULL); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* size is exactly 5 */ size = 5; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); /* szSource is non-NULL while pcchSource is NULL */ lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value); /* try index 1 after failure */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* reset the enumeration */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); /* try index 1 */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "second"), "Expected \"second\", got %s\n", value); ok(size == 6, "Expected 6, got %d\n", size); /* try index 1 again */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* try index 2 */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 2, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* try index < 0 */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, -1, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* NULL szUserSid */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* invalid dwOptions, must be one of MSICODE_ and MSISOURCETYPE_ */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); RegDeleteValueA(url, "1"); RegDeleteValueA(url, "2"); RegDeleteValueA(url, "4"); RegDeleteKeyA(url, ""); RegCloseKey(url); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyA(source, "Net", &net); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* Net key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* sources exist */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); RegDeleteValueA(net, "1"); RegDeleteKeyA(net, ""); RegCloseKey(net); RegDeleteKeyA(source, ""); RegCloseKey(source); RegDeleteKeyA(userkey, ""); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_USERMANAGED */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); lstrcatA(keypath, usersid); lstrcatA(keypath, "\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); goto machine_tests; } /* user product key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyExA(userkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyExA(source, "URL", 0, NULL, 0, access, NULL, &url, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* URL key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* sources exist */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); /* NULL szUserSid */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); RegDeleteValueA(url, "1"); delete_key(url, "", access); RegCloseKey(url); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyExA(source, "Net", 0, NULL, 0, access, NULL, &net, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* Net key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* sources exist */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); RegDeleteValueA(net, "1"); delete_key(net, "", access); RegCloseKey(net); delete_key(source, "", access); RegCloseKey(source); delete_key(userkey, "", access); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_MACHINE */ machine_tests: /* szUserSid is non-NULL */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); /* szUserSid is NULL */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); LocalFree(usersid); return; } /* user product key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyExA(source, "URL", 0, NULL, 0, access, NULL, &url, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* URL key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegSetValueExA(url, "1", 0, REG_SZ, (LPBYTE)"first", 6); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* sources exist */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); /* NULL szUserSid */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); RegDeleteValueA(url, "1"); delete_key(url, "", access); RegCloseKey(url); /* SourceList key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegCreateKeyExA(source, "Net", 0, NULL, 0, access, NULL, &net, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* Net key exists */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value); ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size); res = RegSetValueExA(net, "1", 0, REG_SZ, (LPBYTE)"first", 6); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* sources exist */ size = MAX_PATH; lstrcpyA(value, "aaa"); r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(value, "first"), "Expected \"first\", got %s\n", value); ok(size == 5, "Expected 5, got %d\n", size); RegDeleteValueA(net, "1"); delete_key(net, "", access); RegCloseKey(net); delete_key(source, "", access); RegCloseKey(source); delete_key(prodkey, "", access); RegCloseKey(prodkey); LocalFree(usersid); } static void test_MsiSourceListSetInfo(void) { CHAR prodcode[MAX_PATH]; CHAR prod_squashed[MAX_PATH]; CHAR keypath[MAX_PATH*2]; HKEY prodkey, userkey; HKEY net, url, media, source; LPSTR usersid; LONG res; UINT r; REGSAM access = KEY_ALL_ACCESS; if (!pMsiSourceListSetInfoA) { win_skip("MsiSourceListSetInfoA is not available\n"); return; } if (is_process_limited()) { skip("process is limited\n"); return; } create_test_guid(prodcode, prod_squashed); if (!(usersid = get_user_sid())) { skip("User SID not available -> skipping MsiSourceListSetInfoA tests\n"); return; } if (is_wow64) access |= KEY_WOW64_64KEY; /* GetLastError is not set by the function */ /* NULL szProductCodeOrPatchCode */ r = pMsiSourceListSetInfoA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szProductCodeOrPatchCode */ r = pMsiSourceListSetInfoA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* garbage szProductCodeOrPatchCode */ r = pMsiSourceListSetInfoA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid without brackets */ r = pMsiSourceListSetInfoA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid with brackets */ r = pMsiSourceListSetInfoA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* dwOptions is MSICODE_PRODUCT */ r = pMsiSourceListSetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* dwOptions is MSICODE_PATCH */ r = pMsiSourceListSetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PATCH, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r); /* dwOptions is both MSICODE_PRODUCT and MSICODE_PATCH */ r = pMsiSourceListSetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSICODE_PATCH | MSISOURCETYPE_URL, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r); /* dwOptions has both MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* LastUsedSource and dwOptions has both * MSISOURCETYPE_NETWORK and MSISOURCETYPE_URL */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL, INSTALLPROPERTY_LASTUSEDSOURCEA, "path"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* LastUsedSource and dwOptions has no source type */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, "path"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* MSIINSTALLCONTEXT_USERUNMANAGED */ lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* user product key exists */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyA(userkey, "SourceList", &source); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists, no source type */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Media key is created by MsiSourceListSetInfo */ res = RegOpenKeyA(source, "Media", &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(media, "MediaPackage", "path"); /* set the info again */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path2"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "MediaPackage", "path2"); /* NULL szProperty */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, NULL, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szProperty */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, "", "path"); ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r); /* NULL szValue */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, NULL); ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r); /* empty szValue */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, ""); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "MediaPackage", ""); /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_NETWORK */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_MEDIAPACKAGEPATH, MSISOURCETYPE_URL */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_DISKPROMPT */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPTA, "prompt"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "DiskPrompt", "prompt"); /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_NETWORK */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_DISKPROMPTA, "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_DISKPROMPT, MSISOURCETYPE_URL */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, INSTALLPROPERTY_DISKPROMPTA, "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_LASTUSEDSOURCE */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, "source"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_NETWORK */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_LASTUSEDSOURCEA, "source"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Net key is created by MsiSourceListSetInfo */ res = RegOpenKeyA(source, "Net", &net); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(net, "1", "source\\") CHECK_REG_STR(source, "LastUsedSource", "n;1;source"); /* source has forward slash */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_LASTUSEDSOURCEA, "source/"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(net, "1", "source\\"); CHECK_REG_STR(net, "2", "source/\\"); CHECK_REG_STR(source, "LastUsedSource", "n;2;source/"); /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_URL */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, INSTALLPROPERTY_LASTUSEDSOURCEA, "source"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* URL key is created by MsiSourceListSetInfo */ res = RegOpenKeyA(source, "URL", &url); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(url, "1", "source/"); CHECK_REG_STR(source, "LastUsedSource", "u;1;source"); /* source has backslash */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, INSTALLPROPERTY_LASTUSEDSOURCEA, "source\\"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(url, "1", "source/"); CHECK_REG_STR(url, "2", "source\\/"); CHECK_REG_STR(source, "LastUsedSource", "u;2;source\\"); /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_MEDIA */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_MEDIA, INSTALLPROPERTY_LASTUSEDSOURCEA, "source"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_PACKAGENAME */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEA, "name"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(source, "PackageName", "name"); /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_NETWORK */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_PACKAGENAMEA, "name"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_PACKAGENAME, MSISOURCETYPE_URL */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, INSTALLPROPERTY_PACKAGENAMEA, "name"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_LASTUSEDTYPE */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPEA, "type"); ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r); /* definitely unknown property */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, "unknown", "val"); ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r); RegDeleteValueA(net, "1"); RegDeleteKeyA(net, ""); RegCloseKey(net); RegDeleteValueA(url, "1"); RegDeleteKeyA(url, ""); RegCloseKey(url); RegDeleteValueA(media, "MediaPackage"); RegDeleteValueA(media, "DiskPrompt"); RegDeleteKeyA(media, ""); RegCloseKey(media); RegDeleteValueA(source, "PackageName"); RegDeleteKeyA(source, ""); RegCloseKey(source); RegDeleteKeyA(userkey, ""); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_USERMANAGED */ lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); lstrcatA(keypath, usersid); lstrcatA(keypath, "\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); goto machine_tests; } /* user product key exists */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(userkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists, no source type */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Media key is created by MsiSourceListSetInfo */ res = RegOpenKeyExA(source, "Media", 0, access, &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(media, "MediaPackage", "path"); RegDeleteValueA(media, "MediaPackage"); delete_key(media, "", access); RegCloseKey(media); delete_key(source, "", access); RegCloseKey(source); delete_key(userkey, "", access); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_MACHINE */ machine_tests: lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); LocalFree(usersid); return; } /* user product key exists */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists, no source type */ r = pMsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); if (r == ERROR_ACCESS_DENIED) { skip("MsiSourceListSetInfo (insufficient privileges)\n"); goto done; } ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Media key is created by MsiSourceListSetInfo */ res = RegOpenKeyExA(source, "Media", 0, access, &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(media, "MediaPackage", "path"); /* szUserSid is non-NULL */ r = pMsiSourceListSetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATHA, "path"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); RegDeleteValueA(media, "MediaPackage"); delete_key(media, "", access); RegCloseKey(media); done: delete_key(source, "", access); RegCloseKey(source); delete_key(prodkey, "", access); RegCloseKey(prodkey); LocalFree(usersid); } static void test_MsiSourceListAddMediaDisk(void) { CHAR prodcode[MAX_PATH]; CHAR prod_squashed[MAX_PATH]; CHAR keypath[MAX_PATH*2]; HKEY prodkey, userkey; HKEY media, source; LPSTR usersid; LONG res; UINT r; REGSAM access = KEY_ALL_ACCESS; if (!pMsiSourceListAddMediaDiskA) { win_skip("MsiSourceListAddMediaDiskA is not available\n"); return; } if (is_process_limited()) { skip("process is limited\n"); return; } create_test_guid(prodcode, prod_squashed); if (!(usersid = get_user_sid())) { skip("User SID not available -> skipping MsiSourceListAddMediaDiskA tests\n"); return; } if (is_wow64) access |= KEY_WOW64_64KEY; /* GetLastError is not set by the function */ /* NULL szProductCodeOrPatchCode */ r = pMsiSourceListAddMediaDiskA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szProductCodeOrPatchCode */ r = pMsiSourceListAddMediaDiskA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* garbage szProductCodeOrPatchCode */ r = pMsiSourceListAddMediaDiskA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid without brackets */ r = pMsiSourceListAddMediaDiskA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid with brackets */ r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* dwOptions has MSISOURCETYPE_NETWORK */ r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* dwOptions has MSISOURCETYPE_URL */ r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* dwOptions has MSISOURCETYPE_MEDIA */ r = pMsiSourceListAddMediaDiskA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_MEDIA, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* MSIINSTALLCONTEXT_USERUNMANAGED */ lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* user product key exists */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyA(userkey, "SourceList", &source); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Media subkey is created by MsiSourceListAddMediaDisk */ res = RegOpenKeyA(source, "Media", &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(media, "1", "label;prompt"); /* dwDiskId is random */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 42, "label42", "prompt42"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "1", "label;prompt"); CHECK_REG_STR(media, "42", "label42;prompt42"); /* dwDiskId is 0 */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, "label0", "prompt0"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "0", "label0;prompt0"); CHECK_REG_STR(media, "1", "label;prompt"); CHECK_REG_STR(media, "42", "label42;prompt42"); /* dwDiskId is < 0 */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, -1, "label-1", "prompt-1"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "-1", "label-1;prompt-1"); CHECK_REG_STR(media, "0", "label0;prompt0"); CHECK_REG_STR(media, "1", "label;prompt"); CHECK_REG_STR(media, "42", "label42;prompt42"); /* update dwDiskId 1 */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "newlabel", "newprompt"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "-1", "label-1;prompt-1"); CHECK_REG_STR(media, "0", "label0;prompt0"); CHECK_REG_STR(media, "1", "newlabel;newprompt"); CHECK_REG_STR(media, "42", "label42;prompt42"); /* update dwDiskId 1, szPrompt is NULL */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "etiqueta", NULL); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "-1", "label-1;prompt-1"); CHECK_REG_STR(media, "0", "label0;prompt0"); CHECK_REG_STR(media, "1", "etiqueta;"); CHECK_REG_STR(media, "42", "label42;prompt42"); /* update dwDiskId 1, szPrompt is empty */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "etikett", ""); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* update dwDiskId 1, szVolumeLabel is NULL */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, NULL, "provocar"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "-1", "label-1;prompt-1"); CHECK_REG_STR(media, "0", "label0;prompt0"); CHECK_REG_STR(media, "1", ";provocar"); CHECK_REG_STR(media, "42", "label42;prompt42"); /* update dwDiskId 1, szVolumeLabel is empty */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, "", "provoquer"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* szUserSid is NULL */ r = pMsiSourceListAddMediaDiskA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, NULL, "provoquer"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(media, "-1", "label-1;prompt-1"); CHECK_REG_STR(media, "0", "label0;prompt0"); CHECK_REG_STR(media, "1", ";provoquer"); CHECK_REG_STR(media, "42", "label42;prompt42"); RegDeleteValueA(media, "-1"); RegDeleteValueA(media, "0"); RegDeleteValueA(media, "1"); RegDeleteValueA(media, "42"); RegDeleteKeyA(media, ""); RegCloseKey(media); RegDeleteKeyA(source, ""); RegCloseKey(source); RegDeleteKeyA(userkey, ""); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_USERMANAGED */ lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); lstrcatA(keypath, usersid); lstrcatA(keypath, "\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); goto machine_tests; } /* user product key exists */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(userkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Media subkey is created by MsiSourceListAddMediaDisk */ res = RegOpenKeyExA(source, "Media", 0, access, &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(media, "1", "label;prompt"); RegDeleteValueA(media, "1"); delete_key(media, "", access); RegCloseKey(media); delete_key(source, "", access); RegCloseKey(source); delete_key(userkey, "", access); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_MACHINE */ machine_tests: lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); LocalFree(usersid); return; } /* machine product key exists */ r = pMsiSourceListAddMediaDiskA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ r = pMsiSourceListAddMediaDiskA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 1, "label", "prompt"); if (r == ERROR_ACCESS_DENIED) { skip("MsiSourceListAddMediaDisk (insufficient privileges)\n"); goto done; } ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Media subkey is created by MsiSourceListAddMediaDisk */ res = RegOpenKeyExA(source, "Media", 0, access, &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(media, "1", "label;prompt"); /* szUserSid is non-NULL */ r = pMsiSourceListAddMediaDiskA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 1, "label", "prompt"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); RegDeleteValueA(media, "1"); delete_key(media, "", access); RegCloseKey(media); done: delete_key(source, "", access); RegCloseKey(source); delete_key(prodkey, "", access); RegCloseKey(prodkey); LocalFree(usersid); } static void test_MsiSourceListEnumMediaDisks(void) { CHAR prodcode[MAX_PATH]; CHAR prod_squashed[MAX_PATH]; CHAR keypath[MAX_PATH*2]; CHAR label[MAX_PATH]; CHAR prompt[MAX_PATH]; HKEY prodkey, userkey, media, source; DWORD labelsz, promptsz, val, id; LPSTR usersid; LONG res; UINT r; REGSAM access = KEY_ALL_ACCESS; if (!pMsiSourceListEnumMediaDisksA) { win_skip("MsiSourceListEnumMediaDisksA is not available\n"); return; } create_test_guid(prodcode, prod_squashed); if (!(usersid = get_user_sid())) { skip("User SID not available -> skipping MsiSourceListEnumMediaDisksA tests\n"); return; } if (is_wow64) access |= KEY_WOW64_64KEY; /* GetLastError is not set by the function */ /* NULL szProductCodeOrPatchCode */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szProductCodeOrPatchCode */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* garbage szProductCodeOrPatchCode */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid without brackets */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid with brackets */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* dwOptions has MSISOURCETYPE_NETWORK */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* dwOptions has MSISOURCETYPE_URL */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* dwIndex is non-zero */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* MSIINSTALLCONTEXT_USERUNMANAGED */ lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* user product key exists */ labelsz = sizeof(label); promptsz = sizeof(prompt); r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyA(userkey, "SourceList", &source); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = 0xdeadbeef; lstrcpyA(prompt, "bbb"); promptsz = 0xdeadbeef; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz); res = RegCreateKeyA(source, "Media", &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* Media key exists */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = 0xdeadbeef; lstrcpyA(prompt, "bbb"); promptsz = 0xdeadbeef; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz); res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)"label;prompt", 13); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* disk exists */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); res = RegSetValueExA(media, "2", 0, REG_SZ, (LPBYTE)"one;two", 8); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* now disk 2 exists, get the sizes */ id = 0; labelsz = MAX_PATH; promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, &id, NULL, &labelsz, NULL, &promptsz); ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER, "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r); if (r == ERROR_SUCCESS) { ok(id == 2, "Expected 2, got %d\n", id); ok(labelsz == 3, "Expected 3, got %d\n", labelsz); ok(promptsz == 3, "Expected 3, got %d\n", promptsz); } /* now fill in the values */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER, "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r); if (r == ERROR_SUCCESS) { ok(id == 2, "Expected 2, got %d\n", id); ok(!lstrcmpA(label, "one"), "Expected \"one\", got \"%s\"\n", label); ok(labelsz == 3, "Expected 3, got %d\n", labelsz); ok(!lstrcmpA(prompt, "two"), "Expected \"two\", got \"%s\"\n", prompt); ok(promptsz == 3, "Expected 3, got %d\n", promptsz); } else if (r == ERROR_INVALID_PARAMETER) { ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz); } res = RegSetValueExA(media, "4", 0, REG_SZ, (LPBYTE)"three;four", 11); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* disks 1, 2, 4 exist, reset the enumeration */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); /* disks 1, 2, 4 exist, index 1 */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 2, "Expected 2, got %d\n", id); ok(!lstrcmpA(label, "one"), "Expected \"one\", got \"%s\"\n", label); ok(labelsz == 3, "Expected 3, got %d\n", labelsz); ok(!lstrcmpA(prompt, "two"), "Expected \"two\", got \"%s\"\n", prompt); ok(promptsz == 3, "Expected 3, got %d\n", promptsz); /* disks 1, 2, 4 exist, index 2 */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 2, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 4, "Expected 4, got %d\n", id); ok(!lstrcmpA(label, "three"), "Expected \"three\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "four"), "Expected \"four\", got \"%s\"\n", prompt); ok(promptsz == 4, "Expected 4, got %d\n", promptsz); /* disks 1, 2, 4 exist, index 3, invalid */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 3, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz); /* disks 1, 2, 4 exist, reset the enumeration */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); /* try index 0 again */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); /* jump to index 2 */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 2, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz); /* after error, try index 1 */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 2, "Expected 2, got %d\n", id); ok(!lstrcmpA(label, "one"), "Expected \"one\", got \"%s\"\n", label); ok(labelsz == 3, "Expected 3, got %d\n", labelsz); ok(!lstrcmpA(prompt, "two"), "Expected \"two\", got \"%s\"\n", prompt); ok(promptsz == 3, "Expected 3, got %d\n", promptsz); /* try index 1 again */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 1, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz); /* NULL pdwDiskId */ lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, NULL, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); /* szVolumeLabel is NULL */ id = 0; labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, NULL, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER, "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r); if (r == ERROR_SUCCESS) { ok(id == 1, "Expected 1, got %d\n", id); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); } /* szVolumeLabel and pcchVolumeLabel are NULL */ id = 0; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, NULL, NULL, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); /* szVolumeLabel is non-NULL while pcchVolumeLabel is NULL */ id = 0xbeef; lstrcpyA(label, "aaa"); lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, NULL, prompt, &promptsz); ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER, "Expected ERROR_SUCCESS or ERROR_INVALID_PARAMETER, got %d\n", r); if (r == ERROR_SUCCESS) { ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); } /* szDiskPrompt is NULL */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, NULL, &promptsz); ok(r == ERROR_SUCCESS || r == ERROR_INVALID_PARAMETER, "Expected ERROR_SUCCESS, got %d\n", r); if (r == ERROR_SUCCESS) { ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); } /* szDiskPrompt and pcchDiskPrompt are NULL */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, NULL, NULL); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); /* szDiskPrompt is non-NULL while pcchDiskPrompt is NULL */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); /* pcchVolumeLabel, szDiskPrompt and pcchDiskPrompt are NULL */ id = 0; lstrcpyA(label, "aaa"); r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, NULL, NULL, NULL); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(id == 1, "Expected 1, got %d\n", id); /* szVolumeLabel, pcchVolumeLabel, szDiskPrompt and pcchDiskPrompt are NULL */ id = 0; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, NULL, NULL, NULL, NULL); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); /* pcchVolumeLabel is exactly 5 */ lstrcpyA(label, "aaa"); labelsz = 5; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, NULL, label, &labelsz, prompt, &promptsz); ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); /* pcchDiskPrompt is exactly 6 */ lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = 6; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, NULL, label, &labelsz, prompt, &promptsz); ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)"label", 13); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* no semicolon */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "label"), "Expected \"label\", got \"%s\"\n", prompt); ok(promptsz == 5, "Expected 5, got %d\n", promptsz); res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)"label;", 13); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* semicolon, no disk prompt */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, ""), "Expected \"\", got \"%s\"\n", prompt); ok(promptsz == 0, "Expected 0, got %d\n", promptsz); res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)";prompt", 13); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* semicolon, label doesn't exist */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, ""), "Expected \"\", got \"%s\"\n", label); ok(labelsz == 0, "Expected 0, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); res = RegSetValueExA(media, "1", 0, REG_SZ, (LPBYTE)";", 13); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* semicolon, neither label nor disk prompt exist */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, ""), "Expected \"\", got \"%s\"\n", label); ok(labelsz == 0, "Expected 0, got %d\n", labelsz); ok(!lstrcmpA(prompt, ""), "Expected \"\", got \"%s\"\n", prompt); ok(promptsz == 0, "Expected 0, got %d\n", promptsz); val = 42; res = RegSetValueExA(media, "1", 0, REG_DWORD, (LPBYTE)&val, sizeof(DWORD)); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* type is REG_DWORD */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 1, "Expected 1, got %d\n", id); ok(!lstrcmpA(label, "#42"), "Expected \"#42\", got \"%s\"\n", label); ok(labelsz == 3, "Expected 3, got %d\n", labelsz); ok(!lstrcmpA(prompt, "#42"), "Expected \"#42\", got \"%s\"\n", prompt); ok(promptsz == 3, "Expected 3, got %d\n", promptsz); RegDeleteValueA(media, "1"); RegDeleteValueA(media, "2"); RegDeleteValueA(media, "4"); RegDeleteKeyA(media, ""); RegCloseKey(media); RegDeleteKeyA(source, ""); RegCloseKey(source); RegDeleteKeyA(userkey, ""); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_USERMANAGED */ lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); lstrcatA(keypath, usersid); lstrcatA(keypath, "\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); goto machine_tests; } /* user product key exists */ r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(userkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = 0xdeadbeef; lstrcpyA(prompt, "bbb"); promptsz = 0xdeadbeef; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz); res = RegCreateKeyExA(source, "Media", 0, NULL, 0, access, NULL, &media, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* Media key exists */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = 0xdeadbeef; lstrcpyA(prompt, "bbb"); promptsz = 0xdeadbeef; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz); res = RegSetValueExA(media, "2", 0, REG_SZ, (LPBYTE)"label;prompt", 13); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* disk exists, but no id 1 */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 2, "Expected 2, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); RegDeleteValueA(media, "2"); delete_key(media, "", access); RegCloseKey(media); delete_key(source, "", access); RegCloseKey(source); delete_key(userkey, "", access); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_MACHINE */ machine_tests: lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); LocalFree(usersid); return; } /* machine product key exists */ r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = 0xdeadbeef; lstrcpyA(prompt, "bbb"); promptsz = 0xdeadbeef; r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz); res = RegCreateKeyExA(source, "Media", 0, NULL, 0, access, NULL, &media, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* Media key exists */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = 0xdeadbeef; lstrcpyA(prompt, "bbb"); promptsz = 0xdeadbeef; r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", promptsz); res = RegSetValueExA(media, "2", 0, REG_SZ, (LPBYTE)"label;prompt", 13); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* disk exists, but no id 1 */ id = 0; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(id == 2, "Expected 2, got %d\n", id); ok(!lstrcmpA(label, "label"), "Expected \"label\", got \"%s\"\n", label); ok(labelsz == 5, "Expected 5, got %d\n", labelsz); ok(!lstrcmpA(prompt, "prompt"), "Expected \"prompt\", got \"%s\"\n", prompt); ok(promptsz == 6, "Expected 6, got %d\n", promptsz); /* szUserSid is non-NULL */ id = 0xbeef; lstrcpyA(label, "aaa"); labelsz = MAX_PATH; lstrcpyA(prompt, "bbb"); promptsz = MAX_PATH; r = pMsiSourceListEnumMediaDisksA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, MSICODE_PRODUCT, 0, &id, label, &labelsz, prompt, &promptsz); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); ok(id == 0xbeef, "Expected 0xbeef, got %d\n", id); ok(!lstrcmpA(label, "aaa"), "Expected \"aaa\", got \"%s\"\n", label); ok(labelsz == MAX_PATH, "Expected MAX_PATH, got %d\n", labelsz); ok(!lstrcmpA(prompt, "bbb"), "Expected \"bbb\", got \"%s\"\n", prompt); ok(promptsz == MAX_PATH, "Expected MAX_PATH, got %d\n", promptsz); RegDeleteValueA(media, "2"); delete_key(media, "", access); RegCloseKey(media); delete_key(source, "", access); RegCloseKey(source); delete_key(prodkey, "", access); RegCloseKey(prodkey); LocalFree(usersid); } static void test_MsiSourceListAddSource(void) { CHAR prodcode[MAX_PATH]; CHAR prod_squashed[MAX_PATH]; CHAR keypath[MAX_PATH*2]; CHAR username[MAX_PATH]; LPSTR usersid; LONG res; UINT r; HKEY prodkey, userkey, net, source; DWORD size; REGSAM access = KEY_ALL_ACCESS; if (!pMsiSourceListAddSourceA) { win_skip("Skipping MsiSourceListAddSourceA tests\n"); return; } if (is_process_limited()) { skip("process is limited\n"); return; } create_test_guid(prodcode, prod_squashed); if (!(usersid = get_user_sid())) { skip("User SID not available -> skipping MsiSourceListAddSourceA tests\n"); return; } /* MACHINENAME\username */ size = MAX_PATH; GetUserNameExA(NameSamCompatible, username, &size); trace("username: %s\n", username); if (is_wow64) access |= KEY_WOW64_64KEY; /* GetLastError is not set by the function */ /* NULL szProduct */ r = pMsiSourceListAddSourceA(NULL, username, 0, "source"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* empty szProduct */ r = pMsiSourceListAddSourceA("", username, 0, "source"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* garbage szProduct */ r = pMsiSourceListAddSourceA("garbage", username, 0, "source"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid without brackets */ r = pMsiSourceListAddSourceA("51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA", username, 0, "source"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* guid with brackets */ r = pMsiSourceListAddSourceA("{51CD2AD5-0482-4C46-8DDD-0ED1022AA1AA}", username, 0, "source"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); /* dwReserved is not 0 */ r = pMsiSourceListAddSourceA(prodcode, username, 42, "source"); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* szSource is NULL */ r = pMsiSourceListAddSourceA(prodcode, username, 0, NULL); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* szSource is empty */ r = pMsiSourceListAddSourceA(prodcode, username, 0, ""); ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* MSIINSTALLCONTEXT_USERMANAGED */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); lstrcatA(keypath, usersid); lstrcatA(keypath, "\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); goto userunmanaged_tests; } /* user product key exists */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(userkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Net key is created */ res = RegOpenKeyExA(source, "Net", 0, access, &net); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* LastUsedSource does not exist and it is not created */ res = RegQueryValueExA(source, "LastUsedSource", 0, NULL, NULL, NULL); ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); CHECK_REG_STR(net, "1", "source\\"); RegDeleteValueA(net, "1"); delete_key(net, "", access); RegCloseKey(net); res = RegSetValueExA(source, "LastUsedSource", 0, REG_SZ, (LPBYTE)"blah", 5); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* LastUsedSource value exists */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Net key is created */ res = RegOpenKeyExA(source, "Net", 0, access, &net); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(source, "LastUsedSource", "blah"); CHECK_REG_STR(net, "1", "source\\"); RegDeleteValueA(net, "1"); delete_key(net, "", access); RegCloseKey(net); res = RegSetValueExA(source, "LastUsedSource", 0, REG_SZ, (LPBYTE)"5", 2); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* LastUsedSource is an integer */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Net key is created */ res = RegOpenKeyExA(source, "Net", 0, access, &net); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(source, "LastUsedSource", "5"); CHECK_REG_STR(net, "1", "source\\"); /* Add a second source, has trailing backslash */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "another\\"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(source, "LastUsedSource", "5"); CHECK_REG_STR(net, "1", "source\\"); CHECK_REG_STR(net, "2", "another\\"); res = RegSetValueExA(source, "LastUsedSource", 0, REG_SZ, (LPBYTE)"2", 2); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* LastUsedSource is in the source list */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "third/"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(source, "LastUsedSource", "2"); CHECK_REG_STR(net, "1", "source\\"); CHECK_REG_STR(net, "2", "another\\"); CHECK_REG_STR(net, "3", "third/\\"); RegDeleteValueA(net, "1"); RegDeleteValueA(net, "2"); RegDeleteValueA(net, "3"); delete_key(net, "", access); RegCloseKey(net); delete_key(source, "", access); RegCloseKey(source); delete_key(userkey, "", access); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_USERUNMANAGED */ userunmanaged_tests: r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); goto machine_tests; } /* user product key exists */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyA(userkey, "SourceList", &source); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ r = pMsiSourceListAddSourceA(prodcode, username, 0, "source"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Net key is created */ res = RegOpenKeyA(source, "Net", &net); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(net, "1", "source\\"); RegDeleteValueA(net, "1"); RegDeleteKeyA(net, ""); RegCloseKey(net); RegDeleteKeyA(source, ""); RegCloseKey(source); RegDeleteKeyA(userkey, ""); RegCloseKey(userkey); /* MSIINSTALLCONTEXT_MACHINE */ machine_tests: r = pMsiSourceListAddSourceA(prodcode, NULL, 0, "source"); ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); if (res != ERROR_SUCCESS) { skip("Product key creation failed with error code %u\n", res); LocalFree(usersid); return; } /* machine product key exists */ r = pMsiSourceListAddSourceA(prodcode, NULL, 0, "source"); ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* SourceList key exists */ r = pMsiSourceListAddSourceA(prodcode, NULL, 0, "source"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); /* Net key is created */ res = RegOpenKeyExA(source, "Net", 0, access, &net); if (res == ERROR_ACCESS_DENIED) { skip("MsiSourceListAddSource (insufficient privileges)\n"); goto done; } ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_REG_STR(net, "1", "source\\"); /* empty szUserName */ r = pMsiSourceListAddSourceA(prodcode, "", 0, "another"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); CHECK_REG_STR(net, "1", "source\\"); CHECK_REG_STR(net, "2", "another\\"); RegDeleteValueA(net, "2"); RegDeleteValueA(net, "1"); delete_key(net, "", access); RegCloseKey(net); done: delete_key(source, "", access); RegCloseKey(source); delete_key(prodkey, "", access); RegCloseKey(prodkey); LocalFree(usersid); } START_TEST(source) { init_functionpointers(); if (pIsWow64Process) pIsWow64Process(GetCurrentProcess(), &is_wow64); test_MsiSourceListGetInfo(); test_MsiSourceListAddSourceEx(); test_MsiSourceListEnumSources(); test_MsiSourceListSetInfo(); test_MsiSourceListAddMediaDisk(); test_MsiSourceListEnumMediaDisks(); test_MsiSourceListAddSource(); }