James Hawkins : msi: Do not reinstall an assembly that already exists in the global assembly cache .
Alexandre Julliard
julliard at winehq.org
Wed Oct 29 09:39:18 CDT 2008
Module: wine
Branch: master
Commit: 019f4af1c231aecbc4d141afea6758270ce6f884
URL: http://source.winehq.org/git/wine.git/?a=commit;h=019f4af1c231aecbc4d141afea6758270ce6f884
Author: James Hawkins <jhawkins at codeweavers.com>
Date: Wed Oct 29 03:18:14 2008 -0500
msi: Do not reinstall an assembly that already exists in the global assembly cache.
---
dlls/msi/action.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 145 insertions(+), 6 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 37a7de3..707bc75 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -5771,9 +5771,6 @@ static UINT install_assembly(MSIPACKAGE *package, MSIASSEMBLY *assembly,
return ERROR_SUCCESS;
}
- if (!init_functionpointers() || !pCreateAssemblyCache)
- return ERROR_FUNCTION_FAILED;
-
hr = pCreateAssemblyCache(&cache, 0);
if (FAILED(hr))
goto done;
@@ -5792,9 +5789,138 @@ done:
typedef struct tagASSEMBLY_LIST
{
MSIPACKAGE *package;
+ IAssemblyCache *cache;
struct list *assemblies;
} ASSEMBLY_LIST;
+typedef struct tagASSEMBLY_NAME
+{
+ LPWSTR name;
+ LPWSTR version;
+ LPWSTR culture;
+ LPWSTR pubkeytoken;
+} ASSEMBLY_NAME;
+
+static UINT parse_assembly_name(MSIRECORD *rec, LPVOID param)
+{
+ ASSEMBLY_NAME *asmname = (ASSEMBLY_NAME *)param;
+ LPCWSTR name = MSI_RecordGetString(rec, 2);
+ LPWSTR val = msi_dup_record_field(rec, 3);
+
+ static const WCHAR Name[] = {'N','a','m','e',0};
+ static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
+ static const WCHAR Culture[] = {'C','u','l','t','u','r','e',0};
+ static const WCHAR PublicKeyToken[] = {
+ 'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
+
+ if (!lstrcmpW(name, Name))
+ asmname->name = val;
+ else if (!lstrcmpW(name, Version))
+ asmname->version = val;
+ else if (!lstrcmpW(name, Culture))
+ asmname->culture = val;
+ else if (!lstrcmpW(name, PublicKeyToken))
+ asmname->pubkeytoken = val;
+ else
+ msi_free(val);
+
+ return ERROR_SUCCESS;
+}
+
+static void append_str(LPWSTR *str, DWORD *size, LPCWSTR append)
+{
+ if (!*str)
+ {
+ *size = lstrlenW(append) + 1;
+ *str = msi_alloc((*size) * sizeof(WCHAR));
+ lstrcpyW(*str, append);
+ return;
+ }
+
+ (*size) += lstrlenW(append);
+ *str = msi_realloc(*str, (*size) * sizeof(WCHAR));
+ lstrcatW(*str, append);
+}
+
+static BOOL check_assembly_installed(MSIDATABASE *db, IAssemblyCache *cache,
+ MSICOMPONENT *comp)
+{
+ ASSEMBLY_INFO asminfo;
+ ASSEMBLY_NAME name;
+ MSIQUERY *view;
+ LPWSTR disp;
+ DWORD size;
+ BOOL found;
+ UINT r;
+
+ static const WCHAR separator[] = {',',' ',0};
+ static const WCHAR Version[] = {'V','e','r','s','i','o','n','=',0};
+ static const WCHAR Culture[] = {'C','u','l','t','u','r','e','=',0};
+ static const WCHAR PublicKeyToken[] = {
+ 'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
+ static const WCHAR query[] = {
+ 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+ '`','M','s','i','A','s','s','e','m','b','l','y','N','a','m','e','`',' ',
+ 'W','H','E','R','E',' ','`','C','o','m','p','o','n','e','n','t','_','`',
+ '=','\'','%','s','\'',0};
+
+ disp = NULL;
+ found = FALSE;
+ ZeroMemory(&name, sizeof(ASSEMBLY_NAME));
+ ZeroMemory(&asminfo, sizeof(ASSEMBLY_INFO));
+
+ r = MSI_OpenQuery(db, &view, query, comp->Component);
+ if (r != ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+
+ MSI_IterateRecords(view, NULL, parse_assembly_name, &name);
+ msiobj_release(&view->hdr);
+
+ if (!name.name)
+ {
+ ERR("No assembly name specified!\n");
+ goto done;
+ }
+
+ append_str(&disp, &size, name.name);
+
+ if (name.version)
+ {
+ append_str(&disp, &size, separator);
+ append_str(&disp, &size, Version);
+ append_str(&disp, &size, name.version);
+ }
+
+ if (name.culture)
+ {
+ append_str(&disp, &size, separator);
+ append_str(&disp, &size, Culture);
+ append_str(&disp, &size, name.culture);
+ }
+
+ if (name.pubkeytoken)
+ {
+ append_str(&disp, &size, separator);
+ append_str(&disp, &size, PublicKeyToken);
+ append_str(&disp, &size, name.pubkeytoken);
+ }
+
+ asminfo.cbAssemblyInfo = sizeof(ASSEMBLY_INFO);
+ IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
+ disp, &asminfo);
+ found = (asminfo.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
+
+done:
+ msiobj_release(&view->hdr);
+ msi_free(disp);
+ msi_free(name.name);
+ msi_free(name.version);
+ msi_free(name.culture);
+ msi_free(name.pubkeytoken);
+
+ return found;
+}
+
static UINT load_assembly(MSIRECORD *rec, LPVOID param)
{
ASSEMBLY_LIST *list = (ASSEMBLY_LIST *)param;
@@ -5826,17 +5952,20 @@ static UINT load_assembly(MSIRECORD *rec, LPVOID param)
assembly->manifest = strdupW(MSI_RecordGetString(rec, 3));
assembly->application = strdupW(MSI_RecordGetString(rec, 4));
assembly->attributes = MSI_RecordGetInteger(rec, 5);
- assembly->installed = FALSE;
+ assembly->installed = check_assembly_installed(list->package->db,
+ list->cache,
+ assembly->component);
list_add_head(list->assemblies, &assembly->entry);
-
return ERROR_SUCCESS;
}
static UINT load_assemblies(MSIPACKAGE *package, struct list *assemblies)
{
- MSIQUERY *view;
+ IAssemblyCache *cache = NULL;
ASSEMBLY_LIST list;
+ MSIQUERY *view;
+ HRESULT hr;
UINT r;
static const WCHAR query[] =
@@ -5847,12 +5976,19 @@ static UINT load_assemblies(MSIPACKAGE *package, struct list *assemblies)
if (r != ERROR_SUCCESS)
return ERROR_SUCCESS;
+ hr = pCreateAssemblyCache(&cache, 0);
+ if (FAILED(hr))
+ return ERROR_FUNCTION_FAILED;
+
list.package = package;
+ list.cache = cache;
list.assemblies = assemblies;
r = MSI_IterateRecords(view, NULL, load_assembly, &list);
msiobj_release(&view->hdr);
+ IAssemblyCache_Release(cache);
+
return r;
}
@@ -5929,6 +6065,9 @@ static UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
MSIASSEMBLY *assembly;
MSIMEDIAINFO *mi;
+ if (!init_functionpointers() || !pCreateAssemblyCache)
+ return ERROR_FUNCTION_FAILED;
+
r = load_assemblies(package, &assemblies);
if (r != ERROR_SUCCESS)
goto done;
More information about the wine-cvs
mailing list