From 65f99ed91be2afc988e912b20491a21c092a71c8 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Wed, 12 Mar 2008 18:31:06 -0500 Subject: [PATCH] msi: Test and fix MsiSourceListAddSource. --- dlls/msi/source.c | 46 +++++++-- dlls/msi/tests/source.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+), 7 deletions(-) diff --git a/dlls/msi/source.c b/dlls/msi/source.c index 36fcc80322a..1d90ad82b4f 100644 --- a/dlls/msi/source.c +++ b/dlls/msi/source.c @@ -850,25 +850,57 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid, UINT WINAPI MsiSourceListAddSourceW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD dwReserved, LPCWSTR szSource) { + WCHAR squished_pc[GUID_SIZE]; INT ret; LPWSTR sidstr = NULL; DWORD sidsize = 0; DWORD domsize = 0; + DWORD context; + HKEY hkey = 0; + UINT r; TRACE("%s %s %s\n", debugstr_w(szProduct), debugstr_w(szUserName), debugstr_w(szSource)); - if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, &domsize, NULL)) + if (!szSource || !*szSource) + return ERROR_INVALID_PARAMETER; + + if (dwReserved != 0) + return ERROR_INVALID_PARAMETER; + + if (!szProduct || !squash_guid(szProduct, squished_pc)) + return ERROR_INVALID_PARAMETER; + + if (!szUserName || !*szUserName) + context = MSIINSTALLCONTEXT_MACHINE; + else { - PSID psid = msi_alloc(sidsize); + if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, &domsize, NULL)) + { + PSID psid = msi_alloc(sidsize); + + if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, &domsize, NULL)) + ConvertSidToStringSidW(psid, &sidstr); + + msi_free(psid); + } - if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, &domsize, NULL)) - ConvertSidToStringSidW(psid, &sidstr); + r = MSIREG_OpenLocalManagedProductKey(szProduct, &hkey, FALSE); + if (r == ERROR_SUCCESS) + context = MSIINSTALLCONTEXT_USERMANAGED; + else + { + r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE); + if (r != ERROR_SUCCESS) + return ERROR_UNKNOWN_PRODUCT; + + context = MSIINSTALLCONTEXT_USERUNMANAGED; + } - msi_free(psid); + RegCloseKey(hkey); } ret = MsiSourceListAddSourceExW(szProduct, sidstr, - MSIINSTALLCONTEXT_USERMANAGED, MSISOURCETYPE_NETWORK, szSource, 0); + context, MSISOURCETYPE_NETWORK, szSource, 0); if (sidstr) LocalFree(sidstr); @@ -891,7 +923,7 @@ UINT WINAPI MsiSourceListAddSourceA( LPCSTR szProduct, LPCSTR szUserName, szwusername = strdupAtoW( szUserName ); szwsource = strdupAtoW( szSource ); - ret = MsiSourceListAddSourceW(szwproduct, szwusername, 0, szwsource); + ret = MsiSourceListAddSourceW(szwproduct, szwusername, dwReserved, szwsource); msi_free(szwproduct); msi_free(szwusername); diff --git a/dlls/msi/tests/source.c b/dlls/msi/tests/source.c index ab8e8c7accd..49e40c7326c 100644 --- a/dlls/msi/tests/source.c +++ b/dlls/msi/tests/source.c @@ -44,6 +44,8 @@ static UINT (WINAPI *pMsiSourceListGetInfoA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD); static UINT (WINAPI *pMsiSourceListSetInfoA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD,LPCSTR, LPCSTR); +static UINT (WINAPI *pMsiSourceListAddSourceA) + (LPCSTR, LPCSTR, DWORD, LPCSTR); static void init_functionpointers(void) { @@ -61,6 +63,7 @@ static void init_functionpointers(void) GET_PROC(hmsi, MsiSourceListEnumSourcesA) GET_PROC(hmsi, MsiSourceListGetInfoA) GET_PROC(hmsi, MsiSourceListSetInfoA) + GET_PROC(hmsi, MsiSourceListAddSourceA) GET_PROC(hadvapi32, ConvertSidToStringSidA) @@ -3015,6 +3018,251 @@ static void test_MsiSourceListEnumMediaDisks(void) RegCloseKey(prodkey); } +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, ptr; + LONG res; + UINT r; + HKEY prodkey, userkey; + HKEY net, source; + DWORD size; + + if (!pMsiSourceListAddSourceA) + { + skip("Skipping MsiSourceListAddSourceA tests\n"); + return; + } + + create_test_guid(prodcode, prod_squashed); + get_user_sid(&usersid); + + /* MACHINENAME\username */ + size = MAX_PATH; + GetComputerNameA(username, &size); + lstrcatA(username, "\\"); + ptr = username + lstrlenA(username); + size = MAX_PATH; + GetUserNameA(ptr, &size); + + /* 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 = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* 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); + + /* 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"); + RegDeleteKeyA(net, ""); + 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 = RegOpenKeyA(source, "Net", &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"); + RegDeleteKeyA(net, ""); + 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 = RegOpenKeyA(source, "Net", &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"); + RegDeleteKeyA(net, ""); + RegCloseKey(net); + RegDeleteKeyA(source, ""); + RegCloseKey(source); + RegDeleteKeyA(userkey, ""); + RegCloseKey(userkey); + + /* MSIINSTALLCONTEXT_USERUNMANAGED */ + + 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); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* 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 */ + + 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 = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* machine product key exists */ + r = pMsiSourceListAddSourceA(prodcode, NULL, 0, "source"); + ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r); + + res = RegCreateKeyA(prodkey, "SourceList", &source); + 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 = RegOpenKeyA(source, "Net", &net); + 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"); + RegDeleteKeyA(net, ""); + RegCloseKey(net); + RegDeleteKeyA(source, ""); + RegCloseKey(source); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); +} + START_TEST(source) { init_functionpointers(); @@ -3025,4 +3273,5 @@ START_TEST(source) test_MsiSourceListSetInfo(); test_MsiSourceListAddMediaDisk(); test_MsiSourceListEnumMediaDisks(); + test_MsiSourceListAddSource(); } -- 2.11.4.GIT