1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * Implementation of the Microsoft Installer (msi.dll) 3*c2c66affSColin Finck * 4*c2c66affSColin Finck * Copyright 2004 Aric Stewart for CodeWeavers 5*c2c66affSColin Finck * 6*c2c66affSColin Finck * This library is free software; you can redistribute it and/or 7*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 8*c2c66affSColin Finck * License as published by the Free Software Foundation; either 9*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 10*c2c66affSColin Finck * 11*c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 12*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*c2c66affSColin Finck * Lesser General Public License for more details. 15*c2c66affSColin Finck * 16*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 17*c2c66affSColin Finck * License along with this library; if not, write to the Free Software 18*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19*c2c66affSColin Finck */ 20*c2c66affSColin Finck 21*c2c66affSColin Finck #include "msipriv.h" 22*c2c66affSColin Finck 23*c2c66affSColin Finck #include <wininet.h> 24*c2c66affSColin Finck 25*c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi); 26*c2c66affSColin Finck 27*c2c66affSColin Finck static void free_feature( MSIFEATURE *feature ) 28*c2c66affSColin Finck { 29*c2c66affSColin Finck struct list *item, *cursor; 30*c2c66affSColin Finck 31*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Children ) 32*c2c66affSColin Finck { 33*c2c66affSColin Finck FeatureList *fl = LIST_ENTRY( item, FeatureList, entry ); 34*c2c66affSColin Finck list_remove( &fl->entry ); 35*c2c66affSColin Finck msi_free( fl ); 36*c2c66affSColin Finck } 37*c2c66affSColin Finck 38*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) 39*c2c66affSColin Finck { 40*c2c66affSColin Finck ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); 41*c2c66affSColin Finck list_remove( &cl->entry ); 42*c2c66affSColin Finck msi_free( cl ); 43*c2c66affSColin Finck } 44*c2c66affSColin Finck msi_free( feature->Feature ); 45*c2c66affSColin Finck msi_free( feature->Feature_Parent ); 46*c2c66affSColin Finck msi_free( feature->Directory ); 47*c2c66affSColin Finck msi_free( feature->Description ); 48*c2c66affSColin Finck msi_free( feature->Title ); 49*c2c66affSColin Finck msi_free( feature ); 50*c2c66affSColin Finck } 51*c2c66affSColin Finck 52*c2c66affSColin Finck static void free_folder( MSIFOLDER *folder ) 53*c2c66affSColin Finck { 54*c2c66affSColin Finck struct list *item, *cursor; 55*c2c66affSColin Finck 56*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &folder->children ) 57*c2c66affSColin Finck { 58*c2c66affSColin Finck FolderList *fl = LIST_ENTRY( item, FolderList, entry ); 59*c2c66affSColin Finck list_remove( &fl->entry ); 60*c2c66affSColin Finck msi_free( fl ); 61*c2c66affSColin Finck } 62*c2c66affSColin Finck msi_free( folder->Parent ); 63*c2c66affSColin Finck msi_free( folder->Directory ); 64*c2c66affSColin Finck msi_free( folder->TargetDefault ); 65*c2c66affSColin Finck msi_free( folder->SourceLongPath ); 66*c2c66affSColin Finck msi_free( folder->SourceShortPath ); 67*c2c66affSColin Finck msi_free( folder->ResolvedTarget ); 68*c2c66affSColin Finck msi_free( folder->ResolvedSource ); 69*c2c66affSColin Finck msi_free( folder ); 70*c2c66affSColin Finck } 71*c2c66affSColin Finck 72*c2c66affSColin Finck static void free_extension( MSIEXTENSION *ext ) 73*c2c66affSColin Finck { 74*c2c66affSColin Finck struct list *item, *cursor; 75*c2c66affSColin Finck 76*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs ) 77*c2c66affSColin Finck { 78*c2c66affSColin Finck MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry ); 79*c2c66affSColin Finck 80*c2c66affSColin Finck list_remove( &verb->entry ); 81*c2c66affSColin Finck msi_free( verb->Verb ); 82*c2c66affSColin Finck msi_free( verb->Command ); 83*c2c66affSColin Finck msi_free( verb->Argument ); 84*c2c66affSColin Finck msi_free( verb ); 85*c2c66affSColin Finck } 86*c2c66affSColin Finck 87*c2c66affSColin Finck msi_free( ext->Extension ); 88*c2c66affSColin Finck msi_free( ext->ProgIDText ); 89*c2c66affSColin Finck msi_free( ext ); 90*c2c66affSColin Finck } 91*c2c66affSColin Finck 92*c2c66affSColin Finck static void free_assembly( MSIASSEMBLY *assembly ) 93*c2c66affSColin Finck { 94*c2c66affSColin Finck msi_free( assembly->feature ); 95*c2c66affSColin Finck msi_free( assembly->manifest ); 96*c2c66affSColin Finck msi_free( assembly->application ); 97*c2c66affSColin Finck msi_free( assembly->display_name ); 98*c2c66affSColin Finck if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir ); 99*c2c66affSColin Finck msi_free( assembly->tempdir ); 100*c2c66affSColin Finck msi_free( assembly ); 101*c2c66affSColin Finck } 102*c2c66affSColin Finck 103*c2c66affSColin Finck void msi_free_action_script( MSIPACKAGE *package, UINT script ) 104*c2c66affSColin Finck { 105*c2c66affSColin Finck UINT i; 106*c2c66affSColin Finck for (i = 0; i < package->script->ActionCount[script]; i++) 107*c2c66affSColin Finck msi_free( package->script->Actions[script][i] ); 108*c2c66affSColin Finck 109*c2c66affSColin Finck msi_free( package->script->Actions[script] ); 110*c2c66affSColin Finck package->script->Actions[script] = NULL; 111*c2c66affSColin Finck package->script->ActionCount[script] = 0; 112*c2c66affSColin Finck } 113*c2c66affSColin Finck 114*c2c66affSColin Finck static void free_package_structures( MSIPACKAGE *package ) 115*c2c66affSColin Finck { 116*c2c66affSColin Finck struct list *item, *cursor; 117*c2c66affSColin Finck 118*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->features ) 119*c2c66affSColin Finck { 120*c2c66affSColin Finck MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); 121*c2c66affSColin Finck list_remove( &feature->entry ); 122*c2c66affSColin Finck free_feature( feature ); 123*c2c66affSColin Finck } 124*c2c66affSColin Finck 125*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->folders ) 126*c2c66affSColin Finck { 127*c2c66affSColin Finck MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); 128*c2c66affSColin Finck list_remove( &folder->entry ); 129*c2c66affSColin Finck free_folder( folder ); 130*c2c66affSColin Finck } 131*c2c66affSColin Finck 132*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->files ) 133*c2c66affSColin Finck { 134*c2c66affSColin Finck MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry ); 135*c2c66affSColin Finck 136*c2c66affSColin Finck list_remove( &file->entry ); 137*c2c66affSColin Finck msi_free( file->File ); 138*c2c66affSColin Finck msi_free( file->FileName ); 139*c2c66affSColin Finck msi_free( file->ShortName ); 140*c2c66affSColin Finck msi_free( file->LongName ); 141*c2c66affSColin Finck msi_free( file->Version ); 142*c2c66affSColin Finck msi_free( file->Language ); 143*c2c66affSColin Finck if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath ); 144*c2c66affSColin Finck msi_free( file->TargetPath ); 145*c2c66affSColin Finck msi_free( file ); 146*c2c66affSColin Finck } 147*c2c66affSColin Finck 148*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->components ) 149*c2c66affSColin Finck { 150*c2c66affSColin Finck MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); 151*c2c66affSColin Finck 152*c2c66affSColin Finck list_remove( &comp->entry ); 153*c2c66affSColin Finck msi_free( comp->Component ); 154*c2c66affSColin Finck msi_free( comp->ComponentId ); 155*c2c66affSColin Finck msi_free( comp->Directory ); 156*c2c66affSColin Finck msi_free( comp->Condition ); 157*c2c66affSColin Finck msi_free( comp->KeyPath ); 158*c2c66affSColin Finck msi_free( comp->FullKeypath ); 159*c2c66affSColin Finck if (comp->assembly) free_assembly( comp->assembly ); 160*c2c66affSColin Finck msi_free( comp ); 161*c2c66affSColin Finck } 162*c2c66affSColin Finck 163*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches ) 164*c2c66affSColin Finck { 165*c2c66affSColin Finck MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry ); 166*c2c66affSColin Finck 167*c2c66affSColin Finck list_remove( &patch->entry ); 168*c2c66affSColin Finck msi_free( patch->path ); 169*c2c66affSColin Finck msi_free( patch ); 170*c2c66affSColin Finck } 171*c2c66affSColin Finck 172*c2c66affSColin Finck /* clean up extension, progid, class and verb structures */ 173*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) 174*c2c66affSColin Finck { 175*c2c66affSColin Finck MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry ); 176*c2c66affSColin Finck 177*c2c66affSColin Finck list_remove( &cls->entry ); 178*c2c66affSColin Finck msi_free( cls->clsid ); 179*c2c66affSColin Finck msi_free( cls->Context ); 180*c2c66affSColin Finck msi_free( cls->Description ); 181*c2c66affSColin Finck msi_free( cls->FileTypeMask ); 182*c2c66affSColin Finck msi_free( cls->IconPath ); 183*c2c66affSColin Finck msi_free( cls->DefInprocHandler ); 184*c2c66affSColin Finck msi_free( cls->DefInprocHandler32 ); 185*c2c66affSColin Finck msi_free( cls->Argument ); 186*c2c66affSColin Finck msi_free( cls->ProgIDText ); 187*c2c66affSColin Finck msi_free( cls ); 188*c2c66affSColin Finck } 189*c2c66affSColin Finck 190*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->extensions ) 191*c2c66affSColin Finck { 192*c2c66affSColin Finck MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry ); 193*c2c66affSColin Finck 194*c2c66affSColin Finck list_remove( &ext->entry ); 195*c2c66affSColin Finck free_extension( ext ); 196*c2c66affSColin Finck } 197*c2c66affSColin Finck 198*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->progids ) 199*c2c66affSColin Finck { 200*c2c66affSColin Finck MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry ); 201*c2c66affSColin Finck 202*c2c66affSColin Finck list_remove( &progid->entry ); 203*c2c66affSColin Finck msi_free( progid->ProgID ); 204*c2c66affSColin Finck msi_free( progid->Description ); 205*c2c66affSColin Finck msi_free( progid->IconPath ); 206*c2c66affSColin Finck msi_free( progid ); 207*c2c66affSColin Finck } 208*c2c66affSColin Finck 209*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) 210*c2c66affSColin Finck { 211*c2c66affSColin Finck MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry ); 212*c2c66affSColin Finck 213*c2c66affSColin Finck list_remove( &mt->entry ); 214*c2c66affSColin Finck msi_free( mt->suffix ); 215*c2c66affSColin Finck msi_free( mt->clsid ); 216*c2c66affSColin Finck msi_free( mt->ContentType ); 217*c2c66affSColin Finck msi_free( mt ); 218*c2c66affSColin Finck } 219*c2c66affSColin Finck 220*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->appids ) 221*c2c66affSColin Finck { 222*c2c66affSColin Finck MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry ); 223*c2c66affSColin Finck 224*c2c66affSColin Finck list_remove( &appid->entry ); 225*c2c66affSColin Finck msi_free( appid->AppID ); 226*c2c66affSColin Finck msi_free( appid->RemoteServerName ); 227*c2c66affSColin Finck msi_free( appid->LocalServer ); 228*c2c66affSColin Finck msi_free( appid->ServiceParameters ); 229*c2c66affSColin Finck msi_free( appid->DllSurrogate ); 230*c2c66affSColin Finck msi_free( appid ); 231*c2c66affSColin Finck } 232*c2c66affSColin Finck 233*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info ) 234*c2c66affSColin Finck { 235*c2c66affSColin Finck MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry ); 236*c2c66affSColin Finck 237*c2c66affSColin Finck list_remove( &info->entry ); 238*c2c66affSColin Finck msi_free( info->value ); 239*c2c66affSColin Finck msi_free( info ); 240*c2c66affSColin Finck } 241*c2c66affSColin Finck 242*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media ) 243*c2c66affSColin Finck { 244*c2c66affSColin Finck MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry ); 245*c2c66affSColin Finck 246*c2c66affSColin Finck list_remove( &info->entry ); 247*c2c66affSColin Finck msi_free( info->volume_label ); 248*c2c66affSColin Finck msi_free( info->disk_prompt ); 249*c2c66affSColin Finck msi_free( info ); 250*c2c66affSColin Finck } 251*c2c66affSColin Finck 252*c2c66affSColin Finck if (package->script) 253*c2c66affSColin Finck { 254*c2c66affSColin Finck INT i; 255*c2c66affSColin Finck UINT j; 256*c2c66affSColin Finck 257*c2c66affSColin Finck for (i = 0; i < SCRIPT_MAX; i++) 258*c2c66affSColin Finck msi_free_action_script( package, i ); 259*c2c66affSColin Finck 260*c2c66affSColin Finck for (j = 0; j < package->script->UniqueActionsCount; j++) 261*c2c66affSColin Finck msi_free( package->script->UniqueActions[j] ); 262*c2c66affSColin Finck 263*c2c66affSColin Finck msi_free( package->script->UniqueActions ); 264*c2c66affSColin Finck msi_free( package->script ); 265*c2c66affSColin Finck } 266*c2c66affSColin Finck 267*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->binaries ) 268*c2c66affSColin Finck { 269*c2c66affSColin Finck MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry ); 270*c2c66affSColin Finck 271*c2c66affSColin Finck list_remove( &binary->entry ); 272*c2c66affSColin Finck if (binary->module) 273*c2c66affSColin Finck FreeLibrary( binary->module ); 274*c2c66affSColin Finck if (!DeleteFileW( binary->tmpfile )) 275*c2c66affSColin Finck ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError()); 276*c2c66affSColin Finck msi_free( binary->source ); 277*c2c66affSColin Finck msi_free( binary->tmpfile ); 278*c2c66affSColin Finck msi_free( binary ); 279*c2c66affSColin Finck } 280*c2c66affSColin Finck 281*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams ) 282*c2c66affSColin Finck { 283*c2c66affSColin Finck MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry ); 284*c2c66affSColin Finck 285*c2c66affSColin Finck list_remove( &cab->entry ); 286*c2c66affSColin Finck IStorage_Release( cab->storage ); 287*c2c66affSColin Finck msi_free( cab->stream ); 288*c2c66affSColin Finck msi_free( cab ); 289*c2c66affSColin Finck } 290*c2c66affSColin Finck 291*c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, cursor, &package->patches ) 292*c2c66affSColin Finck { 293*c2c66affSColin Finck MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry ); 294*c2c66affSColin Finck 295*c2c66affSColin Finck list_remove( &patch->entry ); 296*c2c66affSColin Finck if (patch->delete_on_close && !DeleteFileW( patch->localfile )) 297*c2c66affSColin Finck { 298*c2c66affSColin Finck ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError()); 299*c2c66affSColin Finck } 300*c2c66affSColin Finck msi_free_patchinfo( patch ); 301*c2c66affSColin Finck } 302*c2c66affSColin Finck 303*c2c66affSColin Finck msi_free( package->BaseURL ); 304*c2c66affSColin Finck msi_free( package->PackagePath ); 305*c2c66affSColin Finck msi_free( package->ProductCode ); 306*c2c66affSColin Finck msi_free( package->ActionFormat ); 307*c2c66affSColin Finck msi_free( package->LastAction ); 308*c2c66affSColin Finck msi_free( package->langids ); 309*c2c66affSColin Finck 310*c2c66affSColin Finck /* cleanup control event subscriptions */ 311*c2c66affSColin Finck msi_event_cleanup_all_subscriptions( package ); 312*c2c66affSColin Finck } 313*c2c66affSColin Finck 314*c2c66affSColin Finck static void MSI_FreePackage( MSIOBJECTHDR *arg) 315*c2c66affSColin Finck { 316*c2c66affSColin Finck MSIPACKAGE *package = (MSIPACKAGE *)arg; 317*c2c66affSColin Finck 318*c2c66affSColin Finck msi_destroy_assembly_caches( package ); 319*c2c66affSColin Finck 320*c2c66affSColin Finck if( package->dialog ) 321*c2c66affSColin Finck msi_dialog_destroy( package->dialog ); 322*c2c66affSColin Finck 323*c2c66affSColin Finck msiobj_release( &package->db->hdr ); 324*c2c66affSColin Finck free_package_structures(package); 325*c2c66affSColin Finck CloseHandle( package->log_file ); 326*c2c66affSColin Finck 327*c2c66affSColin Finck if (package->delete_on_close) DeleteFileW( package->localfile ); 328*c2c66affSColin Finck msi_free( package->localfile ); 329*c2c66affSColin Finck } 330*c2c66affSColin Finck 331*c2c66affSColin Finck static UINT create_temp_property_table(MSIPACKAGE *package) 332*c2c66affSColin Finck { 333*c2c66affSColin Finck static const WCHAR query[] = { 334*c2c66affSColin Finck 'C','R','E','A','T','E',' ','T','A','B','L','E',' ', 335*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ', 336*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 337*c2c66affSColin Finck 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ', 338*c2c66affSColin Finck 'T','E','M','P','O','R','A','R','Y',',',' ', 339*c2c66affSColin Finck '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ', 340*c2c66affSColin Finck 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y', 341*c2c66affSColin Finck ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ', 342*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0}; 343*c2c66affSColin Finck MSIQUERY *view; 344*c2c66affSColin Finck UINT rc; 345*c2c66affSColin Finck 346*c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(package->db, query, &view); 347*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 348*c2c66affSColin Finck return rc; 349*c2c66affSColin Finck 350*c2c66affSColin Finck rc = MSI_ViewExecute(view, 0); 351*c2c66affSColin Finck MSI_ViewClose(view); 352*c2c66affSColin Finck msiobj_release(&view->hdr); 353*c2c66affSColin Finck return rc; 354*c2c66affSColin Finck } 355*c2c66affSColin Finck 356*c2c66affSColin Finck UINT msi_clone_properties( MSIDATABASE *db ) 357*c2c66affSColin Finck { 358*c2c66affSColin Finck static const WCHAR query_select[] = { 359*c2c66affSColin Finck 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 360*c2c66affSColin Finck '`','P','r','o','p','e','r','t','y','`',0}; 361*c2c66affSColin Finck static const WCHAR query_insert[] = { 362*c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 363*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 364*c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 365*c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 366*c2c66affSColin Finck static const WCHAR query_update[] = { 367*c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 368*c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ', 369*c2c66affSColin Finck 'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0}; 370*c2c66affSColin Finck MSIQUERY *view_select; 371*c2c66affSColin Finck UINT rc; 372*c2c66affSColin Finck 373*c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_select, &view_select ); 374*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 375*c2c66affSColin Finck return rc; 376*c2c66affSColin Finck 377*c2c66affSColin Finck rc = MSI_ViewExecute( view_select, 0 ); 378*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 379*c2c66affSColin Finck { 380*c2c66affSColin Finck MSI_ViewClose( view_select ); 381*c2c66affSColin Finck msiobj_release( &view_select->hdr ); 382*c2c66affSColin Finck return rc; 383*c2c66affSColin Finck } 384*c2c66affSColin Finck 385*c2c66affSColin Finck while (1) 386*c2c66affSColin Finck { 387*c2c66affSColin Finck MSIQUERY *view_insert, *view_update; 388*c2c66affSColin Finck MSIRECORD *rec_select; 389*c2c66affSColin Finck 390*c2c66affSColin Finck rc = MSI_ViewFetch( view_select, &rec_select ); 391*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 392*c2c66affSColin Finck break; 393*c2c66affSColin Finck 394*c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert ); 395*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 396*c2c66affSColin Finck { 397*c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 398*c2c66affSColin Finck continue; 399*c2c66affSColin Finck } 400*c2c66affSColin Finck 401*c2c66affSColin Finck rc = MSI_ViewExecute( view_insert, rec_select ); 402*c2c66affSColin Finck MSI_ViewClose( view_insert ); 403*c2c66affSColin Finck msiobj_release( &view_insert->hdr ); 404*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 405*c2c66affSColin Finck { 406*c2c66affSColin Finck MSIRECORD *rec_update; 407*c2c66affSColin Finck 408*c2c66affSColin Finck TRACE("insert failed, trying update\n"); 409*c2c66affSColin Finck 410*c2c66affSColin Finck rc = MSI_DatabaseOpenViewW( db, query_update, &view_update ); 411*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 412*c2c66affSColin Finck { 413*c2c66affSColin Finck WARN("open view failed %u\n", rc); 414*c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 415*c2c66affSColin Finck continue; 416*c2c66affSColin Finck } 417*c2c66affSColin Finck 418*c2c66affSColin Finck rec_update = MSI_CreateRecord( 2 ); 419*c2c66affSColin Finck MSI_RecordCopyField( rec_select, 1, rec_update, 2 ); 420*c2c66affSColin Finck MSI_RecordCopyField( rec_select, 2, rec_update, 1 ); 421*c2c66affSColin Finck rc = MSI_ViewExecute( view_update, rec_update ); 422*c2c66affSColin Finck if (rc != ERROR_SUCCESS) 423*c2c66affSColin Finck WARN("update failed %u\n", rc); 424*c2c66affSColin Finck 425*c2c66affSColin Finck MSI_ViewClose( view_update ); 426*c2c66affSColin Finck msiobj_release( &view_update->hdr ); 427*c2c66affSColin Finck msiobj_release( &rec_update->hdr ); 428*c2c66affSColin Finck } 429*c2c66affSColin Finck 430*c2c66affSColin Finck msiobj_release( &rec_select->hdr ); 431*c2c66affSColin Finck } 432*c2c66affSColin Finck 433*c2c66affSColin Finck MSI_ViewClose( view_select ); 434*c2c66affSColin Finck msiobj_release( &view_select->hdr ); 435*c2c66affSColin Finck return rc; 436*c2c66affSColin Finck } 437*c2c66affSColin Finck 438*c2c66affSColin Finck /* 439*c2c66affSColin Finck * set_installed_prop 440*c2c66affSColin Finck * 441*c2c66affSColin Finck * Sets the "Installed" property to indicate that 442*c2c66affSColin Finck * the product is installed for the current user. 443*c2c66affSColin Finck */ 444*c2c66affSColin Finck static UINT set_installed_prop( MSIPACKAGE *package ) 445*c2c66affSColin Finck { 446*c2c66affSColin Finck HKEY hkey; 447*c2c66affSColin Finck UINT r; 448*c2c66affSColin Finck 449*c2c66affSColin Finck if (!package->ProductCode) return ERROR_FUNCTION_FAILED; 450*c2c66affSColin Finck 451*c2c66affSColin Finck r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE ); 452*c2c66affSColin Finck if (r == ERROR_SUCCESS) 453*c2c66affSColin Finck { 454*c2c66affSColin Finck RegCloseKey( hkey ); 455*c2c66affSColin Finck msi_set_property( package->db, szInstalled, szOne, -1 ); 456*c2c66affSColin Finck } 457*c2c66affSColin Finck return r; 458*c2c66affSColin Finck } 459*c2c66affSColin Finck 460*c2c66affSColin Finck static UINT set_user_sid_prop( MSIPACKAGE *package ) 461*c2c66affSColin Finck { 462*c2c66affSColin Finck SID_NAME_USE use; 463*c2c66affSColin Finck LPWSTR user_name; 464*c2c66affSColin Finck LPWSTR sid_str = NULL, dom = NULL; 465*c2c66affSColin Finck DWORD size, dom_size; 466*c2c66affSColin Finck PSID psid = NULL; 467*c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 468*c2c66affSColin Finck 469*c2c66affSColin Finck size = 0; 470*c2c66affSColin Finck GetUserNameW( NULL, &size ); 471*c2c66affSColin Finck 472*c2c66affSColin Finck user_name = msi_alloc( (size + 1) * sizeof(WCHAR) ); 473*c2c66affSColin Finck if (!user_name) 474*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 475*c2c66affSColin Finck 476*c2c66affSColin Finck if (!GetUserNameW( user_name, &size )) 477*c2c66affSColin Finck goto done; 478*c2c66affSColin Finck 479*c2c66affSColin Finck size = 0; 480*c2c66affSColin Finck dom_size = 0; 481*c2c66affSColin Finck LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use ); 482*c2c66affSColin Finck 483*c2c66affSColin Finck psid = msi_alloc( size ); 484*c2c66affSColin Finck dom = msi_alloc( dom_size*sizeof (WCHAR) ); 485*c2c66affSColin Finck if (!psid || !dom) 486*c2c66affSColin Finck { 487*c2c66affSColin Finck r = ERROR_OUTOFMEMORY; 488*c2c66affSColin Finck goto done; 489*c2c66affSColin Finck } 490*c2c66affSColin Finck 491*c2c66affSColin Finck if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use )) 492*c2c66affSColin Finck goto done; 493*c2c66affSColin Finck 494*c2c66affSColin Finck if (!ConvertSidToStringSidW( psid, &sid_str )) 495*c2c66affSColin Finck goto done; 496*c2c66affSColin Finck 497*c2c66affSColin Finck r = msi_set_property( package->db, szUserSID, sid_str, -1 ); 498*c2c66affSColin Finck 499*c2c66affSColin Finck done: 500*c2c66affSColin Finck LocalFree( sid_str ); 501*c2c66affSColin Finck msi_free( dom ); 502*c2c66affSColin Finck msi_free( psid ); 503*c2c66affSColin Finck msi_free( user_name ); 504*c2c66affSColin Finck 505*c2c66affSColin Finck return r; 506*c2c66affSColin Finck } 507*c2c66affSColin Finck 508*c2c66affSColin Finck static LPWSTR get_fusion_filename(MSIPACKAGE *package) 509*c2c66affSColin Finck { 510*c2c66affSColin Finck HKEY netsetup; 511*c2c66affSColin Finck LONG res; 512*c2c66affSColin Finck LPWSTR file = NULL; 513*c2c66affSColin Finck DWORD index = 0, size; 514*c2c66affSColin Finck WCHAR ver[MAX_PATH]; 515*c2c66affSColin Finck WCHAR name[MAX_PATH]; 516*c2c66affSColin Finck WCHAR windir[MAX_PATH]; 517*c2c66affSColin Finck 518*c2c66affSColin Finck static const WCHAR fusion[] = {'f','u','s','i','o','n','.','d','l','l',0}; 519*c2c66affSColin Finck static const WCHAR sub[] = { 520*c2c66affSColin Finck 'S','o','f','t','w','a','r','e','\\', 521*c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 522*c2c66affSColin Finck 'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\', 523*c2c66affSColin Finck 'N','D','P',0 524*c2c66affSColin Finck }; 525*c2c66affSColin Finck static const WCHAR subdir[] = { 526*c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','.','N','E','T','\\', 527*c2c66affSColin Finck 'F','r','a','m','e','w','o','r','k','\\',0 528*c2c66affSColin Finck }; 529*c2c66affSColin Finck 530*c2c66affSColin Finck res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub, 0, KEY_ENUMERATE_SUB_KEYS, &netsetup); 531*c2c66affSColin Finck if (res != ERROR_SUCCESS) 532*c2c66affSColin Finck return NULL; 533*c2c66affSColin Finck 534*c2c66affSColin Finck GetWindowsDirectoryW(windir, MAX_PATH); 535*c2c66affSColin Finck 536*c2c66affSColin Finck ver[0] = '\0'; 537*c2c66affSColin Finck size = MAX_PATH; 538*c2c66affSColin Finck while (RegEnumKeyExW(netsetup, index, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 539*c2c66affSColin Finck { 540*c2c66affSColin Finck index++; 541*c2c66affSColin Finck 542*c2c66affSColin Finck /* verify existence of fusion.dll .Net 3.0 does not install a new one */ 543*c2c66affSColin Finck if (strcmpW( ver, name ) < 0) 544*c2c66affSColin Finck { 545*c2c66affSColin Finck LPWSTR check; 546*c2c66affSColin Finck size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3; 547*c2c66affSColin Finck check = msi_alloc(size * sizeof(WCHAR)); 548*c2c66affSColin Finck 549*c2c66affSColin Finck if (!check) 550*c2c66affSColin Finck { 551*c2c66affSColin Finck msi_free(file); 552*c2c66affSColin Finck return NULL; 553*c2c66affSColin Finck } 554*c2c66affSColin Finck 555*c2c66affSColin Finck lstrcpyW(check, windir); 556*c2c66affSColin Finck lstrcatW(check, szBackSlash); 557*c2c66affSColin Finck lstrcatW(check, subdir); 558*c2c66affSColin Finck lstrcatW(check, name); 559*c2c66affSColin Finck lstrcatW(check, szBackSlash); 560*c2c66affSColin Finck lstrcatW(check, fusion); 561*c2c66affSColin Finck 562*c2c66affSColin Finck if(GetFileAttributesW(check) != INVALID_FILE_ATTRIBUTES) 563*c2c66affSColin Finck { 564*c2c66affSColin Finck msi_free(file); 565*c2c66affSColin Finck file = check; 566*c2c66affSColin Finck lstrcpyW(ver, name); 567*c2c66affSColin Finck } 568*c2c66affSColin Finck else 569*c2c66affSColin Finck msi_free(check); 570*c2c66affSColin Finck } 571*c2c66affSColin Finck } 572*c2c66affSColin Finck 573*c2c66affSColin Finck RegCloseKey(netsetup); 574*c2c66affSColin Finck return file; 575*c2c66affSColin Finck } 576*c2c66affSColin Finck 577*c2c66affSColin Finck typedef struct tagLANGANDCODEPAGE 578*c2c66affSColin Finck { 579*c2c66affSColin Finck WORD wLanguage; 580*c2c66affSColin Finck WORD wCodePage; 581*c2c66affSColin Finck } LANGANDCODEPAGE; 582*c2c66affSColin Finck 583*c2c66affSColin Finck static void set_msi_assembly_prop(MSIPACKAGE *package) 584*c2c66affSColin Finck { 585*c2c66affSColin Finck UINT val_len; 586*c2c66affSColin Finck DWORD size, handle; 587*c2c66affSColin Finck LPVOID version = NULL; 588*c2c66affSColin Finck WCHAR buf[MAX_PATH]; 589*c2c66affSColin Finck LPWSTR fusion, verstr; 590*c2c66affSColin Finck LANGANDCODEPAGE *translate; 591*c2c66affSColin Finck 592*c2c66affSColin Finck static const WCHAR netasm[] = { 593*c2c66affSColin Finck 'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0 594*c2c66affSColin Finck }; 595*c2c66affSColin Finck static const WCHAR translation[] = { 596*c2c66affSColin Finck '\\','V','a','r','F','i','l','e','I','n','f','o', 597*c2c66affSColin Finck '\\','T','r','a','n','s','l','a','t','i','o','n',0 598*c2c66affSColin Finck }; 599*c2c66affSColin Finck static const WCHAR verfmt[] = { 600*c2c66affSColin Finck '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o', 601*c2c66affSColin Finck '\\','%','0','4','x','%','0','4','x', 602*c2c66affSColin Finck '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 603*c2c66affSColin Finck }; 604*c2c66affSColin Finck 605*c2c66affSColin Finck fusion = get_fusion_filename(package); 606*c2c66affSColin Finck if (!fusion) 607*c2c66affSColin Finck return; 608*c2c66affSColin Finck 609*c2c66affSColin Finck size = GetFileVersionInfoSizeW(fusion, &handle); 610*c2c66affSColin Finck if (!size) 611*c2c66affSColin Finck goto done; 612*c2c66affSColin Finck 613*c2c66affSColin Finck version = msi_alloc(size); 614*c2c66affSColin Finck if (!version) 615*c2c66affSColin Finck goto done; 616*c2c66affSColin Finck 617*c2c66affSColin Finck if (!GetFileVersionInfoW(fusion, handle, size, version)) 618*c2c66affSColin Finck goto done; 619*c2c66affSColin Finck 620*c2c66affSColin Finck if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len)) 621*c2c66affSColin Finck goto done; 622*c2c66affSColin Finck 623*c2c66affSColin Finck sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage); 624*c2c66affSColin Finck 625*c2c66affSColin Finck if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len)) 626*c2c66affSColin Finck goto done; 627*c2c66affSColin Finck 628*c2c66affSColin Finck if (!val_len || !verstr) 629*c2c66affSColin Finck goto done; 630*c2c66affSColin Finck 631*c2c66affSColin Finck msi_set_property( package->db, netasm, verstr, -1 ); 632*c2c66affSColin Finck 633*c2c66affSColin Finck done: 634*c2c66affSColin Finck msi_free(fusion); 635*c2c66affSColin Finck msi_free(version); 636*c2c66affSColin Finck } 637*c2c66affSColin Finck 638*c2c66affSColin Finck static VOID set_installer_properties(MSIPACKAGE *package) 639*c2c66affSColin Finck { 640*c2c66affSColin Finck WCHAR *ptr; 641*c2c66affSColin Finck OSVERSIONINFOEXW OSVersion; 642*c2c66affSColin Finck MEMORYSTATUSEX msex; 643*c2c66affSColin Finck DWORD verval, len; 644*c2c66affSColin Finck WCHAR pth[MAX_PATH], verstr[11], bufstr[22]; 645*c2c66affSColin Finck HDC dc; 646*c2c66affSColin Finck HKEY hkey; 647*c2c66affSColin Finck LPWSTR username, companyname; 648*c2c66affSColin Finck SYSTEM_INFO sys_info; 649*c2c66affSColin Finck SYSTEMTIME systemtime; 650*c2c66affSColin Finck LANGID langid; 651*c2c66affSColin Finck 652*c2c66affSColin Finck static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0}; 653*c2c66affSColin Finck static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0}; 654*c2c66affSColin 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}; 655*c2c66affSColin Finck static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0}; 656*c2c66affSColin Finck static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0}; 657*c2c66affSColin Finck static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0}; 658*c2c66affSColin Finck static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0}; 659*c2c66affSColin Finck static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0}; 660*c2c66affSColin Finck static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0}; 661*c2c66affSColin Finck static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0}; 662*c2c66affSColin Finck static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0}; 663*c2c66affSColin Finck static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0}; 664*c2c66affSColin Finck static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0}; 665*c2c66affSColin Finck static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0}; 666*c2c66affSColin Finck static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; 667*c2c66affSColin Finck static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0}; 668*c2c66affSColin Finck static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0}; 669*c2c66affSColin Finck static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0}; 670*c2c66affSColin Finck static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0}; 671*c2c66affSColin Finck static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0}; 672*c2c66affSColin Finck static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0}; 673*c2c66affSColin Finck static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0}; 674*c2c66affSColin Finck static const WCHAR szFormat[] = {'%','u',0}; 675*c2c66affSColin Finck static const WCHAR szFormat2[] = {'%','u','.','%','u',0}; 676*c2c66affSColin Finck static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0}; 677*c2c66affSColin Finck static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0}; 678*c2c66affSColin Finck static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 }; 679*c2c66affSColin Finck static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 }; 680*c2c66affSColin Finck static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 }; 681*c2c66affSColin Finck static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0}; 682*c2c66affSColin Finck static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0}; 683*c2c66affSColin Finck static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0}; 684*c2c66affSColin Finck static const WCHAR szIntFormat[] = {'%','d',0}; 685*c2c66affSColin Finck static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 }; 686*c2c66affSColin Finck static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 }; 687*c2c66affSColin Finck static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 }; 688*c2c66affSColin 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 }; 689*c2c66affSColin 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 }; 690*c2c66affSColin Finck static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 }; 691*c2c66affSColin Finck static const WCHAR szUserInfo[] = { 692*c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 693*c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 694*c2c66affSColin Finck 'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\', 695*c2c66affSColin Finck 'U','s','e','r',' ','I','n','f','o',0 696*c2c66affSColin Finck }; 697*c2c66affSColin Finck static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 }; 698*c2c66affSColin Finck static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 }; 699*c2c66affSColin Finck static const WCHAR szCurrentVersion[] = { 700*c2c66affSColin Finck 'S','O','F','T','W','A','R','E','\\', 701*c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 702*c2c66affSColin Finck 'W','i','n','d','o','w','s',' ','N','T','\\', 703*c2c66affSColin Finck 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0 704*c2c66affSColin Finck }; 705*c2c66affSColin Finck static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0}; 706*c2c66affSColin Finck static const WCHAR szRegisteredOrganization[] = { 707*c2c66affSColin Finck 'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0 708*c2c66affSColin Finck }; 709*c2c66affSColin Finck static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0}; 710*c2c66affSColin Finck static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0}; 711*c2c66affSColin Finck static const WCHAR szDate[] = {'D','a','t','e',0}; 712*c2c66affSColin Finck static const WCHAR szTime[] = {'T','i','m','e',0}; 713*c2c66affSColin Finck static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0}; 714*c2c66affSColin Finck static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0}; 715*c2c66affSColin Finck static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0}; 716*c2c66affSColin Finck static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0}; 717*c2c66affSColin Finck static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0}; 718*c2c66affSColin Finck static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0}; 719*c2c66affSColin Finck static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0}; 720*c2c66affSColin Finck static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0}; 721*c2c66affSColin Finck static const WCHAR szBrowseProperty[] = {'_','B','r','o','w','s','e','P','r','o','p','e','r','t','y',0}; 722*c2c66affSColin Finck static const WCHAR szInstallDir[] = {'I','N','S','T','A','L','L','D','I','R',0}; 723*c2c66affSColin Finck 724*c2c66affSColin Finck /* 725*c2c66affSColin Finck * Other things that probably should be set: 726*c2c66affSColin Finck * 727*c2c66affSColin Finck * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging 728*c2c66affSColin Finck * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport 729*c2c66affSColin Finck */ 730*c2c66affSColin Finck 731*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); 732*c2c66affSColin Finck strcatW(pth, szBackSlash); 733*c2c66affSColin Finck msi_set_property( package->db, szCommonAppDataFolder, pth, -1 ); 734*c2c66affSColin Finck 735*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); 736*c2c66affSColin Finck strcatW(pth, szBackSlash); 737*c2c66affSColin Finck msi_set_property( package->db, szFavoritesFolder, pth, -1 ); 738*c2c66affSColin Finck 739*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); 740*c2c66affSColin Finck strcatW(pth, szBackSlash); 741*c2c66affSColin Finck msi_set_property( package->db, szFontsFolder, pth, -1 ); 742*c2c66affSColin Finck 743*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); 744*c2c66affSColin Finck strcatW(pth, szBackSlash); 745*c2c66affSColin Finck msi_set_property( package->db, szSendToFolder, pth, -1 ); 746*c2c66affSColin Finck 747*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); 748*c2c66affSColin Finck strcatW(pth, szBackSlash); 749*c2c66affSColin Finck msi_set_property( package->db, szStartMenuFolder, pth, -1 ); 750*c2c66affSColin Finck 751*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); 752*c2c66affSColin Finck strcatW(pth, szBackSlash); 753*c2c66affSColin Finck msi_set_property( package->db, szStartupFolder, pth, -1 ); 754*c2c66affSColin Finck 755*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); 756*c2c66affSColin Finck strcatW(pth, szBackSlash); 757*c2c66affSColin Finck msi_set_property( package->db, szTemplateFolder, pth, -1 ); 758*c2c66affSColin Finck 759*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); 760*c2c66affSColin Finck strcatW(pth, szBackSlash); 761*c2c66affSColin Finck msi_set_property( package->db, szDesktopFolder, pth, -1 ); 762*c2c66affSColin Finck 763*c2c66affSColin Finck /* FIXME: set to AllUsers profile path if ALLUSERS is set */ 764*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); 765*c2c66affSColin Finck strcatW(pth, szBackSlash); 766*c2c66affSColin Finck msi_set_property( package->db, szProgramMenuFolder, pth, -1 ); 767*c2c66affSColin Finck 768*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); 769*c2c66affSColin Finck strcatW(pth, szBackSlash); 770*c2c66affSColin Finck msi_set_property( package->db, szAdminToolsFolder, pth, -1 ); 771*c2c66affSColin Finck 772*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); 773*c2c66affSColin Finck strcatW(pth, szBackSlash); 774*c2c66affSColin Finck msi_set_property( package->db, szAppDataFolder, pth, -1 ); 775*c2c66affSColin Finck 776*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); 777*c2c66affSColin Finck strcatW(pth, szBackSlash); 778*c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 779*c2c66affSColin Finck msi_set_property( package->db, szSystem16Folder, pth, -1 ); 780*c2c66affSColin Finck 781*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); 782*c2c66affSColin Finck strcatW(pth, szBackSlash); 783*c2c66affSColin Finck msi_set_property( package->db, szLocalAppDataFolder, pth, -1 ); 784*c2c66affSColin Finck 785*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); 786*c2c66affSColin Finck strcatW(pth, szBackSlash); 787*c2c66affSColin Finck msi_set_property( package->db, szMyPicturesFolder, pth, -1 ); 788*c2c66affSColin Finck 789*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); 790*c2c66affSColin Finck strcatW(pth, szBackSlash); 791*c2c66affSColin Finck msi_set_property( package->db, szPersonalFolder, pth, -1 ); 792*c2c66affSColin Finck 793*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 794*c2c66affSColin Finck strcatW(pth, szBackSlash); 795*c2c66affSColin Finck msi_set_property( package->db, szWindowsFolder, pth, -1 ); 796*c2c66affSColin Finck 797*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); 798*c2c66affSColin Finck strcatW(pth, szBackSlash); 799*c2c66affSColin Finck msi_set_property( package->db, szPrintHoodFolder, pth, -1 ); 800*c2c66affSColin Finck 801*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); 802*c2c66affSColin Finck strcatW(pth, szBackSlash); 803*c2c66affSColin Finck msi_set_property( package->db, szNetHoodFolder, pth, -1 ); 804*c2c66affSColin Finck 805*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); 806*c2c66affSColin Finck strcatW(pth, szBackSlash); 807*c2c66affSColin Finck msi_set_property( package->db, szRecentFolder, pth, -1 ); 808*c2c66affSColin Finck 809*c2c66affSColin Finck /* Physical Memory is specified in MB. Using total amount. */ 810*c2c66affSColin Finck msex.dwLength = sizeof(msex); 811*c2c66affSColin Finck GlobalMemoryStatusEx( &msex ); 812*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); 813*c2c66affSColin Finck msi_set_property( package->db, szPhysicalMemory, bufstr, len ); 814*c2c66affSColin Finck 815*c2c66affSColin Finck SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 816*c2c66affSColin Finck ptr = strchrW(pth,'\\'); 817*c2c66affSColin Finck if (ptr) *(ptr + 1) = 0; 818*c2c66affSColin Finck msi_set_property( package->db, szWindowsVolume, pth, -1 ); 819*c2c66affSColin Finck 820*c2c66affSColin Finck len = GetTempPathW(MAX_PATH, pth); 821*c2c66affSColin Finck msi_set_property( package->db, szTempFolder, pth, len ); 822*c2c66affSColin Finck 823*c2c66affSColin Finck /* in a wine environment the user is always admin and privileged */ 824*c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 825*c2c66affSColin Finck msi_set_property( package->db, szPrivileged, szOne, -1 ); 826*c2c66affSColin Finck 827*c2c66affSColin Finck /* set the os things */ 828*c2c66affSColin Finck OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); 829*c2c66affSColin Finck GetVersionExW((OSVERSIONINFOW *)&OSVersion); 830*c2c66affSColin Finck verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; 831*c2c66affSColin Finck len = sprintfW( verstr, szFormat, verval ); 832*c2c66affSColin Finck switch (OSVersion.dwPlatformId) 833*c2c66affSColin Finck { 834*c2c66affSColin Finck case VER_PLATFORM_WIN32_WINDOWS: 835*c2c66affSColin Finck msi_set_property( package->db, szVersion9x, verstr, len ); 836*c2c66affSColin Finck break; 837*c2c66affSColin Finck case VER_PLATFORM_WIN32_NT: 838*c2c66affSColin Finck msi_set_property( package->db, szVersionNT, verstr, len ); 839*c2c66affSColin Finck len = sprintfW( bufstr, szFormat,OSVersion.wProductType ); 840*c2c66affSColin Finck msi_set_property( package->db, szMsiNTProductType, bufstr, len ); 841*c2c66affSColin Finck break; 842*c2c66affSColin Finck } 843*c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber ); 844*c2c66affSColin Finck msi_set_property( package->db, szWindowsBuild, bufstr, len ); 845*c2c66affSColin Finck len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor ); 846*c2c66affSColin Finck msi_set_property( package->db, szServicePackLevel, bufstr, len ); 847*c2c66affSColin Finck 848*c2c66affSColin Finck len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION ); 849*c2c66affSColin Finck msi_set_property( package->db, szVersionMsi, bufstr, len ); 850*c2c66affSColin Finck len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 ); 851*c2c66affSColin Finck msi_set_property( package->db, szVersionDatabase, bufstr, len ); 852*c2c66affSColin Finck 853*c2c66affSColin Finck GetNativeSystemInfo( &sys_info ); 854*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); 855*c2c66affSColin Finck msi_set_property( package->db, szIntel, bufstr, len ); 856*c2c66affSColin Finck if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 857*c2c66affSColin Finck { 858*c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 859*c2c66affSColin Finck PathAddBackslashW( pth ); 860*c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 861*c2c66affSColin Finck 862*c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 863*c2c66affSColin Finck PathAddBackslashW( pth ); 864*c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 865*c2c66affSColin Finck 866*c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 867*c2c66affSColin Finck PathAddBackslashW( pth ); 868*c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 869*c2c66affSColin Finck } 870*c2c66affSColin Finck else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 871*c2c66affSColin Finck { 872*c2c66affSColin Finck msi_set_property( package->db, szMsiAMD64, bufstr, -1 ); 873*c2c66affSColin Finck msi_set_property( package->db, szMsix64, bufstr, -1 ); 874*c2c66affSColin Finck msi_set_property( package->db, szVersionNT64, verstr, -1 ); 875*c2c66affSColin Finck 876*c2c66affSColin Finck GetSystemDirectoryW( pth, MAX_PATH ); 877*c2c66affSColin Finck PathAddBackslashW( pth ); 878*c2c66affSColin Finck msi_set_property( package->db, szSystem64Folder, pth, -1 ); 879*c2c66affSColin Finck 880*c2c66affSColin Finck GetSystemWow64DirectoryW( pth, MAX_PATH ); 881*c2c66affSColin Finck PathAddBackslashW( pth ); 882*c2c66affSColin Finck msi_set_property( package->db, szSystemFolder, pth, -1 ); 883*c2c66affSColin Finck 884*c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 885*c2c66affSColin Finck PathAddBackslashW( pth ); 886*c2c66affSColin Finck msi_set_property( package->db, szProgramFiles64Folder, pth, -1 ); 887*c2c66affSColin Finck 888*c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth ); 889*c2c66affSColin Finck PathAddBackslashW( pth ); 890*c2c66affSColin Finck msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 891*c2c66affSColin Finck 892*c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 893*c2c66affSColin Finck PathAddBackslashW( pth ); 894*c2c66affSColin Finck msi_set_property( package->db, szCommonFiles64Folder, pth, -1 ); 895*c2c66affSColin Finck 896*c2c66affSColin Finck SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth ); 897*c2c66affSColin Finck PathAddBackslashW( pth ); 898*c2c66affSColin Finck msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 899*c2c66affSColin Finck } 900*c2c66affSColin Finck 901*c2c66affSColin Finck /* Screen properties. */ 902*c2c66affSColin Finck dc = GetDC(0); 903*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) ); 904*c2c66affSColin Finck msi_set_property( package->db, szScreenX, bufstr, len ); 905*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) ); 906*c2c66affSColin Finck msi_set_property( package->db, szScreenY, bufstr, len ); 907*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) ); 908*c2c66affSColin Finck msi_set_property( package->db, szColorBits, bufstr, len ); 909*c2c66affSColin Finck ReleaseDC(0, dc); 910*c2c66affSColin Finck 911*c2c66affSColin Finck /* USERNAME and COMPANYNAME */ 912*c2c66affSColin Finck username = msi_dup_property( package->db, szUSERNAME ); 913*c2c66affSColin Finck companyname = msi_dup_property( package->db, szCOMPANYNAME ); 914*c2c66affSColin Finck 915*c2c66affSColin Finck if ((!username || !companyname) && 916*c2c66affSColin Finck RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS) 917*c2c66affSColin Finck { 918*c2c66affSColin Finck if (!username && 919*c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szDefName ))) 920*c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 921*c2c66affSColin Finck if (!companyname && 922*c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szDefCompany ))) 923*c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 924*c2c66affSColin Finck CloseHandle( hkey ); 925*c2c66affSColin Finck } 926*c2c66affSColin Finck if ((!username || !companyname) && 927*c2c66affSColin Finck RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS) 928*c2c66affSColin Finck { 929*c2c66affSColin Finck if (!username && 930*c2c66affSColin Finck (username = msi_reg_get_val_str( hkey, szRegisteredUser ))) 931*c2c66affSColin Finck msi_set_property( package->db, szUSERNAME, username, -1 ); 932*c2c66affSColin Finck if (!companyname && 933*c2c66affSColin Finck (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization ))) 934*c2c66affSColin Finck msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 935*c2c66affSColin Finck CloseHandle( hkey ); 936*c2c66affSColin Finck } 937*c2c66affSColin Finck msi_free( username ); 938*c2c66affSColin Finck msi_free( companyname ); 939*c2c66affSColin Finck 940*c2c66affSColin Finck if ( set_user_sid_prop( package ) != ERROR_SUCCESS) 941*c2c66affSColin Finck ERR("Failed to set the UserSID property\n"); 942*c2c66affSColin Finck 943*c2c66affSColin Finck /* Date and time properties */ 944*c2c66affSColin Finck GetSystemTime( &systemtime ); 945*c2c66affSColin Finck if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime, 946*c2c66affSColin Finck NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) )) 947*c2c66affSColin Finck msi_set_property( package->db, szDate, bufstr, -1 ); 948*c2c66affSColin Finck else 949*c2c66affSColin Finck ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError()); 950*c2c66affSColin Finck 951*c2c66affSColin Finck if (GetTimeFormatW( LOCALE_USER_DEFAULT, 952*c2c66affSColin Finck TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, 953*c2c66affSColin Finck &systemtime, NULL, bufstr, 954*c2c66affSColin Finck sizeof(bufstr)/sizeof(bufstr[0]) )) 955*c2c66affSColin Finck msi_set_property( package->db, szTime, bufstr, -1 ); 956*c2c66affSColin Finck else 957*c2c66affSColin Finck ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError()); 958*c2c66affSColin Finck 959*c2c66affSColin Finck set_msi_assembly_prop( package ); 960*c2c66affSColin Finck 961*c2c66affSColin Finck langid = GetUserDefaultLangID(); 962*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 963*c2c66affSColin Finck msi_set_property( package->db, szUserLanguageID, bufstr, len ); 964*c2c66affSColin Finck 965*c2c66affSColin Finck langid = GetSystemDefaultLangID(); 966*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, langid ); 967*c2c66affSColin Finck msi_set_property( package->db, szSystemLangID, bufstr, len ); 968*c2c66affSColin Finck 969*c2c66affSColin Finck len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) ); 970*c2c66affSColin Finck msi_set_property( package->db, szProductState, bufstr, len ); 971*c2c66affSColin Finck 972*c2c66affSColin Finck len = 0; 973*c2c66affSColin Finck if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 974*c2c66affSColin Finck { 975*c2c66affSColin Finck WCHAR *username; 976*c2c66affSColin Finck if ((username = msi_alloc( len * sizeof(WCHAR) ))) 977*c2c66affSColin Finck { 978*c2c66affSColin Finck if (GetUserNameW( username, &len )) 979*c2c66affSColin Finck msi_set_property( package->db, szLogonUser, username, len - 1 ); 980*c2c66affSColin Finck msi_free( username ); 981*c2c66affSColin Finck } 982*c2c66affSColin Finck } 983*c2c66affSColin Finck len = 0; 984*c2c66affSColin Finck if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW) 985*c2c66affSColin Finck { 986*c2c66affSColin Finck WCHAR *computername; 987*c2c66affSColin Finck if ((computername = msi_alloc( len * sizeof(WCHAR) ))) 988*c2c66affSColin Finck { 989*c2c66affSColin Finck if (GetComputerNameW( computername, &len )) 990*c2c66affSColin Finck msi_set_property( package->db, szComputerName, computername, len ); 991*c2c66affSColin Finck msi_free( computername ); 992*c2c66affSColin Finck } 993*c2c66affSColin Finck } 994*c2c66affSColin Finck msi_set_property( package->db, szBrowseProperty, szInstallDir, -1 ); 995*c2c66affSColin Finck } 996*c2c66affSColin Finck 997*c2c66affSColin Finck static MSIPACKAGE *msi_alloc_package( void ) 998*c2c66affSColin Finck { 999*c2c66affSColin Finck MSIPACKAGE *package; 1000*c2c66affSColin Finck 1001*c2c66affSColin Finck package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), 1002*c2c66affSColin Finck MSI_FreePackage ); 1003*c2c66affSColin Finck if( package ) 1004*c2c66affSColin Finck { 1005*c2c66affSColin Finck list_init( &package->components ); 1006*c2c66affSColin Finck list_init( &package->features ); 1007*c2c66affSColin Finck list_init( &package->files ); 1008*c2c66affSColin Finck list_init( &package->filepatches ); 1009*c2c66affSColin Finck list_init( &package->tempfiles ); 1010*c2c66affSColin Finck list_init( &package->folders ); 1011*c2c66affSColin Finck list_init( &package->subscriptions ); 1012*c2c66affSColin Finck list_init( &package->appids ); 1013*c2c66affSColin Finck list_init( &package->classes ); 1014*c2c66affSColin Finck list_init( &package->mimes ); 1015*c2c66affSColin Finck list_init( &package->extensions ); 1016*c2c66affSColin Finck list_init( &package->progids ); 1017*c2c66affSColin Finck list_init( &package->RunningActions ); 1018*c2c66affSColin Finck list_init( &package->sourcelist_info ); 1019*c2c66affSColin Finck list_init( &package->sourcelist_media ); 1020*c2c66affSColin Finck list_init( &package->patches ); 1021*c2c66affSColin Finck list_init( &package->binaries ); 1022*c2c66affSColin Finck list_init( &package->cabinet_streams ); 1023*c2c66affSColin Finck } 1024*c2c66affSColin Finck 1025*c2c66affSColin Finck return package; 1026*c2c66affSColin Finck } 1027*c2c66affSColin Finck 1028*c2c66affSColin Finck static UINT msi_load_admin_properties(MSIPACKAGE *package) 1029*c2c66affSColin Finck { 1030*c2c66affSColin Finck BYTE *data; 1031*c2c66affSColin Finck UINT r, sz; 1032*c2c66affSColin Finck 1033*c2c66affSColin Finck static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0}; 1034*c2c66affSColin Finck 1035*c2c66affSColin Finck r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz); 1036*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1037*c2c66affSColin Finck return r; 1038*c2c66affSColin Finck 1039*c2c66affSColin Finck r = msi_parse_command_line(package, (WCHAR *)data, TRUE); 1040*c2c66affSColin Finck 1041*c2c66affSColin Finck msi_free(data); 1042*c2c66affSColin Finck return r; 1043*c2c66affSColin Finck } 1044*c2c66affSColin Finck 1045*c2c66affSColin Finck void msi_adjust_privilege_properties( MSIPACKAGE *package ) 1046*c2c66affSColin Finck { 1047*c2c66affSColin Finck /* FIXME: this should depend on the user's privileges */ 1048*c2c66affSColin Finck if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2) 1049*c2c66affSColin Finck { 1050*c2c66affSColin Finck TRACE("resetting ALLUSERS property from 2 to 1\n"); 1051*c2c66affSColin Finck msi_set_property( package->db, szAllUsers, szOne, -1 ); 1052*c2c66affSColin Finck } 1053*c2c66affSColin Finck msi_set_property( package->db, szAdminUser, szOne, -1 ); 1054*c2c66affSColin Finck } 1055*c2c66affSColin Finck 1056*c2c66affSColin Finck MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) 1057*c2c66affSColin Finck { 1058*c2c66affSColin Finck static const WCHAR fmtW[] = {'%','u',0}; 1059*c2c66affSColin Finck MSIPACKAGE *package; 1060*c2c66affSColin Finck WCHAR uilevel[11]; 1061*c2c66affSColin Finck int len; 1062*c2c66affSColin Finck UINT r; 1063*c2c66affSColin Finck 1064*c2c66affSColin Finck TRACE("%p\n", db); 1065*c2c66affSColin Finck 1066*c2c66affSColin Finck package = msi_alloc_package(); 1067*c2c66affSColin Finck if (package) 1068*c2c66affSColin Finck { 1069*c2c66affSColin Finck msiobj_addref( &db->hdr ); 1070*c2c66affSColin Finck package->db = db; 1071*c2c66affSColin Finck 1072*c2c66affSColin Finck package->WordCount = 0; 1073*c2c66affSColin Finck package->PackagePath = strdupW( db->path ); 1074*c2c66affSColin Finck package->BaseURL = strdupW( base_url ); 1075*c2c66affSColin Finck 1076*c2c66affSColin Finck create_temp_property_table( package ); 1077*c2c66affSColin Finck msi_clone_properties( package->db ); 1078*c2c66affSColin Finck msi_adjust_privilege_properties( package ); 1079*c2c66affSColin Finck 1080*c2c66affSColin Finck package->ProductCode = msi_dup_property( package->db, szProductCode ); 1081*c2c66affSColin Finck package->script = msi_alloc_zero( sizeof(MSISCRIPT) ); 1082*c2c66affSColin Finck 1083*c2c66affSColin Finck set_installer_properties( package ); 1084*c2c66affSColin Finck 1085*c2c66affSColin Finck package->ui_level = gUILevel; 1086*c2c66affSColin Finck len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); 1087*c2c66affSColin Finck msi_set_property( package->db, szUILevel, uilevel, len ); 1088*c2c66affSColin Finck 1089*c2c66affSColin Finck r = msi_load_suminfo_properties( package ); 1090*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1091*c2c66affSColin Finck { 1092*c2c66affSColin Finck msiobj_release( &package->hdr ); 1093*c2c66affSColin Finck return NULL; 1094*c2c66affSColin Finck } 1095*c2c66affSColin Finck 1096*c2c66affSColin Finck if (package->WordCount & msidbSumInfoSourceTypeAdminImage) 1097*c2c66affSColin Finck msi_load_admin_properties( package ); 1098*c2c66affSColin Finck 1099*c2c66affSColin Finck package->log_file = INVALID_HANDLE_VALUE; 1100*c2c66affSColin Finck } 1101*c2c66affSColin Finck return package; 1102*c2c66affSColin Finck } 1103*c2c66affSColin Finck 1104*c2c66affSColin Finck UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) 1105*c2c66affSColin Finck { 1106*c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW cache_entry; 1107*c2c66affSColin Finck DWORD size = 0; 1108*c2c66affSColin Finck HRESULT hr; 1109*c2c66affSColin Finck 1110*c2c66affSColin Finck /* call will always fail, because size is 0, 1111*c2c66affSColin Finck * but will return ERROR_FILE_NOT_FOUND first 1112*c2c66affSColin Finck * if the file doesn't exist 1113*c2c66affSColin Finck */ 1114*c2c66affSColin Finck GetUrlCacheEntryInfoW( szUrl, NULL, &size ); 1115*c2c66affSColin Finck if ( GetLastError() != ERROR_FILE_NOT_FOUND ) 1116*c2c66affSColin Finck { 1117*c2c66affSColin Finck cache_entry = msi_alloc( size ); 1118*c2c66affSColin Finck if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) 1119*c2c66affSColin Finck { 1120*c2c66affSColin Finck UINT error = GetLastError(); 1121*c2c66affSColin Finck msi_free( cache_entry ); 1122*c2c66affSColin Finck return error; 1123*c2c66affSColin Finck } 1124*c2c66affSColin Finck 1125*c2c66affSColin Finck lstrcpyW( filename, cache_entry->lpszLocalFileName ); 1126*c2c66affSColin Finck msi_free( cache_entry ); 1127*c2c66affSColin Finck return ERROR_SUCCESS; 1128*c2c66affSColin Finck } 1129*c2c66affSColin Finck 1130*c2c66affSColin Finck hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); 1131*c2c66affSColin Finck if ( FAILED(hr) ) 1132*c2c66affSColin Finck { 1133*c2c66affSColin Finck WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); 1134*c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1135*c2c66affSColin Finck } 1136*c2c66affSColin Finck 1137*c2c66affSColin Finck return ERROR_SUCCESS; 1138*c2c66affSColin Finck } 1139*c2c66affSColin Finck 1140*c2c66affSColin Finck UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) 1141*c2c66affSColin Finck { 1142*c2c66affSColin Finck static const WCHAR szInstaller[] = { 1143*c2c66affSColin Finck '\\','I','n','s','t','a','l','l','e','r','\\',0}; 1144*c2c66affSColin Finck static const WCHAR fmt[] = {'%','x',0}; 1145*c2c66affSColin Finck DWORD time, len, i, offset; 1146*c2c66affSColin Finck HANDLE handle; 1147*c2c66affSColin Finck 1148*c2c66affSColin Finck time = GetTickCount(); 1149*c2c66affSColin Finck GetWindowsDirectoryW( path, MAX_PATH ); 1150*c2c66affSColin Finck strcatW( path, szInstaller ); 1151*c2c66affSColin Finck CreateDirectoryW( path, NULL ); 1152*c2c66affSColin Finck 1153*c2c66affSColin Finck len = strlenW(path); 1154*c2c66affSColin Finck for (i = 0; i < 0x10000; i++) 1155*c2c66affSColin Finck { 1156*c2c66affSColin Finck offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff ); 1157*c2c66affSColin Finck memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) ); 1158*c2c66affSColin Finck handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, 1159*c2c66affSColin Finck CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); 1160*c2c66affSColin Finck if (handle != INVALID_HANDLE_VALUE) 1161*c2c66affSColin Finck { 1162*c2c66affSColin Finck CloseHandle(handle); 1163*c2c66affSColin Finck break; 1164*c2c66affSColin Finck } 1165*c2c66affSColin Finck if (GetLastError() != ERROR_FILE_EXISTS && 1166*c2c66affSColin Finck GetLastError() != ERROR_SHARING_VIOLATION) 1167*c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1168*c2c66affSColin Finck } 1169*c2c66affSColin Finck 1170*c2c66affSColin Finck return ERROR_SUCCESS; 1171*c2c66affSColin Finck } 1172*c2c66affSColin Finck 1173*c2c66affSColin Finck static enum platform parse_platform( const WCHAR *str ) 1174*c2c66affSColin Finck { 1175*c2c66affSColin Finck if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL; 1176*c2c66affSColin Finck else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64; 1177*c2c66affSColin Finck else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64; 1178*c2c66affSColin Finck else if (!strcmpW( str, szARM )) return PLATFORM_ARM; 1179*c2c66affSColin Finck return PLATFORM_UNKNOWN; 1180*c2c66affSColin Finck } 1181*c2c66affSColin Finck 1182*c2c66affSColin Finck static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) 1183*c2c66affSColin Finck { 1184*c2c66affSColin Finck WCHAR *template, *p, *q, *platform; 1185*c2c66affSColin Finck DWORD i, count; 1186*c2c66affSColin Finck 1187*c2c66affSColin Finck package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); 1188*c2c66affSColin Finck TRACE("version: %d\n", package->version); 1189*c2c66affSColin Finck 1190*c2c66affSColin Finck template = msi_suminfo_dup_string( si, PID_TEMPLATE ); 1191*c2c66affSColin Finck if (!template) 1192*c2c66affSColin Finck return ERROR_SUCCESS; /* native accepts missing template property */ 1193*c2c66affSColin Finck 1194*c2c66affSColin Finck TRACE("template: %s\n", debugstr_w(template)); 1195*c2c66affSColin Finck 1196*c2c66affSColin Finck p = strchrW( template, ';' ); 1197*c2c66affSColin Finck if (!p) 1198*c2c66affSColin Finck { 1199*c2c66affSColin Finck WARN("invalid template string %s\n", debugstr_w(template)); 1200*c2c66affSColin Finck msi_free( template ); 1201*c2c66affSColin Finck return ERROR_PATCH_PACKAGE_INVALID; 1202*c2c66affSColin Finck } 1203*c2c66affSColin Finck *p = 0; 1204*c2c66affSColin Finck platform = template; 1205*c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1206*c2c66affSColin Finck package->platform = parse_platform( platform ); 1207*c2c66affSColin Finck while (package->platform == PLATFORM_UNKNOWN && q) 1208*c2c66affSColin Finck { 1209*c2c66affSColin Finck platform = q + 1; 1210*c2c66affSColin Finck if ((q = strchrW( platform, ',' ))) *q = 0; 1211*c2c66affSColin Finck package->platform = parse_platform( platform ); 1212*c2c66affSColin Finck } 1213*c2c66affSColin Finck if (package->platform == PLATFORM_UNKNOWN) 1214*c2c66affSColin Finck { 1215*c2c66affSColin Finck WARN("unknown platform %s\n", debugstr_w(template)); 1216*c2c66affSColin Finck msi_free( template ); 1217*c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1218*c2c66affSColin Finck } 1219*c2c66affSColin Finck p++; 1220*c2c66affSColin Finck if (!*p) 1221*c2c66affSColin Finck { 1222*c2c66affSColin Finck msi_free( template ); 1223*c2c66affSColin Finck return ERROR_SUCCESS; 1224*c2c66affSColin Finck } 1225*c2c66affSColin Finck count = 1; 1226*c2c66affSColin Finck for (q = p; (q = strchrW( q, ',' )); q++) count++; 1227*c2c66affSColin Finck 1228*c2c66affSColin Finck package->langids = msi_alloc( count * sizeof(LANGID) ); 1229*c2c66affSColin Finck if (!package->langids) 1230*c2c66affSColin Finck { 1231*c2c66affSColin Finck msi_free( template ); 1232*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1233*c2c66affSColin Finck } 1234*c2c66affSColin Finck 1235*c2c66affSColin Finck i = 0; 1236*c2c66affSColin Finck while (*p) 1237*c2c66affSColin Finck { 1238*c2c66affSColin Finck q = strchrW( p, ',' ); 1239*c2c66affSColin Finck if (q) *q = 0; 1240*c2c66affSColin Finck package->langids[i] = atoiW( p ); 1241*c2c66affSColin Finck if (!q) break; 1242*c2c66affSColin Finck p = q + 1; 1243*c2c66affSColin Finck i++; 1244*c2c66affSColin Finck } 1245*c2c66affSColin Finck package->num_langids = i + 1; 1246*c2c66affSColin Finck 1247*c2c66affSColin Finck msi_free( template ); 1248*c2c66affSColin Finck return ERROR_SUCCESS; 1249*c2c66affSColin Finck } 1250*c2c66affSColin Finck 1251*c2c66affSColin Finck static UINT validate_package( MSIPACKAGE *package ) 1252*c2c66affSColin Finck { 1253*c2c66affSColin Finck UINT i; 1254*c2c66affSColin Finck 1255*c2c66affSColin Finck if (package->platform == PLATFORM_INTEL64) 1256*c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1257*c2c66affSColin Finck #ifndef __arm__ 1258*c2c66affSColin Finck if (package->platform == PLATFORM_ARM) 1259*c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1260*c2c66affSColin Finck #endif 1261*c2c66affSColin Finck if (package->platform == PLATFORM_X64) 1262*c2c66affSColin Finck { 1263*c2c66affSColin Finck if (!is_64bit && !is_wow64) 1264*c2c66affSColin Finck return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1265*c2c66affSColin Finck if (package->version < 200) 1266*c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1267*c2c66affSColin Finck } 1268*c2c66affSColin Finck if (!package->num_langids) 1269*c2c66affSColin Finck { 1270*c2c66affSColin Finck return ERROR_SUCCESS; 1271*c2c66affSColin Finck } 1272*c2c66affSColin Finck for (i = 0; i < package->num_langids; i++) 1273*c2c66affSColin Finck { 1274*c2c66affSColin Finck LANGID langid = package->langids[i]; 1275*c2c66affSColin Finck 1276*c2c66affSColin Finck if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) 1277*c2c66affSColin Finck { 1278*c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); 1279*c2c66affSColin Finck } 1280*c2c66affSColin Finck if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) 1281*c2c66affSColin Finck { 1282*c2c66affSColin Finck langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); 1283*c2c66affSColin Finck } 1284*c2c66affSColin Finck if (IsValidLocale( langid, LCID_INSTALLED )) 1285*c2c66affSColin Finck return ERROR_SUCCESS; 1286*c2c66affSColin Finck } 1287*c2c66affSColin Finck return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; 1288*c2c66affSColin Finck } 1289*c2c66affSColin Finck 1290*c2c66affSColin Finck static WCHAR *get_product_code( MSIDATABASE *db ) 1291*c2c66affSColin Finck { 1292*c2c66affSColin Finck static const WCHAR query[] = { 1293*c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 1294*c2c66affSColin Finck 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ', 1295*c2c66affSColin Finck 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=', 1296*c2c66affSColin Finck '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0}; 1297*c2c66affSColin Finck MSIQUERY *view; 1298*c2c66affSColin Finck MSIRECORD *rec; 1299*c2c66affSColin Finck WCHAR *ret = NULL; 1300*c2c66affSColin Finck 1301*c2c66affSColin Finck if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) 1302*c2c66affSColin Finck { 1303*c2c66affSColin Finck return NULL; 1304*c2c66affSColin Finck } 1305*c2c66affSColin Finck if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) 1306*c2c66affSColin Finck { 1307*c2c66affSColin Finck MSI_ViewClose( view ); 1308*c2c66affSColin Finck msiobj_release( &view->hdr ); 1309*c2c66affSColin Finck return NULL; 1310*c2c66affSColin Finck } 1311*c2c66affSColin Finck if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) 1312*c2c66affSColin Finck { 1313*c2c66affSColin Finck ret = strdupW( MSI_RecordGetString( rec, 1 ) ); 1314*c2c66affSColin Finck msiobj_release( &rec->hdr ); 1315*c2c66affSColin Finck } 1316*c2c66affSColin Finck MSI_ViewClose( view ); 1317*c2c66affSColin Finck msiobj_release( &view->hdr ); 1318*c2c66affSColin Finck return ret; 1319*c2c66affSColin Finck } 1320*c2c66affSColin Finck 1321*c2c66affSColin Finck static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile ) 1322*c2c66affSColin Finck { 1323*c2c66affSColin Finck MSIINSTALLCONTEXT context; 1324*c2c66affSColin Finck HKEY product_key, props_key; 1325*c2c66affSColin Finck WCHAR *registered_package = NULL, unsquashed[GUID_SIZE]; 1326*c2c66affSColin Finck UINT r; 1327*c2c66affSColin Finck 1328*c2c66affSColin Finck r = msi_locate_product( product, &context ); 1329*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1330*c2c66affSColin Finck return r; 1331*c2c66affSColin Finck 1332*c2c66affSColin Finck r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE ); 1333*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1334*c2c66affSColin Finck return r; 1335*c2c66affSColin Finck 1336*c2c66affSColin Finck r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); 1337*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1338*c2c66affSColin Finck { 1339*c2c66affSColin Finck RegCloseKey( product_key ); 1340*c2c66affSColin Finck return r; 1341*c2c66affSColin Finck } 1342*c2c66affSColin Finck r = ERROR_FUNCTION_FAILED; 1343*c2c66affSColin Finck registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW ); 1344*c2c66affSColin Finck if (!registered_package) 1345*c2c66affSColin Finck goto done; 1346*c2c66affSColin Finck 1347*c2c66affSColin Finck unsquash_guid( registered_package, unsquashed ); 1348*c2c66affSColin Finck if (!strcmpiW( package, unsquashed )) 1349*c2c66affSColin Finck { 1350*c2c66affSColin Finck WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); 1351*c2c66affSColin Finck if (!filename) 1352*c2c66affSColin Finck goto done; 1353*c2c66affSColin Finck 1354*c2c66affSColin Finck strcpyW( localfile, filename ); 1355*c2c66affSColin Finck msi_free( filename ); 1356*c2c66affSColin Finck r = ERROR_SUCCESS; 1357*c2c66affSColin Finck } 1358*c2c66affSColin Finck done: 1359*c2c66affSColin Finck msi_free( registered_package ); 1360*c2c66affSColin Finck RegCloseKey( props_key ); 1361*c2c66affSColin Finck RegCloseKey( product_key ); 1362*c2c66affSColin Finck return r; 1363*c2c66affSColin Finck } 1364*c2c66affSColin Finck 1365*c2c66affSColin Finck static WCHAR *get_package_code( MSIDATABASE *db ) 1366*c2c66affSColin Finck { 1367*c2c66affSColin Finck WCHAR *ret; 1368*c2c66affSColin Finck MSISUMMARYINFO *si; 1369*c2c66affSColin Finck UINT r; 1370*c2c66affSColin Finck 1371*c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1372*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1373*c2c66affSColin Finck { 1374*c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1375*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1376*c2c66affSColin Finck { 1377*c2c66affSColin Finck WARN("failed to load summary info %u\n", r); 1378*c2c66affSColin Finck return NULL; 1379*c2c66affSColin Finck } 1380*c2c66affSColin Finck } 1381*c2c66affSColin Finck ret = msi_suminfo_dup_string( si, PID_REVNUMBER ); 1382*c2c66affSColin Finck msiobj_release( &si->hdr ); 1383*c2c66affSColin Finck return ret; 1384*c2c66affSColin Finck } 1385*c2c66affSColin Finck 1386*c2c66affSColin Finck static UINT get_local_package( const WCHAR *filename, WCHAR *localfile ) 1387*c2c66affSColin Finck { 1388*c2c66affSColin Finck WCHAR *product_code, *package_code; 1389*c2c66affSColin Finck MSIDATABASE *db; 1390*c2c66affSColin Finck UINT r; 1391*c2c66affSColin Finck 1392*c2c66affSColin Finck if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS) 1393*c2c66affSColin Finck { 1394*c2c66affSColin Finck if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES) 1395*c2c66affSColin Finck return ERROR_FILE_NOT_FOUND; 1396*c2c66affSColin Finck return r; 1397*c2c66affSColin Finck } 1398*c2c66affSColin Finck if (!(product_code = get_product_code( db ))) 1399*c2c66affSColin Finck { 1400*c2c66affSColin Finck msiobj_release( &db->hdr ); 1401*c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1402*c2c66affSColin Finck } 1403*c2c66affSColin Finck if (!(package_code = get_package_code( db ))) 1404*c2c66affSColin Finck { 1405*c2c66affSColin Finck msi_free( product_code ); 1406*c2c66affSColin Finck msiobj_release( &db->hdr ); 1407*c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1408*c2c66affSColin Finck } 1409*c2c66affSColin Finck r = get_registered_local_package( product_code, package_code, localfile ); 1410*c2c66affSColin Finck msi_free( package_code ); 1411*c2c66affSColin Finck msi_free( product_code ); 1412*c2c66affSColin Finck msiobj_release( &db->hdr ); 1413*c2c66affSColin Finck return r; 1414*c2c66affSColin Finck } 1415*c2c66affSColin Finck 1416*c2c66affSColin Finck UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) 1417*c2c66affSColin Finck { 1418*c2c66affSColin Finck UINT r; 1419*c2c66affSColin Finck 1420*c2c66affSColin Finck if (UrlIsW( package, URLIS_URL )) 1421*c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, package, -1 ); 1422*c2c66affSColin Finck else if (package[0] == '#') 1423*c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, db->path, -1 ); 1424*c2c66affSColin Finck else 1425*c2c66affSColin Finck { 1426*c2c66affSColin Finck DWORD len; 1427*c2c66affSColin Finck WCHAR *path; 1428*c2c66affSColin Finck 1429*c2c66affSColin Finck if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); 1430*c2c66affSColin Finck if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; 1431*c2c66affSColin Finck len = GetFullPathNameW( package, len, path, NULL ); 1432*c2c66affSColin Finck r = msi_set_property( db, szOriginalDatabase, path, len ); 1433*c2c66affSColin Finck msi_free( path ); 1434*c2c66affSColin Finck } 1435*c2c66affSColin Finck return r; 1436*c2c66affSColin Finck } 1437*c2c66affSColin Finck 1438*c2c66affSColin Finck UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) 1439*c2c66affSColin Finck { 1440*c2c66affSColin Finck static const WCHAR dotmsi[] = {'.','m','s','i',0}; 1441*c2c66affSColin Finck MSIDATABASE *db; 1442*c2c66affSColin Finck MSIPACKAGE *package; 1443*c2c66affSColin Finck MSIHANDLE handle; 1444*c2c66affSColin Finck LPWSTR ptr, base_url = NULL; 1445*c2c66affSColin Finck UINT r; 1446*c2c66affSColin Finck WCHAR localfile[MAX_PATH], cachefile[MAX_PATH]; 1447*c2c66affSColin Finck LPCWSTR file = szPackage; 1448*c2c66affSColin Finck DWORD index = 0; 1449*c2c66affSColin Finck MSISUMMARYINFO *si; 1450*c2c66affSColin Finck BOOL delete_on_close = FALSE; 1451*c2c66affSColin Finck 1452*c2c66affSColin Finck TRACE("%s %p\n", debugstr_w(szPackage), pPackage); 1453*c2c66affSColin Finck 1454*c2c66affSColin Finck localfile[0] = 0; 1455*c2c66affSColin Finck if( szPackage[0] == '#' ) 1456*c2c66affSColin Finck { 1457*c2c66affSColin Finck handle = atoiW(&szPackage[1]); 1458*c2c66affSColin Finck db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); 1459*c2c66affSColin Finck if( !db ) 1460*c2c66affSColin Finck { 1461*c2c66affSColin Finck IWineMsiRemoteDatabase *remote_database; 1462*c2c66affSColin Finck 1463*c2c66affSColin Finck remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( handle ); 1464*c2c66affSColin Finck if ( !remote_database ) 1465*c2c66affSColin Finck return ERROR_INVALID_HANDLE; 1466*c2c66affSColin Finck 1467*c2c66affSColin Finck IWineMsiRemoteDatabase_Release( remote_database ); 1468*c2c66affSColin Finck WARN("MsiOpenPackage not allowed during a custom action!\n"); 1469*c2c66affSColin Finck 1470*c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1471*c2c66affSColin Finck } 1472*c2c66affSColin Finck } 1473*c2c66affSColin Finck else 1474*c2c66affSColin Finck { 1475*c2c66affSColin Finck if ( UrlIsW( szPackage, URLIS_URL ) ) 1476*c2c66affSColin Finck { 1477*c2c66affSColin Finck r = msi_download_file( szPackage, cachefile ); 1478*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1479*c2c66affSColin Finck return r; 1480*c2c66affSColin Finck 1481*c2c66affSColin Finck file = cachefile; 1482*c2c66affSColin Finck 1483*c2c66affSColin Finck base_url = strdupW( szPackage ); 1484*c2c66affSColin Finck if (!base_url) 1485*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1486*c2c66affSColin Finck 1487*c2c66affSColin Finck ptr = strrchrW( base_url, '/' ); 1488*c2c66affSColin Finck if (ptr) *(ptr + 1) = '\0'; 1489*c2c66affSColin Finck } 1490*c2c66affSColin Finck r = get_local_package( file, localfile ); 1491*c2c66affSColin Finck if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) 1492*c2c66affSColin Finck { 1493*c2c66affSColin Finck r = msi_create_empty_local_file( localfile, dotmsi ); 1494*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1495*c2c66affSColin Finck { 1496*c2c66affSColin Finck msi_free ( base_url ); 1497*c2c66affSColin Finck return r; 1498*c2c66affSColin Finck } 1499*c2c66affSColin Finck 1500*c2c66affSColin Finck if (!CopyFileW( file, localfile, FALSE )) 1501*c2c66affSColin Finck { 1502*c2c66affSColin Finck r = GetLastError(); 1503*c2c66affSColin Finck WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1504*c2c66affSColin Finck DeleteFileW( localfile ); 1505*c2c66affSColin Finck msi_free ( base_url ); 1506*c2c66affSColin Finck return r; 1507*c2c66affSColin Finck } 1508*c2c66affSColin Finck delete_on_close = TRUE; 1509*c2c66affSColin Finck } 1510*c2c66affSColin Finck TRACE("opening package %s\n", debugstr_w( localfile )); 1511*c2c66affSColin Finck r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1512*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1513*c2c66affSColin Finck { 1514*c2c66affSColin Finck msi_free ( base_url ); 1515*c2c66affSColin Finck return r; 1516*c2c66affSColin Finck } 1517*c2c66affSColin Finck } 1518*c2c66affSColin Finck package = MSI_CreatePackage( db, base_url ); 1519*c2c66affSColin Finck msi_free( base_url ); 1520*c2c66affSColin Finck msiobj_release( &db->hdr ); 1521*c2c66affSColin Finck if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1522*c2c66affSColin Finck package->localfile = strdupW( localfile ); 1523*c2c66affSColin Finck package->delete_on_close = delete_on_close; 1524*c2c66affSColin Finck 1525*c2c66affSColin Finck r = msi_get_suminfo( db->storage, 0, &si ); 1526*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1527*c2c66affSColin Finck { 1528*c2c66affSColin Finck r = msi_get_db_suminfo( db, 0, &si ); 1529*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1530*c2c66affSColin Finck { 1531*c2c66affSColin Finck WARN("failed to load summary info\n"); 1532*c2c66affSColin Finck msiobj_release( &package->hdr ); 1533*c2c66affSColin Finck return ERROR_INSTALL_PACKAGE_INVALID; 1534*c2c66affSColin Finck } 1535*c2c66affSColin Finck } 1536*c2c66affSColin Finck r = parse_suminfo( si, package ); 1537*c2c66affSColin Finck msiobj_release( &si->hdr ); 1538*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1539*c2c66affSColin Finck { 1540*c2c66affSColin Finck WARN("failed to parse summary info %u\n", r); 1541*c2c66affSColin Finck msiobj_release( &package->hdr ); 1542*c2c66affSColin Finck return r; 1543*c2c66affSColin Finck } 1544*c2c66affSColin Finck r = validate_package( package ); 1545*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1546*c2c66affSColin Finck { 1547*c2c66affSColin Finck msiobj_release( &package->hdr ); 1548*c2c66affSColin Finck return r; 1549*c2c66affSColin Finck } 1550*c2c66affSColin Finck msi_set_property( package->db, szDatabase, db->path, -1 ); 1551*c2c66affSColin Finck set_installed_prop( package ); 1552*c2c66affSColin Finck msi_set_context( package ); 1553*c2c66affSColin Finck 1554*c2c66affSColin Finck while (1) 1555*c2c66affSColin Finck { 1556*c2c66affSColin Finck WCHAR patch_code[GUID_SIZE]; 1557*c2c66affSColin Finck r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1558*c2c66affSColin Finck MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1559*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1560*c2c66affSColin Finck break; 1561*c2c66affSColin Finck 1562*c2c66affSColin Finck TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1563*c2c66affSColin Finck 1564*c2c66affSColin Finck r = msi_apply_registered_patch( package, patch_code ); 1565*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1566*c2c66affSColin Finck { 1567*c2c66affSColin Finck ERR("registered patch failed to apply %u\n", r); 1568*c2c66affSColin Finck msiobj_release( &package->hdr ); 1569*c2c66affSColin Finck return r; 1570*c2c66affSColin Finck } 1571*c2c66affSColin Finck index++; 1572*c2c66affSColin Finck } 1573*c2c66affSColin Finck if (index) msi_adjust_privilege_properties( package ); 1574*c2c66affSColin Finck 1575*c2c66affSColin Finck r = msi_set_original_database_property( package->db, szPackage ); 1576*c2c66affSColin Finck if (r != ERROR_SUCCESS) 1577*c2c66affSColin Finck { 1578*c2c66affSColin Finck msiobj_release( &package->hdr ); 1579*c2c66affSColin Finck return r; 1580*c2c66affSColin Finck } 1581*c2c66affSColin Finck if (gszLogFile) 1582*c2c66affSColin Finck package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1583*c2c66affSColin Finck OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 1584*c2c66affSColin Finck *pPackage = package; 1585*c2c66affSColin Finck return ERROR_SUCCESS; 1586*c2c66affSColin Finck } 1587*c2c66affSColin Finck 1588*c2c66affSColin Finck UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1589*c2c66affSColin Finck { 1590*c2c66affSColin Finck MSIPACKAGE *package = NULL; 1591*c2c66affSColin Finck UINT ret; 1592*c2c66affSColin Finck 1593*c2c66affSColin Finck TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1594*c2c66affSColin Finck 1595*c2c66affSColin Finck if( !szPackage || !phPackage ) 1596*c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 1597*c2c66affSColin Finck 1598*c2c66affSColin Finck if ( !*szPackage ) 1599*c2c66affSColin Finck { 1600*c2c66affSColin Finck FIXME("Should create an empty database and package\n"); 1601*c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1602*c2c66affSColin Finck } 1603*c2c66affSColin Finck 1604*c2c66affSColin Finck if( dwOptions ) 1605*c2c66affSColin Finck FIXME("dwOptions %08x not supported\n", dwOptions); 1606*c2c66affSColin Finck 1607*c2c66affSColin Finck ret = MSI_OpenPackageW( szPackage, &package ); 1608*c2c66affSColin Finck if( ret == ERROR_SUCCESS ) 1609*c2c66affSColin Finck { 1610*c2c66affSColin Finck *phPackage = alloc_msihandle( &package->hdr ); 1611*c2c66affSColin Finck if (! *phPackage) 1612*c2c66affSColin Finck ret = ERROR_NOT_ENOUGH_MEMORY; 1613*c2c66affSColin Finck msiobj_release( &package->hdr ); 1614*c2c66affSColin Finck } 1615*c2c66affSColin Finck 1616*c2c66affSColin Finck return ret; 1617*c2c66affSColin Finck } 1618*c2c66affSColin Finck 1619*c2c66affSColin Finck UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1620*c2c66affSColin Finck { 1621*c2c66affSColin Finck return MsiOpenPackageExW( szPackage, 0, phPackage ); 1622*c2c66affSColin Finck } 1623*c2c66affSColin Finck 1624*c2c66affSColin Finck UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1625*c2c66affSColin Finck { 1626*c2c66affSColin Finck LPWSTR szwPack = NULL; 1627*c2c66affSColin Finck UINT ret; 1628*c2c66affSColin Finck 1629*c2c66affSColin Finck if( szPackage ) 1630*c2c66affSColin Finck { 1631*c2c66affSColin Finck szwPack = strdupAtoW( szPackage ); 1632*c2c66affSColin Finck if( !szwPack ) 1633*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 1634*c2c66affSColin Finck } 1635*c2c66affSColin Finck 1636*c2c66affSColin Finck ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1637*c2c66affSColin Finck 1638*c2c66affSColin Finck msi_free( szwPack ); 1639*c2c66affSColin Finck 1640*c2c66affSColin Finck return ret; 1641*c2c66affSColin Finck } 1642*c2c66affSColin Finck 1643*c2c66affSColin Finck UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1644*c2c66affSColin Finck { 1645*c2c66affSColin Finck return MsiOpenPackageExA( szPackage, 0, phPackage ); 1646*c2c66affSColin Finck } 1647*c2c66affSColin Finck 1648*c2c66affSColin Finck MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) 1649*c2c66affSColin Finck { 1650*c2c66affSColin Finck MSIPACKAGE *package; 1651*c2c66affSColin Finck MSIHANDLE handle = 0; 1652*c2c66affSColin Finck IUnknown *remote_unk; 1653*c2c66affSColin Finck IWineMsiRemotePackage *remote_package; 1654*c2c66affSColin Finck 1655*c2c66affSColin Finck TRACE("(%d)\n",hInstall); 1656*c2c66affSColin Finck 1657*c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1658*c2c66affSColin Finck if( package) 1659*c2c66affSColin Finck { 1660*c2c66affSColin Finck handle = alloc_msihandle( &package->db->hdr ); 1661*c2c66affSColin Finck msiobj_release( &package->hdr ); 1662*c2c66affSColin Finck } 1663*c2c66affSColin Finck else if ((remote_unk = msi_get_remote(hInstall))) 1664*c2c66affSColin Finck { 1665*c2c66affSColin Finck if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage, 1666*c2c66affSColin Finck (LPVOID *)&remote_package) == S_OK) 1667*c2c66affSColin Finck { 1668*c2c66affSColin Finck IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle); 1669*c2c66affSColin Finck IWineMsiRemotePackage_Release(remote_package); 1670*c2c66affSColin Finck } 1671*c2c66affSColin Finck else 1672*c2c66affSColin Finck { 1673*c2c66affSColin Finck WARN("remote handle %d is not a package\n", hInstall); 1674*c2c66affSColin Finck } 1675*c2c66affSColin Finck IUnknown_Release(remote_unk); 1676*c2c66affSColin Finck } 1677*c2c66affSColin Finck 1678*c2c66affSColin Finck return handle; 1679*c2c66affSColin Finck } 1680*c2c66affSColin Finck 1681*c2c66affSColin Finck INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 1682*c2c66affSColin Finck { 1683*c2c66affSColin Finck static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0}; 1684*c2c66affSColin Finck static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0}; 1685*c2c66affSColin Finck static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0}; 1686*c2c66affSColin Finck MSIRECORD *uirow; 1687*c2c66affSColin Finck LPWSTR deformated, message; 1688*c2c66affSColin Finck DWORD i, len, total_len, log_type = 0; 1689*c2c66affSColin Finck INT rc = 0; 1690*c2c66affSColin Finck char *msg; 1691*c2c66affSColin Finck 1692*c2c66affSColin Finck TRACE("%x\n", eMessageType); 1693*c2c66affSColin Finck 1694*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_FATALEXIT) 1695*c2c66affSColin Finck log_type |= INSTALLLOGMODE_FATALEXIT; 1696*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR) 1697*c2c66affSColin Finck log_type |= INSTALLLOGMODE_ERROR; 1698*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING) 1699*c2c66affSColin Finck log_type |= INSTALLLOGMODE_WARNING; 1700*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER) 1701*c2c66affSColin Finck log_type |= INSTALLLOGMODE_USER; 1702*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO) 1703*c2c66affSColin Finck log_type |= INSTALLLOGMODE_INFO; 1704*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_RESOLVESOURCE) 1705*c2c66affSColin Finck log_type |= INSTALLLOGMODE_RESOLVESOURCE; 1706*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_OUTOFDISKSPACE) 1707*c2c66affSColin Finck log_type |= INSTALLLOGMODE_OUTOFDISKSPACE; 1708*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA) 1709*c2c66affSColin Finck log_type |= INSTALLLOGMODE_COMMONDATA; 1710*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART) 1711*c2c66affSColin Finck log_type |= INSTALLLOGMODE_ACTIONSTART; 1712*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA) 1713*c2c66affSColin Finck log_type |= INSTALLLOGMODE_ACTIONDATA; 1714*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS) 1715*c2c66affSColin Finck log_type |= INSTALLLOGMODE_PROGRESS; 1716*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE) 1717*c2c66affSColin Finck log_type |= INSTALLLOGMODE_INITIALIZE; 1718*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE) 1719*c2c66affSColin Finck log_type |= INSTALLLOGMODE_TERMINATE; 1720*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG) 1721*c2c66affSColin Finck log_type |= INSTALLLOGMODE_SHOWDIALOG; 1722*c2c66affSColin Finck 1723*c2c66affSColin Finck if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART) 1724*c2c66affSColin Finck { 1725*c2c66affSColin Finck static const WCHAR template_s[]= 1726*c2c66affSColin Finck {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0}; 1727*c2c66affSColin Finck static const WCHAR format[] = 1728*c2c66affSColin Finck {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; 1729*c2c66affSColin Finck WCHAR timet[0x100]; 1730*c2c66affSColin Finck LPCWSTR action_text, action; 1731*c2c66affSColin Finck LPWSTR deformatted = NULL; 1732*c2c66affSColin Finck 1733*c2c66affSColin Finck GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100); 1734*c2c66affSColin Finck 1735*c2c66affSColin Finck action = MSI_RecordGetString(record, 1); 1736*c2c66affSColin Finck action_text = MSI_RecordGetString(record, 2); 1737*c2c66affSColin Finck 1738*c2c66affSColin Finck if (!action || !action_text) 1739*c2c66affSColin Finck return IDOK; 1740*c2c66affSColin Finck 1741*c2c66affSColin Finck deformat_string(package, action_text, &deformatted); 1742*c2c66affSColin Finck 1743*c2c66affSColin Finck len = strlenW(timet) + strlenW(action) + strlenW(template_s); 1744*c2c66affSColin Finck if (deformatted) 1745*c2c66affSColin Finck len += strlenW(deformatted); 1746*c2c66affSColin Finck message = msi_alloc(len*sizeof(WCHAR)); 1747*c2c66affSColin Finck sprintfW(message, template_s, timet, action); 1748*c2c66affSColin Finck if (deformatted) 1749*c2c66affSColin Finck strcatW(message, deformatted); 1750*c2c66affSColin Finck msi_free(deformatted); 1751*c2c66affSColin Finck } 1752*c2c66affSColin Finck else 1753*c2c66affSColin Finck { 1754*c2c66affSColin Finck static const WCHAR format[] = {'%','u',':',' ',0}; 1755*c2c66affSColin Finck UINT count = MSI_RecordGetFieldCount( record ); 1756*c2c66affSColin Finck WCHAR *p; 1757*c2c66affSColin Finck 1758*c2c66affSColin Finck total_len = 1; 1759*c2c66affSColin Finck for (i = 1; i <= count; i++) 1760*c2c66affSColin Finck { 1761*c2c66affSColin Finck len = 0; 1762*c2c66affSColin Finck MSI_RecordGetStringW( record, i, NULL, &len ); 1763*c2c66affSColin Finck total_len += len + 13; 1764*c2c66affSColin Finck } 1765*c2c66affSColin Finck p = message = msi_alloc( total_len * sizeof(WCHAR) ); 1766*c2c66affSColin Finck if (!p) return ERROR_OUTOFMEMORY; 1767*c2c66affSColin Finck 1768*c2c66affSColin Finck for (i = 1; i <= count; i++) 1769*c2c66affSColin Finck { 1770*c2c66affSColin Finck if (count > 1) 1771*c2c66affSColin Finck { 1772*c2c66affSColin Finck len = sprintfW( p, format, i ); 1773*c2c66affSColin Finck total_len -= len; 1774*c2c66affSColin Finck p += len; 1775*c2c66affSColin Finck } 1776*c2c66affSColin Finck len = total_len; 1777*c2c66affSColin Finck MSI_RecordGetStringW( record, i, p, &len ); 1778*c2c66affSColin Finck total_len -= len; 1779*c2c66affSColin Finck p += len; 1780*c2c66affSColin Finck if (count > 1 && total_len) 1781*c2c66affSColin Finck { 1782*c2c66affSColin Finck *p++ = ' '; 1783*c2c66affSColin Finck total_len--; 1784*c2c66affSColin Finck } 1785*c2c66affSColin Finck } 1786*c2c66affSColin Finck p[0] = 0; 1787*c2c66affSColin Finck } 1788*c2c66affSColin Finck 1789*c2c66affSColin Finck TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord, 1790*c2c66affSColin Finck gUIFilter, log_type, debugstr_w(message)); 1791*c2c66affSColin Finck 1792*c2c66affSColin Finck /* convert it to ASCII */ 1793*c2c66affSColin Finck len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1794*c2c66affSColin Finck msg = msi_alloc( len ); 1795*c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1796*c2c66affSColin Finck 1797*c2c66affSColin Finck if (gUIHandlerW && (gUIFilter & log_type)) 1798*c2c66affSColin Finck { 1799*c2c66affSColin Finck rc = gUIHandlerW( gUIContext, eMessageType, message ); 1800*c2c66affSColin Finck } 1801*c2c66affSColin Finck else if (gUIHandlerA && (gUIFilter & log_type)) 1802*c2c66affSColin Finck { 1803*c2c66affSColin Finck rc = gUIHandlerA( gUIContext, eMessageType, msg ); 1804*c2c66affSColin Finck } 1805*c2c66affSColin Finck else if (gUIHandlerRecord && (gUIFilter & log_type)) 1806*c2c66affSColin Finck { 1807*c2c66affSColin Finck MSIHANDLE rec = MsiCreateRecord( 1 ); 1808*c2c66affSColin Finck MsiRecordSetStringW( rec, 0, message ); 1809*c2c66affSColin Finck rc = gUIHandlerRecord( gUIContext, eMessageType, rec ); 1810*c2c66affSColin Finck MsiCloseHandle( rec ); 1811*c2c66affSColin Finck } 1812*c2c66affSColin Finck 1813*c2c66affSColin Finck if (!rc && package->log_file != INVALID_HANDLE_VALUE && 1814*c2c66affSColin Finck (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1815*c2c66affSColin Finck { 1816*c2c66affSColin Finck DWORD written; 1817*c2c66affSColin Finck WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1818*c2c66affSColin Finck WriteFile( package->log_file, "\n", 1, &written, NULL ); 1819*c2c66affSColin Finck } 1820*c2c66affSColin Finck msi_free( msg ); 1821*c2c66affSColin Finck msi_free( message ); 1822*c2c66affSColin Finck 1823*c2c66affSColin Finck switch (eMessageType & 0xff000000) 1824*c2c66affSColin Finck { 1825*c2c66affSColin Finck case INSTALLMESSAGE_ACTIONDATA: 1826*c2c66affSColin Finck deformat_string(package, MSI_RecordGetString(record, 2), &deformated); 1827*c2c66affSColin Finck uirow = MSI_CreateRecord(1); 1828*c2c66affSColin Finck MSI_RecordSetStringW(uirow, 1, deformated); 1829*c2c66affSColin Finck msi_free(deformated); 1830*c2c66affSColin Finck 1831*c2c66affSColin Finck msi_event_fire( package, szActionData, uirow ); 1832*c2c66affSColin Finck msiobj_release(&uirow->hdr); 1833*c2c66affSColin Finck 1834*c2c66affSColin Finck if (package->action_progress_increment) 1835*c2c66affSColin Finck { 1836*c2c66affSColin Finck uirow = MSI_CreateRecord(2); 1837*c2c66affSColin Finck MSI_RecordSetInteger(uirow, 1, 2); 1838*c2c66affSColin Finck MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 1839*c2c66affSColin Finck msi_event_fire( package, szSetProgress, uirow ); 1840*c2c66affSColin Finck msiobj_release(&uirow->hdr); 1841*c2c66affSColin Finck } 1842*c2c66affSColin Finck break; 1843*c2c66affSColin Finck 1844*c2c66affSColin Finck case INSTALLMESSAGE_ACTIONSTART: 1845*c2c66affSColin Finck deformat_string(package, MSI_RecordGetString(record, 2), &deformated); 1846*c2c66affSColin Finck uirow = MSI_CreateRecord(1); 1847*c2c66affSColin Finck MSI_RecordSetStringW(uirow, 1, deformated); 1848*c2c66affSColin Finck msi_free(deformated); 1849*c2c66affSColin Finck 1850*c2c66affSColin Finck msi_event_fire( package, szActionText, uirow ); 1851*c2c66affSColin Finck 1852*c2c66affSColin Finck msiobj_release(&uirow->hdr); 1853*c2c66affSColin Finck break; 1854*c2c66affSColin Finck 1855*c2c66affSColin Finck case INSTALLMESSAGE_PROGRESS: 1856*c2c66affSColin Finck msi_event_fire( package, szSetProgress, record ); 1857*c2c66affSColin Finck break; 1858*c2c66affSColin Finck } 1859*c2c66affSColin Finck 1860*c2c66affSColin Finck return ERROR_SUCCESS; 1861*c2c66affSColin Finck } 1862*c2c66affSColin Finck 1863*c2c66affSColin Finck INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, 1864*c2c66affSColin Finck MSIHANDLE hRecord) 1865*c2c66affSColin Finck { 1866*c2c66affSColin Finck UINT ret = ERROR_INVALID_HANDLE; 1867*c2c66affSColin Finck MSIPACKAGE *package = NULL; 1868*c2c66affSColin Finck MSIRECORD *record = NULL; 1869*c2c66affSColin Finck 1870*c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 1871*c2c66affSColin Finck if( !package ) 1872*c2c66affSColin Finck { 1873*c2c66affSColin Finck HRESULT hr; 1874*c2c66affSColin Finck IWineMsiRemotePackage *remote_package; 1875*c2c66affSColin Finck 1876*c2c66affSColin Finck remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 1877*c2c66affSColin Finck if (!remote_package) 1878*c2c66affSColin Finck return ERROR_INVALID_HANDLE; 1879*c2c66affSColin Finck 1880*c2c66affSColin Finck hr = IWineMsiRemotePackage_ProcessMessage( remote_package, eMessageType, hRecord ); 1881*c2c66affSColin Finck 1882*c2c66affSColin Finck IWineMsiRemotePackage_Release( remote_package ); 1883*c2c66affSColin Finck 1884*c2c66affSColin Finck if (FAILED(hr)) 1885*c2c66affSColin Finck { 1886*c2c66affSColin Finck if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1887*c2c66affSColin Finck return HRESULT_CODE(hr); 1888*c2c66affSColin Finck 1889*c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 1890*c2c66affSColin Finck } 1891*c2c66affSColin Finck 1892*c2c66affSColin Finck return ERROR_SUCCESS; 1893*c2c66affSColin Finck } 1894*c2c66affSColin Finck 1895*c2c66affSColin Finck record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); 1896*c2c66affSColin Finck if( !record ) 1897*c2c66affSColin Finck goto out; 1898*c2c66affSColin Finck 1899*c2c66affSColin Finck ret = MSI_ProcessMessage( package, eMessageType, record ); 1900*c2c66affSColin Finck 1901*c2c66affSColin Finck out: 1902*c2c66affSColin Finck msiobj_release( &package->hdr ); 1903*c2c66affSColin Finck if( record ) 1904*c2c66affSColin Finck msiobj_release( &record->hdr ); 1905*c2c66affSColin Finck 1906*c2c66affSColin Finck return ret; 1907*c2c66affSColin Finck } 1908*c2c66affSColin Finck 1909*c2c66affSColin Finck /* property code */ 1910*c2c66affSColin Finck 1911*c2c66affSColin Finck UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) 1912*c2c66affSColin Finck { 1913*c2c66affSColin Finck LPWSTR szwName = NULL, szwValue = NULL; 1914*c2c66affSColin Finck UINT r = ERROR_OUTOFMEMORY; 1915*c2c66affSColin Finck 1916*c2c66affSColin Finck szwName = strdupAtoW( szName ); 1917*c2c66affSColin Finck if( szName && !szwName ) 1918*c2c66affSColin Finck goto end; 1919*c2c66affSColin Finck 1920*c2c66affSColin Finck szwValue = strdupAtoW( szValue ); 1921*c2c66affSColin Finck if( szValue && !szwValue ) 1922*c2c66affSColin Finck goto end; 1923*c2c66affSColin Finck 1924*c2c66affSColin Finck r = MsiSetPropertyW( hInstall, szwName, szwValue); 1925*c2c66affSColin Finck 1926*c2c66affSColin Finck end: 1927*c2c66affSColin Finck msi_free( szwName ); 1928*c2c66affSColin Finck msi_free( szwValue ); 1929*c2c66affSColin Finck 1930*c2c66affSColin Finck return r; 1931*c2c66affSColin Finck } 1932*c2c66affSColin Finck 1933*c2c66affSColin Finck void msi_reset_folders( MSIPACKAGE *package, BOOL source ) 1934*c2c66affSColin Finck { 1935*c2c66affSColin Finck MSIFOLDER *folder; 1936*c2c66affSColin Finck 1937*c2c66affSColin Finck LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) 1938*c2c66affSColin Finck { 1939*c2c66affSColin Finck if ( source ) 1940*c2c66affSColin Finck { 1941*c2c66affSColin Finck msi_free( folder->ResolvedSource ); 1942*c2c66affSColin Finck folder->ResolvedSource = NULL; 1943*c2c66affSColin Finck } 1944*c2c66affSColin Finck else 1945*c2c66affSColin Finck { 1946*c2c66affSColin Finck msi_free( folder->ResolvedTarget ); 1947*c2c66affSColin Finck folder->ResolvedTarget = NULL; 1948*c2c66affSColin Finck } 1949*c2c66affSColin Finck } 1950*c2c66affSColin Finck } 1951*c2c66affSColin Finck 1952*c2c66affSColin Finck UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) 1953*c2c66affSColin Finck { 1954*c2c66affSColin Finck static const WCHAR insert_query[] = { 1955*c2c66affSColin Finck 'I','N','S','E','R','T',' ','I','N','T','O',' ', 1956*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ', 1957*c2c66affSColin Finck '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 1958*c2c66affSColin Finck 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 1959*c2c66affSColin Finck static const WCHAR update_query[] = { 1960*c2c66affSColin Finck 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 1961*c2c66affSColin Finck 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ', 1962*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 1963*c2c66affSColin Finck static const WCHAR delete_query[] = { 1964*c2c66affSColin Finck 'D','E','L','E','T','E',' ','F','R','O','M',' ', 1965*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 1966*c2c66affSColin Finck '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 1967*c2c66affSColin Finck MSIQUERY *view; 1968*c2c66affSColin Finck MSIRECORD *row = NULL; 1969*c2c66affSColin Finck DWORD sz = 0; 1970*c2c66affSColin Finck WCHAR query[1024]; 1971*c2c66affSColin Finck UINT rc; 1972*c2c66affSColin Finck 1973*c2c66affSColin Finck TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); 1974*c2c66affSColin Finck 1975*c2c66affSColin Finck if (!name) 1976*c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 1977*c2c66affSColin Finck 1978*c2c66affSColin Finck /* this one is weird... */ 1979*c2c66affSColin Finck if (!name[0]) 1980*c2c66affSColin Finck return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; 1981*c2c66affSColin Finck 1982*c2c66affSColin Finck if (value && len < 0) len = strlenW( value ); 1983*c2c66affSColin Finck 1984*c2c66affSColin Finck rc = msi_get_property( db, name, 0, &sz ); 1985*c2c66affSColin Finck if (!value || (!*value && !len)) 1986*c2c66affSColin Finck { 1987*c2c66affSColin Finck sprintfW( query, delete_query, name ); 1988*c2c66affSColin Finck } 1989*c2c66affSColin Finck else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) 1990*c2c66affSColin Finck { 1991*c2c66affSColin Finck sprintfW( query, update_query, name ); 1992*c2c66affSColin Finck row = MSI_CreateRecord(1); 1993*c2c66affSColin Finck msi_record_set_string( row, 1, value, len ); 1994*c2c66affSColin Finck } 1995*c2c66affSColin Finck else 1996*c2c66affSColin Finck { 1997*c2c66affSColin Finck strcpyW( query, insert_query ); 1998*c2c66affSColin Finck row = MSI_CreateRecord(2); 1999*c2c66affSColin Finck msi_record_set_string( row, 1, name, -1 ); 2000*c2c66affSColin Finck msi_record_set_string( row, 2, value, len ); 2001*c2c66affSColin Finck } 2002*c2c66affSColin Finck 2003*c2c66affSColin Finck rc = MSI_DatabaseOpenViewW(db, query, &view); 2004*c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2005*c2c66affSColin Finck { 2006*c2c66affSColin Finck rc = MSI_ViewExecute(view, row); 2007*c2c66affSColin Finck MSI_ViewClose(view); 2008*c2c66affSColin Finck msiobj_release(&view->hdr); 2009*c2c66affSColin Finck } 2010*c2c66affSColin Finck if (row) msiobj_release(&row->hdr); 2011*c2c66affSColin Finck return rc; 2012*c2c66affSColin Finck } 2013*c2c66affSColin Finck 2014*c2c66affSColin Finck UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) 2015*c2c66affSColin Finck { 2016*c2c66affSColin Finck MSIPACKAGE *package; 2017*c2c66affSColin Finck UINT ret; 2018*c2c66affSColin Finck 2019*c2c66affSColin Finck package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 2020*c2c66affSColin Finck if( !package ) 2021*c2c66affSColin Finck { 2022*c2c66affSColin Finck HRESULT hr; 2023*c2c66affSColin Finck BSTR name = NULL, value = NULL; 2024*c2c66affSColin Finck IWineMsiRemotePackage *remote_package; 2025*c2c66affSColin Finck 2026*c2c66affSColin Finck remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 2027*c2c66affSColin Finck if (!remote_package) 2028*c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2029*c2c66affSColin Finck 2030*c2c66affSColin Finck name = SysAllocString( szName ); 2031*c2c66affSColin Finck value = SysAllocString( szValue ); 2032*c2c66affSColin Finck if ((!name && szName) || (!value && szValue)) 2033*c2c66affSColin Finck { 2034*c2c66affSColin Finck SysFreeString( name ); 2035*c2c66affSColin Finck SysFreeString( value ); 2036*c2c66affSColin Finck IWineMsiRemotePackage_Release( remote_package ); 2037*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2038*c2c66affSColin Finck } 2039*c2c66affSColin Finck 2040*c2c66affSColin Finck hr = IWineMsiRemotePackage_SetProperty( remote_package, name, value ); 2041*c2c66affSColin Finck 2042*c2c66affSColin Finck SysFreeString( name ); 2043*c2c66affSColin Finck SysFreeString( value ); 2044*c2c66affSColin Finck IWineMsiRemotePackage_Release( remote_package ); 2045*c2c66affSColin Finck 2046*c2c66affSColin Finck if (FAILED(hr)) 2047*c2c66affSColin Finck { 2048*c2c66affSColin Finck if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2049*c2c66affSColin Finck return HRESULT_CODE(hr); 2050*c2c66affSColin Finck 2051*c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 2052*c2c66affSColin Finck } 2053*c2c66affSColin Finck 2054*c2c66affSColin Finck return ERROR_SUCCESS; 2055*c2c66affSColin Finck } 2056*c2c66affSColin Finck 2057*c2c66affSColin Finck ret = msi_set_property( package->db, szName, szValue, -1 ); 2058*c2c66affSColin Finck if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) 2059*c2c66affSColin Finck msi_reset_folders( package, TRUE ); 2060*c2c66affSColin Finck 2061*c2c66affSColin Finck msiobj_release( &package->hdr ); 2062*c2c66affSColin Finck return ret; 2063*c2c66affSColin Finck } 2064*c2c66affSColin Finck 2065*c2c66affSColin Finck static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) 2066*c2c66affSColin Finck { 2067*c2c66affSColin Finck static const WCHAR query[]= { 2068*c2c66affSColin Finck 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 2069*c2c66affSColin Finck 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ', 2070*c2c66affSColin Finck 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0}; 2071*c2c66affSColin Finck MSIRECORD *rec, *row = NULL; 2072*c2c66affSColin Finck MSIQUERY *view; 2073*c2c66affSColin Finck UINT r; 2074*c2c66affSColin Finck 2075*c2c66affSColin Finck if (!name || !*name) 2076*c2c66affSColin Finck return NULL; 2077*c2c66affSColin Finck 2078*c2c66affSColin Finck rec = MSI_CreateRecord(1); 2079*c2c66affSColin Finck if (!rec) 2080*c2c66affSColin Finck return NULL; 2081*c2c66affSColin Finck 2082*c2c66affSColin Finck MSI_RecordSetStringW(rec, 1, name); 2083*c2c66affSColin Finck 2084*c2c66affSColin Finck r = MSI_DatabaseOpenViewW(db, query, &view); 2085*c2c66affSColin Finck if (r == ERROR_SUCCESS) 2086*c2c66affSColin Finck { 2087*c2c66affSColin Finck MSI_ViewExecute(view, rec); 2088*c2c66affSColin Finck MSI_ViewFetch(view, &row); 2089*c2c66affSColin Finck MSI_ViewClose(view); 2090*c2c66affSColin Finck msiobj_release(&view->hdr); 2091*c2c66affSColin Finck } 2092*c2c66affSColin Finck msiobj_release(&rec->hdr); 2093*c2c66affSColin Finck return row; 2094*c2c66affSColin Finck } 2095*c2c66affSColin Finck 2096*c2c66affSColin Finck /* internal function, not compatible with MsiGetPropertyW */ 2097*c2c66affSColin Finck UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, 2098*c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2099*c2c66affSColin Finck { 2100*c2c66affSColin Finck MSIRECORD *row; 2101*c2c66affSColin Finck UINT rc = ERROR_FUNCTION_FAILED; 2102*c2c66affSColin Finck 2103*c2c66affSColin Finck TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf); 2104*c2c66affSColin Finck 2105*c2c66affSColin Finck row = msi_get_property_row( db, szName ); 2106*c2c66affSColin Finck 2107*c2c66affSColin Finck if (*pchValueBuf > 0) 2108*c2c66affSColin Finck szValueBuf[0] = 0; 2109*c2c66affSColin Finck 2110*c2c66affSColin Finck if (row) 2111*c2c66affSColin Finck { 2112*c2c66affSColin Finck rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); 2113*c2c66affSColin Finck msiobj_release(&row->hdr); 2114*c2c66affSColin Finck } 2115*c2c66affSColin Finck 2116*c2c66affSColin Finck if (rc == ERROR_SUCCESS) 2117*c2c66affSColin Finck TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), 2118*c2c66affSColin Finck debugstr_w(szName)); 2119*c2c66affSColin Finck else if (rc == ERROR_MORE_DATA) 2120*c2c66affSColin Finck TRACE("need %d sized buffer for %s\n", *pchValueBuf, 2121*c2c66affSColin Finck debugstr_w(szName)); 2122*c2c66affSColin Finck else 2123*c2c66affSColin Finck { 2124*c2c66affSColin Finck *pchValueBuf = 0; 2125*c2c66affSColin Finck TRACE("property %s not found\n", debugstr_w(szName)); 2126*c2c66affSColin Finck } 2127*c2c66affSColin Finck 2128*c2c66affSColin Finck return rc; 2129*c2c66affSColin Finck } 2130*c2c66affSColin Finck 2131*c2c66affSColin Finck LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2132*c2c66affSColin Finck { 2133*c2c66affSColin Finck DWORD sz = 0; 2134*c2c66affSColin Finck LPWSTR str; 2135*c2c66affSColin Finck UINT r; 2136*c2c66affSColin Finck 2137*c2c66affSColin Finck r = msi_get_property(db, prop, NULL, &sz); 2138*c2c66affSColin Finck if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2139*c2c66affSColin Finck return NULL; 2140*c2c66affSColin Finck 2141*c2c66affSColin Finck sz++; 2142*c2c66affSColin Finck str = msi_alloc(sz * sizeof(WCHAR)); 2143*c2c66affSColin Finck r = msi_get_property(db, prop, str, &sz); 2144*c2c66affSColin Finck if (r != ERROR_SUCCESS) 2145*c2c66affSColin Finck { 2146*c2c66affSColin Finck msi_free(str); 2147*c2c66affSColin Finck str = NULL; 2148*c2c66affSColin Finck } 2149*c2c66affSColin Finck 2150*c2c66affSColin Finck return str; 2151*c2c66affSColin Finck } 2152*c2c66affSColin Finck 2153*c2c66affSColin Finck int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2154*c2c66affSColin Finck { 2155*c2c66affSColin Finck LPWSTR str = msi_dup_property( db, prop ); 2156*c2c66affSColin Finck int val = str ? atoiW(str) : def; 2157*c2c66affSColin Finck msi_free(str); 2158*c2c66affSColin Finck return val; 2159*c2c66affSColin Finck } 2160*c2c66affSColin Finck 2161*c2c66affSColin Finck static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, 2162*c2c66affSColin Finck awstring *szValueBuf, LPDWORD pchValueBuf ) 2163*c2c66affSColin Finck { 2164*c2c66affSColin Finck MSIPACKAGE *package; 2165*c2c66affSColin Finck MSIRECORD *row = NULL; 2166*c2c66affSColin Finck UINT r = ERROR_FUNCTION_FAILED; 2167*c2c66affSColin Finck LPCWSTR val = NULL; 2168*c2c66affSColin Finck DWORD len = 0; 2169*c2c66affSColin Finck 2170*c2c66affSColin Finck TRACE("%u %s %p %p\n", handle, debugstr_w(name), 2171*c2c66affSColin Finck szValueBuf->str.w, pchValueBuf ); 2172*c2c66affSColin Finck 2173*c2c66affSColin Finck if (!name) 2174*c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 2175*c2c66affSColin Finck 2176*c2c66affSColin Finck package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); 2177*c2c66affSColin Finck if (!package) 2178*c2c66affSColin Finck { 2179*c2c66affSColin Finck HRESULT hr; 2180*c2c66affSColin Finck IWineMsiRemotePackage *remote_package; 2181*c2c66affSColin Finck LPWSTR value = NULL; 2182*c2c66affSColin Finck BSTR bname; 2183*c2c66affSColin Finck 2184*c2c66affSColin Finck remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle ); 2185*c2c66affSColin Finck if (!remote_package) 2186*c2c66affSColin Finck return ERROR_INVALID_HANDLE; 2187*c2c66affSColin Finck 2188*c2c66affSColin Finck bname = SysAllocString( name ); 2189*c2c66affSColin Finck if (!bname) 2190*c2c66affSColin Finck { 2191*c2c66affSColin Finck IWineMsiRemotePackage_Release( remote_package ); 2192*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2193*c2c66affSColin Finck } 2194*c2c66affSColin Finck 2195*c2c66affSColin Finck hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len ); 2196*c2c66affSColin Finck if (FAILED(hr)) 2197*c2c66affSColin Finck goto done; 2198*c2c66affSColin Finck 2199*c2c66affSColin Finck len++; 2200*c2c66affSColin Finck value = msi_alloc(len * sizeof(WCHAR)); 2201*c2c66affSColin Finck if (!value) 2202*c2c66affSColin Finck { 2203*c2c66affSColin Finck r = ERROR_OUTOFMEMORY; 2204*c2c66affSColin Finck goto done; 2205*c2c66affSColin Finck } 2206*c2c66affSColin Finck 2207*c2c66affSColin Finck hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, value, &len ); 2208*c2c66affSColin Finck if (FAILED(hr)) 2209*c2c66affSColin Finck goto done; 2210*c2c66affSColin Finck 2211*c2c66affSColin Finck r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf ); 2212*c2c66affSColin Finck 2213*c2c66affSColin Finck /* Bug required by Adobe installers */ 2214*c2c66affSColin Finck if (!szValueBuf->unicode && !szValueBuf->str.a) 2215*c2c66affSColin Finck *pchValueBuf *= sizeof(WCHAR); 2216*c2c66affSColin Finck 2217*c2c66affSColin Finck done: 2218*c2c66affSColin Finck IWineMsiRemotePackage_Release(remote_package); 2219*c2c66affSColin Finck SysFreeString(bname); 2220*c2c66affSColin Finck msi_free(value); 2221*c2c66affSColin Finck 2222*c2c66affSColin Finck if (FAILED(hr)) 2223*c2c66affSColin Finck { 2224*c2c66affSColin Finck if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2225*c2c66affSColin Finck return HRESULT_CODE(hr); 2226*c2c66affSColin Finck 2227*c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 2228*c2c66affSColin Finck } 2229*c2c66affSColin Finck 2230*c2c66affSColin Finck return r; 2231*c2c66affSColin Finck } 2232*c2c66affSColin Finck 2233*c2c66affSColin Finck row = msi_get_property_row( package->db, name ); 2234*c2c66affSColin Finck if (row) 2235*c2c66affSColin Finck val = msi_record_get_string( row, 1, (int *)&len ); 2236*c2c66affSColin Finck 2237*c2c66affSColin Finck if (!val) 2238*c2c66affSColin Finck val = szEmpty; 2239*c2c66affSColin Finck 2240*c2c66affSColin Finck r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf ); 2241*c2c66affSColin Finck 2242*c2c66affSColin Finck if (row) 2243*c2c66affSColin Finck msiobj_release( &row->hdr ); 2244*c2c66affSColin Finck msiobj_release( &package->hdr ); 2245*c2c66affSColin Finck 2246*c2c66affSColin Finck return r; 2247*c2c66affSColin Finck } 2248*c2c66affSColin Finck 2249*c2c66affSColin Finck UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName, 2250*c2c66affSColin Finck LPSTR szValueBuf, LPDWORD pchValueBuf ) 2251*c2c66affSColin Finck { 2252*c2c66affSColin Finck awstring val; 2253*c2c66affSColin Finck LPWSTR name; 2254*c2c66affSColin Finck UINT r; 2255*c2c66affSColin Finck 2256*c2c66affSColin Finck val.unicode = FALSE; 2257*c2c66affSColin Finck val.str.a = szValueBuf; 2258*c2c66affSColin Finck 2259*c2c66affSColin Finck name = strdupAtoW( szName ); 2260*c2c66affSColin Finck if (szName && !name) 2261*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2262*c2c66affSColin Finck 2263*c2c66affSColin Finck r = MSI_GetProperty( hInstall, name, &val, pchValueBuf ); 2264*c2c66affSColin Finck msi_free( name ); 2265*c2c66affSColin Finck return r; 2266*c2c66affSColin Finck } 2267*c2c66affSColin Finck 2268*c2c66affSColin Finck UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, 2269*c2c66affSColin Finck LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2270*c2c66affSColin Finck { 2271*c2c66affSColin Finck awstring val; 2272*c2c66affSColin Finck 2273*c2c66affSColin Finck val.unicode = TRUE; 2274*c2c66affSColin Finck val.str.w = szValueBuf; 2275*c2c66affSColin Finck 2276*c2c66affSColin Finck return MSI_GetProperty( hInstall, szName, &val, pchValueBuf ); 2277*c2c66affSColin Finck } 2278*c2c66affSColin Finck 2279*c2c66affSColin Finck typedef struct _msi_remote_package_impl { 2280*c2c66affSColin Finck IWineMsiRemotePackage IWineMsiRemotePackage_iface; 2281*c2c66affSColin Finck MSIHANDLE package; 2282*c2c66affSColin Finck LONG refs; 2283*c2c66affSColin Finck } msi_remote_package_impl; 2284*c2c66affSColin Finck 2285*c2c66affSColin Finck static inline msi_remote_package_impl *impl_from_IWineMsiRemotePackage( IWineMsiRemotePackage *iface ) 2286*c2c66affSColin Finck { 2287*c2c66affSColin Finck return CONTAINING_RECORD(iface, msi_remote_package_impl, IWineMsiRemotePackage_iface); 2288*c2c66affSColin Finck } 2289*c2c66affSColin Finck 2290*c2c66affSColin Finck static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface, 2291*c2c66affSColin Finck REFIID riid,LPVOID *ppobj) 2292*c2c66affSColin Finck { 2293*c2c66affSColin Finck if( IsEqualCLSID( riid, &IID_IUnknown ) || 2294*c2c66affSColin Finck IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) ) 2295*c2c66affSColin Finck { 2296*c2c66affSColin Finck IWineMsiRemotePackage_AddRef( iface ); 2297*c2c66affSColin Finck *ppobj = iface; 2298*c2c66affSColin Finck return S_OK; 2299*c2c66affSColin Finck } 2300*c2c66affSColin Finck 2301*c2c66affSColin Finck return E_NOINTERFACE; 2302*c2c66affSColin Finck } 2303*c2c66affSColin Finck 2304*c2c66affSColin Finck static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface ) 2305*c2c66affSColin Finck { 2306*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2307*c2c66affSColin Finck 2308*c2c66affSColin Finck return InterlockedIncrement( &This->refs ); 2309*c2c66affSColin Finck } 2310*c2c66affSColin Finck 2311*c2c66affSColin Finck static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface ) 2312*c2c66affSColin Finck { 2313*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2314*c2c66affSColin Finck ULONG r; 2315*c2c66affSColin Finck 2316*c2c66affSColin Finck r = InterlockedDecrement( &This->refs ); 2317*c2c66affSColin Finck if (r == 0) 2318*c2c66affSColin Finck { 2319*c2c66affSColin Finck MsiCloseHandle( This->package ); 2320*c2c66affSColin Finck msi_free( This ); 2321*c2c66affSColin Finck } 2322*c2c66affSColin Finck return r; 2323*c2c66affSColin Finck } 2324*c2c66affSColin Finck 2325*c2c66affSColin Finck static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle ) 2326*c2c66affSColin Finck { 2327*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2328*c2c66affSColin Finck This->package = handle; 2329*c2c66affSColin Finck return S_OK; 2330*c2c66affSColin Finck } 2331*c2c66affSColin Finck 2332*c2c66affSColin Finck static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle ) 2333*c2c66affSColin Finck { 2334*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2335*c2c66affSColin Finck IWineMsiRemoteDatabase *rdb = NULL; 2336*c2c66affSColin Finck HRESULT hr; 2337*c2c66affSColin Finck MSIHANDLE hdb; 2338*c2c66affSColin Finck 2339*c2c66affSColin Finck hr = create_msi_remote_database( NULL, (LPVOID *)&rdb ); 2340*c2c66affSColin Finck if (FAILED(hr) || !rdb) 2341*c2c66affSColin Finck { 2342*c2c66affSColin Finck ERR("Failed to create remote database\n"); 2343*c2c66affSColin Finck return hr; 2344*c2c66affSColin Finck } 2345*c2c66affSColin Finck 2346*c2c66affSColin Finck hdb = MsiGetActiveDatabase(This->package); 2347*c2c66affSColin Finck 2348*c2c66affSColin Finck hr = IWineMsiRemoteDatabase_SetMsiHandle( rdb, hdb ); 2349*c2c66affSColin Finck if (FAILED(hr)) 2350*c2c66affSColin Finck { 2351*c2c66affSColin Finck ERR("Failed to set the database handle\n"); 2352*c2c66affSColin Finck return hr; 2353*c2c66affSColin Finck } 2354*c2c66affSColin Finck 2355*c2c66affSColin Finck *handle = alloc_msi_remote_handle( (IUnknown *)rdb ); 2356*c2c66affSColin Finck return S_OK; 2357*c2c66affSColin Finck } 2358*c2c66affSColin Finck 2359*c2c66affSColin Finck static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value, DWORD *size ) 2360*c2c66affSColin Finck { 2361*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2362*c2c66affSColin Finck UINT r = MsiGetPropertyW(This->package, property, value, size); 2363*c2c66affSColin Finck if (r != ERROR_SUCCESS) return HRESULT_FROM_WIN32(r); 2364*c2c66affSColin Finck return S_OK; 2365*c2c66affSColin Finck } 2366*c2c66affSColin Finck 2367*c2c66affSColin Finck static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value ) 2368*c2c66affSColin Finck { 2369*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2370*c2c66affSColin Finck UINT r = MsiSetPropertyW(This->package, property, value); 2371*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2372*c2c66affSColin Finck } 2373*c2c66affSColin Finck 2374*c2c66affSColin Finck static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record ) 2375*c2c66affSColin Finck { 2376*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2377*c2c66affSColin Finck UINT r = MsiProcessMessage(This->package, message, record); 2378*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2379*c2c66affSColin Finck } 2380*c2c66affSColin Finck 2381*c2c66affSColin Finck static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action ) 2382*c2c66affSColin Finck { 2383*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2384*c2c66affSColin Finck UINT r = MsiDoActionW(This->package, action); 2385*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2386*c2c66affSColin Finck } 2387*c2c66affSColin Finck 2388*c2c66affSColin Finck static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence ) 2389*c2c66affSColin Finck { 2390*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2391*c2c66affSColin Finck UINT r = MsiSequenceW(This->package, table, sequence); 2392*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2393*c2c66affSColin Finck } 2394*c2c66affSColin Finck 2395*c2c66affSColin Finck static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size ) 2396*c2c66affSColin Finck { 2397*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2398*c2c66affSColin Finck UINT r = MsiGetTargetPathW(This->package, folder, value, size); 2399*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2400*c2c66affSColin Finck } 2401*c2c66affSColin Finck 2402*c2c66affSColin Finck static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value) 2403*c2c66affSColin Finck { 2404*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2405*c2c66affSColin Finck UINT r = MsiSetTargetPathW(This->package, folder, value); 2406*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2407*c2c66affSColin Finck } 2408*c2c66affSColin Finck 2409*c2c66affSColin Finck static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size ) 2410*c2c66affSColin Finck { 2411*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2412*c2c66affSColin Finck UINT r = MsiGetSourcePathW(This->package, folder, value, size); 2413*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2414*c2c66affSColin Finck } 2415*c2c66affSColin Finck 2416*c2c66affSColin Finck static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret ) 2417*c2c66affSColin Finck { 2418*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2419*c2c66affSColin Finck *ret = MsiGetMode(This->package, mode); 2420*c2c66affSColin Finck return S_OK; 2421*c2c66affSColin Finck } 2422*c2c66affSColin Finck 2423*c2c66affSColin Finck static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state ) 2424*c2c66affSColin Finck { 2425*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2426*c2c66affSColin Finck UINT r = MsiSetMode(This->package, mode, state); 2427*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2428*c2c66affSColin Finck } 2429*c2c66affSColin Finck 2430*c2c66affSColin Finck static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, 2431*c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action ) 2432*c2c66affSColin Finck { 2433*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2434*c2c66affSColin Finck UINT r = MsiGetFeatureStateW(This->package, feature, installed, action); 2435*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2436*c2c66affSColin Finck } 2437*c2c66affSColin Finck 2438*c2c66affSColin Finck static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state ) 2439*c2c66affSColin Finck { 2440*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2441*c2c66affSColin Finck UINT r = MsiSetFeatureStateW(This->package, feature, state); 2442*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2443*c2c66affSColin Finck } 2444*c2c66affSColin Finck 2445*c2c66affSColin Finck static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component, 2446*c2c66affSColin Finck INSTALLSTATE *installed, INSTALLSTATE *action ) 2447*c2c66affSColin Finck { 2448*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2449*c2c66affSColin Finck UINT r = MsiGetComponentStateW(This->package, component, installed, action); 2450*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2451*c2c66affSColin Finck } 2452*c2c66affSColin Finck 2453*c2c66affSColin Finck static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state ) 2454*c2c66affSColin Finck { 2455*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2456*c2c66affSColin Finck UINT r = MsiSetComponentStateW(This->package, component, state); 2457*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2458*c2c66affSColin Finck } 2459*c2c66affSColin Finck 2460*c2c66affSColin Finck static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language ) 2461*c2c66affSColin Finck { 2462*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2463*c2c66affSColin Finck *language = MsiGetLanguage(This->package); 2464*c2c66affSColin Finck return S_OK; 2465*c2c66affSColin Finck } 2466*c2c66affSColin Finck 2467*c2c66affSColin Finck static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level ) 2468*c2c66affSColin Finck { 2469*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2470*c2c66affSColin Finck UINT r = MsiSetInstallLevel(This->package, level); 2471*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2472*c2c66affSColin Finck } 2473*c2c66affSColin Finck 2474*c2c66affSColin Finck static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record, 2475*c2c66affSColin Finck BSTR *value) 2476*c2c66affSColin Finck { 2477*c2c66affSColin Finck DWORD size = 0; 2478*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2479*c2c66affSColin Finck UINT r = MsiFormatRecordW(This->package, record, NULL, &size); 2480*c2c66affSColin Finck if (r == ERROR_SUCCESS) 2481*c2c66affSColin Finck { 2482*c2c66affSColin Finck *value = SysAllocStringLen(NULL, size); 2483*c2c66affSColin Finck if (!*value) 2484*c2c66affSColin Finck return E_OUTOFMEMORY; 2485*c2c66affSColin Finck size++; 2486*c2c66affSColin Finck r = MsiFormatRecordW(This->package, record, *value, &size); 2487*c2c66affSColin Finck } 2488*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2489*c2c66affSColin Finck } 2490*c2c66affSColin Finck 2491*c2c66affSColin Finck static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition ) 2492*c2c66affSColin Finck { 2493*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2494*c2c66affSColin Finck UINT r = MsiEvaluateConditionW(This->package, condition); 2495*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2496*c2c66affSColin Finck } 2497*c2c66affSColin Finck 2498*c2c66affSColin Finck static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature, 2499*c2c66affSColin Finck INT cost_tree, INSTALLSTATE state, INT *cost ) 2500*c2c66affSColin Finck { 2501*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2502*c2c66affSColin Finck UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost); 2503*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2504*c2c66affSColin Finck } 2505*c2c66affSColin Finck 2506*c2c66affSColin Finck static HRESULT WINAPI mrp_EnumComponentCosts( IWineMsiRemotePackage *iface, BSTR component, 2507*c2c66affSColin Finck DWORD index, INSTALLSTATE state, BSTR drive, 2508*c2c66affSColin Finck DWORD *buflen, INT *cost, INT *temp ) 2509*c2c66affSColin Finck { 2510*c2c66affSColin Finck msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2511*c2c66affSColin Finck UINT r = MsiEnumComponentCostsW(This->package, component, index, state, drive, buflen, cost, temp); 2512*c2c66affSColin Finck return HRESULT_FROM_WIN32(r); 2513*c2c66affSColin Finck } 2514*c2c66affSColin Finck 2515*c2c66affSColin Finck static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl = 2516*c2c66affSColin Finck { 2517*c2c66affSColin Finck mrp_QueryInterface, 2518*c2c66affSColin Finck mrp_AddRef, 2519*c2c66affSColin Finck mrp_Release, 2520*c2c66affSColin Finck mrp_SetMsiHandle, 2521*c2c66affSColin Finck mrp_GetActiveDatabase, 2522*c2c66affSColin Finck mrp_GetProperty, 2523*c2c66affSColin Finck mrp_SetProperty, 2524*c2c66affSColin Finck mrp_ProcessMessage, 2525*c2c66affSColin Finck mrp_DoAction, 2526*c2c66affSColin Finck mrp_Sequence, 2527*c2c66affSColin Finck mrp_GetTargetPath, 2528*c2c66affSColin Finck mrp_SetTargetPath, 2529*c2c66affSColin Finck mrp_GetSourcePath, 2530*c2c66affSColin Finck mrp_GetMode, 2531*c2c66affSColin Finck mrp_SetMode, 2532*c2c66affSColin Finck mrp_GetFeatureState, 2533*c2c66affSColin Finck mrp_SetFeatureState, 2534*c2c66affSColin Finck mrp_GetComponentState, 2535*c2c66affSColin Finck mrp_SetComponentState, 2536*c2c66affSColin Finck mrp_GetLanguage, 2537*c2c66affSColin Finck mrp_SetInstallLevel, 2538*c2c66affSColin Finck mrp_FormatRecord, 2539*c2c66affSColin Finck mrp_EvaluateCondition, 2540*c2c66affSColin Finck mrp_GetFeatureCost, 2541*c2c66affSColin Finck mrp_EnumComponentCosts 2542*c2c66affSColin Finck }; 2543*c2c66affSColin Finck 2544*c2c66affSColin Finck HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj ) 2545*c2c66affSColin Finck { 2546*c2c66affSColin Finck msi_remote_package_impl* This; 2547*c2c66affSColin Finck 2548*c2c66affSColin Finck This = msi_alloc( sizeof *This ); 2549*c2c66affSColin Finck if (!This) 2550*c2c66affSColin Finck return E_OUTOFMEMORY; 2551*c2c66affSColin Finck 2552*c2c66affSColin Finck This->IWineMsiRemotePackage_iface.lpVtbl = &msi_remote_package_vtbl; 2553*c2c66affSColin Finck This->package = 0; 2554*c2c66affSColin Finck This->refs = 1; 2555*c2c66affSColin Finck 2556*c2c66affSColin Finck *ppObj = &This->IWineMsiRemotePackage_iface; 2557*c2c66affSColin Finck 2558*c2c66affSColin Finck return S_OK; 2559*c2c66affSColin Finck } 2560*c2c66affSColin Finck 2561*c2c66affSColin Finck UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2562*c2c66affSColin Finck LPCWSTR property, LPWSTR value) 2563*c2c66affSColin Finck { 2564*c2c66affSColin Finck MSISOURCELISTINFO *info; 2565*c2c66affSColin Finck 2566*c2c66affSColin Finck LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2567*c2c66affSColin Finck { 2568*c2c66affSColin Finck if (!strcmpW( info->value, value )) return ERROR_SUCCESS; 2569*c2c66affSColin Finck } 2570*c2c66affSColin Finck 2571*c2c66affSColin Finck info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2572*c2c66affSColin Finck if (!info) 2573*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2574*c2c66affSColin Finck 2575*c2c66affSColin Finck info->context = context; 2576*c2c66affSColin Finck info->options = options; 2577*c2c66affSColin Finck info->property = property; 2578*c2c66affSColin Finck info->value = strdupW(value); 2579*c2c66affSColin Finck list_add_head(&package->sourcelist_info, &info->entry); 2580*c2c66affSColin Finck 2581*c2c66affSColin Finck return ERROR_SUCCESS; 2582*c2c66affSColin Finck } 2583*c2c66affSColin Finck 2584*c2c66affSColin Finck UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2585*c2c66affSColin Finck DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2586*c2c66affSColin Finck { 2587*c2c66affSColin Finck MSIMEDIADISK *disk; 2588*c2c66affSColin Finck 2589*c2c66affSColin Finck LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2590*c2c66affSColin Finck { 2591*c2c66affSColin Finck if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2592*c2c66affSColin Finck } 2593*c2c66affSColin Finck 2594*c2c66affSColin Finck disk = msi_alloc(sizeof(MSIMEDIADISK)); 2595*c2c66affSColin Finck if (!disk) 2596*c2c66affSColin Finck return ERROR_OUTOFMEMORY; 2597*c2c66affSColin Finck 2598*c2c66affSColin Finck disk->context = context; 2599*c2c66affSColin Finck disk->options = options; 2600*c2c66affSColin Finck disk->disk_id = disk_id; 2601*c2c66affSColin Finck disk->volume_label = strdupW(volume_label); 2602*c2c66affSColin Finck disk->disk_prompt = strdupW(disk_prompt); 2603*c2c66affSColin Finck list_add_head(&package->sourcelist_media, &disk->entry); 2604*c2c66affSColin Finck 2605*c2c66affSColin Finck return ERROR_SUCCESS; 2606*c2c66affSColin Finck } 2607