Hans Leidekker : msi: Add a partial implementation of MsiProvideComponent.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Jan 21 15:16:21 CST 2015
Module: wine
Branch: master
Commit: a884d98e99d92d218f53de566f20f9879926e26d
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a884d98e99d92d218f53de566f20f9879926e26d
Author: Hans Leidekker <hans at 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)
More information about the wine-cvs
mailing list