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->BaseURL ); 325c2c66affSColin Finck msi_free( package->PackagePath ); 326c2c66affSColin Finck msi_free( package->ProductCode ); 327c2c66affSColin Finck msi_free( package->ActionFormat ); 328c2c66affSColin Finck msi_free( package->LastAction ); 32971bffdcdSAmine Khaldi msi_free( package->LastActionTemplate ); 330c2c66affSColin Finck msi_free( package->langids ); 331c2c66affSColin Finck 332c2c66affSColin Finck /* cleanup control event subscriptions */ 333c2c66affSColin Finck msi_event_cleanup_all_subscriptions( package ); 334c2c66affSColin Finck } 335c2c66affSColin Finck 336c2c66affSColin Finck static void MSI_FreePackage( MSIOBJECTHDR *arg) 337c2c66affSColin Finck { 338c2c66affSColin Finck MSIPACKAGE *package = (MSIPACKAGE *)arg; 339c2c66affSColin Finck 340c2c66affSColin Finck msi_destroy_assembly_caches( package ); 341c2c66affSColin Finck 342c2c66affSColin Finck if( package->dialog ) 343c2c66affSColin Finck msi_dialog_destroy( package->dialog ); 344c2c66affSColin Finck 345c2c66affSColin Finck msiobj_release( &package->db->hdr ); 346c2c66affSColin Finck free_package_structures(package); 347c2c66affSColin Finck CloseHandle( package->log_file ); 348c2c66affSColin Finck 349c2c66affSColin Finck if (package->delete_on_close) DeleteFileW( package->localfile ); 350c2c66affSColin Finck msi_free( package->localfile ); 35171bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 352c2c66affSColin Finck } 353c2c66affSColin Finck 354c2c66affSColin Finck static UINT create_temp_property_table(MSIPACKAGE *package) 355c2c66affSColin Finck { 356c2c66affSColin Finck static const WCHAR query[] = { 357c2c66affSColin Finck 'C','R','E','A','T','E',' ','T','A','B','L','E',' ', 358c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ', 359c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 360c2c66affSColin Finck 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ', 361c2c66affSColin Finck 'T','E','M','P','O','R','A','R','Y',',',' ', 362c2c66affSColin Finck '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ', 363c2c66affSColin Finck 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y', 364c2c66affSColin Finck ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ', 365c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0}; 366c2c66affSColin Finck MSIQUERY *view; 367c2c66affSColin Finck UINT rc; 368c2c66affSColin Finck 369c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(package->db, query, &view); 370c2c66affSColin Finck if (rc != ERROR_SUCCESS) 371c2c66affSColin Finck return rc; 372c2c66affSColin Finck 373c2c66affSColin Finck rc = MSI_ViewExecute(view, 0); 374c2c66affSColin Finck MSI_ViewClose(view); 375c2c66affSColin Finck msiobj_release(&view->hdr); 376c2c66affSColin Finck return rc; 377c2c66affSColin Finck } 378c2c66affSColin Finck 379c2c66affSColin Finck UINT msi_clone_properties( MSIDATABASE *db ) 380c2c66affSColin Finck { 381c2c66affSColin Finck static const WCHAR query_select[] = { 382c2c66affSColin Finck 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 383c2c66affSColin Finck '`','P','r','o','p','e','r','t','y','`',0}; 384c2c66affSColin Finck static const WCHAR query_insert[] = { 385c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 386c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 387c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 388c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 389c2c66affSColin Finck static const WCHAR query_update[] = { 390c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 391c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ', 392c2c66affSColin Finck 'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0}; 393c2c66affSColin Finck MSIQUERY *view_select; 394c2c66affSColin Finck UINT rc; 395c2c66affSColin Finck 396c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_select, &view_select ); 397c2c66affSColin Finck if (rc != ERROR_SUCCESS) 398c2c66affSColin Finck return rc; 399c2c66affSColin Finck 400c2c66affSColin Finck rc = MSI_ViewExecute( view_select, 0 ); 401c2c66affSColin Finck if (rc != ERROR_SUCCESS) 402c2c66affSColin Finck { 403c2c66affSColin Finck MSI_ViewClose( view_select ); 404c2c66affSColin Finck msiobj_release( &view_select->hdr ); 405c2c66affSColin Finck return rc; 406c2c66affSColin Finck } 407c2c66affSColin Finck 408c2c66affSColin Finck while (1) 409c2c66affSColin Finck { 410c2c66affSColin Finck MSIQUERY *view_insert, *view_update; 411c2c66affSColin Finck MSIRECORD *rec_select; 412c2c66affSColin Finck 413c2c66affSColin Finck rc = MSI_ViewFetch( view_select, &rec_select ); 414c2c66affSColin Finck if (rc != ERROR_SUCCESS) 415c2c66affSColin Finck break; 416c2c66affSColin Finck 417c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert ); 418c2c66affSColin Finck if (rc != ERROR_SUCCESS) 419c2c66affSColin Finck { 420c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 421c2c66affSColin Finck continue; 422c2c66affSColin Finck } 423c2c66affSColin Finck 424c2c66affSColin Finck rc = MSI_ViewExecute( view_insert, rec_select ); 425c2c66affSColin Finck MSI_ViewClose( view_insert ); 426c2c66affSColin Finck msiobj_release( &view_insert->hdr ); 427c2c66affSColin Finck if (rc != ERROR_SUCCESS) 428c2c66affSColin Finck { 429c2c66affSColin Finck MSIRECORD *rec_update; 430c2c66affSColin Finck 431c2c66affSColin Finck TRACE("insert failed, trying update\n"); 432c2c66affSColin Finck 433c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_update, &view_update ); 434c2c66affSColin Finck if (rc != ERROR_SUCCESS) 435c2c66affSColin Finck { 436c2c66affSColin Finck WARN("open view failed %u\n", rc); 437c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 438c2c66affSColin Finck continue; 439c2c66affSColin Finck } 440c2c66affSColin Finck 441c2c66affSColin Finck rec_update = MSI_CreateRecord( 2 ); 442c2c66affSColin Finck MSI_RecordCopyField( rec_select, 1, rec_update, 2 ); 443c2c66affSColin Finck MSI_RecordCopyField( rec_select, 2, rec_update, 1 ); 444c2c66affSColin Finck rc = MSI_ViewExecute( view_update, rec_update ); 445c2c66affSColin Finck if (rc != ERROR_SUCCESS) 446c2c66affSColin Finck WARN("update failed %u\n", rc); 447c2c66affSColin Finck 448c2c66affSColin Finck MSI_ViewClose( view_update ); 449c2c66affSColin Finck msiobj_release( &view_update->hdr ); 450c2c66affSColin Finck msiobj_release( &rec_update->hdr ); 451c2c66affSColin Finck } 452c2c66affSColin Finck 453c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 454c2c66affSColin Finck } 455c2c66affSColin Finck 456c2c66affSColin Finck MSI_ViewClose( view_select ); 457c2c66affSColin Finck msiobj_release( &view_select->hdr ); 458c2c66affSColin Finck return rc; 459c2c66affSColin Finck } 460c2c66affSColin Finck 461c2c66affSColin Finck /* 462c2c66affSColin Finck * set_installed_prop 463c2c66affSColin Finck * 464c2c66affSColin Finck * Sets the "Installed" property to indicate that 465c2c66affSColin Finck * the product is installed for the current user. 466c2c66affSColin Finck */ 467c2c66affSColin Finck static UINT set_installed_prop( MSIPACKAGE *package ) 468c2c66affSColin Finck { 469c2c66affSColin Finck HKEY hkey; 470c2c66affSColin Finck UINT r; 471c2c66affSColin Finck 472c2c66affSColin Finck if (!package->ProductCode) return ERROR_FUNCTION_FAILED; 473c2c66affSColin Finck 474c2c66affSColin Finck r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE ); 475c2c66affSColin Finck if (r == ERROR_SUCCESS) 476c2c66affSColin Finck { 477c2c66affSColin Finck RegCloseKey( hkey ); 478c2c66affSColin Finck msi_set_property( package->db, szInstalled, szOne, -1 ); 479c2c66affSColin Finck } 480c2c66affSColin Finck return r; 481c2c66affSColin Finck } 482c2c66affSColin Finck 483c2c66affSColin Finck static UINT set_user_sid_prop( MSIPACKAGE *package ) 484c2c66affSColin Finck { 485c2c66affSColin Finck SID_NAME_USE use; 486c2c66affSColin Finck LPWSTR user_name; 487c2c66affSColin Finck LPWSTR sid_str = NULL, dom = NULL; 488c2c66affSColin Finck DWORD size, dom_size; 489c2c66affSColin Finck PSID psid = NULL; 490c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 491c2c66affSColin Finck 492c2c66affSColin Finck size = 0; 493c2c66affSColin Finck GetUserNameW( NULL, &size ); 494c2c66affSColin Finck 495c2c66affSColin Finck user_name = msi_alloc( (size + 1) * sizeof(WCHAR) ); 496c2c66affSColin Finck if (!user_name) 497c2c66affSColin Finck return ERROR_OUTOFMEMORY; 498c2c66affSColin Finck 499c2c66affSColin Finck if (!GetUserNameW( user_name, &size )) 500c2c66affSColin Finck goto done; 501c2c66affSColin Finck 502c2c66affSColin Finck size = 0; 503c2c66affSColin Finck dom_size = 0; 504c2c66affSColin Finck LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use ); 505c2c66affSColin Finck 506c2c66affSColin Finck psid = msi_alloc( size ); 507c2c66affSColin Finck dom = msi_alloc( dom_size*sizeof (WCHAR) ); 508c2c66affSColin Finck if (!psid || !dom) 509c2c66affSColin Finck { 510c2c66affSColin Finck r = ERROR_OUTOFMEMORY; 511c2c66affSColin Finck goto done; 512c2c66affSColin Finck } 513c2c66affSColin Finck 514c2c66affSColin Finck if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use )) 515c2c66affSColin Finck goto done; 516c2c66affSColin Finck 517c2c66affSColin Finck if (!ConvertSidToStringSidW( psid, &sid_str )) 518c2c66affSColin Finck goto done; 519c2c66affSColin Finck 520c2c66affSColin Finck r = msi_set_property( package->db, szUserSID, sid_str, -1 ); 521c2c66affSColin Finck 522c2c66affSColin Finck done: 523c2c66affSColin Finck LocalFree( sid_str ); 524c2c66affSColin Finck msi_free( dom ); 525c2c66affSColin Finck msi_free( psid ); 526c2c66affSColin Finck msi_free( user_name ); 527c2c66affSColin Finck 528c2c66affSColin Finck return r; 529c2c66affSColin Finck } 530c2c66affSColin Finck 531c2c66affSColin Finck static LPWSTR get_fusion_filename(MSIPACKAGE *package) 532c2c66affSColin Finck { 533c42b133eSAmine Khaldi static const WCHAR fusion[] = 534c42b133eSAmine Khaldi {'f','u','s','i','o','n','.','d','l','l',0}; 535c42b133eSAmine Khaldi static const WCHAR subkey[] = 536c42b133eSAmine Khaldi {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 537c42b133eSAmine Khaldi 'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\','N','D','P',0}; 538c42b133eSAmine Khaldi static const WCHAR subdir[] = 539c42b133eSAmine Khaldi {'M','i','c','r','o','s','o','f','t','.','N','E','T','\\','F','r','a','m','e','w','o','r','k','\\',0}; 540c42b133eSAmine Khaldi static const WCHAR v2050727[] = 541c42b133eSAmine Khaldi {'v','2','.','0','.','5','0','7','2','7',0}; 542c42b133eSAmine Khaldi static const WCHAR v4client[] = 543c42b133eSAmine Khaldi {'v','4','\\','C','l','i','e','n','t',0}; 544c42b133eSAmine Khaldi static const WCHAR installpath[] = 545c42b133eSAmine Khaldi {'I','n','s','t','a','l','l','P','a','t','h',0}; 546c42b133eSAmine Khaldi HKEY netsetup, hkey; 547c2c66affSColin Finck LONG res; 548c42b133eSAmine Khaldi DWORD size, len, type; 549c42b133eSAmine Khaldi WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL; 550c2c66affSColin Finck 551c42b133eSAmine Khaldi res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, subkey, 0, KEY_CREATE_SUB_KEY, &netsetup); 552c2c66affSColin Finck if (res != ERROR_SUCCESS) 553c2c66affSColin Finck return NULL; 554c2c66affSColin Finck 555c42b133eSAmine Khaldi if (!RegCreateKeyExW(netsetup, v4client, 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 556c42b133eSAmine Khaldi { 557c42b133eSAmine Khaldi size = sizeof(path)/sizeof(path[0]); 558c42b133eSAmine Khaldi if (!RegQueryValueExW(hkey, installpath, NULL, &type, (BYTE *)path, &size)) 559c42b133eSAmine Khaldi { 560c42b133eSAmine Khaldi len = strlenW(path) + strlenW(fusion) + 2; 561c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 562c42b133eSAmine Khaldi 563c42b133eSAmine Khaldi strcpyW(filename, path); 564c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 565c42b133eSAmine Khaldi strcatW(filename, fusion); 566c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 567c42b133eSAmine Khaldi { 568c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 569c42b133eSAmine Khaldi RegCloseKey(hkey); 570c42b133eSAmine Khaldi RegCloseKey(netsetup); 571c42b133eSAmine Khaldi return filename; 572c42b133eSAmine Khaldi } 573c42b133eSAmine Khaldi } 574c42b133eSAmine Khaldi RegCloseKey(hkey); 575c42b133eSAmine Khaldi } 576c42b133eSAmine Khaldi 577c42b133eSAmine Khaldi if (!RegCreateKeyExW(netsetup, v2050727, 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 578c42b133eSAmine Khaldi { 579c42b133eSAmine Khaldi RegCloseKey(hkey); 580c2c66affSColin Finck GetWindowsDirectoryW(windir, MAX_PATH); 581c42b133eSAmine Khaldi len = strlenW(windir) + strlenW(subdir) + strlenW(v2050727) + strlenW(fusion) + 3; 582c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 583c2c66affSColin Finck 584c42b133eSAmine Khaldi strcpyW(filename, windir); 585c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 586c42b133eSAmine Khaldi strcatW(filename, subdir); 587c42b133eSAmine Khaldi strcatW(filename, v2050727); 588c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 589c42b133eSAmine Khaldi strcatW(filename, fusion); 590c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 591c2c66affSColin Finck { 592c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 593c42b133eSAmine Khaldi RegCloseKey(netsetup); 594c42b133eSAmine Khaldi return filename; 595c2c66affSColin Finck } 596c2c66affSColin Finck } 597c2c66affSColin Finck 598c2c66affSColin Finck RegCloseKey(netsetup); 599c42b133eSAmine Khaldi return filename; 600c2c66affSColin Finck } 601c2c66affSColin Finck 602c2c66affSColin Finck typedef struct tagLANGANDCODEPAGE 603c2c66affSColin Finck { 604c2c66affSColin Finck WORD wLanguage; 605c2c66affSColin Finck WORD wCodePage; 606c2c66affSColin Finck } LANGANDCODEPAGE; 607c2c66affSColin Finck 608c2c66affSColin Finck static void set_msi_assembly_prop(MSIPACKAGE *package) 609c2c66affSColin Finck { 610c2c66affSColin Finck UINT val_len; 611c2c66affSColin Finck DWORD size, handle; 612c2c66affSColin Finck LPVOID version = NULL; 613c2c66affSColin Finck WCHAR buf[MAX_PATH]; 614c2c66affSColin Finck LPWSTR fusion, verstr; 615c2c66affSColin Finck LANGANDCODEPAGE *translate; 616c2c66affSColin Finck 617c2c66affSColin Finck static const WCHAR netasm[] = { 618c2c66affSColin Finck 'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0 619c2c66affSColin Finck }; 620c2c66affSColin Finck static const WCHAR translation[] = { 621c2c66affSColin Finck '\\','V','a','r','F','i','l','e','I','n','f','o', 622c2c66affSColin Finck '\\','T','r','a','n','s','l','a','t','i','o','n',0 623c2c66affSColin Finck }; 624c2c66affSColin Finck static const WCHAR verfmt[] = { 625c2c66affSColin Finck '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o', 626c2c66affSColin Finck '\\','%','0','4','x','%','0','4','x', 627c2c66affSColin Finck '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 628c2c66affSColin Finck }; 629c2c66affSColin Finck 630c2c66affSColin Finck fusion = get_fusion_filename(package); 631c2c66affSColin Finck if (!fusion) 632c2c66affSColin Finck return; 633c2c66affSColin Finck 634c2c66affSColin Finck size = GetFileVersionInfoSizeW(fusion, &handle); 635c2c66affSColin Finck if (!size) 636c2c66affSColin Finck goto done; 637c2c66affSColin Finck 638c2c66affSColin Finck version = msi_alloc(size); 639c2c66affSColin Finck if (!version) 640c2c66affSColin Finck goto done; 641c2c66affSColin Finck 642c2c66affSColin Finck if (!GetFileVersionInfoW(fusion, handle, size, version)) 643c2c66affSColin Finck goto done; 644c2c66affSColin Finck 645c2c66affSColin Finck if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len)) 646c2c66affSColin Finck goto done; 647c2c66affSColin Finck 648c2c66affSColin Finck sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage); 649c2c66affSColin Finck 650c2c66affSColin Finck if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len)) 651c2c66affSColin Finck goto done; 652c2c66affSColin Finck 653c2c66affSColin Finck if (!val_len || !verstr) 654c2c66affSColin Finck goto done; 655c2c66affSColin Finck 656c2c66affSColin Finck msi_set_property( package->db, netasm, verstr, -1 ); 657c2c66affSColin Finck 658c2c66affSColin Finck done: 659c2c66affSColin Finck msi_free(fusion); 660c2c66affSColin Finck msi_free(version); 661c2c66affSColin Finck } 662c2c66affSColin Finck 663c2c66affSColin Finck static VOID set_installer_properties(MSIPACKAGE *package) 664c2c66affSColin Finck { 665c2c66affSColin Finck WCHAR *ptr; 666c2c66affSColin Finck OSVERSIONINFOEXW OSVersion; 667c2c66affSColin Finck MEMORYSTATUSEX msex; 668c2c66affSColin Finck DWORD verval, len; 669c2c66affSColin Finck WCHAR pth[MAX_PATH], verstr[11], bufstr[22]; 670c2c66affSColin Finck HDC dc; 671c2c66affSColin Finck HKEY hkey; 672c2c66affSColin Finck LPWSTR username, companyname; 673c2c66affSColin Finck SYSTEM_INFO sys_info; 674c2c66affSColin Finck LANGID langid; 675c2c66affSColin Finck 676c2c66affSColin Finck static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0}; 677c2c66affSColin Finck static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0}; 678c2c66affSColin 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}; 679c2c66affSColin Finck static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0}; 680c2c66affSColin Finck static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0}; 681c2c66affSColin Finck static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0}; 682c2c66affSColin Finck static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0}; 683c2c66affSColin Finck static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0}; 684c2c66affSColin Finck static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0}; 685c2c66affSColin Finck static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0}; 686c2c66affSColin Finck static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0}; 687c2c66affSColin Finck static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0}; 688c2c66affSColin Finck static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0}; 689c2c66affSColin Finck static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0}; 690c2c66affSColin Finck static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; 691c2c66affSColin Finck static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0}; 692c2c66affSColin Finck static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0}; 693c2c66affSColin Finck static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0}; 694c2c66affSColin Finck static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0}; 695c2c66affSColin Finck static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0}; 696c2c66affSColin Finck static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0}; 697c2c66affSColin Finck static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0}; 698c2c66affSColin Finck static const WCHAR szFormat[] = {'%','u',0}; 699c2c66affSColin Finck static const WCHAR szFormat2[] = {'%','u','.','%','u',0}; 700c2c66affSColin Finck static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0}; 701c2c66affSColin Finck static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0}; 702c2c66affSColin Finck static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 }; 703c2c66affSColin Finck static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 }; 704c2c66affSColin Finck static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 }; 705c2c66affSColin Finck static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0}; 706c2c66affSColin Finck static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0}; 707c2c66affSColin Finck static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0}; 708c2c66affSColin Finck static const WCHAR szIntFormat[] = {'%','d',0}; 709c2c66affSColin Finck static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 }; 710c2c66affSColin Finck static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 }; 711c2c66affSColin Finck static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 }; 712c2c66affSColin 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 }; 713c2c66affSColin 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 }; 714c2c66affSColin Finck static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 }; 715c2c66affSColin Finck static const WCHAR szUserInfo[] = { 716c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 717c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 718c2c66affSColin Finck 'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\', 719c2c66affSColin Finck 'U','s','e','r',' ','I','n','f','o',0 720c2c66affSColin Finck }; 721c2c66affSColin Finck static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 }; 722c2c66affSColin Finck static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 }; 723c2c66affSColin Finck static const WCHAR szCurrentVersion[] = { 724c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 725c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 726c2c66affSColin Finck 'W','i','n','d','o','w','s',' ','N','T','\\', 727c2c66affSColin Finck 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0 728c2c66affSColin Finck }; 729c2c66affSColin Finck static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0}; 730c2c66affSColin Finck static const WCHAR szRegisteredOrganization[] = { 731c2c66affSColin Finck 'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0 732c2c66affSColin Finck }; 733c2c66affSColin Finck static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0}; 734c2c66affSColin Finck static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0}; 735c2c66affSColin Finck static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0}; 736c2c66affSColin Finck static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0}; 737c2c66affSColin Finck static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0}; 738c2c66affSColin Finck static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0}; 739c2c66affSColin Finck static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0}; 740c2c66affSColin Finck static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0}; 741c2c66affSColin Finck static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0}; 742c2c66affSColin Finck static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0}; 743c2c66affSColin Finck 744c2c66affSColin Finck /* 745c2c66affSColin Finck * Other things that probably should be set: 746c2c66affSColin Finck * 747c2c66affSColin Finck * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging 748c2c66affSColin Finck * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport 749c2c66affSColin Finck */ 750c2c66affSColin Finck 751c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); 752c2c66affSColin Finck strcatW(pth, szBackSlash); 753c2c66affSColin Finck msi_set_property( package->db, szCommonAppDataFolder, pth, -1 ); 754c2c66affSColin Finck 755c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); 756c2c66affSColin Finck strcatW(pth, szBackSlash); 757c2c66affSColin Finck msi_set_property( package->db, szFavoritesFolder, pth, -1 ); 758c2c66affSColin Finck 759c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); 760c2c66affSColin Finck strcatW(pth, szBackSlash); 761c2c66affSColin Finck msi_set_property( package->db, szFontsFolder, pth, -1 ); 762c2c66affSColin Finck 763c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); 764c2c66affSColin Finck strcatW(pth, szBackSlash); 765c2c66affSColin Finck msi_set_property( package->db, szSendToFolder, pth, -1 ); 766c2c66affSColin Finck 767c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); 768c2c66affSColin Finck strcatW(pth, szBackSlash); 769c2c66affSColin Finck msi_set_property( package->db, szStartMenuFolder, pth, -1 ); 770c2c66affSColin Finck 771c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); 772c2c66affSColin Finck strcatW(pth, szBackSlash); 773c2c66affSColin Finck msi_set_property( package->db, szStartupFolder, pth, -1 ); 774c2c66affSColin Finck 775c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); 776c2c66affSColin Finck strcatW(pth, szBackSlash); 777c2c66affSColin Finck msi_set_property( package->db, szTemplateFolder, pth, -1 ); 778c2c66affSColin Finck 779c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); 780c2c66affSColin Finck strcatW(pth, szBackSlash); 781c2c66affSColin Finck msi_set_property( package->db, szDesktopFolder, pth, -1 ); 782c2c66affSColin Finck 783c2c66affSColin Finck /* FIXME: set to AllUsers profile path if ALLUSERS is set */ 784c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); 785c2c66affSColin Finck strcatW(pth, szBackSlash); 786c2c66affSColin Finck msi_set_property( package->db, szProgramMenuFolder, pth, -1 ); 787c2c66affSColin Finck 788c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); 789c2c66affSColin Finck strcatW(pth, szBackSlash); 790c2c66affSColin Finck msi_set_property( package->db, szAdminToolsFolder, pth, -1 ); 791c2c66affSColin Finck 792c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); 793c2c66affSColin Finck strcatW(pth, szBackSlash); 794c2c66affSColin Finck msi_set_property( package->db, szAppDataFolder, pth, -1 ); 795c2c66affSColin Finck 796c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); 797c2c66affSColin Finck strcatW(pth, szBackSlash); 798c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 799c2c66affSColin Finck msi_set_property( package->db, szSystem16Folder, pth, -1 ); 800c2c66affSColin Finck 801c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); 802c2c66affSColin Finck strcatW(pth, szBackSlash); 803c2c66affSColin Finck msi_set_property( package->db, szLocalAppDataFolder, pth, -1 ); 804c2c66affSColin Finck 805c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); 806c2c66affSColin Finck strcatW(pth, szBackSlash); 807c2c66affSColin Finck msi_set_property( package->db, szMyPicturesFolder, pth, -1 ); 808c2c66affSColin Finck 809c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); 810c2c66affSColin Finck strcatW(pth, szBackSlash); 811c2c66affSColin Finck msi_set_property( package->db, szPersonalFolder, pth, -1 ); 812c2c66affSColin Finck 813c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 814c2c66affSColin Finck strcatW(pth, szBackSlash); 815c2c66affSColin Finck msi_set_property( package->db, szWindowsFolder, pth, -1 ); 816c2c66affSColin Finck 817c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); 818c2c66affSColin Finck strcatW(pth, szBackSlash); 819c2c66affSColin Finck msi_set_property( package->db, szPrintHoodFolder, pth, -1 ); 820c2c66affSColin Finck 821c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); 822c2c66affSColin Finck strcatW(pth, szBackSlash); 823c2c66affSColin Finck msi_set_property( package->db, szNetHoodFolder, pth, -1 ); 824c2c66affSColin Finck 825c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); 826c2c66affSColin Finck strcatW(pth, szBackSlash); 827c2c66affSColin Finck msi_set_property( package->db, szRecentFolder, pth, -1 ); 828c2c66affSColin Finck 829c2c66affSColin Finck /* Physical Memory is specified in MB. Using total amount. */ 830c2c66affSColin Finck msex.dwLength = sizeof(msex); 831c2c66affSColin Finck GlobalMemoryStatusEx( &msex ); 832c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); 833c2c66affSColin Finck msi_set_property( package->db, szPhysicalMemory, bufstr, len ); 834c2c66affSColin Finck 835c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 836c2c66affSColin Finck ptr = strchrW(pth,'\\'); 837c2c66affSColin Finck if (ptr) *(ptr + 1) = 0; 838c2c66affSColin Finck msi_set_property( package->db, szWindowsVolume, pth, -1 ); 839c2c66affSColin Finck 840c2c66affSColin Finck len = GetTempPathW(MAX_PATH, pth); 841c2c66affSColin Finck msi_set_property( package->db, szTempFolder, pth, len ); 842c2c66affSColin Finck 843c2c66affSColin Finck /* in a wine environment the user is always admin and privileged */ 844c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 845c2c66affSColin Finck msi_set_property( package->db, szPrivileged, szOne, -1 ); 846c2c66affSColin Finck 847c2c66affSColin Finck /* set the os things */ 848c2c66affSColin Finck OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); 849c2c66affSColin Finck GetVersionExW((OSVERSIONINFOW *)&OSVersion); 850c2c66affSColin Finck verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; 851c2c66affSColin Finck len = sprintfW( verstr, szFormat, verval ); 852c2c66affSColin Finck switch (OSVersion.dwPlatformId) 853c2c66affSColin Finck { 854c2c66affSColin Finck case VER_PLATFORM_WIN32_WINDOWS: 855c2c66affSColin Finck msi_set_property( package->db, szVersion9x, verstr, len ); 856c2c66affSColin Finck break; 857c2c66affSColin Finck case VER_PLATFORM_WIN32_NT: 858c2c66affSColin Finck msi_set_property( package->db, szVersionNT, verstr, len ); 859c2c66affSColin Finck len = sprintfW( bufstr, szFormat,OSVersion.wProductType ); 860c2c66affSColin Finck msi_set_property( package->db, szMsiNTProductType, bufstr, len ); 861c2c66affSColin Finck break; 862c2c66affSColin Finck } 863c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber ); 864c2c66affSColin Finck msi_set_property( package->db, szWindowsBuild, bufstr, len ); 865c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor ); 866c2c66affSColin Finck msi_set_property( package->db, szServicePackLevel, bufstr, len ); 867c2c66affSColin Finck 868c2c66affSColin Finck len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION ); 869c2c66affSColin Finck msi_set_property( package->db, szVersionMsi, bufstr, len ); 870c2c66affSColin Finck len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 ); 871c2c66affSColin Finck msi_set_property( package->db, szVersionDatabase, bufstr, len ); 872c2c66affSColin Finck 873c2c66affSColin Finck GetNativeSystemInfo( &sys_info ); 874c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); 875c2c66affSColin Finck msi_set_property( package->db, szIntel, bufstr, len ); 876c2c66affSColin Finck if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 877c2c66affSColin Finck { 878c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 879c2c66affSColin Finck PathAddBackslashW( pth ); 880c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 881c2c66affSColin Finck 882c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 883c2c66affSColin Finck PathAddBackslashW( pth ); 884c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 885c2c66affSColin Finck 886c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 887c2c66affSColin Finck PathAddBackslashW( pth ); 888c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 889c2c66affSColin Finck } 890c2c66affSColin Finck else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 891c2c66affSColin Finck { 892c2c66affSColin Finck msi_set_property( package->db, szMsiAMD64, bufstr, -1 ); 893c2c66affSColin Finck msi_set_property( package->db, szMsix64, bufstr, -1 ); 894c2c66affSColin Finck msi_set_property( package->db, szVersionNT64, verstr, -1 ); 895c2c66affSColin Finck 896c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 897c2c66affSColin Finck PathAddBackslashW( pth ); 898c2c66affSColin Finck msi_set_property( package->db, szSystem64Folder, pth, -1 ); 899c2c66affSColin Finck 900c2c66affSColin Finck GetSystemWow64DirectoryW( pth, MAX_PATH ); 901c2c66affSColin Finck PathAddBackslashW( pth ); 902c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 903c2c66affSColin Finck 904c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 905c2c66affSColin Finck PathAddBackslashW( pth ); 906c2c66affSColin Finck msi_set_property( package->db, szProgramFiles64Folder, pth, -1 ); 907c2c66affSColin Finck 908c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth ); 909c2c66affSColin Finck PathAddBackslashW( pth ); 910c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 911c2c66affSColin Finck 912c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 913c2c66affSColin Finck PathAddBackslashW( pth ); 914c2c66affSColin Finck msi_set_property( package->db, szCommonFiles64Folder, pth, -1 ); 915c2c66affSColin Finck 916c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth ); 917c2c66affSColin Finck PathAddBackslashW( pth ); 918c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 919c2c66affSColin Finck } 920c2c66affSColin Finck 921c2c66affSColin Finck /* Screen properties. */ 922c2c66affSColin Finck dc = GetDC(0); 923c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) ); 924c2c66affSColin Finck msi_set_property( package->db, szScreenX, bufstr, len ); 925c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) ); 926c2c66affSColin Finck msi_set_property( package->db, szScreenY, bufstr, len ); 927c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) ); 928c2c66affSColin Finck msi_set_property( package->db, szColorBits, bufstr, len ); 929c2c66affSColin Finck ReleaseDC(0, dc); 930c2c66affSColin Finck 931c2c66affSColin Finck /* USERNAME and COMPANYNAME */ 932c2c66affSColin Finck username = msi_dup_property( package->db, szUSERNAME ); 933c2c66affSColin Finck companyname = msi_dup_property( package->db, szCOMPANYNAME ); 934c2c66affSColin Finck 935c2c66affSColin Finck if ((!username || !companyname) && 936c2c66affSColin Finck RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS) 937c2c66affSColin Finck { 938c2c66affSColin Finck if (!username && 939c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szDefName ))) 940c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 941c2c66affSColin Finck if (!companyname && 942c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szDefCompany ))) 943c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 944c2c66affSColin Finck CloseHandle( hkey ); 945c2c66affSColin Finck } 946c2c66affSColin Finck if ((!username || !companyname) && 947c2c66affSColin Finck RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS) 948c2c66affSColin Finck { 949c2c66affSColin Finck if (!username && 950c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szRegisteredUser ))) 951c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 952c2c66affSColin Finck if (!companyname && 953c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization ))) 954c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 955c2c66affSColin Finck CloseHandle( hkey ); 956c2c66affSColin Finck } 957c2c66affSColin Finck msi_free( username ); 958c2c66affSColin Finck msi_free( companyname ); 959c2c66affSColin Finck 960c2c66affSColin Finck if ( set_user_sid_prop( package ) != ERROR_SUCCESS) 961c2c66affSColin Finck ERR("Failed to set the UserSID property\n"); 962c2c66affSColin Finck 963c2c66affSColin Finck set_msi_assembly_prop( package ); 964c2c66affSColin Finck 965c2c66affSColin Finck langid = GetUserDefaultLangID(); 966c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 967c2c66affSColin Finck msi_set_property( package->db, szUserLanguageID, bufstr, len ); 968c2c66affSColin Finck 969c2c66affSColin Finck langid = GetSystemDefaultLangID(); 970c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 971c2c66affSColin Finck msi_set_property( package->db, szSystemLangID, bufstr, len ); 972c2c66affSColin Finck 973c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) ); 974c2c66affSColin Finck msi_set_property( package->db, szProductState, bufstr, len ); 975c2c66affSColin Finck 976c2c66affSColin Finck len = 0; 977c2c66affSColin Finck if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 978c2c66affSColin Finck { 979c2c66affSColin Finck WCHAR *username; 980c2c66affSColin Finck if ((username = msi_alloc( len * sizeof(WCHAR) ))) 981c2c66affSColin Finck { 982c2c66affSColin Finck if (GetUserNameW( username, &len )) 983c2c66affSColin Finck msi_set_property( package->db, szLogonUser, username, len - 1 ); 984c2c66affSColin Finck msi_free( username ); 985c2c66affSColin Finck } 986c2c66affSColin Finck } 987c2c66affSColin Finck len = 0; 988c2c66affSColin Finck if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW) 989c2c66affSColin Finck { 990c2c66affSColin Finck WCHAR *computername; 991c2c66affSColin Finck if ((computername = msi_alloc( len * sizeof(WCHAR) ))) 992c2c66affSColin Finck { 993c2c66affSColin Finck if (GetComputerNameW( computername, &len )) 994c2c66affSColin Finck msi_set_property( package->db, szComputerName, computername, len ); 995c2c66affSColin Finck msi_free( computername ); 996c2c66affSColin Finck } 997c2c66affSColin Finck } 998c2c66affSColin Finck } 999c2c66affSColin Finck 1000c2c66affSColin Finck static MSIPACKAGE *msi_alloc_package( void ) 1001c2c66affSColin Finck { 1002c2c66affSColin Finck MSIPACKAGE *package; 1003c2c66affSColin Finck 1004c2c66affSColin Finck package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), 1005c2c66affSColin Finck MSI_FreePackage ); 1006c2c66affSColin Finck if( package ) 1007c2c66affSColin Finck { 1008c2c66affSColin Finck list_init( &package->components ); 1009c2c66affSColin Finck list_init( &package->features ); 1010c2c66affSColin Finck list_init( &package->files ); 1011c2c66affSColin Finck list_init( &package->filepatches ); 1012c2c66affSColin Finck list_init( &package->tempfiles ); 1013c2c66affSColin Finck list_init( &package->folders ); 1014c2c66affSColin Finck list_init( &package->subscriptions ); 1015c2c66affSColin Finck list_init( &package->appids ); 1016c2c66affSColin Finck list_init( &package->classes ); 1017c2c66affSColin Finck list_init( &package->mimes ); 1018c2c66affSColin Finck list_init( &package->extensions ); 1019c2c66affSColin Finck list_init( &package->progids ); 1020c2c66affSColin Finck list_init( &package->RunningActions ); 1021c2c66affSColin Finck list_init( &package->sourcelist_info ); 1022c2c66affSColin Finck list_init( &package->sourcelist_media ); 1023c2c66affSColin Finck list_init( &package->patches ); 1024c2c66affSColin Finck list_init( &package->binaries ); 1025c2c66affSColin Finck list_init( &package->cabinet_streams ); 1026c2c66affSColin Finck } 1027c2c66affSColin Finck 1028c2c66affSColin Finck return package; 1029c2c66affSColin Finck } 1030c2c66affSColin Finck 1031c2c66affSColin Finck static UINT msi_load_admin_properties(MSIPACKAGE *package) 1032c2c66affSColin Finck { 1033c2c66affSColin Finck BYTE *data; 1034c2c66affSColin Finck UINT r, sz; 1035c2c66affSColin Finck 1036c2c66affSColin Finck static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0}; 1037c2c66affSColin Finck 1038c2c66affSColin Finck r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz); 1039c2c66affSColin Finck if (r != ERROR_SUCCESS) 1040c2c66affSColin Finck return r; 1041c2c66affSColin Finck 1042c2c66affSColin Finck r = msi_parse_command_line(package, (WCHAR *)data, TRUE); 1043c2c66affSColin Finck 1044c2c66affSColin Finck msi_free(data); 1045c2c66affSColin Finck return r; 1046c2c66affSColin Finck } 1047c2c66affSColin Finck 1048c2c66affSColin Finck void msi_adjust_privilege_properties( MSIPACKAGE *package ) 1049c2c66affSColin Finck { 1050c2c66affSColin Finck /* FIXME: this should depend on the user's privileges */ 1051c2c66affSColin Finck if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2) 1052c2c66affSColin Finck { 1053c2c66affSColin Finck TRACE("resetting ALLUSERS property from 2 to 1\n"); 1054c2c66affSColin Finck msi_set_property( package->db, szAllUsers, szOne, -1 ); 1055c2c66affSColin Finck } 1056c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 1057c2c66affSColin Finck } 1058c2c66affSColin Finck 1059c2c66affSColin Finck MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) 1060c2c66affSColin Finck { 1061c2c66affSColin Finck static const WCHAR fmtW[] = {'%','u',0}; 1062c2c66affSColin Finck MSIPACKAGE *package; 1063c2c66affSColin Finck WCHAR uilevel[11]; 1064c2c66affSColin Finck int len; 1065c2c66affSColin Finck UINT r; 1066c2c66affSColin Finck 1067c2c66affSColin Finck TRACE("%p\n", db); 1068c2c66affSColin Finck 1069c2c66affSColin Finck package = msi_alloc_package(); 1070c2c66affSColin Finck if (package) 1071c2c66affSColin Finck { 1072c2c66affSColin Finck msiobj_addref( &db->hdr ); 1073c2c66affSColin Finck package->db = db; 1074c2c66affSColin Finck 107571bffdcdSAmine Khaldi package->LastAction = NULL; 107671bffdcdSAmine Khaldi package->LastActionTemplate = NULL; 107771bffdcdSAmine Khaldi package->LastActionResult = MSI_NULL_INTEGER; 1078c2c66affSColin Finck package->WordCount = 0; 1079c2c66affSColin Finck package->PackagePath = strdupW( db->path ); 1080c2c66affSColin Finck package->BaseURL = strdupW( base_url ); 1081c2c66affSColin Finck 1082c2c66affSColin Finck create_temp_property_table( package ); 1083c2c66affSColin Finck msi_clone_properties( package->db ); 1084c2c66affSColin Finck msi_adjust_privilege_properties( package ); 1085c2c66affSColin Finck 1086c2c66affSColin Finck package->ProductCode = msi_dup_property( package->db, szProductCode ); 1087c2c66affSColin Finck 1088c2c66affSColin Finck set_installer_properties( package ); 1089c2c66affSColin Finck 1090c2c66affSColin Finck package->ui_level = gUILevel; 1091c2c66affSColin Finck len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); 1092c2c66affSColin Finck msi_set_property( package->db, szUILevel, uilevel, len ); 1093c2c66affSColin Finck 1094c2c66affSColin Finck r = msi_load_suminfo_properties( package ); 1095c2c66affSColin Finck if (r != ERROR_SUCCESS) 1096c2c66affSColin Finck { 1097c2c66affSColin Finck msiobj_release( &package->hdr ); 1098c2c66affSColin Finck return NULL; 1099c2c66affSColin Finck } 1100c2c66affSColin Finck 1101c2c66affSColin Finck if (package->WordCount & msidbSumInfoSourceTypeAdminImage) 1102c2c66affSColin Finck msi_load_admin_properties( package ); 1103c2c66affSColin Finck 1104c2c66affSColin Finck package->log_file = INVALID_HANDLE_VALUE; 1105c2c66affSColin Finck } 1106c2c66affSColin Finck return package; 1107c2c66affSColin Finck } 1108c2c66affSColin Finck 1109c2c66affSColin Finck UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) 1110c2c66affSColin Finck { 1111c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW cache_entry; 1112c2c66affSColin Finck DWORD size = 0; 1113c2c66affSColin Finck HRESULT hr; 1114c2c66affSColin Finck 1115c2c66affSColin Finck /* call will always fail, because size is 0, 1116c2c66affSColin Finck * but will return ERROR_FILE_NOT_FOUND first 1117c2c66affSColin Finck * if the file doesn't exist 1118c2c66affSColin Finck */ 1119c2c66affSColin Finck GetUrlCacheEntryInfoW( szUrl, NULL, &size ); 1120c2c66affSColin Finck if ( GetLastError() != ERROR_FILE_NOT_FOUND ) 1121c2c66affSColin Finck { 1122c2c66affSColin Finck cache_entry = msi_alloc( size ); 1123c2c66affSColin Finck if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) 1124c2c66affSColin Finck { 1125c2c66affSColin Finck UINT error = GetLastError(); 1126c2c66affSColin Finck msi_free( cache_entry ); 1127c2c66affSColin Finck return error; 1128c2c66affSColin Finck } 1129c2c66affSColin Finck 1130c2c66affSColin Finck lstrcpyW( filename, cache_entry->lpszLocalFileName ); 1131c2c66affSColin Finck msi_free( cache_entry ); 1132c2c66affSColin Finck return ERROR_SUCCESS; 1133c2c66affSColin Finck } 1134c2c66affSColin Finck 1135c2c66affSColin Finck hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); 1136c2c66affSColin Finck if ( FAILED(hr) ) 1137c2c66affSColin Finck { 1138c2c66affSColin Finck WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); 1139c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1140c2c66affSColin Finck } 1141c2c66affSColin Finck 1142c2c66affSColin Finck return ERROR_SUCCESS; 1143c2c66affSColin Finck } 1144c2c66affSColin Finck 1145c2c66affSColin Finck UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) 1146c2c66affSColin Finck { 1147c2c66affSColin Finck static const WCHAR szInstaller[] = { 1148c2c66affSColin Finck '\\','I','n','s','t','a','l','l','e','r','\\',0}; 1149c2c66affSColin Finck static const WCHAR fmt[] = {'%','x',0}; 1150c2c66affSColin Finck DWORD time, len, i, offset; 1151c2c66affSColin Finck HANDLE handle; 1152c2c66affSColin Finck 1153c2c66affSColin Finck time = GetTickCount(); 1154c2c66affSColin Finck GetWindowsDirectoryW( path, MAX_PATH ); 1155c2c66affSColin Finck strcatW( path, szInstaller ); 1156c2c66affSColin Finck CreateDirectoryW( path, NULL ); 1157c2c66affSColin Finck 1158c2c66affSColin Finck len = strlenW(path); 1159c2c66affSColin Finck for (i = 0; i < 0x10000; i++) 1160c2c66affSColin Finck { 1161c2c66affSColin Finck offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff ); 1162c2c66affSColin Finck memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) ); 1163c2c66affSColin Finck handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, 1164c2c66affSColin Finck CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); 1165c2c66affSColin Finck if (handle != INVALID_HANDLE_VALUE) 1166c2c66affSColin Finck { 1167c2c66affSColin Finck CloseHandle(handle); 1168c2c66affSColin Finck break; 1169c2c66affSColin Finck } 1170c2c66affSColin Finck if (GetLastError() != ERROR_FILE_EXISTS && 1171c2c66affSColin Finck GetLastError() != ERROR_SHARING_VIOLATION) 1172c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1173c2c66affSColin Finck } 1174c2c66affSColin Finck 1175c2c66affSColin Finck return ERROR_SUCCESS; 1176c2c66affSColin Finck } 1177c2c66affSColin Finck 1178c2c66affSColin Finck static enum platform parse_platform( const WCHAR *str ) 1179c2c66affSColin Finck { 1180c2c66affSColin Finck if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL; 1181c2c66affSColin Finck else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64; 1182c2c66affSColin Finck else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64; 1183c2c66affSColin Finck else if (!strcmpW( str, szARM )) return PLATFORM_ARM; 1184c2c66affSColin Finck return PLATFORM_UNKNOWN; 1185c2c66affSColin Finck } 1186c2c66affSColin Finck 1187c2c66affSColin Finck static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) 1188c2c66affSColin Finck { 1189c2c66affSColin Finck WCHAR *template, *p, *q, *platform; 1190c2c66affSColin Finck DWORD i, count; 1191c2c66affSColin Finck 1192c2c66affSColin Finck package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); 1193c2c66affSColin Finck TRACE("version: %d\n", package->version); 1194c2c66affSColin Finck 1195c2c66affSColin Finck template = msi_suminfo_dup_string( si, PID_TEMPLATE ); 1196c2c66affSColin Finck if (!template) 1197c2c66affSColin Finck return ERROR_SUCCESS; /* native accepts missing template property */ 1198c2c66affSColin Finck 1199c2c66affSColin Finck TRACE("template: %s\n", debugstr_w(template)); 1200c2c66affSColin Finck 1201c2c66affSColin Finck p = strchrW( template, ';' ); 1202c2c66affSColin Finck if (!p) 1203c2c66affSColin Finck { 1204c2c66affSColin Finck WARN("invalid template string %s\n", debugstr_w(template)); 1205c2c66affSColin Finck msi_free( template ); 1206c2c66affSColin Finck return ERROR_PATCH_PACKAGE_INVALID; 1207c2c66affSColin Finck } 1208c2c66affSColin Finck *p = 0; 1209c2c66affSColin Finck platform = template; 1210c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1211c2c66affSColin Finck package->platform = parse_platform( platform ); 1212c2c66affSColin Finck while (package->platform == PLATFORM_UNKNOWN && q) 1213c2c66affSColin Finck { 1214c2c66affSColin Finck platform = q + 1; 1215c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1216c2c66affSColin Finck package->platform = parse_platform( platform ); 1217c2c66affSColin Finck } 1218c2c66affSColin Finck if (package->platform == PLATFORM_UNKNOWN) 1219c2c66affSColin Finck { 1220c2c66affSColin Finck WARN("unknown platform %s\n", debugstr_w(template)); 1221c2c66affSColin Finck msi_free( template ); 1222c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1223c2c66affSColin Finck } 1224c2c66affSColin Finck p++; 1225c2c66affSColin Finck if (!*p) 1226c2c66affSColin Finck { 1227c2c66affSColin Finck msi_free( template ); 1228c2c66affSColin Finck return ERROR_SUCCESS; 1229c2c66affSColin Finck } 1230c2c66affSColin Finck count = 1; 1231c2c66affSColin Finck for (q = p; (q = strchrW( q, ',' )); q++) count++; 1232c2c66affSColin Finck 1233c2c66affSColin Finck package->langids = msi_alloc( count * sizeof(LANGID) ); 1234c2c66affSColin Finck if (!package->langids) 1235c2c66affSColin Finck { 1236c2c66affSColin Finck msi_free( template ); 1237c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1238c2c66affSColin Finck } 1239c2c66affSColin Finck 1240c2c66affSColin Finck i = 0; 1241c2c66affSColin Finck while (*p) 1242c2c66affSColin Finck { 1243c2c66affSColin Finck q = strchrW( p, ',' ); 1244c2c66affSColin Finck if (q) *q = 0; 1245c2c66affSColin Finck package->langids[i] = atoiW( p ); 1246c2c66affSColin Finck if (!q) break; 1247c2c66affSColin Finck p = q + 1; 1248c2c66affSColin Finck i++; 1249c2c66affSColin Finck } 1250c2c66affSColin Finck package->num_langids = i + 1; 1251c2c66affSColin Finck 1252c2c66affSColin Finck msi_free( template ); 1253c2c66affSColin Finck return ERROR_SUCCESS; 1254c2c66affSColin Finck } 1255c2c66affSColin Finck 1256c2c66affSColin Finck static UINT validate_package( MSIPACKAGE *package ) 1257c2c66affSColin Finck { 1258c2c66affSColin Finck UINT i; 1259c2c66affSColin Finck 1260c2c66affSColin Finck if (package->platform == PLATFORM_INTEL64) 1261c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1262c2c66affSColin Finck #ifndef __arm__ 1263c2c66affSColin Finck if (package->platform == PLATFORM_ARM) 1264c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1265c2c66affSColin Finck #endif 1266c2c66affSColin Finck if (package->platform == PLATFORM_X64) 1267c2c66affSColin Finck { 1268c2c66affSColin Finck if (!is_64bit && !is_wow64) 1269c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1270c2c66affSColin Finck if (package->version < 200) 1271c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1272c2c66affSColin Finck } 1273c2c66affSColin Finck if (!package->num_langids) 1274c2c66affSColin Finck { 1275c2c66affSColin Finck return ERROR_SUCCESS; 1276c2c66affSColin Finck } 1277c2c66affSColin Finck for (i = 0; i < package->num_langids; i++) 1278c2c66affSColin Finck { 1279c2c66affSColin Finck LANGID langid = package->langids[i]; 1280c2c66affSColin Finck 1281c2c66affSColin Finck if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) 1282c2c66affSColin Finck { 1283c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); 1284c2c66affSColin Finck } 1285c2c66affSColin Finck if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) 1286c2c66affSColin Finck { 1287c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); 1288c2c66affSColin Finck } 1289c2c66affSColin Finck if (IsValidLocale( langid, LCID_INSTALLED )) 1290c2c66affSColin Finck return ERROR_SUCCESS; 1291c2c66affSColin Finck } 1292c2c66affSColin Finck return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; 1293c2c66affSColin Finck } 1294c2c66affSColin Finck 1295c2c66affSColin Finck static WCHAR *get_product_code( MSIDATABASE *db ) 1296c2c66affSColin Finck { 1297c2c66affSColin Finck static const WCHAR query[] = { 1298c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 1299c2c66affSColin Finck 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ', 1300c2c66affSColin Finck 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=', 1301c2c66affSColin Finck '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0}; 1302c2c66affSColin Finck MSIQUERY *view; 1303c2c66affSColin Finck MSIRECORD *rec; 1304c2c66affSColin Finck WCHAR *ret = NULL; 1305c2c66affSColin Finck 1306c2c66affSColin Finck if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) 1307c2c66affSColin Finck { 1308c2c66affSColin Finck return NULL; 1309c2c66affSColin Finck } 1310c2c66affSColin Finck if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) 1311c2c66affSColin Finck { 1312c2c66affSColin Finck MSI_ViewClose( view ); 1313c2c66affSColin Finck msiobj_release( &view->hdr ); 1314c2c66affSColin Finck return NULL; 1315c2c66affSColin Finck } 1316c2c66affSColin Finck if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) 1317c2c66affSColin Finck { 1318c2c66affSColin Finck ret = strdupW( MSI_RecordGetString( rec, 1 ) ); 1319c2c66affSColin Finck msiobj_release( &rec->hdr ); 1320c2c66affSColin Finck } 1321c2c66affSColin Finck MSI_ViewClose( view ); 1322c2c66affSColin Finck msiobj_release( &view->hdr ); 1323c2c66affSColin Finck return ret; 1324c2c66affSColin Finck } 1325c2c66affSColin Finck 1326c2c66affSColin Finck static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile ) 1327c2c66affSColin Finck { 1328c2c66affSColin Finck MSIINSTALLCONTEXT context; 1329c2c66affSColin Finck HKEY product_key, props_key; 1330c2c66affSColin Finck WCHAR *registered_package = NULL, unsquashed[GUID_SIZE]; 1331c2c66affSColin Finck UINT r; 1332c2c66affSColin Finck 1333c2c66affSColin Finck r = msi_locate_product( product, &context ); 1334c2c66affSColin Finck if (r != ERROR_SUCCESS) 1335c2c66affSColin Finck return r; 1336c2c66affSColin Finck 1337c2c66affSColin Finck r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE ); 1338c2c66affSColin Finck if (r != ERROR_SUCCESS) 1339c2c66affSColin Finck return r; 1340c2c66affSColin Finck 1341c2c66affSColin Finck r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); 1342c2c66affSColin Finck if (r != ERROR_SUCCESS) 1343c2c66affSColin Finck { 1344c2c66affSColin Finck RegCloseKey( product_key ); 1345c2c66affSColin Finck return r; 1346c2c66affSColin Finck } 1347c2c66affSColin Finck r = ERROR_FUNCTION_FAILED; 1348c2c66affSColin Finck registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW ); 1349c2c66affSColin Finck if (!registered_package) 1350c2c66affSColin Finck goto done; 1351c2c66affSColin Finck 1352c2c66affSColin Finck unsquash_guid( registered_package, unsquashed ); 1353c2c66affSColin Finck if (!strcmpiW( package, unsquashed )) 1354c2c66affSColin Finck { 1355c2c66affSColin Finck WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); 1356c2c66affSColin Finck if (!filename) 1357c2c66affSColin Finck goto done; 1358c2c66affSColin Finck 1359c2c66affSColin Finck strcpyW( localfile, filename ); 1360c2c66affSColin Finck msi_free( filename ); 1361c2c66affSColin Finck r = ERROR_SUCCESS; 1362c2c66affSColin Finck } 1363c2c66affSColin Finck done: 1364c2c66affSColin Finck msi_free( registered_package ); 1365c2c66affSColin Finck RegCloseKey( props_key ); 1366c2c66affSColin Finck RegCloseKey( product_key ); 1367c2c66affSColin Finck return r; 1368c2c66affSColin Finck } 1369c2c66affSColin Finck 1370c2c66affSColin Finck static WCHAR *get_package_code( MSIDATABASE *db ) 1371c2c66affSColin Finck { 1372c2c66affSColin Finck WCHAR *ret; 1373c2c66affSColin Finck MSISUMMARYINFO *si; 1374c2c66affSColin Finck UINT r; 1375c2c66affSColin Finck 1376c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1377c2c66affSColin Finck if (r != ERROR_SUCCESS) 1378c2c66affSColin Finck { 1379c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1380c2c66affSColin Finck if (r != ERROR_SUCCESS) 1381c2c66affSColin Finck { 1382c2c66affSColin Finck WARN("failed to load summary info %u\n", r); 1383c2c66affSColin Finck return NULL; 1384c2c66affSColin Finck } 1385c2c66affSColin Finck } 1386c2c66affSColin Finck ret = msi_suminfo_dup_string( si, PID_REVNUMBER ); 1387c2c66affSColin Finck msiobj_release( &si->hdr ); 1388c2c66affSColin Finck return ret; 1389c2c66affSColin Finck } 1390c2c66affSColin Finck 1391c2c66affSColin Finck static UINT get_local_package( const WCHAR *filename, WCHAR *localfile ) 1392c2c66affSColin Finck { 1393c2c66affSColin Finck WCHAR *product_code, *package_code; 1394c2c66affSColin Finck MSIDATABASE *db; 1395c2c66affSColin Finck UINT r; 1396c2c66affSColin Finck 1397c2c66affSColin Finck if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS) 1398c2c66affSColin Finck { 1399c2c66affSColin Finck if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES) 1400c2c66affSColin Finck return ERROR_FILE_NOT_FOUND; 1401c2c66affSColin Finck return r; 1402c2c66affSColin Finck } 1403c2c66affSColin Finck if (!(product_code = get_product_code( db ))) 1404c2c66affSColin Finck { 1405c2c66affSColin Finck msiobj_release( &db->hdr ); 1406c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1407c2c66affSColin Finck } 1408c2c66affSColin Finck if (!(package_code = get_package_code( db ))) 1409c2c66affSColin Finck { 1410c2c66affSColin Finck msi_free( product_code ); 1411c2c66affSColin Finck msiobj_release( &db->hdr ); 1412c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1413c2c66affSColin Finck } 1414c2c66affSColin Finck r = get_registered_local_package( product_code, package_code, localfile ); 1415c2c66affSColin Finck msi_free( package_code ); 1416c2c66affSColin Finck msi_free( product_code ); 1417c2c66affSColin Finck msiobj_release( &db->hdr ); 1418c2c66affSColin Finck return r; 1419c2c66affSColin Finck } 1420c2c66affSColin Finck 1421c2c66affSColin Finck UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) 1422c2c66affSColin Finck { 1423c2c66affSColin Finck UINT r; 1424c2c66affSColin Finck 1425c2c66affSColin Finck if (UrlIsW( package, URLIS_URL )) 1426c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, package, -1 ); 1427c2c66affSColin Finck else if (package[0] == '#') 1428c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, db->path, -1 ); 1429c2c66affSColin Finck else 1430c2c66affSColin Finck { 1431c2c66affSColin Finck DWORD len; 1432c2c66affSColin Finck WCHAR *path; 1433c2c66affSColin Finck 1434c2c66affSColin Finck if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); 1435c2c66affSColin Finck if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; 1436c2c66affSColin Finck len = GetFullPathNameW( package, len, path, NULL ); 1437c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, path, len ); 1438c2c66affSColin Finck msi_free( path ); 1439c2c66affSColin Finck } 1440c2c66affSColin Finck return r; 1441c2c66affSColin Finck } 1442c2c66affSColin Finck 1443c2c66affSColin Finck UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) 1444c2c66affSColin Finck { 1445c2c66affSColin Finck static const WCHAR dotmsi[] = {'.','m','s','i',0}; 1446c2c66affSColin Finck MSIDATABASE *db; 1447c2c66affSColin Finck MSIPACKAGE *package; 1448c2c66affSColin Finck MSIHANDLE handle; 144971bffdcdSAmine Khaldi MSIRECORD *data_row, *info_row; 1450c2c66affSColin Finck LPWSTR ptr, base_url = NULL; 1451c2c66affSColin Finck UINT r; 1452c2c66affSColin Finck WCHAR localfile[MAX_PATH], cachefile[MAX_PATH]; 1453c2c66affSColin Finck LPCWSTR file = szPackage; 1454c2c66affSColin Finck DWORD index = 0; 1455c2c66affSColin Finck MSISUMMARYINFO *si; 1456c2c66affSColin Finck BOOL delete_on_close = FALSE; 145771bffdcdSAmine Khaldi LPWSTR productname; 145871bffdcdSAmine Khaldi WCHAR *info_template; 1459c2c66affSColin Finck 1460c2c66affSColin Finck TRACE("%s %p\n", debugstr_w(szPackage), pPackage); 1461c2c66affSColin Finck 146271bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0); 146371bffdcdSAmine Khaldi 1464c2c66affSColin Finck localfile[0] = 0; 1465c2c66affSColin Finck if( szPackage[0] == '#' ) 1466c2c66affSColin Finck { 1467c2c66affSColin Finck handle = atoiW(&szPackage[1]); 1468c2c66affSColin Finck db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); 1469c2c66affSColin Finck if( !db ) 1470c2c66affSColin Finck { 1471b74b77aaSwinesync MSIHANDLE remote; 1472c2c66affSColin Finck 1473b74b77aaSwinesync if (!(remote = msi_get_remote(handle))) 1474c2c66affSColin Finck return ERROR_INVALID_HANDLE; 1475c2c66affSColin Finck 1476c2c66affSColin Finck WARN("MsiOpenPackage not allowed during a custom action!\n"); 1477c2c66affSColin Finck 1478c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1479c2c66affSColin Finck } 1480c2c66affSColin Finck } 1481c2c66affSColin Finck else 1482c2c66affSColin Finck { 1483c2c66affSColin Finck if ( UrlIsW( szPackage, URLIS_URL ) ) 1484c2c66affSColin Finck { 1485c2c66affSColin Finck r = msi_download_file( szPackage, cachefile ); 1486c2c66affSColin Finck if (r != ERROR_SUCCESS) 1487c2c66affSColin Finck return r; 1488c2c66affSColin Finck 1489c2c66affSColin Finck file = cachefile; 1490c2c66affSColin Finck 1491c2c66affSColin Finck base_url = strdupW( szPackage ); 1492c2c66affSColin Finck if (!base_url) 1493c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1494c2c66affSColin Finck 1495c2c66affSColin Finck ptr = strrchrW( base_url, '/' ); 1496c2c66affSColin Finck if (ptr) *(ptr + 1) = '\0'; 1497c2c66affSColin Finck } 1498c2c66affSColin Finck r = get_local_package( file, localfile ); 1499c2c66affSColin Finck if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) 1500c2c66affSColin Finck { 150163bb43adSJérôme Gardou DWORD localfile_attr; 150263bb43adSJérôme Gardou 1503c2c66affSColin Finck r = msi_create_empty_local_file( localfile, dotmsi ); 1504c2c66affSColin Finck if (r != ERROR_SUCCESS) 1505c2c66affSColin Finck { 1506c2c66affSColin Finck msi_free ( base_url ); 1507c2c66affSColin Finck return r; 1508c2c66affSColin Finck } 1509c2c66affSColin Finck 1510c2c66affSColin Finck if (!CopyFileW( file, localfile, FALSE )) 1511c2c66affSColin Finck { 1512c2c66affSColin Finck r = GetLastError(); 1513c2c66affSColin Finck WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1514c2c66affSColin Finck DeleteFileW( localfile ); 1515c2c66affSColin Finck msi_free ( base_url ); 1516c2c66affSColin Finck return r; 1517c2c66affSColin Finck } 1518c2c66affSColin Finck delete_on_close = TRUE; 151963bb43adSJérôme Gardou 152063bb43adSJérôme Gardou /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */ 152163bb43adSJérôme Gardou localfile_attr = GetFileAttributesW( localfile ); 152263bb43adSJérôme Gardou if (localfile_attr & FILE_ATTRIBUTE_READONLY) 152363bb43adSJérôme Gardou SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY); 1524c2c66affSColin Finck } 1525c2c66affSColin Finck TRACE("opening package %s\n", debugstr_w( localfile )); 1526c2c66affSColin Finck r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1527c2c66affSColin Finck if (r != ERROR_SUCCESS) 1528c2c66affSColin Finck { 1529c2c66affSColin Finck msi_free ( base_url ); 1530c2c66affSColin Finck return r; 1531c2c66affSColin Finck } 1532c2c66affSColin Finck } 1533c2c66affSColin Finck package = MSI_CreatePackage( db, base_url ); 1534c2c66affSColin Finck msi_free( base_url ); 1535c2c66affSColin Finck msiobj_release( &db->hdr ); 1536c2c66affSColin Finck if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1537c2c66affSColin Finck package->localfile = strdupW( localfile ); 1538c2c66affSColin Finck package->delete_on_close = delete_on_close; 1539c2c66affSColin Finck 1540c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1541c2c66affSColin Finck if (r != ERROR_SUCCESS) 1542c2c66affSColin Finck { 1543c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1544c2c66affSColin Finck if (r != ERROR_SUCCESS) 1545c2c66affSColin Finck { 1546c2c66affSColin Finck WARN("failed to load summary info\n"); 1547c2c66affSColin Finck msiobj_release( &package->hdr ); 1548c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1549c2c66affSColin Finck } 1550c2c66affSColin Finck } 1551c2c66affSColin Finck r = parse_suminfo( si, package ); 1552c2c66affSColin Finck msiobj_release( &si->hdr ); 1553c2c66affSColin Finck if (r != ERROR_SUCCESS) 1554c2c66affSColin Finck { 1555c2c66affSColin Finck WARN("failed to parse summary info %u\n", r); 1556c2c66affSColin Finck msiobj_release( &package->hdr ); 1557c2c66affSColin Finck return r; 1558c2c66affSColin Finck } 1559c2c66affSColin Finck r = validate_package( package ); 1560c2c66affSColin Finck if (r != ERROR_SUCCESS) 1561c2c66affSColin Finck { 1562c2c66affSColin Finck msiobj_release( &package->hdr ); 1563c2c66affSColin Finck return r; 1564c2c66affSColin Finck } 1565c2c66affSColin Finck msi_set_property( package->db, szDatabase, db->path, -1 ); 1566c2c66affSColin Finck set_installed_prop( package ); 1567c2c66affSColin Finck msi_set_context( package ); 1568c2c66affSColin Finck 1569c2c66affSColin Finck while (1) 1570c2c66affSColin Finck { 1571c2c66affSColin Finck WCHAR patch_code[GUID_SIZE]; 1572c2c66affSColin Finck r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1573c2c66affSColin Finck MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1574c2c66affSColin Finck if (r != ERROR_SUCCESS) 1575c2c66affSColin Finck break; 1576c2c66affSColin Finck 1577c2c66affSColin Finck TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1578c2c66affSColin Finck 1579c2c66affSColin Finck r = msi_apply_registered_patch( package, patch_code ); 1580c2c66affSColin Finck if (r != ERROR_SUCCESS) 1581c2c66affSColin Finck { 1582c2c66affSColin Finck ERR("registered patch failed to apply %u\n", r); 1583c2c66affSColin Finck msiobj_release( &package->hdr ); 1584c2c66affSColin Finck return r; 1585c2c66affSColin Finck } 1586c2c66affSColin Finck index++; 1587c2c66affSColin Finck } 1588c2c66affSColin Finck if (index) msi_adjust_privilege_properties( package ); 1589c2c66affSColin Finck 1590c2c66affSColin Finck r = msi_set_original_database_property( package->db, szPackage ); 1591c2c66affSColin Finck if (r != ERROR_SUCCESS) 1592c2c66affSColin Finck { 1593c2c66affSColin Finck msiobj_release( &package->hdr ); 1594c2c66affSColin Finck return r; 1595c2c66affSColin Finck } 1596c2c66affSColin Finck if (gszLogFile) 1597c2c66affSColin Finck package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1598c2c66affSColin Finck OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 159971bffdcdSAmine Khaldi 160071bffdcdSAmine Khaldi /* FIXME: when should these messages be sent? */ 160171bffdcdSAmine Khaldi data_row = MSI_CreateRecord(3); 160271bffdcdSAmine Khaldi if (!data_row) 160371bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 160471bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 0, NULL); 160571bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 0); 160671bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0); 160771bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings)); 160871bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row); 160971bffdcdSAmine Khaldi 161071bffdcdSAmine Khaldi info_row = MSI_CreateRecord(0); 161171bffdcdSAmine Khaldi if (!info_row) 161271bffdcdSAmine Khaldi { 161371bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 161471bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 161571bffdcdSAmine Khaldi } 161671bffdcdSAmine Khaldi info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART); 161771bffdcdSAmine Khaldi MSI_RecordSetStringW(info_row, 0, info_template); 161871bffdcdSAmine Khaldi msi_free(info_template); 161971bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row); 162071bffdcdSAmine Khaldi 162171bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 162271bffdcdSAmine Khaldi 162371bffdcdSAmine Khaldi productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW); 162471bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 1); 162571bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 2, productname); 162671bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 3, NULL); 162771bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 162871bffdcdSAmine Khaldi 162971bffdcdSAmine Khaldi msi_free(productname); 163071bffdcdSAmine Khaldi msiobj_release(&info_row->hdr); 163171bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 163271bffdcdSAmine Khaldi 1633c2c66affSColin Finck *pPackage = package; 1634c2c66affSColin Finck return ERROR_SUCCESS; 1635c2c66affSColin Finck } 1636c2c66affSColin Finck 1637c2c66affSColin Finck UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1638c2c66affSColin Finck { 1639c2c66affSColin Finck MSIPACKAGE *package = NULL; 1640c2c66affSColin Finck UINT ret; 1641c2c66affSColin Finck 1642c2c66affSColin Finck TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1643c2c66affSColin Finck 1644c2c66affSColin Finck if( !szPackage || !phPackage ) 1645c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 1646c2c66affSColin Finck 1647c2c66affSColin Finck if ( !*szPackage ) 1648c2c66affSColin Finck { 1649c2c66affSColin Finck FIXME("Should create an empty database and package\n"); 1650c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1651c2c66affSColin Finck } 1652c2c66affSColin Finck 1653c2c66affSColin Finck if( dwOptions ) 1654c2c66affSColin Finck FIXME("dwOptions %08x not supported\n", dwOptions); 1655c2c66affSColin Finck 1656c2c66affSColin Finck ret = MSI_OpenPackageW( szPackage, &package ); 1657c2c66affSColin Finck if( ret == ERROR_SUCCESS ) 1658c2c66affSColin Finck { 1659c2c66affSColin Finck *phPackage = alloc_msihandle( &package->hdr ); 1660c2c66affSColin Finck if (! *phPackage) 1661c2c66affSColin Finck ret = ERROR_NOT_ENOUGH_MEMORY; 1662c2c66affSColin Finck msiobj_release( &package->hdr ); 1663c2c66affSColin Finck } 166471bffdcdSAmine Khaldi else 166571bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 1666c2c66affSColin Finck 1667c2c66affSColin Finck return ret; 1668c2c66affSColin Finck } 1669c2c66affSColin Finck 1670c2c66affSColin Finck UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1671c2c66affSColin Finck { 1672c2c66affSColin Finck return MsiOpenPackageExW( szPackage, 0, phPackage ); 1673c2c66affSColin Finck } 1674c2c66affSColin Finck 1675c2c66affSColin Finck UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1676c2c66affSColin Finck { 1677c2c66affSColin Finck LPWSTR szwPack = NULL; 1678c2c66affSColin Finck UINT ret; 1679c2c66affSColin Finck 1680c2c66affSColin Finck if( szPackage ) 1681c2c66affSColin Finck { 1682c2c66affSColin Finck szwPack = strdupAtoW( szPackage ); 1683c2c66affSColin Finck if( !szwPack ) 1684c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1685c2c66affSColin Finck } 1686c2c66affSColin Finck 1687c2c66affSColin Finck ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1688c2c66affSColin Finck 1689c2c66affSColin Finck msi_free( szwPack ); 1690c2c66affSColin Finck 1691c2c66affSColin Finck return ret; 1692c2c66affSColin Finck } 1693c2c66affSColin Finck 1694c2c66affSColin Finck UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1695c2c66affSColin Finck { 1696c2c66affSColin Finck return MsiOpenPackageExA( szPackage, 0, phPackage ); 1697c2c66affSColin Finck } 1698c2c66affSColin Finck 1699c2c66affSColin Finck MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) 1700c2c66affSColin Finck { 1701c2c66affSColin Finck MSIPACKAGE *package; 1702c2c66affSColin Finck MSIHANDLE handle = 0; 1703b74b77aaSwinesync MSIHANDLE remote; 1704c2c66affSColin Finck 1705c2c66affSColin Finck TRACE("(%d)\n",hInstall); 1706c2c66affSColin Finck 1707c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1708c2c66affSColin Finck if( package) 1709c2c66affSColin Finck { 1710c2c66affSColin Finck handle = alloc_msihandle( &package->db->hdr ); 1711c2c66affSColin Finck msiobj_release( &package->hdr ); 1712c2c66affSColin Finck } 1713b74b77aaSwinesync else if ((remote = msi_get_remote(hInstall))) 1714c2c66affSColin Finck { 1715b74b77aaSwinesync remote_GetActiveDatabase(remote, &handle); 1716c2c66affSColin Finck } 1717c2c66affSColin Finck 1718c2c66affSColin Finck return handle; 1719c2c66affSColin Finck } 1720c2c66affSColin Finck 172171bffdcdSAmine Khaldi static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message) 1722c2c66affSColin Finck { 1723c2c66affSColin Finck static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0}; 1724c2c66affSColin Finck static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0}; 172571bffdcdSAmine Khaldi static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0}; 172671bffdcdSAmine Khaldi static const WCHAR szWindows_Installer[] = 172771bffdcdSAmine Khaldi {'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0}; 172871bffdcdSAmine Khaldi 172971bffdcdSAmine Khaldi if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) 173071bffdcdSAmine Khaldi return 0; 173171bffdcdSAmine Khaldi 173271bffdcdSAmine Khaldi /* todo: check if message needs additional styles (topmost/foreground/modality?) */ 173371bffdcdSAmine Khaldi 173471bffdcdSAmine Khaldi switch (eMessageType & 0xff000000) 173571bffdcdSAmine Khaldi { 173671bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 173771bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 173871bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 173971bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 174071bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 174171bffdcdSAmine Khaldi eMessageType |= MB_ICONEXCLAMATION; 174271bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 174371bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 174471bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 174571bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 174671bffdcdSAmine Khaldi eMessageType |= MB_ICONASTERISK; 174771bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 174871bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 174971bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 175071bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 175171bffdcdSAmine Khaldi eMessageType |= MB_USERICON; 175271bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 175371bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 175471bffdcdSAmine Khaldi case INSTALLMESSAGE_INITIALIZE: 175571bffdcdSAmine Khaldi case INSTALLMESSAGE_TERMINATE: 1756f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLSTART: 1757f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLEND: 175871bffdcdSAmine Khaldi return 0; 175971bffdcdSAmine Khaldi case INSTALLMESSAGE_SHOWDIALOG: 176071bffdcdSAmine Khaldi { 176171bffdcdSAmine Khaldi LPWSTR dialog = msi_dup_record_field(record, 0); 176271bffdcdSAmine Khaldi INT rc = ACTION_DialogBox(package, dialog); 176371bffdcdSAmine Khaldi msi_free(dialog); 176471bffdcdSAmine Khaldi return rc; 176571bffdcdSAmine Khaldi } 176671bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONSTART: 176771bffdcdSAmine Khaldi { 176871bffdcdSAmine Khaldi LPWSTR deformatted; 176971bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 177071bffdcdSAmine Khaldi if (!uirow) return -1; 177171bffdcdSAmine Khaldi deformat_string(package, MSI_RecordGetString(record, 2), &deformatted); 177271bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, deformatted); 177371bffdcdSAmine Khaldi msi_event_fire(package, szActionText, uirow); 177471bffdcdSAmine Khaldi 177571bffdcdSAmine Khaldi msi_free(deformatted); 177671bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 177771bffdcdSAmine Khaldi return 1; 177871bffdcdSAmine Khaldi } 177971bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 178071bffdcdSAmine Khaldi { 178171bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 178271bffdcdSAmine Khaldi if (!uirow) return -1; 178371bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, message); 178471bffdcdSAmine Khaldi msi_event_fire(package, szActionData, uirow); 178571bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 178671bffdcdSAmine Khaldi 178771bffdcdSAmine Khaldi if (package->action_progress_increment) 178871bffdcdSAmine Khaldi { 178971bffdcdSAmine Khaldi uirow = MSI_CreateRecord(2); 179071bffdcdSAmine Khaldi if (!uirow) return -1; 179171bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 1, 2); 179271bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 179371bffdcdSAmine Khaldi msi_event_fire(package, szSetProgress, uirow); 179471bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 179571bffdcdSAmine Khaldi } 179671bffdcdSAmine Khaldi return 1; 179771bffdcdSAmine Khaldi } 179871bffdcdSAmine Khaldi case INSTALLMESSAGE_PROGRESS: 179971bffdcdSAmine Khaldi msi_event_fire(package, szSetProgress, record); 180071bffdcdSAmine Khaldi return 1; 180171bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 180271bffdcdSAmine Khaldi switch (MSI_RecordGetInteger(record, 1)) 180371bffdcdSAmine Khaldi { 180471bffdcdSAmine Khaldi case 0: 180571bffdcdSAmine Khaldi case 1: 180671bffdcdSAmine Khaldi /* do nothing */ 180771bffdcdSAmine Khaldi return 0; 180871bffdcdSAmine Khaldi default: 180971bffdcdSAmine Khaldi /* fall through */ 181071bffdcdSAmine Khaldi ; 181171bffdcdSAmine Khaldi } 181271bffdcdSAmine Khaldi default: 181371bffdcdSAmine Khaldi FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level); 181471bffdcdSAmine Khaldi return 0; 181571bffdcdSAmine Khaldi } 181671bffdcdSAmine Khaldi } 181771bffdcdSAmine Khaldi 181871bffdcdSAmine 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}; 181971bffdcdSAmine Khaldi 182071bffdcdSAmine Khaldi static const struct 182171bffdcdSAmine Khaldi { 182271bffdcdSAmine Khaldi int id; 182371bffdcdSAmine Khaldi const WCHAR *text; 182471bffdcdSAmine Khaldi } 182571bffdcdSAmine Khaldi internal_errors[] = 182671bffdcdSAmine Khaldi { 182771bffdcdSAmine Khaldi {2726, szActionNotFound}, 182871bffdcdSAmine Khaldi {0} 182971bffdcdSAmine Khaldi }; 183071bffdcdSAmine Khaldi 183171bffdcdSAmine Khaldi static LPCWSTR get_internal_error_message(int error) 183271bffdcdSAmine Khaldi { 183371bffdcdSAmine Khaldi int i = 0; 183471bffdcdSAmine Khaldi 183571bffdcdSAmine Khaldi while (internal_errors[i].id != 0) 183671bffdcdSAmine Khaldi { 183771bffdcdSAmine Khaldi if (internal_errors[i].id == error) 183871bffdcdSAmine Khaldi return internal_errors[i].text; 183971bffdcdSAmine Khaldi i++; 184071bffdcdSAmine Khaldi } 184171bffdcdSAmine Khaldi 184271bffdcdSAmine Khaldi FIXME("missing error message %d\n", error); 184371bffdcdSAmine Khaldi return NULL; 184471bffdcdSAmine Khaldi } 184571bffdcdSAmine Khaldi 184671bffdcdSAmine Khaldi /* Returned string must be freed */ 184771bffdcdSAmine Khaldi LPWSTR msi_get_error_message(MSIDATABASE *db, int error) 184871bffdcdSAmine Khaldi { 184971bffdcdSAmine Khaldi static const WCHAR query[] = 185071bffdcdSAmine Khaldi {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ', 185171bffdcdSAmine Khaldi 'F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ', 185271bffdcdSAmine Khaldi '`','E','r','r','o','r','`',' ','=',' ','%','i',0}; 185371bffdcdSAmine Khaldi MSIRECORD *record; 185471bffdcdSAmine Khaldi LPWSTR ret = NULL; 185571bffdcdSAmine Khaldi 185671bffdcdSAmine Khaldi if ((record = MSI_QueryGetRecord(db, query, error))) 185771bffdcdSAmine Khaldi { 185871bffdcdSAmine Khaldi ret = msi_dup_record_field(record, 1); 185971bffdcdSAmine Khaldi msiobj_release(&record->hdr); 186071bffdcdSAmine Khaldi } 186171bffdcdSAmine Khaldi else if (error < 2000) 186271bffdcdSAmine Khaldi { 186371bffdcdSAmine Khaldi int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0); 186471bffdcdSAmine Khaldi if (len) 186571bffdcdSAmine Khaldi { 186671bffdcdSAmine Khaldi ret = msi_alloc((len + 1) * sizeof(WCHAR)); 186771bffdcdSAmine Khaldi LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1); 186871bffdcdSAmine Khaldi } 186971bffdcdSAmine Khaldi else 187071bffdcdSAmine Khaldi ret = NULL; 187171bffdcdSAmine Khaldi } 187271bffdcdSAmine Khaldi 187371bffdcdSAmine Khaldi return ret; 187471bffdcdSAmine Khaldi } 187571bffdcdSAmine Khaldi 187671bffdcdSAmine Khaldi INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record) 187771bffdcdSAmine Khaldi { 187871bffdcdSAmine Khaldi LPWSTR message = {0}; 1879f8b992f2SAmine Khaldi DWORD len; 1880f8b992f2SAmine Khaldi DWORD log_type = 1 << (eMessageType >> 24); 188171bffdcdSAmine Khaldi UINT res; 1882c2c66affSColin Finck INT rc = 0; 1883c2c66affSColin Finck char *msg; 1884c2c66affSColin Finck 1885c2c66affSColin Finck TRACE("%x\n", eMessageType); 188671bffdcdSAmine Khaldi if (TRACE_ON(msi)) dump_record(record); 1887c2c66affSColin Finck 188871bffdcdSAmine Khaldi if (!package || !record) 188971bffdcdSAmine Khaldi message = NULL; 189071bffdcdSAmine Khaldi else { 189171bffdcdSAmine Khaldi res = MSI_FormatRecordW(package, record, message, &len); 189271bffdcdSAmine Khaldi if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 189371bffdcdSAmine Khaldi return res; 189471bffdcdSAmine Khaldi len++; 1895c2c66affSColin Finck message = msi_alloc(len * sizeof(WCHAR)); 189671bffdcdSAmine Khaldi if (!message) return ERROR_OUTOFMEMORY; 189771bffdcdSAmine Khaldi MSI_FormatRecordW(package, record, message, &len); 1898c2c66affSColin Finck } 1899c2c66affSColin Finck 1900c2c66affSColin Finck /* convert it to ASCII */ 1901c2c66affSColin Finck len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1902c2c66affSColin Finck msg = msi_alloc( len ); 1903c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1904c2c66affSColin Finck 190571bffdcdSAmine Khaldi if (gUIHandlerRecord && (gUIFilterRecord & log_type)) 1906c2c66affSColin Finck { 190771bffdcdSAmine Khaldi MSIHANDLE rec = alloc_msihandle(&record->hdr); 190871bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n", 190971bffdcdSAmine Khaldi gUIHandlerRecord, gUIContextRecord, eMessageType, rec); 191071bffdcdSAmine Khaldi rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec ); 1911c2c66affSColin Finck MsiCloseHandle( rec ); 1912c2c66affSColin Finck } 191371bffdcdSAmine Khaldi if (!rc && gUIHandlerW && (gUIFilter & log_type)) 191471bffdcdSAmine Khaldi { 191571bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 191671bffdcdSAmine Khaldi gUIHandlerW, gUIContext, eMessageType, debugstr_w(message)); 191771bffdcdSAmine Khaldi rc = gUIHandlerW( gUIContext, eMessageType, message ); 191871bffdcdSAmine Khaldi } 191971bffdcdSAmine Khaldi else if (!rc && gUIHandlerA && (gUIFilter & log_type)) 192071bffdcdSAmine Khaldi { 192171bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 192271bffdcdSAmine Khaldi gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg)); 192371bffdcdSAmine Khaldi rc = gUIHandlerA( gUIContext, eMessageType, msg ); 192471bffdcdSAmine Khaldi } 1925c2c66affSColin Finck 192671bffdcdSAmine Khaldi if (!rc) 192771bffdcdSAmine Khaldi rc = internal_ui_handler(package, eMessageType, record, message); 192871bffdcdSAmine Khaldi 192971bffdcdSAmine Khaldi if (!rc && package && package->log_file != INVALID_HANDLE_VALUE && 1930c2c66affSColin Finck (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1931c2c66affSColin Finck { 1932c2c66affSColin Finck DWORD written; 1933c2c66affSColin Finck WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1934c2c66affSColin Finck WriteFile( package->log_file, "\n", 1, &written, NULL ); 1935c2c66affSColin Finck } 1936c2c66affSColin Finck msi_free( msg ); 1937c2c66affSColin Finck msi_free( message ); 1938c2c66affSColin Finck 193971bffdcdSAmine Khaldi return rc; 194071bffdcdSAmine Khaldi } 194171bffdcdSAmine Khaldi 194271bffdcdSAmine Khaldi INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 194371bffdcdSAmine Khaldi { 1944c2c66affSColin Finck switch (eMessageType & 0xff000000) 1945c2c66affSColin Finck { 194671bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 194771bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 194871bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 194971bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 195071bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 195171bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 195271bffdcdSAmine Khaldi if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) 1953c2c66affSColin Finck { 195471bffdcdSAmine Khaldi /* error message */ 195571bffdcdSAmine Khaldi 195671bffdcdSAmine Khaldi LPWSTR template; 195771bffdcdSAmine Khaldi LPWSTR template_rec = NULL, template_prefix = NULL; 195871bffdcdSAmine Khaldi int error = MSI_RecordGetInteger(record, 1); 195971bffdcdSAmine Khaldi 196071bffdcdSAmine Khaldi if (MSI_RecordIsNull(record, 0)) 196171bffdcdSAmine Khaldi { 196271bffdcdSAmine Khaldi if (error >= 32) 196371bffdcdSAmine Khaldi { 196471bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, error); 196571bffdcdSAmine Khaldi 196671bffdcdSAmine Khaldi if (!template_rec && error >= 2000) 196771bffdcdSAmine Khaldi { 196871bffdcdSAmine Khaldi /* internal error, not localized */ 196971bffdcdSAmine Khaldi if ((template_rec = (LPWSTR) get_internal_error_message(error))) 197071bffdcdSAmine Khaldi { 197171bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 197271bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record); 197371bffdcdSAmine Khaldi } 197471bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR); 197571bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 197671bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 197771bffdcdSAmine Khaldi msi_free(template_rec); 197871bffdcdSAmine Khaldi return 0; 197971bffdcdSAmine Khaldi } 198071bffdcdSAmine Khaldi } 198171bffdcdSAmine Khaldi } 198271bffdcdSAmine Khaldi else 198371bffdcdSAmine Khaldi template_rec = msi_dup_record_field(record, 0); 198471bffdcdSAmine Khaldi 198571bffdcdSAmine Khaldi template_prefix = msi_get_error_message(package->db, eMessageType >> 24); 198671bffdcdSAmine Khaldi if (!template_prefix) template_prefix = strdupW(szEmpty); 198771bffdcdSAmine Khaldi 198871bffdcdSAmine Khaldi if (!template_rec) 198971bffdcdSAmine Khaldi { 199071bffdcdSAmine Khaldi /* always returns 0 */ 199171bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_prefix); 199271bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 199371bffdcdSAmine Khaldi msi_free(template_prefix); 199471bffdcdSAmine Khaldi return 0; 199571bffdcdSAmine Khaldi } 199671bffdcdSAmine Khaldi 199771bffdcdSAmine Khaldi template = msi_alloc((strlenW(template_rec) + strlenW(template_prefix) + 1) * sizeof(WCHAR)); 199871bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 199971bffdcdSAmine Khaldi 200071bffdcdSAmine Khaldi strcpyW(template, template_prefix); 200171bffdcdSAmine Khaldi strcatW(template, template_rec); 200271bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 200371bffdcdSAmine Khaldi 200471bffdcdSAmine Khaldi msi_free(template_prefix); 200571bffdcdSAmine Khaldi msi_free(template_rec); 200671bffdcdSAmine Khaldi msi_free(template); 2007c2c66affSColin Finck } 2008c2c66affSColin Finck break; 2009c2c66affSColin Finck case INSTALLMESSAGE_ACTIONSTART: 201071bffdcdSAmine Khaldi { 201171bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART); 201271bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 201371bffdcdSAmine Khaldi msi_free(template); 2014c2c66affSColin Finck 201571bffdcdSAmine Khaldi msi_free(package->LastAction); 201671bffdcdSAmine Khaldi msi_free(package->LastActionTemplate); 201771bffdcdSAmine Khaldi package->LastAction = msi_dup_record_field(record, 1); 201871bffdcdSAmine Khaldi if (!package->LastAction) package->LastAction = strdupW(szEmpty); 201971bffdcdSAmine Khaldi package->LastActionTemplate = msi_dup_record_field(record, 3); 2020c2c66affSColin Finck break; 202171bffdcdSAmine Khaldi } 202271bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 202371bffdcdSAmine Khaldi if (package->LastAction && package->LastActionTemplate) 202471bffdcdSAmine Khaldi { 202571bffdcdSAmine Khaldi static const WCHAR template_s[] = 202671bffdcdSAmine Khaldi {'{','{','%','s',':',' ','}','}','%','s',0}; 202771bffdcdSAmine Khaldi WCHAR *template; 2028c2c66affSColin Finck 202971bffdcdSAmine Khaldi template = msi_alloc((strlenW(package->LastAction) + strlenW(package->LastActionTemplate) + 7) * sizeof(WCHAR)); 203071bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 203171bffdcdSAmine Khaldi sprintfW(template, template_s, package->LastAction, package->LastActionTemplate); 203271bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 203371bffdcdSAmine Khaldi msi_free(template); 203471bffdcdSAmine Khaldi } 203571bffdcdSAmine Khaldi break; 203671bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 203771bffdcdSAmine Khaldi { 203871bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA); 203971bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 204071bffdcdSAmine Khaldi msi_free(template); 204171bffdcdSAmine Khaldi } 2042c2c66affSColin Finck break; 2043c2c66affSColin Finck } 2044c2c66affSColin Finck 204571bffdcdSAmine Khaldi return MSI_ProcessMessageVerbatim(package, eMessageType, record); 2046c2c66affSColin Finck } 2047c2c66affSColin Finck 2048c2c66affSColin Finck INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, 2049c2c66affSColin Finck MSIHANDLE hRecord) 2050c2c66affSColin Finck { 2051c2c66affSColin Finck UINT ret = ERROR_INVALID_HANDLE; 2052c2c66affSColin Finck MSIPACKAGE *package = NULL; 2053c2c66affSColin Finck MSIRECORD *record = NULL; 2054c2c66affSColin Finck 205571bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE || 205671bffdcdSAmine Khaldi (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE) 205771bffdcdSAmine Khaldi return -1; 205871bffdcdSAmine Khaldi 205971bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA && 206071bffdcdSAmine Khaldi MsiRecordGetInteger(hRecord, 1) != 2) 206171bffdcdSAmine Khaldi return -1; 206271bffdcdSAmine Khaldi 2063c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 2064c2c66affSColin Finck if( !package ) 2065c2c66affSColin Finck { 2066b74b77aaSwinesync MSIHANDLE remote; 2067c2c66affSColin Finck HRESULT hr; 2068c2c66affSColin Finck 2069b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2070c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2071c2c66affSColin Finck 2072b74b77aaSwinesync hr = remote_ProcessMessage(remote, eMessageType, hRecord); 2073c2c66affSColin Finck 2074c2c66affSColin Finck if (FAILED(hr)) 2075c2c66affSColin Finck { 2076c2c66affSColin Finck if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2077c2c66affSColin Finck return HRESULT_CODE(hr); 2078c2c66affSColin Finck 2079c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 2080c2c66affSColin Finck } 2081c2c66affSColin Finck 2082c2c66affSColin Finck return ERROR_SUCCESS; 2083c2c66affSColin Finck } 2084c2c66affSColin Finck 2085c2c66affSColin Finck record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); 2086c2c66affSColin Finck if( !record ) 2087c2c66affSColin Finck goto out; 2088c2c66affSColin Finck 2089c2c66affSColin Finck ret = MSI_ProcessMessage( package, eMessageType, record ); 2090c2c66affSColin Finck 2091c2c66affSColin Finck out: 2092c2c66affSColin Finck msiobj_release( &package->hdr ); 2093c2c66affSColin Finck if( record ) 2094c2c66affSColin Finck msiobj_release( &record->hdr ); 2095c2c66affSColin Finck 2096c2c66affSColin Finck return ret; 2097c2c66affSColin Finck } 2098c2c66affSColin Finck 2099c2c66affSColin Finck /* property code */ 2100c2c66affSColin Finck 2101c2c66affSColin Finck UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) 2102c2c66affSColin Finck { 2103c2c66affSColin Finck LPWSTR szwName = NULL, szwValue = NULL; 2104c2c66affSColin Finck UINT r = ERROR_OUTOFMEMORY; 2105c2c66affSColin Finck 2106c2c66affSColin Finck szwName = strdupAtoW( szName ); 2107c2c66affSColin Finck if( szName && !szwName ) 2108c2c66affSColin Finck goto end; 2109c2c66affSColin Finck 2110c2c66affSColin Finck szwValue = strdupAtoW( szValue ); 2111c2c66affSColin Finck if( szValue && !szwValue ) 2112c2c66affSColin Finck goto end; 2113c2c66affSColin Finck 2114c2c66affSColin Finck r = MsiSetPropertyW( hInstall, szwName, szwValue); 2115c2c66affSColin Finck 2116c2c66affSColin Finck end: 2117c2c66affSColin Finck msi_free( szwName ); 2118c2c66affSColin Finck msi_free( szwValue ); 2119c2c66affSColin Finck 2120c2c66affSColin Finck return r; 2121c2c66affSColin Finck } 2122c2c66affSColin Finck 2123c2c66affSColin Finck void msi_reset_folders( MSIPACKAGE *package, BOOL source ) 2124c2c66affSColin Finck { 2125c2c66affSColin Finck MSIFOLDER *folder; 2126c2c66affSColin Finck 2127c2c66affSColin Finck LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) 2128c2c66affSColin Finck { 2129c2c66affSColin Finck if ( source ) 2130c2c66affSColin Finck { 2131c2c66affSColin Finck msi_free( folder->ResolvedSource ); 2132c2c66affSColin Finck folder->ResolvedSource = NULL; 2133c2c66affSColin Finck } 2134c2c66affSColin Finck else 2135c2c66affSColin Finck { 2136c2c66affSColin Finck msi_free( folder->ResolvedTarget ); 2137c2c66affSColin Finck folder->ResolvedTarget = NULL; 2138c2c66affSColin Finck } 2139c2c66affSColin Finck } 2140c2c66affSColin Finck } 2141c2c66affSColin Finck 2142c2c66affSColin Finck UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) 2143c2c66affSColin Finck { 2144c2c66affSColin Finck static const WCHAR insert_query[] = { 2145c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 2146c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 2147c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 2148c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 2149c2c66affSColin Finck static const WCHAR update_query[] = { 2150c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 2151c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ', 2152c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2153c2c66affSColin Finck static const WCHAR delete_query[] = { 2154c2c66affSColin Finck 'D','E','L','E','T','E',' ','F','R','O','M',' ', 2155c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 2156c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2157c2c66affSColin Finck MSIQUERY *view; 2158c2c66affSColin Finck MSIRECORD *row = NULL; 2159c2c66affSColin Finck DWORD sz = 0; 2160c2c66affSColin Finck WCHAR query[1024]; 2161c2c66affSColin Finck UINT rc; 2162c2c66affSColin Finck 2163c2c66affSColin Finck TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); 2164c2c66affSColin Finck 2165c2c66affSColin Finck if (!name) 2166c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 2167c2c66affSColin Finck 2168c2c66affSColin Finck /* this one is weird... */ 2169c2c66affSColin Finck if (!name[0]) 2170c2c66affSColin Finck return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; 2171c2c66affSColin Finck 2172c2c66affSColin Finck if (value && len < 0) len = strlenW( value ); 2173c2c66affSColin Finck 2174c2c66affSColin Finck rc = msi_get_property( db, name, 0, &sz ); 2175c2c66affSColin Finck if (!value || (!*value && !len)) 2176c2c66affSColin Finck { 2177c2c66affSColin Finck sprintfW( query, delete_query, name ); 2178c2c66affSColin Finck } 2179c2c66affSColin Finck else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) 2180c2c66affSColin Finck { 2181c2c66affSColin Finck sprintfW( query, update_query, name ); 2182c2c66affSColin Finck row = MSI_CreateRecord(1); 2183c2c66affSColin Finck msi_record_set_string( row, 1, value, len ); 2184c2c66affSColin Finck } 2185c2c66affSColin Finck else 2186c2c66affSColin Finck { 2187c2c66affSColin Finck strcpyW( query, insert_query ); 2188c2c66affSColin Finck row = MSI_CreateRecord(2); 2189c2c66affSColin Finck msi_record_set_string( row, 1, name, -1 ); 2190c2c66affSColin Finck msi_record_set_string( row, 2, value, len ); 2191c2c66affSColin Finck } 2192c2c66affSColin Finck 2193c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(db, query, &view); 2194c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2195c2c66affSColin Finck { 2196c2c66affSColin Finck rc = MSI_ViewExecute(view, row); 2197c2c66affSColin Finck MSI_ViewClose(view); 2198c2c66affSColin Finck msiobj_release(&view->hdr); 2199c2c66affSColin Finck } 2200c2c66affSColin Finck if (row) msiobj_release(&row->hdr); 2201c2c66affSColin Finck return rc; 2202c2c66affSColin Finck } 2203c2c66affSColin Finck 2204c2c66affSColin Finck UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) 2205c2c66affSColin Finck { 2206c2c66affSColin Finck MSIPACKAGE *package; 2207c2c66affSColin Finck UINT ret; 2208c2c66affSColin Finck 2209c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 2210c2c66affSColin Finck if( !package ) 2211c2c66affSColin Finck { 2212b74b77aaSwinesync MSIHANDLE remote; 2213c2c66affSColin Finck 2214b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2215c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2216c2c66affSColin Finck 2217*3431091cSwinesync return remote_SetProperty(remote, szName, szValue); 2218c2c66affSColin Finck } 2219c2c66affSColin Finck 2220c2c66affSColin Finck ret = msi_set_property( package->db, szName, szValue, -1 ); 2221c2c66affSColin Finck if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) 2222c2c66affSColin Finck msi_reset_folders( package, TRUE ); 2223c2c66affSColin Finck 2224c2c66affSColin Finck msiobj_release( &package->hdr ); 2225c2c66affSColin Finck return ret; 2226c2c66affSColin Finck } 2227c2c66affSColin Finck 2228c2c66affSColin Finck static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) 2229c2c66affSColin Finck { 2230c2c66affSColin Finck static const WCHAR query[]= { 2231c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 2232c2c66affSColin Finck 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ', 2233c2c66affSColin Finck 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0}; 2234c2c66affSColin Finck MSIRECORD *rec, *row = NULL; 2235c2c66affSColin Finck MSIQUERY *view; 2236c2c66affSColin Finck UINT r; 2237c2c66affSColin Finck 223871bffdcdSAmine Khaldi static const WCHAR szDate[] = {'D','a','t','e',0}; 223971bffdcdSAmine Khaldi static const WCHAR szTime[] = {'T','i','m','e',0}; 224071bffdcdSAmine Khaldi WCHAR *buffer; 224171bffdcdSAmine Khaldi int length; 224271bffdcdSAmine Khaldi 2243c2c66affSColin Finck if (!name || !*name) 2244c2c66affSColin Finck return NULL; 2245c2c66affSColin Finck 224671bffdcdSAmine Khaldi if (!strcmpW(name, szDate)) 224771bffdcdSAmine Khaldi { 224871bffdcdSAmine Khaldi length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0); 224971bffdcdSAmine Khaldi if (!length) 225071bffdcdSAmine Khaldi return NULL; 225171bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2252fec16ab0SAmine Khaldi GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length); 225371bffdcdSAmine Khaldi 225471bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 225571bffdcdSAmine Khaldi if (!row) 2256f8b992f2SAmine Khaldi { 2257f8b992f2SAmine Khaldi msi_free(buffer); 225871bffdcdSAmine Khaldi return NULL; 2259f8b992f2SAmine Khaldi } 226071bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 226171bffdcdSAmine Khaldi msi_free(buffer); 226271bffdcdSAmine Khaldi return row; 226371bffdcdSAmine Khaldi } 226471bffdcdSAmine Khaldi else if (!strcmpW(name, szTime)) 226571bffdcdSAmine Khaldi { 226671bffdcdSAmine Khaldi length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0); 226771bffdcdSAmine Khaldi if (!length) 226871bffdcdSAmine Khaldi return NULL; 226971bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2270fec16ab0SAmine Khaldi GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length); 227171bffdcdSAmine Khaldi 227271bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 227371bffdcdSAmine Khaldi if (!row) 2274f8b992f2SAmine Khaldi { 2275f8b992f2SAmine Khaldi msi_free(buffer); 227671bffdcdSAmine Khaldi return NULL; 2277f8b992f2SAmine Khaldi } 227871bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 227971bffdcdSAmine Khaldi msi_free(buffer); 228071bffdcdSAmine Khaldi return row; 228171bffdcdSAmine Khaldi } 228271bffdcdSAmine Khaldi 2283c2c66affSColin Finck rec = MSI_CreateRecord(1); 2284c2c66affSColin Finck if (!rec) 2285c2c66affSColin Finck return NULL; 2286c2c66affSColin Finck 2287c2c66affSColin Finck MSI_RecordSetStringW(rec, 1, name); 2288c2c66affSColin Finck 2289c2c66affSColin Finck r = MSI_DatabaseOpenViewW(db, query, &view); 2290c2c66affSColin Finck if (r == ERROR_SUCCESS) 2291c2c66affSColin Finck { 2292c2c66affSColin Finck MSI_ViewExecute(view, rec); 2293c2c66affSColin Finck MSI_ViewFetch(view, &row); 2294c2c66affSColin Finck MSI_ViewClose(view); 2295c2c66affSColin Finck msiobj_release(&view->hdr); 2296c2c66affSColin Finck } 2297c2c66affSColin Finck msiobj_release(&rec->hdr); 2298c2c66affSColin Finck return row; 2299c2c66affSColin Finck } 2300c2c66affSColin Finck 2301c2c66affSColin Finck /* internal function, not compatible with MsiGetPropertyW */ 2302c2c66affSColin Finck UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, 2303c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2304c2c66affSColin Finck { 2305c2c66affSColin Finck MSIRECORD *row; 2306c2c66affSColin Finck UINT rc = ERROR_FUNCTION_FAILED; 2307c2c66affSColin Finck 2308c2c66affSColin Finck TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf); 2309c2c66affSColin Finck 2310c2c66affSColin Finck row = msi_get_property_row( db, szName ); 2311c2c66affSColin Finck 2312c2c66affSColin Finck if (*pchValueBuf > 0) 2313c2c66affSColin Finck szValueBuf[0] = 0; 2314c2c66affSColin Finck 2315c2c66affSColin Finck if (row) 2316c2c66affSColin Finck { 2317c2c66affSColin Finck rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); 2318c2c66affSColin Finck msiobj_release(&row->hdr); 2319c2c66affSColin Finck } 2320c2c66affSColin Finck 2321c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2322c2c66affSColin Finck TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), 2323c2c66affSColin Finck debugstr_w(szName)); 2324c2c66affSColin Finck else if (rc == ERROR_MORE_DATA) 2325c2c66affSColin Finck TRACE("need %d sized buffer for %s\n", *pchValueBuf, 2326c2c66affSColin Finck debugstr_w(szName)); 2327c2c66affSColin Finck else 2328c2c66affSColin Finck { 2329c2c66affSColin Finck *pchValueBuf = 0; 2330c2c66affSColin Finck TRACE("property %s not found\n", debugstr_w(szName)); 2331c2c66affSColin Finck } 2332c2c66affSColin Finck 2333c2c66affSColin Finck return rc; 2334c2c66affSColin Finck } 2335c2c66affSColin Finck 2336c2c66affSColin Finck LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2337c2c66affSColin Finck { 2338c2c66affSColin Finck DWORD sz = 0; 2339c2c66affSColin Finck LPWSTR str; 2340c2c66affSColin Finck UINT r; 2341c2c66affSColin Finck 2342c2c66affSColin Finck r = msi_get_property(db, prop, NULL, &sz); 2343c2c66affSColin Finck if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2344c2c66affSColin Finck return NULL; 2345c2c66affSColin Finck 2346c2c66affSColin Finck sz++; 2347c2c66affSColin Finck str = msi_alloc(sz * sizeof(WCHAR)); 2348c2c66affSColin Finck r = msi_get_property(db, prop, str, &sz); 2349c2c66affSColin Finck if (r != ERROR_SUCCESS) 2350c2c66affSColin Finck { 2351c2c66affSColin Finck msi_free(str); 2352c2c66affSColin Finck str = NULL; 2353c2c66affSColin Finck } 2354c2c66affSColin Finck 2355c2c66affSColin Finck return str; 2356c2c66affSColin Finck } 2357c2c66affSColin Finck 2358c2c66affSColin Finck int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2359c2c66affSColin Finck { 2360c2c66affSColin Finck LPWSTR str = msi_dup_property( db, prop ); 2361c2c66affSColin Finck int val = str ? atoiW(str) : def; 2362c2c66affSColin Finck msi_free(str); 2363c2c66affSColin Finck return val; 2364c2c66affSColin Finck } 2365c2c66affSColin Finck 2366c2c66affSColin Finck static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, 2367c2c66affSColin Finck awstring *szValueBuf, LPDWORD pchValueBuf ) 2368c2c66affSColin Finck { 2369c2c66affSColin Finck MSIPACKAGE *package; 2370c2c66affSColin Finck MSIRECORD *row = NULL; 2371c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 2372c2c66affSColin Finck LPCWSTR val = NULL; 2373c2c66affSColin Finck DWORD len = 0; 2374c2c66affSColin Finck 2375c2c66affSColin Finck TRACE("%u %s %p %p\n", handle, debugstr_w(name), 2376c2c66affSColin Finck szValueBuf->str.w, pchValueBuf ); 2377c2c66affSColin Finck 2378c2c66affSColin Finck if (!name) 2379c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 2380c2c66affSColin Finck 2381c2c66affSColin Finck package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); 2382c2c66affSColin Finck if (!package) 2383c2c66affSColin Finck { 238462ababd7Swinesync LPWSTR value = NULL, buffer; 2385b74b77aaSwinesync MSIHANDLE remote; 2386c2c66affSColin Finck 2387b74b77aaSwinesync if (!(remote = msi_get_remote(handle))) 2388c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2389c2c66affSColin Finck 239062ababd7Swinesync r = remote_GetProperty(remote, name, &value, &len); 239162ababd7Swinesync if (r != ERROR_SUCCESS) 239262ababd7Swinesync return r; 2393c2c66affSColin Finck 239462ababd7Swinesync /* String might contain embedded nulls. 239562ababd7Swinesync * Native returns the correct size but truncates the string. */ 239662ababd7Swinesync buffer = heap_alloc_zero((len + 1) * sizeof(WCHAR)); 239762ababd7Swinesync if (!buffer) 2398c2c66affSColin Finck { 239962ababd7Swinesync midl_user_free(value); 240062ababd7Swinesync return ERROR_OUTOFMEMORY; 2401c2c66affSColin Finck } 240262ababd7Swinesync strcpyW(buffer, value); 2403c2c66affSColin Finck 240462ababd7Swinesync r = msi_strcpy_to_awstring(buffer, len, szValueBuf, pchValueBuf); 2405c2c66affSColin Finck 2406c2c66affSColin Finck /* Bug required by Adobe installers */ 240762ababd7Swinesync if (pchValueBuf && !szValueBuf->unicode && !szValueBuf->str.a) 2408c2c66affSColin Finck *pchValueBuf *= sizeof(WCHAR); 2409c2c66affSColin Finck 241062ababd7Swinesync heap_free(buffer); 241162ababd7Swinesync midl_user_free(value); 2412c2c66affSColin Finck return r; 2413c2c66affSColin Finck } 2414c2c66affSColin Finck 2415c2c66affSColin Finck row = msi_get_property_row( package->db, name ); 2416c2c66affSColin Finck if (row) 2417c2c66affSColin Finck val = msi_record_get_string( row, 1, (int *)&len ); 2418c2c66affSColin Finck 2419c2c66affSColin Finck if (!val) 2420c2c66affSColin Finck val = szEmpty; 2421c2c66affSColin Finck 2422c2c66affSColin Finck r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf ); 2423c2c66affSColin Finck 2424c2c66affSColin Finck if (row) 2425c2c66affSColin Finck msiobj_release( &row->hdr ); 2426c2c66affSColin Finck msiobj_release( &package->hdr ); 2427c2c66affSColin Finck 2428c2c66affSColin Finck return r; 2429c2c66affSColin Finck } 2430c2c66affSColin Finck 2431c2c66affSColin Finck UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName, 2432c2c66affSColin Finck LPSTR szValueBuf, LPDWORD pchValueBuf ) 2433c2c66affSColin Finck { 2434c2c66affSColin Finck awstring val; 2435c2c66affSColin Finck LPWSTR name; 2436c2c66affSColin Finck UINT r; 2437c2c66affSColin Finck 2438c2c66affSColin Finck val.unicode = FALSE; 2439c2c66affSColin Finck val.str.a = szValueBuf; 2440c2c66affSColin Finck 2441c2c66affSColin Finck name = strdupAtoW( szName ); 2442c2c66affSColin Finck if (szName && !name) 2443c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2444c2c66affSColin Finck 2445c2c66affSColin Finck r = MSI_GetProperty( hInstall, name, &val, pchValueBuf ); 2446c2c66affSColin Finck msi_free( name ); 2447c2c66affSColin Finck return r; 2448c2c66affSColin Finck } 2449c2c66affSColin Finck 2450c2c66affSColin Finck UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, 2451c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2452c2c66affSColin Finck { 2453c2c66affSColin Finck awstring val; 2454c2c66affSColin Finck 2455c2c66affSColin Finck val.unicode = TRUE; 2456c2c66affSColin Finck val.str.w = szValueBuf; 2457c2c66affSColin Finck 2458c2c66affSColin Finck return MSI_GetProperty( hInstall, szName, &val, pchValueBuf ); 2459c2c66affSColin Finck } 2460c2c66affSColin Finck 2461b74b77aaSwinesync HRESULT __cdecl remote_GetActiveDatabase(MSIHANDLE hinst, MSIHANDLE *handle) 2462b74b77aaSwinesync { 2463b74b77aaSwinesync *handle = MsiGetActiveDatabase(hinst); 2464c2c66affSColin Finck 2465c2c66affSColin Finck return S_OK; 2466c2c66affSColin Finck } 2467c2c66affSColin Finck 246862ababd7Swinesync UINT __cdecl remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size) 2469c2c66affSColin Finck { 247062ababd7Swinesync WCHAR empty[1]; 247162ababd7Swinesync UINT r; 247262ababd7Swinesync 247362ababd7Swinesync *size = 0; 247462ababd7Swinesync r = MsiGetPropertyW(hinst, property, empty, size); 247562ababd7Swinesync if (r == ERROR_MORE_DATA) 247662ababd7Swinesync { 247762ababd7Swinesync ++*size; 247862ababd7Swinesync *value = midl_user_allocate(*size * sizeof(WCHAR)); 247962ababd7Swinesync if (!*value) 248062ababd7Swinesync return ERROR_OUTOFMEMORY; 248162ababd7Swinesync r = MsiGetPropertyW(hinst, property, *value, size); 248262ababd7Swinesync } 248362ababd7Swinesync return r; 2484c2c66affSColin Finck } 2485c2c66affSColin Finck 2486*3431091cSwinesync UINT __cdecl remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value) 2487c2c66affSColin Finck { 2488*3431091cSwinesync return MsiSetPropertyW(hinst, property, value); 2489c2c66affSColin Finck } 2490c2c66affSColin Finck 2491b74b77aaSwinesync HRESULT __cdecl remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, MSIHANDLE record) 2492c2c66affSColin Finck { 2493b74b77aaSwinesync UINT r = MsiProcessMessage(hinst, message, record); 2494c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2495c2c66affSColin Finck } 2496c2c66affSColin Finck 2497b74b77aaSwinesync HRESULT __cdecl remote_DoAction(MSIHANDLE hinst, BSTR action) 2498c2c66affSColin Finck { 2499b74b77aaSwinesync UINT r = MsiDoActionW(hinst, action); 2500c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2501c2c66affSColin Finck } 2502c2c66affSColin Finck 2503b74b77aaSwinesync HRESULT __cdecl remote_Sequence(MSIHANDLE hinst, BSTR table, int sequence) 2504c2c66affSColin Finck { 2505b74b77aaSwinesync UINT r = MsiSequenceW(hinst, table, sequence); 2506c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2507c2c66affSColin Finck } 2508c2c66affSColin Finck 2509b74b77aaSwinesync HRESULT __cdecl remote_GetTargetPath(MSIHANDLE hinst, BSTR folder, BSTR value, DWORD *size) 2510c2c66affSColin Finck { 2511b74b77aaSwinesync UINT r = MsiGetTargetPathW(hinst, folder, value, size); 2512c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2513c2c66affSColin Finck } 2514c2c66affSColin Finck 2515b74b77aaSwinesync HRESULT __cdecl remote_SetTargetPath(MSIHANDLE hinst, BSTR folder, BSTR value) 2516c2c66affSColin Finck { 2517b74b77aaSwinesync UINT r = MsiSetTargetPathW(hinst, folder, value); 2518c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2519c2c66affSColin Finck } 2520c2c66affSColin Finck 2521b74b77aaSwinesync HRESULT __cdecl remote_GetSourcePath(MSIHANDLE hinst, BSTR folder, BSTR value, DWORD *size) 2522c2c66affSColin Finck { 2523b74b77aaSwinesync UINT r = MsiGetSourcePathW(hinst, folder, value, size); 2524c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2525c2c66affSColin Finck } 2526c2c66affSColin Finck 2527b74b77aaSwinesync HRESULT __cdecl remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL *ret) 2528c2c66affSColin Finck { 2529b74b77aaSwinesync *ret = MsiGetMode(hinst, mode); 2530c2c66affSColin Finck return S_OK; 2531c2c66affSColin Finck } 2532c2c66affSColin Finck 2533b74b77aaSwinesync HRESULT __cdecl remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state) 2534c2c66affSColin Finck { 2535b74b77aaSwinesync UINT r = MsiSetMode(hinst, mode, state); 2536c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2537c2c66affSColin Finck } 2538c2c66affSColin Finck 2539b74b77aaSwinesync HRESULT __cdecl remote_GetFeatureState(MSIHANDLE hinst, BSTR feature, 2540c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2541c2c66affSColin Finck { 2542b74b77aaSwinesync UINT r = MsiGetFeatureStateW(hinst, feature, installed, action); 2543c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2544c2c66affSColin Finck } 2545c2c66affSColin Finck 2546b74b77aaSwinesync HRESULT __cdecl remote_SetFeatureState(MSIHANDLE hinst, BSTR feature, INSTALLSTATE state) 2547c2c66affSColin Finck { 2548b74b77aaSwinesync UINT r = MsiSetFeatureStateW(hinst, feature, state); 2549c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2550c2c66affSColin Finck } 2551c2c66affSColin Finck 2552b74b77aaSwinesync HRESULT __cdecl remote_GetComponentState(MSIHANDLE hinst, BSTR component, 2553c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2554c2c66affSColin Finck { 2555b74b77aaSwinesync UINT r = MsiGetComponentStateW(hinst, component, installed, action); 2556c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2557c2c66affSColin Finck } 2558c2c66affSColin Finck 2559b74b77aaSwinesync HRESULT __cdecl remote_SetComponentState(MSIHANDLE hinst, BSTR component, INSTALLSTATE state) 2560c2c66affSColin Finck { 2561b74b77aaSwinesync UINT r = MsiSetComponentStateW(hinst, component, state); 2562c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2563c2c66affSColin Finck } 2564c2c66affSColin Finck 2565b74b77aaSwinesync HRESULT __cdecl remote_GetLanguage(MSIHANDLE hinst, LANGID *language) 2566c2c66affSColin Finck { 2567b74b77aaSwinesync *language = MsiGetLanguage(hinst); 2568c2c66affSColin Finck return S_OK; 2569c2c66affSColin Finck } 2570c2c66affSColin Finck 2571b74b77aaSwinesync HRESULT __cdecl remote_SetInstallLevel(MSIHANDLE hinst, int level) 2572c2c66affSColin Finck { 2573b74b77aaSwinesync UINT r = MsiSetInstallLevel(hinst, level); 2574c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2575c2c66affSColin Finck } 2576c2c66affSColin Finck 2577b74b77aaSwinesync HRESULT __cdecl remote_FormatRecord(MSIHANDLE hinst, MSIHANDLE record, 2578c2c66affSColin Finck BSTR *value) 2579c2c66affSColin Finck { 2580c2c66affSColin Finck DWORD size = 0; 2581b74b77aaSwinesync UINT r = MsiFormatRecordW(hinst, record, NULL, &size); 2582c2c66affSColin Finck if (r == ERROR_SUCCESS) 2583c2c66affSColin Finck { 2584c2c66affSColin Finck *value = SysAllocStringLen(NULL, size); 2585c2c66affSColin Finck if (!*value) 2586c2c66affSColin Finck return E_OUTOFMEMORY; 2587c2c66affSColin Finck size++; 2588b74b77aaSwinesync r = MsiFormatRecordW(hinst, record, *value, &size); 2589c2c66affSColin Finck } 2590c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2591c2c66affSColin Finck } 2592c2c66affSColin Finck 2593b74b77aaSwinesync HRESULT __cdecl remote_EvaluateCondition(MSIHANDLE hinst, BSTR condition) 2594c2c66affSColin Finck { 2595b74b77aaSwinesync UINT r = MsiEvaluateConditionW(hinst, condition); 2596c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2597c2c66affSColin Finck } 2598c2c66affSColin Finck 2599b74b77aaSwinesync HRESULT __cdecl remote_GetFeatureCost(MSIHANDLE hinst, BSTR feature, 2600c2c66affSColin Finck INT cost_tree, INSTALLSTATE state, INT *cost) 2601c2c66affSColin Finck { 2602b74b77aaSwinesync UINT r = MsiGetFeatureCostW(hinst, feature, cost_tree, state, cost); 2603c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2604c2c66affSColin Finck } 2605c2c66affSColin Finck 2606b74b77aaSwinesync HRESULT __cdecl remote_EnumComponentCosts(MSIHANDLE hinst, BSTR component, 2607c2c66affSColin Finck DWORD index, INSTALLSTATE state, BSTR drive, 2608c2c66affSColin Finck DWORD *buflen, INT *cost, INT *temp) 2609c2c66affSColin Finck { 2610b74b77aaSwinesync UINT r = MsiEnumComponentCostsW(hinst, component, index, state, drive, buflen, cost, temp); 2611c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2612c2c66affSColin Finck } 2613c2c66affSColin Finck 2614c2c66affSColin Finck UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2615c2c66affSColin Finck LPCWSTR property, LPWSTR value) 2616c2c66affSColin Finck { 2617c2c66affSColin Finck MSISOURCELISTINFO *info; 2618c2c66affSColin Finck 2619c2c66affSColin Finck LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2620c2c66affSColin Finck { 2621c2c66affSColin Finck if (!strcmpW( info->value, value )) return ERROR_SUCCESS; 2622c2c66affSColin Finck } 2623c2c66affSColin Finck 2624c2c66affSColin Finck info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2625c2c66affSColin Finck if (!info) 2626c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2627c2c66affSColin Finck 2628c2c66affSColin Finck info->context = context; 2629c2c66affSColin Finck info->options = options; 2630c2c66affSColin Finck info->property = property; 2631c2c66affSColin Finck info->value = strdupW(value); 2632c2c66affSColin Finck list_add_head(&package->sourcelist_info, &info->entry); 2633c2c66affSColin Finck 2634c2c66affSColin Finck return ERROR_SUCCESS; 2635c2c66affSColin Finck } 2636c2c66affSColin Finck 2637c2c66affSColin Finck UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2638c2c66affSColin Finck DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2639c2c66affSColin Finck { 2640c2c66affSColin Finck MSIMEDIADISK *disk; 2641c2c66affSColin Finck 2642c2c66affSColin Finck LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2643c2c66affSColin Finck { 2644c2c66affSColin Finck if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2645c2c66affSColin Finck } 2646c2c66affSColin Finck 2647c2c66affSColin Finck disk = msi_alloc(sizeof(MSIMEDIADISK)); 2648c2c66affSColin Finck if (!disk) 2649c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2650c2c66affSColin Finck 2651c2c66affSColin Finck disk->context = context; 2652c2c66affSColin Finck disk->options = options; 2653c2c66affSColin Finck disk->disk_id = disk_id; 2654c2c66affSColin Finck disk->volume_label = strdupW(volume_label); 2655c2c66affSColin Finck disk->disk_prompt = strdupW(disk_prompt); 2656c2c66affSColin Finck list_add_head(&package->sourcelist_media, &disk->entry); 2657c2c66affSColin Finck 2658c2c66affSColin Finck return ERROR_SUCCESS; 2659c2c66affSColin Finck } 2660