James Hawkins : msi: Implement MsiApplyPatchW.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Jun 18 08:05:00 CDT 2007
Module: wine
Branch: master
Commit: d8860d34e4008299320a0cbd0aea033b608a1395
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d8860d34e4008299320a0cbd0aea033b608a1395
Author: James Hawkins <truiken at gmail.com>
Date: Fri Jun 15 14:08:37 2007 -0700
msi: Implement MsiApplyPatchW.
---
dlls/msi/msi.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
include/msi.h | 3 +-
2 files changed, 85 insertions(+), 3 deletions(-)
diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index ad9c5b4..59a6f67 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -30,6 +30,7 @@
#include "shlwapi.h"
#include "wine/debug.h"
#include "msi.h"
+#include "msidefs.h"
#include "msiquery.h"
#include "msipriv.h"
#include "wincrypt.h"
@@ -256,9 +257,89 @@ done:
UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
{
- FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
+ MSIHANDLE patch, info;
+ UINT r, type;
+ DWORD size = 0;
+ LPCWSTR cmd_ptr = szCommandLine;
+ LPWSTR beg, end;
+ LPWSTR cmd = NULL, codes = NULL;
+
+ static const WCHAR space[] = {' ',0};
+ 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));
- return ERROR_CALL_NOT_IMPLEMENTED;
+
+ if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
+ eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
+ {
+ 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;
+
+ if (!szCommandLine)
+ cmd_ptr = empty;
+
+ size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
+ cmd = msi_alloc(size * sizeof(WCHAR));
+ if (!cmd)
+ {
+ r = ERROR_OUTOFMEMORY;
+ goto done;
+ }
+
+ lstrcpyW(cmd, cmd_ptr);
+ if (szCommandLine) lstrcatW(cmd, space);
+ lstrcatW(cmd, patcheq);
+ lstrcatW(cmd, szPatchPackage);
+
+ beg = codes;
+ while ((end = strchrW(beg, '}')))
+ {
+ *(end + 1) = '\0';
+
+ r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ beg = end + 2;
+ }
+
+done:
+ msi_free(cmd);
+ msi_free(codes);
+
+ MsiCloseHandle(info);
+ MsiCloseHandle(patch);
+
+ return r;
}
UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
diff --git a/include/msi.h b/include/msi.h
index 28b9c51..3fb214b 100644
--- a/include/msi.h
+++ b/include/msi.h
@@ -167,7 +167,8 @@ typedef enum tagSCRIPTFLAGS
typedef enum tagINSTALLTYPE
{
INSTALLTYPE_DEFAULT = 0,
- INSTALLTYPE_NETWORK_IMAGE = 1
+ INSTALLTYPE_NETWORK_IMAGE = 1,
+ INSTALLTYPE_SINGLE_INSTANCE = 2,
} INSTALLTYPE;
typedef enum tagMSIINSTALLCONTEXT
More information about the wine-cvs
mailing list