Module: wine Branch: master Commit: a884d98e99d92d218f53de566f20f9879926e26d URL: http://source.winehq.org/git/wine.git/?a=commit;h=a884d98e99d92d218f53de566f...
Author: Hans Leidekker hans@codeweavers.com Date: Wed Jan 21 13:26:31 2015 +0100
msi: Add a partial implementation of MsiProvideComponent.
---
dlls/msi/msi.c | 86 +++++++++++++++++++++++++++++++++++++++++++ dlls/msi/msi.spec | 4 +- dlls/msi/tests/msi.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/msi.h | 4 ++ 4 files changed, 193 insertions(+), 2 deletions(-)
diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 6589ca9..afd92da 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -4198,6 +4198,92 @@ UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, return ERROR_SUCCESS; }
+UINT WINAPI MsiProvideComponentA( LPCSTR product, LPCSTR feature, LPCSTR component, DWORD mode, LPSTR buf, LPDWORD buflen ) +{ + WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL; + UINT r = ERROR_OUTOFMEMORY; + DWORD lenW; + int len; + + TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_a(product), debugstr_a(component), debugstr_a(feature), mode, buf, buflen); + + if (product && !(productW = strdupAtoW( product ))) goto done; + if (feature && !(featureW = strdupAtoW( feature ))) goto done; + if (component && !(componentW = strdupAtoW( component ))) goto done; + + r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW ); + if (r != ERROR_SUCCESS) + goto done; + + if (!(bufW = msi_alloc( ++lenW * sizeof(WCHAR) ))) + { + r = ERROR_OUTOFMEMORY; + goto done; + } + + r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW ); + if (r != ERROR_SUCCESS) + goto done; + + len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL ); + if (buf) + { + if (len > *buflen) + r = ERROR_MORE_DATA; + else + WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL ); + } + + *buflen = len - 1; + +done: + msi_free( productW ); + msi_free( featureW ); + msi_free( componentW ); + msi_free( bufW ); + return r; +} + +UINT WINAPI MsiProvideComponentW( LPCWSTR product, LPCWSTR feature, LPCWSTR component, DWORD mode, LPWSTR buf, LPDWORD buflen ) +{ + INSTALLSTATE state; + + TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_w(product), debugstr_w(component), debugstr_w(feature), mode, buf, buflen); + + state = MsiQueryFeatureStateW( product, feature ); + TRACE("feature state: %d\n", state); + switch (mode) + { + case INSTALLMODE_NODETECTION: + break; + + default: + FIXME("mode %x not implemented\n", mode); + return ERROR_INSTALL_FAILURE; + } + + state = MsiGetComponentPathW( product, component, buf, buflen ); + TRACE("component state: %d\n", state); + switch (state) + { + case INSTALLSTATE_INVALIDARG: + return ERROR_INVALID_PARAMETER; + + case INSTALLSTATE_MOREDATA: + return ERROR_MORE_DATA; + + case INSTALLSTATE_ADVERTISED: + case INSTALLSTATE_LOCAL: + case INSTALLSTATE_SOURCE: + MsiUseFeatureW( product, feature ); + return ERROR_SUCCESS; + + default: + TRACE("MsiGetComponentPathW returned %d\n", state); + return ERROR_INSTALL_FAILURE; + } +} + /*********************************************************************** * MsiBeginTransactionA [MSI.@] */ diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec index 2d065b1..4438721 100644 --- a/dlls/msi/msi.spec +++ b/dlls/msi/msi.spec @@ -97,10 +97,10 @@ 101 stub MsiProcessAdvertiseScriptA 102 stub MsiProcessAdvertiseScriptW 103 stdcall MsiProcessMessage(long long long) -104 stub MsiProvideComponentA +104 stdcall MsiProvideComponentA(str str str long ptr ptr) 105 stdcall MsiProvideComponentFromDescriptorA(str ptr ptr ptr) 106 stdcall MsiProvideComponentFromDescriptorW(wstr ptr ptr ptr) -107 stub MsiProvideComponentW +107 stdcall MsiProvideComponentW(wstr wstr wstr long ptr ptr) 108 stdcall MsiProvideQualifiedComponentA(str str long ptr ptr) 109 stdcall MsiProvideQualifiedComponentW(wstr wstr long ptr ptr) 110 stdcall MsiQueryFeatureStateA(str str) diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index c517fcf..3ae3901 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -50,6 +50,10 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static INSTALLSTATE (WINAPI *pMsiGetComponentPathA) (LPCSTR, LPCSTR, LPSTR, DWORD*); +static INSTALLSTATE (WINAPI *pMsiProvideComponentA) + (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD); +static INSTALLSTATE (WINAPI *pMsiProvideComponentW) + (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD); static UINT (WINAPI *pMsiGetFileHashA) (LPCSTR, DWORD, PMSIFILEHASHINFO); static UINT (WINAPI *pMsiGetProductInfoExA) @@ -88,6 +92,8 @@ static void init_functionpointers(void) trace("GetProcAddress(%s) failed\n", #func);
GET_PROC(hmsi, MsiGetComponentPathA) + GET_PROC(hmsi, MsiProvideComponentA) + GET_PROC(hmsi, MsiProvideComponentW) GET_PROC(hmsi, MsiGetFileHashA) GET_PROC(hmsi, MsiGetProductInfoExA) GET_PROC(hmsi, MsiOpenPackageExA) @@ -3404,6 +3410,100 @@ static void test_MsiGetComponentPath(void) LocalFree(usersid); }
+static void test_MsiProvideComponent(void) +{ + static const WCHAR sourcedirW[] = + {'s','o','u','r','c','e','d','i','r',0}; + static const WCHAR productW[] = + {'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-', + '8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0}; + static const WCHAR componentW[] = + {'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-', + 'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0}; + INSTALLSTATE state; + char buf[0x100]; + WCHAR bufW[0x100]; + DWORD len, len2; + UINT r; + + if (is_process_limited()) + { + skip("process is limited\n"); + return; + } + + create_test_files(); + create_file("msitest\sourcedir.txt", "msitest\sourcedir.txt", 1000); + create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + buf[0] = 0; + len = sizeof(buf); + r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}", + "{17961602-C4E2-482E-800A-DF6E627549CF}", + "ProductFiles", INSTALLMODE_NODETECTION, buf, &len); + ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir"); + ok(state == INSTALLSTATE_LOCAL, "got %d\n", state); + + buf[0] = 0; + len = sizeof(buf); + r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir", + "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", + INSTALLMODE_NODETECTION, buf, &len); + ok(r == ERROR_SUCCESS, "got %u\n", r); + ok(buf[0], "empty path\n"); + ok(len == lstrlenA(buf), "got %u\n", len); + + len2 = 0; + r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir", + "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", + INSTALLMODE_NODETECTION, NULL, &len2); + ok(r == ERROR_SUCCESS, "got %u\n", r); + ok(len2 == len, "got %u\n", len2); + + len2 = 0; + r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir", + "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", + INSTALLMODE_NODETECTION, buf, &len2); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(len2 == len, "got %u\n", len2); + + /* wide version */ + + bufW[0] = 0; + len = sizeof(buf); + r = pMsiProvideComponentW(productW, sourcedirW, componentW, + INSTALLMODE_NODETECTION, bufW, &len); + ok(r == ERROR_SUCCESS, "got %u\n", r); + ok(bufW[0], "empty path\n"); + ok(len == lstrlenW(bufW), "got %u\n", len); + + len2 = 0; + r = pMsiProvideComponentW(productW, sourcedirW, componentW, + INSTALLMODE_NODETECTION, NULL, &len2); + ok(r == ERROR_SUCCESS, "got %u\n", r); + ok(len2 == len, "got %u\n", len2); + + len2 = 0; + r = pMsiProvideComponentW(productW, sourcedirW, componentW, + INSTALLMODE_NODETECTION, bufW, &len2); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(len2 == len, "got %u\n", len2); + + r = MsiInstallProductA(msifile, "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "got %u\n", r); + + DeleteFileA("msitest\sourcedir.txt"); + delete_test_files(); + DeleteFileA(msifile); +} + static void test_MsiGetProductCode(void) { HKEY compkey, prodkey; @@ -14300,6 +14400,7 @@ START_TEST(msi) test_MsiQueryFeatureState(); test_MsiQueryComponentState(); test_MsiGetComponentPath(); + test_MsiProvideComponent(); test_MsiGetProductCode(); test_MsiEnumClients(); test_MsiGetProductInfo(); diff --git a/include/msi.h b/include/msi.h index 8d0dff2..033ed90 100644 --- a/include/msi.h +++ b/include/msi.h @@ -583,6 +583,10 @@ USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR, LPSTR, LPDWORD, LPSTR, LPDWORD, LPS USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPWSTR, LPDWORD); #define MsiGetUserInfo WINELIB_NAME_AW(MsiGetUserInfo)
+UINT WINAPI MsiProvidedComponentA(LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD); +UINT WINAPI MsiProvideComponentW(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD); +#define MsiProvideComponent WINELIB_NAME_AW(MsiProvideComponent) + UINT WINAPI MsiCollectUserInfoA(LPCSTR); UINT WINAPI MsiCollectUserInfoW(LPCWSTR); #define MsiCollectUserInfo WINELIB_NAME_AW(MsiCollectUserInfo)