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