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