Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenassembly.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
1.7.6.1
|