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