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 24f4d2571bSwinesync #ifdef __REACTOS__ 25f4d2571bSwinesync #define WIN32_NO_STATUS 26f4d2571bSwinesync #endif 27c2c66affSColin Finck 28c42b133eSAmine Khaldi #include <stdarg.h> 29c42b133eSAmine Khaldi #include "windef.h" 30c42b133eSAmine Khaldi #include "winbase.h" 31c42b133eSAmine Khaldi #include "winreg.h" 32c42b133eSAmine Khaldi #include "winnls.h" 33f4d2571bSwinesync #ifdef __REACTOS__ 34f4d2571bSwinesync #include <ndk/rtlfuncs.h> 35f4d2571bSwinesync #else 36f4d2571bSwinesync #include "winternl.h" 37f4d2571bSwinesync #endif 38c42b133eSAmine Khaldi #include "shlwapi.h" 39c42b133eSAmine Khaldi #include "wingdi.h" 40c42b133eSAmine Khaldi #include "msi.h" 41c42b133eSAmine Khaldi #include "msiquery.h" 42c42b133eSAmine Khaldi #include "objidl.h" 43c42b133eSAmine Khaldi #include "wincrypt.h" 44c42b133eSAmine Khaldi #include "winuser.h" 45c42b133eSAmine Khaldi #include "wininet.h" 46c42b133eSAmine Khaldi #include "winver.h" 47c42b133eSAmine Khaldi #include "urlmon.h" 48c42b133eSAmine Khaldi #include "shlobj.h" 49c42b133eSAmine Khaldi #include "objbase.h" 50c42b133eSAmine Khaldi #include "msidefs.h" 51c42b133eSAmine Khaldi #include "sddl.h" 52c42b133eSAmine Khaldi 5362ababd7Swinesync #include "wine/debug.h" 542a9ae858Swinesync #include "wine/exception.h" 5562ababd7Swinesync 56c42b133eSAmine Khaldi #include "msipriv.h" 57a8bc3902Swinesync #include "winemsi_s.h" 58c42b133eSAmine Khaldi #include "resource.h" 59c2c66affSColin Finck 60c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi); 61c2c66affSColin Finck 62c2c66affSColin Finck static void free_feature( MSIFEATURE *feature ) 63c2c66affSColin Finck { 64c2c66affSColin Finck struct list *item, *cursor; 65c2c66affSColin Finck 66c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Children ) 67c2c66affSColin Finck { 68c2c66affSColin Finck FeatureList *fl = LIST_ENTRY( item, FeatureList, entry ); 69c2c66affSColin Finck list_remove( &fl->entry ); 70c2c66affSColin Finck msi_free( fl ); 71c2c66affSColin Finck } 72c2c66affSColin Finck 73c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) 74c2c66affSColin Finck { 75c2c66affSColin Finck ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); 76c2c66affSColin Finck list_remove( &cl->entry ); 77c2c66affSColin Finck msi_free( cl ); 78c2c66affSColin Finck } 79c2c66affSColin Finck msi_free( feature->Feature ); 80c2c66affSColin Finck msi_free( feature->Feature_Parent ); 81c2c66affSColin Finck msi_free( feature->Directory ); 82c2c66affSColin Finck msi_free( feature->Description ); 83c2c66affSColin Finck msi_free( feature->Title ); 84c2c66affSColin Finck msi_free( feature ); 85c2c66affSColin Finck } 86c2c66affSColin Finck 87c2c66affSColin Finck static void free_folder( MSIFOLDER *folder ) 88c2c66affSColin Finck { 89c2c66affSColin Finck struct list *item, *cursor; 90c2c66affSColin Finck 91c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &folder->children ) 92c2c66affSColin Finck { 93c2c66affSColin Finck FolderList *fl = LIST_ENTRY( item, FolderList, entry ); 94c2c66affSColin Finck list_remove( &fl->entry ); 95c2c66affSColin Finck msi_free( fl ); 96c2c66affSColin Finck } 97c2c66affSColin Finck msi_free( folder->Parent ); 98c2c66affSColin Finck msi_free( folder->Directory ); 99c2c66affSColin Finck msi_free( folder->TargetDefault ); 100c2c66affSColin Finck msi_free( folder->SourceLongPath ); 101c2c66affSColin Finck msi_free( folder->SourceShortPath ); 102c2c66affSColin Finck msi_free( folder->ResolvedTarget ); 103c2c66affSColin Finck msi_free( folder->ResolvedSource ); 104c2c66affSColin Finck msi_free( folder ); 105c2c66affSColin Finck } 106c2c66affSColin Finck 107c2c66affSColin Finck static void free_extension( MSIEXTENSION *ext ) 108c2c66affSColin Finck { 109c2c66affSColin Finck struct list *item, *cursor; 110c2c66affSColin Finck 111c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs ) 112c2c66affSColin Finck { 113c2c66affSColin Finck MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry ); 114c2c66affSColin Finck 115c2c66affSColin Finck list_remove( &verb->entry ); 116c2c66affSColin Finck msi_free( verb->Verb ); 117c2c66affSColin Finck msi_free( verb->Command ); 118c2c66affSColin Finck msi_free( verb->Argument ); 119c2c66affSColin Finck msi_free( verb ); 120c2c66affSColin Finck } 121c2c66affSColin Finck 122c2c66affSColin Finck msi_free( ext->Extension ); 123c2c66affSColin Finck msi_free( ext->ProgIDText ); 124c2c66affSColin Finck msi_free( ext ); 125c2c66affSColin Finck } 126c2c66affSColin Finck 127c2c66affSColin Finck static void free_assembly( MSIASSEMBLY *assembly ) 128c2c66affSColin Finck { 129c2c66affSColin Finck msi_free( assembly->feature ); 130c2c66affSColin Finck msi_free( assembly->manifest ); 131c2c66affSColin Finck msi_free( assembly->application ); 132c2c66affSColin Finck msi_free( assembly->display_name ); 133c2c66affSColin Finck if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir ); 134c2c66affSColin Finck msi_free( assembly->tempdir ); 135c2c66affSColin Finck msi_free( assembly ); 136c2c66affSColin Finck } 137c2c66affSColin Finck 138c2c66affSColin Finck void msi_free_action_script( MSIPACKAGE *package, UINT script ) 139c2c66affSColin Finck { 140c2c66affSColin Finck UINT i; 141f8b992f2SAmine Khaldi for (i = 0; i < package->script_actions_count[script]; i++) 142f8b992f2SAmine Khaldi msi_free( package->script_actions[script][i] ); 143c2c66affSColin Finck 144f8b992f2SAmine Khaldi msi_free( package->script_actions[script] ); 145f8b992f2SAmine Khaldi package->script_actions[script] = NULL; 146f8b992f2SAmine Khaldi package->script_actions_count[script] = 0; 147c2c66affSColin Finck } 148c2c66affSColin Finck 149c2c66affSColin Finck static void free_package_structures( MSIPACKAGE *package ) 150c2c66affSColin Finck { 151c2c66affSColin Finck struct list *item, *cursor; 152f8b992f2SAmine Khaldi int i; 153c2c66affSColin Finck 154c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->features ) 155c2c66affSColin Finck { 156c2c66affSColin Finck MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); 157c2c66affSColin Finck list_remove( &feature->entry ); 158c2c66affSColin Finck free_feature( feature ); 159c2c66affSColin Finck } 160c2c66affSColin Finck 161c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->folders ) 162c2c66affSColin Finck { 163c2c66affSColin Finck MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); 164c2c66affSColin Finck list_remove( &folder->entry ); 165c2c66affSColin Finck free_folder( folder ); 166c2c66affSColin Finck } 167c2c66affSColin Finck 168c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->files ) 169c2c66affSColin Finck { 170c2c66affSColin Finck MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry ); 171c2c66affSColin Finck 172c2c66affSColin Finck list_remove( &file->entry ); 173c2c66affSColin Finck msi_free( file->File ); 174c2c66affSColin Finck msi_free( file->FileName ); 175c2c66affSColin Finck msi_free( file->ShortName ); 176c2c66affSColin Finck msi_free( file->LongName ); 177c2c66affSColin Finck msi_free( file->Version ); 178c2c66affSColin Finck msi_free( file->Language ); 179c2c66affSColin Finck if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath ); 180c2c66affSColin Finck msi_free( file->TargetPath ); 181c2c66affSColin Finck msi_free( file ); 182c2c66affSColin Finck } 183c2c66affSColin Finck 184c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->components ) 185c2c66affSColin Finck { 186c2c66affSColin Finck MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); 187c2c66affSColin Finck 188c2c66affSColin Finck list_remove( &comp->entry ); 189c2c66affSColin Finck msi_free( comp->Component ); 190c2c66affSColin Finck msi_free( comp->ComponentId ); 191c2c66affSColin Finck msi_free( comp->Directory ); 192c2c66affSColin Finck msi_free( comp->Condition ); 193c2c66affSColin Finck msi_free( comp->KeyPath ); 194c2c66affSColin Finck msi_free( comp->FullKeypath ); 195c2c66affSColin Finck if (comp->assembly) free_assembly( comp->assembly ); 196c2c66affSColin Finck msi_free( comp ); 197c2c66affSColin Finck } 198c2c66affSColin Finck 199c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches ) 200c2c66affSColin Finck { 201c2c66affSColin Finck MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry ); 202c2c66affSColin Finck 203c2c66affSColin Finck list_remove( &patch->entry ); 204c2c66affSColin Finck msi_free( patch->path ); 205c2c66affSColin Finck msi_free( patch ); 206c2c66affSColin Finck } 207c2c66affSColin Finck 208c2c66affSColin Finck /* clean up extension, progid, class and verb structures */ 209c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) 210c2c66affSColin Finck { 211c2c66affSColin Finck MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry ); 212c2c66affSColin Finck 213c2c66affSColin Finck list_remove( &cls->entry ); 214c2c66affSColin Finck msi_free( cls->clsid ); 215c2c66affSColin Finck msi_free( cls->Context ); 216c2c66affSColin Finck msi_free( cls->Description ); 217c2c66affSColin Finck msi_free( cls->FileTypeMask ); 218c2c66affSColin Finck msi_free( cls->IconPath ); 219c2c66affSColin Finck msi_free( cls->DefInprocHandler ); 220c2c66affSColin Finck msi_free( cls->DefInprocHandler32 ); 221c2c66affSColin Finck msi_free( cls->Argument ); 222c2c66affSColin Finck msi_free( cls->ProgIDText ); 223c2c66affSColin Finck msi_free( cls ); 224c2c66affSColin Finck } 225c2c66affSColin Finck 226c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->extensions ) 227c2c66affSColin Finck { 228c2c66affSColin Finck MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry ); 229c2c66affSColin Finck 230c2c66affSColin Finck list_remove( &ext->entry ); 231c2c66affSColin Finck free_extension( ext ); 232c2c66affSColin Finck } 233c2c66affSColin Finck 234c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->progids ) 235c2c66affSColin Finck { 236c2c66affSColin Finck MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry ); 237c2c66affSColin Finck 238c2c66affSColin Finck list_remove( &progid->entry ); 239c2c66affSColin Finck msi_free( progid->ProgID ); 240c2c66affSColin Finck msi_free( progid->Description ); 241c2c66affSColin Finck msi_free( progid->IconPath ); 242c2c66affSColin Finck msi_free( progid ); 243c2c66affSColin Finck } 244c2c66affSColin Finck 245c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) 246c2c66affSColin Finck { 247c2c66affSColin Finck MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry ); 248c2c66affSColin Finck 249c2c66affSColin Finck list_remove( &mt->entry ); 250c2c66affSColin Finck msi_free( mt->suffix ); 251c2c66affSColin Finck msi_free( mt->clsid ); 252c2c66affSColin Finck msi_free( mt->ContentType ); 253c2c66affSColin Finck msi_free( mt ); 254c2c66affSColin Finck } 255c2c66affSColin Finck 256c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->appids ) 257c2c66affSColin Finck { 258c2c66affSColin Finck MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry ); 259c2c66affSColin Finck 260c2c66affSColin Finck list_remove( &appid->entry ); 261c2c66affSColin Finck msi_free( appid->AppID ); 262c2c66affSColin Finck msi_free( appid->RemoteServerName ); 263c2c66affSColin Finck msi_free( appid->LocalServer ); 264c2c66affSColin Finck msi_free( appid->ServiceParameters ); 265c2c66affSColin Finck msi_free( appid->DllSurrogate ); 266c2c66affSColin Finck msi_free( appid ); 267c2c66affSColin Finck } 268c2c66affSColin Finck 269c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info ) 270c2c66affSColin Finck { 271c2c66affSColin Finck MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry ); 272c2c66affSColin Finck 273c2c66affSColin Finck list_remove( &info->entry ); 274c2c66affSColin Finck msi_free( info->value ); 275c2c66affSColin Finck msi_free( info ); 276c2c66affSColin Finck } 277c2c66affSColin Finck 278c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media ) 279c2c66affSColin Finck { 280c2c66affSColin Finck MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry ); 281c2c66affSColin Finck 282c2c66affSColin Finck list_remove( &info->entry ); 283c2c66affSColin Finck msi_free( info->volume_label ); 284c2c66affSColin Finck msi_free( info->disk_prompt ); 285c2c66affSColin Finck msi_free( info ); 286c2c66affSColin Finck } 287c2c66affSColin Finck 288c2c66affSColin Finck for (i = 0; i < SCRIPT_MAX; i++) 289c2c66affSColin Finck msi_free_action_script( package, i ); 290c2c66affSColin Finck 291f8b992f2SAmine Khaldi for (i = 0; i < package->unique_actions_count; i++) 292f8b992f2SAmine Khaldi msi_free( package->unique_actions[i] ); 293f8b992f2SAmine Khaldi msi_free( package->unique_actions); 294c2c66affSColin Finck 295c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->binaries ) 296c2c66affSColin Finck { 297c2c66affSColin Finck MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry ); 298c2c66affSColin Finck 299c2c66affSColin Finck list_remove( &binary->entry ); 300c2c66affSColin Finck if (!DeleteFileW( binary->tmpfile )) 30102f995b2Swinesync ERR( "failed to delete %s (%lu)\n", debugstr_w(binary->tmpfile), GetLastError() ); 302c2c66affSColin Finck msi_free( binary->source ); 303c2c66affSColin Finck msi_free( binary->tmpfile ); 304c2c66affSColin Finck msi_free( binary ); 305c2c66affSColin Finck } 306c2c66affSColin Finck 307c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams ) 308c2c66affSColin Finck { 309c2c66affSColin Finck MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry ); 310c2c66affSColin Finck 311c2c66affSColin Finck list_remove( &cab->entry ); 312c2c66affSColin Finck IStorage_Release( cab->storage ); 313c2c66affSColin Finck msi_free( cab->stream ); 314c2c66affSColin Finck msi_free( cab ); 315c2c66affSColin Finck } 316c2c66affSColin Finck 317c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->patches ) 318c2c66affSColin Finck { 319c2c66affSColin Finck MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry ); 320c2c66affSColin Finck 321c2c66affSColin Finck list_remove( &patch->entry ); 322c2c66affSColin Finck if (patch->delete_on_close && !DeleteFileW( patch->localfile )) 323c2c66affSColin Finck { 32402f995b2Swinesync ERR( "failed to delete %s (%lu)\n", debugstr_w(patch->localfile), GetLastError() ); 325c2c66affSColin Finck } 326c2c66affSColin Finck msi_free_patchinfo( patch ); 327c2c66affSColin Finck } 328c2c66affSColin Finck 329c2c66affSColin Finck msi_free( package->PackagePath ); 330c2c66affSColin Finck msi_free( package->ProductCode ); 331c2c66affSColin Finck msi_free( package->ActionFormat ); 332c2c66affSColin Finck msi_free( package->LastAction ); 33371bffdcdSAmine Khaldi msi_free( package->LastActionTemplate ); 334c2c66affSColin Finck msi_free( package->langids ); 335c2c66affSColin Finck 336c2c66affSColin Finck /* cleanup control event subscriptions */ 337c2c66affSColin Finck msi_event_cleanup_all_subscriptions( package ); 338c2c66affSColin Finck } 339c2c66affSColin Finck 340c2c66affSColin Finck static void MSI_FreePackage( MSIOBJECTHDR *arg) 341c2c66affSColin Finck { 342c2c66affSColin Finck MSIPACKAGE *package = (MSIPACKAGE *)arg; 343c2c66affSColin Finck 344c2c66affSColin Finck msi_destroy_assembly_caches( package ); 345c2c66affSColin Finck 346c2c66affSColin Finck if( package->dialog ) 347c2c66affSColin Finck msi_dialog_destroy( package->dialog ); 348c2c66affSColin Finck 349c2c66affSColin Finck msiobj_release( &package->db->hdr ); 350c2c66affSColin Finck free_package_structures(package); 351c2c66affSColin Finck CloseHandle( package->log_file ); 3520a327bfeSwinesync if (package->rpc_server_started) 3530a327bfeSwinesync RpcServerUnregisterIf(s_IWineMsiRemote_v0_0_s_ifspec, NULL, FALSE); 354dfdb6d10Swinesync if (rpc_handle) 355dfdb6d10Swinesync RpcBindingFree(&rpc_handle); 35682decec5Swinesync if (package->custom_server_32_process) 35782decec5Swinesync custom_stop_server(package->custom_server_32_process, package->custom_server_32_pipe); 35882decec5Swinesync if (package->custom_server_64_process) 35982decec5Swinesync custom_stop_server(package->custom_server_64_process, package->custom_server_64_pipe); 360c2c66affSColin Finck 361c2c66affSColin Finck if (package->delete_on_close) DeleteFileW( package->localfile ); 362c2c66affSColin Finck msi_free( package->localfile ); 36371bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 364c2c66affSColin Finck } 365c2c66affSColin Finck 366c2c66affSColin Finck static UINT create_temp_property_table(MSIPACKAGE *package) 367c2c66affSColin Finck { 368c2c66affSColin Finck MSIQUERY *view; 369c2c66affSColin Finck UINT rc; 370c2c66affSColin Finck 3710272139cSwinesync rc = MSI_DatabaseOpenViewW(package->db, L"CREATE TABLE `_Property` ( `_Property` CHAR(56) NOT NULL TEMPORARY, " 3720272139cSwinesync L"`Value` CHAR(98) NOT NULL TEMPORARY PRIMARY KEY `_Property`) HOLD", &view); 373c2c66affSColin Finck if (rc != ERROR_SUCCESS) 374c2c66affSColin Finck return rc; 375c2c66affSColin Finck 376c2c66affSColin Finck rc = MSI_ViewExecute(view, 0); 377c2c66affSColin Finck MSI_ViewClose(view); 378c2c66affSColin Finck msiobj_release(&view->hdr); 379c2c66affSColin Finck return rc; 380c2c66affSColin Finck } 381c2c66affSColin Finck 382c2c66affSColin Finck UINT msi_clone_properties( MSIDATABASE *db ) 383c2c66affSColin Finck { 384c2c66affSColin Finck MSIQUERY *view_select; 385c2c66affSColin Finck UINT rc; 386c2c66affSColin Finck 3870272139cSwinesync rc = MSI_DatabaseOpenViewW( db, L"SELECT * FROM `Property`", &view_select ); 388c2c66affSColin Finck if (rc != ERROR_SUCCESS) 389c2c66affSColin Finck return rc; 390c2c66affSColin Finck 391c2c66affSColin Finck rc = MSI_ViewExecute( view_select, 0 ); 392c2c66affSColin Finck if (rc != ERROR_SUCCESS) 393c2c66affSColin Finck { 394c2c66affSColin Finck MSI_ViewClose( view_select ); 395c2c66affSColin Finck msiobj_release( &view_select->hdr ); 396c2c66affSColin Finck return rc; 397c2c66affSColin Finck } 398c2c66affSColin Finck 399c2c66affSColin Finck while (1) 400c2c66affSColin Finck { 401c2c66affSColin Finck MSIQUERY *view_insert, *view_update; 402c2c66affSColin Finck MSIRECORD *rec_select; 403c2c66affSColin Finck 404c2c66affSColin Finck rc = MSI_ViewFetch( view_select, &rec_select ); 405c2c66affSColin Finck if (rc != ERROR_SUCCESS) 406c2c66affSColin Finck break; 407c2c66affSColin Finck 4080272139cSwinesync rc = MSI_DatabaseOpenViewW( db, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)", &view_insert ); 409c2c66affSColin Finck if (rc != ERROR_SUCCESS) 410c2c66affSColin Finck { 411c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 412c2c66affSColin Finck continue; 413c2c66affSColin Finck } 414c2c66affSColin Finck 415c2c66affSColin Finck rc = MSI_ViewExecute( view_insert, rec_select ); 416c2c66affSColin Finck MSI_ViewClose( view_insert ); 417c2c66affSColin Finck msiobj_release( &view_insert->hdr ); 418c2c66affSColin Finck if (rc != ERROR_SUCCESS) 419c2c66affSColin Finck { 420c2c66affSColin Finck MSIRECORD *rec_update; 421c2c66affSColin Finck 422c2c66affSColin Finck TRACE("insert failed, trying update\n"); 423c2c66affSColin Finck 4240272139cSwinesync rc = MSI_DatabaseOpenViewW( db, L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = ?", &view_update ); 425c2c66affSColin Finck if (rc != ERROR_SUCCESS) 426c2c66affSColin Finck { 427c2c66affSColin Finck WARN("open view failed %u\n", rc); 428c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 429c2c66affSColin Finck continue; 430c2c66affSColin Finck } 431c2c66affSColin Finck 432c2c66affSColin Finck rec_update = MSI_CreateRecord( 2 ); 433c2c66affSColin Finck MSI_RecordCopyField( rec_select, 1, rec_update, 2 ); 434c2c66affSColin Finck MSI_RecordCopyField( rec_select, 2, rec_update, 1 ); 435c2c66affSColin Finck rc = MSI_ViewExecute( view_update, rec_update ); 436c2c66affSColin Finck if (rc != ERROR_SUCCESS) 437c2c66affSColin Finck WARN("update failed %u\n", rc); 438c2c66affSColin Finck 439c2c66affSColin Finck MSI_ViewClose( view_update ); 440c2c66affSColin Finck msiobj_release( &view_update->hdr ); 441c2c66affSColin Finck msiobj_release( &rec_update->hdr ); 442c2c66affSColin Finck } 443c2c66affSColin Finck 444c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 445c2c66affSColin Finck } 446c2c66affSColin Finck 447c2c66affSColin Finck MSI_ViewClose( view_select ); 448c2c66affSColin Finck msiobj_release( &view_select->hdr ); 449c2c66affSColin Finck return rc; 450c2c66affSColin Finck } 451c2c66affSColin Finck 452c2c66affSColin Finck /* 453c2c66affSColin Finck * set_installed_prop 454c2c66affSColin Finck * 455c2c66affSColin Finck * Sets the "Installed" property to indicate that 456c2c66affSColin Finck * the product is installed for the current user. 457c2c66affSColin Finck */ 458c2c66affSColin Finck static UINT set_installed_prop( MSIPACKAGE *package ) 459c2c66affSColin Finck { 460c2c66affSColin Finck HKEY hkey; 461c2c66affSColin Finck UINT r; 462c2c66affSColin Finck 463c2c66affSColin Finck if (!package->ProductCode) return ERROR_FUNCTION_FAILED; 464c2c66affSColin Finck 465c2c66affSColin Finck r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE ); 466c2c66affSColin Finck if (r == ERROR_SUCCESS) 467c2c66affSColin Finck { 468c2c66affSColin Finck RegCloseKey( hkey ); 4690272139cSwinesync msi_set_property( package->db, L"Installed", L"1", -1 ); 470c2c66affSColin Finck } 471c2c66affSColin Finck return r; 472c2c66affSColin Finck } 473c2c66affSColin Finck 474c2c66affSColin Finck static UINT set_user_sid_prop( MSIPACKAGE *package ) 475c2c66affSColin Finck { 476c2c66affSColin Finck SID_NAME_USE use; 477c2c66affSColin Finck LPWSTR user_name; 478c2c66affSColin Finck LPWSTR sid_str = NULL, dom = NULL; 479c2c66affSColin Finck DWORD size, dom_size; 480c2c66affSColin Finck PSID psid = NULL; 481c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 482c2c66affSColin Finck 483c2c66affSColin Finck size = 0; 484c2c66affSColin Finck GetUserNameW( NULL, &size ); 485c2c66affSColin Finck 486c2c66affSColin Finck user_name = msi_alloc( (size + 1) * sizeof(WCHAR) ); 487c2c66affSColin Finck if (!user_name) 488c2c66affSColin Finck return ERROR_OUTOFMEMORY; 489c2c66affSColin Finck 490c2c66affSColin Finck if (!GetUserNameW( user_name, &size )) 491c2c66affSColin Finck goto done; 492c2c66affSColin Finck 493c2c66affSColin Finck size = 0; 494c2c66affSColin Finck dom_size = 0; 495c2c66affSColin Finck LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use ); 496c2c66affSColin Finck 497c2c66affSColin Finck psid = msi_alloc( size ); 498c2c66affSColin Finck dom = msi_alloc( dom_size*sizeof (WCHAR) ); 499c2c66affSColin Finck if (!psid || !dom) 500c2c66affSColin Finck { 501c2c66affSColin Finck r = ERROR_OUTOFMEMORY; 502c2c66affSColin Finck goto done; 503c2c66affSColin Finck } 504c2c66affSColin Finck 505c2c66affSColin Finck if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use )) 506c2c66affSColin Finck goto done; 507c2c66affSColin Finck 508c2c66affSColin Finck if (!ConvertSidToStringSidW( psid, &sid_str )) 509c2c66affSColin Finck goto done; 510c2c66affSColin Finck 5110272139cSwinesync r = msi_set_property( package->db, L"UserSID", sid_str, -1 ); 512c2c66affSColin Finck 513c2c66affSColin Finck done: 514c2c66affSColin Finck LocalFree( sid_str ); 515c2c66affSColin Finck msi_free( dom ); 516c2c66affSColin Finck msi_free( psid ); 517c2c66affSColin Finck msi_free( user_name ); 518c2c66affSColin Finck 519c2c66affSColin Finck return r; 520c2c66affSColin Finck } 521c2c66affSColin Finck 522c2c66affSColin Finck static LPWSTR get_fusion_filename(MSIPACKAGE *package) 523c2c66affSColin Finck { 524c42b133eSAmine Khaldi HKEY netsetup, hkey; 525c2c66affSColin Finck LONG res; 526c42b133eSAmine Khaldi DWORD size, len, type; 527c42b133eSAmine Khaldi WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL; 528c2c66affSColin Finck 5290272139cSwinesync res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\NET Framework Setup\\NDP", 0, KEY_CREATE_SUB_KEY, 5300272139cSwinesync &netsetup); 531c2c66affSColin Finck if (res != ERROR_SUCCESS) 532c2c66affSColin Finck return NULL; 533c2c66affSColin Finck 5340272139cSwinesync if (!RegCreateKeyExW(netsetup, L"v4\\Client", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 535c42b133eSAmine Khaldi { 5368c1eae24Swinesync size = sizeof(path); 5370272139cSwinesync if (!RegQueryValueExW(hkey, L"InstallPath", NULL, &type, (BYTE *)path, &size)) 538c42b133eSAmine Khaldi { 5390272139cSwinesync len = lstrlenW(path) + lstrlenW(L"fusion.dll") + 2; 540c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 541c42b133eSAmine Khaldi 542958f1addSwinesync lstrcpyW(filename, path); 543a3e22d89Swinesync lstrcatW(filename, L"\\"); 5440272139cSwinesync lstrcatW(filename, L"fusion.dll"); 545c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 546c42b133eSAmine Khaldi { 547c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 548c42b133eSAmine Khaldi RegCloseKey(hkey); 549c42b133eSAmine Khaldi RegCloseKey(netsetup); 550c42b133eSAmine Khaldi return filename; 551c42b133eSAmine Khaldi } 552c42b133eSAmine Khaldi } 553c42b133eSAmine Khaldi RegCloseKey(hkey); 554c42b133eSAmine Khaldi } 555c42b133eSAmine Khaldi 5560272139cSwinesync if (!RegCreateKeyExW(netsetup, L"v2.0.50727", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 557c42b133eSAmine Khaldi { 558c42b133eSAmine Khaldi RegCloseKey(hkey); 559c2c66affSColin Finck GetWindowsDirectoryW(windir, MAX_PATH); 5600272139cSwinesync len = lstrlenW(windir) + lstrlenW(L"Microsoft.NET\\Framework\\") + lstrlenW(L"v2.0.50727") + 5610272139cSwinesync lstrlenW(L"fusion.dll") + 3; 56284826781Swinesync msi_free(filename); 563c42b133eSAmine Khaldi if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 564c2c66affSColin Finck 565958f1addSwinesync lstrcpyW(filename, windir); 5660272139cSwinesync lstrcatW(filename, L"\\"); 5670272139cSwinesync lstrcatW(filename, L"Microsoft.NET\\Framework\\"); 5680272139cSwinesync lstrcatW(filename, L"v2.0.50727"); 5690272139cSwinesync lstrcatW(filename, L"\\"); 5700272139cSwinesync lstrcatW(filename, L"fusion.dll"); 571c42b133eSAmine Khaldi if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 572c2c66affSColin Finck { 573c42b133eSAmine Khaldi TRACE( "found %s\n", debugstr_w(filename) ); 574c42b133eSAmine Khaldi RegCloseKey(netsetup); 575c42b133eSAmine Khaldi return filename; 576c2c66affSColin Finck } 577c2c66affSColin Finck } 578c2c66affSColin Finck 579c2c66affSColin Finck RegCloseKey(netsetup); 580c42b133eSAmine Khaldi return filename; 581c2c66affSColin Finck } 582c2c66affSColin Finck 583c2c66affSColin Finck typedef struct tagLANGANDCODEPAGE 584c2c66affSColin Finck { 585c2c66affSColin Finck WORD wLanguage; 586c2c66affSColin Finck WORD wCodePage; 587c2c66affSColin Finck } LANGANDCODEPAGE; 588c2c66affSColin Finck 589c2c66affSColin Finck static void set_msi_assembly_prop(MSIPACKAGE *package) 590c2c66affSColin Finck { 591c2c66affSColin Finck UINT val_len; 592c2c66affSColin Finck DWORD size, handle; 593c2c66affSColin Finck LPVOID version = NULL; 594c2c66affSColin Finck WCHAR buf[MAX_PATH]; 595c2c66affSColin Finck LPWSTR fusion, verstr; 596c2c66affSColin Finck LANGANDCODEPAGE *translate; 597c2c66affSColin Finck 598c2c66affSColin Finck fusion = get_fusion_filename(package); 599c2c66affSColin Finck if (!fusion) 600c2c66affSColin Finck return; 601c2c66affSColin Finck 602c2c66affSColin Finck size = GetFileVersionInfoSizeW(fusion, &handle); 603c2c66affSColin Finck if (!size) 604c2c66affSColin Finck goto done; 605c2c66affSColin Finck 606c2c66affSColin Finck version = msi_alloc(size); 607c2c66affSColin Finck if (!version) 608c2c66affSColin Finck goto done; 609c2c66affSColin Finck 610c2c66affSColin Finck if (!GetFileVersionInfoW(fusion, handle, size, version)) 611c2c66affSColin Finck goto done; 612c2c66affSColin Finck 6130272139cSwinesync if (!VerQueryValueW(version, L"\\VarFileInfo\\Translation", (LPVOID *)&translate, &val_len)) 614c2c66affSColin Finck goto done; 615c2c66affSColin Finck 6160272139cSwinesync swprintf(buf, ARRAY_SIZE(buf), L"\\StringFileInfo\\%04x%04x\\ProductVersion", translate[0].wLanguage, 6170272139cSwinesync translate[0].wCodePage); 618c2c66affSColin Finck 619c2c66affSColin Finck if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len)) 620c2c66affSColin Finck goto done; 621c2c66affSColin Finck 622c2c66affSColin Finck if (!val_len || !verstr) 623c2c66affSColin Finck goto done; 624c2c66affSColin Finck 6250272139cSwinesync msi_set_property( package->db, L"MsiNetAssemblySupport", verstr, -1 ); 626c2c66affSColin Finck 627c2c66affSColin Finck done: 628c2c66affSColin Finck msi_free(fusion); 629c2c66affSColin Finck msi_free(version); 630c2c66affSColin Finck } 631c2c66affSColin Finck 632c2c66affSColin Finck static VOID set_installer_properties(MSIPACKAGE *package) 633c2c66affSColin Finck { 634c2c66affSColin Finck WCHAR *ptr; 635f4d2571bSwinesync RTL_OSVERSIONINFOEXW OSVersion; 636c2c66affSColin Finck MEMORYSTATUSEX msex; 6373ec0ea99Swinesync DWORD verval, len, type; 638c2c66affSColin Finck WCHAR pth[MAX_PATH], verstr[11], bufstr[22]; 639c2c66affSColin Finck HDC dc; 640c2c66affSColin Finck HKEY hkey; 641c2c66affSColin Finck LPWSTR username, companyname; 642c2c66affSColin Finck SYSTEM_INFO sys_info; 643c2c66affSColin Finck LANGID langid; 644c2c66affSColin Finck 645c2c66affSColin Finck /* 646c2c66affSColin Finck * Other things that probably should be set: 647c2c66affSColin Finck * 648c2c66affSColin Finck * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging 649c2c66affSColin Finck * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport 650c2c66affSColin Finck */ 651c2c66affSColin Finck 652c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); 6530272139cSwinesync lstrcatW(pth, L"\\"); 6540272139cSwinesync msi_set_property( package->db, L"CommonAppDataFolder", pth, -1 ); 655c2c66affSColin Finck 656c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); 6570272139cSwinesync lstrcatW(pth, L"\\"); 6580272139cSwinesync msi_set_property( package->db, L"FavoritesFolder", pth, -1 ); 659c2c66affSColin Finck 660c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); 6610272139cSwinesync lstrcatW(pth, L"\\"); 6620272139cSwinesync msi_set_property( package->db, L"FontsFolder", pth, -1 ); 663c2c66affSColin Finck 664c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); 6650272139cSwinesync lstrcatW(pth, L"\\"); 6660272139cSwinesync msi_set_property( package->db, L"SendToFolder", pth, -1 ); 667c2c66affSColin Finck 668c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); 6690272139cSwinesync lstrcatW(pth, L"\\"); 6700272139cSwinesync msi_set_property( package->db, L"StartMenuFolder", pth, -1 ); 671c2c66affSColin Finck 672c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); 6730272139cSwinesync lstrcatW(pth, L"\\"); 6740272139cSwinesync msi_set_property( package->db, L"StartupFolder", pth, -1 ); 675c2c66affSColin Finck 676c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); 6770272139cSwinesync lstrcatW(pth, L"\\"); 6780272139cSwinesync msi_set_property( package->db, L"TemplateFolder", pth, -1 ); 679c2c66affSColin Finck 680c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); 6810272139cSwinesync lstrcatW(pth, L"\\"); 6820272139cSwinesync msi_set_property( package->db, L"DesktopFolder", pth, -1 ); 683c2c66affSColin Finck 684c2c66affSColin Finck /* FIXME: set to AllUsers profile path if ALLUSERS is set */ 685c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); 6860272139cSwinesync lstrcatW(pth, L"\\"); 6870272139cSwinesync msi_set_property( package->db, L"ProgramMenuFolder", pth, -1 ); 688c2c66affSColin Finck 689c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); 6900272139cSwinesync lstrcatW(pth, L"\\"); 6910272139cSwinesync msi_set_property( package->db, L"AdminToolsFolder", pth, -1 ); 692c2c66affSColin Finck 693c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); 6940272139cSwinesync lstrcatW(pth, L"\\"); 6950272139cSwinesync msi_set_property( package->db, L"AppDataFolder", pth, -1 ); 696c2c66affSColin Finck 697c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); 6980272139cSwinesync lstrcatW(pth, L"\\"); 6990272139cSwinesync msi_set_property( package->db, L"SystemFolder", pth, -1 ); 7000272139cSwinesync msi_set_property( package->db, L"System16Folder", pth, -1 ); 701c2c66affSColin Finck 702c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); 7030272139cSwinesync lstrcatW(pth, L"\\"); 7040272139cSwinesync msi_set_property( package->db, L"LocalAppDataFolder", pth, -1 ); 705c2c66affSColin Finck 706c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); 7070272139cSwinesync lstrcatW(pth, L"\\"); 7080272139cSwinesync msi_set_property( package->db, L"MyPicturesFolder", pth, -1 ); 709c2c66affSColin Finck 710c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); 7110272139cSwinesync lstrcatW(pth, L"\\"); 7120272139cSwinesync msi_set_property( package->db, L"PersonalFolder", pth, -1 ); 713c2c66affSColin Finck 714c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 7150272139cSwinesync lstrcatW(pth, L"\\"); 7160272139cSwinesync msi_set_property( package->db, L"WindowsFolder", pth, -1 ); 717c2c66affSColin Finck 718c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); 7190272139cSwinesync lstrcatW(pth, L"\\"); 7200272139cSwinesync msi_set_property( package->db, L"PrintHoodFolder", pth, -1 ); 721c2c66affSColin Finck 722c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); 7230272139cSwinesync lstrcatW(pth, L"\\"); 7240272139cSwinesync msi_set_property( package->db, L"NetHoodFolder", pth, -1 ); 725c2c66affSColin Finck 726c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); 7270272139cSwinesync lstrcatW(pth, L"\\"); 7280272139cSwinesync msi_set_property( package->db, L"RecentFolder", pth, -1 ); 729c2c66affSColin Finck 730c2c66affSColin Finck /* Physical Memory is specified in MB. Using total amount. */ 731c2c66affSColin Finck msex.dwLength = sizeof(msex); 732c2c66affSColin Finck GlobalMemoryStatusEx( &msex ); 7330272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", (int)(msex.ullTotalPhys / 1024 / 1024) ); 7340272139cSwinesync msi_set_property( package->db, L"PhysicalMemory", bufstr, len ); 735c2c66affSColin Finck 736c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 737958f1addSwinesync ptr = wcschr(pth,'\\'); 738c2c66affSColin Finck if (ptr) *(ptr + 1) = 0; 7390272139cSwinesync msi_set_property( package->db, L"WindowsVolume", pth, -1 ); 740c2c66affSColin Finck 741c2c66affSColin Finck len = GetTempPathW(MAX_PATH, pth); 7420272139cSwinesync msi_set_property( package->db, L"TempFolder", pth, len ); 743c2c66affSColin Finck 744c2c66affSColin Finck /* in a wine environment the user is always admin and privileged */ 7450272139cSwinesync msi_set_property( package->db, L"AdminUser", L"1", -1 ); 7460272139cSwinesync msi_set_property( package->db, L"Privileged", L"1", -1 ); 74785854456Swinesync msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 ); 748c2c66affSColin Finck 749c2c66affSColin Finck /* set the os things */ 750f4d2571bSwinesync OSVersion.dwOSVersionInfoSize = sizeof(OSVersion); 751f4d2571bSwinesync RtlGetVersion((PRTL_OSVERSIONINFOW)&OSVersion); 752c2c66affSColin Finck verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; 753f4d2571bSwinesync if (verval > 603) 754f4d2571bSwinesync { 755f4d2571bSwinesync verval = 603; 756f4d2571bSwinesync OSVersion.dwBuildNumber = 9600; 757f4d2571bSwinesync } 7580272139cSwinesync len = swprintf( verstr, ARRAY_SIZE(verstr), L"%u", verval ); 759c2c66affSColin Finck switch (OSVersion.dwPlatformId) 760c2c66affSColin Finck { 761c2c66affSColin Finck case VER_PLATFORM_WIN32_WINDOWS: 7620272139cSwinesync msi_set_property( package->db, L"Version9X", verstr, len ); 763c2c66affSColin Finck break; 764c2c66affSColin Finck case VER_PLATFORM_WIN32_NT: 7650272139cSwinesync msi_set_property( package->db, L"VersionNT", verstr, len ); 7660272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wProductType ); 7670272139cSwinesync msi_set_property( package->db, L"MsiNTProductType", bufstr, len ); 768c2c66affSColin Finck break; 769c2c66affSColin Finck } 7700272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.dwBuildNumber ); 7710272139cSwinesync msi_set_property( package->db, L"WindowsBuild", bufstr, len ); 7720272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wServicePackMajor ); 7730272139cSwinesync msi_set_property( package->db, L"ServicePackLevel", bufstr, len ); 774c2c66affSColin Finck 7750272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u.%u", MSI_MAJORVERSION, MSI_MINORVERSION ); 7760272139cSwinesync msi_set_property( package->db, L"VersionMsi", bufstr, len ); 7770272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", MSI_MAJORVERSION * 100 ); 7780272139cSwinesync msi_set_property( package->db, L"VersionDatabase", bufstr, len ); 779c2c66affSColin Finck 7800272139cSwinesync RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, 7813ec0ea99Swinesync KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hkey); 7823ec0ea99Swinesync 783c2c66affSColin Finck GetNativeSystemInfo( &sys_info ); 7840272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", sys_info.wProcessorLevel ); 7850272139cSwinesync msi_set_property( package->db, L"Intel", bufstr, len ); 786c2c66affSColin Finck if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 787c2c66affSColin Finck { 788c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 789c2c66affSColin Finck PathAddBackslashW( pth ); 7900272139cSwinesync msi_set_property( package->db, L"SystemFolder", pth, -1 ); 791c2c66affSColin Finck 7928c1eae24Swinesync len = sizeof(pth); 7930272139cSwinesync RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len); 794c2c66affSColin Finck PathAddBackslashW( pth ); 7950272139cSwinesync msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 ); 796c2c66affSColin Finck 7978c1eae24Swinesync len = sizeof(pth); 7980272139cSwinesync RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len); 799c2c66affSColin Finck PathAddBackslashW( pth ); 8000272139cSwinesync msi_set_property( package->db, L"CommonFilesFolder", pth, -1 ); 801c2c66affSColin Finck } 802c2c66affSColin Finck else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 803c2c66affSColin Finck { 8040272139cSwinesync msi_set_property( package->db, L"MsiAMD64", bufstr, -1 ); 8050272139cSwinesync msi_set_property( package->db, L"Msix64", bufstr, -1 ); 8060272139cSwinesync msi_set_property( package->db, L"VersionNT64", verstr, -1 ); 807c2c66affSColin Finck 808c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 809c2c66affSColin Finck PathAddBackslashW( pth ); 8100272139cSwinesync msi_set_property( package->db, L"System64Folder", pth, -1 ); 811c2c66affSColin Finck 812c2c66affSColin Finck GetSystemWow64DirectoryW( pth, MAX_PATH ); 813c2c66affSColin Finck PathAddBackslashW( pth ); 8140272139cSwinesync msi_set_property( package->db, L"SystemFolder", pth, -1 ); 815c2c66affSColin Finck 8168c1eae24Swinesync len = sizeof(pth); 8170272139cSwinesync RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len); 818c2c66affSColin Finck PathAddBackslashW( pth ); 8190272139cSwinesync msi_set_property( package->db, L"ProgramFiles64Folder", pth, -1 ); 820c2c66affSColin Finck 8218c1eae24Swinesync len = sizeof(pth); 8220272139cSwinesync RegQueryValueExW(hkey, L"ProgramFilesDir (x86)", 0, &type, (BYTE *)pth, &len); 823c2c66affSColin Finck PathAddBackslashW( pth ); 8240272139cSwinesync msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 ); 825c2c66affSColin Finck 8268c1eae24Swinesync len = sizeof(pth); 8270272139cSwinesync RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len); 828c2c66affSColin Finck PathAddBackslashW( pth ); 8290272139cSwinesync msi_set_property( package->db, L"CommonFiles64Folder", pth, -1 ); 830c2c66affSColin Finck 8318c1eae24Swinesync len = sizeof(pth); 8320272139cSwinesync RegQueryValueExW(hkey, L"CommonFilesDir (x86)", 0, &type, (BYTE *)pth, &len); 833c2c66affSColin Finck PathAddBackslashW( pth ); 8340272139cSwinesync msi_set_property( package->db, L"CommonFilesFolder", pth, -1 ); 835c2c66affSColin Finck } 836c2c66affSColin Finck 8373ec0ea99Swinesync RegCloseKey(hkey); 8383ec0ea99Swinesync 839c2c66affSColin Finck /* Screen properties. */ 840c2c66affSColin Finck dc = GetDC(0); 8410272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, HORZRES) ); 8420272139cSwinesync msi_set_property( package->db, L"ScreenX", bufstr, len ); 8430272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, VERTRES) ); 8440272139cSwinesync msi_set_property( package->db, L"ScreenY", bufstr, len ); 8450272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, BITSPIXEL) ); 8460272139cSwinesync msi_set_property( package->db, L"ColorBits", bufstr, len ); 847c2c66affSColin Finck ReleaseDC(0, dc); 848c2c66affSColin Finck 849c2c66affSColin Finck /* USERNAME and COMPANYNAME */ 8500272139cSwinesync username = msi_dup_property( package->db, L"USERNAME" ); 8510272139cSwinesync companyname = msi_dup_property( package->db, L"COMPANYNAME" ); 852c2c66affSColin Finck 853c2c66affSColin Finck if ((!username || !companyname) && 8540272139cSwinesync RegOpenKeyW( HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey ) == ERROR_SUCCESS) 855c2c66affSColin Finck { 856c2c66affSColin Finck if (!username && 8570272139cSwinesync (username = msi_reg_get_val_str( hkey, L"DefName" ))) 8580272139cSwinesync msi_set_property( package->db, L"USERNAME", username, -1 ); 859c2c66affSColin Finck if (!companyname && 8600272139cSwinesync (companyname = msi_reg_get_val_str( hkey, L"DefCompany" ))) 8610272139cSwinesync msi_set_property( package->db, L"COMPANYNAME", companyname, -1 ); 862c2c66affSColin Finck CloseHandle( hkey ); 863c2c66affSColin Finck } 864c2c66affSColin Finck if ((!username || !companyname) && 8650272139cSwinesync RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, 8660272139cSwinesync KEY_QUERY_VALUE|KEY_WOW64_64KEY, &hkey ) == ERROR_SUCCESS) 867c2c66affSColin Finck { 868c2c66affSColin Finck if (!username && 8690272139cSwinesync (username = msi_reg_get_val_str( hkey, L"RegisteredOwner" ))) 8700272139cSwinesync msi_set_property( package->db, L"USERNAME", username, -1 ); 871c2c66affSColin Finck if (!companyname && 8720272139cSwinesync (companyname = msi_reg_get_val_str( hkey, L"RegisteredOrganization" ))) 8730272139cSwinesync msi_set_property( package->db, L"COMPANYNAME", companyname, -1 ); 874c2c66affSColin Finck CloseHandle( hkey ); 875c2c66affSColin Finck } 876c2c66affSColin Finck msi_free( username ); 877c2c66affSColin Finck msi_free( companyname ); 878c2c66affSColin Finck 879c2c66affSColin Finck if ( set_user_sid_prop( package ) != ERROR_SUCCESS) 880c2c66affSColin Finck ERR("Failed to set the UserSID property\n"); 881c2c66affSColin Finck 882c2c66affSColin Finck set_msi_assembly_prop( package ); 883c2c66affSColin Finck 884c2c66affSColin Finck langid = GetUserDefaultLangID(); 8850272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid ); 8860272139cSwinesync msi_set_property( package->db, L"UserLanguageID", bufstr, len ); 887c2c66affSColin Finck 888c2c66affSColin Finck langid = GetSystemDefaultLangID(); 8890272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid ); 8900272139cSwinesync msi_set_property( package->db, L"SystemLanguageID", bufstr, len ); 891c2c66affSColin Finck 8920272139cSwinesync len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", MsiQueryProductStateW(package->ProductCode) ); 8930272139cSwinesync msi_set_property( package->db, L"ProductState", bufstr, len ); 894c2c66affSColin Finck 895c2c66affSColin Finck len = 0; 896c2c66affSColin Finck if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 897c2c66affSColin Finck { 898c2c66affSColin Finck WCHAR *username; 899c2c66affSColin Finck if ((username = msi_alloc( len * sizeof(WCHAR) ))) 900c2c66affSColin Finck { 901c2c66affSColin Finck if (GetUserNameW( username, &len )) 9020272139cSwinesync msi_set_property( package->db, L"LogonUser", username, len - 1 ); 903c2c66affSColin Finck msi_free( username ); 904c2c66affSColin Finck } 905c2c66affSColin Finck } 906c2c66affSColin Finck len = 0; 907c2c66affSColin Finck if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW) 908c2c66affSColin Finck { 909c2c66affSColin Finck WCHAR *computername; 910c2c66affSColin Finck if ((computername = msi_alloc( len * sizeof(WCHAR) ))) 911c2c66affSColin Finck { 912c2c66affSColin Finck if (GetComputerNameW( computername, &len )) 9130272139cSwinesync msi_set_property( package->db, L"ComputerName", computername, len ); 914c2c66affSColin Finck msi_free( computername ); 915c2c66affSColin Finck } 916c2c66affSColin Finck } 917c2c66affSColin Finck } 918c2c66affSColin Finck 919c2c66affSColin Finck static MSIPACKAGE *msi_alloc_package( void ) 920c2c66affSColin Finck { 921c2c66affSColin Finck MSIPACKAGE *package; 922c2c66affSColin Finck 923c2c66affSColin Finck package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), 924c2c66affSColin Finck MSI_FreePackage ); 925c2c66affSColin Finck if( package ) 926c2c66affSColin Finck { 927c2c66affSColin Finck list_init( &package->components ); 928c2c66affSColin Finck list_init( &package->features ); 929c2c66affSColin Finck list_init( &package->files ); 930c2c66affSColin Finck list_init( &package->filepatches ); 931c2c66affSColin Finck list_init( &package->tempfiles ); 932c2c66affSColin Finck list_init( &package->folders ); 933c2c66affSColin Finck list_init( &package->subscriptions ); 934c2c66affSColin Finck list_init( &package->appids ); 935c2c66affSColin Finck list_init( &package->classes ); 936c2c66affSColin Finck list_init( &package->mimes ); 937c2c66affSColin Finck list_init( &package->extensions ); 938c2c66affSColin Finck list_init( &package->progids ); 939c2c66affSColin Finck list_init( &package->RunningActions ); 940c2c66affSColin Finck list_init( &package->sourcelist_info ); 941c2c66affSColin Finck list_init( &package->sourcelist_media ); 942c2c66affSColin Finck list_init( &package->patches ); 943c2c66affSColin Finck list_init( &package->binaries ); 944c2c66affSColin Finck list_init( &package->cabinet_streams ); 945c2c66affSColin Finck } 946c2c66affSColin Finck 947c2c66affSColin Finck return package; 948c2c66affSColin Finck } 949c2c66affSColin Finck 950c2c66affSColin Finck static UINT msi_load_admin_properties(MSIPACKAGE *package) 951c2c66affSColin Finck { 952c2c66affSColin Finck BYTE *data; 953c2c66affSColin Finck UINT r, sz; 954c2c66affSColin Finck 9550272139cSwinesync r = read_stream_data(package->db->storage, L"AdminProperties", FALSE, &data, &sz); 956c2c66affSColin Finck if (r != ERROR_SUCCESS) 957c2c66affSColin Finck return r; 958c2c66affSColin Finck 959c2c66affSColin Finck r = msi_parse_command_line(package, (WCHAR *)data, TRUE); 960c2c66affSColin Finck 961c2c66affSColin Finck msi_free(data); 962c2c66affSColin Finck return r; 963c2c66affSColin Finck } 964c2c66affSColin Finck 965c2c66affSColin Finck void msi_adjust_privilege_properties( MSIPACKAGE *package ) 966c2c66affSColin Finck { 967c2c66affSColin Finck /* FIXME: this should depend on the user's privileges */ 9680272139cSwinesync if (msi_get_property_int( package->db, L"ALLUSERS", 0 ) == 2) 969c2c66affSColin Finck { 970c2c66affSColin Finck TRACE("resetting ALLUSERS property from 2 to 1\n"); 9710272139cSwinesync msi_set_property( package->db, L"ALLUSERS", L"1", -1 ); 972c2c66affSColin Finck } 9730272139cSwinesync msi_set_property( package->db, L"AdminUser", L"1", -1 ); 97485854456Swinesync msi_set_property( package->db, L"Privileged", L"1", -1 ); 97585854456Swinesync msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 ); 976c2c66affSColin Finck } 977c2c66affSColin Finck 97834c2011cSwinesync MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db ) 979c2c66affSColin Finck { 980c2c66affSColin Finck MSIPACKAGE *package; 981c2c66affSColin Finck WCHAR uilevel[11]; 982c2c66affSColin Finck int len; 983c2c66affSColin Finck UINT r; 984c2c66affSColin Finck 985c2c66affSColin Finck TRACE("%p\n", db); 986c2c66affSColin Finck 987c2c66affSColin Finck package = msi_alloc_package(); 988c2c66affSColin Finck if (package) 989c2c66affSColin Finck { 990c2c66affSColin Finck msiobj_addref( &db->hdr ); 991c2c66affSColin Finck package->db = db; 992c2c66affSColin Finck 99371bffdcdSAmine Khaldi package->LastAction = NULL; 99471bffdcdSAmine Khaldi package->LastActionTemplate = NULL; 99571bffdcdSAmine Khaldi package->LastActionResult = MSI_NULL_INTEGER; 996c2c66affSColin Finck package->WordCount = 0; 997c2c66affSColin Finck package->PackagePath = strdupW( db->path ); 998c2c66affSColin Finck 999c2c66affSColin Finck create_temp_property_table( package ); 1000c2c66affSColin Finck msi_clone_properties( package->db ); 1001c2c66affSColin Finck msi_adjust_privilege_properties( package ); 1002c2c66affSColin Finck 10030272139cSwinesync package->ProductCode = msi_dup_property( package->db, L"ProductCode" ); 1004c2c66affSColin Finck 1005c2c66affSColin Finck set_installer_properties( package ); 1006c2c66affSColin Finck 1007c2c66affSColin Finck package->ui_level = gUILevel; 10080272139cSwinesync len = swprintf( uilevel, ARRAY_SIZE(uilevel), L"%u", gUILevel & INSTALLUILEVEL_MASK ); 10090272139cSwinesync msi_set_property( package->db, L"UILevel", uilevel, len ); 1010c2c66affSColin Finck 1011c2c66affSColin Finck r = msi_load_suminfo_properties( package ); 1012c2c66affSColin Finck if (r != ERROR_SUCCESS) 1013c2c66affSColin Finck { 1014c2c66affSColin Finck msiobj_release( &package->hdr ); 1015c2c66affSColin Finck return NULL; 1016c2c66affSColin Finck } 1017c2c66affSColin Finck 1018c2c66affSColin Finck if (package->WordCount & msidbSumInfoSourceTypeAdminImage) 1019c2c66affSColin Finck msi_load_admin_properties( package ); 1020c2c66affSColin Finck 1021c2c66affSColin Finck package->log_file = INVALID_HANDLE_VALUE; 10220d762dcbSwinesync package->script = SCRIPT_NONE; 1023c2c66affSColin Finck } 1024c2c66affSColin Finck return package; 1025c2c66affSColin Finck } 1026c2c66affSColin Finck 1027c2c66affSColin Finck UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) 1028c2c66affSColin Finck { 1029c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW cache_entry; 1030c2c66affSColin Finck DWORD size = 0; 1031c2c66affSColin Finck HRESULT hr; 1032c2c66affSColin Finck 1033c2c66affSColin Finck /* call will always fail, because size is 0, 1034c2c66affSColin Finck * but will return ERROR_FILE_NOT_FOUND first 1035c2c66affSColin Finck * if the file doesn't exist 1036c2c66affSColin Finck */ 1037c2c66affSColin Finck GetUrlCacheEntryInfoW( szUrl, NULL, &size ); 1038c2c66affSColin Finck if ( GetLastError() != ERROR_FILE_NOT_FOUND ) 1039c2c66affSColin Finck { 1040c2c66affSColin Finck cache_entry = msi_alloc( size ); 1041c2c66affSColin Finck if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) 1042c2c66affSColin Finck { 1043c2c66affSColin Finck UINT error = GetLastError(); 1044c2c66affSColin Finck msi_free( cache_entry ); 1045c2c66affSColin Finck return error; 1046c2c66affSColin Finck } 1047c2c66affSColin Finck 1048c2c66affSColin Finck lstrcpyW( filename, cache_entry->lpszLocalFileName ); 1049c2c66affSColin Finck msi_free( cache_entry ); 1050c2c66affSColin Finck return ERROR_SUCCESS; 1051c2c66affSColin Finck } 1052c2c66affSColin Finck 1053c2c66affSColin Finck hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); 1054c2c66affSColin Finck if ( FAILED(hr) ) 1055c2c66affSColin Finck { 1056c2c66affSColin Finck WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); 1057c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1058c2c66affSColin Finck } 1059c2c66affSColin Finck 1060c2c66affSColin Finck return ERROR_SUCCESS; 1061c2c66affSColin Finck } 1062c2c66affSColin Finck 1063c2c66affSColin Finck UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) 1064c2c66affSColin Finck { 1065c2c66affSColin Finck DWORD time, len, i, offset; 1066c2c66affSColin Finck HANDLE handle; 1067c2c66affSColin Finck 1068c2c66affSColin Finck time = GetTickCount(); 1069c2c66affSColin Finck GetWindowsDirectoryW( path, MAX_PATH ); 10700272139cSwinesync lstrcatW( path, L"\\Installer\\" ); 1071c2c66affSColin Finck CreateDirectoryW( path, NULL ); 1072c2c66affSColin Finck 1073958f1addSwinesync len = lstrlenW(path); 1074c2c66affSColin Finck for (i = 0; i < 0x10000; i++) 1075c2c66affSColin Finck { 10760272139cSwinesync offset = swprintf( path + len, MAX_PATH - len, L"%x", (time + i) & 0xffff ); 1077958f1addSwinesync memcpy( path + len + offset, suffix, (lstrlenW( suffix ) + 1) * sizeof(WCHAR) ); 1078c2c66affSColin Finck handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, 1079c2c66affSColin Finck CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); 1080c2c66affSColin Finck if (handle != INVALID_HANDLE_VALUE) 1081c2c66affSColin Finck { 1082c2c66affSColin Finck CloseHandle(handle); 1083c2c66affSColin Finck break; 1084c2c66affSColin Finck } 1085c2c66affSColin Finck if (GetLastError() != ERROR_FILE_EXISTS && 1086c2c66affSColin Finck GetLastError() != ERROR_SHARING_VIOLATION) 1087c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1088c2c66affSColin Finck } 1089c2c66affSColin Finck 1090c2c66affSColin Finck return ERROR_SUCCESS; 1091c2c66affSColin Finck } 1092c2c66affSColin Finck 1093c2c66affSColin Finck static enum platform parse_platform( const WCHAR *str ) 1094c2c66affSColin Finck { 10950272139cSwinesync if (!str[0] || !wcscmp( str, L"Intel" )) return PLATFORM_INTEL; 10960272139cSwinesync else if (!wcscmp( str, L"Intel64" )) return PLATFORM_INTEL64; 10970272139cSwinesync else if (!wcscmp( str, L"x64" ) || !wcscmp( str, L"AMD64" )) return PLATFORM_X64; 10980272139cSwinesync else if (!wcscmp( str, L"Arm" )) return PLATFORM_ARM; 10990272139cSwinesync else if (!wcscmp( str, L"Arm64" )) return PLATFORM_ARM64; 110098d8ddaaSwinesync return PLATFORM_UNRECOGNIZED; 1101c2c66affSColin Finck } 1102c2c66affSColin Finck 1103c2c66affSColin Finck static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) 1104c2c66affSColin Finck { 1105c2c66affSColin Finck WCHAR *template, *p, *q, *platform; 1106c2c66affSColin Finck DWORD i, count; 1107c2c66affSColin Finck 1108c2c66affSColin Finck package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); 1109c2c66affSColin Finck TRACE("version: %d\n", package->version); 1110c2c66affSColin Finck 1111c2c66affSColin Finck template = msi_suminfo_dup_string( si, PID_TEMPLATE ); 1112c2c66affSColin Finck if (!template) 1113c2c66affSColin Finck return ERROR_SUCCESS; /* native accepts missing template property */ 1114c2c66affSColin Finck 1115c2c66affSColin Finck TRACE("template: %s\n", debugstr_w(template)); 1116c2c66affSColin Finck 1117958f1addSwinesync p = wcschr( template, ';' ); 1118c2c66affSColin Finck if (!p) 1119c2c66affSColin Finck { 1120c2c66affSColin Finck WARN("invalid template string %s\n", debugstr_w(template)); 1121c2c66affSColin Finck msi_free( template ); 1122c2c66affSColin Finck return ERROR_PATCH_PACKAGE_INVALID; 1123c2c66affSColin Finck } 1124c2c66affSColin Finck *p = 0; 1125c2c66affSColin Finck platform = template; 1126958f1addSwinesync if ((q = wcschr( platform, ',' ))) *q = 0; 1127c2c66affSColin Finck package->platform = parse_platform( platform ); 112898d8ddaaSwinesync while (package->platform == PLATFORM_UNRECOGNIZED && q) 1129c2c66affSColin Finck { 1130c2c66affSColin Finck platform = q + 1; 1131958f1addSwinesync if ((q = wcschr( platform, ',' ))) *q = 0; 1132c2c66affSColin Finck package->platform = parse_platform( platform ); 1133c2c66affSColin Finck } 113498d8ddaaSwinesync if (package->platform == PLATFORM_UNRECOGNIZED) 1135c2c66affSColin Finck { 1136c2c66affSColin Finck WARN("unknown platform %s\n", debugstr_w(template)); 1137c2c66affSColin Finck msi_free( template ); 1138c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1139c2c66affSColin Finck } 1140c2c66affSColin Finck p++; 1141c2c66affSColin Finck if (!*p) 1142c2c66affSColin Finck { 1143c2c66affSColin Finck msi_free( template ); 1144c2c66affSColin Finck return ERROR_SUCCESS; 1145c2c66affSColin Finck } 1146c2c66affSColin Finck count = 1; 1147958f1addSwinesync for (q = p; (q = wcschr( q, ',' )); q++) count++; 1148c2c66affSColin Finck 1149c2c66affSColin Finck package->langids = msi_alloc( count * sizeof(LANGID) ); 1150c2c66affSColin Finck if (!package->langids) 1151c2c66affSColin Finck { 1152c2c66affSColin Finck msi_free( template ); 1153c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1154c2c66affSColin Finck } 1155c2c66affSColin Finck 1156c2c66affSColin Finck i = 0; 1157c2c66affSColin Finck while (*p) 1158c2c66affSColin Finck { 1159958f1addSwinesync q = wcschr( p, ',' ); 1160c2c66affSColin Finck if (q) *q = 0; 1161958f1addSwinesync package->langids[i] = wcstol( p, NULL, 10 ); 1162c2c66affSColin Finck if (!q) break; 1163c2c66affSColin Finck p = q + 1; 1164c2c66affSColin Finck i++; 1165c2c66affSColin Finck } 1166c2c66affSColin Finck package->num_langids = i + 1; 1167c2c66affSColin Finck 1168c2c66affSColin Finck msi_free( template ); 1169c2c66affSColin Finck return ERROR_SUCCESS; 1170c2c66affSColin Finck } 1171c2c66affSColin Finck 1172c2c66affSColin Finck static UINT validate_package( MSIPACKAGE *package ) 1173c2c66affSColin Finck { 1174c2c66affSColin Finck UINT i; 1175c2c66affSColin Finck 1176c2c66affSColin Finck if (package->platform == PLATFORM_INTEL64) 1177c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1178c2c66affSColin Finck #ifndef __arm__ 1179c2c66affSColin Finck if (package->platform == PLATFORM_ARM) 1180c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1181c2c66affSColin Finck #endif 1182de59794fSwinesync #ifndef __aarch64__ 1183de59794fSwinesync if (package->platform == PLATFORM_ARM64) 1184de59794fSwinesync return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1185de59794fSwinesync #endif 1186c2c66affSColin Finck if (package->platform == PLATFORM_X64) 1187c2c66affSColin Finck { 1188c2c66affSColin Finck if (!is_64bit && !is_wow64) 1189c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1190c2c66affSColin Finck if (package->version < 200) 1191c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1192c2c66affSColin Finck } 1193c2c66affSColin Finck if (!package->num_langids) 1194c2c66affSColin Finck { 1195c2c66affSColin Finck return ERROR_SUCCESS; 1196c2c66affSColin Finck } 1197c2c66affSColin Finck for (i = 0; i < package->num_langids; i++) 1198c2c66affSColin Finck { 1199c2c66affSColin Finck LANGID langid = package->langids[i]; 1200c2c66affSColin Finck 1201c2c66affSColin Finck if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) 1202c2c66affSColin Finck { 1203c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); 1204c2c66affSColin Finck } 1205c2c66affSColin Finck if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) 1206c2c66affSColin Finck { 1207c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); 1208c2c66affSColin Finck } 1209c2c66affSColin Finck if (IsValidLocale( langid, LCID_INSTALLED )) 1210c2c66affSColin Finck return ERROR_SUCCESS; 1211c2c66affSColin Finck } 1212c2c66affSColin Finck return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; 1213c2c66affSColin Finck } 1214c2c66affSColin Finck 1215b7b9c0c4Swinesync static WCHAR *get_property( MSIDATABASE *db, const WCHAR *prop ) 1216c2c66affSColin Finck { 1217b7b9c0c4Swinesync WCHAR query[MAX_PATH]; 1218c2c66affSColin Finck MSIQUERY *view; 1219c2c66affSColin Finck MSIRECORD *rec; 1220c2c66affSColin Finck WCHAR *ret = NULL; 1221c2c66affSColin Finck 12220272139cSwinesync swprintf(query, ARRAY_SIZE(query), L"SELECT `Value` FROM `Property` WHERE `Property`='%s'", prop); 1223c2c66affSColin Finck if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) 1224c2c66affSColin Finck { 1225c2c66affSColin Finck return NULL; 1226c2c66affSColin Finck } 1227c2c66affSColin Finck if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) 1228c2c66affSColin Finck { 1229c2c66affSColin Finck MSI_ViewClose( view ); 1230c2c66affSColin Finck msiobj_release( &view->hdr ); 1231c2c66affSColin Finck return NULL; 1232c2c66affSColin Finck } 1233c2c66affSColin Finck if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) 1234c2c66affSColin Finck { 1235c2c66affSColin Finck ret = strdupW( MSI_RecordGetString( rec, 1 ) ); 1236c2c66affSColin Finck msiobj_release( &rec->hdr ); 1237c2c66affSColin Finck } 1238c2c66affSColin Finck MSI_ViewClose( view ); 1239c2c66affSColin Finck msiobj_release( &view->hdr ); 1240c2c66affSColin Finck return ret; 1241c2c66affSColin Finck } 1242c2c66affSColin Finck 1243b7b9c0c4Swinesync static WCHAR *get_product_code( MSIDATABASE *db ) 1244b7b9c0c4Swinesync { 12450272139cSwinesync return get_property( db, L"ProductCode" ); 1246b7b9c0c4Swinesync } 1247b7b9c0c4Swinesync 1248b7b9c0c4Swinesync static WCHAR *get_product_version( MSIDATABASE *db ) 1249b7b9c0c4Swinesync { 12500272139cSwinesync return get_property( db, L"ProductVersion" ); 1251b7b9c0c4Swinesync } 1252b7b9c0c4Swinesync 1253b7b9c0c4Swinesync static UINT get_registered_local_package( const WCHAR *product, WCHAR *localfile ) 1254c2c66affSColin Finck { 1255c2c66affSColin Finck MSIINSTALLCONTEXT context; 1256b7b9c0c4Swinesync WCHAR *filename; 1257b7b9c0c4Swinesync HKEY props_key; 1258c2c66affSColin Finck UINT r; 1259c2c66affSColin Finck 1260c2c66affSColin Finck r = msi_locate_product( product, &context ); 1261c2c66affSColin Finck if (r != ERROR_SUCCESS) 1262c2c66affSColin Finck return r; 1263c2c66affSColin Finck 1264c2c66affSColin Finck r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); 1265c2c66affSColin Finck if (r != ERROR_SUCCESS) 1266c2c66affSColin Finck return r; 1267c2c66affSColin Finck 1268b7b9c0c4Swinesync filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); 1269b7b9c0c4Swinesync RegCloseKey( props_key ); 1270c2c66affSColin Finck if (!filename) 1271b7b9c0c4Swinesync return ERROR_FUNCTION_FAILED; 1272c2c66affSColin Finck 1273958f1addSwinesync lstrcpyW( localfile, filename ); 1274c2c66affSColin Finck msi_free( filename ); 1275b7b9c0c4Swinesync return ERROR_SUCCESS; 1276c2c66affSColin Finck } 1277c2c66affSColin Finck 127874196b80Swinesync WCHAR *msi_get_package_code( MSIDATABASE *db ) 1279c2c66affSColin Finck { 1280c2c66affSColin Finck WCHAR *ret; 1281c2c66affSColin Finck MSISUMMARYINFO *si; 1282c2c66affSColin Finck UINT r; 1283c2c66affSColin Finck 1284c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1285c2c66affSColin Finck if (r != ERROR_SUCCESS) 1286c2c66affSColin Finck { 1287c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1288c2c66affSColin Finck if (r != ERROR_SUCCESS) 1289c2c66affSColin Finck { 1290c2c66affSColin Finck WARN("failed to load summary info %u\n", r); 1291c2c66affSColin Finck return NULL; 1292c2c66affSColin Finck } 1293c2c66affSColin Finck } 1294c2c66affSColin Finck ret = msi_suminfo_dup_string( si, PID_REVNUMBER ); 1295c2c66affSColin Finck msiobj_release( &si->hdr ); 1296c2c66affSColin Finck return ret; 1297c2c66affSColin Finck } 1298c2c66affSColin Finck 1299b7b9c0c4Swinesync static UINT get_local_package( MSIDATABASE *db, WCHAR *localfile ) 1300c2c66affSColin Finck { 1301b7b9c0c4Swinesync WCHAR *product_code; 1302c2c66affSColin Finck UINT r; 1303c2c66affSColin Finck 1304c2c66affSColin Finck if (!(product_code = get_product_code( db ))) 1305c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1306b7b9c0c4Swinesync r = get_registered_local_package( product_code, localfile ); 1307c2c66affSColin Finck msi_free( product_code ); 1308c2c66affSColin Finck return r; 1309c2c66affSColin Finck } 1310c2c66affSColin Finck 1311c2c66affSColin Finck UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) 1312c2c66affSColin Finck { 1313c2c66affSColin Finck UINT r; 1314c2c66affSColin Finck 1315c2c66affSColin Finck if (UrlIsW( package, URLIS_URL )) 13160272139cSwinesync r = msi_set_property( db, L"OriginalDatabase", package, -1 ); 1317c2c66affSColin Finck else if (package[0] == '#') 13180272139cSwinesync r = msi_set_property( db, L"OriginalDatabase", db->path, -1 ); 1319c2c66affSColin Finck else 1320c2c66affSColin Finck { 1321c2c66affSColin Finck DWORD len; 1322c2c66affSColin Finck WCHAR *path; 1323c2c66affSColin Finck 1324c2c66affSColin Finck if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); 1325c2c66affSColin Finck if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; 1326c2c66affSColin Finck len = GetFullPathNameW( package, len, path, NULL ); 13270272139cSwinesync r = msi_set_property( db, L"OriginalDatabase", path, len ); 1328c2c66affSColin Finck msi_free( path ); 1329c2c66affSColin Finck } 1330c2c66affSColin Finck return r; 1331c2c66affSColin Finck } 1332c2c66affSColin Finck 1333*05637a5eSMark Jansen #ifdef __REACTOS__ 1334*05637a5eSMark Jansen BOOL WINAPI ApphelpCheckRunAppEx(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PCWSTR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, PVOID *SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, 1335*05637a5eSMark Jansen PVOID *SxsData, PULONG SxsDataSize, PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2); 1336*05637a5eSMark Jansen BOOL WINAPI SE_DynamicShim(LPCWSTR ProcessImage, PVOID hsdb, PVOID pQueryResult, LPCSTR Module, LPDWORD lpdwDynamicToken); 1337*05637a5eSMark Jansen PVOID WINAPI SdbInitDatabase(DWORD flags, LPCWSTR path); 1338*05637a5eSMark Jansen PVOID WINAPI SdbReleaseDatabase(PVOID hsdb); 1339*05637a5eSMark Jansen 1340*05637a5eSMark Jansen #define HID_DOS_PATHS 0x1 1341*05637a5eSMark Jansen #define SDB_DATABASE_MAIN_SHIM 0x80030000 1342*05637a5eSMark Jansen 1343*05637a5eSMark Jansen #define APPHELP_VALID_RESULT 0x10000 1344*05637a5eSMark Jansen #define APPHELP_RESULT_FOUND 0x40000 1345*05637a5eSMark Jansen 1346*05637a5eSMark Jansen static void 1347*05637a5eSMark Jansen AppHelpCheckPackage(LPCWSTR szPackage) 1348*05637a5eSMark Jansen { 1349*05637a5eSMark Jansen USHORT ExeType = 0; 1350*05637a5eSMark Jansen ULONG Reason = 0; 1351*05637a5eSMark Jansen 1352*05637a5eSMark Jansen PVOID QueryResult = NULL; 1353*05637a5eSMark Jansen ULONG QueryResultSize = 0; 1354*05637a5eSMark Jansen 1355*05637a5eSMark Jansen HANDLE Handle = NULL; 1356*05637a5eSMark Jansen BOOL Continue = ApphelpCheckRunAppEx( 1357*05637a5eSMark Jansen Handle, NULL, NULL, szPackage, NULL, ExeType, &Reason, &QueryResult, &QueryResultSize, NULL, 1358*05637a5eSMark Jansen NULL, NULL, NULL, NULL); 1359*05637a5eSMark Jansen 1360*05637a5eSMark Jansen if (Continue) 1361*05637a5eSMark Jansen { 1362*05637a5eSMark Jansen if ((Reason & (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND)) 1363*05637a5eSMark Jansen { 1364*05637a5eSMark Jansen DWORD dwToken; 1365*05637a5eSMark Jansen PVOID hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL); 1366*05637a5eSMark Jansen if (hsdb) 1367*05637a5eSMark Jansen { 1368*05637a5eSMark Jansen BOOL bShim = SE_DynamicShim(szPackage, hsdb, QueryResult, "msi.dll", &dwToken); 1369*05637a5eSMark Jansen ERR("ReactOS HACK: Used SE_DynamicShim %d!\n", bShim); 1370*05637a5eSMark Jansen 1371*05637a5eSMark Jansen SdbReleaseDatabase(hsdb); 1372*05637a5eSMark Jansen } 1373*05637a5eSMark Jansen else 1374*05637a5eSMark Jansen { 1375*05637a5eSMark Jansen ERR("Unable to open SDB_DATABASE_MAIN_SHIM\n"); 1376*05637a5eSMark Jansen } 1377*05637a5eSMark Jansen } 1378*05637a5eSMark Jansen } 1379*05637a5eSMark Jansen 1380*05637a5eSMark Jansen if (QueryResult) 1381*05637a5eSMark Jansen RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult); 1382*05637a5eSMark Jansen } 1383*05637a5eSMark Jansen #endif 1384*05637a5eSMark Jansen 1385a2371385Swinesync UINT MSI_OpenPackageW(LPCWSTR szPackage, DWORD dwOptions, MSIPACKAGE **pPackage) 1386c2c66affSColin Finck { 1387c2c66affSColin Finck MSIDATABASE *db; 1388c2c66affSColin Finck MSIPACKAGE *package; 1389c2c66affSColin Finck MSIHANDLE handle; 139071bffdcdSAmine Khaldi MSIRECORD *data_row, *info_row; 1391c2c66affSColin Finck UINT r; 1392c2c66affSColin Finck WCHAR localfile[MAX_PATH], cachefile[MAX_PATH]; 1393c2c66affSColin Finck LPCWSTR file = szPackage; 1394c2c66affSColin Finck DWORD index = 0; 1395c2c66affSColin Finck MSISUMMARYINFO *si; 1396c2c66affSColin Finck BOOL delete_on_close = FALSE; 1397da848361Swinesync WCHAR *info_template, *productname, *product_code; 1398da848361Swinesync MSIINSTALLCONTEXT context; 1399c2c66affSColin Finck 1400c2c66affSColin Finck TRACE("%s %p\n", debugstr_w(szPackage), pPackage); 1401c2c66affSColin Finck 140271bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0); 140371bffdcdSAmine Khaldi 1404c2c66affSColin Finck localfile[0] = 0; 1405c2c66affSColin Finck if( szPackage[0] == '#' ) 1406c2c66affSColin Finck { 1407958f1addSwinesync handle = wcstol(&szPackage[1], NULL, 10); 1408b720e4c0Swinesync if (!(db = msihandle2msiinfo(handle, MSIHANDLETYPE_DATABASE))) 1409c2c66affSColin Finck return ERROR_INVALID_HANDLE; 1410c2c66affSColin Finck } 1411c2c66affSColin Finck else 1412c2c66affSColin Finck { 1413b7b9c0c4Swinesync WCHAR *product_version = NULL; 1414b7b9c0c4Swinesync 1415c2c66affSColin Finck if ( UrlIsW( szPackage, URLIS_URL ) ) 1416c2c66affSColin Finck { 1417c2c66affSColin Finck r = msi_download_file( szPackage, cachefile ); 1418c2c66affSColin Finck if (r != ERROR_SUCCESS) 1419c2c66affSColin Finck return r; 1420c2c66affSColin Finck 1421c2c66affSColin Finck file = cachefile; 1422c2c66affSColin Finck } 1423*05637a5eSMark Jansen #ifdef __REACTOS__ 1424*05637a5eSMark Jansen AppHelpCheckPackage(file); 1425*05637a5eSMark Jansen #endif 1426*05637a5eSMark Jansen 1427b7b9c0c4Swinesync r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db ); 1428b7b9c0c4Swinesync if (r != ERROR_SUCCESS) 1429b7b9c0c4Swinesync { 1430b7b9c0c4Swinesync if (GetFileAttributesW( file ) == INVALID_FILE_ATTRIBUTES) 1431b7b9c0c4Swinesync return ERROR_FILE_NOT_FOUND; 1432b7b9c0c4Swinesync return r; 1433b7b9c0c4Swinesync } 1434b7b9c0c4Swinesync r = get_local_package( db, localfile ); 1435c2c66affSColin Finck if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) 1436c2c66affSColin Finck { 143763bb43adSJérôme Gardou DWORD localfile_attr; 143863bb43adSJérôme Gardou 14390272139cSwinesync r = msi_create_empty_local_file( localfile, L".msi" ); 1440c2c66affSColin Finck if (r != ERROR_SUCCESS) 1441b7b9c0c4Swinesync { 1442b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1443c2c66affSColin Finck return r; 1444b7b9c0c4Swinesync } 1445c2c66affSColin Finck 1446c2c66affSColin Finck if (!CopyFileW( file, localfile, FALSE )) 1447c2c66affSColin Finck { 1448c2c66affSColin Finck r = GetLastError(); 1449c2c66affSColin Finck WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1450c2c66affSColin Finck DeleteFileW( localfile ); 1451b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1452c2c66affSColin Finck return r; 1453c2c66affSColin Finck } 1454c2c66affSColin Finck delete_on_close = TRUE; 145563bb43adSJérôme Gardou 145663bb43adSJérôme Gardou /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */ 145763bb43adSJérôme Gardou localfile_attr = GetFileAttributesW( localfile ); 145863bb43adSJérôme Gardou if (localfile_attr & FILE_ATTRIBUTE_READONLY) 145963bb43adSJérôme Gardou SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY); 1460c2c66affSColin Finck } 1461a2371385Swinesync else if (dwOptions & WINE_OPENPACKAGEFLAGS_RECACHE) 1462a2371385Swinesync { 1463a2371385Swinesync if (!CopyFileW( file, localfile, FALSE )) 1464a2371385Swinesync { 1465a2371385Swinesync r = GetLastError(); 1466a2371385Swinesync WARN("unable to update cached package (%u)\n", r); 1467a2371385Swinesync msiobj_release( &db->hdr ); 1468a2371385Swinesync return r; 1469a2371385Swinesync } 1470a2371385Swinesync } 1471b7b9c0c4Swinesync else 1472b7b9c0c4Swinesync product_version = get_product_version( db ); 1473b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1474c2c66affSColin Finck TRACE("opening package %s\n", debugstr_w( localfile )); 1475c2c66affSColin Finck r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1476c2c66affSColin Finck if (r != ERROR_SUCCESS) 1477c2c66affSColin Finck return r; 1478b7b9c0c4Swinesync 1479b7b9c0c4Swinesync if (product_version) 1480b7b9c0c4Swinesync { 1481b7b9c0c4Swinesync WCHAR *cache_version = get_product_version( db ); 1482b7b9c0c4Swinesync if (!product_version != !cache_version || 1483958f1addSwinesync (product_version && wcscmp(product_version, cache_version))) 1484b7b9c0c4Swinesync { 1485b7b9c0c4Swinesync msiobj_release( &db->hdr ); 1486b7b9c0c4Swinesync msi_free(product_version); 1487b7b9c0c4Swinesync msi_free(cache_version); 1488b7b9c0c4Swinesync return ERROR_PRODUCT_VERSION; 1489b7b9c0c4Swinesync } 1490b7b9c0c4Swinesync msi_free(product_version); 1491b7b9c0c4Swinesync msi_free(cache_version); 1492b7b9c0c4Swinesync } 1493c2c66affSColin Finck } 149434c2011cSwinesync package = MSI_CreatePackage( db ); 1495c2c66affSColin Finck msiobj_release( &db->hdr ); 1496c2c66affSColin Finck if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1497c2c66affSColin Finck package->localfile = strdupW( localfile ); 1498c2c66affSColin Finck package->delete_on_close = delete_on_close; 1499c2c66affSColin Finck 1500c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1501c2c66affSColin Finck if (r != ERROR_SUCCESS) 1502c2c66affSColin Finck { 1503c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1504c2c66affSColin Finck if (r != ERROR_SUCCESS) 1505c2c66affSColin Finck { 1506c2c66affSColin Finck WARN("failed to load summary info\n"); 1507c2c66affSColin Finck msiobj_release( &package->hdr ); 1508c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1509c2c66affSColin Finck } 1510c2c66affSColin Finck } 1511c2c66affSColin Finck r = parse_suminfo( si, package ); 1512c2c66affSColin Finck msiobj_release( &si->hdr ); 1513c2c66affSColin Finck if (r != ERROR_SUCCESS) 1514c2c66affSColin Finck { 1515c2c66affSColin Finck WARN("failed to parse summary info %u\n", r); 1516c2c66affSColin Finck msiobj_release( &package->hdr ); 1517c2c66affSColin Finck return r; 1518c2c66affSColin Finck } 1519c2c66affSColin Finck r = validate_package( package ); 1520c2c66affSColin Finck if (r != ERROR_SUCCESS) 1521c2c66affSColin Finck { 1522c2c66affSColin Finck msiobj_release( &package->hdr ); 1523c2c66affSColin Finck return r; 1524c2c66affSColin Finck } 15250272139cSwinesync msi_set_property( package->db, L"DATABASE", db->path, -1 ); 1526c2c66affSColin Finck set_installed_prop( package ); 1527c2c66affSColin Finck msi_set_context( package ); 1528c2c66affSColin Finck 1529da848361Swinesync product_code = get_product_code( db ); 1530da848361Swinesync if (msi_locate_product( product_code, &context ) == ERROR_SUCCESS) 1531da848361Swinesync { 1532da848361Swinesync TRACE("product already registered\n"); 15330272139cSwinesync msi_set_property( package->db, L"ProductToBeRegistered", L"1", -1 ); 1534da848361Swinesync } 1535da848361Swinesync msi_free(product_code); 1536da848361Swinesync 1537c2c66affSColin Finck while (1) 1538c2c66affSColin Finck { 1539c2c66affSColin Finck WCHAR patch_code[GUID_SIZE]; 1540c2c66affSColin Finck r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1541c2c66affSColin Finck MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1542c2c66affSColin Finck if (r != ERROR_SUCCESS) 1543c2c66affSColin Finck break; 1544c2c66affSColin Finck 1545c2c66affSColin Finck TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1546c2c66affSColin Finck 1547c2c66affSColin Finck r = msi_apply_registered_patch( package, patch_code ); 1548c2c66affSColin Finck if (r != ERROR_SUCCESS) 1549c2c66affSColin Finck { 1550c2c66affSColin Finck ERR("registered patch failed to apply %u\n", r); 1551c2c66affSColin Finck msiobj_release( &package->hdr ); 1552c2c66affSColin Finck return r; 1553c2c66affSColin Finck } 1554c2c66affSColin Finck index++; 1555c2c66affSColin Finck } 1556c2c66affSColin Finck if (index) msi_adjust_privilege_properties( package ); 1557c2c66affSColin Finck 1558c2c66affSColin Finck r = msi_set_original_database_property( package->db, szPackage ); 1559c2c66affSColin Finck if (r != ERROR_SUCCESS) 1560c2c66affSColin Finck { 1561c2c66affSColin Finck msiobj_release( &package->hdr ); 1562c2c66affSColin Finck return r; 1563c2c66affSColin Finck } 1564c2c66affSColin Finck if (gszLogFile) 1565c2c66affSColin Finck package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1566c2c66affSColin Finck OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 156771bffdcdSAmine Khaldi 1568e342f337Swinesync if (!msi_init_assembly_caches( package )) 1569e342f337Swinesync { 1570e342f337Swinesync ERR("can't initialize assembly caches\n"); 1571e342f337Swinesync msiobj_release( &package->hdr ); 1572e342f337Swinesync return ERROR_FUNCTION_FAILED; 1573e342f337Swinesync } 1574e342f337Swinesync 157571bffdcdSAmine Khaldi /* FIXME: when should these messages be sent? */ 157671bffdcdSAmine Khaldi data_row = MSI_CreateRecord(3); 157771bffdcdSAmine Khaldi if (!data_row) 157871bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 157971bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 0, NULL); 158071bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 0); 158171bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0); 158271bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings)); 158371bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row); 158471bffdcdSAmine Khaldi 158571bffdcdSAmine Khaldi info_row = MSI_CreateRecord(0); 158671bffdcdSAmine Khaldi if (!info_row) 158771bffdcdSAmine Khaldi { 158871bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 158971bffdcdSAmine Khaldi return ERROR_OUTOFMEMORY; 159071bffdcdSAmine Khaldi } 159171bffdcdSAmine Khaldi info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART); 159271bffdcdSAmine Khaldi MSI_RecordSetStringW(info_row, 0, info_template); 159371bffdcdSAmine Khaldi msi_free(info_template); 159471bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row); 159571bffdcdSAmine Khaldi 159671bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 159771bffdcdSAmine Khaldi 159871bffdcdSAmine Khaldi productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW); 159971bffdcdSAmine Khaldi MSI_RecordSetInteger(data_row, 1, 1); 160071bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 2, productname); 160171bffdcdSAmine Khaldi MSI_RecordSetStringW(data_row, 3, NULL); 160271bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 160371bffdcdSAmine Khaldi 160471bffdcdSAmine Khaldi msi_free(productname); 160571bffdcdSAmine Khaldi msiobj_release(&info_row->hdr); 160671bffdcdSAmine Khaldi msiobj_release(&data_row->hdr); 160771bffdcdSAmine Khaldi 1608c2c66affSColin Finck *pPackage = package; 1609c2c66affSColin Finck return ERROR_SUCCESS; 1610c2c66affSColin Finck } 1611c2c66affSColin Finck 161202f995b2Swinesync UINT WINAPI MsiOpenPackageExW( const WCHAR *szPackage, DWORD dwOptions, MSIHANDLE *phPackage ) 1613c2c66affSColin Finck { 1614c2c66affSColin Finck MSIPACKAGE *package = NULL; 1615c2c66affSColin Finck UINT ret; 1616c2c66affSColin Finck 161702f995b2Swinesync TRACE( "%s, %#lx, %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1618c2c66affSColin Finck 1619c2c66affSColin Finck if( !szPackage || !phPackage ) 1620c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 1621c2c66affSColin Finck 1622c2c66affSColin Finck if ( !*szPackage ) 1623c2c66affSColin Finck { 1624c2c66affSColin Finck FIXME("Should create an empty database and package\n"); 1625c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1626c2c66affSColin Finck } 1627c2c66affSColin Finck 1628c2c66affSColin Finck if( dwOptions ) 162902f995b2Swinesync FIXME( "dwOptions %#lx not supported\n", dwOptions ); 1630c2c66affSColin Finck 1631a2371385Swinesync ret = MSI_OpenPackageW( szPackage, 0, &package ); 1632c2c66affSColin Finck if( ret == ERROR_SUCCESS ) 1633c2c66affSColin Finck { 1634c2c66affSColin Finck *phPackage = alloc_msihandle( &package->hdr ); 1635c2c66affSColin Finck if (! *phPackage) 1636c2c66affSColin Finck ret = ERROR_NOT_ENOUGH_MEMORY; 1637c2c66affSColin Finck msiobj_release( &package->hdr ); 1638c2c66affSColin Finck } 163971bffdcdSAmine Khaldi else 164071bffdcdSAmine Khaldi MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 1641c2c66affSColin Finck 1642c2c66affSColin Finck return ret; 1643c2c66affSColin Finck } 1644c2c66affSColin Finck 1645c2c66affSColin Finck UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1646c2c66affSColin Finck { 1647c2c66affSColin Finck return MsiOpenPackageExW( szPackage, 0, phPackage ); 1648c2c66affSColin Finck } 1649c2c66affSColin Finck 1650c2c66affSColin Finck UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1651c2c66affSColin Finck { 1652c2c66affSColin Finck LPWSTR szwPack = NULL; 1653c2c66affSColin Finck UINT ret; 1654c2c66affSColin Finck 1655c2c66affSColin Finck if( szPackage ) 1656c2c66affSColin Finck { 1657c2c66affSColin Finck szwPack = strdupAtoW( szPackage ); 1658c2c66affSColin Finck if( !szwPack ) 1659c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1660c2c66affSColin Finck } 1661c2c66affSColin Finck 1662c2c66affSColin Finck ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1663c2c66affSColin Finck 1664c2c66affSColin Finck msi_free( szwPack ); 1665c2c66affSColin Finck 1666c2c66affSColin Finck return ret; 1667c2c66affSColin Finck } 1668c2c66affSColin Finck 1669c2c66affSColin Finck UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1670c2c66affSColin Finck { 1671c2c66affSColin Finck return MsiOpenPackageExA( szPackage, 0, phPackage ); 1672c2c66affSColin Finck } 1673c2c66affSColin Finck 1674c2c66affSColin Finck MSIHANDLE WINAPI MsiGetActiveDatabase( MSIHANDLE hInstall ) 1675c2c66affSColin Finck { 1676c2c66affSColin Finck MSIPACKAGE *package; 1677c2c66affSColin Finck MSIHANDLE handle = 0; 1678b74b77aaSwinesync MSIHANDLE remote; 1679c2c66affSColin Finck 168002f995b2Swinesync TRACE( "%lu\n", hInstall ); 1681c2c66affSColin Finck 1682c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1683c2c66affSColin Finck if( package) 1684c2c66affSColin Finck { 1685c2c66affSColin Finck handle = alloc_msihandle( &package->db->hdr ); 1686c2c66affSColin Finck msiobj_release( &package->hdr ); 1687c2c66affSColin Finck } 1688b74b77aaSwinesync else if ((remote = msi_get_remote(hInstall))) 1689c2c66affSColin Finck { 16902a9ae858Swinesync __TRY 16912a9ae858Swinesync { 1692bf1ca658Swinesync handle = remote_GetActiveDatabase(remote); 16937cc54a4fSwinesync handle = alloc_msi_remote_handle(handle); 1694c2c66affSColin Finck } 16952a9ae858Swinesync __EXCEPT(rpc_filter) 16962a9ae858Swinesync { 16972a9ae858Swinesync handle = 0; 16982a9ae858Swinesync } 16992a9ae858Swinesync __ENDTRY 17002a9ae858Swinesync } 1701c2c66affSColin Finck 1702c2c66affSColin Finck return handle; 1703c2c66affSColin Finck } 1704c2c66affSColin Finck 170571bffdcdSAmine Khaldi static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message) 1706c2c66affSColin Finck { 170771bffdcdSAmine Khaldi if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) 170871bffdcdSAmine Khaldi return 0; 170971bffdcdSAmine Khaldi 171071bffdcdSAmine Khaldi /* todo: check if message needs additional styles (topmost/foreground/modality?) */ 171171bffdcdSAmine Khaldi 171271bffdcdSAmine Khaldi switch (eMessageType & 0xff000000) 171371bffdcdSAmine Khaldi { 171471bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 171571bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 171671bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 171771bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 171871bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 171971bffdcdSAmine Khaldi eMessageType |= MB_ICONEXCLAMATION; 17200272139cSwinesync return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff); 172171bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 172271bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 172371bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 172471bffdcdSAmine Khaldi eMessageType |= MB_ICONASTERISK; 17250272139cSwinesync return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff); 172671bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 172771bffdcdSAmine Khaldi if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 172871bffdcdSAmine Khaldi if (!(eMessageType & MB_ICONMASK)) 172971bffdcdSAmine Khaldi eMessageType |= MB_USERICON; 17300272139cSwinesync return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff); 173171bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 173271bffdcdSAmine Khaldi case INSTALLMESSAGE_INITIALIZE: 173371bffdcdSAmine Khaldi case INSTALLMESSAGE_TERMINATE: 1734f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLSTART: 1735f8b992f2SAmine Khaldi case INSTALLMESSAGE_INSTALLEND: 173671bffdcdSAmine Khaldi return 0; 173771bffdcdSAmine Khaldi case INSTALLMESSAGE_SHOWDIALOG: 173871bffdcdSAmine Khaldi { 173971bffdcdSAmine Khaldi LPWSTR dialog = msi_dup_record_field(record, 0); 174071bffdcdSAmine Khaldi INT rc = ACTION_DialogBox(package, dialog); 174171bffdcdSAmine Khaldi msi_free(dialog); 174271bffdcdSAmine Khaldi return rc; 174371bffdcdSAmine Khaldi } 174471bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONSTART: 174571bffdcdSAmine Khaldi { 174671bffdcdSAmine Khaldi LPWSTR deformatted; 174771bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 174871bffdcdSAmine Khaldi if (!uirow) return -1; 174971bffdcdSAmine Khaldi deformat_string(package, MSI_RecordGetString(record, 2), &deformatted); 175071bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, deformatted); 17510272139cSwinesync msi_event_fire(package, L"ActionText", uirow); 175271bffdcdSAmine Khaldi 175371bffdcdSAmine Khaldi msi_free(deformatted); 175471bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 175571bffdcdSAmine Khaldi return 1; 175671bffdcdSAmine Khaldi } 175771bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 175871bffdcdSAmine Khaldi { 175971bffdcdSAmine Khaldi MSIRECORD *uirow = MSI_CreateRecord(1); 176071bffdcdSAmine Khaldi if (!uirow) return -1; 176171bffdcdSAmine Khaldi MSI_RecordSetStringW(uirow, 1, message); 17620272139cSwinesync msi_event_fire(package, L"ActionData", uirow); 176371bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 176471bffdcdSAmine Khaldi 176571bffdcdSAmine Khaldi if (package->action_progress_increment) 176671bffdcdSAmine Khaldi { 176771bffdcdSAmine Khaldi uirow = MSI_CreateRecord(2); 176871bffdcdSAmine Khaldi if (!uirow) return -1; 176971bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 1, 2); 177071bffdcdSAmine Khaldi MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 17710272139cSwinesync msi_event_fire(package, L"SetProgress", uirow); 177271bffdcdSAmine Khaldi msiobj_release(&uirow->hdr); 177371bffdcdSAmine Khaldi } 177471bffdcdSAmine Khaldi return 1; 177571bffdcdSAmine Khaldi } 177671bffdcdSAmine Khaldi case INSTALLMESSAGE_PROGRESS: 17770272139cSwinesync msi_event_fire(package, L"SetProgress", record); 177871bffdcdSAmine Khaldi return 1; 177971bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 178071bffdcdSAmine Khaldi switch (MSI_RecordGetInteger(record, 1)) 178171bffdcdSAmine Khaldi { 178271bffdcdSAmine Khaldi case 0: 178371bffdcdSAmine Khaldi case 1: 178471bffdcdSAmine Khaldi /* do nothing */ 178571bffdcdSAmine Khaldi return 0; 178671bffdcdSAmine Khaldi default: 178771bffdcdSAmine Khaldi /* fall through */ 178871bffdcdSAmine Khaldi ; 178971bffdcdSAmine Khaldi } 179071bffdcdSAmine Khaldi default: 179171bffdcdSAmine Khaldi FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level); 179271bffdcdSAmine Khaldi return 0; 179371bffdcdSAmine Khaldi } 179471bffdcdSAmine Khaldi } 179571bffdcdSAmine Khaldi 179671bffdcdSAmine Khaldi static const struct 179771bffdcdSAmine Khaldi { 179871bffdcdSAmine Khaldi int id; 179971bffdcdSAmine Khaldi const WCHAR *text; 180071bffdcdSAmine Khaldi } 180171bffdcdSAmine Khaldi internal_errors[] = 180271bffdcdSAmine Khaldi { 18030272139cSwinesync {2726, L"DEBUG: Error [1]: Action not found: [2]"}, 180471bffdcdSAmine Khaldi {0} 180571bffdcdSAmine Khaldi }; 180671bffdcdSAmine Khaldi 180771bffdcdSAmine Khaldi static LPCWSTR get_internal_error_message(int error) 180871bffdcdSAmine Khaldi { 180971bffdcdSAmine Khaldi int i = 0; 181071bffdcdSAmine Khaldi 181171bffdcdSAmine Khaldi while (internal_errors[i].id != 0) 181271bffdcdSAmine Khaldi { 181371bffdcdSAmine Khaldi if (internal_errors[i].id == error) 181471bffdcdSAmine Khaldi return internal_errors[i].text; 181571bffdcdSAmine Khaldi i++; 181671bffdcdSAmine Khaldi } 181771bffdcdSAmine Khaldi 181871bffdcdSAmine Khaldi FIXME("missing error message %d\n", error); 181971bffdcdSAmine Khaldi return NULL; 182071bffdcdSAmine Khaldi } 182171bffdcdSAmine Khaldi 182271bffdcdSAmine Khaldi /* Returned string must be freed */ 182371bffdcdSAmine Khaldi LPWSTR msi_get_error_message(MSIDATABASE *db, int error) 182471bffdcdSAmine Khaldi { 182571bffdcdSAmine Khaldi MSIRECORD *record; 182671bffdcdSAmine Khaldi LPWSTR ret = NULL; 182771bffdcdSAmine Khaldi 18280272139cSwinesync if ((record = MSI_QueryGetRecord(db, L"SELECT `Message` FROM `Error` WHERE `Error` = %d", error))) 182971bffdcdSAmine Khaldi { 183071bffdcdSAmine Khaldi ret = msi_dup_record_field(record, 1); 183171bffdcdSAmine Khaldi msiobj_release(&record->hdr); 183271bffdcdSAmine Khaldi } 183371bffdcdSAmine Khaldi else if (error < 2000) 183471bffdcdSAmine Khaldi { 183571bffdcdSAmine Khaldi int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0); 183671bffdcdSAmine Khaldi if (len) 183771bffdcdSAmine Khaldi { 183871bffdcdSAmine Khaldi ret = msi_alloc((len + 1) * sizeof(WCHAR)); 183971bffdcdSAmine Khaldi LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1); 184071bffdcdSAmine Khaldi } 184171bffdcdSAmine Khaldi else 184271bffdcdSAmine Khaldi ret = NULL; 184371bffdcdSAmine Khaldi } 184471bffdcdSAmine Khaldi 184571bffdcdSAmine Khaldi return ret; 184671bffdcdSAmine Khaldi } 184771bffdcdSAmine Khaldi 184871bffdcdSAmine Khaldi INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record) 184971bffdcdSAmine Khaldi { 185071bffdcdSAmine Khaldi LPWSTR message = {0}; 1851f8b992f2SAmine Khaldi DWORD len; 1852f8b992f2SAmine Khaldi DWORD log_type = 1 << (eMessageType >> 24); 185371bffdcdSAmine Khaldi UINT res; 1854c2c66affSColin Finck INT rc = 0; 1855c2c66affSColin Finck char *msg; 1856c2c66affSColin Finck 1857c2c66affSColin Finck TRACE("%x\n", eMessageType); 185871bffdcdSAmine Khaldi if (TRACE_ON(msi)) dump_record(record); 1859c2c66affSColin Finck 186071bffdcdSAmine Khaldi if (!package || !record) 186171bffdcdSAmine Khaldi message = NULL; 186271bffdcdSAmine Khaldi else { 186371bffdcdSAmine Khaldi res = MSI_FormatRecordW(package, record, message, &len); 186471bffdcdSAmine Khaldi if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 186571bffdcdSAmine Khaldi return res; 186671bffdcdSAmine Khaldi len++; 1867c2c66affSColin Finck message = msi_alloc(len * sizeof(WCHAR)); 186871bffdcdSAmine Khaldi if (!message) return ERROR_OUTOFMEMORY; 186971bffdcdSAmine Khaldi MSI_FormatRecordW(package, record, message, &len); 1870c2c66affSColin Finck } 1871c2c66affSColin Finck 1872026a2db6Swinesync /* convert it to ANSI */ 1873c2c66affSColin Finck len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1874c2c66affSColin Finck msg = msi_alloc( len ); 1875c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1876c2c66affSColin Finck 187771bffdcdSAmine Khaldi if (gUIHandlerRecord && (gUIFilterRecord & log_type)) 1878c2c66affSColin Finck { 187971bffdcdSAmine Khaldi MSIHANDLE rec = alloc_msihandle(&record->hdr); 188002f995b2Swinesync TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, hRecord = %lu)\n", 188171bffdcdSAmine Khaldi gUIHandlerRecord, gUIContextRecord, eMessageType, rec ); 188271bffdcdSAmine Khaldi rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec ); 1883c2c66affSColin Finck MsiCloseHandle( rec ); 1884c2c66affSColin Finck } 188571bffdcdSAmine Khaldi if (!rc && gUIHandlerW && (gUIFilter & log_type)) 188671bffdcdSAmine Khaldi { 188702f995b2Swinesync TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n", 188871bffdcdSAmine Khaldi gUIHandlerW, gUIContext, eMessageType, debugstr_w(message) ); 188971bffdcdSAmine Khaldi rc = gUIHandlerW( gUIContext, eMessageType, message ); 189071bffdcdSAmine Khaldi } 189171bffdcdSAmine Khaldi else if (!rc && gUIHandlerA && (gUIFilter & log_type)) 189271bffdcdSAmine Khaldi { 189302f995b2Swinesync TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n", 189471bffdcdSAmine Khaldi gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg) ); 189571bffdcdSAmine Khaldi rc = gUIHandlerA( gUIContext, eMessageType, msg ); 189671bffdcdSAmine Khaldi } 1897c2c66affSColin Finck 189871bffdcdSAmine Khaldi if (!rc) 189971bffdcdSAmine Khaldi rc = internal_ui_handler(package, eMessageType, record, message); 190071bffdcdSAmine Khaldi 190171bffdcdSAmine Khaldi if (!rc && package && package->log_file != INVALID_HANDLE_VALUE && 1902c2c66affSColin Finck (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1903c2c66affSColin Finck { 1904c2c66affSColin Finck DWORD written; 1905c2c66affSColin Finck WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1906c2c66affSColin Finck WriteFile( package->log_file, "\n", 1, &written, NULL ); 1907c2c66affSColin Finck } 1908c2c66affSColin Finck msi_free( msg ); 1909c2c66affSColin Finck msi_free( message ); 1910c2c66affSColin Finck 191171bffdcdSAmine Khaldi return rc; 191271bffdcdSAmine Khaldi } 191371bffdcdSAmine Khaldi 191471bffdcdSAmine Khaldi INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 191571bffdcdSAmine Khaldi { 1916c2c66affSColin Finck switch (eMessageType & 0xff000000) 1917c2c66affSColin Finck { 191871bffdcdSAmine Khaldi case INSTALLMESSAGE_FATALEXIT: 191971bffdcdSAmine Khaldi case INSTALLMESSAGE_ERROR: 192071bffdcdSAmine Khaldi case INSTALLMESSAGE_WARNING: 192171bffdcdSAmine Khaldi case INSTALLMESSAGE_USER: 192271bffdcdSAmine Khaldi case INSTALLMESSAGE_INFO: 192371bffdcdSAmine Khaldi case INSTALLMESSAGE_OUTOFDISKSPACE: 192471bffdcdSAmine Khaldi if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) 1925c2c66affSColin Finck { 192671bffdcdSAmine Khaldi /* error message */ 192771bffdcdSAmine Khaldi 192871bffdcdSAmine Khaldi LPWSTR template; 192971bffdcdSAmine Khaldi LPWSTR template_rec = NULL, template_prefix = NULL; 193071bffdcdSAmine Khaldi int error = MSI_RecordGetInteger(record, 1); 193171bffdcdSAmine Khaldi 193271bffdcdSAmine Khaldi if (MSI_RecordIsNull(record, 0)) 193371bffdcdSAmine Khaldi { 193471bffdcdSAmine Khaldi if (error >= 32) 193571bffdcdSAmine Khaldi { 193671bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, error); 193771bffdcdSAmine Khaldi 193871bffdcdSAmine Khaldi if (!template_rec && error >= 2000) 193971bffdcdSAmine Khaldi { 194071bffdcdSAmine Khaldi /* internal error, not localized */ 194171bffdcdSAmine Khaldi if ((template_rec = (LPWSTR) get_internal_error_message(error))) 194271bffdcdSAmine Khaldi { 194371bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 194471bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record); 194571bffdcdSAmine Khaldi } 194671bffdcdSAmine Khaldi template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR); 194771bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_rec); 194871bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 194971bffdcdSAmine Khaldi msi_free(template_rec); 195071bffdcdSAmine Khaldi return 0; 195171bffdcdSAmine Khaldi } 195271bffdcdSAmine Khaldi } 195371bffdcdSAmine Khaldi } 195471bffdcdSAmine Khaldi else 195571bffdcdSAmine Khaldi template_rec = msi_dup_record_field(record, 0); 195671bffdcdSAmine Khaldi 195771bffdcdSAmine Khaldi template_prefix = msi_get_error_message(package->db, eMessageType >> 24); 19580272139cSwinesync if (!template_prefix) template_prefix = strdupW(L""); 195971bffdcdSAmine Khaldi 196071bffdcdSAmine Khaldi if (!template_rec) 196171bffdcdSAmine Khaldi { 196271bffdcdSAmine Khaldi /* always returns 0 */ 196371bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template_prefix); 196471bffdcdSAmine Khaldi MSI_ProcessMessageVerbatim(package, eMessageType, record); 196571bffdcdSAmine Khaldi msi_free(template_prefix); 196671bffdcdSAmine Khaldi return 0; 196771bffdcdSAmine Khaldi } 196871bffdcdSAmine Khaldi 1969958f1addSwinesync template = msi_alloc((lstrlenW(template_rec) + lstrlenW(template_prefix) + 1) * sizeof(WCHAR)); 197071bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 197171bffdcdSAmine Khaldi 1972958f1addSwinesync lstrcpyW(template, template_prefix); 1973958f1addSwinesync lstrcatW(template, template_rec); 197471bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 197571bffdcdSAmine Khaldi 197671bffdcdSAmine Khaldi msi_free(template_prefix); 197771bffdcdSAmine Khaldi msi_free(template_rec); 197871bffdcdSAmine Khaldi msi_free(template); 1979c2c66affSColin Finck } 1980c2c66affSColin Finck break; 1981c2c66affSColin Finck case INSTALLMESSAGE_ACTIONSTART: 198271bffdcdSAmine Khaldi { 198371bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART); 198471bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 198571bffdcdSAmine Khaldi msi_free(template); 1986c2c66affSColin Finck 198771bffdcdSAmine Khaldi msi_free(package->LastAction); 198871bffdcdSAmine Khaldi msi_free(package->LastActionTemplate); 198971bffdcdSAmine Khaldi package->LastAction = msi_dup_record_field(record, 1); 19900272139cSwinesync if (!package->LastAction) package->LastAction = strdupW(L""); 199171bffdcdSAmine Khaldi package->LastActionTemplate = msi_dup_record_field(record, 3); 1992c2c66affSColin Finck break; 199371bffdcdSAmine Khaldi } 199471bffdcdSAmine Khaldi case INSTALLMESSAGE_ACTIONDATA: 199571bffdcdSAmine Khaldi if (package->LastAction && package->LastActionTemplate) 199671bffdcdSAmine Khaldi { 1997958f1addSwinesync size_t len = lstrlenW(package->LastAction) + lstrlenW(package->LastActionTemplate) + 7; 1998958f1addSwinesync WCHAR *template = msi_alloc(len * sizeof(WCHAR)); 199971bffdcdSAmine Khaldi if (!template) return ERROR_OUTOFMEMORY; 20000272139cSwinesync swprintf(template, len, L"{{%s: }}%s", package->LastAction, package->LastActionTemplate); 200171bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 200271bffdcdSAmine Khaldi msi_free(template); 200371bffdcdSAmine Khaldi } 200471bffdcdSAmine Khaldi break; 200571bffdcdSAmine Khaldi case INSTALLMESSAGE_COMMONDATA: 200671bffdcdSAmine Khaldi { 200771bffdcdSAmine Khaldi WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA); 200871bffdcdSAmine Khaldi MSI_RecordSetStringW(record, 0, template); 200971bffdcdSAmine Khaldi msi_free(template); 201071bffdcdSAmine Khaldi } 2011c2c66affSColin Finck break; 2012c2c66affSColin Finck } 2013c2c66affSColin Finck 201471bffdcdSAmine Khaldi return MSI_ProcessMessageVerbatim(package, eMessageType, record); 2015c2c66affSColin Finck } 2016c2c66affSColin Finck 2017c2c66affSColin Finck INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, 2018c2c66affSColin Finck MSIHANDLE hRecord) 2019c2c66affSColin Finck { 2020c2c66affSColin Finck UINT ret = ERROR_INVALID_HANDLE; 2021c2c66affSColin Finck MSIPACKAGE *package = NULL; 2022c2c66affSColin Finck MSIRECORD *record = NULL; 2023c2c66affSColin Finck 202471bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE || 202571bffdcdSAmine Khaldi (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE) 202671bffdcdSAmine Khaldi return -1; 202771bffdcdSAmine Khaldi 202871bffdcdSAmine Khaldi if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA && 202971bffdcdSAmine Khaldi MsiRecordGetInteger(hRecord, 1) != 2) 203071bffdcdSAmine Khaldi return -1; 203171bffdcdSAmine Khaldi 20322e19edd6Swinesync record = msihandle2msiinfo(hRecord, MSIHANDLETYPE_RECORD); 20332e19edd6Swinesync if (!record) 20342e19edd6Swinesync return ERROR_INVALID_HANDLE; 20352e19edd6Swinesync 2036c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 2037c2c66affSColin Finck if( !package ) 2038c2c66affSColin Finck { 2039b74b77aaSwinesync MSIHANDLE remote; 2040c2c66affSColin Finck 2041b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2042c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2043c2c66affSColin Finck 20442a9ae858Swinesync __TRY 20452a9ae858Swinesync { 20462e19edd6Swinesync ret = remote_ProcessMessage(remote, eMessageType, (struct wire_record *)&record->count); 20472a9ae858Swinesync } 20482a9ae858Swinesync __EXCEPT(rpc_filter) 20492a9ae858Swinesync { 20502a9ae858Swinesync ret = GetExceptionCode(); 20512a9ae858Swinesync } 20522a9ae858Swinesync __ENDTRY 2053c2c66affSColin Finck 20542e19edd6Swinesync msiobj_release(&record->hdr); 20552e19edd6Swinesync return ret; 2056c2c66affSColin Finck } 2057c2c66affSColin Finck 2058c2c66affSColin Finck ret = MSI_ProcessMessage( package, eMessageType, record ); 2059c2c66affSColin Finck 2060eab017d1Swinesync msiobj_release( &record->hdr ); 2061c2c66affSColin Finck msiobj_release( &package->hdr ); 2062c2c66affSColin Finck return ret; 2063c2c66affSColin Finck } 2064c2c66affSColin Finck 2065c2c66affSColin Finck /* property code */ 2066c2c66affSColin Finck 2067c2c66affSColin Finck UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) 2068c2c66affSColin Finck { 2069c2c66affSColin Finck LPWSTR szwName = NULL, szwValue = NULL; 2070c2c66affSColin Finck UINT r = ERROR_OUTOFMEMORY; 2071c2c66affSColin Finck 2072c2c66affSColin Finck szwName = strdupAtoW( szName ); 2073c2c66affSColin Finck if( szName && !szwName ) 2074c2c66affSColin Finck goto end; 2075c2c66affSColin Finck 2076c2c66affSColin Finck szwValue = strdupAtoW( szValue ); 2077c2c66affSColin Finck if( szValue && !szwValue ) 2078c2c66affSColin Finck goto end; 2079c2c66affSColin Finck 2080c2c66affSColin Finck r = MsiSetPropertyW( hInstall, szwName, szwValue); 2081c2c66affSColin Finck 2082c2c66affSColin Finck end: 2083c2c66affSColin Finck msi_free( szwName ); 2084c2c66affSColin Finck msi_free( szwValue ); 2085c2c66affSColin Finck 2086c2c66affSColin Finck return r; 2087c2c66affSColin Finck } 2088c2c66affSColin Finck 20890922e524Swinesync void msi_reset_source_folders( MSIPACKAGE *package ) 2090c2c66affSColin Finck { 2091c2c66affSColin Finck MSIFOLDER *folder; 2092c2c66affSColin Finck 2093c2c66affSColin Finck LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) 2094c2c66affSColin Finck { 2095c2c66affSColin Finck msi_free( folder->ResolvedSource ); 2096c2c66affSColin Finck folder->ResolvedSource = NULL; 2097c2c66affSColin Finck } 2098c2c66affSColin Finck } 2099c2c66affSColin Finck 2100c2c66affSColin Finck UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) 2101c2c66affSColin Finck { 2102c2c66affSColin Finck MSIQUERY *view; 2103c2c66affSColin Finck MSIRECORD *row = NULL; 2104c2c66affSColin Finck DWORD sz = 0; 2105c2c66affSColin Finck WCHAR query[1024]; 2106c2c66affSColin Finck UINT rc; 2107c2c66affSColin Finck 2108c2c66affSColin Finck TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); 2109c2c66affSColin Finck 2110c2c66affSColin Finck if (!name) 2111c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 2112c2c66affSColin Finck 2113c2c66affSColin Finck /* this one is weird... */ 2114c2c66affSColin Finck if (!name[0]) 2115c2c66affSColin Finck return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; 2116c2c66affSColin Finck 2117958f1addSwinesync if (value && len < 0) len = lstrlenW( value ); 2118c2c66affSColin Finck 2119c2c66affSColin Finck rc = msi_get_property( db, name, 0, &sz ); 2120c2c66affSColin Finck if (!value || (!*value && !len)) 2121c2c66affSColin Finck { 21220272139cSwinesync swprintf( query, ARRAY_SIZE(query), L"DELETE FROM `_Property` WHERE `_Property` = '%s'", name ); 2123c2c66affSColin Finck } 2124c2c66affSColin Finck else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) 2125c2c66affSColin Finck { 21260272139cSwinesync swprintf( query, ARRAY_SIZE(query), L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = '%s'", name ); 2127c2c66affSColin Finck row = MSI_CreateRecord(1); 2128c2c66affSColin Finck msi_record_set_string( row, 1, value, len ); 2129c2c66affSColin Finck } 2130c2c66affSColin Finck else 2131c2c66affSColin Finck { 21320272139cSwinesync lstrcpyW( query, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)" ); 2133c2c66affSColin Finck row = MSI_CreateRecord(2); 2134c2c66affSColin Finck msi_record_set_string( row, 1, name, -1 ); 2135c2c66affSColin Finck msi_record_set_string( row, 2, value, len ); 2136c2c66affSColin Finck } 2137c2c66affSColin Finck 2138c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(db, query, &view); 2139c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2140c2c66affSColin Finck { 2141c2c66affSColin Finck rc = MSI_ViewExecute(view, row); 2142c2c66affSColin Finck MSI_ViewClose(view); 2143c2c66affSColin Finck msiobj_release(&view->hdr); 2144c2c66affSColin Finck } 2145c2c66affSColin Finck if (row) msiobj_release(&row->hdr); 2146c2c66affSColin Finck return rc; 2147c2c66affSColin Finck } 2148c2c66affSColin Finck 2149c2c66affSColin Finck UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) 2150c2c66affSColin Finck { 2151c2c66affSColin Finck MSIPACKAGE *package; 2152c2c66affSColin Finck UINT ret; 2153c2c66affSColin Finck 2154c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 2155c2c66affSColin Finck if( !package ) 2156c2c66affSColin Finck { 2157b74b77aaSwinesync MSIHANDLE remote; 2158c2c66affSColin Finck 2159b74b77aaSwinesync if (!(remote = msi_get_remote(hInstall))) 2160c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2161c2c66affSColin Finck 21622a9ae858Swinesync __TRY 21632a9ae858Swinesync { 21642a9ae858Swinesync ret = remote_SetProperty(remote, szName, szValue); 21652a9ae858Swinesync } 21662a9ae858Swinesync __EXCEPT(rpc_filter) 21672a9ae858Swinesync { 21682a9ae858Swinesync ret = GetExceptionCode(); 21692a9ae858Swinesync } 21702a9ae858Swinesync __ENDTRY 21712a9ae858Swinesync 21722a9ae858Swinesync return ret; 2173c2c66affSColin Finck } 2174c2c66affSColin Finck 2175c2c66affSColin Finck ret = msi_set_property( package->db, szName, szValue, -1 ); 21760272139cSwinesync if (ret == ERROR_SUCCESS && !wcscmp( szName, L"SourceDir" )) 21770922e524Swinesync msi_reset_source_folders( package ); 2178c2c66affSColin Finck 2179c2c66affSColin Finck msiobj_release( &package->hdr ); 2180c2c66affSColin Finck return ret; 2181c2c66affSColin Finck } 2182c2c66affSColin Finck 2183c2c66affSColin Finck static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) 2184c2c66affSColin Finck { 2185c2c66affSColin Finck MSIRECORD *rec, *row = NULL; 2186c2c66affSColin Finck MSIQUERY *view; 2187c2c66affSColin Finck UINT r; 218871bffdcdSAmine Khaldi WCHAR *buffer; 218971bffdcdSAmine Khaldi int length; 219071bffdcdSAmine Khaldi 2191c2c66affSColin Finck if (!name || !*name) 2192c2c66affSColin Finck return NULL; 2193c2c66affSColin Finck 21940272139cSwinesync if (!wcscmp(name, L"Date")) 219571bffdcdSAmine Khaldi { 219671bffdcdSAmine Khaldi length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0); 219771bffdcdSAmine Khaldi if (!length) 219871bffdcdSAmine Khaldi return NULL; 219971bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2200fec16ab0SAmine Khaldi GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length); 220171bffdcdSAmine Khaldi 220271bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 220371bffdcdSAmine Khaldi if (!row) 2204f8b992f2SAmine Khaldi { 2205f8b992f2SAmine Khaldi msi_free(buffer); 220671bffdcdSAmine Khaldi return NULL; 2207f8b992f2SAmine Khaldi } 220871bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 220971bffdcdSAmine Khaldi msi_free(buffer); 221071bffdcdSAmine Khaldi return row; 221171bffdcdSAmine Khaldi } 22120272139cSwinesync else if (!wcscmp(name, L"Time")) 221371bffdcdSAmine Khaldi { 221471bffdcdSAmine Khaldi length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0); 221571bffdcdSAmine Khaldi if (!length) 221671bffdcdSAmine Khaldi return NULL; 221771bffdcdSAmine Khaldi buffer = msi_alloc(length * sizeof(WCHAR)); 2218fec16ab0SAmine Khaldi GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length); 221971bffdcdSAmine Khaldi 222071bffdcdSAmine Khaldi row = MSI_CreateRecord(1); 222171bffdcdSAmine Khaldi if (!row) 2222f8b992f2SAmine Khaldi { 2223f8b992f2SAmine Khaldi msi_free(buffer); 222471bffdcdSAmine Khaldi return NULL; 2225f8b992f2SAmine Khaldi } 222671bffdcdSAmine Khaldi MSI_RecordSetStringW(row, 1, buffer); 222771bffdcdSAmine Khaldi msi_free(buffer); 222871bffdcdSAmine Khaldi return row; 222971bffdcdSAmine Khaldi } 223071bffdcdSAmine Khaldi 2231c2c66affSColin Finck rec = MSI_CreateRecord(1); 2232c2c66affSColin Finck if (!rec) 2233c2c66affSColin Finck return NULL; 2234c2c66affSColin Finck 2235c2c66affSColin Finck MSI_RecordSetStringW(rec, 1, name); 2236c2c66affSColin Finck 22370272139cSwinesync r = MSI_DatabaseOpenViewW(db, L"SELECT `Value` FROM `_Property` WHERE `_Property`=?", &view); 2238c2c66affSColin Finck if (r == ERROR_SUCCESS) 2239c2c66affSColin Finck { 2240c2c66affSColin Finck MSI_ViewExecute(view, rec); 2241c2c66affSColin Finck MSI_ViewFetch(view, &row); 2242c2c66affSColin Finck MSI_ViewClose(view); 2243c2c66affSColin Finck msiobj_release(&view->hdr); 2244c2c66affSColin Finck } 2245c2c66affSColin Finck msiobj_release(&rec->hdr); 2246c2c66affSColin Finck return row; 2247c2c66affSColin Finck } 2248c2c66affSColin Finck 2249c2c66affSColin Finck /* internal function, not compatible with MsiGetPropertyW */ 2250c2c66affSColin Finck UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, 2251c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2252c2c66affSColin Finck { 2253c2c66affSColin Finck MSIRECORD *row; 2254c2c66affSColin Finck UINT rc = ERROR_FUNCTION_FAILED; 2255c2c66affSColin Finck 2256c2c66affSColin Finck TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf); 2257c2c66affSColin Finck 2258c2c66affSColin Finck row = msi_get_property_row( db, szName ); 2259c2c66affSColin Finck 2260c2c66affSColin Finck if (*pchValueBuf > 0) 2261c2c66affSColin Finck szValueBuf[0] = 0; 2262c2c66affSColin Finck 2263c2c66affSColin Finck if (row) 2264c2c66affSColin Finck { 2265c2c66affSColin Finck rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); 2266c2c66affSColin Finck msiobj_release(&row->hdr); 2267c2c66affSColin Finck } 2268c2c66affSColin Finck 2269c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2270c2c66affSColin Finck TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), 2271c2c66affSColin Finck debugstr_w(szName)); 2272c2c66affSColin Finck else if (rc == ERROR_MORE_DATA) 227302f995b2Swinesync TRACE( "need %lu sized buffer for %s\n", *pchValueBuf, debugstr_w(szName) ); 2274c2c66affSColin Finck else 2275c2c66affSColin Finck { 2276c2c66affSColin Finck *pchValueBuf = 0; 2277c2c66affSColin Finck TRACE("property %s not found\n", debugstr_w(szName)); 2278c2c66affSColin Finck } 2279c2c66affSColin Finck 2280c2c66affSColin Finck return rc; 2281c2c66affSColin Finck } 2282c2c66affSColin Finck 2283c2c66affSColin Finck LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2284c2c66affSColin Finck { 2285c2c66affSColin Finck DWORD sz = 0; 2286c2c66affSColin Finck LPWSTR str; 2287c2c66affSColin Finck UINT r; 2288c2c66affSColin Finck 2289c2c66affSColin Finck r = msi_get_property(db, prop, NULL, &sz); 2290c2c66affSColin Finck if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2291c2c66affSColin Finck return NULL; 2292c2c66affSColin Finck 2293c2c66affSColin Finck sz++; 2294c2c66affSColin Finck str = msi_alloc(sz * sizeof(WCHAR)); 2295c2c66affSColin Finck r = msi_get_property(db, prop, str, &sz); 2296c2c66affSColin Finck if (r != ERROR_SUCCESS) 2297c2c66affSColin Finck { 2298c2c66affSColin Finck msi_free(str); 2299c2c66affSColin Finck str = NULL; 2300c2c66affSColin Finck } 2301c2c66affSColin Finck 2302c2c66affSColin Finck return str; 2303c2c66affSColin Finck } 2304c2c66affSColin Finck 2305c2c66affSColin Finck int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2306c2c66affSColin Finck { 2307c2c66affSColin Finck LPWSTR str = msi_dup_property( db, prop ); 2308958f1addSwinesync int val = str ? wcstol(str, NULL, 10) : def; 2309c2c66affSColin Finck msi_free(str); 2310c2c66affSColin Finck return val; 2311c2c66affSColin Finck } 2312c2c66affSColin Finck 2313e12fb503Swinesync UINT WINAPI MsiGetPropertyA(MSIHANDLE hinst, const char *name, char *buf, DWORD *sz) 2314c2c66affSColin Finck { 23150272139cSwinesync const WCHAR *value = L""; 2316e12fb503Swinesync MSIPACKAGE *package; 23174748b312Swinesync MSIRECORD *row; 2318e12fb503Swinesync WCHAR *nameW; 23194748b312Swinesync int len = 0; 2320c2c66affSColin Finck UINT r; 2321c2c66affSColin Finck 2322e12fb503Swinesync if (!name) 2323e12fb503Swinesync return ERROR_INVALID_PARAMETER; 2324c2c66affSColin Finck 2325e12fb503Swinesync if (!(nameW = strdupAtoW(name))) 2326c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2327c2c66affSColin Finck 2328e12fb503Swinesync package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE); 2329e12fb503Swinesync if (!package) 2330e12fb503Swinesync { 2331e12fb503Swinesync WCHAR *value = NULL, *tmp; 2332e12fb503Swinesync MSIHANDLE remote; 2333e12fb503Swinesync DWORD len; 2334e12fb503Swinesync 2335e12fb503Swinesync if (!(remote = msi_get_remote(hinst))) 233602726bbcSwinesync { 23371b18dc22Swinesync free(nameW); 2338e12fb503Swinesync return ERROR_INVALID_HANDLE; 233902726bbcSwinesync } 2340e12fb503Swinesync 23412a9ae858Swinesync __TRY 23422a9ae858Swinesync { 2343e12fb503Swinesync r = remote_GetProperty(remote, nameW, &value, &len); 23442a9ae858Swinesync } 23452a9ae858Swinesync __EXCEPT(rpc_filter) 23462a9ae858Swinesync { 23472a9ae858Swinesync r = GetExceptionCode(); 23482a9ae858Swinesync } 23492a9ae858Swinesync __ENDTRY 23502a9ae858Swinesync 23511b18dc22Swinesync free(nameW); 235202726bbcSwinesync 2353e12fb503Swinesync if (!r) 2354e12fb503Swinesync { 2355e12fb503Swinesync /* String might contain embedded nulls. 2356e12fb503Swinesync * Native returns the correct size but truncates the string. */ 23571b18dc22Swinesync tmp = calloc(1, (len + 1) * sizeof(WCHAR)); 2358e12fb503Swinesync if (!tmp) 2359e12fb503Swinesync { 2360e12fb503Swinesync midl_user_free(value); 2361e12fb503Swinesync return ERROR_OUTOFMEMORY; 2362e12fb503Swinesync } 2363958f1addSwinesync lstrcpyW(tmp, value); 2364e12fb503Swinesync 2365e12fb503Swinesync r = msi_strncpyWtoA(tmp, len, buf, sz, TRUE); 2366e12fb503Swinesync 23671b18dc22Swinesync free(tmp); 2368e12fb503Swinesync } 2369e12fb503Swinesync midl_user_free(value); 2370e12fb503Swinesync return r; 2371e12fb503Swinesync } 2372e12fb503Swinesync 23734748b312Swinesync row = msi_get_property_row(package->db, nameW); 23744748b312Swinesync if (row) 23754748b312Swinesync value = msi_record_get_string(row, 1, &len); 2376e12fb503Swinesync 23774748b312Swinesync r = msi_strncpyWtoA(value, len, buf, sz, FALSE); 2378e12fb503Swinesync 23791b18dc22Swinesync free(nameW); 23804748b312Swinesync if (row) msiobj_release(&row->hdr); 2381e12fb503Swinesync msiobj_release(&package->hdr); 2382c2c66affSColin Finck return r; 2383c2c66affSColin Finck } 2384c2c66affSColin Finck 23854748b312Swinesync UINT WINAPI MsiGetPropertyW(MSIHANDLE hinst, const WCHAR *name, WCHAR *buf, DWORD *sz) 2386c2c66affSColin Finck { 23870272139cSwinesync const WCHAR *value = L""; 23884748b312Swinesync MSIPACKAGE *package; 23894748b312Swinesync MSIRECORD *row; 23904748b312Swinesync int len = 0; 23914748b312Swinesync UINT r; 2392c2c66affSColin Finck 23934748b312Swinesync if (!name) 23944748b312Swinesync return ERROR_INVALID_PARAMETER; 2395c2c66affSColin Finck 23964748b312Swinesync package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE); 23974748b312Swinesync if (!package) 23984748b312Swinesync { 23994748b312Swinesync WCHAR *value = NULL, *tmp; 24004748b312Swinesync MSIHANDLE remote; 24014748b312Swinesync DWORD len; 24024748b312Swinesync 24034748b312Swinesync if (!(remote = msi_get_remote(hinst))) 24044748b312Swinesync return ERROR_INVALID_HANDLE; 24054748b312Swinesync 24062a9ae858Swinesync __TRY 24072a9ae858Swinesync { 24084748b312Swinesync r = remote_GetProperty(remote, name, &value, &len); 24092a9ae858Swinesync } 24102a9ae858Swinesync __EXCEPT(rpc_filter) 24112a9ae858Swinesync { 24122a9ae858Swinesync r = GetExceptionCode(); 24132a9ae858Swinesync } 24142a9ae858Swinesync __ENDTRY 24152a9ae858Swinesync 24164748b312Swinesync if (!r) 24174748b312Swinesync { 24184748b312Swinesync /* String might contain embedded nulls. 24194748b312Swinesync * Native returns the correct size but truncates the string. */ 24201b18dc22Swinesync tmp = calloc(1, (len + 1) * sizeof(WCHAR)); 24214748b312Swinesync if (!tmp) 24224748b312Swinesync { 24234748b312Swinesync midl_user_free(value); 24244748b312Swinesync return ERROR_OUTOFMEMORY; 24254748b312Swinesync } 2426958f1addSwinesync lstrcpyW(tmp, value); 24274748b312Swinesync 24284748b312Swinesync r = msi_strncpyW(tmp, len, buf, sz); 24294748b312Swinesync 24301b18dc22Swinesync free(tmp); 24314748b312Swinesync } 24324748b312Swinesync midl_user_free(value); 24334748b312Swinesync return r; 24344748b312Swinesync } 24354748b312Swinesync 24364748b312Swinesync row = msi_get_property_row(package->db, name); 24374748b312Swinesync if (row) 24384748b312Swinesync value = msi_record_get_string(row, 1, &len); 24394748b312Swinesync 24404748b312Swinesync r = msi_strncpyW(value, len, buf, sz); 24414748b312Swinesync 24424748b312Swinesync if (row) msiobj_release(&row->hdr); 24434748b312Swinesync msiobj_release(&package->hdr); 24444748b312Swinesync return r; 2445c2c66affSColin Finck } 2446c2c66affSColin Finck 2447a8bc3902Swinesync MSIHANDLE __cdecl s_remote_GetActiveDatabase(MSIHANDLE hinst) 2448b74b77aaSwinesync { 24497cc54a4fSwinesync return MsiGetActiveDatabase(hinst); 2450c2c66affSColin Finck } 2451c2c66affSColin Finck 2452a8bc3902Swinesync UINT __cdecl s_remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size) 2453c2c66affSColin Finck { 245462ababd7Swinesync WCHAR empty[1]; 245562ababd7Swinesync UINT r; 245662ababd7Swinesync 245762ababd7Swinesync *size = 0; 245862ababd7Swinesync r = MsiGetPropertyW(hinst, property, empty, size); 245962ababd7Swinesync if (r == ERROR_MORE_DATA) 246062ababd7Swinesync { 246162ababd7Swinesync ++*size; 246262ababd7Swinesync *value = midl_user_allocate(*size * sizeof(WCHAR)); 246362ababd7Swinesync if (!*value) 246462ababd7Swinesync return ERROR_OUTOFMEMORY; 246562ababd7Swinesync r = MsiGetPropertyW(hinst, property, *value, size); 246662ababd7Swinesync } 246762ababd7Swinesync return r; 2468c2c66affSColin Finck } 2469c2c66affSColin Finck 2470a8bc3902Swinesync UINT __cdecl s_remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value) 2471c2c66affSColin Finck { 24723431091cSwinesync return MsiSetPropertyW(hinst, property, value); 2473c2c66affSColin Finck } 2474c2c66affSColin Finck 2475a8bc3902Swinesync int __cdecl s_remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, struct wire_record *remote_rec) 2476c2c66affSColin Finck { 24772e19edd6Swinesync MSIHANDLE rec; 24782e19edd6Swinesync int ret; 24792e19edd6Swinesync UINT r; 24802e19edd6Swinesync 24812e19edd6Swinesync if ((r = unmarshal_record(remote_rec, &rec))) 24822e19edd6Swinesync return r; 24832e19edd6Swinesync 24842e19edd6Swinesync ret = MsiProcessMessage(hinst, message, rec); 24852e19edd6Swinesync 24862e19edd6Swinesync MsiCloseHandle(rec); 24872e19edd6Swinesync return ret; 2488c2c66affSColin Finck } 2489c2c66affSColin Finck 2490a8bc3902Swinesync UINT __cdecl s_remote_DoAction(MSIHANDLE hinst, LPCWSTR action) 2491c2c66affSColin Finck { 2492c65c209aSwinesync return MsiDoActionW(hinst, action); 2493c2c66affSColin Finck } 2494c2c66affSColin Finck 2495a8bc3902Swinesync UINT __cdecl s_remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence) 2496c2c66affSColin Finck { 249710abb6f6Swinesync return MsiSequenceW(hinst, table, sequence); 2498c2c66affSColin Finck } 2499c2c66affSColin Finck 2500a8bc3902Swinesync UINT __cdecl s_remote_GetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2501c2c66affSColin Finck { 2502a529a627Swinesync WCHAR empty[1]; 2503a529a627Swinesync DWORD size = 0; 2504a529a627Swinesync UINT r; 2505a529a627Swinesync 2506a529a627Swinesync r = MsiGetTargetPathW(hinst, folder, empty, &size); 2507a529a627Swinesync if (r == ERROR_MORE_DATA) 2508a529a627Swinesync { 2509a529a627Swinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 2510a529a627Swinesync if (!*value) 2511a529a627Swinesync return ERROR_OUTOFMEMORY; 2512a529a627Swinesync r = MsiGetTargetPathW(hinst, folder, *value, &size); 2513a529a627Swinesync } 2514a529a627Swinesync return r; 2515c2c66affSColin Finck } 2516c2c66affSColin Finck 2517a8bc3902Swinesync UINT __cdecl s_remote_SetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPCWSTR value) 2518c2c66affSColin Finck { 2519a5e21001Swinesync return MsiSetTargetPathW(hinst, folder, value); 2520c2c66affSColin Finck } 2521c2c66affSColin Finck 2522a8bc3902Swinesync UINT __cdecl s_remote_GetSourcePath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2523c2c66affSColin Finck { 25244253f351Swinesync WCHAR empty[1]; 25254253f351Swinesync DWORD size = 1; 25264253f351Swinesync UINT r; 25274253f351Swinesync 25284253f351Swinesync r = MsiGetSourcePathW(hinst, folder, empty, &size); 25294253f351Swinesync if (r == ERROR_MORE_DATA) 25304253f351Swinesync { 25314253f351Swinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 25324253f351Swinesync if (!*value) 25334253f351Swinesync return ERROR_OUTOFMEMORY; 25344253f351Swinesync r = MsiGetSourcePathW(hinst, folder, *value, &size); 25354253f351Swinesync } 25364253f351Swinesync return r; 2537c2c66affSColin Finck } 2538c2c66affSColin Finck 2539a8bc3902Swinesync BOOL __cdecl s_remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode) 2540c2c66affSColin Finck { 254183bbe8c8Swinesync return MsiGetMode(hinst, mode); 2542c2c66affSColin Finck } 2543c2c66affSColin Finck 2544a8bc3902Swinesync UINT __cdecl s_remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state) 2545c2c66affSColin Finck { 25465219367eSwinesync return MsiSetMode(hinst, mode, state); 2547c2c66affSColin Finck } 2548c2c66affSColin Finck 2549a8bc3902Swinesync UINT __cdecl s_remote_GetFeatureState(MSIHANDLE hinst, LPCWSTR feature, 2550c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2551c2c66affSColin Finck { 2552ed5fbe39Swinesync return MsiGetFeatureStateW(hinst, feature, installed, action); 2553c2c66affSColin Finck } 2554c2c66affSColin Finck 2555a8bc3902Swinesync UINT __cdecl s_remote_SetFeatureState(MSIHANDLE hinst, LPCWSTR feature, INSTALLSTATE state) 2556c2c66affSColin Finck { 25575bbed507Swinesync return MsiSetFeatureStateW(hinst, feature, state); 2558c2c66affSColin Finck } 2559c2c66affSColin Finck 2560a8bc3902Swinesync UINT __cdecl s_remote_GetComponentState(MSIHANDLE hinst, LPCWSTR component, 2561c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action) 2562c2c66affSColin Finck { 2563709d0f5bSwinesync return MsiGetComponentStateW(hinst, component, installed, action); 2564c2c66affSColin Finck } 2565c2c66affSColin Finck 2566a8bc3902Swinesync UINT __cdecl s_remote_SetComponentState(MSIHANDLE hinst, LPCWSTR component, INSTALLSTATE state) 2567c2c66affSColin Finck { 25681c8fdff2Swinesync return MsiSetComponentStateW(hinst, component, state); 2569c2c66affSColin Finck } 2570c2c66affSColin Finck 2571a8bc3902Swinesync LANGID __cdecl s_remote_GetLanguage(MSIHANDLE hinst) 2572c2c66affSColin Finck { 2573fdca3090Swinesync return MsiGetLanguage(hinst); 2574c2c66affSColin Finck } 2575c2c66affSColin Finck 2576a8bc3902Swinesync UINT __cdecl s_remote_SetInstallLevel(MSIHANDLE hinst, int level) 2577c2c66affSColin Finck { 2578d20dc08fSwinesync return MsiSetInstallLevel(hinst, level); 2579c2c66affSColin Finck } 2580c2c66affSColin Finck 2581a8bc3902Swinesync UINT __cdecl s_remote_FormatRecord(MSIHANDLE hinst, struct wire_record *remote_rec, LPWSTR *value) 2582c2c66affSColin Finck { 2583cde5f24cSwinesync WCHAR empty[1]; 2584c2c66affSColin Finck DWORD size = 0; 2585cde5f24cSwinesync MSIHANDLE rec; 2586cde5f24cSwinesync UINT r; 2587cde5f24cSwinesync 2588cde5f24cSwinesync if ((r = unmarshal_record(remote_rec, &rec))) 2589cde5f24cSwinesync return r; 2590cde5f24cSwinesync 2591cde5f24cSwinesync r = MsiFormatRecordW(hinst, rec, empty, &size); 2592cde5f24cSwinesync if (r == ERROR_MORE_DATA) 2593c2c66affSColin Finck { 2594cde5f24cSwinesync *value = midl_user_allocate(++size * sizeof(WCHAR)); 2595c2c66affSColin Finck if (!*value) 2596eab017d1Swinesync { 2597eab017d1Swinesync MsiCloseHandle(rec); 2598cde5f24cSwinesync return ERROR_OUTOFMEMORY; 2599eab017d1Swinesync } 2600cde5f24cSwinesync r = MsiFormatRecordW(hinst, rec, *value, &size); 2601c2c66affSColin Finck } 2602cde5f24cSwinesync 2603cde5f24cSwinesync MsiCloseHandle(rec); 2604cde5f24cSwinesync return r; 2605c2c66affSColin Finck } 2606c2c66affSColin Finck 2607a8bc3902Swinesync MSICONDITION __cdecl s_remote_EvaluateCondition(MSIHANDLE hinst, LPCWSTR condition) 2608c2c66affSColin Finck { 260903faa107Swinesync return MsiEvaluateConditionW(hinst, condition); 2610c2c66affSColin Finck } 2611c2c66affSColin Finck 2612a8bc3902Swinesync UINT __cdecl s_remote_GetFeatureCost(MSIHANDLE hinst, LPCWSTR feature, 26139f3e4bbbSwinesync MSICOSTTREE cost_tree, INSTALLSTATE state, INT *cost) 2614c2c66affSColin Finck { 26159f3e4bbbSwinesync return MsiGetFeatureCostW(hinst, feature, cost_tree, state, cost); 2616c2c66affSColin Finck } 2617c2c66affSColin Finck 2618a8bc3902Swinesync UINT __cdecl s_remote_EnumComponentCosts(MSIHANDLE hinst, LPCWSTR component, 261939198134Swinesync DWORD index, INSTALLSTATE state, LPWSTR drive, INT *cost, INT *temp) 2620c2c66affSColin Finck { 262139198134Swinesync DWORD size = 3; 262239198134Swinesync return MsiEnumComponentCostsW(hinst, component, index, state, drive, &size, cost, temp); 2623c2c66affSColin Finck } 2624c2c66affSColin Finck 2625c2c66affSColin Finck UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2626c2c66affSColin Finck LPCWSTR property, LPWSTR value) 2627c2c66affSColin Finck { 2628c2c66affSColin Finck MSISOURCELISTINFO *info; 2629c2c66affSColin Finck 2630c2c66affSColin Finck LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2631c2c66affSColin Finck { 2632958f1addSwinesync if (!wcscmp( info->value, value )) return ERROR_SUCCESS; 2633c2c66affSColin Finck } 2634c2c66affSColin Finck 2635c2c66affSColin Finck info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2636c2c66affSColin Finck if (!info) 2637c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2638c2c66affSColin Finck 2639c2c66affSColin Finck info->context = context; 2640c2c66affSColin Finck info->options = options; 2641c2c66affSColin Finck info->property = property; 2642c2c66affSColin Finck info->value = strdupW(value); 2643c2c66affSColin Finck list_add_head(&package->sourcelist_info, &info->entry); 2644c2c66affSColin Finck 2645c2c66affSColin Finck return ERROR_SUCCESS; 2646c2c66affSColin Finck } 2647c2c66affSColin Finck 2648c2c66affSColin Finck UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2649c2c66affSColin Finck DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2650c2c66affSColin Finck { 2651c2c66affSColin Finck MSIMEDIADISK *disk; 2652c2c66affSColin Finck 2653c2c66affSColin Finck LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2654c2c66affSColin Finck { 2655c2c66affSColin Finck if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2656c2c66affSColin Finck } 2657c2c66affSColin Finck 2658c2c66affSColin Finck disk = msi_alloc(sizeof(MSIMEDIADISK)); 2659c2c66affSColin Finck if (!disk) 2660c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2661c2c66affSColin Finck 2662c2c66affSColin Finck disk->context = context; 2663c2c66affSColin Finck disk->options = options; 2664c2c66affSColin Finck disk->disk_id = disk_id; 2665c2c66affSColin Finck disk->volume_label = strdupW(volume_label); 2666c2c66affSColin Finck disk->disk_prompt = strdupW(disk_prompt); 2667c2c66affSColin Finck list_add_head(&package->sourcelist_media, &disk->entry); 2668c2c66affSColin Finck 2669c2c66affSColin Finck return ERROR_SUCCESS; 2670c2c66affSColin Finck } 2671