ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

package.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2004 Aric Stewart for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #define NONAMELESSUNION
00022 #define NONAMELESSSTRUCT
00023 #define COBJMACROS
00024 
00025 #include <stdarg.h>
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winreg.h"
00029 #include "winnls.h"
00030 #include "shlwapi.h"
00031 #include "wingdi.h"
00032 #include "wine/debug.h"
00033 #include "msi.h"
00034 #include "msiquery.h"
00035 #include "objidl.h"
00036 #include "wincrypt.h"
00037 #include "winuser.h"
00038 #include "wininet.h"
00039 #include "winver.h"
00040 #include "urlmon.h"
00041 #include "shlobj.h"
00042 #include "wine/unicode.h"
00043 #include "objbase.h"
00044 #include "msidefs.h"
00045 #include "sddl.h"
00046 
00047 #include "msipriv.h"
00048 #include "msiserver.h"
00049 
00050 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00051 
00052 static void remove_tracked_tempfiles( MSIPACKAGE *package )
00053 {
00054     struct list *item, *cursor;
00055 
00056     LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
00057     {
00058         MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
00059 
00060         list_remove( &temp->entry );
00061         TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
00062         DeleteFileW( temp->Path );
00063         msi_free( temp->Path );
00064         msi_free( temp );
00065     }
00066 }
00067 
00068 static void free_feature( MSIFEATURE *feature )
00069 {
00070     struct list *item, *cursor;
00071 
00072     LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
00073     {
00074         FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
00075         list_remove( &fl->entry );
00076         msi_free( fl );
00077     }
00078 
00079     LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
00080     {
00081         ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
00082         list_remove( &cl->entry );
00083         msi_free( cl );
00084     }
00085     msi_free( feature->Feature );
00086     msi_free( feature->Feature_Parent );
00087     msi_free( feature->Directory );
00088     msi_free( feature->Description );
00089     msi_free( feature->Title );
00090     msi_free( feature );
00091 }
00092 
00093 static void free_folder( MSIFOLDER *folder )
00094 {
00095     struct list *item, *cursor;
00096 
00097     LIST_FOR_EACH_SAFE( item, cursor, &folder->children )
00098     {
00099         FolderList *fl = LIST_ENTRY( item, FolderList, entry );
00100         list_remove( &fl->entry );
00101         msi_free( fl );
00102     }
00103     msi_free( folder->Parent );
00104     msi_free( folder->Directory );
00105     msi_free( folder->TargetDefault );
00106     msi_free( folder->SourceLongPath );
00107     msi_free( folder->SourceShortPath );
00108     msi_free( folder->ResolvedTarget );
00109     msi_free( folder->ResolvedSource );
00110     msi_free( folder );
00111 }
00112 
00113 static void free_extension( MSIEXTENSION *ext )
00114 {
00115     struct list *item, *cursor;
00116 
00117     LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
00118     {
00119         MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
00120 
00121         list_remove( &verb->entry );
00122         msi_free( verb->Verb );
00123         msi_free( verb->Command );
00124         msi_free( verb->Argument );
00125         msi_free( verb );
00126     }
00127 
00128     msi_free( ext->Extension );
00129     msi_free( ext->ProgIDText );
00130     msi_free( ext );
00131 }
00132 
00133 static void free_assembly( MSIASSEMBLY *assembly )
00134 {
00135     msi_free( assembly->feature );
00136     msi_free( assembly->manifest );
00137     msi_free( assembly->application );
00138     msi_free( assembly->display_name );
00139     if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir );
00140     msi_free( assembly->tempdir );
00141     msi_free( assembly );
00142 }
00143 
00144 void msi_free_action_script( MSIPACKAGE *package, UINT script )
00145 {
00146     UINT i;
00147     for (i = 0; i < package->script->ActionCount[script]; i++)
00148         msi_free( package->script->Actions[script][i] );
00149 
00150     msi_free( package->script->Actions[script] );
00151     package->script->Actions[script] = NULL;
00152     package->script->ActionCount[script] = 0;
00153 }
00154 
00155 static void free_package_structures( MSIPACKAGE *package )
00156 {
00157     INT i;
00158     struct list *item, *cursor;
00159 
00160     LIST_FOR_EACH_SAFE( item, cursor, &package->features )
00161     {
00162         MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
00163         list_remove( &feature->entry );
00164         free_feature( feature );
00165     }
00166 
00167     LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
00168     {
00169         MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
00170         list_remove( &folder->entry );
00171         free_folder( folder );
00172     }
00173 
00174     LIST_FOR_EACH_SAFE( item, cursor, &package->components )
00175     {
00176         MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
00177 
00178         list_remove( &comp->entry );
00179         msi_free( comp->Component );
00180         msi_free( comp->ComponentId );
00181         msi_free( comp->Directory );
00182         msi_free( comp->Condition );
00183         msi_free( comp->KeyPath );
00184         msi_free( comp->FullKeypath );
00185         if (comp->assembly) free_assembly( comp->assembly );
00186         msi_free( comp );
00187     }
00188 
00189     LIST_FOR_EACH_SAFE( item, cursor, &package->files )
00190     {
00191         MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
00192 
00193         list_remove( &file->entry );
00194         msi_free( file->File );
00195         msi_free( file->FileName );
00196         msi_free( file->ShortName );
00197         msi_free( file->LongName );
00198         msi_free( file->Version );
00199         msi_free( file->Language );
00200         msi_free( file->TargetPath );
00201         msi_free( file );
00202     }
00203 
00204     /* clean up extension, progid, class and verb structures */
00205     LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
00206     {
00207         MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
00208 
00209         list_remove( &cls->entry );
00210         msi_free( cls->clsid );
00211         msi_free( cls->Context );
00212         msi_free( cls->Description );
00213         msi_free( cls->FileTypeMask );
00214         msi_free( cls->IconPath );
00215         msi_free( cls->DefInprocHandler );
00216         msi_free( cls->DefInprocHandler32 );
00217         msi_free( cls->Argument );
00218         msi_free( cls->ProgIDText );
00219         msi_free( cls );
00220     }
00221 
00222     LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
00223     {
00224         MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
00225 
00226         list_remove( &ext->entry );
00227         free_extension( ext );
00228     }
00229 
00230     LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
00231     {
00232         MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
00233 
00234         list_remove( &progid->entry );
00235         msi_free( progid->ProgID );
00236         msi_free( progid->Description );
00237         msi_free( progid->IconPath );
00238         msi_free( progid );
00239     }
00240 
00241     LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
00242     {
00243         MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
00244 
00245         list_remove( &mt->entry );
00246         msi_free( mt->suffix );
00247         msi_free( mt->clsid );
00248         msi_free( mt->ContentType );
00249         msi_free( mt );
00250     }
00251 
00252     LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
00253     {
00254         MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
00255 
00256         list_remove( &appid->entry );
00257         msi_free( appid->AppID );
00258         msi_free( appid->RemoteServerName );
00259         msi_free( appid->LocalServer );
00260         msi_free( appid->ServiceParameters );
00261         msi_free( appid->DllSurrogate );
00262         msi_free( appid );
00263     }
00264 
00265     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
00266     {
00267         MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
00268 
00269         list_remove( &info->entry );
00270         msi_free( info->value );
00271         msi_free( info );
00272     }
00273 
00274     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
00275     {
00276         MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
00277 
00278         list_remove( &info->entry );
00279         msi_free( info->volume_label );
00280         msi_free( info->disk_prompt );
00281         msi_free( info );
00282     }
00283 
00284     if (package->script)
00285     {
00286         for (i = 0; i < SCRIPT_MAX; i++)
00287             msi_free_action_script( package, i );
00288 
00289         for (i = 0; i < package->script->UniqueActionsCount; i++)
00290             msi_free( package->script->UniqueActions[i] );
00291 
00292         msi_free( package->script->UniqueActions );
00293         msi_free( package->script );
00294     }
00295 
00296     LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
00297     {
00298         MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry );
00299 
00300         list_remove( &binary->entry );
00301         if (binary->module)
00302             FreeLibrary( binary->module );
00303         if (!DeleteFileW( binary->tmpfile ))
00304             ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError());
00305         msi_free( binary->source );
00306         msi_free( binary->tmpfile );
00307         msi_free( binary );
00308     }
00309 
00310     LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams )
00311     {
00312         MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry );
00313 
00314         list_remove( &cab->entry );
00315         IStorage_Release( cab->storage );
00316         msi_free( cab->stream );
00317         msi_free( cab );
00318     }
00319 
00320     LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
00321     {
00322         MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
00323 
00324         list_remove( &patch->entry );
00325         if (patch->delete_on_close && !DeleteFileW( patch->localfile ))
00326         {
00327             ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError());
00328         }
00329         msi_free_patchinfo( patch );
00330     }
00331 
00332     msi_free( package->BaseURL );
00333     msi_free( package->PackagePath );
00334     msi_free( package->ProductCode );
00335     msi_free( package->ActionFormat );
00336     msi_free( package->LastAction );
00337     msi_free( package->langids );
00338 
00339     remove_tracked_tempfiles(package);
00340 
00341     /* cleanup control event subscriptions */
00342     ControlEvent_CleanupSubscriptions( package );
00343 }
00344 
00345 static void MSI_FreePackage( MSIOBJECTHDR *arg)
00346 {
00347     UINT i;
00348     MSIPACKAGE *package = (MSIPACKAGE *)arg;
00349 
00350     if( package->dialog )
00351         msi_dialog_destroy( package->dialog );
00352 
00353     msiobj_release( &package->db->hdr );
00354     free_package_structures(package);
00355     CloseHandle( package->log_file );
00356 
00357     for (i = 0; i < CLR_VERSION_MAX; i++)
00358         if (package->cache_net[i]) IAssemblyCache_Release( package->cache_net[i] );
00359     if (package->cache_sxs) IAssemblyCache_Release( package->cache_sxs );
00360 
00361     if (package->delete_on_close) DeleteFileW( package->localfile );
00362     msi_free( package->localfile );
00363 }
00364 
00365 static UINT create_temp_property_table(MSIPACKAGE *package)
00366 {
00367     static const WCHAR query[] = {
00368         'C','R','E','A','T','E',' ','T','A','B','L','E',' ',
00369         '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ',
00370         '`','_','P','r','o','p','e','r','t','y','`',' ',
00371         'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ',
00372         'T','E','M','P','O','R','A','R','Y',',',' ',
00373         '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ',
00374         'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y',
00375         ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ',
00376         '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0};
00377     MSIQUERY *view;
00378     UINT rc;
00379 
00380     rc = MSI_DatabaseOpenViewW(package->db, query, &view);
00381     if (rc != ERROR_SUCCESS)
00382         return rc;
00383 
00384     rc = MSI_ViewExecute(view, 0);
00385     MSI_ViewClose(view);
00386     msiobj_release(&view->hdr);
00387     return rc;
00388 }
00389 
00390 UINT msi_clone_properties(MSIPACKAGE *package)
00391 {
00392     static const WCHAR query_select[] = {
00393         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00394         '`','P','r','o','p','e','r','t','y','`',0};
00395     static const WCHAR query_insert[] = {
00396         'I','N','S','E','R','T',' ','I','N','T','O',' ',
00397         '`','_','P','r','o','p','e','r','t','y','`',' ',
00398         '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ',
00399         'V','A','L','U','E','S',' ','(','?',',','?',')',0};
00400     static const WCHAR query_update[] = {
00401         'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ',
00402         'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ',
00403         'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0};
00404     MSIQUERY *view_select;
00405     UINT rc;
00406 
00407     rc = MSI_DatabaseOpenViewW( package->db, query_select, &view_select );
00408     if (rc != ERROR_SUCCESS)
00409         return rc;
00410 
00411     rc = MSI_ViewExecute( view_select, 0 );
00412     if (rc != ERROR_SUCCESS)
00413     {
00414         MSI_ViewClose( view_select );
00415         msiobj_release( &view_select->hdr );
00416         return rc;
00417     }
00418 
00419     while (1)
00420     {
00421         MSIQUERY *view_insert, *view_update;
00422         MSIRECORD *rec_select;
00423 
00424         rc = MSI_ViewFetch( view_select, &rec_select );
00425         if (rc != ERROR_SUCCESS)
00426             break;
00427 
00428         rc = MSI_DatabaseOpenViewW( package->db, query_insert, &view_insert );
00429         if (rc != ERROR_SUCCESS)
00430         {
00431             msiobj_release( &rec_select->hdr );
00432             continue;
00433         }
00434 
00435         rc = MSI_ViewExecute( view_insert, rec_select );
00436         MSI_ViewClose( view_insert );
00437         msiobj_release( &view_insert->hdr );
00438         if (rc != ERROR_SUCCESS)
00439         {
00440             MSIRECORD *rec_update;
00441 
00442             TRACE("insert failed, trying update\n");
00443 
00444             rc = MSI_DatabaseOpenViewW( package->db, query_update, &view_update );
00445             if (rc != ERROR_SUCCESS)
00446             {
00447                 WARN("open view failed %u\n", rc);
00448                 msiobj_release( &rec_select->hdr );
00449                 continue;
00450             }
00451 
00452             rec_update = MSI_CreateRecord( 2 );
00453             MSI_RecordCopyField( rec_select, 1, rec_update, 2 );
00454             MSI_RecordCopyField( rec_select, 2, rec_update, 1 );
00455             rc = MSI_ViewExecute( view_update, rec_update );
00456             if (rc != ERROR_SUCCESS)
00457                 WARN("update failed %u\n", rc);
00458 
00459             MSI_ViewClose( view_update );
00460             msiobj_release( &view_update->hdr );
00461             msiobj_release( &rec_update->hdr );
00462         }
00463 
00464         msiobj_release( &rec_select->hdr );
00465     }
00466 
00467     MSI_ViewClose( view_select );
00468     msiobj_release( &view_select->hdr );
00469     return rc;
00470 }
00471 
00472 /*
00473  * set_installed_prop
00474  *
00475  * Sets the "Installed" property to indicate that
00476  *  the product is installed for the current user.
00477  */
00478 static UINT set_installed_prop( MSIPACKAGE *package )
00479 {
00480     HKEY hkey;
00481     UINT r;
00482 
00483     if (!package->ProductCode) return ERROR_FUNCTION_FAILED;
00484 
00485     r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE );
00486     if (r == ERROR_SUCCESS)
00487     {
00488         RegCloseKey( hkey );
00489         msi_set_property( package->db, szInstalled, szOne );
00490     }
00491     return r;
00492 }
00493 
00494 static UINT set_user_sid_prop( MSIPACKAGE *package )
00495 {
00496     SID_NAME_USE use;
00497     LPWSTR user_name;
00498     LPWSTR sid_str = NULL, dom = NULL;
00499     DWORD size, dom_size;
00500     PSID psid = NULL;
00501     UINT r = ERROR_FUNCTION_FAILED;
00502 
00503     size = 0;
00504     GetUserNameW( NULL, &size );
00505 
00506     user_name = msi_alloc( (size + 1) * sizeof(WCHAR) );
00507     if (!user_name)
00508         return ERROR_OUTOFMEMORY;
00509 
00510     if (!GetUserNameW( user_name, &size ))
00511         goto done;
00512 
00513     size = 0;
00514     dom_size = 0;
00515     LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use );
00516 
00517     psid = msi_alloc( size );
00518     dom = msi_alloc( dom_size*sizeof (WCHAR) );
00519     if (!psid || !dom)
00520     {
00521         r = ERROR_OUTOFMEMORY;
00522         goto done;
00523     }
00524 
00525     if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use ))
00526         goto done;
00527 
00528     if (!ConvertSidToStringSidW( psid, &sid_str ))
00529         goto done;
00530 
00531     r = msi_set_property( package->db, szUserSID, sid_str );
00532 
00533 done:
00534     LocalFree( sid_str );
00535     msi_free( dom );
00536     msi_free( psid );
00537     msi_free( user_name );
00538 
00539     return r;
00540 }
00541 
00542 static LPWSTR get_fusion_filename(MSIPACKAGE *package)
00543 {
00544     HKEY netsetup;
00545     LONG res;
00546     LPWSTR file = NULL;
00547     DWORD index = 0, size;
00548     WCHAR ver[MAX_PATH];
00549     WCHAR name[MAX_PATH];
00550     WCHAR windir[MAX_PATH];
00551 
00552     static const WCHAR fusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
00553     static const WCHAR sub[] = {
00554         'S','o','f','t','w','a','r','e','\\',
00555         'M','i','c','r','o','s','o','f','t','\\',
00556         'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\',
00557         'N','D','P',0
00558     };
00559     static const WCHAR subdir[] = {
00560         'M','i','c','r','o','s','o','f','t','.','N','E','T','\\',
00561         'F','r','a','m','e','w','o','r','k','\\',0
00562     };
00563 
00564     res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub, 0, KEY_ENUMERATE_SUB_KEYS, &netsetup);
00565     if (res != ERROR_SUCCESS)
00566         return NULL;
00567 
00568     GetWindowsDirectoryW(windir, MAX_PATH);
00569 
00570     ver[0] = '\0';
00571     size = MAX_PATH;
00572     while (RegEnumKeyExW(netsetup, index, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
00573     {
00574         index++;
00575 
00576         /* verify existence of fusion.dll .Net 3.0 does not install a new one */
00577         if (strcmpW( ver, name ) < 0)
00578         {
00579             LPWSTR check;
00580             size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3;
00581             check = msi_alloc(size * sizeof(WCHAR));
00582 
00583             if (!check)
00584             {
00585                 msi_free(file);
00586                 return NULL;
00587             }
00588 
00589             lstrcpyW(check, windir);
00590             lstrcatW(check, szBackSlash);
00591             lstrcatW(check, subdir);
00592             lstrcatW(check, name);
00593             lstrcatW(check, szBackSlash);
00594             lstrcatW(check, fusion);
00595 
00596             if(GetFileAttributesW(check) != INVALID_FILE_ATTRIBUTES)
00597             {
00598                 msi_free(file);
00599                 file = check;
00600                 lstrcpyW(ver, name);
00601             }
00602             else
00603                 msi_free(check);
00604         }
00605     }
00606 
00607     RegCloseKey(netsetup);
00608     return file;
00609 }
00610 
00611 typedef struct tagLANGANDCODEPAGE
00612 {
00613   WORD wLanguage;
00614   WORD wCodePage;
00615 } LANGANDCODEPAGE;
00616 
00617 static void set_msi_assembly_prop(MSIPACKAGE *package)
00618 {
00619     UINT val_len;
00620     DWORD size, handle;
00621     LPVOID version = NULL;
00622     WCHAR buf[MAX_PATH];
00623     LPWSTR fusion, verstr;
00624     LANGANDCODEPAGE *translate;
00625 
00626     static const WCHAR netasm[] = {
00627         'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0
00628     };
00629     static const WCHAR translation[] = {
00630         '\\','V','a','r','F','i','l','e','I','n','f','o',
00631         '\\','T','r','a','n','s','l','a','t','i','o','n',0
00632     };
00633     static const WCHAR verfmt[] = {
00634         '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
00635         '\\','%','0','4','x','%','0','4','x',
00636         '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0
00637     };
00638 
00639     fusion = get_fusion_filename(package);
00640     if (!fusion)
00641         return;
00642 
00643     size = GetFileVersionInfoSizeW(fusion, &handle);
00644     if (!size) return;
00645 
00646     version = msi_alloc(size);
00647     if (!version) return;
00648 
00649     if (!GetFileVersionInfoW(fusion, handle, size, version))
00650         goto done;
00651 
00652     if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len))
00653         goto done;
00654 
00655     sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage);
00656 
00657     if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len))
00658         goto done;
00659 
00660     if (!val_len || !verstr)
00661         goto done;
00662 
00663     msi_set_property(package->db, netasm, verstr);
00664 
00665 done:
00666     msi_free(fusion);
00667     msi_free(version);
00668 }
00669 
00670 static VOID set_installer_properties(MSIPACKAGE *package)
00671 {
00672     WCHAR pth[MAX_PATH];
00673     WCHAR *ptr;
00674     OSVERSIONINFOEXW OSVersion;
00675     MEMORYSTATUSEX msex;
00676     DWORD verval, len;
00677     WCHAR verstr[10], bufstr[20];
00678     HDC dc;
00679     HKEY hkey;
00680     LPWSTR username, companyname;
00681     SYSTEM_INFO sys_info;
00682     SYSTEMTIME systemtime;
00683     LANGID langid;
00684 
00685     static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
00686     static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
00687     static const WCHAR szCommonAppDataFolder[] = {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
00688     static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
00689     static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0};
00690     static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0};
00691     static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
00692     static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
00693     static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
00694     static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
00695     static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
00696     static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
00697     static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0};
00698     static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
00699     static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
00700     static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
00701     static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
00702     static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
00703     static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0};
00704     static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0};
00705     static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0};
00706     static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0};
00707     static const WCHAR szFormat[] = {'%','l','i',0};
00708     static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0};
00709     static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0};
00710     static const WCHAR szSix[] = {'6',0 };
00711     static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
00712     static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 };
00713     static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
00714     static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
00715     static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
00716     static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
00717     static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
00718     static const WCHAR szIntFormat[] = {'%','d',0};
00719     static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 };
00720     static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 };
00721     static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 };
00722     static const WCHAR szCommonFiles64Folder[] = { 'C','o','m','m','o','n','F','i','l','e','s','6','4','F','o','l','d','e','r',0 };
00723     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 };
00724     static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 };
00725     static const WCHAR szUserInfo[] = {
00726         'S','O','F','T','W','A','R','E','\\',
00727         'M','i','c','r','o','s','o','f','t','\\',
00728         'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\',
00729         'U','s','e','r',' ','I','n','f','o',0
00730     };
00731     static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 };
00732     static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 };
00733     static const WCHAR szCurrentVersion[] = {
00734         'S','O','F','T','W','A','R','E','\\',
00735         'M','i','c','r','o','s','o','f','t','\\',
00736         'W','i','n','d','o','w','s',' ','N','T','\\',
00737         'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
00738     };
00739     static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0};
00740     static const WCHAR szRegisteredOrganization[] = {
00741         'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0
00742     };
00743     static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0};
00744     static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
00745     static const WCHAR szDate[] = {'D','a','t','e',0};
00746     static const WCHAR szTime[] = {'T','i','m','e',0};
00747     static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
00748     static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0};
00749     static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0};
00750     static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0};
00751     static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0};
00752     static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0};
00753     static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0};
00754     static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
00755 
00756     /*
00757      * Other things that probably should be set:
00758      *
00759      * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging
00760      * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport
00761      */
00762 
00763     SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
00764     strcatW(pth, szBackSlash);
00765     msi_set_property(package->db, szCommonAppDataFolder, pth);
00766 
00767     SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
00768     strcatW(pth, szBackSlash);
00769     msi_set_property(package->db, szFavoritesFolder, pth);
00770 
00771     SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
00772     strcatW(pth, szBackSlash);
00773     msi_set_property(package->db, szFontsFolder, pth);
00774 
00775     SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
00776     strcatW(pth, szBackSlash);
00777     msi_set_property(package->db, szSendToFolder, pth);
00778 
00779     SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
00780     strcatW(pth, szBackSlash);
00781     msi_set_property(package->db, szStartMenuFolder, pth);
00782 
00783     SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
00784     strcatW(pth, szBackSlash);
00785     msi_set_property(package->db, szStartupFolder, pth);
00786 
00787     SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
00788     strcatW(pth, szBackSlash);
00789     msi_set_property(package->db, szTemplateFolder, pth);
00790 
00791     SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
00792     strcatW(pth, szBackSlash);
00793     msi_set_property(package->db, szDesktopFolder, pth);
00794 
00795     /* FIXME: set to AllUsers profile path if ALLUSERS is set */
00796     SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
00797     strcatW(pth, szBackSlash);
00798     msi_set_property(package->db, szProgramMenuFolder, pth);
00799 
00800     SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
00801     strcatW(pth, szBackSlash);
00802     msi_set_property(package->db, szAdminToolsFolder, pth);
00803 
00804     SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
00805     strcatW(pth, szBackSlash);
00806     msi_set_property(package->db, szAppDataFolder, pth);
00807 
00808     SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
00809     strcatW(pth, szBackSlash);
00810     msi_set_property(package->db, szSystemFolder, pth);
00811     msi_set_property(package->db, szSystem16Folder, pth);
00812 
00813     SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
00814     strcatW(pth, szBackSlash);
00815     msi_set_property(package->db, szLocalAppDataFolder, pth);
00816 
00817     SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
00818     strcatW(pth, szBackSlash);
00819     msi_set_property(package->db, szMyPicturesFolder, pth);
00820 
00821     SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
00822     strcatW(pth, szBackSlash);
00823     msi_set_property(package->db, szPersonalFolder, pth);
00824 
00825     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
00826     strcatW(pth, szBackSlash);
00827     msi_set_property(package->db, szWindowsFolder, pth);
00828     
00829     SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
00830     strcatW(pth, szBackSlash);
00831     msi_set_property(package->db, szPrintHoodFolder, pth);
00832 
00833     SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
00834     strcatW(pth, szBackSlash);
00835     msi_set_property(package->db, szNetHoodFolder, pth);
00836 
00837     SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
00838     strcatW(pth, szBackSlash);
00839     msi_set_property(package->db, szRecentFolder, pth);
00840 
00841     /* Physical Memory is specified in MB. Using total amount. */
00842     msex.dwLength = sizeof(msex);
00843     GlobalMemoryStatusEx( &msex );
00844     sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
00845     msi_set_property(package->db, szPhysicalMemory, bufstr);
00846 
00847     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
00848     ptr = strchrW(pth,'\\');
00849     if (ptr) *(ptr + 1) = 0;
00850     msi_set_property(package->db, szWindowsVolume, pth);
00851     
00852     GetTempPathW(MAX_PATH,pth);
00853     msi_set_property(package->db, szTempFolder, pth);
00854 
00855     /* in a wine environment the user is always admin and privileged */
00856     msi_set_property(package->db, szAdminUser, szOne);
00857     msi_set_property(package->db, szPrivileged, szOne);
00858 
00859     /* set the os things */
00860     OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
00861     GetVersionExW((OSVERSIONINFOW *)&OSVersion);
00862     verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
00863     sprintfW(verstr, szFormat, verval);
00864     switch (OSVersion.dwPlatformId)
00865     {
00866         case VER_PLATFORM_WIN32_WINDOWS:    
00867             msi_set_property(package->db, szVersion9x, verstr);
00868             break;
00869         case VER_PLATFORM_WIN32_NT:
00870             msi_set_property(package->db, szVersionNT, verstr);
00871             sprintfW(verstr, szFormat,OSVersion.wProductType);
00872             msi_set_property(package->db, szMsiNTProductType, verstr);
00873             break;
00874     }
00875     sprintfW(verstr, szFormat, OSVersion.dwBuildNumber);
00876     msi_set_property(package->db, szWindowsBuild, verstr);
00877     /* just fudge this */
00878     msi_set_property(package->db, szServicePackLevel, szSix);
00879 
00880     sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
00881     msi_set_property( package->db, szVersionMsi, bufstr );
00882     sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100);
00883     msi_set_property( package->db, szVersionDatabase, bufstr );
00884 
00885     GetNativeSystemInfo( &sys_info );
00886     sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
00887     msi_set_property( package->db, szIntel, bufstr );
00888     if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
00889     {
00890         GetSystemDirectoryW( pth, MAX_PATH );
00891         PathAddBackslashW( pth );
00892         msi_set_property( package->db, szSystemFolder, pth );
00893 
00894         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
00895         PathAddBackslashW( pth );
00896         msi_set_property( package->db, szProgramFilesFolder, pth );
00897 
00898         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
00899         PathAddBackslashW( pth );
00900         msi_set_property( package->db, szCommonFilesFolder, pth );
00901     }
00902     else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
00903     {
00904         msi_set_property( package->db, szMsiAMD64, bufstr );
00905         msi_set_property( package->db, szMsix64, bufstr );
00906         msi_set_property( package->db, szVersionNT64, verstr );
00907 
00908         GetSystemDirectoryW( pth, MAX_PATH );
00909         PathAddBackslashW( pth );
00910         msi_set_property( package->db, szSystem64Folder, pth );
00911 
00912         GetSystemWow64DirectoryW( pth, MAX_PATH );
00913         PathAddBackslashW( pth );
00914         msi_set_property( package->db, szSystemFolder, pth );
00915 
00916         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
00917         PathAddBackslashW( pth );
00918         msi_set_property( package->db, szProgramFiles64Folder, pth );
00919 
00920         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth );
00921         PathAddBackslashW( pth );
00922         msi_set_property( package->db, szProgramFilesFolder, pth );
00923 
00924         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
00925         PathAddBackslashW( pth );
00926         msi_set_property( package->db, szCommonFiles64Folder, pth );
00927 
00928         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth );
00929         PathAddBackslashW( pth );
00930         msi_set_property( package->db, szCommonFilesFolder, pth );
00931     }
00932 
00933     /* Screen properties. */
00934     dc = GetDC(0);
00935     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
00936     msi_set_property( package->db, szScreenX, bufstr );
00937     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
00938     msi_set_property( package->db, szScreenY, bufstr );
00939     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
00940     msi_set_property( package->db, szColorBits, bufstr );
00941     ReleaseDC(0, dc);
00942 
00943     /* USERNAME and COMPANYNAME */
00944     username = msi_dup_property( package->db, szUSERNAME );
00945     companyname = msi_dup_property( package->db, szCOMPANYNAME );
00946 
00947     if ((!username || !companyname) &&
00948         RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS)
00949     {
00950         if (!username &&
00951             (username = msi_reg_get_val_str( hkey, szDefName )))
00952             msi_set_property( package->db, szUSERNAME, username );
00953         if (!companyname &&
00954             (companyname = msi_reg_get_val_str( hkey, szDefCompany )))
00955             msi_set_property( package->db, szCOMPANYNAME, companyname );
00956         CloseHandle( hkey );
00957     }
00958     if ((!username || !companyname) &&
00959         RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS)
00960     {
00961         if (!username &&
00962             (username = msi_reg_get_val_str( hkey, szRegisteredUser )))
00963             msi_set_property( package->db, szUSERNAME, username );
00964         if (!companyname &&
00965             (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization )))
00966             msi_set_property( package->db, szCOMPANYNAME, companyname );
00967         CloseHandle( hkey );
00968     }
00969     msi_free( username );
00970     msi_free( companyname );
00971 
00972     if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
00973         ERR("Failed to set the UserSID property\n");
00974 
00975     /* Date and time properties */
00976     GetSystemTime( &systemtime );
00977     if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime,
00978                         NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) ))
00979         msi_set_property( package->db, szDate, bufstr );
00980     else
00981         ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError());
00982 
00983     if (GetTimeFormatW( LOCALE_USER_DEFAULT,
00984                         TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
00985                         &systemtime, NULL, bufstr,
00986                         sizeof(bufstr)/sizeof(bufstr[0]) ))
00987         msi_set_property( package->db, szTime, bufstr );
00988     else
00989         ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError());
00990 
00991     set_msi_assembly_prop( package );
00992 
00993     langid = GetUserDefaultLangID();
00994     sprintfW(bufstr, szIntFormat, langid);
00995     msi_set_property( package->db, szUserLanguageID, bufstr );
00996 
00997     langid = GetSystemDefaultLangID();
00998     sprintfW(bufstr, szIntFormat, langid);
00999     msi_set_property( package->db, szSystemLangID, bufstr );
01000 
01001     sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode));
01002     msi_set_property( package->db, szProductState, bufstr );
01003 
01004     len = 0;
01005     if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
01006     {
01007         WCHAR *username;
01008         if ((username = msi_alloc( len * sizeof(WCHAR) )))
01009         {
01010             if (GetUserNameW( username, &len ))
01011                 msi_set_property( package->db, szLogonUser, username );
01012             msi_free( username );
01013         }
01014     }
01015     len = 0;
01016     if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW)
01017     {
01018         WCHAR *computername;
01019         if ((computername = msi_alloc( len * sizeof(WCHAR) )))
01020         {
01021             if (GetComputerNameW( computername, &len ))
01022                 msi_set_property( package->db, szComputerName, computername );
01023             msi_free( computername );
01024         }
01025     }
01026 }
01027 
01028 static UINT msi_load_summary_properties( MSIPACKAGE *package )
01029 {
01030     UINT rc;
01031     MSIHANDLE suminfo;
01032     MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
01033     INT count;
01034     DWORD len;
01035     LPWSTR package_code;
01036     static const WCHAR szPackageCode[] = {
01037         'P','a','c','k','a','g','e','C','o','d','e',0};
01038 
01039     if (!hdb) {
01040         ERR("Unable to allocate handle\n");
01041         return ERROR_OUTOFMEMORY;
01042     }
01043 
01044     rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
01045     MsiCloseHandle(hdb);
01046     if (rc != ERROR_SUCCESS)
01047     {
01048         ERR("Unable to open Summary Information\n");
01049         return rc;
01050     }
01051 
01052     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_PAGECOUNT, NULL,
01053                                      &count, NULL, NULL, NULL );
01054     if (rc != ERROR_SUCCESS)
01055     {
01056         WARN("Unable to query page count: %d\n", rc);
01057         goto done;
01058     }
01059 
01060     /* load package code property */
01061     len = 0;
01062     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
01063                                      NULL, NULL, NULL, &len );
01064     if (rc != ERROR_MORE_DATA)
01065     {
01066         WARN("Unable to query revision number: %d\n", rc);
01067         rc = ERROR_FUNCTION_FAILED;
01068         goto done;
01069     }
01070 
01071     len++;
01072     package_code = msi_alloc( len * sizeof(WCHAR) );
01073     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
01074                                      NULL, NULL, package_code, &len );
01075     if (rc != ERROR_SUCCESS)
01076     {
01077         WARN("Unable to query rev number: %d\n", rc);
01078         goto done;
01079     }
01080 
01081     msi_set_property( package->db, szPackageCode, package_code );
01082     msi_free( package_code );
01083 
01084     /* load package attributes */
01085     count = 0;
01086     MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
01087                                 &count, NULL, NULL, NULL );
01088     package->WordCount = count;
01089 
01090 done:
01091     MsiCloseHandle(suminfo);
01092     return rc;
01093 }
01094 
01095 static MSIPACKAGE *msi_alloc_package( void )
01096 {
01097     MSIPACKAGE *package;
01098 
01099     package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
01100                                MSI_FreePackage );
01101     if( package )
01102     {
01103         list_init( &package->components );
01104         list_init( &package->features );
01105         list_init( &package->files );
01106         list_init( &package->filepatches );
01107         list_init( &package->tempfiles );
01108         list_init( &package->folders );
01109         list_init( &package->subscriptions );
01110         list_init( &package->appids );
01111         list_init( &package->classes );
01112         list_init( &package->mimes );
01113         list_init( &package->extensions );
01114         list_init( &package->progids );
01115         list_init( &package->RunningActions );
01116         list_init( &package->sourcelist_info );
01117         list_init( &package->sourcelist_media );
01118         list_init( &package->patches );
01119         list_init( &package->binaries );
01120         list_init( &package->cabinet_streams );
01121     }
01122 
01123     return package;
01124 }
01125 
01126 static UINT msi_load_admin_properties(MSIPACKAGE *package)
01127 {
01128     BYTE *data;
01129     UINT r, sz;
01130 
01131     static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0};
01132 
01133     r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz);
01134     if (r != ERROR_SUCCESS)
01135         return r;
01136 
01137     r = msi_parse_command_line(package, (WCHAR *)data, TRUE);
01138 
01139     msi_free(data);
01140     return r;
01141 }
01142 
01143 void msi_adjust_privilege_properties( MSIPACKAGE *package )
01144 {
01145     /* FIXME: this should depend on the user's privileges */
01146     if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
01147     {
01148         TRACE("resetting ALLUSERS property from 2 to 1\n");
01149         msi_set_property( package->db, szAllUsers, szOne );
01150     }
01151     msi_set_property( package->db, szAdminUser, szOne );
01152 }
01153 
01154 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
01155 {
01156     static const WCHAR fmtW[] = {'%','u',0};
01157     MSIPACKAGE *package;
01158     WCHAR uilevel[11];
01159     UINT r;
01160 
01161     TRACE("%p\n", db);
01162 
01163     package = msi_alloc_package();
01164     if (package)
01165     {
01166         msiobj_addref( &db->hdr );
01167         package->db = db;
01168 
01169         package->WordCount = 0;
01170         package->PackagePath = strdupW( db->path );
01171         package->BaseURL = strdupW( base_url );
01172 
01173         create_temp_property_table( package );
01174         msi_clone_properties( package );
01175         msi_adjust_privilege_properties( package );
01176 
01177         package->ProductCode = msi_dup_property( package->db, szProductCode );
01178         package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
01179 
01180         set_installed_prop( package );
01181         set_installer_properties( package );
01182 
01183         package->ui_level = gUILevel;
01184         sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
01185         msi_set_property(package->db, szUILevel, uilevel);
01186 
01187         r = msi_load_summary_properties( package );
01188         if (r != ERROR_SUCCESS)
01189         {
01190             msiobj_release( &package->hdr );
01191             return NULL;
01192         }
01193 
01194         if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
01195             msi_load_admin_properties( package );
01196 
01197         package->log_file = INVALID_HANDLE_VALUE;
01198     }
01199     return package;
01200 }
01201 
01202 UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
01203 {
01204     LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
01205     DWORD size = 0;
01206     HRESULT hr;
01207 
01208     /* call will always fail, because size is 0,
01209      * but will return ERROR_FILE_NOT_FOUND first
01210      * if the file doesn't exist
01211      */
01212     GetUrlCacheEntryInfoW( szUrl, NULL, &size );
01213     if ( GetLastError() != ERROR_FILE_NOT_FOUND )
01214     {
01215         cache_entry = msi_alloc( size );
01216         if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
01217         {
01218             UINT error = GetLastError();
01219             msi_free( cache_entry );
01220             return error;
01221         }
01222 
01223         lstrcpyW( filename, cache_entry->lpszLocalFileName );
01224         msi_free( cache_entry );
01225         return ERROR_SUCCESS;
01226     }
01227 
01228     hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
01229     if ( FAILED(hr) )
01230     {
01231         WARN("failed to download %s to cache file\n", debugstr_w(szUrl));
01232         return ERROR_FUNCTION_FAILED;
01233     }
01234 
01235     return ERROR_SUCCESS;
01236 }
01237 
01238 UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
01239 {
01240     static const WCHAR szInstaller[] = {
01241         '\\','I','n','s','t','a','l','l','e','r','\\',0};
01242     static const WCHAR fmt[] = {'%','x',0};
01243     DWORD time, len, i, offset;
01244     HANDLE handle;
01245 
01246     time = GetTickCount();
01247     GetWindowsDirectoryW( path, MAX_PATH );
01248     strcatW( path, szInstaller );
01249     CreateDirectoryW( path, NULL );
01250 
01251     len = strlenW(path);
01252     for (i = 0; i < 0x10000; i++)
01253     {
01254         offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff );
01255         memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) );
01256         handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
01257                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
01258         if (handle != INVALID_HANDLE_VALUE)
01259         {
01260             CloseHandle(handle);
01261             break;
01262         }
01263         if (GetLastError() != ERROR_FILE_EXISTS &&
01264             GetLastError() != ERROR_SHARING_VIOLATION)
01265             return ERROR_FUNCTION_FAILED;
01266     }
01267 
01268     return ERROR_SUCCESS;
01269 }
01270 
01271 static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
01272 {
01273     WCHAR *template, *p, *q;
01274     DWORD i, count;
01275 
01276     package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
01277     TRACE("version: %d\n", package->version);
01278 
01279     template = msi_suminfo_dup_string( si, PID_TEMPLATE );
01280     if (!template)
01281         return ERROR_SUCCESS; /* native accepts missing template property */
01282 
01283     TRACE("template: %s\n", debugstr_w(template));
01284 
01285     p = strchrW( template, ';' );
01286     if (!p)
01287     {
01288         WARN("invalid template string %s\n", debugstr_w(template));
01289         msi_free( template );
01290         return ERROR_PATCH_PACKAGE_INVALID;
01291     }
01292     *p = 0;
01293     if ((q = strchrW( template, ',' ))) *q = 0;
01294     if (!template[0] || !strcmpW( template, szIntel ))
01295         package->platform = PLATFORM_INTEL;
01296     else if (!strcmpW( template, szIntel64 ))
01297         package->platform = PLATFORM_INTEL64;
01298     else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 ))
01299         package->platform = PLATFORM_X64;
01300     else if (!strcmpW( template, szARM ))
01301         package->platform = PLATFORM_ARM;
01302     else
01303     {
01304         WARN("unknown platform %s\n", debugstr_w(template));
01305         msi_free( template );
01306         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
01307     }
01308     p++;
01309     if (!*p)
01310     {
01311         msi_free( template );
01312         return ERROR_SUCCESS;
01313     }
01314     count = 1;
01315     for (q = p; (q = strchrW( q, ',' )); q++) count++;
01316 
01317     package->langids = msi_alloc( count * sizeof(LANGID) );
01318     if (!package->langids)
01319     {
01320         msi_free( template );
01321         return ERROR_OUTOFMEMORY;
01322     }
01323 
01324     i = 0;
01325     while (*p)
01326     {
01327         q = strchrW( p, ',' );
01328         if (q) *q = 0;
01329         package->langids[i] = atoiW( p );
01330         if (!q) break;
01331         p = q + 1;
01332         i++;
01333     }
01334     package->num_langids = i + 1;
01335 
01336     msi_free( template );
01337     return ERROR_SUCCESS;
01338 }
01339 
01340 static UINT validate_package( MSIPACKAGE *package )
01341 {
01342     BOOL is_wow64;
01343     UINT i;
01344 
01345     if (package->platform == PLATFORM_INTEL64)
01346         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
01347 #ifndef __arm__
01348     if (package->platform == PLATFORM_ARM)
01349         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
01350 #endif
01351     IsWow64Process( GetCurrentProcess(), &is_wow64 );
01352     if (package->platform == PLATFORM_X64)
01353     {
01354         if (!is_64bit && !is_wow64)
01355             return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
01356         if (package->version < 200)
01357             return ERROR_INSTALL_PACKAGE_INVALID;
01358     }
01359     if (!package->num_langids)
01360     {
01361         return ERROR_SUCCESS;
01362     }
01363     for (i = 0; i < package->num_langids; i++)
01364     {
01365         LANGID langid = package->langids[i];
01366 
01367         if (PRIMARYLANGID( langid ) == LANG_NEUTRAL)
01368         {
01369             langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) );
01370         }
01371         if (SUBLANGID( langid ) == SUBLANG_NEUTRAL)
01372         {
01373             langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) );
01374         }
01375         if (IsValidLocale( langid, LCID_INSTALLED ))
01376             return ERROR_SUCCESS;
01377     }
01378     return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
01379 }
01380 
01381 int msi_track_tempfile( MSIPACKAGE *package, const WCHAR *path )
01382 {
01383     MSITEMPFILE *temp;
01384 
01385     TRACE("%s\n", debugstr_w(path));
01386 
01387     LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
01388     {
01389         if (!strcmpW( path, temp->Path )) return 0;
01390     }
01391     if (!(temp = msi_alloc_zero( sizeof (MSITEMPFILE) ))) return -1;
01392     list_add_head( &package->tempfiles, &temp->entry );
01393     temp->Path = strdupW( path );
01394     return 0;
01395 }
01396 
01397 static WCHAR *get_product_code( MSIDATABASE *db )
01398 {
01399     static const WCHAR query[] = {
01400         'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
01401         'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ',
01402         'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=',
01403         '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0};
01404     MSIQUERY *view;
01405     MSIRECORD *rec;
01406     WCHAR *ret = NULL;
01407 
01408     if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS)
01409     {
01410         return NULL;
01411     }
01412     if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS)
01413     {
01414         MSI_ViewClose( view );
01415         msiobj_release( &view->hdr );
01416         return NULL;
01417     }
01418     if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
01419     {
01420         ret = strdupW( MSI_RecordGetString( rec, 1 ) );
01421         msiobj_release( &rec->hdr );
01422     }
01423     MSI_ViewClose( view );
01424     msiobj_release( &view->hdr );
01425     return ret;
01426 }
01427 
01428 static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile )
01429 {
01430     MSIINSTALLCONTEXT context;
01431     HKEY product_key, props_key;
01432     WCHAR *registered_package = NULL, unsquashed[GUID_SIZE];
01433     UINT r;
01434 
01435     r = msi_locate_product( product, &context );
01436     if (r != ERROR_SUCCESS)
01437         return r;
01438 
01439     r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE );
01440     if (r != ERROR_SUCCESS)
01441         return r;
01442 
01443     r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE );
01444     if (r != ERROR_SUCCESS)
01445     {
01446         RegCloseKey( product_key );
01447         return r;
01448     }
01449     r = ERROR_FUNCTION_FAILED;
01450     registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW );
01451     if (!registered_package)
01452         goto done;
01453 
01454     unsquash_guid( registered_package, unsquashed );
01455     if (!strcmpiW( package, unsquashed ))
01456     {
01457         WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
01458         if (!filename)
01459             goto done;
01460 
01461         strcpyW( localfile, filename );
01462         msi_free( filename );
01463         r = ERROR_SUCCESS;
01464     }
01465 done:
01466     msi_free( registered_package );
01467     RegCloseKey( props_key );
01468     RegCloseKey( product_key );
01469     return r;
01470 }
01471 
01472 static WCHAR *get_package_code( MSIDATABASE *db )
01473 {
01474     WCHAR *ret;
01475     MSISUMMARYINFO *si;
01476 
01477     if (!(si = MSI_GetSummaryInformationW( db->storage, 0 )))
01478     {
01479         WARN("failed to load summary info\n");
01480         return NULL;
01481     }
01482     ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
01483     msiobj_release( &si->hdr );
01484     return ret;
01485 }
01486 
01487 static UINT get_local_package( const WCHAR *filename, WCHAR *localfile )
01488 {
01489     WCHAR *product_code, *package_code;
01490     MSIDATABASE *db;
01491     UINT r;
01492 
01493     if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS)
01494     {
01495         if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES)
01496             return ERROR_FILE_NOT_FOUND;
01497         return r;
01498     }
01499     if (!(product_code = get_product_code( db )))
01500     {
01501         msiobj_release( &db->hdr );
01502         return ERROR_INSTALL_PACKAGE_INVALID;
01503     }
01504     if (!(package_code = get_package_code( db )))
01505     {
01506         msi_free( product_code );
01507         msiobj_release( &db->hdr );
01508         return ERROR_INSTALL_PACKAGE_INVALID;
01509     }
01510     r = get_registered_local_package( product_code, package_code, localfile );
01511     msi_free( package_code );
01512     msi_free( product_code );
01513     msiobj_release( &db->hdr );
01514     return r;
01515 }
01516 
01517 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
01518 {
01519     static const WCHAR dotmsi[] = {'.','m','s','i',0};
01520     MSIDATABASE *db;
01521     MSIPACKAGE *package;
01522     MSIHANDLE handle;
01523     LPWSTR ptr, base_url = NULL;
01524     UINT r;
01525     WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
01526     LPCWSTR file = szPackage;
01527     DWORD index = 0;
01528     MSISUMMARYINFO *si;
01529     BOOL delete_on_close = FALSE;
01530 
01531     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
01532 
01533     localfile[0] = 0;
01534     if( szPackage[0] == '#' )
01535     {
01536         handle = atoiW(&szPackage[1]);
01537         db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
01538         if( !db )
01539         {
01540             IWineMsiRemoteDatabase *remote_database;
01541 
01542             remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( handle );
01543             if ( !remote_database )
01544                 return ERROR_INVALID_HANDLE;
01545 
01546             IWineMsiRemoteDatabase_Release( remote_database );
01547             WARN("MsiOpenPackage not allowed during a custom action!\n");
01548 
01549             return ERROR_FUNCTION_FAILED;
01550         }
01551     }
01552     else
01553     {
01554         if ( UrlIsW( szPackage, URLIS_URL ) )
01555         {
01556             r = msi_download_file( szPackage, cachefile );
01557             if (r != ERROR_SUCCESS)
01558                 return r;
01559 
01560             file = cachefile;
01561 
01562             base_url = strdupW( szPackage );
01563             if (!base_url)
01564                 return ERROR_OUTOFMEMORY;
01565 
01566             ptr = strrchrW( base_url, '/' );
01567             if (ptr) *(ptr + 1) = '\0';
01568         }
01569         r = get_local_package( file, localfile );
01570         if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES)
01571         {
01572             r = msi_create_empty_local_file( localfile, dotmsi );
01573             if (r != ERROR_SUCCESS)
01574                 return r;
01575 
01576             if (!CopyFileW( file, localfile, FALSE ))
01577             {
01578                 r = GetLastError();
01579                 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
01580                 DeleteFileW( localfile );
01581                 return r;
01582             }
01583             delete_on_close = TRUE;
01584         }
01585         TRACE("opening package %s\n", debugstr_w( localfile ));
01586         r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
01587         if (r != ERROR_SUCCESS)
01588             return r;
01589     }
01590     package = MSI_CreatePackage( db, base_url );
01591     msi_free( base_url );
01592     msiobj_release( &db->hdr );
01593     if (!package) return ERROR_INSTALL_PACKAGE_INVALID;
01594     package->localfile = strdupW( localfile );
01595     package->delete_on_close = delete_on_close;
01596 
01597     si = MSI_GetSummaryInformationW( db->storage, 0 );
01598     if (!si)
01599     {
01600         WARN("failed to load summary info\n");
01601         msiobj_release( &package->hdr );
01602         return ERROR_INSTALL_PACKAGE_INVALID;
01603     }
01604     r = msi_parse_summary( si, package );
01605     msiobj_release( &si->hdr );
01606     if (r != ERROR_SUCCESS)
01607     {
01608         WARN("failed to parse summary info %u\n", r);
01609         msiobj_release( &package->hdr );
01610         return r;
01611     }
01612     r = validate_package( package );
01613     if (r != ERROR_SUCCESS)
01614     {
01615         msiobj_release( &package->hdr );
01616         return r;
01617     }
01618     msi_set_property( package->db, szDatabase, db->path );
01619 
01620     if( UrlIsW( szPackage, URLIS_URL ) )
01621         msi_set_property( package->db, szOriginalDatabase, szPackage );
01622     else if( szPackage[0] == '#' )
01623         msi_set_property( package->db, szOriginalDatabase, db->path );
01624     else
01625     {
01626         WCHAR fullpath[MAX_PATH];
01627 
01628         GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
01629         msi_set_property( package->db, szOriginalDatabase, fullpath );
01630     }
01631     msi_set_context( package );
01632 
01633     while (1)
01634     {
01635         WCHAR patch_code[GUID_SIZE];
01636         r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context,
01637                                MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL );
01638         if (r != ERROR_SUCCESS)
01639             break;
01640 
01641         TRACE("found registered patch %s\n", debugstr_w(patch_code));
01642 
01643         r = msi_apply_registered_patch( package, patch_code );
01644         if (r != ERROR_SUCCESS)
01645         {
01646             ERR("registered patch failed to apply %u\n", r);
01647             msiobj_release( &package->hdr );
01648             return r;
01649         }
01650         index++;
01651     }
01652     if (index)
01653     {
01654         msi_clone_properties( package );
01655         msi_adjust_privilege_properties( package );
01656     }
01657     if (gszLogFile)
01658         package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
01659                                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
01660     *pPackage = package;
01661     return ERROR_SUCCESS;
01662 }
01663 
01664 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
01665 {
01666     MSIPACKAGE *package = NULL;
01667     UINT ret;
01668 
01669     TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage );
01670 
01671     if( !szPackage || !phPackage )
01672         return ERROR_INVALID_PARAMETER;
01673 
01674     if ( !*szPackage )
01675     {
01676         FIXME("Should create an empty database and package\n");
01677         return ERROR_FUNCTION_FAILED;
01678     }
01679 
01680     if( dwOptions )
01681         FIXME("dwOptions %08x not supported\n", dwOptions);
01682 
01683     ret = MSI_OpenPackageW( szPackage, &package );
01684     if( ret == ERROR_SUCCESS )
01685     {
01686         *phPackage = alloc_msihandle( &package->hdr );
01687         if (! *phPackage)
01688             ret = ERROR_NOT_ENOUGH_MEMORY;
01689         msiobj_release( &package->hdr );
01690     }
01691 
01692     return ret;
01693 }
01694 
01695 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
01696 {
01697     return MsiOpenPackageExW( szPackage, 0, phPackage );
01698 }
01699 
01700 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
01701 {
01702     LPWSTR szwPack = NULL;
01703     UINT ret;
01704 
01705     if( szPackage )
01706     {
01707         szwPack = strdupAtoW( szPackage );
01708         if( !szwPack )
01709             return ERROR_OUTOFMEMORY;
01710     }
01711 
01712     ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
01713 
01714     msi_free( szwPack );
01715 
01716     return ret;
01717 }
01718 
01719 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
01720 {
01721     return MsiOpenPackageExA( szPackage, 0, phPackage );
01722 }
01723 
01724 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
01725 {
01726     MSIPACKAGE *package;
01727     MSIHANDLE handle = 0;
01728     IUnknown *remote_unk;
01729     IWineMsiRemotePackage *remote_package;
01730 
01731     TRACE("(%d)\n",hInstall);
01732 
01733     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
01734     if( package)
01735     {
01736         handle = alloc_msihandle( &package->db->hdr );
01737         msiobj_release( &package->hdr );
01738     }
01739     else if ((remote_unk = msi_get_remote(hInstall)))
01740     {
01741         if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage,
01742                                         (LPVOID *)&remote_package) == S_OK)
01743         {
01744             IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle);
01745             IWineMsiRemotePackage_Release(remote_package);
01746         }
01747         else
01748         {
01749             WARN("remote handle %d is not a package\n", hInstall);
01750         }
01751         IUnknown_Release(remote_unk);
01752     }
01753 
01754     return handle;
01755 }
01756 
01757 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
01758 {
01759     static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0};
01760     static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
01761     static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0};
01762     MSIRECORD *uirow;
01763     LPWSTR deformated, message;
01764     DWORD i, len, total_len, log_type = 0;
01765     INT rc = 0;
01766     char *msg;
01767 
01768     TRACE("%x\n", eMessageType);
01769 
01770     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_FATALEXIT)
01771         log_type |= INSTALLLOGMODE_FATALEXIT;
01772     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
01773         log_type |= INSTALLLOGMODE_ERROR;
01774     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
01775         log_type |= INSTALLLOGMODE_WARNING;
01776     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
01777         log_type |= INSTALLLOGMODE_USER;
01778     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
01779         log_type |= INSTALLLOGMODE_INFO;
01780     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_RESOLVESOURCE)
01781         log_type |= INSTALLLOGMODE_RESOLVESOURCE;
01782     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_OUTOFDISKSPACE)
01783         log_type |= INSTALLLOGMODE_OUTOFDISKSPACE;
01784     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
01785         log_type |= INSTALLLOGMODE_COMMONDATA;
01786     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
01787         log_type |= INSTALLLOGMODE_ACTIONSTART;
01788     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
01789         log_type |= INSTALLLOGMODE_ACTIONDATA;
01790     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
01791         log_type |= INSTALLLOGMODE_PROGRESS;
01792     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE)
01793         log_type |= INSTALLLOGMODE_INITIALIZE;
01794     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
01795         log_type |= INSTALLLOGMODE_TERMINATE;
01796     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG)
01797         log_type |= INSTALLLOGMODE_SHOWDIALOG;
01798 
01799     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
01800     {
01801         static const WCHAR template_s[]=
01802             {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0};
01803         static const WCHAR format[] = 
01804             {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
01805         WCHAR timet[0x100];
01806         LPCWSTR action_text, action;
01807         LPWSTR deformatted = NULL;
01808 
01809         GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
01810 
01811         action = MSI_RecordGetString(record, 1);
01812         action_text = MSI_RecordGetString(record, 2);
01813 
01814         if (!action || !action_text)
01815             return IDOK;
01816 
01817         deformat_string(package, action_text, &deformatted);
01818 
01819         len = strlenW(timet) + strlenW(action) + strlenW(template_s);
01820         if (deformatted)
01821             len += strlenW(deformatted);
01822         message = msi_alloc(len*sizeof(WCHAR));
01823         sprintfW(message, template_s, timet, action);
01824         if (deformatted)
01825             strcatW(message, deformatted);
01826         msi_free(deformatted);
01827     }
01828     else
01829     {
01830         static const WCHAR format[] = {'%','u',':',' ',0};
01831         UINT count = MSI_RecordGetFieldCount( record );
01832         WCHAR *p;
01833 
01834         total_len = 1;
01835         for (i = 1; i <= count; i++)
01836         {
01837             len = 0;
01838             MSI_RecordGetStringW( record, i, NULL, &len );
01839             total_len += len + 13;
01840         }
01841         p = message = msi_alloc( total_len * sizeof(WCHAR) );
01842         if (!p) return ERROR_OUTOFMEMORY;
01843 
01844         for (i = 1; i <= count; i++)
01845         {
01846             if (count > 1)
01847             {
01848                 len = sprintfW( p, format, i );
01849                 total_len -= len;
01850                 p += len;
01851             }
01852             len = total_len;
01853             MSI_RecordGetStringW( record, i, p, &len );
01854             total_len -= len;
01855             p += len;
01856             if (count > 1 && total_len)
01857             {
01858                 *p++ = ' ';
01859                 total_len--;
01860             }
01861         }
01862         p[0] = 0;
01863     }
01864 
01865     TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord,
01866           gUIFilter, log_type, debugstr_w(message));
01867 
01868     /* convert it to ASCII */
01869     len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
01870     msg = msi_alloc( len );
01871     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
01872 
01873     if (gUIHandlerW && (gUIFilter & log_type))
01874     {
01875         rc = gUIHandlerW( gUIContext, eMessageType, message );
01876     }
01877     else if (gUIHandlerA && (gUIFilter & log_type))
01878     {
01879         rc = gUIHandlerA( gUIContext, eMessageType, msg );
01880     }
01881     else if (gUIHandlerRecord && (gUIFilter & log_type))
01882     {
01883         MSIHANDLE rec = MsiCreateRecord( 1 );
01884         MsiRecordSetStringW( rec, 0, message );
01885         rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
01886         MsiCloseHandle( rec );
01887     }
01888 
01889     if (!rc && package->log_file != INVALID_HANDLE_VALUE &&
01890         (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
01891     {
01892         DWORD written;
01893         WriteFile( package->log_file, msg, len - 1, &written, NULL );
01894         WriteFile( package->log_file, "\n", 1, &written, NULL );
01895     }
01896     msi_free( msg );
01897     msi_free( message );
01898 
01899     switch (eMessageType & 0xff000000)
01900     {
01901     case INSTALLMESSAGE_ACTIONDATA:
01902         deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
01903         uirow = MSI_CreateRecord(1);
01904         MSI_RecordSetStringW(uirow, 1, deformated);
01905         msi_free(deformated);
01906 
01907         ControlEvent_FireSubscribedEvent(package, szActionData, uirow);
01908 
01909         msiobj_release(&uirow->hdr);
01910         break;
01911 
01912     case INSTALLMESSAGE_ACTIONSTART:
01913         deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
01914         uirow = MSI_CreateRecord(1);
01915         MSI_RecordSetStringW(uirow, 1, deformated);
01916         msi_free(deformated);
01917 
01918         ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
01919 
01920         msiobj_release(&uirow->hdr);
01921         break;
01922 
01923     case INSTALLMESSAGE_PROGRESS:
01924         ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
01925         break;
01926     }
01927 
01928     return ERROR_SUCCESS;
01929 }
01930 
01931 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
01932                               MSIHANDLE hRecord)
01933 {
01934     UINT ret = ERROR_INVALID_HANDLE;
01935     MSIPACKAGE *package = NULL;
01936     MSIRECORD *record = NULL;
01937 
01938     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
01939     if( !package )
01940     {
01941         HRESULT hr;
01942         IWineMsiRemotePackage *remote_package;
01943 
01944         remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
01945         if (!remote_package)
01946             return ERROR_INVALID_HANDLE;
01947 
01948         hr = IWineMsiRemotePackage_ProcessMessage( remote_package, eMessageType, hRecord );
01949 
01950         IWineMsiRemotePackage_Release( remote_package );
01951 
01952         if (FAILED(hr))
01953         {
01954             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
01955                 return HRESULT_CODE(hr);
01956 
01957             return ERROR_FUNCTION_FAILED;
01958         }
01959 
01960         return ERROR_SUCCESS;
01961     }
01962 
01963     record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
01964     if( !record )
01965         goto out;
01966 
01967     ret = MSI_ProcessMessage( package, eMessageType, record );
01968 
01969 out:
01970     msiobj_release( &package->hdr );
01971     if( record )
01972         msiobj_release( &record->hdr );
01973 
01974     return ret;
01975 }
01976 
01977 /* property code */
01978 
01979 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
01980 {
01981     LPWSTR szwName = NULL, szwValue = NULL;
01982     UINT r = ERROR_OUTOFMEMORY;
01983 
01984     szwName = strdupAtoW( szName );
01985     if( szName && !szwName )
01986         goto end;
01987 
01988     szwValue = strdupAtoW( szValue );
01989     if( szValue && !szwValue )
01990         goto end;
01991 
01992     r = MsiSetPropertyW( hInstall, szwName, szwValue);
01993 
01994 end:
01995     msi_free( szwName );
01996     msi_free( szwValue );
01997 
01998     return r;
01999 }
02000 
02001 void msi_reset_folders( MSIPACKAGE *package, BOOL source )
02002 {
02003     MSIFOLDER *folder;
02004 
02005     LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
02006     {
02007         if ( source )
02008         {
02009             msi_free( folder->ResolvedSource );
02010             folder->ResolvedSource = NULL;
02011         }
02012         else
02013         {
02014             msi_free( folder->ResolvedTarget );
02015             folder->ResolvedTarget = NULL;
02016         }
02017     }
02018 }
02019 
02020 UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
02021 {
02022     static const WCHAR insert_query[] = {
02023         'I','N','S','E','R','T',' ','I','N','T','O',' ',
02024         '`','_','P','r','o','p','e','r','t','y','`',' ',
02025         '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ',
02026         'V','A','L','U','E','S',' ','(','?',',','?',')',0};
02027     static const WCHAR update_query[] = {
02028         'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ',
02029         'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ',
02030         '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
02031     static const WCHAR delete_query[] = {
02032         'D','E','L','E','T','E',' ','F','R','O','M',' ',
02033         '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
02034         '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
02035     MSIQUERY *view;
02036     MSIRECORD *row = NULL;
02037     DWORD sz = 0;
02038     WCHAR query[1024];
02039     UINT rc;
02040 
02041     TRACE("%p %s %s\n", db, debugstr_w(szName), debugstr_w(szValue));
02042 
02043     if (!szName)
02044         return ERROR_INVALID_PARAMETER;
02045 
02046     /* this one is weird... */
02047     if (!szName[0])
02048         return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
02049 
02050     rc = msi_get_property(db, szName, 0, &sz);
02051     if (!szValue || !*szValue)
02052     {
02053         sprintfW(query, delete_query, szName);
02054     }
02055     else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
02056     {
02057         sprintfW(query, update_query, szName);
02058 
02059         row = MSI_CreateRecord(1);
02060         MSI_RecordSetStringW(row, 1, szValue);
02061     }
02062     else
02063     {
02064         strcpyW(query, insert_query);
02065 
02066         row = MSI_CreateRecord(2);
02067         MSI_RecordSetStringW(row, 1, szName);
02068         MSI_RecordSetStringW(row, 2, szValue);
02069     }
02070 
02071     rc = MSI_DatabaseOpenViewW(db, query, &view);
02072     if (rc == ERROR_SUCCESS)
02073     {
02074         rc = MSI_ViewExecute(view, row);
02075         MSI_ViewClose(view);
02076         msiobj_release(&view->hdr);
02077     }
02078     if (row) msiobj_release(&row->hdr);
02079     return rc;
02080 }
02081 
02082 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
02083 {
02084     MSIPACKAGE *package;
02085     UINT ret;
02086 
02087     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
02088     if( !package )
02089     {
02090         HRESULT hr;
02091         BSTR name = NULL, value = NULL;
02092         IWineMsiRemotePackage *remote_package;
02093 
02094         remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
02095         if (!remote_package)
02096             return ERROR_INVALID_HANDLE;
02097 
02098         name = SysAllocString( szName );
02099         value = SysAllocString( szValue );
02100         if ((!name && szName) || (!value && szValue))
02101         {
02102             SysFreeString( name );
02103             SysFreeString( value );
02104             IWineMsiRemotePackage_Release( remote_package );
02105             return ERROR_OUTOFMEMORY;
02106         }
02107 
02108         hr = IWineMsiRemotePackage_SetProperty( remote_package, name, value );
02109 
02110         SysFreeString( name );
02111         SysFreeString( value );
02112         IWineMsiRemotePackage_Release( remote_package );
02113 
02114         if (FAILED(hr))
02115         {
02116             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
02117                 return HRESULT_CODE(hr);
02118 
02119             return ERROR_FUNCTION_FAILED;
02120         }
02121 
02122         return ERROR_SUCCESS;
02123     }
02124 
02125     ret = msi_set_property( package->db, szName, szValue );
02126     if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir ))
02127         msi_reset_folders( package, TRUE );
02128 
02129     msiobj_release( &package->hdr );
02130     return ret;
02131 }
02132 
02133 static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
02134 {
02135     static const WCHAR query[]= {
02136         'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
02137         'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ',
02138         'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0};
02139     MSIRECORD *rec, *row = NULL;
02140     MSIQUERY *view;
02141     UINT r;
02142 
02143     if (!name || !*name)
02144         return NULL;
02145 
02146     rec = MSI_CreateRecord(1);
02147     if (!rec)
02148         return NULL;
02149 
02150     MSI_RecordSetStringW(rec, 1, name);
02151 
02152     r = MSI_DatabaseOpenViewW(db, query, &view);
02153     if (r == ERROR_SUCCESS)
02154     {
02155         MSI_ViewExecute(view, rec);
02156         MSI_ViewFetch(view, &row);
02157         MSI_ViewClose(view);
02158         msiobj_release(&view->hdr);
02159     }
02160     msiobj_release(&rec->hdr);
02161     return row;
02162 }
02163 
02164 /* internal function, not compatible with MsiGetPropertyW */
02165 UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
02166                        LPWSTR szValueBuf, LPDWORD pchValueBuf )
02167 {
02168     MSIRECORD *row;
02169     UINT rc = ERROR_FUNCTION_FAILED;
02170 
02171     row = msi_get_property_row( db, szName );
02172 
02173     if (*pchValueBuf > 0)
02174         szValueBuf[0] = 0;
02175 
02176     if (row)
02177     {
02178         rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf);
02179         msiobj_release(&row->hdr);
02180     }
02181 
02182     if (rc == ERROR_SUCCESS)
02183         TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
02184             debugstr_w(szName));
02185     else if (rc == ERROR_MORE_DATA)
02186         TRACE("need %d sized buffer for %s\n", *pchValueBuf,
02187             debugstr_w(szName));
02188     else
02189     {
02190         *pchValueBuf = 0;
02191         TRACE("property %s not found\n", debugstr_w(szName));
02192     }
02193 
02194     return rc;
02195 }
02196 
02197 LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop)
02198 {
02199     DWORD sz = 0;
02200     LPWSTR str;
02201     UINT r;
02202 
02203     r = msi_get_property(db, prop, NULL, &sz);
02204     if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
02205         return NULL;
02206 
02207     sz++;
02208     str = msi_alloc(sz * sizeof(WCHAR));
02209     r = msi_get_property(db, prop, str, &sz);
02210     if (r != ERROR_SUCCESS)
02211     {
02212         msi_free(str);
02213         str = NULL;
02214     }
02215 
02216     return str;
02217 }
02218 
02219 int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def )
02220 {
02221     LPWSTR str = msi_dup_property( db, prop );
02222     int val = str ? atoiW(str) : def;
02223     msi_free(str);
02224     return val;
02225 }
02226 
02227 static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
02228                              awstring *szValueBuf, LPDWORD pchValueBuf )
02229 {
02230     MSIPACKAGE *package;
02231     MSIRECORD *row = NULL;
02232     UINT r = ERROR_FUNCTION_FAILED;
02233     LPCWSTR val = NULL;
02234 
02235     TRACE("%u %s %p %p\n", handle, debugstr_w(name),
02236           szValueBuf->str.w, pchValueBuf );
02237 
02238     if (!name)
02239         return ERROR_INVALID_PARAMETER;
02240 
02241     package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE );
02242     if (!package)
02243     {
02244         HRESULT hr;
02245         IWineMsiRemotePackage *remote_package;
02246         LPWSTR value = NULL;
02247         BSTR bname;
02248         DWORD len;
02249 
02250         remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
02251         if (!remote_package)
02252             return ERROR_INVALID_HANDLE;
02253 
02254         bname = SysAllocString( name );
02255         if (!bname)
02256         {
02257             IWineMsiRemotePackage_Release( remote_package );
02258             return ERROR_OUTOFMEMORY;
02259         }
02260 
02261         len = 0;
02262         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
02263         if (FAILED(hr))
02264             goto done;
02265 
02266         len++;
02267         value = msi_alloc(len * sizeof(WCHAR));
02268         if (!value)
02269         {
02270             r = ERROR_OUTOFMEMORY;
02271             goto done;
02272         }
02273 
02274         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, value, &len );
02275         if (FAILED(hr))
02276             goto done;
02277 
02278         r = msi_strcpy_to_awstring( value, szValueBuf, pchValueBuf );
02279 
02280         /* Bug required by Adobe installers */
02281         if (!szValueBuf->unicode && !szValueBuf->str.a)
02282             *pchValueBuf *= sizeof(WCHAR);
02283 
02284 done:
02285         IWineMsiRemotePackage_Release(remote_package);
02286         SysFreeString(bname);
02287         msi_free(value);
02288 
02289         if (FAILED(hr))
02290         {
02291             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
02292                 return HRESULT_CODE(hr);
02293 
02294             return ERROR_FUNCTION_FAILED;
02295         }
02296 
02297         return r;
02298     }
02299 
02300     row = msi_get_property_row( package->db, name );
02301     if (row)
02302         val = MSI_RecordGetString( row, 1 );
02303 
02304     if (!val)
02305         val = szEmpty;
02306 
02307     r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
02308 
02309     if (row)
02310         msiobj_release( &row->hdr );
02311     msiobj_release( &package->hdr );
02312 
02313     return r;
02314 }
02315 
02316 UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
02317                              LPSTR szValueBuf, LPDWORD pchValueBuf )
02318 {
02319     awstring val;
02320     LPWSTR name;
02321     UINT r;
02322 
02323     val.unicode = FALSE;
02324     val.str.a = szValueBuf;
02325 
02326     name = strdupAtoW( szName );
02327     if (szName && !name)
02328         return ERROR_OUTOFMEMORY;
02329 
02330     r = MSI_GetProperty( hInstall, name, &val, pchValueBuf );
02331     msi_free( name );
02332     return r;
02333 }
02334 
02335 UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
02336                              LPWSTR szValueBuf, LPDWORD pchValueBuf )
02337 {
02338     awstring val;
02339 
02340     val.unicode = TRUE;
02341     val.str.w = szValueBuf;
02342 
02343     return MSI_GetProperty( hInstall, szName, &val, pchValueBuf );
02344 }
02345 
02346 typedef struct _msi_remote_package_impl {
02347     IWineMsiRemotePackage IWineMsiRemotePackage_iface;
02348     MSIHANDLE package;
02349     LONG refs;
02350 } msi_remote_package_impl;
02351 
02352 static inline msi_remote_package_impl *impl_from_IWineMsiRemotePackage( IWineMsiRemotePackage *iface )
02353 {
02354     return CONTAINING_RECORD(iface, msi_remote_package_impl, IWineMsiRemotePackage_iface);
02355 }
02356 
02357 static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface,
02358                 REFIID riid,LPVOID *ppobj)
02359 {
02360     if( IsEqualCLSID( riid, &IID_IUnknown ) ||
02361         IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) )
02362     {
02363         IUnknown_AddRef( iface );
02364         *ppobj = iface;
02365         return S_OK;
02366     }
02367 
02368     return E_NOINTERFACE;
02369 }
02370 
02371 static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface )
02372 {
02373     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02374 
02375     return InterlockedIncrement( &This->refs );
02376 }
02377 
02378 static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
02379 {
02380     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02381     ULONG r;
02382 
02383     r = InterlockedDecrement( &This->refs );
02384     if (r == 0)
02385     {
02386         MsiCloseHandle( This->package );
02387         msi_free( This );
02388     }
02389     return r;
02390 }
02391 
02392 static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle )
02393 {
02394     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02395     This->package = handle;
02396     return S_OK;
02397 }
02398 
02399 static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
02400 {
02401     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02402     IWineMsiRemoteDatabase *rdb = NULL;
02403     HRESULT hr;
02404     MSIHANDLE hdb;
02405 
02406     hr = create_msi_remote_database( NULL, (LPVOID *)&rdb );
02407     if (FAILED(hr) || !rdb)
02408     {
02409         ERR("Failed to create remote database\n");
02410         return hr;
02411     }
02412 
02413     hdb = MsiGetActiveDatabase(This->package);
02414 
02415     hr = IWineMsiRemoteDatabase_SetMsiHandle( rdb, hdb );
02416     if (FAILED(hr))
02417     {
02418         ERR("Failed to set the database handle\n");
02419         return hr;
02420     }
02421 
02422     *handle = alloc_msi_remote_handle( (IUnknown *)rdb );
02423     return S_OK;
02424 }
02425 
02426 static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value, DWORD *size )
02427 {
02428     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02429     UINT r = MsiGetPropertyW(This->package, property, value, size);
02430     if (r != ERROR_SUCCESS) return HRESULT_FROM_WIN32(r);
02431     return S_OK;
02432 }
02433 
02434 static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
02435 {
02436     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02437     UINT r = MsiSetPropertyW(This->package, property, value);
02438     return HRESULT_FROM_WIN32(r);
02439 }
02440 
02441 static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
02442 {
02443     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02444     UINT r = MsiProcessMessage(This->package, message, record);
02445     return HRESULT_FROM_WIN32(r);
02446 }
02447 
02448 static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
02449 {
02450     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02451     UINT r = MsiDoActionW(This->package, action);
02452     return HRESULT_FROM_WIN32(r);
02453 }
02454 
02455 static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
02456 {
02457     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02458     UINT r = MsiSequenceW(This->package, table, sequence);
02459     return HRESULT_FROM_WIN32(r);
02460 }
02461 
02462 static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size )
02463 {
02464     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02465     UINT r = MsiGetTargetPathW(This->package, folder, value, size);
02466     return HRESULT_FROM_WIN32(r);
02467 }
02468 
02469 static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
02470 {
02471     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02472     UINT r = MsiSetTargetPathW(This->package, folder, value);
02473     return HRESULT_FROM_WIN32(r);
02474 }
02475 
02476 static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size )
02477 {
02478     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02479     UINT r = MsiGetSourcePathW(This->package, folder, value, size);
02480     return HRESULT_FROM_WIN32(r);
02481 }
02482 
02483 static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
02484 {
02485     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02486     *ret = MsiGetMode(This->package, mode);
02487     return S_OK;
02488 }
02489 
02490 static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state )
02491 {
02492     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02493     UINT r = MsiSetMode(This->package, mode, state);
02494     return HRESULT_FROM_WIN32(r);
02495 }
02496 
02497 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
02498                                     INSTALLSTATE *installed, INSTALLSTATE *action )
02499 {
02500     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02501     UINT r = MsiGetFeatureStateW(This->package, feature, installed, action);
02502     return HRESULT_FROM_WIN32(r);
02503 }
02504 
02505 static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
02506 {
02507     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02508     UINT r = MsiSetFeatureStateW(This->package, feature, state);
02509     return HRESULT_FROM_WIN32(r);
02510 }
02511 
02512 static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
02513                                       INSTALLSTATE *installed, INSTALLSTATE *action )
02514 {
02515     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02516     UINT r = MsiGetComponentStateW(This->package, component, installed, action);
02517     return HRESULT_FROM_WIN32(r);
02518 }
02519 
02520 static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
02521 {
02522     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02523     UINT r = MsiSetComponentStateW(This->package, component, state);
02524     return HRESULT_FROM_WIN32(r);
02525 }
02526 
02527 static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
02528 {
02529     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02530     *language = MsiGetLanguage(This->package);
02531     return S_OK;
02532 }
02533 
02534 static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
02535 {
02536     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02537     UINT r = MsiSetInstallLevel(This->package, level);
02538     return HRESULT_FROM_WIN32(r);
02539 }
02540 
02541 static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
02542                                         BSTR *value)
02543 {
02544     DWORD size = 0;
02545     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02546     UINT r = MsiFormatRecordW(This->package, record, NULL, &size);
02547     if (r == ERROR_SUCCESS)
02548     {
02549         *value = SysAllocStringLen(NULL, size);
02550         if (!*value)
02551             return E_OUTOFMEMORY;
02552         size++;
02553         r = MsiFormatRecordW(This->package, record, *value, &size);
02554     }
02555     return HRESULT_FROM_WIN32(r);
02556 }
02557 
02558 static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
02559 {
02560     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02561     UINT r = MsiEvaluateConditionW(This->package, condition);
02562     return HRESULT_FROM_WIN32(r);
02563 }
02564 
02565 static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature,
02566                                           INT cost_tree, INSTALLSTATE state, INT *cost )
02567 {
02568     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02569     UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost);
02570     return HRESULT_FROM_WIN32(r);
02571 }
02572 
02573 static HRESULT WINAPI mrp_EnumComponentCosts( IWineMsiRemotePackage *iface, BSTR component,
02574                                               DWORD index, INSTALLSTATE state, BSTR drive,
02575                                               DWORD *buflen, INT *cost, INT *temp )
02576 {
02577     msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
02578     UINT r = MsiEnumComponentCostsW(This->package, component, index, state, drive, buflen, cost, temp);
02579     return HRESULT_FROM_WIN32(r);
02580 }
02581 
02582 static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl =
02583 {
02584     mrp_QueryInterface,
02585     mrp_AddRef,
02586     mrp_Release,
02587     mrp_SetMsiHandle,
02588     mrp_GetActiveDatabase,
02589     mrp_GetProperty,
02590     mrp_SetProperty,
02591     mrp_ProcessMessage,
02592     mrp_DoAction,
02593     mrp_Sequence,
02594     mrp_GetTargetPath,
02595     mrp_SetTargetPath,
02596     mrp_GetSourcePath,
02597     mrp_GetMode,
02598     mrp_SetMode,
02599     mrp_GetFeatureState,
02600     mrp_SetFeatureState,
02601     mrp_GetComponentState,
02602     mrp_SetComponentState,
02603     mrp_GetLanguage,
02604     mrp_SetInstallLevel,
02605     mrp_FormatRecord,
02606     mrp_EvaluateCondition,
02607     mrp_GetFeatureCost,
02608     mrp_EnumComponentCosts
02609 };
02610 
02611 HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
02612 {
02613     msi_remote_package_impl* This;
02614 
02615     This = msi_alloc( sizeof *This );
02616     if (!This)
02617         return E_OUTOFMEMORY;
02618 
02619     This->IWineMsiRemotePackage_iface.lpVtbl = &msi_remote_package_vtbl;
02620     This->package = 0;
02621     This->refs = 1;
02622 
02623     *ppObj = This;
02624 
02625     return S_OK;
02626 }
02627 
02628 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
02629                           LPCWSTR property, LPWSTR value)
02630 {
02631     MSISOURCELISTINFO *info;
02632 
02633     LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry )
02634     {
02635         if (!strcmpW( info->value, value )) return ERROR_SUCCESS;
02636     }
02637 
02638     info = msi_alloc(sizeof(MSISOURCELISTINFO));
02639     if (!info)
02640         return ERROR_OUTOFMEMORY;
02641 
02642     info->context = context;
02643     info->options = options;
02644     info->property = property;
02645     info->value = strdupW(value);
02646     list_add_head(&package->sourcelist_info, &info->entry);
02647 
02648     return ERROR_SUCCESS;
02649 }
02650 
02651 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options,
02652                                 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt)
02653 {
02654     MSIMEDIADISK *disk;
02655 
02656     LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry )
02657     {
02658         if (disk->disk_id == disk_id) return ERROR_SUCCESS;
02659     }
02660 
02661     disk = msi_alloc(sizeof(MSIMEDIADISK));
02662     if (!disk)
02663         return ERROR_OUTOFMEMORY;
02664 
02665     disk->context = context;
02666     disk->options = options;
02667     disk->disk_id = disk_id;
02668     disk->volume_label = strdupW(volume_label);
02669     disk->disk_prompt = strdupW(disk_prompt);
02670     list_add_head(&package->sourcelist_media, &disk->entry);
02671 
02672     return ERROR_SUCCESS;
02673 }

Generated on Thu May 24 2012 04:25:42 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.