Hans Leidekker : msi: Implement MsiApplyMultiplePatchesA/W.

Alexandre Julliard julliard at winehq.org
Fri May 1 09:33:21 CDT 2009


Module: wine
Branch: master
Commit: b4b8bc830f7b9cb370f2d0e0c2ff04e4c70315d7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b4b8bc830f7b9cb370f2d0e0c2ff04e4c70315d7

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri May  1 15:06:53 2009 +0200

msi: Implement MsiApplyMultiplePatchesA/W.

---

 dlls/msi/msi.c           |  150 ++++++++++++++++++++++++++++++++++++----------
 dlls/msi/msi.spec        |    4 +-
 dlls/msi/tests/package.c |   33 ++++++++++
 include/msi.h            |    4 +
 4 files changed, 158 insertions(+), 33 deletions(-)

diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index bee45b0..43436bd 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -301,13 +301,13 @@ done:
     return r;
 }
 
-UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
-         INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
+static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
 {
     MSIHANDLE patch, info;
     UINT r, type;
     DWORD size = 0;
     LPCWSTR cmd_ptr = szCommandLine;
+    LPCWSTR product_code = szProductCode;
     LPWSTR beg, end;
     LPWSTR cmd = NULL, codes = NULL;
 
@@ -315,41 +315,36 @@ UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
     static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
     static WCHAR empty[] = {0};
 
-    TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
-          eInstallType, debugstr_w(szCommandLine));
-
-    if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
-        eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
+    if (!szProductCode)
     {
-        FIXME("Only reading target products from patch\n");
-        return ERROR_CALL_NOT_IMPLEMENTED;
-    }
+        r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
+        if (r != ERROR_SUCCESS)
+            return r;
 
-    r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
-    if (r != ERROR_SUCCESS)
-        return r;
+        r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
+        if (r != ERROR_SUCCESS)
+            goto done;
 
-    r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
-    if (r != ERROR_SUCCESS)
-        goto done;
+        r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
+        if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
+        {
+            ERR("Failed to read product codes from patch\n");
+            goto done;
+        }
 
-    r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
-    if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
-    {
-        ERR("Failed to read product codes from patch\n");
-        goto done;
-    }
+        codes = msi_alloc(++size * sizeof(WCHAR));
+        if (!codes)
+        {
+            r = ERROR_OUTOFMEMORY;
+            goto done;
+        }
 
-    codes = msi_alloc(++size * sizeof(WCHAR));
-    if (!codes)
-    {
-        r = ERROR_OUTOFMEMORY;
-        goto done;
-    }
+        r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
+        if (r != ERROR_SUCCESS)
+            goto done;
 
-    r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
-    if (r != ERROR_SUCCESS)
-        goto done;
+        product_code = codes;
+    }
 
     if (!szCommandLine)
         cmd_ptr = empty;
@@ -389,6 +384,99 @@ done:
     return r;
 }
 
+UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
+         INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
+{
+    TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
+          eInstallType, debugstr_w(szCommandLine));
+
+    if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
+        eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
+    {
+        FIXME("Only reading target products from patch\n");
+        return ERROR_CALL_NOT_IMPLEMENTED;
+    }
+
+    return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine);
+}
+
+UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,
+        LPCSTR szProductCode, LPCSTR szPropertiesList)
+{
+    LPWSTR patch_packages = NULL;
+    LPWSTR product_code = NULL;
+    LPWSTR properties_list = NULL;
+    UINT r = ERROR_OUTOFMEMORY;
+
+    TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode),
+          debugstr_a(szPropertiesList));
+
+    if (!szPatchPackages || !szPatchPackages[0])
+        return ERROR_INVALID_PARAMETER;
+
+    if (!(patch_packages = strdupAtoW(szPatchPackages)))
+        return ERROR_OUTOFMEMORY;
+
+    if (szProductCode && !(product_code = strdupAtoW(szProductCode)))
+        goto done;
+
+    if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList)))
+        goto done;
+
+    r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list);
+
+done:
+    msi_free(patch_packages);
+    msi_free(product_code);
+    msi_free(properties_list);
+
+    return r;
+}
+
+UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,
+        LPCWSTR szProductCode, LPCWSTR szPropertiesList)
+{
+    UINT r = ERROR_SUCCESS;
+    LPCWSTR beg, end;
+
+    TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode),
+          debugstr_w(szPropertiesList));
+
+    if (!szPatchPackages || !szPatchPackages[0])
+        return ERROR_INVALID_PARAMETER;
+
+    beg = end = szPatchPackages;
+    while (*beg)
+    {
+        DWORD len;
+        LPWSTR patch;
+
+        while (*beg == ' ') beg++;
+        while (*end && *end != ';') end++;
+
+        len = end - beg;
+        while (len && beg[len - 1] == ' ') len--;
+
+        if (!len) return ERROR_INVALID_NAME;
+
+        patch = msi_alloc((len + 1) * sizeof(WCHAR));
+        if (!patch)
+            return ERROR_OUTOFMEMORY;
+
+        memcpy(patch, beg, len * sizeof(WCHAR));
+        patch[len] = '\0';
+
+        r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList);
+        msi_free(patch);
+
+        if (r != ERROR_SUCCESS)
+            break;
+
+        beg = ++end;
+    }
+    return r;
+}
+
 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
         DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
 {
diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec
index 14178e8..1475028 100644
--- a/dlls/msi/msi.spec
+++ b/dlls/msi/msi.spec
@@ -232,8 +232,8 @@
 236 stub Migrate10CachedPackagesW
 237 stub MsiRemovePatchesA
 238 stub MsiRemovePatchesW
-239 stub MsiApplyMultiplePatchesA
-240 stub MsiApplyMultiplePatchesW
+239 stdcall MsiApplyMultiplePatchesA(str str str)
+240 stdcall MsiApplyMultiplePatchesW(wstr wstr wstr)
 241 stub MsiExtractPatchXMLDataA
 242 stub MsiExtractPatchXMLDataW
 243 stdcall MsiGetPatchInfoExA(str str str long str ptr ptr)
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c
index ccc9208..35a22de 100644
--- a/dlls/msi/tests/package.c
+++ b/dlls/msi/tests/package.c
@@ -11533,6 +11533,38 @@ static void test_MsiSetProperty(void)
     DeleteFileA(msifile);
 }
 
+static void test_MsiApplyMultiplePatches(void)
+{
+    UINT r;
+
+    r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
+    ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA("", NULL, NULL);
+    ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA(";", NULL, NULL);
+    ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
+    ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
+    ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
+    todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
+    ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
+    todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
+
+    r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
+    todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
+}
+
 START_TEST(package)
 {
     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
@@ -11566,4 +11598,5 @@ START_TEST(package)
     test_emptypackage();
     test_MsiGetProductProperty();
     test_MsiSetProperty();
+    test_MsiApplyMultiplePatches();
 }
diff --git a/include/msi.h b/include/msi.h
index a6a5f3d..5e68fdc 100644
--- a/include/msi.h
+++ b/include/msi.h
@@ -649,6 +649,10 @@ UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR, DWORD, PMSIPATCHSEQUENCEINFOA
 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR, DWORD, PMSIPATCHSEQUENCEINFOW);
 #define     MsiDetermineApplicablePatches WINELIB_NAME_AW(MsiDetermineApplicablePatches)
 
+UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR, LPCSTR, LPCSTR);
+UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR, LPCWSTR, LPCWSTR);
+#define     MsiApplyMultiplePatches WINELIB_NAME_AW(MsiApplyMultiplePatches)
+
 /* Non Unicode */
 UINT WINAPI MsiCloseHandle(MSIHANDLE);
 UINT WINAPI MsiCloseAllHandles(void);




More information about the wine-cvs mailing list