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" 472a9ae858Swinesync #include "wine/exception.h" 4862ababd7Swinesync #include "wine/unicode.h" 4962ababd7Swinesync 50c42b133eSAmine Khaldi #include "msipriv.h" 51a8bc3902Swinesync #include "winemsi_s.h" 52c42b133eSAmine Khaldi #include "resource.h" 53c2c66affSColin Finck 54c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi); 55c2c66affSColin Finck 56c2c66affSColin Finck static void free_feature( MSIFEATURE *feature ) 57c2c66affSColin Finck { 58c2c66affSColin Finck struct list *item, *cursor; 59c2c66affSColin Finck 60c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Children ) 61c2c66affSColin Finck { 62c2c66affSColin Finck FeatureList *fl = LIST_ENTRY( item, FeatureList, entry ); 63c2c66affSColin Finck list_remove( &fl->entry ); 64c2c66affSColin Finck msi_free( fl ); 65c2c66affSColin Finck } 66c2c66affSColin Finck 67c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) 68c2c66affSColin Finck { 69c2c66affSColin Finck ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); 70c2c66affSColin Finck list_remove( &cl->entry ); 71c2c66affSColin Finck msi_free( cl ); 72c2c66affSColin Finck } 73c2c66affSColin Finck msi_free( feature->Feature ); 74c2c66affSColin Finck msi_free( feature->Feature_Parent ); 75c2c66affSColin Finck msi_free( feature->Directory ); 76c2c66affSColin Finck msi_free( feature->Description ); 77c2c66affSColin Finck msi_free( feature->Title ); 78c2c66affSColin Finck msi_free( feature ); 79c2c66affSColin Finck } 80c2c66affSColin Finck 81c2c66affSColin Finck static void free_folder( MSIFOLDER *folder ) 82c2c66affSColin Finck { 83c2c66affSColin Finck struct list *item, *cursor; 84c2c66affSColin Finck 85c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &folder->children ) 86c2c66affSColin Finck { 87c2c66affSColin Finck FolderList *fl = LIST_ENTRY( item, FolderList, entry ); 88c2c66affSColin Finck list_remove( &fl->entry ); 89c2c66affSColin Finck msi_free( fl ); 90c2c66affSColin Finck } 91c2c66affSColin Finck msi_free( folder->Parent ); 92c2c66affSColin Finck msi_free( folder->Directory ); 93c2c66affSColin Finck msi_free( folder->TargetDefault ); 94c2c66affSColin Finck msi_free( folder->SourceLongPath ); 95c2c66affSColin Finck msi_free( folder->SourceShortPath ); 96c2c66affSColin Finck msi_free( folder->ResolvedTarget ); 97c2c66affSColin Finck msi_free( folder->ResolvedSource ); 98c2c66affSColin Finck msi_free( folder ); 99c2c66affSColin Finck } 100c2c66affSColin Finck 101c2c66affSColin Finck static void free_extension( MSIEXTENSION *ext ) 102c2c66affSColin Finck { 103c2c66affSColin Finck struct list *item, *cursor; 104c2c66affSColin Finck 105c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs ) 106c2c66affSColin Finck { 107c2c66affSColin Finck MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry ); 108c2c66affSColin Finck 109c2c66affSColin Finck list_remove( &verb->entry ); 110c2c66affSColin Finck msi_free( verb->Verb ); 111c2c66affSColin Finck msi_free( verb->Command ); 112c2c66affSColin Finck msi_free( verb->Argument ); 113c2c66affSColin Finck msi_free( verb ); 114c2c66affSColin Finck } 115c2c66affSColin Finck 116c2c66affSColin Finck msi_free( ext->Extension ); 117c2c66affSColin Finck msi_free( ext->ProgIDText ); 118c2c66affSColin Finck msi_free( ext ); 119c2c66affSColin Finck } 120c2c66affSColin Finck 121c2c66affSColin Finck static void free_assembly( MSIASSEMBLY *assembly ) 122c2c66affSColin Finck { 123c2c66affSColin Finck msi_free( assembly->feature ); 124c2c66affSColin Finck msi_free( assembly->manifest ); 125c2c66affSColin Finck msi_free( assembly->application ); 126c2c66affSColin Finck msi_free( assembly->display_name ); 127c2c66affSColin Finck if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir ); 128c2c66affSColin Finck msi_free( assembly->tempdir ); 129c2c66affSColin Finck msi_free( assembly ); 130c2c66affSColin Finck } 131c2c66affSColin Finck 132c2c66affSColin Finck void msi_free_action_script( MSIPACKAGE *package, UINT script ) 133c2c66affSColin Finck { 134c2c66affSColin Finck UINT i; 135f8b992f2SAmine Khaldi for (i = 0; i < package->script_actions_count[script]; i++) 136f8b992f2SAmine Khaldi msi_free( package->script_actions[script][i] ); 137c2c66affSColin Finck 138f8b992f2SAmine Khaldi msi_free( package->script_actions[script] ); 139f8b992f2SAmine Khaldi package->script_actions[script] = NULL; 140f8b992f2SAmine Khaldi package->script_actions_count[script] = 0; 141c2c66affSColin Finck } 142c2c66affSColin Finck 143c2c66affSColin Finck static void free_package_structures( MSIPACKAGE *package ) 144c2c66affSColin Finck { 145c2c66affSColin Finck struct list *item, *cursor; 146f8b992f2SAmine Khaldi int i; 147c2c66affSColin Finck 148c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->features ) 149c2c66affSColin Finck { 150c2c66affSColin Finck MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); 151c2c66affSColin Finck list_remove( &feature->entry ); 152c2c66affSColin Finck free_feature( feature ); 153c2c66affSColin Finck } 154c2c66affSColin Finck 155c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->folders ) 156c2c66affSColin Finck { 157c2c66affSColin Finck MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); 158c2c66affSColin Finck list_remove( &folder->entry ); 159c2c66affSColin Finck free_folder( folder ); 160c2c66affSColin Finck } 161c2c66affSColin Finck 162c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->files ) 163c2c66affSColin Finck { 164c2c66affSColin Finck MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry ); 165c2c66affSColin Finck 166c2c66affSColin Finck list_remove( &file->entry ); 167c2c66affSColin Finck msi_free( file->File ); 168c2c66affSColin Finck msi_free( file->FileName ); 169c2c66affSColin Finck msi_free( file->ShortName ); 170c2c66affSColin Finck msi_free( file->LongName ); 171c2c66affSColin Finck msi_free( file->Version ); 172c2c66affSColin Finck msi_free( file->Language ); 173c2c66affSColin Finck if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath ); 174c2c66affSColin Finck msi_free( file->TargetPath ); 175c2c66affSColin Finck msi_free( file ); 176c2c66affSColin Finck } 177c2c66affSColin Finck 178c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->components ) 179c2c66affSColin Finck { 180c2c66affSColin Finck MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); 181c2c66affSColin Finck 182c2c66affSColin Finck list_remove( &comp->entry ); 183c2c66affSColin Finck msi_free( comp->Component ); 184c2c66affSColin Finck msi_free( comp->ComponentId ); 185c2c66affSColin Finck msi_free( comp->Directory ); 186c2c66affSColin Finck msi_free( comp->Condition ); 187c2c66affSColin Finck msi_free( comp->KeyPath ); 188c2c66affSColin Finck msi_free( comp->FullKeypath ); 189c2c66affSColin Finck if (comp->assembly) free_assembly( comp->assembly ); 190c2c66affSColin Finck msi_free( comp ); 191c2c66affSColin Finck } 192c2c66affSColin Finck 193c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches ) 194c2c66affSColin Finck { 195c2c66affSColin Finck MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry ); 196c2c66affSColin Finck 197c2c66affSColin Finck list_remove( &patch->entry ); 198c2c66affSColin Finck msi_free( patch->path ); 199c2c66affSColin Finck msi_free( patch ); 200c2c66affSColin Finck } 201c2c66affSColin Finck 202c2c66affSColin Finck /* clean up extension, progid, class and verb structures */ 203c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) 204c2c66affSColin Finck { 205c2c66affSColin Finck MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry ); 206c2c66affSColin Finck 207c2c66affSColin Finck list_remove( &cls->entry ); 208c2c66affSColin Finck msi_free( cls->clsid ); 209c2c66affSColin Finck msi_free( cls->Context ); 210c2c66affSColin Finck msi_free( cls->Description ); 211c2c66affSColin Finck msi_free( cls->FileTypeMask ); 212c2c66affSColin Finck msi_free( cls->IconPath ); 213c2c66affSColin Finck msi_free( cls->DefInprocHandler ); 214c2c66affSColin Finck msi_free( cls->DefInprocHandler32 ); 215c2c66affSColin Finck msi_free( cls->Argument ); 216c2c66affSColin Finck msi_free( cls->ProgIDText ); 217c2c66affSColin Finck msi_free( cls ); 218c2c66affSColin Finck } 219c2c66affSColin Finck 220c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->extensions ) 221c2c66affSColin Finck { 222c2c66affSColin Finck MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry ); 223c2c66affSColin Finck 224c2c66affSColin Finck list_remove( &ext->entry ); 225c2c66affSColin Finck free_extension( ext ); 226c2c66affSColin Finck } 227c2c66affSColin Finck 228c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->progids ) 229c2c66affSColin Finck { 230c2c66affSColin Finck MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry ); 231c2c66affSColin Finck 232c2c66affSColin Finck list_remove( &progid->entry ); 233c2c66affSColin Finck msi_free( progid->ProgID ); 234c2c66affSColin Finck msi_free( progid->Description ); 235c2c66affSColin Finck msi_free( progid->IconPath ); 236c2c66affSColin Finck msi_free( progid ); 237c2c66affSColin Finck } 238c2c66affSColin Finck 239c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) 240c2c66affSColin Finck { 241c2c66affSColin Finck MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry ); 242c2c66affSColin Finck 243c2c66affSColin Finck list_remove( &mt->entry ); 244c2c66affSColin Finck msi_free( mt->suffix ); 245c2c66affSColin Finck msi_free( mt->clsid ); 246c2c66affSColin Finck msi_free( mt->ContentType ); 247c2c66affSColin Finck msi_free( mt ); 248c2c66affSColin Finck } 249c2c66affSColin Finck 250c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->appids ) 251c2c66affSColin Finck { 252c2c66affSColin Finck MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry ); 253c2c66affSColin Finck 254c2c66affSColin Finck list_remove( &appid->entry ); 255c2c66affSColin Finck msi_free( appid->AppID ); 256c2c66affSColin Finck msi_free( appid->RemoteServerName ); 257c2c66affSColin Finck msi_free( appid->LocalServer ); 258c2c66affSColin Finck msi_free( appid->ServiceParameters ); 259c2c66affSColin Finck msi_free( appid->DllSurrogate ); 260c2c66affSColin Finck msi_free( appid ); 261c2c66affSColin Finck } 262c2c66affSColin Finck 263c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info ) 264c2c66affSColin Finck { 265c2c66affSColin Finck MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry ); 266c2c66affSColin Finck 267c2c66affSColin Finck list_remove( &info->entry ); 268c2c66affSColin Finck msi_free( info->value ); 269c2c66affSColin Finck msi_free( info ); 270c2c66affSColin Finck } 271c2c66affSColin Finck 272c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media ) 273c2c66affSColin Finck { 274c2c66affSColin Finck MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry ); 275c2c66affSColin Finck 276c2c66affSColin Finck list_remove( &info->entry ); 277c2c66affSColin Finck msi_free( info->volume_label ); 278c2c66affSColin Finck msi_free( info->disk_prompt ); 279c2c66affSColin Finck msi_free( info ); 280c2c66affSColin Finck } 281c2c66affSColin Finck 282c2c66affSColin Finck for (i = 0; i < SCRIPT_MAX; i++) 283c2c66affSColin Finck msi_free_action_script( package, i ); 284c2c66affSColin Finck 285f8b992f2SAmine Khaldi for (i = 0; i < package->unique_actions_count; i++) 286f8b992f2SAmine Khaldi msi_free( package->unique_actions[i] ); 287f8b992f2SAmine Khaldi msi_free( package->unique_actions); 288c2c66affSColin Finck 289c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->binaries ) 290c2c66affSColin Finck { 291c2c66affSColin Finck MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry ); 292c2c66affSColin Finck 293c2c66affSColin Finck list_remove( &binary->entry ); 294c2c66affSColin Finck if (!DeleteFileW( binary->tmpfile )) 295c2c66affSColin Finck ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError()); 296c2c66affSColin Finck msi_free( binary->source ); 297c2c66affSColin Finck msi_free( binary->tmpfile ); 298c2c66affSColin Finck msi_free( binary ); 299c2c66affSColin Finck } 300c2c66affSColin Finck 301c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams ) 302c2c66affSColin Finck { 303c2c66affSColin Finck MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry ); 304c2c66affSColin Finck 305c2c66affSColin Finck list_remove( &cab->entry ); 306c2c66affSColin Finck IStorage_Release( cab->storage ); 307c2c66affSColin Finck msi_free( cab->stream ); 308c2c66affSColin Finck msi_free( cab ); 309c2c66affSColin Finck } 310c2c66affSColin Finck 311c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->patches ) 312c2c66affSColin Finck { 313c2c66affSColin Finck MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry ); 314c2c66affSColin Finck 315c2c66affSColin Finck list_remove( &patch->entry ); 316c2c66affSColin Finck if (patch->delete_on_close && !DeleteFileW( patch->localfile )) 317c2c66affSColin Finck { 318c2c66affSColin Finck ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError()); 319c2c66affSColin Finck } 320c2c66affSColin Finck msi_free_patchinfo( patch ); 321c2c66affSColin Finck } 322c2c66affSColin Finck 323c2c66affSColin Finck msi_free( package->PackagePath ); 324c2c66affSColin Finck msi_free( package->ProductCode ); 325c2c66affSColin Finck msi_free( package->ActionFormat ); 326c2c66affSColin Finck msi_free( package->LastAction ); 32771bffdcdSAmine Khaldi msi_free( package->LastActionTemplate ); 328c2c66affSColin Finck msi_free( package->langids ); 329c2c66affSColin Finck 330c2c66affSColin Finck /* cleanup control event subscriptions */ 331c2c66affSColin Finck msi_event_cleanup_all_subscriptions( package ); 332c2c66affSColin Finck } 333c2c66affSColin Finck 334c2c66affSColin Finck static void MSI_FreePackage( MSIOBJECTHDR *arg) 335c2c66affSColin Finck { 336c2c66affSColin Finck MSIPACKAGE *package = (MSIPACKAGE *)arg; 337c2c66affSColin Finck 338c2c66affSColin Finck msi_destroy_assembly_caches( package ); 339c2c66affSColin Finck 340c2c66affSColin Finck if( package->dialog ) 341c2c66affSColin Finck msi_dialog_destroy( package->dialog ); 342c2c66affSColin Finck 343c2c66affSColin Finck msiobj_release( &package->db->hdr ); 344c2c66affSColin Finck free_package_structures(package); 345c2c66affSColin Finck CloseHandle( package->log_file ); 3460a327bfeSwinesync if (package->rpc_server_started) 3470a327bfeSwinesync RpcServerUnregisterIf(s_IWineMsiRemote_v0_0_s_ifspec, NULL, FALSE); 348dfdb6d10Swinesync if (rpc_handle) 349dfdb6d10Swinesync RpcBindingFree(&rpc_handle); 35082decec5Swinesync if (package->custom_server_32_process) 35182decec5Swinesync custom_stop_server(package->custom_server_32_process, package->custom_server_32_pipe); 35282decec5Swinesync if (package->custom_server_64_process) 35382decec5Swinesync custom_stop_server(package->custom_server_64_process, package->custom_server_64_pipe); 354c2c66affSColin Finck 355c2c66affSColin Finck if (package->delete_on_close) DeleteFileW( package->localfile ); 356c2c66affSColin Finck msi_free( package->localfile ); 35771bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 358c2c66affSColin Finck } 359c2c66affSColin Finck 360c2c66affSColin Finck static UINT create_temp_property_table(MSIPACKAGE *package) 361c2c66affSColin Finck { 362c2c66affSColin Finck static const WCHAR query[] = { 363c2c66affSColin Finck 'C','R','E','A','T','E',' ','T','A','B','L','E',' ', 364c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ', 365c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 366c2c66affSColin Finck 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ', 367c2c66affSColin Finck 'T','E','M','P','O','R','A','R','Y',',',' ', 368c2c66affSColin Finck '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ', 369c2c66affSColin Finck 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y', 370c2c66affSColin Finck ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ', 371c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0}; 372c2c66affSColin Finck MSIQUERY *view; 373c2c66affSColin Finck UINT rc; 374c2c66affSColin Finck 375c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(package->db, query, &view); 376c2c66affSColin Finck if (rc != ERROR_SUCCESS) 377c2c66affSColin Finck return rc; 378c2c66affSColin Finck 379c2c66affSColin Finck rc = MSI_ViewExecute(view, 0); 380c2c66affSColin Finck MSI_ViewClose(view); 381c2c66affSColin Finck msiobj_release(&view->hdr); 382c2c66affSColin Finck return rc; 383c2c66affSColin Finck } 384c2c66affSColin Finck 385c2c66affSColin Finck UINT msi_clone_properties( MSIDATABASE *db ) 386c2c66affSColin Finck { 387c2c66affSColin Finck static const WCHAR query_select[] = { 388c2c66affSColin Finck 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 389c2c66affSColin Finck '`','P','r','o','p','e','r','t','y','`',0}; 390c2c66affSColin Finck static const WCHAR query_insert[] = { 391c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 392c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 393c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 394c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 395c2c66affSColin Finck static const WCHAR query_update[] = { 396c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 397c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ', 398c2c66affSColin Finck 'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0}; 399c2c66affSColin Finck MSIQUERY *view_select; 400c2c66affSColin Finck UINT rc; 401c2c66affSColin Finck 402c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_select, &view_select ); 403c2c66affSColin Finck if (rc != ERROR_SUCCESS) 404c2c66affSColin Finck return rc; 405c2c66affSColin Finck 406c2c66affSColin Finck rc = MSI_ViewExecute( view_select, 0 ); 407c2c66affSColin Finck if (rc != ERROR_SUCCESS) 408c2c66affSColin Finck { 409c2c66affSColin Finck MSI_ViewClose( view_select ); 410c2c66affSColin Finck msiobj_release( &view_select->hdr ); 411c2c66affSColin Finck return rc; 412c2c66affSColin Finck } 413c2c66affSColin Finck 414c2c66affSColin Finck while (1) 415c2c66affSColin Finck { 416c2c66affSColin Finck MSIQUERY *view_insert, *view_update; 417c2c66affSColin Finck MSIRECORD *rec_select; 418c2c66affSColin Finck 419c2c66affSColin Finck rc = MSI_ViewFetch( view_select, &rec_select ); 420c2c66affSColin Finck if (rc != ERROR_SUCCESS) 421c2c66affSColin Finck break; 422c2c66affSColin Finck 423c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert ); 424c2c66affSColin Finck if (rc != ERROR_SUCCESS) 425c2c66affSColin Finck { 426c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 427c2c66affSColin Finck continue; 428c2c66affSColin Finck } 429c2c66affSColin Finck 430c2c66affSColin Finck rc = MSI_ViewExecute( view_insert, rec_select ); 431c2c66affSColin Finck MSI_ViewClose( view_insert ); 432c2c66affSColin Finck msiobj_release( &view_insert->hdr ); 433c2c66affSColin Finck if (rc != ERROR_SUCCESS) 434c2c66affSColin Finck { 435c2c66affSColin Finck MSIRECORD *rec_update; 436c2c66affSColin Finck 437c2c66affSColin Finck TRACE("insert failed, trying update\n"); 438c2c66affSColin Finck 439c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_update, &view_update ); 440c2c66affSColin Finck if (rc != ERROR_SUCCESS) 441c2c66affSColin Finck { 442c2c66affSColin Finck WARN("open view failed %u\n", rc); 443c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 444c2c66affSColin Finck continue; 445c2c66affSColin Finck } 446c2c66affSColin Finck 447c2c66affSColin Finck rec_update = MSI_CreateRecord( 2 ); 448c2c66affSColin Finck MSI_RecordCopyField( rec_select, 1, rec_update, 2 ); 449c2c66affSColin Finck MSI_RecordCopyField( rec_select, 2, rec_update, 1 ); 450c2c66affSColin Finck rc = MSI_ViewExecute( view_update, rec_update ); 451c2c66affSColin Finck if (rc != ERROR_SUCCESS) 452c2c66affSColin Finck WARN("update failed %u\n", rc); 453c2c66affSColin Finck 454c2c66affSColin Finck MSI_ViewClose( view_update ); 455c2c66affSColin Finck msiobj_release( &view_update->hdr ); 456c2c66affSColin Finck msiobj_release( &rec_update->hdr ); 457c2c66affSColin Finck } 458c2c66affSColin Finck 459c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 460c2c66affSColin Finck } 461c2c66affSColin Finck 462c2c66affSColin Finck MSI_ViewClose( view_select ); 463c2c66affSColin Finck msiobj_release( &view_select->hdr ); 464c2c66affSColin Finck return rc; 465c2c66affSColin Finck } 466c2c66affSColin Finck 467c2c66affSColin Finck /* 468c2c66affSColin Finck * set_installed_prop 469c2c66affSColin Finck * 470c2c66affSColin Finck * Sets the "Installed" property to indicate that 471c2c66affSColin Finck * the product is installed for the current user. 472c2c66affSColin Finck */ 473c2c66affSColin Finck static UINT set_installed_prop( MSIPACKAGE *package ) 474c2c66affSColin Finck { 475c2c66affSColin Finck HKEY hkey; 476c2c66affSColin Finck UINT r; 477c2c66affSColin Finck 478c2c66affSColin Finck if (!package->ProductCode) return ERROR_FUNCTION_FAILED; 479c2c66affSColin Finck 480c2c66affSColin Finck r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE ); 481c2c66affSColin Finck if (r == ERROR_SUCCESS) 482c2c66affSColin Finck { 483c2c66affSColin Finck RegCloseKey( hkey ); 484c2c66affSColin Finck msi_set_property( package->db, szInstalled, szOne, -1 ); 485c2c66affSColin Finck } 486c2c66affSColin Finck return r; 487c2c66affSColin Finck } 488c2c66affSColin Finck 489c2c66affSColin Finck static UINT set_user_sid_prop( MSIPACKAGE *package ) 490c2c66affSColin Finck { 491c2c66affSColin Finck SID_NAME_USE use; 492c2c66affSColin Finck LPWSTR user_name; 493c2c66affSColin Finck LPWSTR sid_str = NULL, dom = NULL; 494c2c66affSColin Finck DWORD size, dom_size; 495c2c66affSColin Finck PSID psid = NULL; 496c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 497c2c66affSColin Finck 498c2c66affSColin Finck size = 0; 499c2c66affSColin Finck GetUserNameW( NULL, &size ); 500c2c66affSColin Finck 501c2c66affSColin Finck user_name = msi_alloc( (size + 1) * sizeof(WCHAR) ); 502c2c66affSColin Finck if (!user_name) 503c2c66affSColin Finck return ERROR_OUTOFMEMORY; 504c2c66affSColin Finck 505c2c66affSColin Finck if (!GetUserNameW( user_name, &size )) 506c2c66affSColin Finck goto done; 507c2c66affSColin Finck 508c2c66affSColin Finck size = 0; 509c2c66affSColin Finck dom_size = 0; 510c2c66affSColin Finck LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use ); 511c2c66affSColin Finck 512c2c66affSColin Finck psid = msi_alloc( size ); 513c2c66affSColin Finck dom = msi_alloc( dom_size*sizeof (WCHAR) ); 514c2c66affSColin Finck if (!psid || !dom) 515c2c66affSColin Finck { 516c2c66affSColin Finck r = ERROR_OUTOFMEMORY; 517c2c66affSColin Finck goto done; 518c2c66affSColin Finck } 519c2c66affSColin Finck 520c2c66affSColin Finck if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use )) 521c2c66affSColin Finck goto done; 522c2c66affSColin Finck 523c2c66affSColin Finck if (!ConvertSidToStringSidW( psid, &sid_str )) 524c2c66affSColin Finck goto done; 525c2c66affSColin Finck 526c2c66affSColin Finck r = msi_set_property( package->db, szUserSID, sid_str, -1 ); 527c2c66affSColin Finck 528c2c66affSColin Finck done: 529c2c66affSColin Finck LocalFree( sid_str ); 530c2c66affSColin Finck msi_free( dom ); 531c2c66affSColin Finck msi_free( psid ); 532c2c66affSColin Finck msi_free( user_name ); 533c2c66affSColin Finck 534c2c66affSColin Finck return r; 535c2c66affSColin Finck } 536c2c66affSColin Finck 537c2c66affSColin Finck static LPWSTR get_fusion_filename(MSIPACKAGE *package) 538c2c66affSColin Finck { 539c42b133eSAmine Khaldi static const WCHAR fusion[] = 540c42b133eSAmine Khaldi {'f','u','s','i','o','n','.','d','l','l',0}; 541c42b133eSAmine Khaldi static const WCHAR subkey[] = 542c42b133eSAmine Khaldi {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 543c42b133eSAmine Khaldi 'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\','N','D','P',0}; 544c42b133eSAmine Khaldi static const WCHAR subdir[] = 545c42b133eSAmine Khaldi {'M','i','c','r','o','s','o','f','t','.','N','E','T','\\','F','r','a','m','e','w','o','r','k','\\',0}; 546c42b133eSAmine Khaldi static const WCHAR v2050727[] = 547c42b133eSAmine Khaldi {'v','2','.','0','.','5','0','7','2','7',0}; 548c42b133eSAmine Khaldi static const WCHAR v4client[] = 549c42b133eSAmine Khaldi {'v','4','\\','C','l','i','e','n','t',0}; 550c42b133eSAmine Khaldi static const WCHAR installpath[] = 551c42b133eSAmine Khaldi {'I','n','s','t','a','l','l','P','a','t','h',0}; 552c42b133eSAmine Khaldi HKEY netsetup, hkey; 553c2c66affSColin Finck LONG res; 554c42b133eSAmine Khaldi DWORD size, len, type; 555c42b133eSAmine Khaldi WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL; 556c2c66affSColin Finck 557c42b133eSAmine Khaldi res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, subkey, 0, KEY_CREATE_SUB_KEY, &netsetup); 558c2c66affSColin Finck if (res != ERROR_SUCCESS) 559c2c66affSColin Finck return NULL; 560c2c66affSColin Finck 561c42b133eSAmine Khaldi if (!RegCreateKeyExW(netsetup, v4client, 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 562c42b133eSAmine Khaldi { 5639792c08fSwinesync size = ARRAY_SIZE(path); 564c42b133eSAmine Khaldi if (!RegQueryValueExW(hkey, installpath, NULL, &type, (BYTE *)path, &size)) 565c42b133eSAmine Khaldi { 566c42b133eSAmine Khaldi len = strlenW(path) + strlenW(fusion) + 2; 567c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 568c42b133eSAmine Khaldi 569c42b133eSAmine Khaldi strcpyW(filename, path); 570c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 571c42b133eSAmine Khaldi strcatW(filename, fusion); 572c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 573c42b133eSAmine Khaldi { 574c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 575c42b133eSAmine Khaldi RegCloseKey(hkey); 576c42b133eSAmine Khaldi RegCloseKey(netsetup); 577c42b133eSAmine Khaldi return filename; 578c42b133eSAmine Khaldi } 579c42b133eSAmine Khaldi } 580c42b133eSAmine Khaldi RegCloseKey(hkey); 581c42b133eSAmine Khaldi } 582c42b133eSAmine Khaldi 583c42b133eSAmine Khaldi if (!RegCreateKeyExW(netsetup, v2050727, 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 584c42b133eSAmine Khaldi { 585c42b133eSAmine Khaldi RegCloseKey(hkey); 586c2c66affSColin Finck GetWindowsDirectoryW(windir, MAX_PATH); 587c42b133eSAmine Khaldi len = strlenW(windir) + strlenW(subdir) + strlenW(v2050727) + strlenW(fusion) + 3; 588c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 589c2c66affSColin Finck 590c42b133eSAmine Khaldi strcpyW(filename, windir); 591c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 592c42b133eSAmine Khaldi strcatW(filename, subdir); 593c42b133eSAmine Khaldi strcatW(filename, v2050727); 594c42b133eSAmine Khaldi strcatW(filename, szBackSlash); 595c42b133eSAmine Khaldi strcatW(filename, fusion); 596c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 597c2c66affSColin Finck { 598c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 599c42b133eSAmine Khaldi RegCloseKey(netsetup); 600c42b133eSAmine Khaldi return filename; 601c2c66affSColin Finck } 602c2c66affSColin Finck } 603c2c66affSColin Finck 604c2c66affSColin Finck RegCloseKey(netsetup); 605c42b133eSAmine Khaldi return filename; 606c2c66affSColin Finck } 607c2c66affSColin Finck 608c2c66affSColin Finck typedef struct tagLANGANDCODEPAGE 609c2c66affSColin Finck { 610c2c66affSColin Finck WORD wLanguage; 611c2c66affSColin Finck WORD wCodePage; 612c2c66affSColin Finck } LANGANDCODEPAGE; 613c2c66affSColin Finck 614c2c66affSColin Finck static void set_msi_assembly_prop(MSIPACKAGE *package) 615c2c66affSColin Finck { 616c2c66affSColin Finck UINT val_len; 617c2c66affSColin Finck DWORD size, handle; 618c2c66affSColin Finck LPVOID version = NULL; 619c2c66affSColin Finck WCHAR buf[MAX_PATH]; 620c2c66affSColin Finck LPWSTR fusion, verstr; 621c2c66affSColin Finck LANGANDCODEPAGE *translate; 622c2c66affSColin Finck 623c2c66affSColin Finck static const WCHAR netasm[] = { 624c2c66affSColin Finck 'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0 625c2c66affSColin Finck }; 626c2c66affSColin Finck static const WCHAR translation[] = { 627c2c66affSColin Finck '\\','V','a','r','F','i','l','e','I','n','f','o', 628c2c66affSColin Finck '\\','T','r','a','n','s','l','a','t','i','o','n',0 629c2c66affSColin Finck }; 630c2c66affSColin Finck static const WCHAR verfmt[] = { 631c2c66affSColin Finck '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o', 632c2c66affSColin Finck '\\','%','0','4','x','%','0','4','x', 633c2c66affSColin Finck '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 634c2c66affSColin Finck }; 635c2c66affSColin Finck 636c2c66affSColin Finck fusion = get_fusion_filename(package); 637c2c66affSColin Finck if (!fusion) 638c2c66affSColin Finck return; 639c2c66affSColin Finck 640c2c66affSColin Finck size = GetFileVersionInfoSizeW(fusion, &handle); 641c2c66affSColin Finck if (!size) 642c2c66affSColin Finck goto done; 643c2c66affSColin Finck 644c2c66affSColin Finck version = msi_alloc(size); 645c2c66affSColin Finck if (!version) 646c2c66affSColin Finck goto done; 647c2c66affSColin Finck 648c2c66affSColin Finck if (!GetFileVersionInfoW(fusion, handle, size, version)) 649c2c66affSColin Finck goto done; 650c2c66affSColin Finck 651c2c66affSColin Finck if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len)) 652c2c66affSColin Finck goto done; 653c2c66affSColin Finck 654c2c66affSColin Finck sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage); 655c2c66affSColin Finck 656c2c66affSColin Finck if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len)) 657c2c66affSColin Finck goto done; 658c2c66affSColin Finck 659c2c66affSColin Finck if (!val_len || !verstr) 660c2c66affSColin Finck goto done; 661c2c66affSColin Finck 662c2c66affSColin Finck msi_set_property( package->db, netasm, verstr, -1 ); 663c2c66affSColin Finck 664c2c66affSColin Finck done: 665c2c66affSColin Finck msi_free(fusion); 666c2c66affSColin Finck msi_free(version); 667c2c66affSColin Finck } 668c2c66affSColin Finck 669c2c66affSColin Finck static VOID set_installer_properties(MSIPACKAGE *package) 670c2c66affSColin Finck { 671c2c66affSColin Finck WCHAR *ptr; 672c2c66affSColin Finck OSVERSIONINFOEXW OSVersion; 673c2c66affSColin Finck MEMORYSTATUSEX msex; 6743ec0ea99Swinesync DWORD verval, len, type; 675c2c66affSColin Finck WCHAR pth[MAX_PATH], verstr[11], bufstr[22]; 676c2c66affSColin Finck HDC dc; 677c2c66affSColin Finck HKEY hkey; 678c2c66affSColin Finck LPWSTR username, companyname; 679c2c66affSColin Finck SYSTEM_INFO sys_info; 680c2c66affSColin Finck LANGID langid; 681c2c66affSColin Finck 682c2c66affSColin Finck static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0}; 683c2c66affSColin Finck static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0}; 684c2c66affSColin 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}; 685c2c66affSColin Finck static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0}; 686c2c66affSColin Finck static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0}; 687c2c66affSColin Finck static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0}; 688c2c66affSColin Finck static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0}; 689c2c66affSColin Finck static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0}; 690c2c66affSColin Finck static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0}; 691c2c66affSColin Finck static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0}; 692c2c66affSColin Finck static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0}; 693c2c66affSColin Finck static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0}; 694c2c66affSColin Finck static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0}; 695c2c66affSColin Finck static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0}; 696c2c66affSColin Finck static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; 697c2c66affSColin Finck static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0}; 698c2c66affSColin Finck static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0}; 699c2c66affSColin Finck static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0}; 700c2c66affSColin Finck static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0}; 701c2c66affSColin Finck static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0}; 702c2c66affSColin Finck static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0}; 703c2c66affSColin Finck static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0}; 704c2c66affSColin Finck static const WCHAR szFormat[] = {'%','u',0}; 705c2c66affSColin Finck static const WCHAR szFormat2[] = {'%','u','.','%','u',0}; 706c2c66affSColin Finck static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0}; 707c2c66affSColin Finck static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0}; 708c2c66affSColin Finck static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 }; 709c2c66affSColin Finck static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 }; 710c2c66affSColin Finck static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 }; 711c2c66affSColin Finck static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0}; 712c2c66affSColin Finck static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0}; 713c2c66affSColin Finck static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0}; 714c2c66affSColin Finck static const WCHAR szIntFormat[] = {'%','d',0}; 715c2c66affSColin Finck static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 }; 716c2c66affSColin Finck static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 }; 717c2c66affSColin Finck static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 }; 718c2c66affSColin 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 }; 719c2c66affSColin 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 }; 7203ec0ea99Swinesync static const WCHAR szProgramFilesDir[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r',0}; 7213ec0ea99Swinesync static const WCHAR szProgramFilesDirx86[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r',' ','(','x','8','6',')',0}; 7223ec0ea99Swinesync static const WCHAR szCommonFilesDir[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r',0}; 7233ec0ea99Swinesync static const WCHAR szCommonFilesDirx86[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r',' ','(','x','8','6',')',0}; 724c2c66affSColin Finck static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 }; 725c2c66affSColin Finck static const WCHAR szUserInfo[] = { 726c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 727c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 728c2c66affSColin Finck 'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\', 729c2c66affSColin Finck 'U','s','e','r',' ','I','n','f','o',0 730c2c66affSColin Finck }; 731c2c66affSColin Finck static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 }; 732c2c66affSColin Finck static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 }; 733c2c66affSColin Finck static const WCHAR szCurrentVersion[] = { 734c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 735c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 7363ec0ea99Swinesync 'W','i','n','d','o','w','s','\\', 7373ec0ea99Swinesync 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0 7383ec0ea99Swinesync }; 7393ec0ea99Swinesync static const WCHAR szCurrentVersionNT[] = { 7403ec0ea99Swinesync 'S','O','F','T','W','A','R','E','\\', 7413ec0ea99Swinesync 'M','i','c','r','o','s','o','f','t','\\', 742c2c66affSColin Finck 'W','i','n','d','o','w','s',' ','N','T','\\', 743c2c66affSColin Finck 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0 744c2c66affSColin Finck }; 745c2c66affSColin Finck static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0}; 746c2c66affSColin Finck static const WCHAR szRegisteredOrganization[] = { 747c2c66affSColin Finck 'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0 748c2c66affSColin Finck }; 749c2c66affSColin Finck static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0}; 750c2c66affSColin Finck static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0}; 751c2c66affSColin Finck static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0}; 752c2c66affSColin Finck static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0}; 753c2c66affSColin Finck static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0}; 754c2c66affSColin Finck static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0}; 755c2c66affSColin Finck static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0}; 756c2c66affSColin Finck static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0}; 757c2c66affSColin Finck static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0}; 758c2c66affSColin Finck static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0}; 759c2c66affSColin Finck 760c2c66affSColin Finck /* 761c2c66affSColin Finck * Other things that probably should be set: 762c2c66affSColin Finck * 763c2c66affSColin Finck * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging 764c2c66affSColin Finck * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport 765c2c66affSColin Finck */ 766c2c66affSColin Finck 767c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); 768c2c66affSColin Finck strcatW(pth, szBackSlash); 769c2c66affSColin Finck msi_set_property( package->db, szCommonAppDataFolder, pth, -1 ); 770c2c66affSColin Finck 771c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); 772c2c66affSColin Finck strcatW(pth, szBackSlash); 773c2c66affSColin Finck msi_set_property( package->db, szFavoritesFolder, pth, -1 ); 774c2c66affSColin Finck 775c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); 776c2c66affSColin Finck strcatW(pth, szBackSlash); 777c2c66affSColin Finck msi_set_property( package->db, szFontsFolder, pth, -1 ); 778c2c66affSColin Finck 779c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); 780c2c66affSColin Finck strcatW(pth, szBackSlash); 781c2c66affSColin Finck msi_set_property( package->db, szSendToFolder, pth, -1 ); 782c2c66affSColin Finck 783c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); 784c2c66affSColin Finck strcatW(pth, szBackSlash); 785c2c66affSColin Finck msi_set_property( package->db, szStartMenuFolder, pth, -1 ); 786c2c66affSColin Finck 787c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); 788c2c66affSColin Finck strcatW(pth, szBackSlash); 789c2c66affSColin Finck msi_set_property( package->db, szStartupFolder, pth, -1 ); 790c2c66affSColin Finck 791c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); 792c2c66affSColin Finck strcatW(pth, szBackSlash); 793c2c66affSColin Finck msi_set_property( package->db, szTemplateFolder, pth, -1 ); 794c2c66affSColin Finck 795c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); 796c2c66affSColin Finck strcatW(pth, szBackSlash); 797c2c66affSColin Finck msi_set_property( package->db, szDesktopFolder, pth, -1 ); 798c2c66affSColin Finck 799c2c66affSColin Finck /* FIXME: set to AllUsers profile path if ALLUSERS is set */ 800c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); 801c2c66affSColin Finck strcatW(pth, szBackSlash); 802c2c66affSColin Finck msi_set_property( package->db, szProgramMenuFolder, pth, -1 ); 803c2c66affSColin Finck 804c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); 805c2c66affSColin Finck strcatW(pth, szBackSlash); 806c2c66affSColin Finck msi_set_property( package->db, szAdminToolsFolder, pth, -1 ); 807c2c66affSColin Finck 808c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); 809c2c66affSColin Finck strcatW(pth, szBackSlash); 810c2c66affSColin Finck msi_set_property( package->db, szAppDataFolder, pth, -1 ); 811c2c66affSColin Finck 812c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); 813c2c66affSColin Finck strcatW(pth, szBackSlash); 814c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 815c2c66affSColin Finck msi_set_property( package->db, szSystem16Folder, pth, -1 ); 816c2c66affSColin Finck 817c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); 818c2c66affSColin Finck strcatW(pth, szBackSlash); 819c2c66affSColin Finck msi_set_property( package->db, szLocalAppDataFolder, pth, -1 ); 820c2c66affSColin Finck 821c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); 822c2c66affSColin Finck strcatW(pth, szBackSlash); 823c2c66affSColin Finck msi_set_property( package->db, szMyPicturesFolder, pth, -1 ); 824c2c66affSColin Finck 825c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); 826c2c66affSColin Finck strcatW(pth, szBackSlash); 827c2c66affSColin Finck msi_set_property( package->db, szPersonalFolder, pth, -1 ); 828c2c66affSColin Finck 829c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 830c2c66affSColin Finck strcatW(pth, szBackSlash); 831c2c66affSColin Finck msi_set_property( package->db, szWindowsFolder, pth, -1 ); 832c2c66affSColin Finck 833c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); 834c2c66affSColin Finck strcatW(pth, szBackSlash); 835c2c66affSColin Finck msi_set_property( package->db, szPrintHoodFolder, pth, -1 ); 836c2c66affSColin Finck 837c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); 838c2c66affSColin Finck strcatW(pth, szBackSlash); 839c2c66affSColin Finck msi_set_property( package->db, szNetHoodFolder, pth, -1 ); 840c2c66affSColin Finck 841c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); 842c2c66affSColin Finck strcatW(pth, szBackSlash); 843c2c66affSColin Finck msi_set_property( package->db, szRecentFolder, pth, -1 ); 844c2c66affSColin Finck 845c2c66affSColin Finck /* Physical Memory is specified in MB. Using total amount. */ 846c2c66affSColin Finck msex.dwLength = sizeof(msex); 847c2c66affSColin Finck GlobalMemoryStatusEx( &msex ); 848c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); 849c2c66affSColin Finck msi_set_property( package->db, szPhysicalMemory, bufstr, len ); 850c2c66affSColin Finck 851c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 852c2c66affSColin Finck ptr = strchrW(pth,'\\'); 853c2c66affSColin Finck if (ptr) *(ptr + 1) = 0; 854c2c66affSColin Finck msi_set_property( package->db, szWindowsVolume, pth, -1 ); 855c2c66affSColin Finck 856c2c66affSColin Finck len = GetTempPathW(MAX_PATH, pth); 857c2c66affSColin Finck msi_set_property( package->db, szTempFolder, pth, len ); 858c2c66affSColin Finck 859c2c66affSColin Finck /* in a wine environment the user is always admin and privileged */ 860c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 861c2c66affSColin Finck msi_set_property( package->db, szPrivileged, szOne, -1 ); 862c2c66affSColin Finck 863c2c66affSColin Finck /* set the os things */ 864c2c66affSColin Finck OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); 865c2c66affSColin Finck GetVersionExW((OSVERSIONINFOW *)&OSVersion); 866c2c66affSColin Finck verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; 867c2c66affSColin Finck len = sprintfW( verstr, szFormat, verval ); 868c2c66affSColin Finck switch (OSVersion.dwPlatformId) 869c2c66affSColin Finck { 870c2c66affSColin Finck case VER_PLATFORM_WIN32_WINDOWS: 871c2c66affSColin Finck msi_set_property( package->db, szVersion9x, verstr, len ); 872c2c66affSColin Finck break; 873c2c66affSColin Finck case VER_PLATFORM_WIN32_NT: 874c2c66affSColin Finck msi_set_property( package->db, szVersionNT, verstr, len ); 875c2c66affSColin Finck len = sprintfW( bufstr, szFormat,OSVersion.wProductType ); 876c2c66affSColin Finck msi_set_property( package->db, szMsiNTProductType, bufstr, len ); 877c2c66affSColin Finck break; 878c2c66affSColin Finck } 879c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber ); 880c2c66affSColin Finck msi_set_property( package->db, szWindowsBuild, bufstr, len ); 881c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor ); 882c2c66affSColin Finck msi_set_property( package->db, szServicePackLevel, bufstr, len ); 883c2c66affSColin Finck 884c2c66affSColin Finck len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION ); 885c2c66affSColin Finck msi_set_property( package->db, szVersionMsi, bufstr, len ); 886c2c66affSColin Finck len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 ); 887c2c66affSColin Finck msi_set_property( package->db, szVersionDatabase, bufstr, len ); 888c2c66affSColin Finck 8893ec0ea99Swinesync RegOpenKeyExW(HKEY_LOCAL_MACHINE, szCurrentVersion, 0, 8903ec0ea99Swinesync KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hkey); 8913ec0ea99Swinesync 892c2c66affSColin Finck GetNativeSystemInfo( &sys_info ); 893c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); 894c2c66affSColin Finck msi_set_property( package->db, szIntel, bufstr, len ); 895c2c66affSColin Finck if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 896c2c66affSColin Finck { 897c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 898c2c66affSColin Finck PathAddBackslashW( pth ); 899c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 900c2c66affSColin Finck 9013ec0ea99Swinesync len = MAX_PATH; 9023ec0ea99Swinesync RegQueryValueExW(hkey, szProgramFilesDir, 0, &type, (BYTE *)pth, &len); 903c2c66affSColin Finck PathAddBackslashW( pth ); 904c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 905c2c66affSColin Finck 9063ec0ea99Swinesync len = MAX_PATH; 9073ec0ea99Swinesync RegQueryValueExW(hkey, szCommonFilesDir, 0, &type, (BYTE *)pth, &len); 908c2c66affSColin Finck PathAddBackslashW( pth ); 909c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 910c2c66affSColin Finck } 911c2c66affSColin Finck else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 912c2c66affSColin Finck { 913c2c66affSColin Finck msi_set_property( package->db, szMsiAMD64, bufstr, -1 ); 914c2c66affSColin Finck msi_set_property( package->db, szMsix64, bufstr, -1 ); 915c2c66affSColin Finck msi_set_property( package->db, szVersionNT64, verstr, -1 ); 916c2c66affSColin Finck 917c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 918c2c66affSColin Finck PathAddBackslashW( pth ); 919c2c66affSColin Finck msi_set_property( package->db, szSystem64Folder, pth, -1 ); 920c2c66affSColin Finck 921c2c66affSColin Finck GetSystemWow64DirectoryW( pth, MAX_PATH ); 922c2c66affSColin Finck PathAddBackslashW( pth ); 923c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 924c2c66affSColin Finck 9253ec0ea99Swinesync len = MAX_PATH; 9263ec0ea99Swinesync RegQueryValueExW(hkey, szProgramFilesDir, 0, &type, (BYTE *)pth, &len); 927c2c66affSColin Finck PathAddBackslashW( pth ); 928c2c66affSColin Finck msi_set_property( package->db, szProgramFiles64Folder, pth, -1 ); 929c2c66affSColin Finck 9303ec0ea99Swinesync len = MAX_PATH; 9313ec0ea99Swinesync RegQueryValueExW(hkey, szProgramFilesDirx86, 0, &type, (BYTE *)pth, &len); 932c2c66affSColin Finck PathAddBackslashW( pth ); 933c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 934c2c66affSColin Finck 9353ec0ea99Swinesync len = MAX_PATH; 9363ec0ea99Swinesync RegQueryValueExW(hkey, szCommonFilesDir, 0, &type, (BYTE *)pth, &len); 937c2c66affSColin Finck PathAddBackslashW( pth ); 938c2c66affSColin Finck msi_set_property( package->db, szCommonFiles64Folder, pth, -1 ); 939c2c66affSColin Finck 9403ec0ea99Swinesync len = MAX_PATH; 9413ec0ea99Swinesync RegQueryValueExW(hkey, szCommonFilesDirx86, 0, &type, (BYTE *)pth, &len); 942c2c66affSColin Finck PathAddBackslashW( pth ); 943c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 944c2c66affSColin Finck } 945c2c66affSColin Finck 9463ec0ea99Swinesync RegCloseKey(hkey); 9473ec0ea99Swinesync 948c2c66affSColin Finck /* Screen properties. */ 949c2c66affSColin Finck dc = GetDC(0); 950c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) ); 951c2c66affSColin Finck msi_set_property( package->db, szScreenX, bufstr, len ); 952c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) ); 953c2c66affSColin Finck msi_set_property( package->db, szScreenY, bufstr, len ); 954c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) ); 955c2c66affSColin Finck msi_set_property( package->db, szColorBits, bufstr, len ); 956c2c66affSColin Finck ReleaseDC(0, dc); 957c2c66affSColin Finck 958c2c66affSColin Finck /* USERNAME and COMPANYNAME */ 959c2c66affSColin Finck username = msi_dup_property( package->db, szUSERNAME ); 960c2c66affSColin Finck companyname = msi_dup_property( package->db, szCOMPANYNAME ); 961c2c66affSColin Finck 962c2c66affSColin Finck if ((!username || !companyname) && 963c2c66affSColin Finck RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS) 964c2c66affSColin Finck { 965c2c66affSColin Finck if (!username && 966c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szDefName ))) 967c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 968c2c66affSColin Finck if (!companyname && 969c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szDefCompany ))) 970c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 971c2c66affSColin Finck CloseHandle( hkey ); 972c2c66affSColin Finck } 973c2c66affSColin Finck if ((!username || !companyname) && 9743ec0ea99Swinesync RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersionNT, &hkey ) == ERROR_SUCCESS) 975c2c66affSColin Finck { 976c2c66affSColin Finck if (!username && 977c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szRegisteredUser ))) 978c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 979c2c66affSColin Finck if (!companyname && 980c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization ))) 981c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 982c2c66affSColin Finck CloseHandle( hkey ); 983c2c66affSColin Finck } 984c2c66affSColin Finck msi_free( username ); 985c2c66affSColin Finck msi_free( companyname ); 986c2c66affSColin Finck 987c2c66affSColin Finck if ( set_user_sid_prop( package ) != ERROR_SUCCESS) 988c2c66affSColin Finck ERR("Failed to set the UserSID property\n"); 989c2c66affSColin Finck 990c2c66affSColin Finck set_msi_assembly_prop( package ); 991c2c66affSColin Finck 992c2c66affSColin Finck langid = GetUserDefaultLangID(); 993c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 994c2c66affSColin Finck msi_set_property( package->db, szUserLanguageID, bufstr, len ); 995c2c66affSColin Finck 996c2c66affSColin Finck langid = GetSystemDefaultLangID(); 997c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 998c2c66affSColin Finck msi_set_property( package->db, szSystemLangID, bufstr, len ); 999c2c66affSColin Finck 1000c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) ); 1001c2c66affSColin Finck msi_set_property( package->db, szProductState, bufstr, len ); 1002c2c66affSColin Finck 1003c2c66affSColin Finck len = 0; 1004c2c66affSColin Finck if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 1005c2c66affSColin Finck { 1006c2c66affSColin Finck WCHAR *username; 1007c2c66affSColin Finck if ((username = msi_alloc( len * sizeof(WCHAR) ))) 1008c2c66affSColin Finck { 1009c2c66affSColin Finck if (GetUserNameW( username, &len )) 1010c2c66affSColin Finck msi_set_property( package->db, szLogonUser, username, len - 1 ); 1011c2c66affSColin Finck msi_free( username ); 1012c2c66affSColin Finck } 1013c2c66affSColin Finck } 1014c2c66affSColin Finck len = 0; 1015c2c66affSColin Finck if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW) 1016c2c66affSColin Finck { 1017c2c66affSColin Finck WCHAR *computername; 1018c2c66affSColin Finck if ((computername = msi_alloc( len * sizeof(WCHAR) ))) 1019c2c66affSColin Finck { 1020c2c66affSColin Finck if (GetComputerNameW( computername, &len )) 1021c2c66affSColin Finck msi_set_property( package->db, szComputerName, computername, len ); 1022c2c66affSColin Finck msi_free( computername ); 1023c2c66affSColin Finck } 1024c2c66affSColin Finck } 1025c2c66affSColin Finck } 1026c2c66affSColin Finck 1027c2c66affSColin Finck static MSIPACKAGE *msi_alloc_package( void ) 1028c2c66affSColin Finck { 1029c2c66affSColin Finck MSIPACKAGE *package; 1030c2c66affSColin Finck 1031c2c66affSColin Finck package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), 1032c2c66affSColin Finck MSI_FreePackage ); 1033c2c66affSColin Finck if( package ) 1034c2c66affSColin Finck { 1035c2c66affSColin Finck list_init( &package->components ); 1036c2c66affSColin Finck list_init( &package->features ); 1037c2c66affSColin Finck list_init( &package->files ); 1038c2c66affSColin Finck list_init( &package->filepatches ); 1039c2c66affSColin Finck list_init( &package->tempfiles ); 1040c2c66affSColin Finck list_init( &package->folders ); 1041c2c66affSColin Finck list_init( &package->subscriptions ); 1042c2c66affSColin Finck list_init( &package->appids ); 1043c2c66affSColin Finck list_init( &package->classes ); 1044c2c66affSColin Finck list_init( &package->mimes ); 1045c2c66affSColin Finck list_init( &package->extensions ); 1046c2c66affSColin Finck list_init( &package->progids ); 1047c2c66affSColin Finck list_init( &package->RunningActions ); 1048c2c66affSColin Finck list_init( &package->sourcelist_info ); 1049c2c66affSColin Finck list_init( &package->sourcelist_media ); 1050c2c66affSColin Finck list_init( &package->patches ); 1051c2c66affSColin Finck list_init( &package->binaries ); 1052c2c66affSColin Finck list_init( &package->cabinet_streams ); 1053c2c66affSColin Finck } 1054c2c66affSColin Finck 1055c2c66affSColin Finck return package; 1056c2c66affSColin Finck } 1057c2c66affSColin Finck 1058c2c66affSColin Finck static UINT msi_load_admin_properties(MSIPACKAGE *package) 1059c2c66affSColin Finck { 1060c2c66affSColin Finck BYTE *data; 1061c2c66affSColin Finck UINT r, sz; 1062c2c66affSColin Finck 1063c2c66affSColin Finck static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0}; 1064c2c66affSColin Finck 1065c2c66affSColin Finck r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz); 1066c2c66affSColin Finck if (r != ERROR_SUCCESS) 1067c2c66affSColin Finck return r; 1068c2c66affSColin Finck 1069c2c66affSColin Finck r = msi_parse_command_line(package, (WCHAR *)data, TRUE); 1070c2c66affSColin Finck 1071c2c66affSColin Finck msi_free(data); 1072c2c66affSColin Finck return r; 1073c2c66affSColin Finck } 1074c2c66affSColin Finck 1075c2c66affSColin Finck void msi_adjust_privilege_properties( MSIPACKAGE *package ) 1076c2c66affSColin Finck { 1077c2c66affSColin Finck /* FIXME: this should depend on the user's privileges */ 1078c2c66affSColin Finck if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2) 1079c2c66affSColin Finck { 1080c2c66affSColin Finck TRACE("resetting ALLUSERS property from 2 to 1\n"); 1081c2c66affSColin Finck msi_set_property( package->db, szAllUsers, szOne, -1 ); 1082c2c66affSColin Finck } 1083c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 1084c2c66affSColin Finck } 1085c2c66affSColin Finck 108634c2011cSwinesync MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db ) 1087c2c66affSColin Finck { 1088c2c66affSColin Finck static const WCHAR fmtW[] = {'%','u',0}; 1089c2c66affSColin Finck MSIPACKAGE *package; 1090c2c66affSColin Finck WCHAR uilevel[11]; 1091c2c66affSColin Finck int len; 1092c2c66affSColin Finck UINT r; 1093c2c66affSColin Finck 1094c2c66affSColin Finck TRACE("%p\n", db); 1095c2c66affSColin Finck 1096c2c66affSColin Finck package = msi_alloc_package(); 1097c2c66affSColin Finck if (package) 1098c2c66affSColin Finck { 1099c2c66affSColin Finck msiobj_addref( &db->hdr ); 1100c2c66affSColin Finck package->db = db; 1101c2c66affSColin Finck 110271bffdcdSAmine Khaldi package->LastAction = NULL; 110371bffdcdSAmine Khaldi package->LastActionTemplate = NULL; 110471bffdcdSAmine Khaldi package->LastActionResult = MSI_NULL_INTEGER; 1105c2c66affSColin Finck package->WordCount = 0; 1106c2c66affSColin Finck package->PackagePath = strdupW( db->path ); 1107c2c66affSColin Finck 1108c2c66affSColin Finck create_temp_property_table( package ); 1109c2c66affSColin Finck msi_clone_properties( package->db ); 1110c2c66affSColin Finck msi_adjust_privilege_properties( package ); 1111c2c66affSColin Finck 1112c2c66affSColin Finck package->ProductCode = msi_dup_property( package->db, szProductCode ); 1113c2c66affSColin Finck 1114c2c66affSColin Finck set_installer_properties( package ); 1115c2c66affSColin Finck 1116c2c66affSColin Finck package->ui_level = gUILevel; 1117c2c66affSColin Finck len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); 1118c2c66affSColin Finck msi_set_property( package->db, szUILevel, uilevel, len ); 1119c2c66affSColin Finck 1120c2c66affSColin Finck r = msi_load_suminfo_properties( package ); 1121c2c66affSColin Finck if (r != ERROR_SUCCESS) 1122c2c66affSColin Finck { 1123c2c66affSColin Finck msiobj_release( &package->hdr ); 1124c2c66affSColin Finck return NULL; 1125c2c66affSColin Finck } 1126c2c66affSColin Finck 1127c2c66affSColin Finck if (package->WordCount & msidbSumInfoSourceTypeAdminImage) 1128c2c66affSColin Finck msi_load_admin_properties( package ); 1129c2c66affSColin Finck 1130c2c66affSColin Finck package->log_file = INVALID_HANDLE_VALUE; 11310d762dcbSwinesync package->script = SCRIPT_NONE; 1132c2c66affSColin Finck } 1133c2c66affSColin Finck return package; 1134c2c66affSColin Finck } 1135c2c66affSColin Finck 1136c2c66affSColin Finck UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) 1137c2c66affSColin Finck { 1138c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW cache_entry; 1139c2c66affSColin Finck DWORD size = 0; 1140c2c66affSColin Finck HRESULT hr; 1141c2c66affSColin Finck 1142c2c66affSColin Finck /* call will always fail, because size is 0, 1143c2c66affSColin Finck * but will return ERROR_FILE_NOT_FOUND first 1144c2c66affSColin Finck * if the file doesn't exist 1145c2c66affSColin Finck */ 1146c2c66affSColin Finck GetUrlCacheEntryInfoW( szUrl, NULL, &size ); 1147c2c66affSColin Finck if ( GetLastError() != ERROR_FILE_NOT_FOUND ) 1148c2c66affSColin Finck { 1149c2c66affSColin Finck cache_entry = msi_alloc( size ); 1150c2c66affSColin Finck if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) 1151c2c66affSColin Finck { 1152c2c66affSColin Finck UINT error = GetLastError(); 1153c2c66affSColin Finck msi_free( cache_entry ); 1154c2c66affSColin Finck return error; 1155c2c66affSColin Finck } 1156c2c66affSColin Finck 1157c2c66affSColin Finck lstrcpyW( filename, cache_entry->lpszLocalFileName ); 1158c2c66affSColin Finck msi_free( cache_entry ); 1159c2c66affSColin Finck return ERROR_SUCCESS; 1160c2c66affSColin Finck } 1161c2c66affSColin Finck 1162c2c66affSColin Finck hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); 1163c2c66affSColin Finck if ( FAILED(hr) ) 1164c2c66affSColin Finck { 1165c2c66affSColin Finck WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); 1166c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1167c2c66affSColin Finck } 1168c2c66affSColin Finck 1169c2c66affSColin Finck return ERROR_SUCCESS; 1170c2c66affSColin Finck } 1171c2c66affSColin Finck 1172c2c66affSColin Finck UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) 1173c2c66affSColin Finck { 1174c2c66affSColin Finck static const WCHAR szInstaller[] = { 1175c2c66affSColin Finck '\\','I','n','s','t','a','l','l','e','r','\\',0}; 1176c2c66affSColin Finck static const WCHAR fmt[] = {'%','x',0}; 1177c2c66affSColin Finck DWORD time, len, i, offset; 1178c2c66affSColin Finck HANDLE handle; 1179c2c66affSColin Finck 1180c2c66affSColin Finck time = GetTickCount(); 1181c2c66affSColin Finck GetWindowsDirectoryW( path, MAX_PATH ); 1182c2c66affSColin Finck strcatW( path, szInstaller ); 1183c2c66affSColin Finck CreateDirectoryW( path, NULL ); 1184c2c66affSColin Finck 1185c2c66affSColin Finck len = strlenW(path); 1186c2c66affSColin Finck for (i = 0; i < 0x10000; i++) 1187c2c66affSColin Finck { 1188c2c66affSColin Finck offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff ); 1189c2c66affSColin Finck memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) ); 1190c2c66affSColin Finck handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, 1191c2c66affSColin Finck CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); 1192c2c66affSColin Finck if (handle != INVALID_HANDLE_VALUE) 1193c2c66affSColin Finck { 1194c2c66affSColin Finck CloseHandle(handle); 1195c2c66affSColin Finck break; 1196c2c66affSColin Finck } 1197c2c66affSColin Finck if (GetLastError() != ERROR_FILE_EXISTS && 1198c2c66affSColin Finck GetLastError() != ERROR_SHARING_VIOLATION) 1199c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1200c2c66affSColin Finck } 1201c2c66affSColin Finck 1202c2c66affSColin Finck return ERROR_SUCCESS; 1203c2c66affSColin Finck } 1204c2c66affSColin Finck 1205c2c66affSColin Finck static enum platform parse_platform( const WCHAR *str ) 1206c2c66affSColin Finck { 1207c2c66affSColin Finck if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL; 1208c2c66affSColin Finck else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64; 1209c2c66affSColin Finck else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64; 1210c2c66affSColin Finck else if (!strcmpW( str, szARM )) return PLATFORM_ARM; 1211de59794fSwinesync else if (!strcmpW( str, szARM64 )) return PLATFORM_ARM64; 1212c2c66affSColin Finck return PLATFORM_UNKNOWN; 1213c2c66affSColin Finck } 1214c2c66affSColin Finck 1215c2c66affSColin Finck static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) 1216c2c66affSColin Finck { 1217c2c66affSColin Finck WCHAR *template, *p, *q, *platform; 1218c2c66affSColin Finck DWORD i, count; 1219c2c66affSColin Finck 1220c2c66affSColin Finck package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); 1221c2c66affSColin Finck TRACE("version: %d\n", package->version); 1222c2c66affSColin Finck 1223c2c66affSColin Finck template = msi_suminfo_dup_string( si, PID_TEMPLATE ); 1224c2c66affSColin Finck if (!template) 1225c2c66affSColin Finck return ERROR_SUCCESS; /* native accepts missing template property */ 1226c2c66affSColin Finck 1227c2c66affSColin Finck TRACE("template: %s\n", debugstr_w(template)); 1228c2c66affSColin Finck 1229c2c66affSColin Finck p = strchrW( template, ';' ); 1230c2c66affSColin Finck if (!p) 1231c2c66affSColin Finck { 1232c2c66affSColin Finck WARN("invalid template string %s\n", debugstr_w(template)); 1233c2c66affSColin Finck msi_free( template ); 1234c2c66affSColin Finck return ERROR_PATCH_PACKAGE_INVALID; 1235c2c66affSColin Finck } 1236c2c66affSColin Finck *p = 0; 1237c2c66affSColin Finck platform = template; 1238c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1239c2c66affSColin Finck package->platform = parse_platform( platform ); 1240c2c66affSColin Finck while (package->platform == PLATFORM_UNKNOWN && q) 1241c2c66affSColin Finck { 1242c2c66affSColin Finck platform = q + 1; 1243c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1244c2c66affSColin Finck package->platform = parse_platform( platform ); 1245c2c66affSColin Finck } 1246c2c66affSColin Finck if (package->platform == PLATFORM_UNKNOWN) 1247c2c66affSColin Finck { 1248c2c66affSColin Finck WARN("unknown platform %s\n", debugstr_w(template)); 1249c2c66affSColin Finck msi_free( template ); 1250c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1251c2c66affSColin Finck } 1252c2c66affSColin Finck p++; 1253c2c66affSColin Finck if (!*p) 1254c2c66affSColin Finck { 1255c2c66affSColin Finck msi_free( template ); 1256c2c66affSColin Finck return ERROR_SUCCESS; 1257c2c66affSColin Finck } 1258c2c66affSColin Finck count = 1; 1259c2c66affSColin Finck for (q = p; (q = strchrW( q, ',' )); q++) count++; 1260c2c66affSColin Finck 1261c2c66affSColin Finck package->langids = msi_alloc( count * sizeof(LANGID) ); 1262c2c66affSColin Finck if (!package->langids) 1263c2c66affSColin Finck { 1264c2c66affSColin Finck msi_free( template ); 1265c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1266c2c66affSColin Finck } 1267c2c66affSColin Finck 1268c2c66affSColin Finck i = 0; 1269c2c66affSColin Finck while (*p) 1270c2c66affSColin Finck { 1271c2c66affSColin Finck q = strchrW( p, ',' ); 1272c2c66affSColin Finck if (q) *q = 0; 1273c2c66affSColin Finck package->langids[i] = atoiW( p ); 1274c2c66affSColin Finck if (!q) break; 1275c2c66affSColin Finck p = q + 1; 1276c2c66affSColin Finck i++; 1277c2c66affSColin Finck } 1278c2c66affSColin Finck package->num_langids = i + 1; 1279c2c66affSColin Finck 1280c2c66affSColin Finck msi_free( template ); 1281c2c66affSColin Finck return ERROR_SUCCESS; 1282c2c66affSColin Finck } 1283c2c66affSColin Finck 1284c2c66affSColin Finck static UINT validate_package( MSIPACKAGE *package ) 1285c2c66affSColin Finck { 1286c2c66affSColin Finck UINT i; 1287c2c66affSColin Finck 1288c2c66affSColin Finck if (package->platform == PLATFORM_INTEL64) 1289c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1290c2c66affSColin Finck #ifndef __arm__ 1291c2c66affSColin Finck if (package->platform == PLATFORM_ARM) 1292c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1293c2c66affSColin Finck #endif 1294de59794fSwinesync #ifndef __aarch64__ 1295de59794fSwinesync if (package->platform == PLATFORM_ARM64) 1296de59794fSwinesync return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1297de59794fSwinesync #endif 1298c2c66affSColin Finck if (package->platform == PLATFORM_X64) 1299c2c66affSColin Finck { 1300c2c66affSColin Finck if (!is_64bit && !is_wow64) 1301c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1302c2c66affSColin Finck if (package->version < 200) 1303c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1304c2c66affSColin Finck } 1305c2c66affSColin Finck if (!package->num_langids) 1306c2c66affSColin Finck { 1307c2c66affSColin Finck return ERROR_SUCCESS; 1308c2c66affSColin Finck } 1309c2c66affSColin Finck for (i = 0; i < package->num_langids; i++) 1310c2c66affSColin Finck { 1311c2c66affSColin Finck LANGID langid = package->langids[i]; 1312c2c66affSColin Finck 1313c2c66affSColin Finck if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) 1314c2c66affSColin Finck { 1315c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); 1316c2c66affSColin Finck } 1317c2c66affSColin Finck if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) 1318c2c66affSColin Finck { 1319c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); 1320c2c66affSColin Finck } 1321c2c66affSColin Finck if (IsValidLocale( langid, LCID_INSTALLED )) 1322c2c66affSColin Finck return ERROR_SUCCESS; 1323c2c66affSColin Finck } 1324c2c66affSColin Finck return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; 1325c2c66affSColin Finck } 1326c2c66affSColin Finck 1327b7b9c0c4Swinesync static WCHAR *get_property( MSIDATABASE *db, const WCHAR *prop ) 1328c2c66affSColin Finck { 1329b7b9c0c4Swinesync static const WCHAR select_query[] = { 1330c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 1331c2c66affSColin Finck 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ', 1332c2c66affSColin Finck 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=', 1333b7b9c0c4Swinesync '\'','%','s','\'',0}; 1334b7b9c0c4Swinesync WCHAR query[MAX_PATH]; 1335c2c66affSColin Finck MSIQUERY *view; 1336c2c66affSColin Finck MSIRECORD *rec; 1337c2c66affSColin Finck WCHAR *ret = NULL; 1338c2c66affSColin Finck 1339b7b9c0c4Swinesync sprintfW(query, select_query, prop); 1340c2c66affSColin Finck if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) 1341c2c66affSColin Finck { 1342c2c66affSColin Finck return NULL; 1343c2c66affSColin Finck } 1344c2c66affSColin Finck if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) 1345c2c66affSColin Finck { 1346c2c66affSColin Finck MSI_ViewClose( view ); 1347c2c66affSColin Finck msiobj_release( &view->hdr ); 1348c2c66affSColin Finck return NULL; 1349c2c66affSColin Finck } 1350c2c66affSColin Finck if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) 1351c2c66affSColin Finck { 1352c2c66affSColin Finck ret = strdupW( MSI_RecordGetString( rec, 1 ) ); 1353c2c66affSColin Finck msiobj_release( &rec->hdr ); 1354c2c66affSColin Finck } 1355c2c66affSColin Finck MSI_ViewClose( view ); 1356c2c66affSColin Finck msiobj_release( &view->hdr ); 1357c2c66affSColin Finck return ret; 1358c2c66affSColin Finck } 1359c2c66affSColin Finck 1360b7b9c0c4Swinesync static WCHAR *get_product_code( MSIDATABASE *db ) 1361b7b9c0c4Swinesync { 1362b7b9c0c4Swinesync return get_property( db, szProductCode ); 1363b7b9c0c4Swinesync } 1364b7b9c0c4Swinesync 1365b7b9c0c4Swinesync static WCHAR *get_product_version( MSIDATABASE *db ) 1366b7b9c0c4Swinesync { 1367b7b9c0c4Swinesync return get_property( db, szProductVersion ); 1368b7b9c0c4Swinesync } 1369b7b9c0c4Swinesync 1370b7b9c0c4Swinesync static UINT get_registered_local_package( const WCHAR *product, WCHAR *localfile ) 1371c2c66affSColin Finck { 1372c2c66affSColin Finck MSIINSTALLCONTEXT context; 1373b7b9c0c4Swinesync WCHAR *filename; 1374b7b9c0c4Swinesync HKEY props_key; 1375c2c66affSColin Finck UINT r; 1376c2c66affSColin Finck 1377c2c66affSColin Finck r = msi_locate_product( product, &context ); 1378c2c66affSColin Finck if (r != ERROR_SUCCESS) 1379c2c66affSColin Finck return r; 1380c2c66affSColin Finck 1381c2c66affSColin Finck r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); 1382c2c66affSColin Finck if (r != ERROR_SUCCESS) 1383c2c66affSColin Finck return r; 1384c2c66affSColin Finck 1385b7b9c0c4Swinesync filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); 1386b7b9c0c4Swinesync RegCloseKey( props_key ); 1387c2c66affSColin Finck if (!filename) 1388b7b9c0c4Swinesync return ERROR_FUNCTION_FAILED; 1389c2c66affSColin Finck 1390c2c66affSColin Finck strcpyW( localfile, filename ); 1391c2c66affSColin Finck msi_free( filename ); 1392b7b9c0c4Swinesync return ERROR_SUCCESS; 1393c2c66affSColin Finck } 1394c2c66affSColin Finck 139574196b80Swinesync WCHAR *msi_get_package_code( MSIDATABASE *db ) 1396c2c66affSColin Finck { 1397c2c66affSColin Finck WCHAR *ret; 1398c2c66affSColin Finck MSISUMMARYINFO *si; 1399c2c66affSColin Finck UINT r; 1400c2c66affSColin Finck 1401c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1402c2c66affSColin Finck if (r != ERROR_SUCCESS) 1403c2c66affSColin Finck { 1404c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1405c2c66affSColin Finck if (r != ERROR_SUCCESS) 1406c2c66affSColin Finck { 1407c2c66affSColin Finck WARN("failed to load summary info %u\n", r); 1408c2c66affSColin Finck return NULL; 1409c2c66affSColin Finck } 1410c2c66affSColin Finck } 1411c2c66affSColin Finck ret = msi_suminfo_dup_string( si, PID_REVNUMBER ); 1412c2c66affSColin Finck msiobj_release( &si->hdr ); 1413c2c66affSColin Finck return ret; 1414c2c66affSColin Finck } 1415c2c66affSColin Finck 1416b7b9c0c4Swinesync static UINT get_local_package( MSIDATABASE *db, WCHAR *localfile ) 1417c2c66affSColin Finck { 1418b7b9c0c4Swinesync WCHAR *product_code; 1419c2c66affSColin Finck UINT r; 1420c2c66affSColin Finck 1421c2c66affSColin Finck if (!(product_code = get_product_code( db ))) 1422c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1423b7b9c0c4Swinesync r = get_registered_local_package( product_code, localfile ); 1424c2c66affSColin Finck msi_free( product_code ); 1425c2c66affSColin Finck return r; 1426c2c66affSColin Finck } 1427c2c66affSColin Finck 1428c2c66affSColin Finck UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) 1429c2c66affSColin Finck { 1430c2c66affSColin Finck UINT r; 1431c2c66affSColin Finck 1432c2c66affSColin Finck if (UrlIsW( package, URLIS_URL )) 1433c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, package, -1 ); 1434c2c66affSColin Finck else if (package[0] == '#') 1435c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, db->path, -1 ); 1436c2c66affSColin Finck else 1437c2c66affSColin Finck { 1438c2c66affSColin Finck DWORD len; 1439c2c66affSColin Finck WCHAR *path; 1440c2c66affSColin Finck 1441c2c66affSColin Finck if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); 1442c2c66affSColin Finck if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; 1443c2c66affSColin Finck len = GetFullPathNameW( package, len, path, NULL ); 1444c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, path, len ); 1445c2c66affSColin Finck msi_free( path ); 1446c2c66affSColin Finck } 1447c2c66affSColin Finck return r; 1448c2c66affSColin Finck } 1449c2c66affSColin Finck 1450a2371385Swinesync UINT MSI_OpenPackageW(LPCWSTR szPackage, DWORD dwOptions, MSIPACKAGE **pPackage) 1451c2c66affSColin Finck { 1452c2c66affSColin Finck static const WCHAR dotmsi[] = {'.','m','s','i',0}; 1453c2c66affSColin Finck MSIDATABASE *db; 1454c2c66affSColin Finck MSIPACKAGE *package; 1455c2c66affSColin Finck MSIHANDLE handle; 145671bffdcdSAmine Khaldi MSIRECORD *data_row, *info_row; 1457c2c66affSColin Finck UINT r; 1458c2c66affSColin Finck WCHAR localfile[MAX_PATH], cachefile[MAX_PATH]; 1459c2c66affSColin Finck LPCWSTR file = szPackage; 1460c2c66affSColin Finck DWORD index = 0; 1461c2c66affSColin Finck MSISUMMARYINFO *si; 1462c2c66affSColin Finck BOOL delete_on_close = FALSE; 1463da848361Swinesync WCHAR *info_template, *productname, *product_code; 1464da848361Swinesync MSIINSTALLCONTEXT context; 1465c2c66affSColin Finck 1466c2c66affSColin Finck TRACE("%s %p\n", debugstr_w(szPackage), pPackage); 1467c2c66affSColin Finck 146871bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0); 146971bffdcdSAmine Khaldi 1470c2c66affSColin Finck localfile[0] = 0; 1471c2c66affSColin Finck if( szPackage[0] == '#' ) 1472c2c66affSColin Finck { 1473c2c66affSColin Finck handle = atoiW(&szPackage[1]); 1474c2c66affSColin Finck db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); 1475c2c66affSColin Finck if( !db ) 1476c2c66affSColin Finck { 1477b74b77aaSwinesync MSIHANDLE remote; 1478c2c66affSColin Finck 1479b74b77aaSwinesync if (!(remote = msi_get_remote(handle))) 1480c2c66affSColin Finck return ERROR_INVALID_HANDLE; 1481c2c66affSColin Finck 1482c2c66affSColin Finck WARN("MsiOpenPackage not allowed during a custom action!\n"); 1483c2c66affSColin Finck 1484c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1485c2c66affSColin Finck } 1486c2c66affSColin Finck } 1487c2c66affSColin Finck else 1488c2c66affSColin Finck { 1489b7b9c0c4Swinesync WCHAR *product_version = NULL; 1490b7b9c0c4Swinesync 1491c2c66affSColin Finck if ( UrlIsW( szPackage, URLIS_URL ) ) 1492c2c66affSColin Finck { 1493c2c66affSColin Finck r = msi_download_file( szPackage, cachefile ); 1494c2c66affSColin Finck if (r != ERROR_SUCCESS) 1495c2c66affSColin Finck return r; 1496c2c66affSColin Finck 1497c2c66affSColin Finck file = cachefile; 1498c2c66affSColin Finck } 1499b7b9c0c4Swinesync r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db ); 1500b7b9c0c4Swinesync if (r != ERROR_SUCCESS) 1501b7b9c0c4Swinesync { 1502b7b9c0c4Swinesync if (GetFileAttributesW( file ) == INVALID_FILE_ATTRIBUTES) 1503b7b9c0c4Swinesync return ERROR_FILE_NOT_FOUND; 1504b7b9c0c4Swinesync return r; 1505b7b9c0c4Swinesync } 1506b7b9c0c4Swinesync r = get_local_package( db, localfile ); 1507c2c66affSColin Finck if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) 1508c2c66affSColin Finck { 150963bb43adSJérôme Gardou DWORD localfile_attr; 151063bb43adSJérôme Gardou 1511c2c66affSColin Finck r = msi_create_empty_local_file( localfile, dotmsi ); 1512c2c66affSColin Finck if (r != ERROR_SUCCESS) 1513b7b9c0c4Swinesync { 1514b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1515c2c66affSColin Finck return r; 1516b7b9c0c4Swinesync } 1517c2c66affSColin Finck 1518c2c66affSColin Finck if (!CopyFileW( file, localfile, FALSE )) 1519c2c66affSColin Finck { 1520c2c66affSColin Finck r = GetLastError(); 1521c2c66affSColin Finck WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1522c2c66affSColin Finck DeleteFileW( localfile ); 1523b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1524c2c66affSColin Finck return r; 1525c2c66affSColin Finck } 1526c2c66affSColin Finck delete_on_close = TRUE; 152763bb43adSJérôme Gardou 152863bb43adSJérôme Gardou /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */ 152963bb43adSJérôme Gardou localfile_attr = GetFileAttributesW( localfile ); 153063bb43adSJérôme Gardou if (localfile_attr & FILE_ATTRIBUTE_READONLY) 153163bb43adSJérôme Gardou SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY); 1532c2c66affSColin Finck } 1533a2371385Swinesync else if (dwOptions & WINE_OPENPACKAGEFLAGS_RECACHE) 1534a2371385Swinesync { 1535a2371385Swinesync if (!CopyFileW( file, localfile, FALSE )) 1536a2371385Swinesync { 1537a2371385Swinesync r = GetLastError(); 1538a2371385Swinesync WARN("unable to update cached package (%u)\n", r); 1539a2371385Swinesync msiobj_release( &db->hdr ); 1540a2371385Swinesync return r; 1541a2371385Swinesync } 1542a2371385Swinesync } 1543b7b9c0c4Swinesync else 1544b7b9c0c4Swinesync product_version = get_product_version( db ); 1545b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1546c2c66affSColin Finck TRACE("opening package %s\n", debugstr_w( localfile )); 1547c2c66affSColin Finck r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1548c2c66affSColin Finck if (r != ERROR_SUCCESS) 1549c2c66affSColin Finck return r; 1550b7b9c0c4Swinesync 1551b7b9c0c4Swinesync if (product_version) 1552b7b9c0c4Swinesync { 1553b7b9c0c4Swinesync WCHAR *cache_version = get_product_version( db ); 1554b7b9c0c4Swinesync if (!product_version != !cache_version || 1555b7b9c0c4Swinesync (product_version && strcmpW(product_version, cache_version))) 1556b7b9c0c4Swinesync { 1557b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1558b7b9c0c4Swinesync msi_free(product_version); 1559b7b9c0c4Swinesync msi_free(cache_version); 1560b7b9c0c4Swinesync return ERROR_PRODUCT_VERSION; 1561b7b9c0c4Swinesync } 1562b7b9c0c4Swinesync msi_free(product_version); 1563b7b9c0c4Swinesync msi_free(cache_version); 1564b7b9c0c4Swinesync } 1565c2c66affSColin Finck } 156634c2011cSwinesync package = MSI_CreatePackage( db ); 1567c2c66affSColin Finck msiobj_release( &db->hdr ); 1568c2c66affSColin Finck if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1569c2c66affSColin Finck package->localfile = strdupW( localfile ); 1570c2c66affSColin Finck package->delete_on_close = delete_on_close; 1571c2c66affSColin Finck 1572c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1573c2c66affSColin Finck if (r != ERROR_SUCCESS) 1574c2c66affSColin Finck { 1575c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1576c2c66affSColin Finck if (r != ERROR_SUCCESS) 1577c2c66affSColin Finck { 1578c2c66affSColin Finck WARN("failed to load summary info\n"); 1579c2c66affSColin Finck msiobj_release( &package->hdr ); 1580c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1581c2c66affSColin Finck } 1582c2c66affSColin Finck } 1583c2c66affSColin Finck r = parse_suminfo( si, package ); 1584c2c66affSColin Finck msiobj_release( &si->hdr ); 1585c2c66affSColin Finck if (r != ERROR_SUCCESS) 1586c2c66affSColin Finck { 1587c2c66affSColin Finck WARN("failed to parse summary info %u\n", r); 1588c2c66affSColin Finck msiobj_release( &package->hdr ); 1589c2c66affSColin Finck return r; 1590c2c66affSColin Finck } 1591c2c66affSColin Finck r = validate_package( package ); 1592c2c66affSColin Finck if (r != ERROR_SUCCESS) 1593c2c66affSColin Finck { 1594c2c66affSColin Finck msiobj_release( &package->hdr ); 1595c2c66affSColin Finck return r; 1596c2c66affSColin Finck } 1597c2c66affSColin Finck msi_set_property( package->db, szDatabase, db->path, -1 ); 1598c2c66affSColin Finck set_installed_prop( package ); 1599c2c66affSColin Finck msi_set_context( package ); 1600c2c66affSColin Finck 1601da848361Swinesync product_code = get_product_code( db ); 1602da848361Swinesync if (msi_locate_product( product_code, &context ) == ERROR_SUCCESS) 1603da848361Swinesync { 1604da848361Swinesync TRACE("product already registered\n"); 1605da848361Swinesync msi_set_property( package->db, szProductToBeRegistered, szOne, -1 ); 1606da848361Swinesync } 1607da848361Swinesync msi_free(product_code); 1608da848361Swinesync 1609c2c66affSColin Finck while (1) 1610c2c66affSColin Finck { 1611c2c66affSColin Finck WCHAR patch_code[GUID_SIZE]; 1612c2c66affSColin Finck r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1613c2c66affSColin Finck MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1614c2c66affSColin Finck if (r != ERROR_SUCCESS) 1615c2c66affSColin Finck break; 1616c2c66affSColin Finck 1617c2c66affSColin Finck TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1618c2c66affSColin Finck 1619c2c66affSColin Finck r = msi_apply_registered_patch( package, patch_code ); 1620c2c66affSColin Finck if (r != ERROR_SUCCESS) 1621c2c66affSColin Finck { 1622c2c66affSColin Finck ERR("registered patch failed to apply %u\n", r); 1623c2c66affSColin Finck msiobj_release( &package->hdr ); 1624c2c66affSColin Finck return r; 1625c2c66affSColin Finck } 1626c2c66affSColin Finck index++; 1627c2c66affSColin Finck } 1628c2c66affSColin Finck if (index) msi_adjust_privilege_properties( package ); 1629c2c66affSColin Finck 1630c2c66affSColin Finck r = msi_set_original_database_property( package->db, szPackage ); 1631c2c66affSColin Finck if (r != ERROR_SUCCESS) 1632c2c66affSColin Finck { 1633c2c66affSColin Finck msiobj_release( &package->hdr ); 1634c2c66affSColin Finck return r; 1635c2c66affSColin Finck } 1636c2c66affSColin Finck if (gszLogFile) 1637c2c66affSColin Finck package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1638c2c66affSColin Finck OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 163971bffdcdSAmine Khaldi 1640*e342f337Swinesync if (!msi_init_assembly_caches( package )) 1641*e342f337Swinesync { 1642*e342f337Swinesync ERR("can't initialize assembly caches\n"); 1643*e342f337Swinesync msiobj_release( &package->hdr ); 1644*e342f337Swinesync return ERROR_FUNCTION_FAILED; 1645*e342f337Swinesync } 1646*e342f337Swinesync 164771bffdcdSAmine Khaldi /* FIXME: when should these messages be sent? */ 164871bffdcdSAmine Khaldi data_row = MSI_CreateRecord(3); 164971bffdcdSAmine Khaldi if (!data_row) 165071bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 165171bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 0, NULL); 165271bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 0); 165371bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0); 165471bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings)); 165571bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row); 165671bffdcdSAmine Khaldi 165771bffdcdSAmine Khaldi info_row = MSI_CreateRecord(0); 165871bffdcdSAmine Khaldi if (!info_row) 165971bffdcdSAmine Khaldi { 166071bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 166171bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 166271bffdcdSAmine Khaldi } 166371bffdcdSAmine Khaldi info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART); 166471bffdcdSAmine Khaldi MSI_RecordSetStringW(info_row, 0, info_template); 166571bffdcdSAmine Khaldi msi_free(info_template); 166671bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row); 166771bffdcdSAmine Khaldi 166871bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 166971bffdcdSAmine Khaldi 167071bffdcdSAmine Khaldi productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW); 167171bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 1); 167271bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 2, productname); 167371bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 3, NULL); 167471bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 167571bffdcdSAmine Khaldi 167671bffdcdSAmine Khaldi msi_free(productname); 167771bffdcdSAmine Khaldi msiobj_release(&info_row->hdr); 167871bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 167971bffdcdSAmine Khaldi 1680c2c66affSColin Finck *pPackage = package; 1681c2c66affSColin Finck return ERROR_SUCCESS; 1682c2c66affSColin Finck } 1683c2c66affSColin Finck 1684c2c66affSColin Finck UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1685c2c66affSColin Finck { 1686c2c66affSColin Finck MSIPACKAGE *package = NULL; 1687c2c66affSColin Finck UINT ret; 1688c2c66affSColin Finck 1689c2c66affSColin Finck TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1690c2c66affSColin Finck 1691c2c66affSColin Finck if( !szPackage || !phPackage ) 1692c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 1693c2c66affSColin Finck 1694c2c66affSColin Finck if ( !*szPackage ) 1695c2c66affSColin Finck { 1696c2c66affSColin Finck FIXME("Should create an empty database and package\n"); 1697c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1698c2c66affSColin Finck } 1699c2c66affSColin Finck 1700c2c66affSColin Finck if( dwOptions ) 1701c2c66affSColin Finck FIXME("dwOptions %08x not supported\n", dwOptions); 1702c2c66affSColin Finck 1703a2371385Swinesync ret = MSI_OpenPackageW( szPackage, 0, &package ); 1704c2c66affSColin Finck if( ret == ERROR_SUCCESS ) 1705c2c66affSColin Finck { 1706c2c66affSColin Finck *phPackage = alloc_msihandle( &package->hdr ); 1707c2c66affSColin Finck if (! *phPackage) 1708c2c66affSColin Finck ret = ERROR_NOT_ENOUGH_MEMORY; 1709c2c66affSColin Finck msiobj_release( &package->hdr ); 1710c2c66affSColin Finck } 171171bffdcdSAmine Khaldi else 171271bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 1713c2c66affSColin Finck 1714c2c66affSColin Finck return ret; 1715c2c66affSColin Finck } 1716c2c66affSColin Finck 1717c2c66affSColin Finck UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1718c2c66affSColin Finck { 1719c2c66affSColin Finck return MsiOpenPackageExW( szPackage, 0, phPackage ); 1720c2c66affSColin Finck } 1721c2c66affSColin Finck 1722c2c66affSColin Finck UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1723c2c66affSColin Finck { 1724c2c66affSColin Finck LPWSTR szwPack = NULL; 1725c2c66affSColin Finck UINT ret; 1726c2c66affSColin Finck 1727c2c66affSColin Finck if( szPackage ) 1728c2c66affSColin Finck { 1729c2c66affSColin Finck szwPack = strdupAtoW( szPackage ); 1730c2c66affSColin Finck if( !szwPack ) 1731c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1732c2c66affSColin Finck } 1733c2c66affSColin Finck 1734c2c66affSColin Finck ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1735c2c66affSColin Finck 1736c2c66affSColin Finck msi_free( szwPack ); 1737c2c66affSColin Finck 1738c2c66affSColin Finck return ret; 1739c2c66affSColin Finck } 1740c2c66affSColin Finck 1741c2c66affSColin Finck UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1742c2c66affSColin Finck { 1743c2c66affSColin Finck return MsiOpenPackageExA( szPackage, 0, phPackage ); 1744c2c66affSColin Finck } 1745c2c66affSColin Finck 1746c2c66affSColin Finck MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) 1747c2c66affSColin Finck { 1748c2c66affSColin Finck MSIPACKAGE *package; 1749c2c66affSColin Finck MSIHANDLE handle = 0; 1750b74b77aaSwinesync MSIHANDLE remote; 1751c2c66affSColin Finck 1752c2c66affSColin Finck TRACE("(%d)\n",hInstall); 1753c2c66affSColin Finck 1754c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1755c2c66affSColin Finck if( package) 1756c2c66affSColin Finck { 1757c2c66affSColin Finck handle = alloc_msihandle( &package->db->hdr ); 1758c2c66affSColin Finck msiobj_release( &package->hdr ); 1759c2c66affSColin Finck } 1760b74b77aaSwinesync else if ((remote = msi_get_remote(hInstall))) 1761c2c66affSColin Finck { 17622a9ae858Swinesync __TRY 17632a9ae858Swinesync { 1764bf1ca658Swinesync handle = remote_GetActiveDatabase(remote); 17657cc54a4fSwinesync handle = alloc_msi_remote_handle(handle); 1766c2c66affSColin Finck } 17672a9ae858Swinesync __EXCEPT(rpc_filter) 17682a9ae858Swinesync { 17692a9ae858Swinesync handle = 0; 17702a9ae858Swinesync } 17712a9ae858Swinesync __ENDTRY 17722a9ae858Swinesync } 1773c2c66affSColin Finck 1774c2c66affSColin Finck return handle; 1775c2c66affSColin Finck } 1776c2c66affSColin Finck 177771bffdcdSAmine Khaldi static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message) 1778c2c66affSColin Finck { 1779c2c66affSColin Finck static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0}; 1780c2c66affSColin Finck static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0}; 178171bffdcdSAmine Khaldi static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0}; 178271bffdcdSAmine Khaldi static const WCHAR szWindows_Installer[] = 178371bffdcdSAmine Khaldi {'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0}; 178471bffdcdSAmine Khaldi 178571bffdcdSAmine Khaldi if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) 178671bffdcdSAmine Khaldi return 0; 178771bffdcdSAmine Khaldi 178871bffdcdSAmine Khaldi /* todo: check if message needs additional styles (topmost/foreground/modality?) */ 178971bffdcdSAmine Khaldi 179071bffdcdSAmine Khaldi switch (eMessageType & 0xff000000) 179171bffdcdSAmine Khaldi { 179271bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 179371bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 179471bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 179571bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 179671bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 179771bffdcdSAmine Khaldi eMessageType |= MB_ICONEXCLAMATION; 179871bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 179971bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 180071bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 180171bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 180271bffdcdSAmine Khaldi eMessageType |= MB_ICONASTERISK; 180371bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 180471bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 180571bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 180671bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 180771bffdcdSAmine Khaldi eMessageType |= MB_USERICON; 180871bffdcdSAmine Khaldi return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 180971bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 181071bffdcdSAmine Khaldi case INSTALLMESSAGE_INITIALIZE: 181171bffdcdSAmine Khaldi case INSTALLMESSAGE_TERMINATE: 1812f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLSTART: 1813f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLEND: 181471bffdcdSAmine Khaldi return 0; 181571bffdcdSAmine Khaldi case INSTALLMESSAGE_SHOWDIALOG: 181671bffdcdSAmine Khaldi { 181771bffdcdSAmine Khaldi LPWSTR dialog = msi_dup_record_field(record, 0); 181871bffdcdSAmine Khaldi INT rc = ACTION_DialogBox(package, dialog); 181971bffdcdSAmine Khaldi msi_free(dialog); 182071bffdcdSAmine Khaldi return rc; 182171bffdcdSAmine Khaldi } 182271bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONSTART: 182371bffdcdSAmine Khaldi { 182471bffdcdSAmine Khaldi LPWSTR deformatted; 182571bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 182671bffdcdSAmine Khaldi if (!uirow) return -1; 182771bffdcdSAmine Khaldi deformat_string(package, MSI_RecordGetString(record, 2), &deformatted); 182871bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, deformatted); 182971bffdcdSAmine Khaldi msi_event_fire(package, szActionText, uirow); 183071bffdcdSAmine Khaldi 183171bffdcdSAmine Khaldi msi_free(deformatted); 183271bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 183371bffdcdSAmine Khaldi return 1; 183471bffdcdSAmine Khaldi } 183571bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 183671bffdcdSAmine Khaldi { 183771bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 183871bffdcdSAmine Khaldi if (!uirow) return -1; 183971bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, message); 184071bffdcdSAmine Khaldi msi_event_fire(package, szActionData, uirow); 184171bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 184271bffdcdSAmine Khaldi 184371bffdcdSAmine Khaldi if (package->action_progress_increment) 184471bffdcdSAmine Khaldi { 184571bffdcdSAmine Khaldi uirow = MSI_CreateRecord(2); 184671bffdcdSAmine Khaldi if (!uirow) return -1; 184771bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 1, 2); 184871bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 184971bffdcdSAmine Khaldi msi_event_fire(package, szSetProgress, uirow); 185071bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 185171bffdcdSAmine Khaldi } 185271bffdcdSAmine Khaldi return 1; 185371bffdcdSAmine Khaldi } 185471bffdcdSAmine Khaldi case INSTALLMESSAGE_PROGRESS: 185571bffdcdSAmine Khaldi msi_event_fire(package, szSetProgress, record); 185671bffdcdSAmine Khaldi return 1; 185771bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 185871bffdcdSAmine Khaldi switch (MSI_RecordGetInteger(record, 1)) 185971bffdcdSAmine Khaldi { 186071bffdcdSAmine Khaldi case 0: 186171bffdcdSAmine Khaldi case 1: 186271bffdcdSAmine Khaldi /* do nothing */ 186371bffdcdSAmine Khaldi return 0; 186471bffdcdSAmine Khaldi default: 186571bffdcdSAmine Khaldi /* fall through */ 186671bffdcdSAmine Khaldi ; 186771bffdcdSAmine Khaldi } 186871bffdcdSAmine Khaldi default: 186971bffdcdSAmine Khaldi FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level); 187071bffdcdSAmine Khaldi return 0; 187171bffdcdSAmine Khaldi } 187271bffdcdSAmine Khaldi } 187371bffdcdSAmine Khaldi 187471bffdcdSAmine 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}; 187571bffdcdSAmine Khaldi 187671bffdcdSAmine Khaldi static const struct 187771bffdcdSAmine Khaldi { 187871bffdcdSAmine Khaldi int id; 187971bffdcdSAmine Khaldi const WCHAR *text; 188071bffdcdSAmine Khaldi } 188171bffdcdSAmine Khaldi internal_errors[] = 188271bffdcdSAmine Khaldi { 188371bffdcdSAmine Khaldi {2726, szActionNotFound}, 188471bffdcdSAmine Khaldi {0} 188571bffdcdSAmine Khaldi }; 188671bffdcdSAmine Khaldi 188771bffdcdSAmine Khaldi static LPCWSTR get_internal_error_message(int error) 188871bffdcdSAmine Khaldi { 188971bffdcdSAmine Khaldi int i = 0; 189071bffdcdSAmine Khaldi 189171bffdcdSAmine Khaldi while (internal_errors[i].id != 0) 189271bffdcdSAmine Khaldi { 189371bffdcdSAmine Khaldi if (internal_errors[i].id == error) 189471bffdcdSAmine Khaldi return internal_errors[i].text; 189571bffdcdSAmine Khaldi i++; 189671bffdcdSAmine Khaldi } 189771bffdcdSAmine Khaldi 189871bffdcdSAmine Khaldi FIXME("missing error message %d\n", error); 189971bffdcdSAmine Khaldi return NULL; 190071bffdcdSAmine Khaldi } 190171bffdcdSAmine Khaldi 190271bffdcdSAmine Khaldi /* Returned string must be freed */ 190371bffdcdSAmine Khaldi LPWSTR msi_get_error_message(MSIDATABASE *db, int error) 190471bffdcdSAmine Khaldi { 190571bffdcdSAmine Khaldi static const WCHAR query[] = 190671bffdcdSAmine Khaldi {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ', 190771bffdcdSAmine Khaldi 'F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ', 190871bffdcdSAmine Khaldi '`','E','r','r','o','r','`',' ','=',' ','%','i',0}; 190971bffdcdSAmine Khaldi MSIRECORD *record; 191071bffdcdSAmine Khaldi LPWSTR ret = NULL; 191171bffdcdSAmine Khaldi 191271bffdcdSAmine Khaldi if ((record = MSI_QueryGetRecord(db, query, error))) 191371bffdcdSAmine Khaldi { 191471bffdcdSAmine Khaldi ret = msi_dup_record_field(record, 1); 191571bffdcdSAmine Khaldi msiobj_release(&record->hdr); 191671bffdcdSAmine Khaldi } 191771bffdcdSAmine Khaldi else if (error < 2000) 191871bffdcdSAmine Khaldi { 191971bffdcdSAmine Khaldi int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0); 192071bffdcdSAmine Khaldi if (len) 192171bffdcdSAmine Khaldi { 192271bffdcdSAmine Khaldi ret = msi_alloc((len + 1) * sizeof(WCHAR)); 192371bffdcdSAmine Khaldi LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1); 192471bffdcdSAmine Khaldi } 192571bffdcdSAmine Khaldi else 192671bffdcdSAmine Khaldi ret = NULL; 192771bffdcdSAmine Khaldi } 192871bffdcdSAmine Khaldi 192971bffdcdSAmine Khaldi return ret; 193071bffdcdSAmine Khaldi } 193171bffdcdSAmine Khaldi 193271bffdcdSAmine Khaldi INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record) 193371bffdcdSAmine Khaldi { 193471bffdcdSAmine Khaldi LPWSTR message = {0}; 1935f8b992f2SAmine Khaldi DWORD len; 1936f8b992f2SAmine Khaldi DWORD log_type = 1 << (eMessageType >> 24); 193771bffdcdSAmine Khaldi UINT res; 1938c2c66affSColin Finck INT rc = 0; 1939c2c66affSColin Finck char *msg; 1940c2c66affSColin Finck 1941c2c66affSColin Finck TRACE("%x\n", eMessageType); 194271bffdcdSAmine Khaldi if (TRACE_ON(msi)) dump_record(record); 1943c2c66affSColin Finck 194471bffdcdSAmine Khaldi if (!package || !record) 194571bffdcdSAmine Khaldi message = NULL; 194671bffdcdSAmine Khaldi else { 194771bffdcdSAmine Khaldi res = MSI_FormatRecordW(package, record, message, &len); 194871bffdcdSAmine Khaldi if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 194971bffdcdSAmine Khaldi return res; 195071bffdcdSAmine Khaldi len++; 1951c2c66affSColin Finck message = msi_alloc(len * sizeof(WCHAR)); 195271bffdcdSAmine Khaldi if (!message) return ERROR_OUTOFMEMORY; 195371bffdcdSAmine Khaldi MSI_FormatRecordW(package, record, message, &len); 1954c2c66affSColin Finck } 1955c2c66affSColin Finck 1956c2c66affSColin Finck /* convert it to ASCII */ 1957c2c66affSColin Finck len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1958c2c66affSColin Finck msg = msi_alloc( len ); 1959c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1960c2c66affSColin Finck 196171bffdcdSAmine Khaldi if (gUIHandlerRecord && (gUIFilterRecord & log_type)) 1962c2c66affSColin Finck { 196371bffdcdSAmine Khaldi MSIHANDLE rec = alloc_msihandle(&record->hdr); 196471bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n", 196571bffdcdSAmine Khaldi gUIHandlerRecord, gUIContextRecord, eMessageType, rec); 196671bffdcdSAmine Khaldi rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec ); 1967c2c66affSColin Finck MsiCloseHandle( rec ); 1968c2c66affSColin Finck } 196971bffdcdSAmine Khaldi if (!rc && gUIHandlerW && (gUIFilter & log_type)) 197071bffdcdSAmine Khaldi { 197171bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 197271bffdcdSAmine Khaldi gUIHandlerW, gUIContext, eMessageType, debugstr_w(message)); 197371bffdcdSAmine Khaldi rc = gUIHandlerW( gUIContext, eMessageType, message ); 197471bffdcdSAmine Khaldi } 197571bffdcdSAmine Khaldi else if (!rc && gUIHandlerA && (gUIFilter & log_type)) 197671bffdcdSAmine Khaldi { 197771bffdcdSAmine Khaldi TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 197871bffdcdSAmine Khaldi gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg)); 197971bffdcdSAmine Khaldi rc = gUIHandlerA( gUIContext, eMessageType, msg ); 198071bffdcdSAmine Khaldi } 1981c2c66affSColin Finck 198271bffdcdSAmine Khaldi if (!rc) 198371bffdcdSAmine Khaldi rc = internal_ui_handler(package, eMessageType, record, message); 198471bffdcdSAmine Khaldi 198571bffdcdSAmine Khaldi if (!rc && package && package->log_file != INVALID_HANDLE_VALUE && 1986c2c66affSColin Finck (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1987c2c66affSColin Finck { 1988c2c66affSColin Finck DWORD written; 1989c2c66affSColin Finck WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1990c2c66affSColin Finck WriteFile( package->log_file, "\n", 1, &written, NULL ); 1991c2c66affSColin Finck } 1992c2c66affSColin Finck msi_free( msg ); 1993c2c66affSColin Finck msi_free( message ); 1994c2c66affSColin Finck 199571bffdcdSAmine Khaldi return rc; 199671bffdcdSAmine Khaldi } 199771bffdcdSAmine Khaldi 199871bffdcdSAmine Khaldi INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 199971bffdcdSAmine Khaldi { 2000c2c66affSColin Finck switch (eMessageType & 0xff000000) 2001c2c66affSColin Finck { 200271bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 200371bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 200471bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 200571bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 200671bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 200771bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 200871bffdcdSAmine Khaldi if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) 2009c2c66affSColin Finck { 201071bffdcdSAmine Khaldi /* error message */ 201171bffdcdSAmine Khaldi 201271bffdcdSAmine Khaldi LPWSTR template; 201371bffdcdSAmine Khaldi LPWSTR template_rec = NULL, template_prefix = NULL; 201471bffdcdSAmine Khaldi int error = MSI_RecordGetInteger(record, 1); 201571bffdcdSAmine Khaldi 201671bffdcdSAmine Khaldi if (MSI_RecordIsNull(record, 0)) 201771bffdcdSAmine Khaldi { 201871bffdcdSAmine Khaldi if (error >= 32) 201971bffdcdSAmine Khaldi { 202071bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, error); 202171bffdcdSAmine Khaldi 202271bffdcdSAmine Khaldi if (!template_rec && error >= 2000) 202371bffdcdSAmine Khaldi { 202471bffdcdSAmine Khaldi /* internal error, not localized */ 202571bffdcdSAmine Khaldi if ((template_rec = (LPWSTR) get_internal_error_message(error))) 202671bffdcdSAmine Khaldi { 202771bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 202871bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record); 202971bffdcdSAmine Khaldi } 203071bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR); 203171bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 203271bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 203371bffdcdSAmine Khaldi msi_free(template_rec); 203471bffdcdSAmine Khaldi return 0; 203571bffdcdSAmine Khaldi } 203671bffdcdSAmine Khaldi } 203771bffdcdSAmine Khaldi } 203871bffdcdSAmine Khaldi else 203971bffdcdSAmine Khaldi template_rec = msi_dup_record_field(record, 0); 204071bffdcdSAmine Khaldi 204171bffdcdSAmine Khaldi template_prefix = msi_get_error_message(package->db, eMessageType >> 24); 204271bffdcdSAmine Khaldi if (!template_prefix) template_prefix = strdupW(szEmpty); 204371bffdcdSAmine Khaldi 204471bffdcdSAmine Khaldi if (!template_rec) 204571bffdcdSAmine Khaldi { 204671bffdcdSAmine Khaldi /* always returns 0 */ 204771bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_prefix); 204871bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 204971bffdcdSAmine Khaldi msi_free(template_prefix); 205071bffdcdSAmine Khaldi return 0; 205171bffdcdSAmine Khaldi } 205271bffdcdSAmine Khaldi 205371bffdcdSAmine Khaldi template = msi_alloc((strlenW(template_rec) + strlenW(template_prefix) + 1) * sizeof(WCHAR)); 205471bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 205571bffdcdSAmine Khaldi 205671bffdcdSAmine Khaldi strcpyW(template, template_prefix); 205771bffdcdSAmine Khaldi strcatW(template, template_rec); 205871bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 205971bffdcdSAmine Khaldi 206071bffdcdSAmine Khaldi msi_free(template_prefix); 206171bffdcdSAmine Khaldi msi_free(template_rec); 206271bffdcdSAmine Khaldi msi_free(template); 2063c2c66affSColin Finck } 2064c2c66affSColin Finck break; 2065c2c66affSColin Finck case INSTALLMESSAGE_ACTIONSTART: 206671bffdcdSAmine Khaldi { 206771bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART); 206871bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 206971bffdcdSAmine Khaldi msi_free(template); 2070c2c66affSColin Finck 207171bffdcdSAmine Khaldi msi_free(package->LastAction); 207271bffdcdSAmine Khaldi msi_free(package->LastActionTemplate); 207371bffdcdSAmine Khaldi package->LastAction = msi_dup_record_field(record, 1); 207471bffdcdSAmine Khaldi if (!package->LastAction) package->LastAction = strdupW(szEmpty); 207571bffdcdSAmine Khaldi package->LastActionTemplate = msi_dup_record_field(record, 3); 2076c2c66affSColin Finck break; 207771bffdcdSAmine Khaldi } 207871bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 207971bffdcdSAmine Khaldi if (package->LastAction && package->LastActionTemplate) 208071bffdcdSAmine Khaldi { 208171bffdcdSAmine Khaldi static const WCHAR template_s[] = 208271bffdcdSAmine Khaldi {'{','{','%','s',':',' ','}','}','%','s',0}; 208371bffdcdSAmine Khaldi WCHAR *template; 2084c2c66affSColin Finck 208571bffdcdSAmine Khaldi template = msi_alloc((strlenW(package->LastAction) + strlenW(package->LastActionTemplate) + 7) * sizeof(WCHAR)); 208671bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 208771bffdcdSAmine Khaldi sprintfW(template, template_s, package->LastAction, package->LastActionTemplate); 208871bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 208971bffdcdSAmine Khaldi msi_free(template); 209071bffdcdSAmine Khaldi } 209171bffdcdSAmine Khaldi break; 209271bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 209371bffdcdSAmine Khaldi { 209471bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA); 209571bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 209671bffdcdSAmine Khaldi msi_free(template); 209771bffdcdSAmine Khaldi } 2098c2c66affSColin Finck break; 2099c2c66affSColin Finck } 2100c2c66affSColin Finck 210171bffdcdSAmine Khaldi return MSI_ProcessMessageVerbatim(package, eMessageType, record); 2102c2c66affSColin Finck } 2103c2c66affSColin Finck 2104c2c66affSColin Finck INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, 2105c2c66affSColin Finck MSIHANDLE hRecord) 2106c2c66affSColin Finck { 2107c2c66affSColin Finck UINT ret = ERROR_INVALID_HANDLE; 2108c2c66affSColin Finck MSIPACKAGE *package = NULL; 2109c2c66affSColin Finck MSIRECORD *record = NULL; 2110c2c66affSColin Finck 211171bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE || 211271bffdcdSAmine Khaldi (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE) 211371bffdcdSAmine Khaldi return -1; 211471bffdcdSAmine Khaldi 211571bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA && 211671bffdcdSAmine Khaldi MsiRecordGetInteger(hRecord, 1) != 2) 211771bffdcdSAmine Khaldi return -1; 211871bffdcdSAmine Khaldi 21192e19edd6Swinesync record = msihandle2msiinfo(hRecord, MSIHANDLETYPE_RECORD); 21202e19edd6Swinesync if (!record) 21212e19edd6Swinesync return ERROR_INVALID_HANDLE; 21222e19edd6Swinesync 2123c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 2124c2c66affSColin Finck if( !package ) 2125c2c66affSColin Finck { 2126b74b77aaSwinesync MSIHANDLE remote; 2127c2c66affSColin Finck 2128b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2129c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2130c2c66affSColin Finck 21312a9ae858Swinesync __TRY 21322a9ae858Swinesync { 21332e19edd6Swinesync ret = remote_ProcessMessage(remote, eMessageType, (struct wire_record *)&record->count); 21342a9ae858Swinesync } 21352a9ae858Swinesync __EXCEPT(rpc_filter) 21362a9ae858Swinesync { 21372a9ae858Swinesync ret = GetExceptionCode(); 21382a9ae858Swinesync } 21392a9ae858Swinesync __ENDTRY 2140c2c66affSColin Finck 21412e19edd6Swinesync msiobj_release(&record->hdr); 21422e19edd6Swinesync return ret; 2143c2c66affSColin Finck } 2144c2c66affSColin Finck 2145c2c66affSColin Finck ret = MSI_ProcessMessage( package, eMessageType, record ); 2146c2c66affSColin Finck 2147eab017d1Swinesync msiobj_release( &record->hdr ); 2148c2c66affSColin Finck msiobj_release( &package->hdr ); 2149c2c66affSColin Finck return ret; 2150c2c66affSColin Finck } 2151c2c66affSColin Finck 2152c2c66affSColin Finck /* property code */ 2153c2c66affSColin Finck 2154c2c66affSColin Finck UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) 2155c2c66affSColin Finck { 2156c2c66affSColin Finck LPWSTR szwName = NULL, szwValue = NULL; 2157c2c66affSColin Finck UINT r = ERROR_OUTOFMEMORY; 2158c2c66affSColin Finck 2159c2c66affSColin Finck szwName = strdupAtoW( szName ); 2160c2c66affSColin Finck if( szName && !szwName ) 2161c2c66affSColin Finck goto end; 2162c2c66affSColin Finck 2163c2c66affSColin Finck szwValue = strdupAtoW( szValue ); 2164c2c66affSColin Finck if( szValue && !szwValue ) 2165c2c66affSColin Finck goto end; 2166c2c66affSColin Finck 2167c2c66affSColin Finck r = MsiSetPropertyW( hInstall, szwName, szwValue); 2168c2c66affSColin Finck 2169c2c66affSColin Finck end: 2170c2c66affSColin Finck msi_free( szwName ); 2171c2c66affSColin Finck msi_free( szwValue ); 2172c2c66affSColin Finck 2173c2c66affSColin Finck return r; 2174c2c66affSColin Finck } 2175c2c66affSColin Finck 21760922e524Swinesync void msi_reset_source_folders( MSIPACKAGE *package ) 2177c2c66affSColin Finck { 2178c2c66affSColin Finck MSIFOLDER *folder; 2179c2c66affSColin Finck 2180c2c66affSColin Finck LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) 2181c2c66affSColin Finck { 2182c2c66affSColin Finck msi_free( folder->ResolvedSource ); 2183c2c66affSColin Finck folder->ResolvedSource = NULL; 2184c2c66affSColin Finck } 2185c2c66affSColin Finck } 2186c2c66affSColin Finck 2187c2c66affSColin Finck UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) 2188c2c66affSColin Finck { 2189c2c66affSColin Finck static const WCHAR insert_query[] = { 2190c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 2191c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 2192c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 2193c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 2194c2c66affSColin Finck static const WCHAR update_query[] = { 2195c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 2196c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ', 2197c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2198c2c66affSColin Finck static const WCHAR delete_query[] = { 2199c2c66affSColin Finck 'D','E','L','E','T','E',' ','F','R','O','M',' ', 2200c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 2201c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2202c2c66affSColin Finck MSIQUERY *view; 2203c2c66affSColin Finck MSIRECORD *row = NULL; 2204c2c66affSColin Finck DWORD sz = 0; 2205c2c66affSColin Finck WCHAR query[1024]; 2206c2c66affSColin Finck UINT rc; 2207c2c66affSColin Finck 2208c2c66affSColin Finck TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); 2209c2c66affSColin Finck 2210c2c66affSColin Finck if (!name) 2211c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 2212c2c66affSColin Finck 2213c2c66affSColin Finck /* this one is weird... */ 2214c2c66affSColin Finck if (!name[0]) 2215c2c66affSColin Finck return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; 2216c2c66affSColin Finck 2217c2c66affSColin Finck if (value && len < 0) len = strlenW( value ); 2218c2c66affSColin Finck 2219c2c66affSColin Finck rc = msi_get_property( db, name, 0, &sz ); 2220c2c66affSColin Finck if (!value || (!*value && !len)) 2221c2c66affSColin Finck { 2222c2c66affSColin Finck sprintfW( query, delete_query, name ); 2223c2c66affSColin Finck } 2224c2c66affSColin Finck else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) 2225c2c66affSColin Finck { 2226c2c66affSColin Finck sprintfW( query, update_query, name ); 2227c2c66affSColin Finck row = MSI_CreateRecord(1); 2228c2c66affSColin Finck msi_record_set_string( row, 1, value, len ); 2229c2c66affSColin Finck } 2230c2c66affSColin Finck else 2231c2c66affSColin Finck { 2232c2c66affSColin Finck strcpyW( query, insert_query ); 2233c2c66affSColin Finck row = MSI_CreateRecord(2); 2234c2c66affSColin Finck msi_record_set_string( row, 1, name, -1 ); 2235c2c66affSColin Finck msi_record_set_string( row, 2, value, len ); 2236c2c66affSColin Finck } 2237c2c66affSColin Finck 2238c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(db, query, &view); 2239c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2240c2c66affSColin Finck { 2241c2c66affSColin Finck rc = MSI_ViewExecute(view, row); 2242c2c66affSColin Finck MSI_ViewClose(view); 2243c2c66affSColin Finck msiobj_release(&view->hdr); 2244c2c66affSColin Finck } 2245c2c66affSColin Finck if (row) msiobj_release(&row->hdr); 2246c2c66affSColin Finck return rc; 2247c2c66affSColin Finck } 2248c2c66affSColin Finck 2249c2c66affSColin Finck UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) 2250c2c66affSColin Finck { 2251c2c66affSColin Finck MSIPACKAGE *package; 2252c2c66affSColin Finck UINT ret; 2253c2c66affSColin Finck 2254c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 2255c2c66affSColin Finck if( !package ) 2256c2c66affSColin Finck { 2257b74b77aaSwinesync MSIHANDLE remote; 2258c2c66affSColin Finck 2259b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2260c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2261c2c66affSColin Finck 22622a9ae858Swinesync __TRY 22632a9ae858Swinesync { 22642a9ae858Swinesync ret = remote_SetProperty(remote, szName, szValue); 22652a9ae858Swinesync } 22662a9ae858Swinesync __EXCEPT(rpc_filter) 22672a9ae858Swinesync { 22682a9ae858Swinesync ret = GetExceptionCode(); 22692a9ae858Swinesync } 22702a9ae858Swinesync __ENDTRY 22712a9ae858Swinesync 22722a9ae858Swinesync return ret; 2273c2c66affSColin Finck } 2274c2c66affSColin Finck 2275c2c66affSColin Finck ret = msi_set_property( package->db, szName, szValue, -1 ); 2276c2c66affSColin Finck if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) 22770922e524Swinesync msi_reset_source_folders( package ); 2278c2c66affSColin Finck 2279c2c66affSColin Finck msiobj_release( &package->hdr ); 2280c2c66affSColin Finck return ret; 2281c2c66affSColin Finck } 2282c2c66affSColin Finck 2283c2c66affSColin Finck static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) 2284c2c66affSColin Finck { 2285c2c66affSColin Finck static const WCHAR query[]= { 2286c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 2287c2c66affSColin Finck 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ', 2288c2c66affSColin Finck 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0}; 2289c2c66affSColin Finck MSIRECORD *rec, *row = NULL; 2290c2c66affSColin Finck MSIQUERY *view; 2291c2c66affSColin Finck UINT r; 2292c2c66affSColin Finck 229371bffdcdSAmine Khaldi static const WCHAR szDate[] = {'D','a','t','e',0}; 229471bffdcdSAmine Khaldi static const WCHAR szTime[] = {'T','i','m','e',0}; 229571bffdcdSAmine Khaldi WCHAR *buffer; 229671bffdcdSAmine Khaldi int length; 229771bffdcdSAmine Khaldi 2298c2c66affSColin Finck if (!name || !*name) 2299c2c66affSColin Finck return NULL; 2300c2c66affSColin Finck 230171bffdcdSAmine Khaldi if (!strcmpW(name, szDate)) 230271bffdcdSAmine Khaldi { 230371bffdcdSAmine Khaldi length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0); 230471bffdcdSAmine Khaldi if (!length) 230571bffdcdSAmine Khaldi return NULL; 230671bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2307fec16ab0SAmine Khaldi GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length); 230871bffdcdSAmine Khaldi 230971bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 231071bffdcdSAmine Khaldi if (!row) 2311f8b992f2SAmine Khaldi { 2312f8b992f2SAmine Khaldi msi_free(buffer); 231371bffdcdSAmine Khaldi return NULL; 2314f8b992f2SAmine Khaldi } 231571bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 231671bffdcdSAmine Khaldi msi_free(buffer); 231771bffdcdSAmine Khaldi return row; 231871bffdcdSAmine Khaldi } 231971bffdcdSAmine Khaldi else if (!strcmpW(name, szTime)) 232071bffdcdSAmine Khaldi { 232171bffdcdSAmine Khaldi length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0); 232271bffdcdSAmine Khaldi if (!length) 232371bffdcdSAmine Khaldi return NULL; 232471bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2325fec16ab0SAmine Khaldi GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length); 232671bffdcdSAmine Khaldi 232771bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 232871bffdcdSAmine Khaldi if (!row) 2329f8b992f2SAmine Khaldi { 2330f8b992f2SAmine Khaldi msi_free(buffer); 233171bffdcdSAmine Khaldi return NULL; 2332f8b992f2SAmine Khaldi } 233371bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 233471bffdcdSAmine Khaldi msi_free(buffer); 233571bffdcdSAmine Khaldi return row; 233671bffdcdSAmine Khaldi } 233771bffdcdSAmine Khaldi 2338c2c66affSColin Finck rec = MSI_CreateRecord(1); 2339c2c66affSColin Finck if (!rec) 2340c2c66affSColin Finck return NULL; 2341c2c66affSColin Finck 2342c2c66affSColin Finck MSI_RecordSetStringW(rec, 1, name); 2343c2c66affSColin Finck 2344c2c66affSColin Finck r = MSI_DatabaseOpenViewW(db, query, &view); 2345c2c66affSColin Finck if (r == ERROR_SUCCESS) 2346c2c66affSColin Finck { 2347c2c66affSColin Finck MSI_ViewExecute(view, rec); 2348c2c66affSColin Finck MSI_ViewFetch(view, &row); 2349c2c66affSColin Finck MSI_ViewClose(view); 2350c2c66affSColin Finck msiobj_release(&view->hdr); 2351c2c66affSColin Finck } 2352c2c66affSColin Finck msiobj_release(&rec->hdr); 2353c2c66affSColin Finck return row; 2354c2c66affSColin Finck } 2355c2c66affSColin Finck 2356c2c66affSColin Finck /* internal function, not compatible with MsiGetPropertyW */ 2357c2c66affSColin Finck UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, 2358c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2359c2c66affSColin Finck { 2360c2c66affSColin Finck MSIRECORD *row; 2361c2c66affSColin Finck UINT rc = ERROR_FUNCTION_FAILED; 2362c2c66affSColin Finck 2363c2c66affSColin Finck TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf); 2364c2c66affSColin Finck 2365c2c66affSColin Finck row = msi_get_property_row( db, szName ); 2366c2c66affSColin Finck 2367c2c66affSColin Finck if (*pchValueBuf > 0) 2368c2c66affSColin Finck szValueBuf[0] = 0; 2369c2c66affSColin Finck 2370c2c66affSColin Finck if (row) 2371c2c66affSColin Finck { 2372c2c66affSColin Finck rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); 2373c2c66affSColin Finck msiobj_release(&row->hdr); 2374c2c66affSColin Finck } 2375c2c66affSColin Finck 2376c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2377c2c66affSColin Finck TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), 2378c2c66affSColin Finck debugstr_w(szName)); 2379c2c66affSColin Finck else if (rc == ERROR_MORE_DATA) 2380c2c66affSColin Finck TRACE("need %d sized buffer for %s\n", *pchValueBuf, 2381c2c66affSColin Finck debugstr_w(szName)); 2382c2c66affSColin Finck else 2383c2c66affSColin Finck { 2384c2c66affSColin Finck *pchValueBuf = 0; 2385c2c66affSColin Finck TRACE("property %s not found\n", debugstr_w(szName)); 2386c2c66affSColin Finck } 2387c2c66affSColin Finck 2388c2c66affSColin Finck return rc; 2389c2c66affSColin Finck } 2390c2c66affSColin Finck 2391c2c66affSColin Finck LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2392c2c66affSColin Finck { 2393c2c66affSColin Finck DWORD sz = 0; 2394c2c66affSColin Finck LPWSTR str; 2395c2c66affSColin Finck UINT r; 2396c2c66affSColin Finck 2397c2c66affSColin Finck r = msi_get_property(db, prop, NULL, &sz); 2398c2c66affSColin Finck if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2399c2c66affSColin Finck return NULL; 2400c2c66affSColin Finck 2401c2c66affSColin Finck sz++; 2402c2c66affSColin Finck str = msi_alloc(sz * sizeof(WCHAR)); 2403c2c66affSColin Finck r = msi_get_property(db, prop, str, &sz); 2404c2c66affSColin Finck if (r != ERROR_SUCCESS) 2405c2c66affSColin Finck { 2406c2c66affSColin Finck msi_free(str); 2407c2c66affSColin Finck str = NULL; 2408c2c66affSColin Finck } 2409c2c66affSColin Finck 2410c2c66affSColin Finck return str; 2411c2c66affSColin Finck } 2412c2c66affSColin Finck 2413c2c66affSColin Finck int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2414c2c66affSColin Finck { 2415c2c66affSColin Finck LPWSTR str = msi_dup_property( db, prop ); 2416c2c66affSColin Finck int val = str ? atoiW(str) : def; 2417c2c66affSColin Finck msi_free(str); 2418c2c66affSColin Finck return val; 2419c2c66affSColin Finck } 2420c2c66affSColin Finck 2421e12fb503Swinesync UINT WINAPI MsiGetPropertyA(MSIHANDLE hinst, const char *name, char *buf, DWORD *sz) 2422c2c66affSColin Finck { 24234748b312Swinesync const WCHAR *value = szEmpty; 2424e12fb503Swinesync MSIPACKAGE *package; 24254748b312Swinesync MSIRECORD *row; 2426e12fb503Swinesync WCHAR *nameW; 24274748b312Swinesync int len = 0; 2428c2c66affSColin Finck UINT r; 2429c2c66affSColin Finck 2430e12fb503Swinesync if (!name) 2431e12fb503Swinesync return ERROR_INVALID_PARAMETER; 2432c2c66affSColin Finck 2433e12fb503Swinesync if (!(nameW = strdupAtoW(name))) 2434c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2435c2c66affSColin Finck 2436e12fb503Swinesync package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE); 2437e12fb503Swinesync if (!package) 2438e12fb503Swinesync { 2439e12fb503Swinesync WCHAR *value = NULL, *tmp; 2440e12fb503Swinesync MSIHANDLE remote; 2441e12fb503Swinesync DWORD len; 2442e12fb503Swinesync 2443e12fb503Swinesync if (!(remote = msi_get_remote(hinst))) 244402726bbcSwinesync { 244502726bbcSwinesync heap_free(nameW); 2446e12fb503Swinesync return ERROR_INVALID_HANDLE; 244702726bbcSwinesync } 2448e12fb503Swinesync 24492a9ae858Swinesync __TRY 24502a9ae858Swinesync { 2451e12fb503Swinesync r = remote_GetProperty(remote, nameW, &value, &len); 24522a9ae858Swinesync } 24532a9ae858Swinesync __EXCEPT(rpc_filter) 24542a9ae858Swinesync { 24552a9ae858Swinesync r = GetExceptionCode(); 24562a9ae858Swinesync } 24572a9ae858Swinesync __ENDTRY 24582a9ae858Swinesync 245902726bbcSwinesync heap_free(nameW); 246002726bbcSwinesync 2461e12fb503Swinesync if (!r) 2462e12fb503Swinesync { 2463e12fb503Swinesync /* String might contain embedded nulls. 2464e12fb503Swinesync * Native returns the correct size but truncates the string. */ 2465e12fb503Swinesync tmp = heap_alloc_zero((len + 1) * sizeof(WCHAR)); 2466e12fb503Swinesync if (!tmp) 2467e12fb503Swinesync { 2468e12fb503Swinesync midl_user_free(value); 2469e12fb503Swinesync return ERROR_OUTOFMEMORY; 2470e12fb503Swinesync } 2471e12fb503Swinesync strcpyW(tmp, value); 2472e12fb503Swinesync 2473e12fb503Swinesync r = msi_strncpyWtoA(tmp, len, buf, sz, TRUE); 2474e12fb503Swinesync 2475e12fb503Swinesync heap_free(tmp); 2476e12fb503Swinesync } 2477e12fb503Swinesync midl_user_free(value); 2478e12fb503Swinesync return r; 2479e12fb503Swinesync } 2480e12fb503Swinesync 24814748b312Swinesync row = msi_get_property_row(package->db, nameW); 24824748b312Swinesync if (row) 24834748b312Swinesync value = msi_record_get_string(row, 1, &len); 2484e12fb503Swinesync 24854748b312Swinesync r = msi_strncpyWtoA(value, len, buf, sz, FALSE); 2486e12fb503Swinesync 2487e12fb503Swinesync heap_free(nameW); 24884748b312Swinesync if (row) msiobj_release(&row->hdr); 2489e12fb503Swinesync msiobj_release(&package->hdr); 2490c2c66affSColin Finck return r; 2491c2c66affSColin Finck } 2492c2c66affSColin Finck 24934748b312Swinesync UINT WINAPI MsiGetPropertyW(MSIHANDLE hinst, const WCHAR *name, WCHAR *buf, DWORD *sz) 2494c2c66affSColin Finck { 24954748b312Swinesync const WCHAR *value = szEmpty; 24964748b312Swinesync MSIPACKAGE *package; 24974748b312Swinesync MSIRECORD *row; 24984748b312Swinesync int len = 0; 24994748b312Swinesync UINT r; 2500c2c66affSColin Finck 25014748b312Swinesync if (!name) 25024748b312Swinesync return ERROR_INVALID_PARAMETER; 2503c2c66affSColin Finck 25044748b312Swinesync package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE); 25054748b312Swinesync if (!package) 25064748b312Swinesync { 25074748b312Swinesync WCHAR *value = NULL, *tmp; 25084748b312Swinesync MSIHANDLE remote; 25094748b312Swinesync DWORD len; 25104748b312Swinesync 25114748b312Swinesync if (!(remote = msi_get_remote(hinst))) 25124748b312Swinesync return ERROR_INVALID_HANDLE; 25134748b312Swinesync 25142a9ae858Swinesync __TRY 25152a9ae858Swinesync { 25164748b312Swinesync r = remote_GetProperty(remote, name, &value, &len); 25172a9ae858Swinesync } 25182a9ae858Swinesync __EXCEPT(rpc_filter) 25192a9ae858Swinesync { 25202a9ae858Swinesync r = GetExceptionCode(); 25212a9ae858Swinesync } 25222a9ae858Swinesync __ENDTRY 25232a9ae858Swinesync 25244748b312Swinesync if (!r) 25254748b312Swinesync { 25264748b312Swinesync /* String might contain embedded nulls. 25274748b312Swinesync * Native returns the correct size but truncates the string. */ 25284748b312Swinesync tmp = heap_alloc_zero((len + 1) * sizeof(WCHAR)); 25294748b312Swinesync if (!tmp) 25304748b312Swinesync { 25314748b312Swinesync midl_user_free(value); 25324748b312Swinesync return ERROR_OUTOFMEMORY; 25334748b312Swinesync } 25344748b312Swinesync strcpyW(tmp, value); 25354748b312Swinesync 25364748b312Swinesync r = msi_strncpyW(tmp, len, buf, sz); 25374748b312Swinesync 25384748b312Swinesync heap_free(tmp); 25394748b312Swinesync } 25404748b312Swinesync midl_user_free(value); 25414748b312Swinesync return r; 25424748b312Swinesync } 25434748b312Swinesync 25444748b312Swinesync row = msi_get_property_row(package->db, name); 25454748b312Swinesync if (row) 25464748b312Swinesync value = msi_record_get_string(row, 1, &len); 25474748b312Swinesync 25484748b312Swinesync r = msi_strncpyW(value, len, buf, sz); 25494748b312Swinesync 25504748b312Swinesync if (row) msiobj_release(&row->hdr); 25514748b312Swinesync msiobj_release(&package->hdr); 25524748b312Swinesync return r; 2553c2c66affSColin Finck } 2554c2c66affSColin Finck 2555a8bc3902Swinesync MSIHANDLE __cdecl s_remote_GetActiveDatabase(MSIHANDLE hinst) 2556b74b77aaSwinesync { 25577cc54a4fSwinesync return MsiGetActiveDatabase(hinst); 2558c2c66affSColin Finck } 2559c2c66affSColin Finck 2560a8bc3902Swinesync UINT __cdecl s_remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size) 2561c2c66affSColin Finck { 256262ababd7Swinesync WCHAR empty[1]; 256362ababd7Swinesync UINT r; 256462ababd7Swinesync 256562ababd7Swinesync *size = 0; 256662ababd7Swinesync r = MsiGetPropertyW(hinst, property, empty, size); 256762ababd7Swinesync if (r == ERROR_MORE_DATA) 256862ababd7Swinesync { 256962ababd7Swinesync ++*size; 257062ababd7Swinesync *value = midl_user_allocate(*size * sizeof(WCHAR)); 257162ababd7Swinesync if (!*value) 257262ababd7Swinesync return ERROR_OUTOFMEMORY; 257362ababd7Swinesync r = MsiGetPropertyW(hinst, property, *value, size); 257462ababd7Swinesync } 257562ababd7Swinesync return r; 2576c2c66affSColin Finck } 2577c2c66affSColin Finck 2578a8bc3902Swinesync UINT __cdecl s_remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value) 2579c2c66affSColin Finck { 25803431091cSwinesync return MsiSetPropertyW(hinst, property, value); 2581c2c66affSColin Finck } 2582c2c66affSColin Finck 2583a8bc3902Swinesync int __cdecl s_remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, struct wire_record *remote_rec) 2584c2c66affSColin Finck { 25852e19edd6Swinesync MSIHANDLE rec; 25862e19edd6Swinesync int ret; 25872e19edd6Swinesync UINT r; 25882e19edd6Swinesync 25892e19edd6Swinesync if ((r = unmarshal_record(remote_rec, &rec))) 25902e19edd6Swinesync return r; 25912e19edd6Swinesync 25922e19edd6Swinesync ret = MsiProcessMessage(hinst, message, rec); 25932e19edd6Swinesync 25942e19edd6Swinesync MsiCloseHandle(rec); 25952e19edd6Swinesync return ret; 2596c2c66affSColin Finck } 2597c2c66affSColin Finck 2598a8bc3902Swinesync UINT __cdecl s_remote_DoAction(MSIHANDLE hinst, LPCWSTR action) 2599c2c66affSColin Finck { 2600c65c209aSwinesync return MsiDoActionW(hinst, action); 2601c2c66affSColin Finck } 2602c2c66affSColin Finck 2603a8bc3902Swinesync UINT __cdecl s_remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence) 2604c2c66affSColin Finck { 260510abb6f6Swinesync return MsiSequenceW(hinst, table, sequence); 2606c2c66affSColin Finck } 2607c2c66affSColin Finck 2608a8bc3902Swinesync UINT __cdecl s_remote_GetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2609c2c66affSColin Finck { 2610a529a627Swinesync WCHAR empty[1]; 2611a529a627Swinesync DWORD size = 0; 2612a529a627Swinesync UINT r; 2613a529a627Swinesync 2614a529a627Swinesync r = MsiGetTargetPathW(hinst, folder, empty, &size); 2615a529a627Swinesync if (r == ERROR_MORE_DATA) 2616a529a627Swinesync { 2617a529a627Swinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 2618a529a627Swinesync if (!*value) 2619a529a627Swinesync return ERROR_OUTOFMEMORY; 2620a529a627Swinesync r = MsiGetTargetPathW(hinst, folder, *value, &size); 2621a529a627Swinesync } 2622a529a627Swinesync return r; 2623c2c66affSColin Finck } 2624c2c66affSColin Finck 2625a8bc3902Swinesync UINT __cdecl s_remote_SetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPCWSTR value) 2626c2c66affSColin Finck { 2627a5e21001Swinesync return MsiSetTargetPathW(hinst, folder, value); 2628c2c66affSColin Finck } 2629c2c66affSColin Finck 2630a8bc3902Swinesync UINT __cdecl s_remote_GetSourcePath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2631c2c66affSColin Finck { 26324253f351Swinesync WCHAR empty[1]; 26334253f351Swinesync DWORD size = 1; 26344253f351Swinesync UINT r; 26354253f351Swinesync 26364253f351Swinesync r = MsiGetSourcePathW(hinst, folder, empty, &size); 26374253f351Swinesync if (r == ERROR_MORE_DATA) 26384253f351Swinesync { 26394253f351Swinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 26404253f351Swinesync if (!*value) 26414253f351Swinesync return ERROR_OUTOFMEMORY; 26424253f351Swinesync r = MsiGetSourcePathW(hinst, folder, *value, &size); 26434253f351Swinesync } 26444253f351Swinesync return r; 2645c2c66affSColin Finck } 2646c2c66affSColin Finck 2647a8bc3902Swinesync BOOL __cdecl s_remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode) 2648c2c66affSColin Finck { 264983bbe8c8Swinesync return MsiGetMode(hinst, mode); 2650c2c66affSColin Finck } 2651c2c66affSColin Finck 2652a8bc3902Swinesync UINT __cdecl s_remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state) 2653c2c66affSColin Finck { 26545219367eSwinesync return MsiSetMode(hinst, mode, state); 2655c2c66affSColin Finck } 2656c2c66affSColin Finck 2657a8bc3902Swinesync UINT __cdecl s_remote_GetFeatureState(MSIHANDLE hinst, LPCWSTR feature, 2658c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2659c2c66affSColin Finck { 2660ed5fbe39Swinesync return MsiGetFeatureStateW(hinst, feature, installed, action); 2661c2c66affSColin Finck } 2662c2c66affSColin Finck 2663a8bc3902Swinesync UINT __cdecl s_remote_SetFeatureState(MSIHANDLE hinst, LPCWSTR feature, INSTALLSTATE state) 2664c2c66affSColin Finck { 26655bbed507Swinesync return MsiSetFeatureStateW(hinst, feature, state); 2666c2c66affSColin Finck } 2667c2c66affSColin Finck 2668a8bc3902Swinesync UINT __cdecl s_remote_GetComponentState(MSIHANDLE hinst, LPCWSTR component, 2669c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2670c2c66affSColin Finck { 2671709d0f5bSwinesync return MsiGetComponentStateW(hinst, component, installed, action); 2672c2c66affSColin Finck } 2673c2c66affSColin Finck 2674a8bc3902Swinesync UINT __cdecl s_remote_SetComponentState(MSIHANDLE hinst, LPCWSTR component, INSTALLSTATE state) 2675c2c66affSColin Finck { 26761c8fdff2Swinesync return MsiSetComponentStateW(hinst, component, state); 2677c2c66affSColin Finck } 2678c2c66affSColin Finck 2679a8bc3902Swinesync LANGID __cdecl s_remote_GetLanguage(MSIHANDLE hinst) 2680c2c66affSColin Finck { 2681fdca3090Swinesync return MsiGetLanguage(hinst); 2682c2c66affSColin Finck } 2683c2c66affSColin Finck 2684a8bc3902Swinesync UINT __cdecl s_remote_SetInstallLevel(MSIHANDLE hinst, int level) 2685c2c66affSColin Finck { 2686d20dc08fSwinesync return MsiSetInstallLevel(hinst, level); 2687c2c66affSColin Finck } 2688c2c66affSColin Finck 2689a8bc3902Swinesync UINT __cdecl s_remote_FormatRecord(MSIHANDLE hinst, struct wire_record *remote_rec, LPWSTR *value) 2690c2c66affSColin Finck { 2691cde5f24cSwinesync WCHAR empty[1]; 2692c2c66affSColin Finck DWORD size = 0; 2693cde5f24cSwinesync MSIHANDLE rec; 2694cde5f24cSwinesync UINT r; 2695cde5f24cSwinesync 2696cde5f24cSwinesync if ((r = unmarshal_record(remote_rec, &rec))) 2697cde5f24cSwinesync return r; 2698cde5f24cSwinesync 2699cde5f24cSwinesync r = MsiFormatRecordW(hinst, rec, empty, &size); 2700cde5f24cSwinesync if (r == ERROR_MORE_DATA) 2701c2c66affSColin Finck { 2702cde5f24cSwinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 2703c2c66affSColin Finck if (!*value) 2704eab017d1Swinesync { 2705eab017d1Swinesync MsiCloseHandle(rec); 2706cde5f24cSwinesync return ERROR_OUTOFMEMORY; 2707eab017d1Swinesync } 2708cde5f24cSwinesync r = MsiFormatRecordW(hinst, rec, *value, &size); 2709c2c66affSColin Finck } 2710cde5f24cSwinesync 2711cde5f24cSwinesync MsiCloseHandle(rec); 2712cde5f24cSwinesync return r; 2713c2c66affSColin Finck } 2714c2c66affSColin Finck 2715a8bc3902Swinesync MSICONDITION __cdecl s_remote_EvaluateCondition(MSIHANDLE hinst, LPCWSTR condition) 2716c2c66affSColin Finck { 271703faa107Swinesync return MsiEvaluateConditionW(hinst, condition); 2718c2c66affSColin Finck } 2719c2c66affSColin Finck 2720a8bc3902Swinesync UINT __cdecl s_remote_GetFeatureCost(MSIHANDLE hinst, LPCWSTR feature, 27219f3e4bbbSwinesync MSICOSTTREE cost_tree, INSTALLSTATE state, INT *cost) 2722c2c66affSColin Finck { 27239f3e4bbbSwinesync return MsiGetFeatureCostW(hinst, feature, cost_tree, state, cost); 2724c2c66affSColin Finck } 2725c2c66affSColin Finck 2726a8bc3902Swinesync UINT __cdecl s_remote_EnumComponentCosts(MSIHANDLE hinst, LPCWSTR component, 272739198134Swinesync DWORD index, INSTALLSTATE state, LPWSTR drive, INT *cost, INT *temp) 2728c2c66affSColin Finck { 272939198134Swinesync DWORD size = 3; 273039198134Swinesync return MsiEnumComponentCostsW(hinst, component, index, state, drive, &size, cost, temp); 2731c2c66affSColin Finck } 2732c2c66affSColin Finck 2733c2c66affSColin Finck UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2734c2c66affSColin Finck LPCWSTR property, LPWSTR value) 2735c2c66affSColin Finck { 2736c2c66affSColin Finck MSISOURCELISTINFO *info; 2737c2c66affSColin Finck 2738c2c66affSColin Finck LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2739c2c66affSColin Finck { 2740c2c66affSColin Finck if (!strcmpW( info->value, value )) return ERROR_SUCCESS; 2741c2c66affSColin Finck } 2742c2c66affSColin Finck 2743c2c66affSColin Finck info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2744c2c66affSColin Finck if (!info) 2745c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2746c2c66affSColin Finck 2747c2c66affSColin Finck info->context = context; 2748c2c66affSColin Finck info->options = options; 2749c2c66affSColin Finck info->property = property; 2750c2c66affSColin Finck info->value = strdupW(value); 2751c2c66affSColin Finck list_add_head(&package->sourcelist_info, &info->entry); 2752c2c66affSColin Finck 2753c2c66affSColin Finck return ERROR_SUCCESS; 2754c2c66affSColin Finck } 2755c2c66affSColin Finck 2756c2c66affSColin Finck UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2757c2c66affSColin Finck DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2758c2c66affSColin Finck { 2759c2c66affSColin Finck MSIMEDIADISK *disk; 2760c2c66affSColin Finck 2761c2c66affSColin Finck LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2762c2c66affSColin Finck { 2763c2c66affSColin Finck if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2764c2c66affSColin Finck } 2765c2c66affSColin Finck 2766c2c66affSColin Finck disk = msi_alloc(sizeof(MSIMEDIADISK)); 2767c2c66affSColin Finck if (!disk) 2768c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2769c2c66affSColin Finck 2770c2c66affSColin Finck disk->context = context; 2771c2c66affSColin Finck disk->options = options; 2772c2c66affSColin Finck disk->disk_id = disk_id; 2773c2c66affSColin Finck disk->volume_label = strdupW(volume_label); 2774c2c66affSColin Finck disk->disk_prompt = strdupW(disk_prompt); 2775c2c66affSColin Finck list_add_head(&package->sourcelist_media, &disk->entry); 2776c2c66affSColin Finck 2777c2c66affSColin Finck return ERROR_SUCCESS; 2778c2c66affSColin Finck } 2779