ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

assembly.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2010 Hans Leidekker for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 
00025 #include "windef.h"
00026 #include "winbase.h"
00027 #include "winreg.h"
00028 #include "wine/debug.h"
00029 #include "wine/unicode.h"
00030 #include "msipriv.h"
00031 
00032 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00033 
00034 static HRESULT (WINAPI *pCreateAssemblyCacheNet10)( IAssemblyCache **, DWORD );
00035 static HRESULT (WINAPI *pCreateAssemblyCacheNet11)( IAssemblyCache **, DWORD );
00036 static HRESULT (WINAPI *pCreateAssemblyCacheNet20)( IAssemblyCache **, DWORD );
00037 static HRESULT (WINAPI *pCreateAssemblyCacheSxs)( IAssemblyCache **, DWORD );
00038 static HRESULT (WINAPI *pLoadLibraryShim)( LPCWSTR, LPCWSTR, LPVOID, HMODULE * );
00039 static HRESULT (WINAPI *pGetFileVersion)( LPCWSTR, LPWSTR, DWORD, DWORD * );
00040 
00041 static HMODULE hfusion10, hfusion11, hfusion20, hmscoree, hsxs;
00042 
00043 static BOOL init_function_pointers( void )
00044 {
00045     static const WCHAR szFusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
00046     static const WCHAR szVersion10[] = {'v','1','.','0','.','3','7','0','5',0};
00047     static const WCHAR szVersion11[] = {'v','1','.','1','.','4','3','2','2',0};
00048     static const WCHAR szVersion20[] = {'v','2','.','0','.','5','0','7','2','7',0};
00049 
00050     if (pCreateAssemblyCacheNet10 || pCreateAssemblyCacheNet11 || pCreateAssemblyCacheNet20) return TRUE;
00051 
00052     if (!(hmscoree = LoadLibraryA( "mscoree.dll" ))) return FALSE;
00053     pGetFileVersion = (void *)GetProcAddress( hmscoree, "GetFileVersion" ); /* missing from v1.0.3705 */
00054     if (!(pLoadLibraryShim = (void *)GetProcAddress( hmscoree, "LoadLibraryShim" ))) goto error;
00055 
00056     if (!pLoadLibraryShim( szFusion, szVersion10, NULL, &hfusion10 ))
00057         pCreateAssemblyCacheNet10 = (void *)GetProcAddress( hfusion10, "CreateAssemblyCache" );
00058 
00059     if (!pLoadLibraryShim( szFusion, szVersion11, NULL, &hfusion11 ))
00060         pCreateAssemblyCacheNet11 = (void *)GetProcAddress( hfusion11, "CreateAssemblyCache" );
00061 
00062     if (!pLoadLibraryShim( szFusion, szVersion20, NULL, &hfusion20 ))
00063         pCreateAssemblyCacheNet20 = (void *)GetProcAddress( hfusion20, "CreateAssemblyCache" );
00064 
00065     if (!pCreateAssemblyCacheNet10 && !pCreateAssemblyCacheNet11 && !pCreateAssemblyCacheNet20) goto error;
00066 
00067     if (!(hsxs = LoadLibraryA( "sxs.dll" ))) goto error;
00068     if (!(pCreateAssemblyCacheSxs = (void *)GetProcAddress( hsxs, "CreateAssemblyCache" ))) goto error;
00069     return TRUE;
00070 
00071 error:
00072     pCreateAssemblyCacheNet10 = NULL;
00073     pCreateAssemblyCacheNet11 = NULL;
00074     pCreateAssemblyCacheNet20 = NULL;
00075     FreeLibrary( hfusion10 );
00076     FreeLibrary( hfusion11 );
00077     FreeLibrary( hfusion20 );
00078     FreeLibrary( hmscoree );
00079     return FALSE;
00080 }
00081 
00082 BOOL msi_init_assembly_caches( MSIPACKAGE *package )
00083 {
00084     if (!init_function_pointers()) return FALSE;
00085     if (package->cache_net[CLR_VERSION_V10] ||
00086         package->cache_net[CLR_VERSION_V11] ||
00087         package->cache_net[CLR_VERSION_V20]) return TRUE;
00088     if (pCreateAssemblyCacheSxs( &package->cache_sxs, 0 ) != S_OK) return FALSE;
00089 
00090     if (pCreateAssemblyCacheNet10) pCreateAssemblyCacheNet11( &package->cache_net[CLR_VERSION_V10], 0 );
00091     if (pCreateAssemblyCacheNet11) pCreateAssemblyCacheNet11( &package->cache_net[CLR_VERSION_V11], 0 );
00092     if (pCreateAssemblyCacheNet20) pCreateAssemblyCacheNet20( &package->cache_net[CLR_VERSION_V20], 0 );
00093 
00094     if (package->cache_net[CLR_VERSION_V10] ||
00095         package->cache_net[CLR_VERSION_V11] ||
00096         package->cache_net[CLR_VERSION_V20])
00097     {
00098         return TRUE;
00099     }
00100     if (package->cache_net[CLR_VERSION_V10])
00101     {
00102         IAssemblyCache_Release( package->cache_net[CLR_VERSION_V10] );
00103         package->cache_net[CLR_VERSION_V10] = NULL;
00104     }
00105     if (package->cache_net[CLR_VERSION_V11])
00106     {
00107         IAssemblyCache_Release( package->cache_net[CLR_VERSION_V11] );
00108         package->cache_net[CLR_VERSION_V11] = NULL;
00109     }
00110     if (package->cache_net[CLR_VERSION_V20])
00111     {
00112         IAssemblyCache_Release( package->cache_net[CLR_VERSION_V20] );
00113         package->cache_net[CLR_VERSION_V20] = NULL;
00114     }
00115     IAssemblyCache_Release( package->cache_sxs );
00116     package->cache_sxs = NULL;
00117     return FALSE;
00118 }
00119 
00120 void msi_destroy_assembly_caches( MSIPACKAGE *package )
00121 {
00122     UINT i;
00123 
00124     for (i = 0; i < CLR_VERSION_MAX; i++)
00125     {
00126         if (package->cache_net[i])
00127         {
00128             IAssemblyCache_Release( package->cache_net[i] );
00129             package->cache_net[i] = NULL;
00130         }
00131     }
00132     if (package->cache_sxs)
00133     {
00134         IAssemblyCache_Release( package->cache_sxs );
00135         package->cache_sxs = NULL;
00136     }
00137     pCreateAssemblyCacheNet10 = NULL;
00138     pCreateAssemblyCacheNet11 = NULL;
00139     pCreateAssemblyCacheNet20 = NULL;
00140     FreeLibrary( hfusion10 );
00141     FreeLibrary( hfusion11 );
00142     FreeLibrary( hfusion20 );
00143     FreeLibrary( hmscoree );
00144     FreeLibrary( hsxs );
00145 }
00146 
00147 static MSIRECORD *get_assembly_record( MSIPACKAGE *package, const WCHAR *comp )
00148 {
00149     static const WCHAR query[] = {
00150         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00151          '`','M','s','i','A','s','s','e','m','b','l','y','`',' ',
00152          'W','H','E','R','E',' ','`','C','o','m','p','o','n','e','n','t','_','`',
00153          ' ','=',' ','\'','%','s','\'',0};
00154     MSIQUERY *view;
00155     MSIRECORD *rec;
00156     UINT r;
00157 
00158     r = MSI_OpenQuery( package->db, &view, query, comp );
00159     if (r != ERROR_SUCCESS)
00160         return NULL;
00161 
00162     r = MSI_ViewExecute( view, NULL );
00163     if (r != ERROR_SUCCESS)
00164     {
00165         msiobj_release( &view->hdr );
00166         return NULL;
00167     }
00168     r = MSI_ViewFetch( view, &rec );
00169     if (r != ERROR_SUCCESS)
00170     {
00171         msiobj_release( &view->hdr );
00172         return NULL;
00173     }
00174     if (!MSI_RecordGetString( rec, 4 ))
00175         TRACE("component is a global assembly\n");
00176 
00177     msiobj_release( &view->hdr );
00178     return rec;
00179 }
00180 
00181 struct assembly_name
00182 {
00183     UINT    count;
00184     UINT    index;
00185     WCHAR **attrs;
00186 };
00187 
00188 static UINT get_assembly_name_attribute( MSIRECORD *rec, LPVOID param )
00189 {
00190     static const WCHAR fmtW[] = {'%','s','=','"','%','s','"',0};
00191     static const WCHAR nameW[] = {'n','a','m','e',0};
00192     struct assembly_name *name = param;
00193     const WCHAR *attr = MSI_RecordGetString( rec, 2 );
00194     const WCHAR *value = MSI_RecordGetString( rec, 3 );
00195     int len = strlenW( fmtW ) + strlenW( attr ) + strlenW( value );
00196 
00197     if (!(name->attrs[name->index] = msi_alloc( len * sizeof(WCHAR) )))
00198         return ERROR_OUTOFMEMORY;
00199 
00200     if (!strcmpiW( attr, nameW )) strcpyW( name->attrs[name->index++], value );
00201     else sprintfW( name->attrs[name->index++], fmtW, attr, value );
00202     return ERROR_SUCCESS;
00203 }
00204 
00205 static WCHAR *get_assembly_display_name( MSIDATABASE *db, const WCHAR *comp, MSIASSEMBLY *assembly )
00206 {
00207     static const WCHAR commaW[] = {',',0};
00208     static const WCHAR queryW[] = {
00209         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00210         '`','M','s','i','A','s','s','e','m','b','l','y','N','a','m','e','`',' ',
00211         'W','H','E','R','E',' ','`','C','o','m','p','o','n','e','n','t','_','`',
00212         ' ','=',' ','\'','%','s','\'',0};
00213     struct assembly_name name;
00214     WCHAR *display_name = NULL;
00215     MSIQUERY *view;
00216     UINT i, r;
00217     int len;
00218 
00219     r = MSI_OpenQuery( db, &view, queryW, comp );
00220     if (r != ERROR_SUCCESS)
00221         return NULL;
00222 
00223     name.count = 0;
00224     name.index = 0;
00225     name.attrs = NULL;
00226     MSI_IterateRecords( view, &name.count, NULL, NULL );
00227     if (!name.count) goto done;
00228 
00229     name.attrs = msi_alloc( name.count * sizeof(WCHAR *) );
00230     if (!name.attrs) goto done;
00231 
00232     MSI_IterateRecords( view, NULL, get_assembly_name_attribute, &name );
00233 
00234     len = 0;
00235     for (i = 0; i < name.count; i++) len += strlenW( name.attrs[i] ) + 1;
00236 
00237     display_name = msi_alloc( (len + 1) * sizeof(WCHAR) );
00238     if (display_name)
00239     {
00240         display_name[0] = 0;
00241         for (i = 0; i < name.count; i++)
00242         {
00243             strcatW( display_name, name.attrs[i] );
00244             if (i < name.count - 1) strcatW( display_name, commaW );
00245         }
00246     }
00247 
00248 done:
00249     msiobj_release( &view->hdr );
00250     if (name.attrs)
00251     {
00252         for (i = 0; i < name.count; i++) msi_free( name.attrs[i] );
00253         msi_free( name.attrs );
00254     }
00255     return display_name;
00256 }
00257 
00258 static BOOL is_assembly_installed( IAssemblyCache *cache, const WCHAR *display_name )
00259 {
00260     HRESULT hr;
00261     ASSEMBLY_INFO info;
00262 
00263     memset( &info, 0, sizeof(info) );
00264     info.cbAssemblyInfo = sizeof(info);
00265     hr = IAssemblyCache_QueryAssemblyInfo( cache, 0, display_name, &info );
00266     if (hr == S_OK /* sxs version */ || hr == HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
00267     {
00268         return (info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
00269     }
00270     TRACE("QueryAssemblyInfo returned 0x%08x\n", hr);
00271     return FALSE;
00272 }
00273 
00274 static const WCHAR clr_version_v10[] = {'v','1','.','0','.','3','7','0','5',0};
00275 static const WCHAR clr_version_v11[] = {'v','1','.','1','.','4','3','2','2',0};
00276 static const WCHAR clr_version_v20[] = {'v','2','.','0','.','5','0','7','2','7',0};
00277 static const WCHAR clr_version_unknown[] = {'u','n','k','n','o','w','n',0};
00278 
00279 static const WCHAR *clr_version[] =
00280 {
00281     clr_version_v10,
00282     clr_version_v11,
00283     clr_version_v20
00284 };
00285 
00286 static const WCHAR *get_clr_version_str( enum clr_version version )
00287 {
00288     if (version >= sizeof(clr_version)/sizeof(clr_version[0])) return clr_version_unknown;
00289     return clr_version[version];
00290 }
00291 
00292 /* assembly caches must be initialized */
00293 MSIASSEMBLY *msi_load_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
00294 {
00295     MSIRECORD *rec;
00296     MSIASSEMBLY *a;
00297 
00298     if (!(rec = get_assembly_record( package, comp->Component ))) return NULL;
00299     if (!(a = msi_alloc_zero( sizeof(MSIASSEMBLY) )))
00300     {
00301         msiobj_release( &rec->hdr );
00302         return NULL;
00303     }
00304     a->feature = strdupW( MSI_RecordGetString( rec, 2 ) );
00305     TRACE("feature %s\n", debugstr_w(a->feature));
00306 
00307     a->manifest = strdupW( MSI_RecordGetString( rec, 3 ) );
00308     TRACE("manifest %s\n", debugstr_w(a->manifest));
00309 
00310     a->application = strdupW( MSI_RecordGetString( rec, 4 ) );
00311     TRACE("application %s\n", debugstr_w(a->application));
00312 
00313     a->attributes = MSI_RecordGetInteger( rec, 5 );
00314     TRACE("attributes %u\n", a->attributes);
00315 
00316     if (!(a->display_name = get_assembly_display_name( package->db, comp->Component, a )))
00317     {
00318         WARN("can't get display name\n");
00319         msiobj_release( &rec->hdr );
00320         msi_free( a->feature );
00321         msi_free( a->manifest );
00322         msi_free( a->application );
00323         msi_free( a );
00324         return NULL;
00325     }
00326     TRACE("display name %s\n", debugstr_w(a->display_name));
00327 
00328     if (a->application)
00329     {
00330         /* We can't check the manifest here because the target path may still change.
00331            So we assume that the assembly is not installed and lean on the InstallFiles
00332            action to determine which files need to be installed.
00333          */
00334         a->installed = FALSE;
00335     }
00336     else
00337     {
00338         if (a->attributes == msidbAssemblyAttributesWin32)
00339             a->installed = is_assembly_installed( package->cache_sxs, a->display_name );
00340         else
00341         {
00342             UINT i;
00343             for (i = 0; i < CLR_VERSION_MAX; i++)
00344             {
00345                 a->clr_version[i] = is_assembly_installed( package->cache_net[i], a->display_name );
00346                 if (a->clr_version[i])
00347                 {
00348                     TRACE("runtime version %s\n", debugstr_w(get_clr_version_str( i )));
00349                     a->installed = TRUE;
00350                 }
00351             }
00352         }
00353     }
00354     TRACE("assembly is %s\n", a->installed ? "installed" : "not installed");
00355     msiobj_release( &rec->hdr );
00356     return a;
00357 }
00358 
00359 static enum clr_version get_clr_version( const WCHAR *filename )
00360 {
00361     DWORD len;
00362     HRESULT hr;
00363     enum clr_version version = CLR_VERSION_V11;
00364     WCHAR *strW;
00365 
00366     if (!pGetFileVersion) return CLR_VERSION_V10;
00367 
00368     hr = pGetFileVersion( filename, NULL, 0, &len );
00369     if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) return CLR_VERSION_V11;
00370     if ((strW = msi_alloc( len * sizeof(WCHAR) )))
00371     {
00372         hr = pGetFileVersion( filename, strW, len, &len );
00373         if (hr == S_OK)
00374         {
00375             UINT i;
00376             for (i = 0; i < CLR_VERSION_MAX; i++)
00377                 if (!strcmpW( strW, clr_version[i] )) version = i;
00378         }
00379         msi_free( strW );
00380     }
00381     return version;
00382 }
00383 
00384 UINT msi_install_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
00385 {
00386     HRESULT hr;
00387     const WCHAR *manifest;
00388     IAssemblyCache *cache;
00389     MSIASSEMBLY *assembly = comp->assembly;
00390     MSIFEATURE *feature = NULL;
00391 
00392     if (comp->assembly->feature)
00393         feature = msi_get_loaded_feature( package, comp->assembly->feature );
00394 
00395     if (assembly->application)
00396     {
00397         if (feature) feature->Action = INSTALLSTATE_LOCAL;
00398         return ERROR_SUCCESS;
00399     }
00400     if (assembly->attributes == msidbAssemblyAttributesWin32)
00401     {
00402         if (!assembly->manifest)
00403         {
00404             WARN("no manifest\n");
00405             return ERROR_FUNCTION_FAILED;
00406         }
00407         manifest = msi_get_loaded_file( package, assembly->manifest )->TargetPath;
00408         cache = package->cache_sxs;
00409     }
00410     else
00411     {
00412         manifest = msi_get_loaded_file( package, comp->KeyPath )->TargetPath;
00413         cache = package->cache_net[get_clr_version( manifest )];
00414     }
00415     TRACE("installing assembly %s\n", debugstr_w(manifest));
00416 
00417     hr = IAssemblyCache_InstallAssembly( cache, 0, manifest, NULL );
00418     if (hr != S_OK)
00419     {
00420         ERR("Failed to install assembly %s (0x%08x)\n", debugstr_w(manifest), hr);
00421         return ERROR_FUNCTION_FAILED;
00422     }
00423     if (feature) feature->Action = INSTALLSTATE_LOCAL;
00424     assembly->installed = TRUE;
00425     return ERROR_SUCCESS;
00426 }
00427 
00428 UINT msi_uninstall_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
00429 {
00430     HRESULT hr;
00431     IAssemblyCache *cache;
00432     MSIASSEMBLY *assembly = comp->assembly;
00433     MSIFEATURE *feature = NULL;
00434 
00435     if (comp->assembly->feature)
00436         feature = msi_get_loaded_feature( package, comp->assembly->feature );
00437 
00438     if (assembly->application)
00439     {
00440         if (feature) feature->Action = INSTALLSTATE_ABSENT;
00441         return ERROR_SUCCESS;
00442     }
00443     TRACE("removing %s\n", debugstr_w(assembly->display_name));
00444 
00445     if (assembly->attributes == msidbAssemblyAttributesWin32)
00446     {
00447         cache = package->cache_sxs;
00448         hr = IAssemblyCache_UninstallAssembly( cache, 0, assembly->display_name, NULL, NULL );
00449         if (FAILED( hr )) WARN("failed to uninstall assembly 0x%08x\n", hr);
00450     }
00451     else
00452     {
00453         unsigned int i;
00454         for (i = 0; i < CLR_VERSION_MAX; i++)
00455         {
00456             if (!assembly->clr_version[i]) continue;
00457             cache = package->cache_net[i];
00458             hr = IAssemblyCache_UninstallAssembly( cache, 0, assembly->display_name, NULL, NULL );
00459             if (FAILED( hr )) WARN("failed to uninstall assembly 0x%08x\n", hr);
00460         }
00461     }
00462     if (feature) feature->Action = INSTALLSTATE_ABSENT;
00463     assembly->installed = FALSE;
00464     return ERROR_SUCCESS;
00465 }
00466 
00467 static WCHAR *build_local_assembly_path( const WCHAR *filename )
00468 {
00469     UINT i;
00470     WCHAR *ret;
00471 
00472     if (!(ret = msi_alloc( (strlenW( filename ) + 1) * sizeof(WCHAR) )))
00473         return NULL;
00474 
00475     for (i = 0; filename[i]; i++)
00476     {
00477         if (filename[i] == '\\' || filename[i] == '/') ret[i] = '|';
00478         else ret[i] = filename[i];
00479     }
00480     ret[i] = 0;
00481     return ret;
00482 }
00483 
00484 static LONG open_assemblies_key( UINT context, BOOL win32, HKEY *hkey )
00485 {
00486     static const WCHAR path_win32[] =
00487         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00488           'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',0};
00489     static const WCHAR path_dotnet[] =
00490         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00491          'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\',0};
00492     static const WCHAR classes_path_win32[] =
00493         {'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',0};
00494     static const WCHAR classes_path_dotnet[] =
00495         {'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\',0};
00496     HKEY root;
00497     const WCHAR *path;
00498 
00499     if (context == MSIINSTALLCONTEXT_MACHINE)
00500     {
00501         root = HKEY_CLASSES_ROOT;
00502         if (win32) path = classes_path_win32;
00503         else path = classes_path_dotnet;
00504     }
00505     else
00506     {
00507         root = HKEY_CURRENT_USER;
00508         if (win32) path = path_win32;
00509         else path = path_dotnet;
00510     }
00511     return RegCreateKeyW( root, path, hkey );
00512 }
00513 
00514 static LONG open_local_assembly_key( UINT context, BOOL win32, const WCHAR *filename, HKEY *hkey )
00515 {
00516     LONG res;
00517     HKEY root;
00518     WCHAR *path;
00519 
00520     if (!(path = build_local_assembly_path( filename )))
00521         return ERROR_OUTOFMEMORY;
00522 
00523     if ((res = open_assemblies_key( context, win32, &root )))
00524     {
00525         msi_free( path );
00526         return res;
00527     }
00528     res = RegCreateKeyW( root, path, hkey );
00529     RegCloseKey( root );
00530     msi_free( path );
00531     return res;
00532 }
00533 
00534 static LONG delete_local_assembly_key( UINT context, BOOL win32, const WCHAR *filename )
00535 {
00536     LONG res;
00537     HKEY root;
00538     WCHAR *path;
00539 
00540     if (!(path = build_local_assembly_path( filename )))
00541         return ERROR_OUTOFMEMORY;
00542 
00543     if ((res = open_assemblies_key( context, win32, &root )))
00544     {
00545         msi_free( path );
00546         return res;
00547     }
00548     res = RegDeleteKeyW( root, path );
00549     RegCloseKey( root );
00550     msi_free( path );
00551     return res;
00552 }
00553 
00554 static LONG open_global_assembly_key( UINT context, BOOL win32, HKEY *hkey )
00555 {
00556     static const WCHAR path_win32[] =
00557         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00558          'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',
00559          'G','l','o','b','a','l',0};
00560     static const WCHAR path_dotnet[] =
00561         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00562          'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\',
00563          'G','l','o','b','a','l',0};
00564     static const WCHAR classes_path_win32[] =
00565         {'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',
00566          'G','l','o','b','a','l',0};
00567     static const WCHAR classes_path_dotnet[] =
00568         {'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\','G','l','o','b','a','l',0};
00569     HKEY root;
00570     const WCHAR *path;
00571 
00572     if (context == MSIINSTALLCONTEXT_MACHINE)
00573     {
00574         root = HKEY_CLASSES_ROOT;
00575         if (win32) path = classes_path_win32;
00576         else path = classes_path_dotnet;
00577     }
00578     else
00579     {
00580         root = HKEY_CURRENT_USER;
00581         if (win32) path = path_win32;
00582         else path = path_dotnet;
00583     }
00584     return RegCreateKeyW( root, path, hkey );
00585 }
00586 
00587 UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
00588 {
00589     MSICOMPONENT *comp;
00590 
00591     LIST_FOR_EACH_ENTRY(comp, &package->components, MSICOMPONENT, entry)
00592     {
00593         LONG res;
00594         HKEY hkey;
00595         GUID guid;
00596         DWORD size;
00597         WCHAR buffer[43];
00598         MSIRECORD *uirow;
00599         MSIASSEMBLY *assembly = comp->assembly;
00600         BOOL win32;
00601 
00602         if (!assembly || !comp->ComponentId) continue;
00603 
00604         comp->Action = msi_get_component_action( package, comp );
00605         if (comp->Action != INSTALLSTATE_LOCAL)
00606         {
00607             TRACE("component not scheduled for installation %s\n", debugstr_w(comp->Component));
00608             continue;
00609         }
00610         TRACE("publishing %s\n", debugstr_w(comp->Component));
00611 
00612         CLSIDFromString( package->ProductCode, &guid );
00613         encode_base85_guid( &guid, buffer );
00614         buffer[20] = '>';
00615         CLSIDFromString( comp->ComponentId, &guid );
00616         encode_base85_guid( &guid, buffer + 21 );
00617         buffer[42] = 0;
00618 
00619         win32 = assembly->attributes & msidbAssemblyAttributesWin32;
00620         if (assembly->application)
00621         {
00622             MSIFILE *file = msi_get_loaded_file( package, assembly->application );
00623             if ((res = open_local_assembly_key( package->Context, win32, file->TargetPath, &hkey )))
00624             {
00625                 WARN("failed to open local assembly key %d\n", res);
00626                 return ERROR_FUNCTION_FAILED;
00627             }
00628         }
00629         else
00630         {
00631             if ((res = open_global_assembly_key( package->Context, win32, &hkey )))
00632             {
00633                 WARN("failed to open global assembly key %d\n", res);
00634                 return ERROR_FUNCTION_FAILED;
00635             }
00636         }
00637         size = sizeof(buffer);
00638         if ((res = RegSetValueExW( hkey, assembly->display_name, 0, REG_MULTI_SZ, (const BYTE *)buffer, size )))
00639         {
00640             WARN("failed to set assembly value %d\n", res);
00641         }
00642         RegCloseKey( hkey );
00643 
00644         uirow = MSI_CreateRecord( 2 );
00645         MSI_RecordSetStringW( uirow, 2, assembly->display_name );
00646         msi_ui_actiondata( package, szMsiPublishAssemblies, uirow );
00647         msiobj_release( &uirow->hdr );
00648     }
00649     return ERROR_SUCCESS;
00650 }
00651 
00652 UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
00653 {
00654     MSICOMPONENT *comp;
00655 
00656     LIST_FOR_EACH_ENTRY(comp, &package->components, MSICOMPONENT, entry)
00657     {
00658         LONG res;
00659         MSIRECORD *uirow;
00660         MSIASSEMBLY *assembly = comp->assembly;
00661         BOOL win32;
00662 
00663         if (!assembly || !comp->ComponentId) continue;
00664 
00665         comp->Action = msi_get_component_action( package, comp );
00666         if (comp->Action != INSTALLSTATE_ABSENT)
00667         {
00668             TRACE("component not scheduled for removal %s\n", debugstr_w(comp->Component));
00669             continue;
00670         }
00671         TRACE("unpublishing %s\n", debugstr_w(comp->Component));
00672 
00673         win32 = assembly->attributes & msidbAssemblyAttributesWin32;
00674         if (assembly->application)
00675         {
00676             MSIFILE *file = msi_get_loaded_file( package, assembly->application );
00677             if ((res = delete_local_assembly_key( package->Context, win32, file->TargetPath )))
00678                 WARN("failed to delete local assembly key %d\n", res);
00679         }
00680         else
00681         {
00682             HKEY hkey;
00683             if ((res = open_global_assembly_key( package->Context, win32, &hkey )))
00684                 WARN("failed to delete global assembly key %d\n", res);
00685             else
00686             {
00687                 if ((res = RegDeleteValueW( hkey, assembly->display_name )))
00688                     WARN("failed to delete global assembly value %d\n", res);
00689                 RegCloseKey( hkey );
00690             }
00691         }
00692 
00693         uirow = MSI_CreateRecord( 2 );
00694         MSI_RecordSetStringW( uirow, 2, assembly->display_name );
00695         msi_ui_actiondata( package, szMsiPublishAssemblies, uirow );
00696         msiobj_release( &uirow->hdr );
00697     }
00698     return ERROR_SUCCESS;
00699 }

Generated on Sun May 27 2012 04:23:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.