Module: wine Branch: master Commit: b4b8bc830f7b9cb370f2d0e0c2ff04e4c70315d7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b4b8bc830f7b9cb370f2d0e0c2...
Author: Hans Leidekker hans@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);