msi: implement FindRelatedProducts
Aric Stewart
aric at codeweavers.com
Wed Jun 8 13:53:10 CDT 2005
Add module upgrade.c
implement FindRelatedProducts
-------------- next part --------------
Index: include/msidefs.h
===================================================================
RCS file: /home/wine/wine/include/msidefs.h,v
retrieving revision 1.7
diff -u -r1.7 msidefs.h
--- include/msidefs.h 16 May 2005 21:37:35 -0000 1.7
+++ include/msidefs.h 8 Jun 2005 18:48:39 -0000
@@ -23,6 +23,15 @@
extern "C" {
#endif
+enum msidbUpgradeAttributes {
+ msidbUpgradeAttributesMigrateFeatures = 0x0000001,
+ msidbUpgradeAttributesOnlyDetect = 0x00000002,
+ msidbUpgradeAttributesIgnoreRemoveFailure = 0x00000004,
+ msidbUpgradeAttributesVersionMinInclusive = 0x00000100,
+ msidbUpgradeAttributesVersionMaxInclusive = 0x00000200,
+ msidbUpgradeAttributesLanguagesExclusive = 0x00000400
+};
+
enum msidbFileAttributes {
msidbFileAttributesReadOnly = 0x00000001,
msidbFileAttributesHidden = 0x00000002,
Index: dlls/msi/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/msi/Makefile.in,v
retrieving revision 1.27
diff -u -r1.27 Makefile.in
--- dlls/msi/Makefile.in 27 May 2005 09:11:18 -0000 1.27
+++ dlls/msi/Makefile.in 8 Jun 2005 18:48:39 -0000
@@ -34,6 +34,7 @@
table.c \
tokenize.c \
update.c \
+ upgrade.c \
where.c
RC_SRCS = msi.rc
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.138
diff -u -r1.138 action.c
--- dlls/msi/action.c 8 Jun 2005 18:34:04 -0000 1.138
+++ dlls/msi/action.c 8 Jun 2005 18:48:42 -0000
@@ -305,7 +305,7 @@
{ szDuplicateFiles, ACTION_DuplicateFiles },
{ szExecuteAction, ACTION_ExecuteAction },
{ szFileCost, ACTION_FileCost },
- { szFindRelatedProducts, NULL},
+ { szFindRelatedProducts, ACTION_FindRelatedProducts },
{ szForceReboot, ACTION_ForceReboot },
{ szInstallAdminPackage, NULL},
{ szInstallExecute, ACTION_InstallExecute },
@@ -571,6 +571,47 @@
return 0;
}
+DWORD build_version_dword(LPCWSTR version_string)
+{
+ SHORT major,minor;
+ WORD build;
+ DWORD rc = 0x00000000;
+ LPCWSTR ptr1;
+
+ ptr1 = version_string;
+
+ if (!ptr1)
+ return rc;
+ else
+ major = atoiW(ptr1);
+
+
+ if(ptr1)
+ ptr1 = strchrW(ptr1,'.');
+ if (ptr1)
+ {
+ ptr1++;
+ minor = atoiW(ptr1);
+ }
+ else
+ minor = 0;
+
+ if (ptr1)
+ ptr1 = strchrW(ptr1,'.');
+
+ if (ptr1)
+ {
+ ptr1++;
+ build = atoiW(ptr1);
+ }
+ else
+ build = 0;
+
+ rc = MAKELONG(build,MAKEWORD(minor,major));
+ TRACE("%s -> 0x%lx\n",debugstr_w(version_string),rc);
+ return rc;
+}
+
/* Called when the package is being closed */
void ACTION_free_package_structures( MSIPACKAGE* package)
{
Index: dlls/msi/action.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.h,v
retrieving revision 1.15
diff -u -r1.15 action.h
--- dlls/msi/action.h 7 Jun 2005 20:29:51 -0000 1.15
+++ dlls/msi/action.h 8 Jun 2005 18:48:42 -0000
@@ -192,6 +192,7 @@
LPWSTR *Actions[TOTAL_SCRIPTS];
UINT ActionCount[TOTAL_SCRIPTS];
BOOL ExecuteSequenceRun;
+ BOOL FindRelatedProductsRun;
BOOL CurrentlyScripting;
}MSISCRIPT;
@@ -202,6 +203,7 @@
UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute);
void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
UINT ACTION_AppSearch(MSIPACKAGE *package);
+UINT ACTION_FindRelatedProducts(MSIPACKAGE *package);
DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index);
@@ -222,3 +224,6 @@
LPCWSTR control, LPCWSTR attribute);
VOID ControlEvent_UnSubscribeToEvent( MSIPACKAGE *package, LPCWSTR event,
LPCWSTR control, LPCWSTR attribute );
+
+/* version stuff for upgrades */
+DWORD build_version_dword(LPCWSTR version_string);
--- /dev/null 2005-03-17 08:20:53.000000000 -0600
+++ dlls/msi/upgrade.c 2005-06-08 13:44:17.000000000 -0500
@@ -0,0 +1,235 @@
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2005 Aric Stewart for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Actions focused on in this module
+ *
+ * FindRelatedProducts
+ * MigrateFeatureStates (TODO)
+ * RemoveExistingProducts (TODO)
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "wine/debug.h"
+#include "msi.h"
+#include "msiquery.h"
+#include "msidefs.h"
+#include "msipriv.h"
+#include "winnls.h"
+#include "winuser.h"
+#include "winver.h"
+#include "action.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+static BOOL check_language(DWORD lang1, LPCWSTR lang2, DWORD attributes)
+{
+ DWORD langdword;
+
+ if (!lang2 || lang2[0]==0)
+ return TRUE;
+
+ langdword = atoiW(lang2);
+
+ if (attributes & msidbUpgradeAttributesLanguagesExclusive)
+ {
+ if (lang1 == langdword)
+ return FALSE;
+ else
+ return TRUE;
+ }
+
+ if (lang1 == langdword)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void append_productcode(MSIPACKAGE* package, LPCWSTR action_property,
+ LPCWSTR productid)
+{
+ LPWSTR prop;
+ LPWSTR newprop;
+ DWORD len;
+ static const WCHAR seperator[] = {';',0};
+
+ prop = load_dynamic_property(package, action_property, NULL);
+ if (prop)
+ len = strlenW(prop);
+ else
+ len = 0;
+
+ /*seperator*/
+ len ++;
+
+ len += strlenW(productid);
+
+ /*null*/
+ len++;
+
+ newprop = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
+
+ if (prop)
+ {
+ strcpyW(newprop,prop);
+ strcatW(newprop,seperator);
+ }
+ else
+ newprop[0] = 0;
+ strcatW(newprop,productid);
+
+ MSI_SetPropertyW(package, action_property, newprop);
+ TRACE("Found Related Product... %s now %s\n",debugstr_w(action_property),
+ debugstr_w(newprop));
+ HeapFree(GetProcessHeap(),0,prop);
+ HeapFree(GetProcessHeap(),0,newprop);
+}
+
+static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
+{
+ MSIPACKAGE *package = (MSIPACKAGE*)param;
+ WCHAR product[GUID_SIZE];
+ DWORD index = 0;
+ DWORD attributes = 0;
+ DWORD sz = GUID_SIZE;
+ LPCWSTR upgrade_code;
+ HKEY hkey = 0;
+ UINT rc = ERROR_SUCCESS;
+
+ upgrade_code = MSI_RecordGetString(rec,1);
+
+ rc = MSIREG_OpenUpgradeCodesKey(upgrade_code, &hkey, FALSE);
+ if (rc != ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+
+ attributes = MSI_RecordGetInteger(rec,5);
+
+ while (rc == ERROR_SUCCESS)
+ {
+ rc = RegEnumValueW(hkey, index, product, &sz, NULL, NULL, NULL, NULL);
+ TRACE("Looking at (%li) %s\n",index,debugstr_w(product));
+ if (rc == ERROR_SUCCESS)
+ {
+ WCHAR productid[GUID_SIZE];
+ LPCWSTR ver;
+ LPCWSTR language;
+ LPCWSTR action_property;;
+ DWORD check = 0x00000000;
+ DWORD comp_ver = 0x00000000;
+ DWORD sz = 0x100;
+ HKEY hukey;
+ INT r;
+ static const WCHAR szVersion[] =
+ {'V','e','r','s','i','o','n',0};
+ static const WCHAR szLanguage[] =
+ {'L','a','n','g','u','a','g','e',0};
+
+ unsquash_guid(product,productid);
+ rc = MSIREG_OpenUserProductsKey(productid, &hukey, FALSE);
+ if (rc != ERROR_SUCCESS)
+ {
+ rc = ERROR_SUCCESS;
+ index ++;
+ continue;
+ }
+
+ sz = sizeof(DWORD);
+ RegQueryValueExW(hukey, szVersion, NULL, NULL, (LPBYTE)&check,
+ &sz);
+ /* check min */
+ ver = MSI_RecordGetString(rec,2);
+ comp_ver = build_version_dword(ver);
+ r = check - comp_ver;
+ if (r < 0 || (r == 0 && !(attributes &
+ msidbUpgradeAttributesVersionMinInclusive)))
+ {
+ RegCloseKey(hukey);
+ index ++;
+ continue;
+ }
+
+ /* check max */
+ ver = MSI_RecordGetString(rec,3);
+ comp_ver = build_version_dword(ver);
+ r = check - comp_ver;
+ if (r > 0 || (r == 0 && !(attributes &
+ msidbUpgradeAttributesVersionMaxInclusive)))
+ {
+ RegCloseKey(hukey);
+ index ++;
+ continue;
+ }
+
+ /* check language*/
+ sz = sizeof(DWORD);
+ RegQueryValueExW(hukey, szLanguage, NULL, NULL, (LPBYTE)&check,
+ &sz);
+ RegCloseKey(hukey);
+ language = MSI_RecordGetString(rec,4);
+ TRACE("Checking languages 0x%lx and %s\n", check,
+ debugstr_w(language));
+ if (!check_language(check, language, attributes))
+ {
+ index ++;
+ continue;
+ }
+
+ action_property = MSI_RecordGetString(rec,7);
+ append_productcode(package,action_property,productid);
+ }
+ index ++;
+ }
+ RegCloseKey(hkey);
+
+ return ERROR_SUCCESS;
+}
+
+UINT ACTION_FindRelatedProducts(MSIPACKAGE *package)
+{
+ static const WCHAR Query[] =
+ {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',
+ ' ','`','U','p','g','r','a','d','e','`',0};
+ UINT rc = ERROR_SUCCESS;
+ MSIQUERY *view;
+
+ if (package->script && package->script->FindRelatedProductsRun)
+ return ERROR_SUCCESS;
+
+ if (package->script)
+ package->script->FindRelatedProductsRun = TRUE;
+
+ rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+ if (rc != ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+
+ rc = MSI_IterateRecords(view, NULL, ITERATE_FindRelatedProducts, package);
+ msiobj_release(&view->hdr);
+
+ return rc;
+}
More information about the wine-patches
mailing list