1c2c66affSColin Finck /* 2c2c66affSColin Finck * Implementation of the Microsoft Installer (msi.dll) 3c2c66affSColin Finck * 4c2c66affSColin Finck * Copyright 2004 Aric Stewart for CodeWeavers 5c2c66affSColin Finck * 6c2c66affSColin Finck * This library is free software; you can redistribute it and/or 7c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 8c2c66affSColin Finck * License as published by the Free Software Foundation; either 9c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 10c2c66affSColin Finck * 11c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 12c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 13c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14c2c66affSColin Finck * Lesser General Public License for more details. 15c2c66affSColin Finck * 16c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 17c2c66affSColin Finck * License along with this library; if not, write to the Free Software 18c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19c2c66affSColin Finck */ 20c2c66affSColin Finck 21c42b133eSAmine Khaldi #define NONAMELESSUNION 22c42b133eSAmine Khaldi #define NONAMELESSSTRUCT 23c42b133eSAmine Khaldi #define COBJMACROS 24c2c66affSColin Finck 25c42b133eSAmine Khaldi #include <stdarg.h> 26c42b133eSAmine Khaldi #include "windef.h" 27c42b133eSAmine Khaldi #include "winbase.h" 28c42b133eSAmine Khaldi #include "winreg.h" 29c42b133eSAmine Khaldi #include "winnls.h" 30c42b133eSAmine Khaldi #include "shlwapi.h" 31c42b133eSAmine Khaldi #include "wingdi.h" 32c42b133eSAmine Khaldi #include "msi.h" 33c42b133eSAmine Khaldi #include "msiquery.h" 34c42b133eSAmine Khaldi #include "objidl.h" 35c42b133eSAmine Khaldi #include "wincrypt.h" 36c42b133eSAmine Khaldi #include "winuser.h" 37c42b133eSAmine Khaldi #include "wininet.h" 38c42b133eSAmine Khaldi #include "winver.h" 39c42b133eSAmine Khaldi #include "urlmon.h" 40c42b133eSAmine Khaldi #include "shlobj.h" 41c42b133eSAmine Khaldi #include "objbase.h" 42c42b133eSAmine Khaldi #include "msidefs.h" 43c42b133eSAmine Khaldi #include "sddl.h" 44c42b133eSAmine Khaldi 4562ababd7Swinesync #include "wine/heap.h" 4662ababd7Swinesync #include "wine/debug.h" 4762ababd7Swinesync #include "wine/unicode.h" 4862ababd7Swinesync 49c42b133eSAmine Khaldi #include "msipriv.h" 50b74b77aaSwinesync #include "winemsi.h" 51c42b133eSAmine Khaldi #include "resource.h" 52c2c66affSColin Finck 53c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi); 54c2c66affSColin Finck 55c2c66affSColin Finck static void free_feature( MSIFEATURE *feature ) 56c2c66affSColin Finck { 57c2c66affSColin Finck struct list *item, *cursor; 58c2c66affSColin Finck 59c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Children ) 60c2c66affSColin Finck { 61c2c66affSColin Finck FeatureList *fl = LIST_ENTRY( item, FeatureList, entry ); 62c2c66affSColin Finck list_remove( &fl->entry ); 63c2c66affSColin Finck msi_free( fl ); 64c2c66affSColin Finck } 65c2c66affSColin Finck 66c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) 67c2c66affSColin Finck { 68c2c66affSColin Finck ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); 69c2c66affSColin Finck list_remove( &cl->entry ); 70c2c66affSColin Finck msi_free( cl ); 71c2c66affSColin Finck } 72c2c66affSColin Finck msi_free( feature->Feature ); 73c2c66affSColin Finck msi_free( feature->Feature_Parent ); 74c2c66affSColin Finck msi_free( feature->Directory ); 75c2c66affSColin Finck msi_free( feature->Description ); 76c2c66affSColin Finck msi_free( feature->Title ); 77c2c66affSColin Finck msi_free( feature ); 78c2c66affSColin Finck } 79c2c66affSColin Finck 80c2c66affSColin Finck static void free_folder( MSIFOLDER *folder ) 81c2c66affSColin Finck { 82c2c66affSColin Finck struct list *item, *cursor; 83c2c66affSColin Finck 84c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &folder->children ) 85c2c66affSColin Finck { 86c2c66affSColin Finck FolderList *fl = LIST_ENTRY( item, FolderList, entry ); 87c2c66affSColin Finck list_remove( &fl->entry ); 88c2c66affSColin Finck msi_free( fl ); 89c2c66affSColin Finck } 90c2c66affSColin Finck msi_free( folder->Parent ); 91c2c66affSColin Finck msi_free( folder->Directory ); 92c2c66affSColin Finck msi_free( folder->TargetDefault ); 93c2c66affSColin Finck msi_free( folder->SourceLongPath ); 94c2c66affSColin Finck msi_free( folder->SourceShortPath ); 95c2c66affSColin Finck msi_free( folder->ResolvedTarget ); 96c2c66affSColin Finck msi_free( folder->ResolvedSource ); 97c2c66affSColin Finck msi_free( folder ); 98c2c66affSColin Finck } 99c2c66affSColin Finck 100c2c66affSColin Finck static void free_extension( MSIEXTENSION *ext ) 101c2c66affSColin Finck { 102c2c66affSColin Finck struct list *item, *cursor; 103c2c66affSColin Finck 104c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs ) 105c2c66affSColin Finck { 106c2c66affSColin Finck MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry ); 107c2c66affSColin Finck 108c2c66affSColin Finck list_remove( &verb->entry ); 109c2c66affSColin Finck msi_free( verb->Verb ); 110c2c66affSColin Finck msi_free( verb->Command ); 111c2c66affSColin Finck msi_free( verb->Argument ); 112c2c66affSColin Finck msi_free( verb ); 113c2c66affSColin Finck } 114c2c66affSColin Finck 115c2c66affSColin Finck msi_free( ext->Extension ); 116c2c66affSColin Finck msi_free( ext->ProgIDText ); 117c2c66affSColin Finck msi_free( ext ); 118c2c66affSColin Finck } 119c2c66affSColin Finck 120c2c66affSColin Finck static void free_assembly( MSIASSEMBLY *assembly ) 121c2c66affSColin Finck { 122c2c66affSColin Finck msi_free( assembly->feature ); 123c2c66affSColin Finck msi_free( assembly->manifest ); 124c2c66affSColin Finck msi_free( assembly->application ); 125c2c66affSColin Finck msi_free( assembly->display_name ); 126c2c66affSColin Finck if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir ); 127c2c66affSColin Finck msi_free( assembly->tempdir ); 128c2c66affSColin Finck msi_free( assembly ); 129c2c66affSColin Finck } 130c2c66affSColin Finck 131c2c66affSColin Finck void msi_free_action_script( MSIPACKAGE *package, UINT script ) 132c2c66affSColin Finck { 133c2c66affSColin Finck UINT i; 134f8b992f2SAmine Khaldi for (i = 0; i < package->script_actions_count[script]; i++) 135f8b992f2SAmine Khaldi msi_free( package->script_actions[script][i] ); 136c2c66affSColin Finck 137f8b992f2SAmine Khaldi msi_free( package->script_actions[script] ); 138f8b992f2SAmine Khaldi package->script_actions[script] = NULL; 139f8b992f2SAmine Khaldi package->script_actions_count[script] = 0; 140c2c66affSColin Finck } 141c2c66affSColin Finck 142c2c66affSColin Finck static void free_package_structures( MSIPACKAGE *package ) 143c2c66affSColin Finck { 144c2c66affSColin Finck struct list *item, *cursor; 145f8b992f2SAmine Khaldi int i; 146c2c66affSColin Finck 147c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->features ) 148c2c66affSColin Finck { 149c2c66affSColin Finck MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); 150c2c66affSColin Finck list_remove( &feature->entry ); 151c2c66affSColin Finck free_feature( feature ); 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->folders ) 155c2c66affSColin Finck { 156c2c66affSColin Finck MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); 157c2c66affSColin Finck list_remove( &folder->entry ); 158c2c66affSColin Finck free_folder( folder ); 159c2c66affSColin Finck } 160c2c66affSColin Finck 161c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->files ) 162c2c66affSColin Finck { 163c2c66affSColin Finck MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry ); 164c2c66affSColin Finck 165c2c66affSColin Finck list_remove( &file->entry ); 166c2c66affSColin Finck msi_free( file->File ); 167c2c66affSColin Finck msi_free( file->FileName ); 168c2c66affSColin Finck msi_free( file->ShortName ); 169c2c66affSColin Finck msi_free( file->LongName ); 170c2c66affSColin Finck msi_free( file->Version ); 171c2c66affSColin Finck msi_free( file->Language ); 172c2c66affSColin Finck if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath ); 173c2c66affSColin Finck msi_free( file->TargetPath ); 174c2c66affSColin Finck msi_free( file ); 175c2c66affSColin Finck } 176c2c66affSColin Finck 177c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->components ) 178c2c66affSColin Finck { 179c2c66affSColin Finck MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); 180c2c66affSColin Finck 181c2c66affSColin Finck list_remove( &comp->entry ); 182c2c66affSColin Finck msi_free( comp->Component ); 183c2c66affSColin Finck msi_free( comp->ComponentId ); 184c2c66affSColin Finck msi_free( comp->Directory ); 185c2c66affSColin Finck msi_free( comp->Condition ); 186c2c66affSColin Finck msi_free( comp->KeyPath ); 187c2c66affSColin Finck msi_free( comp->FullKeypath ); 188c2c66affSColin Finck if (comp->assembly) free_assembly( comp->assembly ); 189c2c66affSColin Finck msi_free( comp ); 190c2c66affSColin Finck } 191c2c66affSColin Finck 192c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches ) 193c2c66affSColin Finck { 194c2c66affSColin Finck MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry ); 195c2c66affSColin Finck 196c2c66affSColin Finck list_remove( &patch->entry ); 197c2c66affSColin Finck msi_free( patch->path ); 198c2c66affSColin Finck msi_free( patch ); 199c2c66affSColin Finck } 200c2c66affSColin Finck 201c2c66affSColin Finck /* clean up extension, progid, class and verb structures */ 202c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) 203c2c66affSColin Finck { 204c2c66affSColin Finck MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry ); 205c2c66affSColin Finck 206c2c66affSColin Finck list_remove( &cls->entry ); 207c2c66affSColin Finck msi_free( cls->clsid ); 208c2c66affSColin Finck msi_free( cls->Context ); 209c2c66affSColin Finck msi_free( cls->Description ); 210c2c66affSColin Finck msi_free( cls->FileTypeMask ); 211c2c66affSColin Finck msi_free( cls->IconPath ); 212c2c66affSColin Finck msi_free( cls->DefInprocHandler ); 213c2c66affSColin Finck msi_free( cls->DefInprocHandler32 ); 214c2c66affSColin Finck msi_free( cls->Argument ); 215c2c66affSColin Finck msi_free( cls->ProgIDText ); 216c2c66affSColin Finck msi_free( cls ); 217c2c66affSColin Finck } 218c2c66affSColin Finck 219c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->extensions ) 220c2c66affSColin Finck { 221c2c66affSColin Finck MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry ); 222c2c66affSColin Finck 223c2c66affSColin Finck list_remove( &ext->entry ); 224c2c66affSColin Finck free_extension( ext ); 225c2c66affSColin Finck } 226c2c66affSColin Finck 227c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->progids ) 228c2c66affSColin Finck { 229c2c66affSColin Finck MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry ); 230c2c66affSColin Finck 231c2c66affSColin Finck list_remove( &progid->entry ); 232c2c66affSColin Finck msi_free( progid->ProgID ); 233c2c66affSColin Finck msi_free( progid->Description ); 234c2c66affSColin Finck msi_free( progid->IconPath ); 235c2c66affSColin Finck msi_free( progid ); 236c2c66affSColin Finck } 237c2c66affSColin Finck 238c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) 239c2c66affSColin Finck { 240c2c66affSColin Finck MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry ); 241c2c66affSColin Finck 242c2c66affSColin Finck list_remove( &mt->entry ); 243c2c66affSColin Finck msi_free( mt->suffix ); 244c2c66affSColin Finck msi_free( mt->clsid ); 245c2c66affSColin Finck msi_free( mt->ContentType ); 246c2c66affSColin Finck msi_free( mt ); 247c2c66affSColin Finck } 248c2c66affSColin Finck 249c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->appids ) 250c2c66affSColin Finck { 251c2c66affSColin Finck MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry ); 252c2c66affSColin Finck 253c2c66affSColin Finck list_remove( &appid->entry ); 254c2c66affSColin Finck msi_free( appid->AppID ); 255c2c66affSColin Finck msi_free( appid->RemoteServerName ); 256c2c66affSColin Finck msi_free( appid->LocalServer ); 257c2c66affSColin Finck msi_free( appid->ServiceParameters ); 258c2c66affSColin Finck msi_free( appid->DllSurrogate ); 259c2c66affSColin Finck msi_free( appid ); 260c2c66affSColin Finck } 261c2c66affSColin Finck 262c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info ) 263c2c66affSColin Finck { 264c2c66affSColin Finck MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry ); 265c2c66affSColin Finck 266c2c66affSColin Finck list_remove( &info->entry ); 267c2c66affSColin Finck msi_free( info->value ); 268c2c66affSColin Finck msi_free( info ); 269c2c66affSColin Finck } 270c2c66affSColin Finck 271c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media ) 272c2c66affSColin Finck { 273c2c66affSColin Finck MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry ); 274c2c66affSColin Finck 275c2c66affSColin Finck list_remove( &info->entry ); 276c2c66affSColin Finck msi_free( info->volume_label ); 277c2c66affSColin Finck msi_free( info->disk_prompt ); 278c2c66affSColin Finck msi_free( info ); 279c2c66affSColin Finck } 280c2c66affSColin Finck 281c2c66affSColin Finck for (i = 0; i < SCRIPT_MAX; i++) 282c2c66affSColin Finck msi_free_action_script( package, i ); 283c2c66affSColin Finck 284f8b992f2SAmine Khaldi for (i = 0; i < package->unique_actions_count; i++) 285f8b992f2SAmine Khaldi msi_free( package->unique_actions[i] ); 286f8b992f2SAmine Khaldi msi_free( package->unique_actions); 287c2c66affSColin Finck 288c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->binaries ) 289c2c66affSColin Finck { 290c2c66affSColin Finck MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry ); 291c2c66affSColin Finck 292c2c66affSColin Finck list_remove( &binary->entry ); 293c2c66affSColin Finck if (binary->module) 294c2c66affSColin Finck FreeLibrary( binary->module ); 295c2c66affSColin Finck if (!DeleteFileW( binary->tmpfile )) 296c2c66affSColin Finck ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError()); 297c2c66affSColin Finck msi_free( binary->source ); 298c2c66affSColin Finck msi_free( binary->tmpfile ); 299c2c66affSColin Finck msi_free( binary ); 300c2c66affSColin Finck } 301c2c66affSColin Finck 302c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams ) 303c2c66affSColin Finck { 304c2c66affSColin Finck MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry ); 305c2c66affSColin Finck 306c2c66affSColin Finck list_remove( &cab->entry ); 307c2c66affSColin Finck IStorage_Release( cab->storage ); 308c2c66affSColin Finck msi_free( cab->stream ); 309c2c66affSColin Finck msi_free( cab ); 310c2c66affSColin Finck } 311c2c66affSColin Finck 312c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->patches ) 313c2c66affSColin Finck { 314c2c66affSColin Finck MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry ); 315c2c66affSColin Finck 316c2c66affSColin Finck list_remove( &patch->entry ); 317c2c66affSColin Finck if (patch->delete_on_close && !DeleteFileW( patch->localfile )) 318c2c66affSColin Finck { 319c2c66affSColin Finck ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError()); 320c2c66affSColin Finck } 321c2c66affSColin Finck msi_free_patchinfo( patch ); 322c2c66affSColin Finck } 323c2c66affSColin Finck 324c2c66affSColin Finck msi_free( package->PackagePath ); 325c2c66affSColin Finck msi_free( package->ProductCode ); 326c2c66affSColin Finck msi_free( package->ActionFormat ); 327c2c66affSColin Finck msi_free( package->LastAction ); 32871bffdcdSAmine Khaldi msi_free( package->LastActionTemplate ); 329c2c66affSColin Finck msi_free( package->langids ); 330c2c66affSColin Finck 331c2c66affSColin Finck /* cleanup control event subscriptions */ 332c2c66affSColin Finck msi_event_cleanup_all_subscriptions( package ); 333c2c66affSColin Finck } 334c2c66affSColin Finck 335c2c66affSColin Finck static void MSI_FreePackage( MSIOBJECTHDR *arg) 336c2c66affSColin Finck { 337c2c66affSColin Finck MSIPACKAGE *package = (MSIPACKAGE *)arg; 338c2c66affSColin Finck 339c2c66affSColin Finck msi_destroy_assembly_caches( package ); 340c2c66affSColin Finck 341c2c66affSColin Finck if( package->dialog ) 342c2c66affSColin Finck msi_dialog_destroy( package->dialog ); 343c2c66affSColin Finck 344c2c66affSColin Finck msiobj_release( &package->db->hdr ); 345c2c66affSColin Finck free_package_structures(package); 346c2c66affSColin Finck CloseHandle( package->log_file ); 347c2c66affSColin Finck 348c2c66affSColin Finck if (package->delete_on_close) DeleteFileW( package->localfile ); 349c2c66affSColin Finck msi_free( package->localfile ); 35071bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 351c2c66affSColin Finck } 352c2c66affSColin Finck 353c2c66affSColin Finck static UINT create_temp_property_table(MSIPACKAGE *package) 354c2c66affSColin Finck { 355c2c66affSColin Finck static const WCHAR query[] = { 356c2c66affSColin Finck 'C','R','E','A','T','E',' ','T','A','B','L','E',' ', 357c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ', 358c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 359c2c66affSColin Finck 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ', 360c2c66affSColin Finck 'T','E','M','P','O','R','A','R','Y',',',' ', 361c2c66affSColin Finck '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ', 362c2c66affSColin Finck 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y', 363c2c66affSColin Finck ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ', 364c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0}; 365c2c66affSColin Finck MSIQUERY *view; 366c2c66affSColin Finck UINT rc; 367c2c66affSColin Finck 368c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(package->db, query, &view); 369c2c66affSColin Finck if (rc != ERROR_SUCCESS) 370c2c66affSColin Finck return rc; 371c2c66affSColin Finck 372c2c66affSColin Finck rc = MSI_ViewExecute(view, 0); 373c2c66affSColin Finck MSI_ViewClose(view); 374c2c66affSColin Finck msiobj_release(&view->hdr); 375c2c66affSColin Finck return rc; 376c2c66affSColin Finck } 377c2c66affSColin Finck 378c2c66affSColin Finck UINT msi_clone_properties( MSIDATABASE *db ) 379c2c66affSColin Finck { 380c2c66affSColin Finck static const WCHAR query_select[] = { 381c2c66affSColin Finck 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 382c2c66affSColin Finck '`','P','r','o','p','e','r','t','y','`',0}; 383c2c66affSColin Finck static const WCHAR query_insert[] = { 384c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 385c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 386c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 387c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 388c2c66affSColin Finck static const WCHAR query_update[] = { 389c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 390c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ', 391c2c66affSColin Finck 'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0}; 392c2c66affSColin Finck MSIQUERY *view_select; 393c2c66affSColin Finck UINT rc; 394c2c66affSColin Finck 395c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_select, &view_select ); 396c2c66affSColin Finck if (rc != ERROR_SUCCESS) 397c2c66affSColin Finck return rc; 398c2c66affSColin Finck 399c2c66affSColin Finck rc = MSI_ViewExecute( view_select, 0 ); 400c2c66affSColin Finck if (rc != ERROR_SUCCESS) 401c2c66affSColin Finck { 402c2c66affSColin Finck MSI_ViewClose( view_select ); 403c2c66affSColin Finck msiobj_release( &view_select->hdr ); 404c2c66affSColin Finck return rc; 405c2c66affSColin Finck } 406c2c66affSColin Finck 407c2c66affSColin Finck while (1) 408c2c66affSColin Finck { 409c2c66affSColin Finck MSIQUERY *view_insert, *view_update; 410c2c66affSColin Finck MSIRECORD *rec_select; 411c2c66affSColin Finck 412c2c66affSColin Finck rc = MSI_ViewFetch( view_select, &rec_select ); 413c2c66affSColin Finck if (rc != ERROR_SUCCESS) 414c2c66affSColin Finck break; 415c2c66affSColin Finck 416c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert ); 417c2c66affSColin Finck if (rc != ERROR_SUCCESS) 418c2c66affSColin Finck { 419c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 420c2c66affSColin Finck continue; 421c2c66affSColin Finck } 422c2c66affSColin Finck 423c2c66affSColin Finck rc = MSI_ViewExecute( view_insert, rec_select ); 424c2c66affSColin Finck MSI_ViewClose( view_insert ); 425c2c66affSColin Finck msiobj_release( &view_insert->hdr ); 426c2c66affSColin Finck if (rc != ERROR_SUCCESS) 427c2c66affSColin Finck { 428c2c66affSColin Finck MSIRECORD *rec_update; 429c2c66affSColin Finck 430c2c66affSColin Finck TRACE("insert failed, trying update\n"); 431c2c66affSColin Finck 432c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_update, &view_update ); 433c2c66affSColin Finck if (rc != ERROR_SUCCESS) 434c2c66affSColin Finck { 435c2c66affSColin Finck WARN("open view failed %u\n", rc); 436c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 437c2c66affSColin Finck continue; 438c2c66affSColin Finck } 439c2c66affSColin Finck 440c2c66affSColin Finck rec_update = MSI_CreateRecord( 2 ); 441c2c66affSColin Finck MSI_RecordCopyField( rec_select, 1, rec_update, 2 ); 442c2c66affSColin Finck MSI_RecordCopyField( rec_select, 2, rec_update, 1 ); 443c2c66affSColin Finck rc = MSI_ViewExecute( view_update, rec_update ); 444c2c66affSColin Finck if (rc != ERROR_SUCCESS) 445c2c66affSColin Finck WARN("update failed %u\n", rc); 446c2c66affSColin Finck 447c2c66affSColin Finck MSI_ViewClose( view_update ); 448c2c66affSColin Finck msiobj_release( &view_update->hdr ); 449c2c66affSColin Finck msiobj_release( &rec_update->hdr ); 450c2c66affSColin Finck } 451c2c66affSColin Finck 452c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 453c2c66affSColin Finck } 454c2c66affSColin Finck 455c2c66affSColin Finck MSI_ViewClose( view_select ); 456c2c66affSColin Finck msiobj_release( &view_select->hdr ); 457c2c66affSColin Finck return rc; 458c2c66affSColin Finck } 459c2c66affSColin Finck 460c2c66affSColin Finck /* 461c2c66affSColin Finck * set_installed_prop 462c2c66affSColin Finck * 463c2c66affSColin Finck * Sets the "Installed" property to indicate that 464c2c66affSColin Finck * the product is installed for the current user. 465c2c66affSColin Finck */ 466c2c66affSColin Finck static UINT set_installed_prop( MSIPACKAGE *package ) 467c2c66affSColin Finck { 468c2c66affSColin Finck HKEY hkey; 469c2c66affSColin Finck UINT r; 470c2c66affSColin Finck 471c2c66affSColin Finck if (!package->ProductCode) return ERROR_FUNCTION_FAILED; 472c2c66affSColin Finck 473c2c66affSColin Finck r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE ); 474c2c66affSColin Finck if (r == ERROR_SUCCESS) 475c2c66affSColin Finck { 476c2c66affSColin Finck RegCloseKey( hkey ); 477c2c66affSColin Finck msi_set_property( package->db, szInstalled, szOne, -1 ); 478c2c66affSColin Finck } 479c2c66affSColin Finck return r; 480c2c66affSColin Finck } 481c2c66affSColin Finck 482c2c66affSColin Finck static UINT set_user_sid_prop( MSIPACKAGE *package ) 483c2c66affSColin Finck { 484c2c66affSColin Finck SID_NAME_USE use; 485c2c66affSColin Finck LPWSTR user_name; 486c2c66affSColin Finck LPWSTR sid_str = NULL, dom = NULL; 487c2c66affSColin Finck DWORD size, dom_size; 488c2c66affSColin Finck PSID psid = NULL; 489c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 490c2c66affSColin Finck 491c2c66affSColin Finck size = 0; 492c2c66affSColin Finck GetUserNameW( NULL, &size ); 493c2c66affSColin Finck 494c2c66affSColin Finck user_name = msi_alloc( (size + 1) * sizeof(WCHAR) ); 495c2c66affSColin Finck if (!user_name) 496c2c66affSColin Finck return ERROR_OUTOFMEMORY; 497c2c66affSColin Finck 498c2c66affSColin Finck if (!GetUserNameW( user_name, &size )) 499c2c66affSColin Finck goto done; 500c2c66affSColin Finck 501c2c66affSColin Finck size = 0; 502c2c66affSColin Finck dom_size = 0; 503c2c66affSColin Finck LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use ); 504c2c66affSColin Finck 505c2c66affSColin Finck psid = msi_alloc( size ); 506c2c66affSColin Finck dom = msi_alloc( dom_size*sizeof (WCHAR) ); 507c2c66affSColin Finck if (!psid || !dom) 508c2c66affSColin Finck { 509c2c66affSColin Finck r = ERROR_OUTOFMEMORY; 510c2c66affSColin Finck goto done; 511c2c66affSColin Finck } 512c2c66affSColin Finck 513c2c66affSColin Finck if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use )) 514c2c66affSColin Finck goto done; 515c2c66affSColin Finck 516c2c66affSColin Finck if (!ConvertSidToStringSidW( psid, &sid_str )) 517c2c66affSColin Finck goto done; 518c2c66affSColin Finck 519c2c66affSColin Finck r = msi_set_property( package->db, szUserSID, sid_str, -1 ); 520c2c66affSColin Finck 521c2c66affSColin Finck done: 522c2c66affSColin Finck LocalFree( sid_str ); 523c2c66affSColin Finck msi_free( dom ); 524c2c66affSColin Finck msi_free( psid ); 525c2c66affSColin Finck msi_free( user_name ); 526c2c66affSColin Finck 527c2c66affSColin Finck return r; 528c2c66affSColin Finck } 529c2c66affSColin Finck 530c2c66affSColin Finck static LPWSTR get_fusion_filename(MSIPACKAGE *package) 531c2c66affSColin Finck { 532c42b133eSAmine Khaldi static const WCHAR fusion[] = 533c42b133eSAmine Khaldi {'f','u','s','i','o','n','.','d','l','l',0}; 534c42b133eSAmine Khaldi static const WCHAR subkey[] = 535c42b133eSAmine Khaldi {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 536c42b133eSAmine Khaldi 'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\','N','D','P',0}; 537c42b133eSAmine Khaldi static const WCHAR subdir[] = 538c42b133eSAmine Khaldi {'M','i','c','r','o','s','o','f','t','.','N','E','T','\\','F','r','a','m','e','w','o','r','k','\\',0}; 539c42b133eSAmine Khaldi static const WCHAR v2050727[] = 540c42b133eSAmine Khaldi {'v','2','.','0','.','5','0','7','2','7',0}; 541c42b133eSAmine Khaldi static const WCHAR v4client[] = 542c42b133eSAmine Khaldi {'v','4','\\','C','l','i','e','n','t',0}; 543c42b133eSAmine Khaldi static const WCHAR installpath[] = 544c42b133eSAmine Khaldi {'I','n','s','t','a','l','l','P','a','t','h',0}; 545c42b133eSAmine Khaldi HKEY netsetup, hkey; 546c2c66affSColin Finck LONG res; 547c42b133eSAmine Khaldi DWORD size, len, type; 548c42b133eSAmine Khaldi WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL; 549c2c66affSColin Finck 550c42b133eSAmine Khaldi res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, subkey, 0, KEY_CREATE_SUB_KEY, &netsetup); 551c2c66affSColin Finck if (res != ERROR_SUCCESS) 552c2c66affSColin Finck return NULL; 553c2c66affSColin Finck 554c42b133eSAmine Khaldi if (!RegCreateKeyExW(netsetup, v4client, 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 555c42b133eSAmine Khaldi { 556c42b133eSAmine Khaldi size = sizeof(path)/sizeof(path[0]); 557c42b133eSAmine Khaldi if (!RegQueryValueExW(hkey, installpath, NULL, &type, (BYTE *)path, &size)) 558c42b133eSAmine Khaldi { 559c42b133eSAmine Khaldi len = strlenW(path) + strlenW(fusion) + 2; 560c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 561c42b133eSAmine Khaldi 562c42b133eSAmine Khaldi strcpyW(filename, path); 563c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 564c42b133eSAmine Khaldi strcatW(filename, fusion); 565c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 566c42b133eSAmine Khaldi { 567c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 568c42b133eSAmine Khaldi RegCloseKey(hkey); 569c42b133eSAmine Khaldi RegCloseKey(netsetup); 570c42b133eSAmine Khaldi return filename; 571c42b133eSAmine Khaldi } 572c42b133eSAmine Khaldi } 573c42b133eSAmine Khaldi RegCloseKey(hkey); 574c42b133eSAmine Khaldi } 575c42b133eSAmine Khaldi 576c42b133eSAmine Khaldi if (!RegCreateKeyExW(netsetup, v2050727, 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 577c42b133eSAmine Khaldi { 578c42b133eSAmine Khaldi RegCloseKey(hkey); 579c2c66affSColin Finck GetWindowsDirectoryW(windir, MAX_PATH); 580c42b133eSAmine Khaldi len = strlenW(windir) + strlenW(subdir) + strlenW(v2050727) + strlenW(fusion) + 3; 581c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 582c2c66affSColin Finck 583c42b133eSAmine Khaldi strcpyW(filename, windir); 584c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 585c42b133eSAmine Khaldi strcatW(filename, subdir); 586c42b133eSAmine Khaldi strcatW(filename, v2050727); 587c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 588c42b133eSAmine Khaldi strcatW(filename, fusion); 589c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 590c2c66affSColin Finck { 591c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 592c42b133eSAmine Khaldi RegCloseKey(netsetup); 593c42b133eSAmine Khaldi return filename; 594c2c66affSColin Finck } 595c2c66affSColin Finck } 596c2c66affSColin Finck 597c2c66affSColin Finck RegCloseKey(netsetup); 598c42b133eSAmine Khaldi return filename; 599c2c66affSColin Finck } 600c2c66affSColin Finck 601c2c66affSColin Finck typedef struct tagLANGANDCODEPAGE 602c2c66affSColin Finck { 603c2c66affSColin Finck WORD wLanguage; 604c2c66affSColin Finck WORD wCodePage; 605c2c66affSColin Finck } LANGANDCODEPAGE; 606c2c66affSColin Finck 607c2c66affSColin Finck static void set_msi_assembly_prop(MSIPACKAGE *package) 608c2c66affSColin Finck { 609c2c66affSColin Finck UINT val_len; 610c2c66affSColin Finck DWORD size, handle; 611c2c66affSColin Finck LPVOID version = NULL; 612c2c66affSColin Finck WCHAR buf[MAX_PATH]; 613c2c66affSColin Finck LPWSTR fusion, verstr; 614c2c66affSColin Finck LANGANDCODEPAGE *translate; 615c2c66affSColin Finck 616c2c66affSColin Finck static const WCHAR netasm[] = { 617c2c66affSColin Finck 'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0 618c2c66affSColin Finck }; 619c2c66affSColin Finck static const WCHAR translation[] = { 620c2c66affSColin Finck '\\','V','a','r','F','i','l','e','I','n','f','o', 621c2c66affSColin Finck '\\','T','r','a','n','s','l','a','t','i','o','n',0 622c2c66affSColin Finck }; 623c2c66affSColin Finck static const WCHAR verfmt[] = { 624c2c66affSColin Finck '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o', 625c2c66affSColin Finck '\\','%','0','4','x','%','0','4','x', 626c2c66affSColin Finck '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 627c2c66affSColin Finck }; 628c2c66affSColin Finck 629c2c66affSColin Finck fusion = get_fusion_filename(package); 630c2c66affSColin Finck if (!fusion) 631c2c66affSColin Finck return; 632c2c66affSColin Finck 633c2c66affSColin Finck size = GetFileVersionInfoSizeW(fusion, &handle); 634c2c66affSColin Finck if (!size) 635c2c66affSColin Finck goto done; 636c2c66affSColin Finck 637c2c66affSColin Finck version = msi_alloc(size); 638c2c66affSColin Finck if (!version) 639c2c66affSColin Finck goto done; 640c2c66affSColin Finck 641c2c66affSColin Finck if (!GetFileVersionInfoW(fusion, handle, size, version)) 642c2c66affSColin Finck goto done; 643c2c66affSColin Finck 644c2c66affSColin Finck if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len)) 645c2c66affSColin Finck goto done; 646c2c66affSColin Finck 647c2c66affSColin Finck sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage); 648c2c66affSColin Finck 649c2c66affSColin Finck if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len)) 650c2c66affSColin Finck goto done; 651c2c66affSColin Finck 652c2c66affSColin Finck if (!val_len || !verstr) 653c2c66affSColin Finck goto done; 654c2c66affSColin Finck 655c2c66affSColin Finck msi_set_property( package->db, netasm, verstr, -1 ); 656c2c66affSColin Finck 657c2c66affSColin Finck done: 658c2c66affSColin Finck msi_free(fusion); 659c2c66affSColin Finck msi_free(version); 660c2c66affSColin Finck } 661c2c66affSColin Finck 662c2c66affSColin Finck static VOID set_installer_properties(MSIPACKAGE *package) 663c2c66affSColin Finck { 664c2c66affSColin Finck WCHAR *ptr; 665c2c66affSColin Finck OSVERSIONINFOEXW OSVersion; 666c2c66affSColin Finck MEMORYSTATUSEX msex; 667c2c66affSColin Finck DWORD verval, len; 668c2c66affSColin Finck WCHAR pth[MAX_PATH], verstr[11], bufstr[22]; 669c2c66affSColin Finck HDC dc; 670c2c66affSColin Finck HKEY hkey; 671c2c66affSColin Finck LPWSTR username, companyname; 672c2c66affSColin Finck SYSTEM_INFO sys_info; 673c2c66affSColin Finck LANGID langid; 674c2c66affSColin Finck 675c2c66affSColin Finck static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0}; 676c2c66affSColin Finck static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0}; 677c2c66affSColin Finck static const WCHAR szCommonAppDataFolder[] = {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; 678c2c66affSColin Finck static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0}; 679c2c66affSColin Finck static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0}; 680c2c66affSColin Finck static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0}; 681c2c66affSColin Finck static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0}; 682c2c66affSColin Finck static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0}; 683c2c66affSColin Finck static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0}; 684c2c66affSColin Finck static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0}; 685c2c66affSColin Finck static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0}; 686c2c66affSColin Finck static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0}; 687c2c66affSColin Finck static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0}; 688c2c66affSColin Finck static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0}; 689c2c66affSColin Finck static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; 690c2c66affSColin Finck static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0}; 691c2c66affSColin Finck static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0}; 692c2c66affSColin Finck static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0}; 693c2c66affSColin Finck static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0}; 694c2c66affSColin Finck static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0}; 695c2c66affSColin Finck static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0}; 696c2c66affSColin Finck static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0}; 697c2c66affSColin Finck static const WCHAR szFormat[] = {'%','u',0}; 698c2c66affSColin Finck static const WCHAR szFormat2[] = {'%','u','.','%','u',0}; 699c2c66affSColin Finck static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0}; 700c2c66affSColin Finck static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0}; 701c2c66affSColin Finck static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 }; 702c2c66affSColin Finck static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 }; 703c2c66affSColin Finck static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 }; 704c2c66affSColin Finck static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0}; 705c2c66affSColin Finck static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0}; 706c2c66affSColin Finck static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0}; 707c2c66affSColin Finck static const WCHAR szIntFormat[] = {'%','d',0}; 708c2c66affSColin Finck static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 }; 709c2c66affSColin Finck static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 }; 710c2c66affSColin Finck static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 }; 711c2c66affSColin Finck static const WCHAR szCommonFiles64Folder[] = { 'C','o','m','m','o','n','F','i','l','e','s','6','4','F','o','l','d','e','r',0 }; 712c2c66affSColin Finck static const WCHAR szProgramFiles64Folder[] = { 'P','r','o','g','r','a','m','F','i','l','e','s','6','4','F','o','l','d','e','r',0 }; 713c2c66affSColin Finck static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 }; 714c2c66affSColin Finck static const WCHAR szUserInfo[] = { 715c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 716c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 717c2c66affSColin Finck 'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\', 718c2c66affSColin Finck 'U','s','e','r',' ','I','n','f','o',0 719c2c66affSColin Finck }; 720c2c66affSColin Finck static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 }; 721c2c66affSColin Finck static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 }; 722c2c66affSColin Finck static const WCHAR szCurrentVersion[] = { 723c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 724c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 725c2c66affSColin Finck 'W','i','n','d','o','w','s',' ','N','T','\\', 726c2c66affSColin Finck 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0 727c2c66affSColin Finck }; 728c2c66affSColin Finck static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0}; 729c2c66affSColin Finck static const WCHAR szRegisteredOrganization[] = { 730c2c66affSColin Finck 'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0 731c2c66affSColin Finck }; 732c2c66affSColin Finck static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0}; 733c2c66affSColin Finck static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0}; 734c2c66affSColin Finck static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0}; 735c2c66affSColin Finck static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0}; 736c2c66affSColin Finck static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0}; 737c2c66affSColin Finck static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0}; 738c2c66affSColin Finck static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0}; 739c2c66affSColin Finck static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0}; 740c2c66affSColin Finck static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0}; 741c2c66affSColin Finck static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0}; 742c2c66affSColin Finck 743c2c66affSColin Finck /* 744c2c66affSColin Finck * Other things that probably should be set: 745c2c66affSColin Finck * 746c2c66affSColin Finck * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging 747c2c66affSColin Finck * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport 748c2c66affSColin Finck */ 749c2c66affSColin Finck 750c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); 751c2c66affSColin Finck strcatW(pth, szBackSlash); 752c2c66affSColin Finck msi_set_property( package->db, szCommonAppDataFolder, pth, -1 ); 753c2c66affSColin Finck 754c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); 755c2c66affSColin Finck strcatW(pth, szBackSlash); 756c2c66affSColin Finck msi_set_property( package->db, szFavoritesFolder, pth, -1 ); 757c2c66affSColin Finck 758c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); 759c2c66affSColin Finck strcatW(pth, szBackSlash); 760c2c66affSColin Finck msi_set_property( package->db, szFontsFolder, pth, -1 ); 761c2c66affSColin Finck 762c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); 763c2c66affSColin Finck strcatW(pth, szBackSlash); 764c2c66affSColin Finck msi_set_property( package->db, szSendToFolder, pth, -1 ); 765c2c66affSColin Finck 766c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); 767c2c66affSColin Finck strcatW(pth, szBackSlash); 768c2c66affSColin Finck msi_set_property( package->db, szStartMenuFolder, pth, -1 ); 769c2c66affSColin Finck 770c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); 771c2c66affSColin Finck strcatW(pth, szBackSlash); 772c2c66affSColin Finck msi_set_property( package->db, szStartupFolder, pth, -1 ); 773c2c66affSColin Finck 774c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); 775c2c66affSColin Finck strcatW(pth, szBackSlash); 776c2c66affSColin Finck msi_set_property( package->db, szTemplateFolder, pth, -1 ); 777c2c66affSColin Finck 778c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); 779c2c66affSColin Finck strcatW(pth, szBackSlash); 780c2c66affSColin Finck msi_set_property( package->db, szDesktopFolder, pth, -1 ); 781c2c66affSColin Finck 782c2c66affSColin Finck /* FIXME: set to AllUsers profile path if ALLUSERS is set */ 783c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); 784c2c66affSColin Finck strcatW(pth, szBackSlash); 785c2c66affSColin Finck msi_set_property( package->db, szProgramMenuFolder, pth, -1 ); 786c2c66affSColin Finck 787c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); 788c2c66affSColin Finck strcatW(pth, szBackSlash); 789c2c66affSColin Finck msi_set_property( package->db, szAdminToolsFolder, pth, -1 ); 790c2c66affSColin Finck 791c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); 792c2c66affSColin Finck strcatW(pth, szBackSlash); 793c2c66affSColin Finck msi_set_property( package->db, szAppDataFolder, pth, -1 ); 794c2c66affSColin Finck 795c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); 796c2c66affSColin Finck strcatW(pth, szBackSlash); 797c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 798c2c66affSColin Finck msi_set_property( package->db, szSystem16Folder, pth, -1 ); 799c2c66affSColin Finck 800c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); 801c2c66affSColin Finck strcatW(pth, szBackSlash); 802c2c66affSColin Finck msi_set_property( package->db, szLocalAppDataFolder, pth, -1 ); 803c2c66affSColin Finck 804c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); 805c2c66affSColin Finck strcatW(pth, szBackSlash); 806c2c66affSColin Finck msi_set_property( package->db, szMyPicturesFolder, pth, -1 ); 807c2c66affSColin Finck 808c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); 809c2c66affSColin Finck strcatW(pth, szBackSlash); 810c2c66affSColin Finck msi_set_property( package->db, szPersonalFolder, pth, -1 ); 811c2c66affSColin Finck 812c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 813c2c66affSColin Finck strcatW(pth, szBackSlash); 814c2c66affSColin Finck msi_set_property( package->db, szWindowsFolder, pth, -1 ); 815c2c66affSColin Finck 816c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); 817c2c66affSColin Finck strcatW(pth, szBackSlash); 818c2c66affSColin Finck msi_set_property( package->db, szPrintHoodFolder, pth, -1 ); 819c2c66affSColin Finck 820c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); 821c2c66affSColin Finck strcatW(pth, szBackSlash); 822c2c66affSColin Finck msi_set_property( package->db, szNetHoodFolder, pth, -1 ); 823c2c66affSColin Finck 824c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); 825c2c66affSColin Finck strcatW(pth, szBackSlash); 826c2c66affSColin Finck msi_set_property( package->db, szRecentFolder, pth, -1 ); 827c2c66affSColin Finck 828c2c66affSColin Finck /* Physical Memory is specified in MB. Using total amount. */ 829c2c66affSColin Finck msex.dwLength = sizeof(msex); 830c2c66affSColin Finck GlobalMemoryStatusEx( &msex ); 831c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); 832c2c66affSColin Finck msi_set_property( package->db, szPhysicalMemory, bufstr, len ); 833c2c66affSColin Finck 834c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 835c2c66affSColin Finck ptr = strchrW(pth,'\\'); 836c2c66affSColin Finck if (ptr) *(ptr + 1) = 0; 837c2c66affSColin Finck msi_set_property( package->db, szWindowsVolume, pth, -1 ); 838c2c66affSColin Finck 839c2c66affSColin Finck len = GetTempPathW(MAX_PATH, pth); 840c2c66affSColin Finck msi_set_property( package->db, szTempFolder, pth, len ); 841c2c66affSColin Finck 842c2c66affSColin Finck /* in a wine environment the user is always admin and privileged */ 843c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 844c2c66affSColin Finck msi_set_property( package->db, szPrivileged, szOne, -1 ); 845c2c66affSColin Finck 846c2c66affSColin Finck /* set the os things */ 847c2c66affSColin Finck OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); 848c2c66affSColin Finck GetVersionExW((OSVERSIONINFOW *)&OSVersion); 849c2c66affSColin Finck verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; 850c2c66affSColin Finck len = sprintfW( verstr, szFormat, verval ); 851c2c66affSColin Finck switch (OSVersion.dwPlatformId) 852c2c66affSColin Finck { 853c2c66affSColin Finck case VER_PLATFORM_WIN32_WINDOWS: 854c2c66affSColin Finck msi_set_property( package->db, szVersion9x, verstr, len ); 855c2c66affSColin Finck break; 856c2c66affSColin Finck case VER_PLATFORM_WIN32_NT: 857c2c66affSColin Finck msi_set_property( package->db, szVersionNT, verstr, len ); 858c2c66affSColin Finck len = sprintfW( bufstr, szFormat,OSVersion.wProductType ); 859c2c66affSColin Finck msi_set_property( package->db, szMsiNTProductType, bufstr, len ); 860c2c66affSColin Finck break; 861c2c66affSColin Finck } 862c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber ); 863c2c66affSColin Finck msi_set_property( package->db, szWindowsBuild, bufstr, len ); 864c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor ); 865c2c66affSColin Finck msi_set_property( package->db, szServicePackLevel, bufstr, len ); 866c2c66affSColin Finck 867c2c66affSColin Finck len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION ); 868c2c66affSColin Finck msi_set_property( package->db, szVersionMsi, bufstr, len ); 869c2c66affSColin Finck len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 ); 870c2c66affSColin Finck msi_set_property( package->db, szVersionDatabase, bufstr, len ); 871c2c66affSColin Finck 872c2c66affSColin Finck GetNativeSystemInfo( &sys_info ); 873c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); 874c2c66affSColin Finck msi_set_property( package->db, szIntel, bufstr, len ); 875c2c66affSColin Finck if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 876c2c66affSColin Finck { 877c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 878c2c66affSColin Finck PathAddBackslashW( pth ); 879c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 880c2c66affSColin Finck 881c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 882c2c66affSColin Finck PathAddBackslashW( pth ); 883c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 884c2c66affSColin Finck 885c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 886c2c66affSColin Finck PathAddBackslashW( pth ); 887c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 888c2c66affSColin Finck } 889c2c66affSColin Finck else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 890c2c66affSColin Finck { 891c2c66affSColin Finck msi_set_property( package->db, szMsiAMD64, bufstr, -1 ); 892c2c66affSColin Finck msi_set_property( package->db, szMsix64, bufstr, -1 ); 893c2c66affSColin Finck msi_set_property( package->db, szVersionNT64, verstr, -1 ); 894c2c66affSColin Finck 895c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 896c2c66affSColin Finck PathAddBackslashW( pth ); 897c2c66affSColin Finck msi_set_property( package->db, szSystem64Folder, pth, -1 ); 898c2c66affSColin Finck 899c2c66affSColin Finck GetSystemWow64DirectoryW( pth, MAX_PATH ); 900c2c66affSColin Finck PathAddBackslashW( pth ); 901c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 902c2c66affSColin Finck 903c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 904c2c66affSColin Finck PathAddBackslashW( pth ); 905c2c66affSColin Finck msi_set_property( package->db, szProgramFiles64Folder, pth, -1 ); 906c2c66affSColin Finck 907c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth ); 908c2c66affSColin Finck PathAddBackslashW( pth ); 909c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 910c2c66affSColin Finck 911c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 912c2c66affSColin Finck PathAddBackslashW( pth ); 913c2c66affSColin Finck msi_set_property( package->db, szCommonFiles64Folder, pth, -1 ); 914c2c66affSColin Finck 915c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth ); 916c2c66affSColin Finck PathAddBackslashW( pth ); 917c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 918c2c66affSColin Finck } 919c2c66affSColin Finck 920c2c66affSColin Finck /* Screen properties. */ 921c2c66affSColin Finck dc = GetDC(0); 922c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) ); 923c2c66affSColin Finck msi_set_property( package->db, szScreenX, bufstr, len ); 924c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) ); 925c2c66affSColin Finck msi_set_property( package->db, szScreenY, bufstr, len ); 926c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) ); 927c2c66affSColin Finck msi_set_property( package->db, szColorBits, bufstr, len ); 928c2c66affSColin Finck ReleaseDC(0, dc); 929c2c66affSColin Finck 930c2c66affSColin Finck /* USERNAME and COMPANYNAME */ 931c2c66affSColin Finck username = msi_dup_property( package->db, szUSERNAME ); 932c2c66affSColin Finck companyname = msi_dup_property( package->db, szCOMPANYNAME ); 933c2c66affSColin Finck 934c2c66affSColin Finck if ((!username || !companyname) && 935c2c66affSColin Finck RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS) 936c2c66affSColin Finck { 937c2c66affSColin Finck if (!username && 938c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szDefName ))) 939c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 940c2c66affSColin Finck if (!companyname && 941c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szDefCompany ))) 942c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 943c2c66affSColin Finck CloseHandle( hkey ); 944c2c66affSColin Finck } 945c2c66affSColin Finck if ((!username || !companyname) && 946c2c66affSColin Finck RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS) 947c2c66affSColin Finck { 948c2c66affSColin Finck if (!username && 949c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szRegisteredUser ))) 950c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 951c2c66affSColin Finck if (!companyname && 952c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization ))) 953c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 954c2c66affSColin Finck CloseHandle( hkey ); 955c2c66affSColin Finck } 956c2c66affSColin Finck msi_free( username ); 957c2c66affSColin Finck msi_free( companyname ); 958c2c66affSColin Finck 959c2c66affSColin Finck if ( set_user_sid_prop( package ) != ERROR_SUCCESS) 960c2c66affSColin Finck ERR("Failed to set the UserSID property\n"); 961c2c66affSColin Finck 962c2c66affSColin Finck set_msi_assembly_prop( package ); 963c2c66affSColin Finck 964c2c66affSColin Finck langid = GetUserDefaultLangID(); 965c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 966c2c66affSColin Finck msi_set_property( package->db, szUserLanguageID, bufstr, len ); 967c2c66affSColin Finck 968c2c66affSColin Finck langid = GetSystemDefaultLangID(); 969c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 970c2c66affSColin Finck msi_set_property( package->db, szSystemLangID, bufstr, len ); 971c2c66affSColin Finck 972c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) ); 973c2c66affSColin Finck msi_set_property( package->db, szProductState, bufstr, len ); 974c2c66affSColin Finck 975c2c66affSColin Finck len = 0; 976c2c66affSColin Finck if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 977c2c66affSColin Finck { 978c2c66affSColin Finck WCHAR *username; 979c2c66affSColin Finck if ((username = msi_alloc( len * sizeof(WCHAR) ))) 980c2c66affSColin Finck { 981c2c66affSColin Finck if (GetUserNameW( username, &len )) 982c2c66affSColin Finck msi_set_property( package->db, szLogonUser, username, len - 1 ); 983c2c66affSColin Finck msi_free( username ); 984c2c66affSColin Finck } 985c2c66affSColin Finck } 986c2c66affSColin Finck len = 0; 987c2c66affSColin Finck if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW) 988c2c66affSColin Finck { 989c2c66affSColin Finck WCHAR *computername; 990c2c66affSColin Finck if ((computername = msi_alloc( len * sizeof(WCHAR) ))) 991c2c66affSColin Finck { 992c2c66affSColin Finck if (GetComputerNameW( computername, &len )) 993c2c66affSColin Finck msi_set_property( package->db, szComputerName, computername, len ); 994c2c66affSColin Finck msi_free( computername ); 995c2c66affSColin Finck } 996c2c66affSColin Finck } 997c2c66affSColin Finck } 998c2c66affSColin Finck 999c2c66affSColin Finck static MSIPACKAGE *msi_alloc_package( void ) 1000c2c66affSColin Finck { 1001c2c66affSColin Finck MSIPACKAGE *package; 1002c2c66affSColin Finck 1003c2c66affSColin Finck package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), 1004c2c66affSColin Finck MSI_FreePackage ); 1005c2c66affSColin Finck if( package ) 1006c2c66affSColin Finck { 1007c2c66affSColin Finck list_init( &package->components ); 1008c2c66affSColin Finck list_init( &package->features ); 1009c2c66affSColin Finck list_init( &package->files ); 1010c2c66affSColin Finck list_init( &package->filepatches ); 1011c2c66affSColin Finck list_init( &package->tempfiles ); 1012c2c66affSColin Finck list_init( &package->folders ); 1013c2c66affSColin Finck list_init( &package->subscriptions ); 1014c2c66affSColin Finck list_init( &package->appids ); 1015c2c66affSColin Finck list_init( &package->classes ); 1016c2c66affSColin Finck list_init( &package->mimes ); 1017c2c66affSColin Finck list_init( &package->extensions ); 1018c2c66affSColin Finck list_init( &package->progids ); 1019c2c66affSColin Finck list_init( &package->RunningActions ); 1020c2c66affSColin Finck list_init( &package->sourcelist_info ); 1021c2c66affSColin Finck list_init( &package->sourcelist_media ); 1022c2c66affSColin Finck list_init( &package->patches ); 1023c2c66affSColin Finck list_init( &package->binaries ); 1024c2c66affSColin Finck list_init( &package->cabinet_streams ); 1025c2c66affSColin Finck } 1026c2c66affSColin Finck 1027c2c66affSColin Finck return package; 1028c2c66affSColin Finck } 1029c2c66affSColin Finck 1030c2c66affSColin Finck static UINT msi_load_admin_properties(MSIPACKAGE *package) 1031c2c66affSColin Finck { 1032c2c66affSColin Finck BYTE *data; 1033c2c66affSColin Finck UINT r, sz; 1034c2c66affSColin Finck 1035c2c66affSColin Finck static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0}; 1036c2c66affSColin Finck 1037c2c66affSColin Finck r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz); 1038c2c66affSColin Finck if (r != ERROR_SUCCESS) 1039c2c66affSColin Finck return r; 1040c2c66affSColin Finck 1041c2c66affSColin Finck r = msi_parse_command_line(package, (WCHAR *)data, TRUE); 1042c2c66affSColin Finck 1043c2c66affSColin Finck msi_free(data); 1044c2c66affSColin Finck return r; 1045c2c66affSColin Finck } 1046c2c66affSColin Finck 1047c2c66affSColin Finck void msi_adjust_privilege_properties( MSIPACKAGE *package ) 1048c2c66affSColin Finck { 1049c2c66affSColin Finck /* FIXME: this should depend on the user's privileges */ 1050c2c66affSColin Finck if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2) 1051c2c66affSColin Finck { 1052c2c66affSColin Finck TRACE("resetting ALLUSERS property from 2 to 1\n"); 1053c2c66affSColin Finck msi_set_property( package->db, szAllUsers, szOne, -1 ); 1054c2c66affSColin Finck } 1055c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 1056c2c66affSColin Finck } 1057c2c66affSColin Finck 105834c2011cSwinesync MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db ) 1059c2c66affSColin Finck { 1060c2c66affSColin Finck static const WCHAR fmtW[] = {'%','u',0}; 1061c2c66affSColin Finck MSIPACKAGE *package; 1062c2c66affSColin Finck WCHAR uilevel[11]; 1063c2c66affSColin Finck int len; 1064c2c66affSColin Finck UINT r; 1065c2c66affSColin Finck 1066c2c66affSColin Finck TRACE("%p\n", db); 1067c2c66affSColin Finck 1068c2c66affSColin Finck package = msi_alloc_package(); 1069c2c66affSColin Finck if (package) 1070c2c66affSColin Finck { 1071c2c66affSColin Finck msiobj_addref( &db->hdr ); 1072c2c66affSColin Finck package->db = db; 1073c2c66affSColin Finck 107471bffdcdSAmine Khaldi package->LastAction = NULL; 107571bffdcdSAmine Khaldi package->LastActionTemplate = NULL; 107671bffdcdSAmine Khaldi package->LastActionResult = MSI_NULL_INTEGER; 1077c2c66affSColin Finck package->WordCount = 0; 1078c2c66affSColin Finck package->PackagePath = strdupW( db->path ); 1079c2c66affSColin Finck 1080c2c66affSColin Finck create_temp_property_table( package ); 1081c2c66affSColin Finck msi_clone_properties( package->db ); 1082c2c66affSColin Finck msi_adjust_privilege_properties( package ); 1083c2c66affSColin Finck 1084c2c66affSColin Finck package->ProductCode = msi_dup_property( package->db, szProductCode ); 1085c2c66affSColin Finck 1086c2c66affSColin Finck set_installer_properties( package ); 1087c2c66affSColin Finck 1088c2c66affSColin Finck package->ui_level = gUILevel; 1089c2c66affSColin Finck len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); 1090c2c66affSColin Finck msi_set_property( package->db, szUILevel, uilevel, len ); 1091c2c66affSColin Finck 1092c2c66affSColin Finck r = msi_load_suminfo_properties( package ); 1093c2c66affSColin Finck if (r != ERROR_SUCCESS) 1094c2c66affSColin Finck { 1095c2c66affSColin Finck msiobj_release( &package->hdr ); 1096c2c66affSColin Finck return NULL; 1097c2c66affSColin Finck } 1098c2c66affSColin Finck 1099c2c66affSColin Finck if (package->WordCount & msidbSumInfoSourceTypeAdminImage) 1100c2c66affSColin Finck msi_load_admin_properties( package ); 1101c2c66affSColin Finck 1102c2c66affSColin Finck package->log_file = INVALID_HANDLE_VALUE; 1103c2c66affSColin Finck } 1104c2c66affSColin Finck return package; 1105c2c66affSColin Finck } 1106c2c66affSColin Finck 1107c2c66affSColin Finck UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) 1108c2c66affSColin Finck { 1109c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW cache_entry; 1110c2c66affSColin Finck DWORD size = 0; 1111c2c66affSColin Finck HRESULT hr; 1112c2c66affSColin Finck 1113c2c66affSColin Finck /* call will always fail, because size is 0, 1114c2c66affSColin Finck * but will return ERROR_FILE_NOT_FOUND first 1115c2c66affSColin Finck * if the file doesn't exist 1116c2c66affSColin Finck */ 1117c2c66affSColin Finck GetUrlCacheEntryInfoW( szUrl, NULL, &size ); 1118c2c66affSColin Finck if ( GetLastError() != ERROR_FILE_NOT_FOUND ) 1119c2c66affSColin Finck { 1120c2c66affSColin Finck cache_entry = msi_alloc( size ); 1121c2c66affSColin Finck if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) 1122c2c66affSColin Finck { 1123c2c66affSColin Finck UINT error = GetLastError(); 1124c2c66affSColin Finck msi_free( cache_entry ); 1125c2c66affSColin Finck return error; 1126c2c66affSColin Finck } 1127c2c66affSColin Finck 1128c2c66affSColin Finck lstrcpyW( filename, cache_entry->lpszLocalFileName ); 1129c2c66affSColin Finck msi_free( cache_entry ); 1130c2c66affSColin Finck return ERROR_SUCCESS; 1131c2c66affSColin Finck } 1132c2c66affSColin Finck 1133c2c66affSColin Finck hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); 1134c2c66affSColin Finck if ( FAILED(hr) ) 1135c2c66affSColin Finck { 1136c2c66affSColin Finck WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); 1137c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1138c2c66affSColin Finck } 1139c2c66affSColin Finck 1140c2c66affSColin Finck return ERROR_SUCCESS; 1141c2c66affSColin Finck } 1142c2c66affSColin Finck 1143c2c66affSColin Finck UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) 1144c2c66affSColin Finck { 1145c2c66affSColin Finck static const WCHAR szInstaller[] = { 1146c2c66affSColin Finck '\\','I','n','s','t','a','l','l','e','r','\\',0}; 1147c2c66affSColin Finck static const WCHAR fmt[] = {'%','x',0}; 1148c2c66affSColin Finck DWORD time, len, i, offset; 1149c2c66affSColin Finck HANDLE handle; 1150c2c66affSColin Finck 1151c2c66affSColin Finck time = GetTickCount(); 1152c2c66affSColin Finck GetWindowsDirectoryW( path, MAX_PATH ); 1153c2c66affSColin Finck strcatW( path, szInstaller ); 1154c2c66affSColin Finck CreateDirectoryW( path, NULL ); 1155c2c66affSColin Finck 1156c2c66affSColin Finck len = strlenW(path); 1157c2c66affSColin Finck for (i = 0; i < 0x10000; i++) 1158c2c66affSColin Finck { 1159c2c66affSColin Finck offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff ); 1160c2c66affSColin Finck memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) ); 1161c2c66affSColin Finck handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, 1162c2c66affSColin Finck CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); 1163c2c66affSColin Finck if (handle != INVALID_HANDLE_VALUE) 1164c2c66affSColin Finck { 1165c2c66affSColin Finck CloseHandle(handle); 1166c2c66affSColin Finck break; 1167c2c66affSColin Finck } 1168c2c66affSColin Finck if (GetLastError() != ERROR_FILE_EXISTS && 1169c2c66affSColin Finck GetLastError() != ERROR_SHARING_VIOLATION) 1170c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1171c2c66affSColin Finck } 1172c2c66affSColin Finck 1173c2c66affSColin Finck return ERROR_SUCCESS; 1174c2c66affSColin Finck } 1175c2c66affSColin Finck 1176c2c66affSColin Finck static enum platform parse_platform( const WCHAR *str ) 1177c2c66affSColin Finck { 1178c2c66affSColin Finck if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL; 1179c2c66affSColin Finck else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64; 1180c2c66affSColin Finck else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64; 1181c2c66affSColin Finck else if (!strcmpW( str, szARM )) return PLATFORM_ARM; 1182c2c66affSColin Finck return PLATFORM_UNKNOWN; 1183c2c66affSColin Finck } 1184c2c66affSColin Finck 1185c2c66affSColin Finck static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) 1186c2c66affSColin Finck { 1187c2c66affSColin Finck WCHAR *template, *p, *q, *platform; 1188c2c66affSColin Finck DWORD i, count; 1189c2c66affSColin Finck 1190c2c66affSColin Finck package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); 1191c2c66affSColin Finck TRACE("version: %d\n", package->version); 1192c2c66affSColin Finck 1193c2c66affSColin Finck template = msi_suminfo_dup_string( si, PID_TEMPLATE ); 1194c2c66affSColin Finck if (!template) 1195c2c66affSColin Finck return ERROR_SUCCESS; /* native accepts missing template property */ 1196c2c66affSColin Finck 1197c2c66affSColin Finck TRACE("template: %s\n", debugstr_w(template)); 1198c2c66affSColin Finck 1199c2c66affSColin Finck p = strchrW( template, ';' ); 1200c2c66affSColin Finck if (!p) 1201c2c66affSColin Finck { 1202c2c66affSColin Finck WARN("invalid template string %s\n", debugstr_w(template)); 1203c2c66affSColin Finck msi_free( template ); 1204c2c66affSColin Finck return ERROR_PATCH_PACKAGE_INVALID; 1205c2c66affSColin Finck } 1206c2c66affSColin Finck *p = 0; 1207c2c66affSColin Finck platform = template; 1208c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1209c2c66affSColin Finck package->platform = parse_platform( platform ); 1210c2c66affSColin Finck while (package->platform == PLATFORM_UNKNOWN && q) 1211c2c66affSColin Finck { 1212c2c66affSColin Finck platform = q + 1; 1213c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1214c2c66affSColin Finck package->platform = parse_platform( platform ); 1215c2c66affSColin Finck } 1216c2c66affSColin Finck if (package->platform == PLATFORM_UNKNOWN) 1217c2c66affSColin Finck { 1218c2c66affSColin Finck WARN("unknown platform %s\n", debugstr_w(template)); 1219c2c66affSColin Finck msi_free( template ); 1220c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1221c2c66affSColin Finck } 1222c2c66affSColin Finck p++; 1223c2c66affSColin Finck if (!*p) 1224c2c66affSColin Finck { 1225c2c66affSColin Finck msi_free( template ); 1226c2c66affSColin Finck return ERROR_SUCCESS; 1227c2c66affSColin Finck } 1228c2c66affSColin Finck count = 1; 1229c2c66affSColin Finck for (q = p; (q = strchrW( q, ',' )); q++) count++; 1230c2c66affSColin Finck 1231c2c66affSColin Finck package->langids = msi_alloc( count * sizeof(LANGID) ); 1232c2c66affSColin Finck if (!package->langids) 1233c2c66affSColin Finck { 1234c2c66affSColin Finck msi_free( template ); 1235c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1236c2c66affSColin Finck } 1237c2c66affSColin Finck 1238c2c66affSColin Finck i = 0; 1239c2c66affSColin Finck while (*p) 1240c2c66affSColin Finck { 1241c2c66affSColin Finck q = strchrW( p, ',' ); 1242c2c66affSColin Finck if (q) *q = 0; 1243c2c66affSColin Finck package->langids[i] = atoiW( p ); 1244c2c66affSColin Finck if (!q) break; 1245c2c66affSColin Finck p = q + 1; 1246c2c66affSColin Finck i++; 1247c2c66affSColin Finck } 1248c2c66affSColin Finck package->num_langids = i + 1; 1249c2c66affSColin Finck 1250c2c66affSColin Finck msi_free( template ); 1251c2c66affSColin Finck return ERROR_SUCCESS; 1252c2c66affSColin Finck } 1253c2c66affSColin Finck 1254c2c66affSColin Finck static UINT validate_package( MSIPACKAGE *package ) 1255c2c66affSColin Finck { 1256c2c66affSColin Finck UINT i; 1257c2c66affSColin Finck 1258c2c66affSColin Finck if (package->platform == PLATFORM_INTEL64) 1259c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1260c2c66affSColin Finck #ifndef __arm__ 1261c2c66affSColin Finck if (package->platform == PLATFORM_ARM) 1262c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1263c2c66affSColin Finck #endif 1264c2c66affSColin Finck if (package->platform == PLATFORM_X64) 1265c2c66affSColin Finck { 1266c2c66affSColin Finck if (!is_64bit && !is_wow64) 1267c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1268c2c66affSColin Finck if (package->version < 200) 1269c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1270c2c66affSColin Finck } 1271c2c66affSColin Finck if (!package->num_langids) 1272c2c66affSColin Finck { 1273c2c66affSColin Finck return ERROR_SUCCESS; 1274c2c66affSColin Finck } 1275c2c66affSColin Finck for (i = 0; i < package->num_langids; i++) 1276c2c66affSColin Finck { 1277c2c66affSColin Finck LANGID langid = package->langids[i]; 1278c2c66affSColin Finck 1279c2c66affSColin Finck if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) 1280c2c66affSColin Finck { 1281c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); 1282c2c66affSColin Finck } 1283c2c66affSColin Finck if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) 1284c2c66affSColin Finck { 1285c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); 1286c2c66affSColin Finck } 1287c2c66affSColin Finck if (IsValidLocale( langid, LCID_INSTALLED )) 1288c2c66affSColin Finck return ERROR_SUCCESS; 1289c2c66affSColin Finck } 1290c2c66affSColin Finck return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; 1291c2c66affSColin Finck } 1292c2c66affSColin Finck 1293c2c66affSColin Finck static WCHAR *get_product_code( MSIDATABASE *db ) 1294c2c66affSColin Finck { 1295c2c66affSColin Finck static const WCHAR query[] = { 1296c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 1297c2c66affSColin Finck 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ', 1298c2c66affSColin Finck 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=', 1299c2c66affSColin Finck '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0}; 1300c2c66affSColin Finck MSIQUERY *view; 1301c2c66affSColin Finck MSIRECORD *rec; 1302c2c66affSColin Finck WCHAR *ret = NULL; 1303c2c66affSColin Finck 1304c2c66affSColin Finck if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) 1305c2c66affSColin Finck { 1306c2c66affSColin Finck return NULL; 1307c2c66affSColin Finck } 1308c2c66affSColin Finck if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) 1309c2c66affSColin Finck { 1310c2c66affSColin Finck MSI_ViewClose( view ); 1311c2c66affSColin Finck msiobj_release( &view->hdr ); 1312c2c66affSColin Finck return NULL; 1313c2c66affSColin Finck } 1314c2c66affSColin Finck if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) 1315c2c66affSColin Finck { 1316c2c66affSColin Finck ret = strdupW( MSI_RecordGetString( rec, 1 ) ); 1317c2c66affSColin Finck msiobj_release( &rec->hdr ); 1318c2c66affSColin Finck } 1319c2c66affSColin Finck MSI_ViewClose( view ); 1320c2c66affSColin Finck msiobj_release( &view->hdr ); 1321c2c66affSColin Finck return ret; 1322c2c66affSColin Finck } 1323c2c66affSColin Finck 1324c2c66affSColin Finck static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile ) 1325c2c66affSColin Finck { 1326c2c66affSColin Finck MSIINSTALLCONTEXT context; 1327c2c66affSColin Finck HKEY product_key, props_key; 1328c2c66affSColin Finck WCHAR *registered_package = NULL, unsquashed[GUID_SIZE]; 1329c2c66affSColin Finck UINT r; 1330c2c66affSColin Finck 1331c2c66affSColin Finck r = msi_locate_product( product, &context ); 1332c2c66affSColin Finck if (r != ERROR_SUCCESS) 1333c2c66affSColin Finck return r; 1334c2c66affSColin Finck 1335c2c66affSColin Finck r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE ); 1336c2c66affSColin Finck if (r != ERROR_SUCCESS) 1337c2c66affSColin Finck return r; 1338c2c66affSColin Finck 1339c2c66affSColin Finck r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); 1340c2c66affSColin Finck if (r != ERROR_SUCCESS) 1341c2c66affSColin Finck { 1342c2c66affSColin Finck RegCloseKey( product_key ); 1343c2c66affSColin Finck return r; 1344c2c66affSColin Finck } 1345c2c66affSColin Finck r = ERROR_FUNCTION_FAILED; 1346c2c66affSColin Finck registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW ); 1347c2c66affSColin Finck if (!registered_package) 1348c2c66affSColin Finck goto done; 1349c2c66affSColin Finck 1350c2c66affSColin Finck unsquash_guid( registered_package, unsquashed ); 1351c2c66affSColin Finck if (!strcmpiW( package, unsquashed )) 1352c2c66affSColin Finck { 1353c2c66affSColin Finck WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); 1354c2c66affSColin Finck if (!filename) 1355c2c66affSColin Finck goto done; 1356c2c66affSColin Finck 1357c2c66affSColin Finck strcpyW( localfile, filename ); 1358c2c66affSColin Finck msi_free( filename ); 1359c2c66affSColin Finck r = ERROR_SUCCESS; 1360c2c66affSColin Finck } 1361c2c66affSColin Finck done: 1362c2c66affSColin Finck msi_free( registered_package ); 1363c2c66affSColin Finck RegCloseKey( props_key ); 1364c2c66affSColin Finck RegCloseKey( product_key ); 1365c2c66affSColin Finck return r; 1366c2c66affSColin Finck } 1367c2c66affSColin Finck 1368c2c66affSColin Finck static WCHAR *get_package_code( MSIDATABASE *db ) 1369c2c66affSColin Finck { 1370c2c66affSColin Finck WCHAR *ret; 1371c2c66affSColin Finck MSISUMMARYINFO *si; 1372c2c66affSColin Finck UINT r; 1373c2c66affSColin Finck 1374c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1375c2c66affSColin Finck if (r != ERROR_SUCCESS) 1376c2c66affSColin Finck { 1377c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1378c2c66affSColin Finck if (r != ERROR_SUCCESS) 1379c2c66affSColin Finck { 1380c2c66affSColin Finck WARN("failed to load summary info %u\n", r); 1381c2c66affSColin Finck return NULL; 1382c2c66affSColin Finck } 1383c2c66affSColin Finck } 1384c2c66affSColin Finck ret = msi_suminfo_dup_string( si, PID_REVNUMBER ); 1385c2c66affSColin Finck msiobj_release( &si->hdr ); 1386c2c66affSColin Finck return ret; 1387c2c66affSColin Finck } 1388c2c66affSColin Finck 1389c2c66affSColin Finck static UINT get_local_package( const WCHAR *filename, WCHAR *localfile ) 1390c2c66affSColin Finck { 1391c2c66affSColin Finck WCHAR *product_code, *package_code; 1392c2c66affSColin Finck MSIDATABASE *db; 1393c2c66affSColin Finck UINT r; 1394c2c66affSColin Finck 1395c2c66affSColin Finck if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS) 1396c2c66affSColin Finck { 1397c2c66affSColin Finck if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES) 1398c2c66affSColin Finck return ERROR_FILE_NOT_FOUND; 1399c2c66affSColin Finck return r; 1400c2c66affSColin Finck } 1401c2c66affSColin Finck if (!(product_code = get_product_code( db ))) 1402c2c66affSColin Finck { 1403c2c66affSColin Finck msiobj_release( &db->hdr ); 1404c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1405c2c66affSColin Finck } 1406c2c66affSColin Finck if (!(package_code = get_package_code( db ))) 1407c2c66affSColin Finck { 1408c2c66affSColin Finck msi_free( product_code ); 1409c2c66affSColin Finck msiobj_release( &db->hdr ); 1410c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1411c2c66affSColin Finck } 1412c2c66affSColin Finck r = get_registered_local_package( product_code, package_code, localfile ); 1413c2c66affSColin Finck msi_free( package_code ); 1414c2c66affSColin Finck msi_free( product_code ); 1415c2c66affSColin Finck msiobj_release( &db->hdr ); 1416c2c66affSColin Finck return r; 1417c2c66affSColin Finck } 1418c2c66affSColin Finck 1419c2c66affSColin Finck UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) 1420c2c66affSColin Finck { 1421c2c66affSColin Finck UINT r; 1422c2c66affSColin Finck 1423c2c66affSColin Finck if (UrlIsW( package, URLIS_URL )) 1424c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, package, -1 ); 1425c2c66affSColin Finck else if (package[0] == '#') 1426c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, db->path, -1 ); 1427c2c66affSColin Finck else 1428c2c66affSColin Finck { 1429c2c66affSColin Finck DWORD len; 1430c2c66affSColin Finck WCHAR *path; 1431c2c66affSColin Finck 1432c2c66affSColin Finck if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); 1433c2c66affSColin Finck if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; 1434c2c66affSColin Finck len = GetFullPathNameW( package, len, path, NULL ); 1435c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, path, len ); 1436c2c66affSColin Finck msi_free( path ); 1437c2c66affSColin Finck } 1438c2c66affSColin Finck return r; 1439c2c66affSColin Finck } 1440c2c66affSColin Finck 1441c2c66affSColin Finck UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) 1442c2c66affSColin Finck { 1443c2c66affSColin Finck static const WCHAR dotmsi[] = {'.','m','s','i',0}; 1444c2c66affSColin Finck MSIDATABASE *db; 1445c2c66affSColin Finck MSIPACKAGE *package; 1446c2c66affSColin Finck MSIHANDLE handle; 144771bffdcdSAmine Khaldi MSIRECORD *data_row, *info_row; 1448c2c66affSColin Finck UINT r; 1449c2c66affSColin Finck WCHAR localfile[MAX_PATH], cachefile[MAX_PATH]; 1450c2c66affSColin Finck LPCWSTR file = szPackage; 1451c2c66affSColin Finck DWORD index = 0; 1452c2c66affSColin Finck MSISUMMARYINFO *si; 1453c2c66affSColin Finck BOOL delete_on_close = FALSE; 145434c2011cSwinesync WCHAR *info_template, *productname; 1455c2c66affSColin Finck 1456c2c66affSColin Finck TRACE("%s %p\n", debugstr_w(szPackage), pPackage); 1457c2c66affSColin Finck 145871bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0); 145971bffdcdSAmine Khaldi 1460c2c66affSColin Finck localfile[0] = 0; 1461c2c66affSColin Finck if( szPackage[0] == '#' ) 1462c2c66affSColin Finck { 1463c2c66affSColin Finck handle = atoiW(&szPackage[1]); 1464c2c66affSColin Finck db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); 1465c2c66affSColin Finck if( !db ) 1466c2c66affSColin Finck { 1467b74b77aaSwinesync MSIHANDLE remote; 1468c2c66affSColin Finck 1469b74b77aaSwinesync if (!(remote = msi_get_remote(handle))) 1470c2c66affSColin Finck return ERROR_INVALID_HANDLE; 1471c2c66affSColin Finck 1472c2c66affSColin Finck WARN("MsiOpenPackage not allowed during a custom action!\n"); 1473c2c66affSColin Finck 1474c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1475c2c66affSColin Finck } 1476c2c66affSColin Finck } 1477c2c66affSColin Finck else 1478c2c66affSColin Finck { 1479c2c66affSColin Finck if ( UrlIsW( szPackage, URLIS_URL ) ) 1480c2c66affSColin Finck { 1481c2c66affSColin Finck r = msi_download_file( szPackage, cachefile ); 1482c2c66affSColin Finck if (r != ERROR_SUCCESS) 1483c2c66affSColin Finck return r; 1484c2c66affSColin Finck 1485c2c66affSColin Finck file = cachefile; 1486c2c66affSColin Finck } 1487c2c66affSColin Finck r = get_local_package( file, localfile ); 1488c2c66affSColin Finck if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) 1489c2c66affSColin Finck { 149063bb43adSJérôme Gardou DWORD localfile_attr; 149163bb43adSJérôme Gardou 1492c2c66affSColin Finck r = msi_create_empty_local_file( localfile, dotmsi ); 1493c2c66affSColin Finck if (r != ERROR_SUCCESS) 1494c2c66affSColin Finck return r; 1495c2c66affSColin Finck 1496c2c66affSColin Finck if (!CopyFileW( file, localfile, FALSE )) 1497c2c66affSColin Finck { 1498c2c66affSColin Finck r = GetLastError(); 1499c2c66affSColin Finck WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1500c2c66affSColin Finck DeleteFileW( localfile ); 1501c2c66affSColin Finck return r; 1502c2c66affSColin Finck } 1503c2c66affSColin Finck delete_on_close = TRUE; 150463bb43adSJérôme Gardou 150563bb43adSJérôme Gardou /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */ 150663bb43adSJérôme Gardou localfile_attr = GetFileAttributesW( localfile ); 150763bb43adSJérôme Gardou if (localfile_attr & FILE_ATTRIBUTE_READONLY) 150863bb43adSJérôme Gardou SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY); 1509c2c66affSColin Finck } 1510c2c66affSColin Finck TRACE("opening package %s\n", debugstr_w( localfile )); 1511c2c66affSColin Finck r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1512c2c66affSColin Finck if (r != ERROR_SUCCESS) 1513c2c66affSColin Finck return r; 1514c2c66affSColin Finck } 151534c2011cSwinesync package = MSI_CreatePackage( db ); 1516c2c66affSColin Finck msiobj_release( &db->hdr ); 1517c2c66affSColin Finck if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1518c2c66affSColin Finck package->localfile = strdupW( localfile ); 1519c2c66affSColin Finck package->delete_on_close = delete_on_close; 1520c2c66affSColin Finck 1521c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1522c2c66affSColin Finck if (r != ERROR_SUCCESS) 1523c2c66affSColin Finck { 1524c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1525c2c66affSColin Finck if (r != ERROR_SUCCESS) 1526c2c66affSColin Finck { 1527c2c66affSColin Finck WARN("failed to load summary info\n"); 1528c2c66affSColin Finck msiobj_release( &package->hdr ); 1529c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1530c2c66affSColin Finck } 1531c2c66affSColin Finck } 1532c2c66affSColin Finck r = parse_suminfo( si, package ); 1533c2c66affSColin Finck msiobj_release( &si->hdr ); 1534c2c66affSColin Finck if (r != ERROR_SUCCESS) 1535c2c66affSColin Finck { 1536c2c66affSColin Finck WARN("failed to parse summary info %u\n", r); 1537c2c66affSColin Finck msiobj_release( &package->hdr ); 1538c2c66affSColin Finck return r; 1539c2c66affSColin Finck } 1540c2c66affSColin Finck r = validate_package( package ); 1541c2c66affSColin Finck if (r != ERROR_SUCCESS) 1542c2c66affSColin Finck { 1543c2c66affSColin Finck msiobj_release( &package->hdr ); 1544c2c66affSColin Finck return r; 1545c2c66affSColin Finck } 1546c2c66affSColin Finck msi_set_property( package->db, szDatabase, db->path, -1 ); 1547c2c66affSColin Finck set_installed_prop( package ); 1548c2c66affSColin Finck msi_set_context( package ); 1549c2c66affSColin Finck 1550c2c66affSColin Finck while (1) 1551c2c66affSColin Finck { 1552c2c66affSColin Finck WCHAR patch_code[GUID_SIZE]; 1553c2c66affSColin Finck r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1554c2c66affSColin Finck MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1555c2c66affSColin Finck if (r != ERROR_SUCCESS) 1556c2c66affSColin Finck break; 1557c2c66affSColin Finck 1558c2c66affSColin Finck TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1559c2c66affSColin Finck 1560c2c66affSColin Finck r = msi_apply_registered_patch( package, patch_code ); 1561c2c66affSColin Finck if (r != ERROR_SUCCESS) 1562c2c66affSColin Finck { 1563c2c66affSColin Finck ERR("registered patch failed to apply %u\n", r); 1564c2c66affSColin Finck msiobj_release( &package->hdr ); 1565c2c66affSColin Finck return r; 1566c2c66affSColin Finck } 1567c2c66affSColin Finck index++; 1568c2c66affSColin Finck } 1569c2c66affSColin Finck if (index) msi_adjust_privilege_properties( package ); 1570c2c66affSColin Finck 1571c2c66affSColin Finck r = msi_set_original_database_property( package->db, szPackage ); 1572c2c66affSColin Finck if (r != ERROR_SUCCESS) 1573c2c66affSColin Finck { 1574c2c66affSColin Finck msiobj_release( &package->hdr ); 1575c2c66affSColin Finck return r; 1576c2c66affSColin Finck } 1577c2c66affSColin Finck if (gszLogFile) 1578c2c66affSColin Finck package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1579c2c66affSColin Finck OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 158071bffdcdSAmine Khaldi 158171bffdcdSAmine Khaldi /* FIXME: when should these messages be sent? */ 158271bffdcdSAmine Khaldi data_row = MSI_CreateRecord(3); 158371bffdcdSAmine Khaldi if (!data_row) 158471bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 158571bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 0, NULL); 158671bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 0); 158771bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0); 158871bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings)); 158971bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row); 159071bffdcdSAmine Khaldi 159171bffdcdSAmine Khaldi info_row = MSI_CreateRecord(0); 159271bffdcdSAmine Khaldi if (!info_row) 159371bffdcdSAmine Khaldi { 159471bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 159571bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 159671bffdcdSAmine Khaldi } 159771bffdcdSAmine Khaldi info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART); 159871bffdcdSAmine Khaldi MSI_RecordSetStringW(info_row, 0, info_template); 159971bffdcdSAmine Khaldi msi_free(info_template); 160071bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row); 160171bffdcdSAmine Khaldi 160271bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 160371bffdcdSAmine Khaldi 160471bffdcdSAmine Khaldi productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW); 160571bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 1); 160671bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 2, productname); 160771bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 3, NULL); 160871bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 160971bffdcdSAmine Khaldi 161071bffdcdSAmine Khaldi msi_free(productname); 161171bffdcdSAmine Khaldi msiobj_release(&info_row->hdr); 161271bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 161371bffdcdSAmine Khaldi 1614c2c66affSColin Finck *pPackage = package; 1615c2c66affSColin Finck return ERROR_SUCCESS; 1616c2c66affSColin Finck } 1617c2c66affSColin Finck 1618c2c66affSColin Finck UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1619c2c66affSColin Finck { 1620c2c66affSColin Finck MSIPACKAGE *package = NULL; 1621c2c66affSColin Finck UINT ret; 1622c2c66affSColin Finck 1623c2c66affSColin Finck TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1624c2c66affSColin Finck 1625c2c66affSColin Finck if( !szPackage || !phPackage ) 1626c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 1627c2c66affSColin Finck 1628c2c66affSColin Finck if ( !*szPackage ) 1629c2c66affSColin Finck { 1630c2c66affSColin Finck FIXME("Should create an empty database and package\n"); 1631c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1632c2c66affSColin Finck } 1633c2c66affSColin Finck 1634c2c66affSColin Finck if( dwOptions ) 1635c2c66affSColin Finck FIXME("dwOptions %08x not supported\n", dwOptions); 1636c2c66affSColin Finck 1637c2c66affSColin Finck ret = MSI_OpenPackageW( szPackage, &package ); 1638c2c66affSColin Finck if( ret == ERROR_SUCCESS ) 1639c2c66affSColin Finck { 1640c2c66affSColin Finck *phPackage = alloc_msihandle( &package->hdr ); 1641c2c66affSColin Finck if (! *phPackage) 1642c2c66affSColin Finck ret = ERROR_NOT_ENOUGH_MEMORY; 1643c2c66affSColin Finck msiobj_release( &package->hdr ); 1644c2c66affSColin Finck } 164571bffdcdSAmine Khaldi else 164671bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 1647c2c66affSColin Finck 1648c2c66affSColin Finck return ret; 1649c2c66affSColin Finck } 1650c2c66affSColin Finck 1651c2c66affSColin Finck UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1652c2c66affSColin Finck { 1653c2c66affSColin Finck return MsiOpenPackageExW( szPackage, 0, phPackage ); 1654c2c66affSColin Finck } 1655c2c66affSColin Finck 1656c2c66affSColin Finck UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1657c2c66affSColin Finck { 1658c2c66affSColin Finck LPWSTR szwPack = NULL; 1659c2c66affSColin Finck UINT ret; 1660c2c66affSColin Finck 1661c2c66affSColin Finck if( szPackage ) 1662c2c66affSColin Finck { 1663c2c66affSColin Finck szwPack = strdupAtoW( szPackage ); 1664c2c66affSColin Finck if( !szwPack ) 1665c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1666c2c66affSColin Finck } 1667c2c66affSColin Finck 1668c2c66affSColin Finck ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1669c2c66affSColin Finck 1670c2c66affSColin Finck msi_free( szwPack ); 1671c2c66affSColin Finck 1672c2c66affSColin Finck return ret; 1673c2c66affSColin Finck } 1674c2c66affSColin Finck 1675c2c66affSColin Finck UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1676c2c66affSColin Finck { 1677c2c66affSColin Finck return MsiOpenPackageExA( szPackage, 0, phPackage ); 1678c2c66affSColin Finck } 1679c2c66affSColin Finck 1680c2c66affSColin Finck MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) 1681c2c66affSColin Finck { 1682c2c66affSColin Finck MSIPACKAGE *package; 1683c2c66affSColin Finck MSIHANDLE handle = 0; 1684b74b77aaSwinesync MSIHANDLE remote; 1685c2c66affSColin Finck 1686c2c66affSColin Finck TRACE("(%d)\n",hInstall); 1687c2c66affSColin Finck 1688c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1689c2c66affSColin Finck if( package) 1690c2c66affSColin Finck { 1691c2c66affSColin Finck handle = alloc_msihandle( &package->db->hdr ); 1692c2c66affSColin Finck msiobj_release( &package->hdr ); 1693c2c66affSColin Finck } 1694b74b77aaSwinesync else if ((remote = msi_get_remote(hInstall))) 1695c2c66affSColin Finck { 16967cc54a4fSwinesync handle = remote_GetActiveDatabase(remote); 16977cc54a4fSwinesync handle = alloc_msi_remote_handle(handle); 1698c2c66affSColin Finck } 1699c2c66affSColin Finck 1700c2c66affSColin Finck return handle; 1701c2c66affSColin Finck } 1702c2c66affSColin Finck 170371bffdcdSAmine Khaldi static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message) 1704c2c66affSColin Finck { 1705c2c66affSColin Finck static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0}; 1706c2c66affSColin Finck static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0}; 170771bffdcdSAmine Khaldi static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0}; 170871bffdcdSAmine Khaldi static const WCHAR szWindows_Installer[] = 170971bffdcdSAmine Khaldi {'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0}; 171071bffdcdSAmine Khaldi 171171bffdcdSAmine Khaldi if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) 171271bffdcdSAmine Khaldi return 0; 171371bffdcdSAmine Khaldi 171471bffdcdSAmine Khaldi /* todo: check if message needs additional styles (topmost/foreground/modality?) */ 171571bffdcdSAmine Khaldi 171671bffdcdSAmine Khaldi switch (eMessageType & 0xff000000) 171771bffdcdSAmine Khaldi { 171871bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 171971bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 172071bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 172171bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 172271bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 172371bffdcdSAmine Khaldi eMessageType |= MB_ICONEXCLAMATION; 172471bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 172571bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 172671bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 172771bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 172871bffdcdSAmine Khaldi eMessageType |= MB_ICONASTERISK; 172971bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 173071bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 173171bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 173271bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 173371bffdcdSAmine Khaldi eMessageType |= MB_USERICON; 173471bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 173571bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 173671bffdcdSAmine Khaldi case INSTALLMESSAGE_INITIALIZE: 173771bffdcdSAmine Khaldi case INSTALLMESSAGE_TERMINATE: 1738f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLSTART: 1739f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLEND: 174071bffdcdSAmine Khaldi return 0; 174171bffdcdSAmine Khaldi case INSTALLMESSAGE_SHOWDIALOG: 174271bffdcdSAmine Khaldi { 174371bffdcdSAmine Khaldi LPWSTR dialog = msi_dup_record_field(record, 0); 174471bffdcdSAmine Khaldi INT rc = ACTION_DialogBox(package, dialog); 174571bffdcdSAmine Khaldi msi_free(dialog); 174671bffdcdSAmine Khaldi return rc; 174771bffdcdSAmine Khaldi } 174871bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONSTART: 174971bffdcdSAmine Khaldi { 175071bffdcdSAmine Khaldi LPWSTR deformatted; 175171bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 175271bffdcdSAmine Khaldi if (!uirow) return -1; 175371bffdcdSAmine Khaldi deformat_string(package, MSI_RecordGetString(record, 2), &deformatted); 175471bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, deformatted); 175571bffdcdSAmine Khaldi msi_event_fire(package, szActionText, uirow); 175671bffdcdSAmine Khaldi 175771bffdcdSAmine Khaldi msi_free(deformatted); 175871bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 175971bffdcdSAmine Khaldi return 1; 176071bffdcdSAmine Khaldi } 176171bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 176271bffdcdSAmine Khaldi { 176371bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 176471bffdcdSAmine Khaldi if (!uirow) return -1; 176571bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, message); 176671bffdcdSAmine Khaldi msi_event_fire(package, szActionData, uirow); 176771bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 176871bffdcdSAmine Khaldi 176971bffdcdSAmine Khaldi if (package->action_progress_increment) 177071bffdcdSAmine Khaldi { 177171bffdcdSAmine Khaldi uirow = MSI_CreateRecord(2); 177271bffdcdSAmine Khaldi if (!uirow) return -1; 177371bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 1, 2); 177471bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 177571bffdcdSAmine Khaldi msi_event_fire(package, szSetProgress, uirow); 177671bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 177771bffdcdSAmine Khaldi } 177871bffdcdSAmine Khaldi return 1; 177971bffdcdSAmine Khaldi } 178071bffdcdSAmine Khaldi case INSTALLMESSAGE_PROGRESS: 178171bffdcdSAmine Khaldi msi_event_fire(package, szSetProgress, record); 178271bffdcdSAmine Khaldi return 1; 178371bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 178471bffdcdSAmine Khaldi switch (MSI_RecordGetInteger(record, 1)) 178571bffdcdSAmine Khaldi { 178671bffdcdSAmine Khaldi case 0: 178771bffdcdSAmine Khaldi case 1: 178871bffdcdSAmine Khaldi /* do nothing */ 178971bffdcdSAmine Khaldi return 0; 179071bffdcdSAmine Khaldi default: 179171bffdcdSAmine Khaldi /* fall through */ 179271bffdcdSAmine Khaldi ; 179371bffdcdSAmine Khaldi } 179471bffdcdSAmine Khaldi default: 179571bffdcdSAmine Khaldi FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level); 179671bffdcdSAmine Khaldi return 0; 179771bffdcdSAmine Khaldi } 179871bffdcdSAmine Khaldi } 179971bffdcdSAmine Khaldi 180071bffdcdSAmine Khaldi static const WCHAR szActionNotFound[] = {'D','E','B','U','G',':',' ','E','r','r','o','r',' ','[','1',']',':',' ',' ','A','c','t','i','o','n',' ','n','o','t',' ','f','o','u','n','d',':',' ','[','2',']',0}; 180171bffdcdSAmine Khaldi 180271bffdcdSAmine Khaldi static const struct 180371bffdcdSAmine Khaldi { 180471bffdcdSAmine Khaldi int id; 180571bffdcdSAmine Khaldi const WCHAR *text; 180671bffdcdSAmine Khaldi } 180771bffdcdSAmine Khaldi internal_errors[] = 180871bffdcdSAmine Khaldi { 180971bffdcdSAmine Khaldi {2726, szActionNotFound}, 181071bffdcdSAmine Khaldi {0} 181171bffdcdSAmine Khaldi }; 181271bffdcdSAmine Khaldi 181371bffdcdSAmine Khaldi static LPCWSTR get_internal_error_message(int error) 181471bffdcdSAmine Khaldi { 181571bffdcdSAmine Khaldi int i = 0; 181671bffdcdSAmine Khaldi 181771bffdcdSAmine Khaldi while (internal_errors[i].id != 0) 181871bffdcdSAmine Khaldi { 181971bffdcdSAmine Khaldi if (internal_errors[i].id == error) 182071bffdcdSAmine Khaldi return internal_errors[i].text; 182171bffdcdSAmine Khaldi i++; 182271bffdcdSAmine Khaldi } 182371bffdcdSAmine Khaldi 182471bffdcdSAmine Khaldi FIXME("missing error message %d\n", error); 182571bffdcdSAmine Khaldi return NULL; 182671bffdcdSAmine Khaldi } 182771bffdcdSAmine Khaldi 182871bffdcdSAmine Khaldi /* Returned string must be freed */ 182971bffdcdSAmine Khaldi LPWSTR msi_get_error_message(MSIDATABASE *db, int error) 183071bffdcdSAmine Khaldi { 183171bffdcdSAmine Khaldi static const WCHAR query[] = 183271bffdcdSAmine Khaldi {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ', 183371bffdcdSAmine Khaldi 'F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ', 183471bffdcdSAmine Khaldi '`','E','r','r','o','r','`',' ','=',' ','%','i',0}; 183571bffdcdSAmine Khaldi MSIRECORD *record; 183671bffdcdSAmine Khaldi LPWSTR ret = NULL; 183771bffdcdSAmine Khaldi 183871bffdcdSAmine Khaldi if ((record = MSI_QueryGetRecord(db, query, error))) 183971bffdcdSAmine Khaldi { 184071bffdcdSAmine Khaldi ret = msi_dup_record_field(record, 1); 184171bffdcdSAmine Khaldi msiobj_release(&record->hdr); 184271bffdcdSAmine Khaldi } 184371bffdcdSAmine Khaldi else if (error < 2000) 184471bffdcdSAmine Khaldi { 184571bffdcdSAmine Khaldi int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0); 184671bffdcdSAmine Khaldi if (len) 184771bffdcdSAmine Khaldi { 184871bffdcdSAmine Khaldi ret = msi_alloc((len + 1) * sizeof(WCHAR)); 184971bffdcdSAmine Khaldi LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1); 185071bffdcdSAmine Khaldi } 185171bffdcdSAmine Khaldi else 185271bffdcdSAmine Khaldi ret = NULL; 185371bffdcdSAmine Khaldi } 185471bffdcdSAmine Khaldi 185571bffdcdSAmine Khaldi return ret; 185671bffdcdSAmine Khaldi } 185771bffdcdSAmine Khaldi 185871bffdcdSAmine Khaldi INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record) 185971bffdcdSAmine Khaldi { 186071bffdcdSAmine Khaldi LPWSTR message = {0}; 1861f8b992f2SAmine Khaldi DWORD len; 1862f8b992f2SAmine Khaldi DWORD log_type = 1 << (eMessageType >> 24); 186371bffdcdSAmine Khaldi UINT res; 1864c2c66affSColin Finck INT rc = 0; 1865c2c66affSColin Finck char *msg; 1866c2c66affSColin Finck 1867c2c66affSColin Finck TRACE("%x\n", eMessageType); 186871bffdcdSAmine Khaldi if (TRACE_ON(msi)) dump_record(record); 1869c2c66affSColin Finck 187071bffdcdSAmine Khaldi if (!package || !record) 187171bffdcdSAmine Khaldi message = NULL; 187271bffdcdSAmine Khaldi else { 187371bffdcdSAmine Khaldi res = MSI_FormatRecordW(package, record, message, &len); 187471bffdcdSAmine Khaldi if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 187571bffdcdSAmine Khaldi return res; 187671bffdcdSAmine Khaldi len++; 1877c2c66affSColin Finck message = msi_alloc(len * sizeof(WCHAR)); 187871bffdcdSAmine Khaldi if (!message) return ERROR_OUTOFMEMORY; 187971bffdcdSAmine Khaldi MSI_FormatRecordW(package, record, message, &len); 1880c2c66affSColin Finck } 1881c2c66affSColin Finck 1882c2c66affSColin Finck /* convert it to ASCII */ 1883c2c66affSColin Finck len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1884c2c66affSColin Finck msg = msi_alloc( len ); 1885c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1886c2c66affSColin Finck 188771bffdcdSAmine Khaldi if (gUIHandlerRecord && (gUIFilterRecord & log_type)) 1888c2c66affSColin Finck { 188971bffdcdSAmine Khaldi MSIHANDLE rec = alloc_msihandle(&record->hdr); 189071bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n", 189171bffdcdSAmine Khaldi gUIHandlerRecord, gUIContextRecord, eMessageType, rec); 189271bffdcdSAmine Khaldi rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec ); 1893c2c66affSColin Finck MsiCloseHandle( rec ); 1894c2c66affSColin Finck } 189571bffdcdSAmine Khaldi if (!rc && gUIHandlerW && (gUIFilter & log_type)) 189671bffdcdSAmine Khaldi { 189771bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 189871bffdcdSAmine Khaldi gUIHandlerW, gUIContext, eMessageType, debugstr_w(message)); 189971bffdcdSAmine Khaldi rc = gUIHandlerW( gUIContext, eMessageType, message ); 190071bffdcdSAmine Khaldi } 190171bffdcdSAmine Khaldi else if (!rc && gUIHandlerA && (gUIFilter & log_type)) 190271bffdcdSAmine Khaldi { 190371bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 190471bffdcdSAmine Khaldi gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg)); 190571bffdcdSAmine Khaldi rc = gUIHandlerA( gUIContext, eMessageType, msg ); 190671bffdcdSAmine Khaldi } 1907c2c66affSColin Finck 190871bffdcdSAmine Khaldi if (!rc) 190971bffdcdSAmine Khaldi rc = internal_ui_handler(package, eMessageType, record, message); 191071bffdcdSAmine Khaldi 191171bffdcdSAmine Khaldi if (!rc && package && package->log_file != INVALID_HANDLE_VALUE && 1912c2c66affSColin Finck (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1913c2c66affSColin Finck { 1914c2c66affSColin Finck DWORD written; 1915c2c66affSColin Finck WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1916c2c66affSColin Finck WriteFile( package->log_file, "\n", 1, &written, NULL ); 1917c2c66affSColin Finck } 1918c2c66affSColin Finck msi_free( msg ); 1919c2c66affSColin Finck msi_free( message ); 1920c2c66affSColin Finck 192171bffdcdSAmine Khaldi return rc; 192271bffdcdSAmine Khaldi } 192371bffdcdSAmine Khaldi 192471bffdcdSAmine Khaldi INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 192571bffdcdSAmine Khaldi { 1926c2c66affSColin Finck switch (eMessageType & 0xff000000) 1927c2c66affSColin Finck { 192871bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 192971bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 193071bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 193171bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 193271bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 193371bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 193471bffdcdSAmine Khaldi if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) 1935c2c66affSColin Finck { 193671bffdcdSAmine Khaldi /* error message */ 193771bffdcdSAmine Khaldi 193871bffdcdSAmine Khaldi LPWSTR template; 193971bffdcdSAmine Khaldi LPWSTR template_rec = NULL, template_prefix = NULL; 194071bffdcdSAmine Khaldi int error = MSI_RecordGetInteger(record, 1); 194171bffdcdSAmine Khaldi 194271bffdcdSAmine Khaldi if (MSI_RecordIsNull(record, 0)) 194371bffdcdSAmine Khaldi { 194471bffdcdSAmine Khaldi if (error >= 32) 194571bffdcdSAmine Khaldi { 194671bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, error); 194771bffdcdSAmine Khaldi 194871bffdcdSAmine Khaldi if (!template_rec && error >= 2000) 194971bffdcdSAmine Khaldi { 195071bffdcdSAmine Khaldi /* internal error, not localized */ 195171bffdcdSAmine Khaldi if ((template_rec = (LPWSTR) get_internal_error_message(error))) 195271bffdcdSAmine Khaldi { 195371bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 195471bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record); 195571bffdcdSAmine Khaldi } 195671bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR); 195771bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 195871bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 195971bffdcdSAmine Khaldi msi_free(template_rec); 196071bffdcdSAmine Khaldi return 0; 196171bffdcdSAmine Khaldi } 196271bffdcdSAmine Khaldi } 196371bffdcdSAmine Khaldi } 196471bffdcdSAmine Khaldi else 196571bffdcdSAmine Khaldi template_rec = msi_dup_record_field(record, 0); 196671bffdcdSAmine Khaldi 196771bffdcdSAmine Khaldi template_prefix = msi_get_error_message(package->db, eMessageType >> 24); 196871bffdcdSAmine Khaldi if (!template_prefix) template_prefix = strdupW(szEmpty); 196971bffdcdSAmine Khaldi 197071bffdcdSAmine Khaldi if (!template_rec) 197171bffdcdSAmine Khaldi { 197271bffdcdSAmine Khaldi /* always returns 0 */ 197371bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_prefix); 197471bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 197571bffdcdSAmine Khaldi msi_free(template_prefix); 197671bffdcdSAmine Khaldi return 0; 197771bffdcdSAmine Khaldi } 197871bffdcdSAmine Khaldi 197971bffdcdSAmine Khaldi template = msi_alloc((strlenW(template_rec) + strlenW(template_prefix) + 1) * sizeof(WCHAR)); 198071bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 198171bffdcdSAmine Khaldi 198271bffdcdSAmine Khaldi strcpyW(template, template_prefix); 198371bffdcdSAmine Khaldi strcatW(template, template_rec); 198471bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 198571bffdcdSAmine Khaldi 198671bffdcdSAmine Khaldi msi_free(template_prefix); 198771bffdcdSAmine Khaldi msi_free(template_rec); 198871bffdcdSAmine Khaldi msi_free(template); 1989c2c66affSColin Finck } 1990c2c66affSColin Finck break; 1991c2c66affSColin Finck case INSTALLMESSAGE_ACTIONSTART: 199271bffdcdSAmine Khaldi { 199371bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART); 199471bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 199571bffdcdSAmine Khaldi msi_free(template); 1996c2c66affSColin Finck 199771bffdcdSAmine Khaldi msi_free(package->LastAction); 199871bffdcdSAmine Khaldi msi_free(package->LastActionTemplate); 199971bffdcdSAmine Khaldi package->LastAction = msi_dup_record_field(record, 1); 200071bffdcdSAmine Khaldi if (!package->LastAction) package->LastAction = strdupW(szEmpty); 200171bffdcdSAmine Khaldi package->LastActionTemplate = msi_dup_record_field(record, 3); 2002c2c66affSColin Finck break; 200371bffdcdSAmine Khaldi } 200471bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 200571bffdcdSAmine Khaldi if (package->LastAction && package->LastActionTemplate) 200671bffdcdSAmine Khaldi { 200771bffdcdSAmine Khaldi static const WCHAR template_s[] = 200871bffdcdSAmine Khaldi {'{','{','%','s',':',' ','}','}','%','s',0}; 200971bffdcdSAmine Khaldi WCHAR *template; 2010c2c66affSColin Finck 201171bffdcdSAmine Khaldi template = msi_alloc((strlenW(package->LastAction) + strlenW(package->LastActionTemplate) + 7) * sizeof(WCHAR)); 201271bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 201371bffdcdSAmine Khaldi sprintfW(template, template_s, package->LastAction, package->LastActionTemplate); 201471bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 201571bffdcdSAmine Khaldi msi_free(template); 201671bffdcdSAmine Khaldi } 201771bffdcdSAmine Khaldi break; 201871bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 201971bffdcdSAmine Khaldi { 202071bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA); 202171bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 202271bffdcdSAmine Khaldi msi_free(template); 202371bffdcdSAmine Khaldi } 2024c2c66affSColin Finck break; 2025c2c66affSColin Finck } 2026c2c66affSColin Finck 202771bffdcdSAmine Khaldi return MSI_ProcessMessageVerbatim(package, eMessageType, record); 2028c2c66affSColin Finck } 2029c2c66affSColin Finck 2030c2c66affSColin Finck INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, 2031c2c66affSColin Finck MSIHANDLE hRecord) 2032c2c66affSColin Finck { 2033c2c66affSColin Finck UINT ret = ERROR_INVALID_HANDLE; 2034c2c66affSColin Finck MSIPACKAGE *package = NULL; 2035c2c66affSColin Finck MSIRECORD *record = NULL; 2036c2c66affSColin Finck 203771bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE || 203871bffdcdSAmine Khaldi (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE) 203971bffdcdSAmine Khaldi return -1; 204071bffdcdSAmine Khaldi 204171bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA && 204271bffdcdSAmine Khaldi MsiRecordGetInteger(hRecord, 1) != 2) 204371bffdcdSAmine Khaldi return -1; 204471bffdcdSAmine Khaldi 20452e19edd6Swinesync record = msihandle2msiinfo(hRecord, MSIHANDLETYPE_RECORD); 20462e19edd6Swinesync if (!record) 20472e19edd6Swinesync return ERROR_INVALID_HANDLE; 20482e19edd6Swinesync 2049c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 2050c2c66affSColin Finck if( !package ) 2051c2c66affSColin Finck { 2052b74b77aaSwinesync MSIHANDLE remote; 2053c2c66affSColin Finck 2054b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2055c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2056c2c66affSColin Finck 20572e19edd6Swinesync ret = remote_ProcessMessage(remote, eMessageType, (struct wire_record *)&record->count); 2058c2c66affSColin Finck 20592e19edd6Swinesync msiobj_release(&record->hdr); 20602e19edd6Swinesync return ret; 2061c2c66affSColin Finck } 2062c2c66affSColin Finck 2063c2c66affSColin Finck ret = MSI_ProcessMessage( package, eMessageType, record ); 2064c2c66affSColin Finck 2065c2c66affSColin Finck msiobj_release( &package->hdr ); 2066c2c66affSColin Finck return ret; 2067c2c66affSColin Finck } 2068c2c66affSColin Finck 2069c2c66affSColin Finck /* property code */ 2070c2c66affSColin Finck 2071c2c66affSColin Finck UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) 2072c2c66affSColin Finck { 2073c2c66affSColin Finck LPWSTR szwName = NULL, szwValue = NULL; 2074c2c66affSColin Finck UINT r = ERROR_OUTOFMEMORY; 2075c2c66affSColin Finck 2076c2c66affSColin Finck szwName = strdupAtoW( szName ); 2077c2c66affSColin Finck if( szName && !szwName ) 2078c2c66affSColin Finck goto end; 2079c2c66affSColin Finck 2080c2c66affSColin Finck szwValue = strdupAtoW( szValue ); 2081c2c66affSColin Finck if( szValue && !szwValue ) 2082c2c66affSColin Finck goto end; 2083c2c66affSColin Finck 2084c2c66affSColin Finck r = MsiSetPropertyW( hInstall, szwName, szwValue); 2085c2c66affSColin Finck 2086c2c66affSColin Finck end: 2087c2c66affSColin Finck msi_free( szwName ); 2088c2c66affSColin Finck msi_free( szwValue ); 2089c2c66affSColin Finck 2090c2c66affSColin Finck return r; 2091c2c66affSColin Finck } 2092c2c66affSColin Finck 2093c2c66affSColin Finck void msi_reset_folders( MSIPACKAGE *package, BOOL source ) 2094c2c66affSColin Finck { 2095c2c66affSColin Finck MSIFOLDER *folder; 2096c2c66affSColin Finck 2097c2c66affSColin Finck LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) 2098c2c66affSColin Finck { 2099c2c66affSColin Finck if ( source ) 2100c2c66affSColin Finck { 2101c2c66affSColin Finck msi_free( folder->ResolvedSource ); 2102c2c66affSColin Finck folder->ResolvedSource = NULL; 2103c2c66affSColin Finck } 2104c2c66affSColin Finck else 2105c2c66affSColin Finck { 2106c2c66affSColin Finck msi_free( folder->ResolvedTarget ); 2107c2c66affSColin Finck folder->ResolvedTarget = NULL; 2108c2c66affSColin Finck } 2109c2c66affSColin Finck } 2110c2c66affSColin Finck } 2111c2c66affSColin Finck 2112c2c66affSColin Finck UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) 2113c2c66affSColin Finck { 2114c2c66affSColin Finck static const WCHAR insert_query[] = { 2115c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 2116c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 2117c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 2118c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 2119c2c66affSColin Finck static const WCHAR update_query[] = { 2120c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 2121c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ', 2122c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2123c2c66affSColin Finck static const WCHAR delete_query[] = { 2124c2c66affSColin Finck 'D','E','L','E','T','E',' ','F','R','O','M',' ', 2125c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 2126c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2127c2c66affSColin Finck MSIQUERY *view; 2128c2c66affSColin Finck MSIRECORD *row = NULL; 2129c2c66affSColin Finck DWORD sz = 0; 2130c2c66affSColin Finck WCHAR query[1024]; 2131c2c66affSColin Finck UINT rc; 2132c2c66affSColin Finck 2133c2c66affSColin Finck TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); 2134c2c66affSColin Finck 2135c2c66affSColin Finck if (!name) 2136c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 2137c2c66affSColin Finck 2138c2c66affSColin Finck /* this one is weird... */ 2139c2c66affSColin Finck if (!name[0]) 2140c2c66affSColin Finck return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; 2141c2c66affSColin Finck 2142c2c66affSColin Finck if (value && len < 0) len = strlenW( value ); 2143c2c66affSColin Finck 2144c2c66affSColin Finck rc = msi_get_property( db, name, 0, &sz ); 2145c2c66affSColin Finck if (!value || (!*value && !len)) 2146c2c66affSColin Finck { 2147c2c66affSColin Finck sprintfW( query, delete_query, name ); 2148c2c66affSColin Finck } 2149c2c66affSColin Finck else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) 2150c2c66affSColin Finck { 2151c2c66affSColin Finck sprintfW( query, update_query, name ); 2152c2c66affSColin Finck row = MSI_CreateRecord(1); 2153c2c66affSColin Finck msi_record_set_string( row, 1, value, len ); 2154c2c66affSColin Finck } 2155c2c66affSColin Finck else 2156c2c66affSColin Finck { 2157c2c66affSColin Finck strcpyW( query, insert_query ); 2158c2c66affSColin Finck row = MSI_CreateRecord(2); 2159c2c66affSColin Finck msi_record_set_string( row, 1, name, -1 ); 2160c2c66affSColin Finck msi_record_set_string( row, 2, value, len ); 2161c2c66affSColin Finck } 2162c2c66affSColin Finck 2163c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(db, query, &view); 2164c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2165c2c66affSColin Finck { 2166c2c66affSColin Finck rc = MSI_ViewExecute(view, row); 2167c2c66affSColin Finck MSI_ViewClose(view); 2168c2c66affSColin Finck msiobj_release(&view->hdr); 2169c2c66affSColin Finck } 2170c2c66affSColin Finck if (row) msiobj_release(&row->hdr); 2171c2c66affSColin Finck return rc; 2172c2c66affSColin Finck } 2173c2c66affSColin Finck 2174c2c66affSColin Finck UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) 2175c2c66affSColin Finck { 2176c2c66affSColin Finck MSIPACKAGE *package; 2177c2c66affSColin Finck UINT ret; 2178c2c66affSColin Finck 2179c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 2180c2c66affSColin Finck if( !package ) 2181c2c66affSColin Finck { 2182b74b77aaSwinesync MSIHANDLE remote; 2183c2c66affSColin Finck 2184b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2185c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2186c2c66affSColin Finck 21873431091cSwinesync return remote_SetProperty(remote, szName, szValue); 2188c2c66affSColin Finck } 2189c2c66affSColin Finck 2190c2c66affSColin Finck ret = msi_set_property( package->db, szName, szValue, -1 ); 2191c2c66affSColin Finck if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) 2192c2c66affSColin Finck msi_reset_folders( package, TRUE ); 2193c2c66affSColin Finck 2194c2c66affSColin Finck msiobj_release( &package->hdr ); 2195c2c66affSColin Finck return ret; 2196c2c66affSColin Finck } 2197c2c66affSColin Finck 2198c2c66affSColin Finck static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) 2199c2c66affSColin Finck { 2200c2c66affSColin Finck static const WCHAR query[]= { 2201c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 2202c2c66affSColin Finck 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ', 2203c2c66affSColin Finck 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0}; 2204c2c66affSColin Finck MSIRECORD *rec, *row = NULL; 2205c2c66affSColin Finck MSIQUERY *view; 2206c2c66affSColin Finck UINT r; 2207c2c66affSColin Finck 220871bffdcdSAmine Khaldi static const WCHAR szDate[] = {'D','a','t','e',0}; 220971bffdcdSAmine Khaldi static const WCHAR szTime[] = {'T','i','m','e',0}; 221071bffdcdSAmine Khaldi WCHAR *buffer; 221171bffdcdSAmine Khaldi int length; 221271bffdcdSAmine Khaldi 2213c2c66affSColin Finck if (!name || !*name) 2214c2c66affSColin Finck return NULL; 2215c2c66affSColin Finck 221671bffdcdSAmine Khaldi if (!strcmpW(name, szDate)) 221771bffdcdSAmine Khaldi { 221871bffdcdSAmine Khaldi length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0); 221971bffdcdSAmine Khaldi if (!length) 222071bffdcdSAmine Khaldi return NULL; 222171bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2222fec16ab0SAmine Khaldi GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length); 222371bffdcdSAmine Khaldi 222471bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 222571bffdcdSAmine Khaldi if (!row) 2226f8b992f2SAmine Khaldi { 2227f8b992f2SAmine Khaldi msi_free(buffer); 222871bffdcdSAmine Khaldi return NULL; 2229f8b992f2SAmine Khaldi } 223071bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 223171bffdcdSAmine Khaldi msi_free(buffer); 223271bffdcdSAmine Khaldi return row; 223371bffdcdSAmine Khaldi } 223471bffdcdSAmine Khaldi else if (!strcmpW(name, szTime)) 223571bffdcdSAmine Khaldi { 223671bffdcdSAmine Khaldi length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0); 223771bffdcdSAmine Khaldi if (!length) 223871bffdcdSAmine Khaldi return NULL; 223971bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2240fec16ab0SAmine Khaldi GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length); 224171bffdcdSAmine Khaldi 224271bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 224371bffdcdSAmine Khaldi if (!row) 2244f8b992f2SAmine Khaldi { 2245f8b992f2SAmine Khaldi msi_free(buffer); 224671bffdcdSAmine Khaldi return NULL; 2247f8b992f2SAmine Khaldi } 224871bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 224971bffdcdSAmine Khaldi msi_free(buffer); 225071bffdcdSAmine Khaldi return row; 225171bffdcdSAmine Khaldi } 225271bffdcdSAmine Khaldi 2253c2c66affSColin Finck rec = MSI_CreateRecord(1); 2254c2c66affSColin Finck if (!rec) 2255c2c66affSColin Finck return NULL; 2256c2c66affSColin Finck 2257c2c66affSColin Finck MSI_RecordSetStringW(rec, 1, name); 2258c2c66affSColin Finck 2259c2c66affSColin Finck r = MSI_DatabaseOpenViewW(db, query, &view); 2260c2c66affSColin Finck if (r == ERROR_SUCCESS) 2261c2c66affSColin Finck { 2262c2c66affSColin Finck MSI_ViewExecute(view, rec); 2263c2c66affSColin Finck MSI_ViewFetch(view, &row); 2264c2c66affSColin Finck MSI_ViewClose(view); 2265c2c66affSColin Finck msiobj_release(&view->hdr); 2266c2c66affSColin Finck } 2267c2c66affSColin Finck msiobj_release(&rec->hdr); 2268c2c66affSColin Finck return row; 2269c2c66affSColin Finck } 2270c2c66affSColin Finck 2271c2c66affSColin Finck /* internal function, not compatible with MsiGetPropertyW */ 2272c2c66affSColin Finck UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, 2273c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2274c2c66affSColin Finck { 2275c2c66affSColin Finck MSIRECORD *row; 2276c2c66affSColin Finck UINT rc = ERROR_FUNCTION_FAILED; 2277c2c66affSColin Finck 2278c2c66affSColin Finck TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf); 2279c2c66affSColin Finck 2280c2c66affSColin Finck row = msi_get_property_row( db, szName ); 2281c2c66affSColin Finck 2282c2c66affSColin Finck if (*pchValueBuf > 0) 2283c2c66affSColin Finck szValueBuf[0] = 0; 2284c2c66affSColin Finck 2285c2c66affSColin Finck if (row) 2286c2c66affSColin Finck { 2287c2c66affSColin Finck rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); 2288c2c66affSColin Finck msiobj_release(&row->hdr); 2289c2c66affSColin Finck } 2290c2c66affSColin Finck 2291c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2292c2c66affSColin Finck TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), 2293c2c66affSColin Finck debugstr_w(szName)); 2294c2c66affSColin Finck else if (rc == ERROR_MORE_DATA) 2295c2c66affSColin Finck TRACE("need %d sized buffer for %s\n", *pchValueBuf, 2296c2c66affSColin Finck debugstr_w(szName)); 2297c2c66affSColin Finck else 2298c2c66affSColin Finck { 2299c2c66affSColin Finck *pchValueBuf = 0; 2300c2c66affSColin Finck TRACE("property %s not found\n", debugstr_w(szName)); 2301c2c66affSColin Finck } 2302c2c66affSColin Finck 2303c2c66affSColin Finck return rc; 2304c2c66affSColin Finck } 2305c2c66affSColin Finck 2306c2c66affSColin Finck LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2307c2c66affSColin Finck { 2308c2c66affSColin Finck DWORD sz = 0; 2309c2c66affSColin Finck LPWSTR str; 2310c2c66affSColin Finck UINT r; 2311c2c66affSColin Finck 2312c2c66affSColin Finck r = msi_get_property(db, prop, NULL, &sz); 2313c2c66affSColin Finck if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2314c2c66affSColin Finck return NULL; 2315c2c66affSColin Finck 2316c2c66affSColin Finck sz++; 2317c2c66affSColin Finck str = msi_alloc(sz * sizeof(WCHAR)); 2318c2c66affSColin Finck r = msi_get_property(db, prop, str, &sz); 2319c2c66affSColin Finck if (r != ERROR_SUCCESS) 2320c2c66affSColin Finck { 2321c2c66affSColin Finck msi_free(str); 2322c2c66affSColin Finck str = NULL; 2323c2c66affSColin Finck } 2324c2c66affSColin Finck 2325c2c66affSColin Finck return str; 2326c2c66affSColin Finck } 2327c2c66affSColin Finck 2328c2c66affSColin Finck int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2329c2c66affSColin Finck { 2330c2c66affSColin Finck LPWSTR str = msi_dup_property( db, prop ); 2331c2c66affSColin Finck int val = str ? atoiW(str) : def; 2332c2c66affSColin Finck msi_free(str); 2333c2c66affSColin Finck return val; 2334c2c66affSColin Finck } 2335c2c66affSColin Finck 2336c2c66affSColin Finck static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, 2337c2c66affSColin Finck awstring *szValueBuf, LPDWORD pchValueBuf ) 2338c2c66affSColin Finck { 2339c2c66affSColin Finck MSIPACKAGE *package; 2340c2c66affSColin Finck MSIRECORD *row = NULL; 2341c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 2342c2c66affSColin Finck LPCWSTR val = NULL; 2343c2c66affSColin Finck DWORD len = 0; 2344c2c66affSColin Finck 2345c2c66affSColin Finck TRACE("%u %s %p %p\n", handle, debugstr_w(name), 2346c2c66affSColin Finck szValueBuf->str.w, pchValueBuf ); 2347c2c66affSColin Finck 2348c2c66affSColin Finck if (!name) 2349c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 2350c2c66affSColin Finck 2351c2c66affSColin Finck package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); 2352c2c66affSColin Finck if (!package) 2353c2c66affSColin Finck { 235462ababd7Swinesync LPWSTR value = NULL, buffer; 2355b74b77aaSwinesync MSIHANDLE remote; 2356c2c66affSColin Finck 2357b74b77aaSwinesync if (!(remote = msi_get_remote(handle))) 2358c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2359c2c66affSColin Finck 236062ababd7Swinesync r = remote_GetProperty(remote, name, &value, &len); 236162ababd7Swinesync if (r != ERROR_SUCCESS) 236262ababd7Swinesync return r; 2363c2c66affSColin Finck 236462ababd7Swinesync /* String might contain embedded nulls. 236562ababd7Swinesync * Native returns the correct size but truncates the string. */ 236662ababd7Swinesync buffer = heap_alloc_zero((len + 1) * sizeof(WCHAR)); 236762ababd7Swinesync if (!buffer) 2368c2c66affSColin Finck { 236962ababd7Swinesync midl_user_free(value); 237062ababd7Swinesync return ERROR_OUTOFMEMORY; 2371c2c66affSColin Finck } 237262ababd7Swinesync strcpyW(buffer, value); 2373c2c66affSColin Finck 237462ababd7Swinesync r = msi_strcpy_to_awstring(buffer, len, szValueBuf, pchValueBuf); 2375c2c66affSColin Finck 2376c2c66affSColin Finck /* Bug required by Adobe installers */ 237762ababd7Swinesync if (pchValueBuf && !szValueBuf->unicode && !szValueBuf->str.a) 2378c2c66affSColin Finck *pchValueBuf *= sizeof(WCHAR); 2379c2c66affSColin Finck 238062ababd7Swinesync heap_free(buffer); 238162ababd7Swinesync midl_user_free(value); 2382c2c66affSColin Finck return r; 2383c2c66affSColin Finck } 2384c2c66affSColin Finck 2385c2c66affSColin Finck row = msi_get_property_row( package->db, name ); 2386c2c66affSColin Finck if (row) 2387c2c66affSColin Finck val = msi_record_get_string( row, 1, (int *)&len ); 2388c2c66affSColin Finck 2389c2c66affSColin Finck if (!val) 2390c2c66affSColin Finck val = szEmpty; 2391c2c66affSColin Finck 2392c2c66affSColin Finck r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf ); 2393c2c66affSColin Finck 2394c2c66affSColin Finck if (row) 2395c2c66affSColin Finck msiobj_release( &row->hdr ); 2396c2c66affSColin Finck msiobj_release( &package->hdr ); 2397c2c66affSColin Finck 2398c2c66affSColin Finck return r; 2399c2c66affSColin Finck } 2400c2c66affSColin Finck 2401c2c66affSColin Finck UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName, 2402c2c66affSColin Finck LPSTR szValueBuf, LPDWORD pchValueBuf ) 2403c2c66affSColin Finck { 2404c2c66affSColin Finck awstring val; 2405c2c66affSColin Finck LPWSTR name; 2406c2c66affSColin Finck UINT r; 2407c2c66affSColin Finck 2408c2c66affSColin Finck val.unicode = FALSE; 2409c2c66affSColin Finck val.str.a = szValueBuf; 2410c2c66affSColin Finck 2411c2c66affSColin Finck name = strdupAtoW( szName ); 2412c2c66affSColin Finck if (szName && !name) 2413c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2414c2c66affSColin Finck 2415c2c66affSColin Finck r = MSI_GetProperty( hInstall, name, &val, pchValueBuf ); 2416c2c66affSColin Finck msi_free( name ); 2417c2c66affSColin Finck return r; 2418c2c66affSColin Finck } 2419c2c66affSColin Finck 2420c2c66affSColin Finck UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, 2421c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2422c2c66affSColin Finck { 2423c2c66affSColin Finck awstring val; 2424c2c66affSColin Finck 2425c2c66affSColin Finck val.unicode = TRUE; 2426c2c66affSColin Finck val.str.w = szValueBuf; 2427c2c66affSColin Finck 2428c2c66affSColin Finck return MSI_GetProperty( hInstall, szName, &val, pchValueBuf ); 2429c2c66affSColin Finck } 2430c2c66affSColin Finck 24317cc54a4fSwinesync MSIHANDLE __cdecl remote_GetActiveDatabase(MSIHANDLE hinst) 2432b74b77aaSwinesync { 24337cc54a4fSwinesync return MsiGetActiveDatabase(hinst); 2434c2c66affSColin Finck } 2435c2c66affSColin Finck 243662ababd7Swinesync UINT __cdecl remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size) 2437c2c66affSColin Finck { 243862ababd7Swinesync WCHAR empty[1]; 243962ababd7Swinesync UINT r; 244062ababd7Swinesync 244162ababd7Swinesync *size = 0; 244262ababd7Swinesync r = MsiGetPropertyW(hinst, property, empty, size); 244362ababd7Swinesync if (r == ERROR_MORE_DATA) 244462ababd7Swinesync { 244562ababd7Swinesync ++*size; 244662ababd7Swinesync *value = midl_user_allocate(*size * sizeof(WCHAR)); 244762ababd7Swinesync if (!*value) 244862ababd7Swinesync return ERROR_OUTOFMEMORY; 244962ababd7Swinesync r = MsiGetPropertyW(hinst, property, *value, size); 245062ababd7Swinesync } 245162ababd7Swinesync return r; 2452c2c66affSColin Finck } 2453c2c66affSColin Finck 24543431091cSwinesync UINT __cdecl remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value) 2455c2c66affSColin Finck { 24563431091cSwinesync return MsiSetPropertyW(hinst, property, value); 2457c2c66affSColin Finck } 2458c2c66affSColin Finck 24592e19edd6Swinesync int __cdecl remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, struct wire_record *remote_rec) 2460c2c66affSColin Finck { 24612e19edd6Swinesync MSIHANDLE rec; 24622e19edd6Swinesync int ret; 24632e19edd6Swinesync UINT r; 24642e19edd6Swinesync 24652e19edd6Swinesync if ((r = unmarshal_record(remote_rec, &rec))) 24662e19edd6Swinesync return r; 24672e19edd6Swinesync 24682e19edd6Swinesync ret = MsiProcessMessage(hinst, message, rec); 24692e19edd6Swinesync 24702e19edd6Swinesync MsiCloseHandle(rec); 24712e19edd6Swinesync return ret; 2472c2c66affSColin Finck } 2473c2c66affSColin Finck 2474c65c209aSwinesync UINT __cdecl remote_DoAction(MSIHANDLE hinst, LPCWSTR action) 2475c2c66affSColin Finck { 2476c65c209aSwinesync return MsiDoActionW(hinst, action); 2477c2c66affSColin Finck } 2478c2c66affSColin Finck 247910abb6f6Swinesync UINT __cdecl remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence) 2480c2c66affSColin Finck { 248110abb6f6Swinesync return MsiSequenceW(hinst, table, sequence); 2482c2c66affSColin Finck } 2483c2c66affSColin Finck 2484a529a627Swinesync UINT __cdecl remote_GetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2485c2c66affSColin Finck { 2486a529a627Swinesync WCHAR empty[1]; 2487a529a627Swinesync DWORD size = 0; 2488a529a627Swinesync UINT r; 2489a529a627Swinesync 2490a529a627Swinesync r = MsiGetTargetPathW(hinst, folder, empty, &size); 2491a529a627Swinesync if (r == ERROR_MORE_DATA) 2492a529a627Swinesync { 2493a529a627Swinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 2494a529a627Swinesync if (!*value) 2495a529a627Swinesync return ERROR_OUTOFMEMORY; 2496a529a627Swinesync r = MsiGetTargetPathW(hinst, folder, *value, &size); 2497a529a627Swinesync } 2498a529a627Swinesync return r; 2499c2c66affSColin Finck } 2500c2c66affSColin Finck 2501a5e21001Swinesync UINT __cdecl remote_SetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPCWSTR value) 2502c2c66affSColin Finck { 2503a5e21001Swinesync return MsiSetTargetPathW(hinst, folder, value); 2504c2c66affSColin Finck } 2505c2c66affSColin Finck 25064253f351Swinesync UINT __cdecl remote_GetSourcePath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2507c2c66affSColin Finck { 25084253f351Swinesync WCHAR empty[1]; 25094253f351Swinesync DWORD size = 1; 25104253f351Swinesync UINT r; 25114253f351Swinesync 25124253f351Swinesync r = MsiGetSourcePathW(hinst, folder, empty, &size); 25134253f351Swinesync if (r == ERROR_MORE_DATA) 25144253f351Swinesync { 25154253f351Swinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 25164253f351Swinesync if (!*value) 25174253f351Swinesync return ERROR_OUTOFMEMORY; 25184253f351Swinesync r = MsiGetSourcePathW(hinst, folder, *value, &size); 25194253f351Swinesync } 25204253f351Swinesync return r; 2521c2c66affSColin Finck } 2522c2c66affSColin Finck 252383bbe8c8Swinesync BOOL __cdecl remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode) 2524c2c66affSColin Finck { 252583bbe8c8Swinesync return MsiGetMode(hinst, mode); 2526c2c66affSColin Finck } 2527c2c66affSColin Finck 25285219367eSwinesync UINT __cdecl remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state) 2529c2c66affSColin Finck { 25305219367eSwinesync return MsiSetMode(hinst, mode, state); 2531c2c66affSColin Finck } 2532c2c66affSColin Finck 2533*ed5fbe39Swinesync UINT __cdecl remote_GetFeatureState(MSIHANDLE hinst, LPCWSTR feature, 2534c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2535c2c66affSColin Finck { 2536*ed5fbe39Swinesync return MsiGetFeatureStateW(hinst, feature, installed, action); 2537c2c66affSColin Finck } 2538c2c66affSColin Finck 2539b74b77aaSwinesync HRESULT __cdecl remote_SetFeatureState(MSIHANDLE hinst, BSTR feature, INSTALLSTATE state) 2540c2c66affSColin Finck { 2541b74b77aaSwinesync UINT r = MsiSetFeatureStateW(hinst, feature, state); 2542c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2543c2c66affSColin Finck } 2544c2c66affSColin Finck 2545b74b77aaSwinesync HRESULT __cdecl remote_GetComponentState(MSIHANDLE hinst, BSTR component, 2546c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2547c2c66affSColin Finck { 2548b74b77aaSwinesync UINT r = MsiGetComponentStateW(hinst, component, installed, action); 2549c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2550c2c66affSColin Finck } 2551c2c66affSColin Finck 2552b74b77aaSwinesync HRESULT __cdecl remote_SetComponentState(MSIHANDLE hinst, BSTR component, INSTALLSTATE state) 2553c2c66affSColin Finck { 2554b74b77aaSwinesync UINT r = MsiSetComponentStateW(hinst, component, state); 2555c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2556c2c66affSColin Finck } 2557c2c66affSColin Finck 2558b74b77aaSwinesync HRESULT __cdecl remote_GetLanguage(MSIHANDLE hinst, LANGID *language) 2559c2c66affSColin Finck { 2560b74b77aaSwinesync *language = MsiGetLanguage(hinst); 2561c2c66affSColin Finck return S_OK; 2562c2c66affSColin Finck } 2563c2c66affSColin Finck 2564b74b77aaSwinesync HRESULT __cdecl remote_SetInstallLevel(MSIHANDLE hinst, int level) 2565c2c66affSColin Finck { 2566b74b77aaSwinesync UINT r = MsiSetInstallLevel(hinst, level); 2567c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2568c2c66affSColin Finck } 2569c2c66affSColin Finck 2570b74b77aaSwinesync HRESULT __cdecl remote_FormatRecord(MSIHANDLE hinst, MSIHANDLE record, 2571c2c66affSColin Finck BSTR *value) 2572c2c66affSColin Finck { 2573c2c66affSColin Finck DWORD size = 0; 2574b74b77aaSwinesync UINT r = MsiFormatRecordW(hinst, record, NULL, &size); 2575c2c66affSColin Finck if (r == ERROR_SUCCESS) 2576c2c66affSColin Finck { 2577c2c66affSColin Finck *value = SysAllocStringLen(NULL, size); 2578c2c66affSColin Finck if (!*value) 2579c2c66affSColin Finck return E_OUTOFMEMORY; 2580c2c66affSColin Finck size++; 2581b74b77aaSwinesync r = MsiFormatRecordW(hinst, record, *value, &size); 2582c2c66affSColin Finck } 2583c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2584c2c66affSColin Finck } 2585c2c66affSColin Finck 2586b74b77aaSwinesync HRESULT __cdecl remote_EvaluateCondition(MSIHANDLE hinst, BSTR condition) 2587c2c66affSColin Finck { 2588b74b77aaSwinesync UINT r = MsiEvaluateConditionW(hinst, condition); 2589c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2590c2c66affSColin Finck } 2591c2c66affSColin Finck 2592b74b77aaSwinesync HRESULT __cdecl remote_GetFeatureCost(MSIHANDLE hinst, BSTR feature, 2593c2c66affSColin Finck INT cost_tree, INSTALLSTATE state, INT *cost) 2594c2c66affSColin Finck { 2595b74b77aaSwinesync UINT r = MsiGetFeatureCostW(hinst, feature, cost_tree, state, cost); 2596c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2597c2c66affSColin Finck } 2598c2c66affSColin Finck 2599b74b77aaSwinesync HRESULT __cdecl remote_EnumComponentCosts(MSIHANDLE hinst, BSTR component, 2600c2c66affSColin Finck DWORD index, INSTALLSTATE state, BSTR drive, 2601c2c66affSColin Finck DWORD *buflen, INT *cost, INT *temp) 2602c2c66affSColin Finck { 2603b74b77aaSwinesync UINT r = MsiEnumComponentCostsW(hinst, component, index, state, drive, buflen, cost, temp); 2604c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2605c2c66affSColin Finck } 2606c2c66affSColin Finck 2607c2c66affSColin Finck UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2608c2c66affSColin Finck LPCWSTR property, LPWSTR value) 2609c2c66affSColin Finck { 2610c2c66affSColin Finck MSISOURCELISTINFO *info; 2611c2c66affSColin Finck 2612c2c66affSColin Finck LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2613c2c66affSColin Finck { 2614c2c66affSColin Finck if (!strcmpW( info->value, value )) return ERROR_SUCCESS; 2615c2c66affSColin Finck } 2616c2c66affSColin Finck 2617c2c66affSColin Finck info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2618c2c66affSColin Finck if (!info) 2619c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2620c2c66affSColin Finck 2621c2c66affSColin Finck info->context = context; 2622c2c66affSColin Finck info->options = options; 2623c2c66affSColin Finck info->property = property; 2624c2c66affSColin Finck info->value = strdupW(value); 2625c2c66affSColin Finck list_add_head(&package->sourcelist_info, &info->entry); 2626c2c66affSColin Finck 2627c2c66affSColin Finck return ERROR_SUCCESS; 2628c2c66affSColin Finck } 2629c2c66affSColin Finck 2630c2c66affSColin Finck UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2631c2c66affSColin Finck DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2632c2c66affSColin Finck { 2633c2c66affSColin Finck MSIMEDIADISK *disk; 2634c2c66affSColin Finck 2635c2c66affSColin Finck LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2636c2c66affSColin Finck { 2637c2c66affSColin Finck if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2638c2c66affSColin Finck } 2639c2c66affSColin Finck 2640c2c66affSColin Finck disk = msi_alloc(sizeof(MSIMEDIADISK)); 2641c2c66affSColin Finck if (!disk) 2642c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2643c2c66affSColin Finck 2644c2c66affSColin Finck disk->context = context; 2645c2c66affSColin Finck disk->options = options; 2646c2c66affSColin Finck disk->disk_id = disk_id; 2647c2c66affSColin Finck disk->volume_label = strdupW(volume_label); 2648c2c66affSColin Finck disk->disk_prompt = strdupW(disk_prompt); 2649c2c66affSColin Finck list_add_head(&package->sourcelist_media, &disk->entry); 2650c2c66affSColin Finck 2651c2c66affSColin Finck return ERROR_SUCCESS; 2652c2c66affSColin Finck } 2653