msi: Implement MsiApplyMultiplePatchesA/W.
This commit is contained in:
parent
dd16b91a87
commit
b4b8bc830f
158
dlls/msi/msi.c
158
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,42 +315,37 @@ 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 = 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
product_code = codes;
|
||||
}
|
||||
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue