diff --git a/dlls/msi/source.c b/dlls/msi/source.c index e44b3a17e91..44ab0c11630 100644 --- a/dlls/msi/source.c +++ b/dlls/msi/source.c @@ -524,6 +524,52 @@ UINT WINAPI MsiSourceListSetInfoA(LPCSTR szProduct, LPCSTR szUserSid, return ret; } +static UINT set_last_used_source(HKEY source, LPCWSTR product, LPCWSTR usersid, + MSIINSTALLCONTEXT context, DWORD options, + LPCWSTR value) +{ + LPWSTR buffer; + WCHAR typechar; + DWORD size; + UINT r; + int index = 0; + + static const WCHAR format[] = {'%','c',';','%','i',';','%','s',0}; + + if (options & MSISOURCETYPE_NETWORK) + typechar = 'n'; + else if (options & MSISOURCETYPE_URL) + typechar = 'u'; + else + return ERROR_INVALID_PARAMETER; + + /* make sure the source is registered */ + r = MsiSourceListAddSourceExW(product, usersid, context, + options, value, 0); + if (r != ERROR_SUCCESS) + return r; + + while ((r = MsiSourceListEnumSourcesW(product, usersid, context, options, + index, NULL, NULL)) == ERROR_SUCCESS) + index++; + + if (r != ERROR_NO_MORE_ITEMS) + return r; + + size = (lstrlenW(format) + lstrlenW(value) + 7) * sizeof(WCHAR); + buffer = msi_alloc(size); + if (!buffer) + return ERROR_OUTOFMEMORY; + + sprintfW(buffer, format, typechar, index, value); + + r = RegSetValueExW(source, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, + REG_SZ, (LPBYTE)buffer, size); + msi_free(buffer); + + return r; +} + /****************************************************************** * MsiSourceListSetInfoW (MSI.@) */ @@ -586,35 +632,6 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid, RegCloseKey(media); } } - else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0) - { - LPWSTR buffer = NULL; - DWORD size; - WCHAR typechar = 'n'; - static const WCHAR LastUsedSource_Fmt[] = {'%','c',';','%','i',';','%','s',0}; - - /* make sure the source is registered */ - MsiSourceListAddSourceExW(szProduct, szUserSid, dwContext, - dwOptions, szValue, 0); - - if (dwOptions & MSISOURCETYPE_NETWORK) - typechar = 'n'; - else if (dwOptions & MSISOURCETYPE_URL) - typechar = 'u'; - else if (dwOptions & MSISOURCETYPE_MEDIA) - typechar = 'm'; - else - ERR("Unknown source type! %x\n", dwOptions); - - size = (lstrlenW(szValue)+5)*sizeof(WCHAR); - buffer = msi_alloc(size); - sprintfW(buffer, LastUsedSource_Fmt, typechar, 1, szValue); - rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, - REG_EXPAND_SZ, (LPBYTE)buffer, size); - if (rc != ERROR_SUCCESS) - rc = ERROR_UNKNOWN_PROPERTY; - msi_free( buffer ); - } else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0) { DWORD size = lstrlenW(szValue)*sizeof(WCHAR); @@ -623,6 +640,9 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid, if (rc != ERROR_SUCCESS) rc = ERROR_UNKNOWN_PROPERTY; } + else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0) + rc = set_last_used_source(sourcekey, szProduct, szUserSid, dwContext, + dwOptions, szValue); else rc = ERROR_UNKNOWN_PROPERTY; diff --git a/dlls/msi/tests/source.c b/dlls/msi/tests/source.c index 8a275d27585..b48979547e7 100644 --- a/dlls/msi/tests/source.c +++ b/dlls/msi/tests/source.c @@ -1546,11 +1546,8 @@ static void test_MsiSourceListSetInfo(void) r = MsiSourceListSetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, "source"); - todo_wine - { - ok(r == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %d\n", r); - } + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_LASTUSEDSOURCE, MSISOURCETYPE_NETWORK */ r = MsiSourceListSetInfoA(prodcode, NULL, @@ -1563,6 +1560,7 @@ static void test_MsiSourceListSetInfo(void) 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 = MsiSourceListSetInfoA(prodcode, NULL, @@ -1570,7 +1568,9 @@ static void test_MsiSourceListSetInfo(void) MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, INSTALLPROPERTY_LASTUSEDSOURCE, "source/"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - CHECK_REG_STR(net, "1", "source\\") + 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 = MsiSourceListSetInfoA(prodcode, NULL, @@ -1583,6 +1583,7 @@ static void test_MsiSourceListSetInfo(void) 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 = MsiSourceListSetInfoA(prodcode, NULL, @@ -1591,6 +1592,16 @@ static void test_MsiSourceListSetInfo(void) INSTALLPROPERTY_LASTUSEDSOURCE, "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 = MsiSourceListSetInfoA(prodcode, NULL, + MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT | MSISOURCETYPE_MEDIA, + INSTALLPROPERTY_LASTUSEDSOURCE, "source"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); /* INSTALLPROPERTY_PACKAGENAME */ r = MsiSourceListSetInfoA(prodcode, NULL,