Commit b4b8bc83 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Implement MsiApplyMultiplePatchesA/W.

parent dd16b91a
......@@ -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)
{
......
......@@ -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)
......
......@@ -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();
}
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment