diff options
Diffstat (limited to 'libmsi/package.c')
-rw-r--r-- | libmsi/package.c | 1195 |
1 files changed, 0 insertions, 1195 deletions
diff --git a/libmsi/package.c b/libmsi/package.c deleted file mode 100644 index 0503211..0000000 --- a/libmsi/package.c +++ /dev/null @@ -1,1195 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2004 Aric Stewart for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#define COBJMACROS - -#include <stdarg.h> -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winnls.h" -#include "shlwapi.h" -#include "wingdi.h" -#include "wine/debug.h" -#include "msi.h" -#include "msiquery.h" -#include "objidl.h" -#include "wincrypt.h" -#include "wingdi.h" -#include "winuser.h" -#include "wininet.h" -#include "winver.h" -#include "urlmon.h" -#include "shlobj.h" -#include "wine/unicode.h" -#include "objbase.h" -#include "msidefs.h" -#include "sddl.h" - -#include "msipriv.h" -#include "msiserver.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - -MSICOMPONENT *msi_get_loaded_component( MSIPACKAGE *package, const WCHAR *Component ) -{ - MSICOMPONENT *comp; - - LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry ) - { - if (!strcmpW( Component, comp->Component )) return comp; - } - return NULL; -} - -MSIFEATURE *msi_get_loaded_feature(MSIPACKAGE* package, const WCHAR *Feature ) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) - { - if (!strcmpW( Feature, feature->Feature )) return feature; - } - return NULL; -} - -MSIFILE *msi_get_loaded_file( MSIPACKAGE *package, const WCHAR *key ) -{ - MSIFILE *file; - - LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry ) - { - if (!strcmpW( key, file->File )) return file; - } - return NULL; -} - -MSIFILEPATCH *msi_get_loaded_filepatch( MSIPACKAGE *package, const WCHAR *key ) -{ - MSIFILEPATCH *patch; - - /* FIXME: There might be more than one patch */ - LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry ) - { - if (!strcmpW( key, patch->File->File )) return patch; - } - return NULL; -} - -MSIFOLDER *msi_get_loaded_folder( MSIPACKAGE *package, const WCHAR *dir ) -{ - MSIFOLDER *folder; - - LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) - { - if (!strcmpW( dir, folder->Directory )) return folder; - } - return NULL; -} - - -static void remove_tracked_tempfiles( MSIPACKAGE *package ) -{ - struct list *item, *cursor; - - LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles ) - { - MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry ); - - list_remove( &temp->entry ); - TRACE("deleting temp file %s\n", debugstr_w( temp->Path )); - DeleteFileW( temp->Path ); - msi_free( temp->Path ); - msi_free( temp ); - } -} - -static void free_feature( MSIFEATURE *feature ) -{ - struct list *item, *cursor; - - LIST_FOR_EACH_SAFE( item, cursor, &feature->Children ) - { - FeatureList *fl = LIST_ENTRY( item, FeatureList, entry ); - list_remove( &fl->entry ); - msi_free( fl ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) - { - ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); - list_remove( &cl->entry ); - msi_free( cl ); - } - msi_free( feature->Feature ); - msi_free( feature->Feature_Parent ); - msi_free( feature->Directory ); - msi_free( feature->Description ); - msi_free( feature->Title ); - msi_free( feature ); -} - -static void free_folder( MSIFOLDER *folder ) -{ - struct list *item, *cursor; - - LIST_FOR_EACH_SAFE( item, cursor, &folder->children ) - { - FolderList *fl = LIST_ENTRY( item, FolderList, entry ); - list_remove( &fl->entry ); - msi_free( fl ); - } - msi_free( folder->Parent ); - msi_free( folder->Directory ); - msi_free( folder->TargetDefault ); - msi_free( folder->SourceLongPath ); - msi_free( folder->SourceShortPath ); - msi_free( folder->ResolvedTarget ); - msi_free( folder->ResolvedSource ); - msi_free( folder ); -} - -static void free_extension( MSIEXTENSION *ext ) -{ - struct list *item, *cursor; - - LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs ) - { - MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry ); - - list_remove( &verb->entry ); - msi_free( verb->Verb ); - msi_free( verb->Command ); - msi_free( verb->Argument ); - msi_free( verb ); - } - - msi_free( ext->Extension ); - msi_free( ext->ProgIDText ); - msi_free( ext ); -} - -static void free_assembly( MSIASSEMBLY *assembly ) -{ - msi_free( assembly->feature ); - msi_free( assembly->manifest ); - msi_free( assembly->application ); - msi_free( assembly->display_name ); - if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir ); - msi_free( assembly->tempdir ); - msi_free( assembly ); -} - -void msi_free_action_script( MSIPACKAGE *package, UINT script ) -{ - UINT i; - for (i = 0; i < package->script->ActionCount[script]; i++) - msi_free( package->script->Actions[script][i] ); - - msi_free( package->script->Actions[script] ); - package->script->Actions[script] = NULL; - package->script->ActionCount[script] = 0; -} - -static void free_package_structures( MSIPACKAGE *package ) -{ - INT i; - struct list *item, *cursor; - - LIST_FOR_EACH_SAFE( item, cursor, &package->features ) - { - MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); - list_remove( &feature->entry ); - free_feature( feature ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->folders ) - { - MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); - list_remove( &folder->entry ); - free_folder( folder ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->components ) - { - MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); - - list_remove( &comp->entry ); - msi_free( comp->Component ); - msi_free( comp->ComponentId ); - msi_free( comp->Directory ); - msi_free( comp->Condition ); - msi_free( comp->KeyPath ); - msi_free( comp->FullKeypath ); - if (comp->assembly) free_assembly( comp->assembly ); - msi_free( comp ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->files ) - { - MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry ); - - list_remove( &file->entry ); - msi_free( file->File ); - msi_free( file->FileName ); - msi_free( file->ShortName ); - msi_free( file->LongName ); - msi_free( file->Version ); - msi_free( file->Language ); - msi_free( file->TargetPath ); - msi_free( file ); - } - - /* clean up extension, progid, class and verb structures */ - LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) - { - MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry ); - - list_remove( &cls->entry ); - msi_free( cls->clsid ); - msi_free( cls->Context ); - msi_free( cls->Description ); - msi_free( cls->FileTypeMask ); - msi_free( cls->IconPath ); - msi_free( cls->DefInprocHandler ); - msi_free( cls->DefInprocHandler32 ); - msi_free( cls->Argument ); - msi_free( cls->ProgIDText ); - msi_free( cls ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->extensions ) - { - MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry ); - - list_remove( &ext->entry ); - free_extension( ext ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->progids ) - { - MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry ); - - list_remove( &progid->entry ); - msi_free( progid->ProgID ); - msi_free( progid->Description ); - msi_free( progid->IconPath ); - msi_free( progid ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) - { - MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry ); - - list_remove( &mt->entry ); - msi_free( mt->suffix ); - msi_free( mt->clsid ); - msi_free( mt->ContentType ); - msi_free( mt ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->appids ) - { - MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry ); - - list_remove( &appid->entry ); - msi_free( appid->AppID ); - msi_free( appid->RemoteServerName ); - msi_free( appid->LocalServer ); - msi_free( appid->ServiceParameters ); - msi_free( appid->DllSurrogate ); - msi_free( appid ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info ) - { - MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry ); - - list_remove( &info->entry ); - msi_free( info->value ); - msi_free( info ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media ) - { - MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry ); - - list_remove( &info->entry ); - msi_free( info->volume_label ); - msi_free( info->disk_prompt ); - msi_free( info ); - } - - if (package->script) - { - for (i = 0; i < SCRIPT_MAX; i++) - msi_free_action_script( package, i ); - - for (i = 0; i < package->script->UniqueActionsCount; i++) - msi_free( package->script->UniqueActions[i] ); - - msi_free( package->script->UniqueActions ); - msi_free( package->script ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->binaries ) - { - MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry ); - - list_remove( &binary->entry ); - if (binary->module) - FreeLibrary( binary->module ); - if (!DeleteFileW( binary->tmpfile )) - ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError()); - msi_free( binary->source ); - msi_free( binary->tmpfile ); - msi_free( binary ); - } - - LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams ) - { - MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry ); - - list_remove( &cab->entry ); - IStorage_Release( cab->storage ); - msi_free( cab->stream ); - msi_free( cab ); - } - - msi_free( package->BaseURL ); - msi_free( package->PackagePath ); - msi_free( package->ProductCode ); - msi_free( package->ActionFormat ); - msi_free( package->LastAction ); - msi_free( package->langids ); - - remove_tracked_tempfiles(package); -} - -static void MSI_FreePackage( MSIOBJECTHDR *arg) -{ - MSIPACKAGE *package = (MSIPACKAGE *)arg; - - msiobj_release( &package->db->hdr ); - free_package_structures(package); - CloseHandle( package->log_file ); - - if (package->delete_on_close) DeleteFileW( package->localfile ); - msi_free( package->localfile ); -} - -typedef struct tagLANGANDCODEPAGE -{ - WORD wLanguage; - WORD wCodePage; -} LANGANDCODEPAGE; - -static UINT msi_load_summary_properties( MSIPACKAGE *package ) -{ - UINT rc; - MSIHANDLE suminfo; - MSIHANDLE hdb = alloc_msihandle( &package->db->hdr ); - INT count; - DWORD len; - LPWSTR package_code; - static const WCHAR szPackageCode[] = { - 'P','a','c','k','a','g','e','C','o','d','e',0}; - - if (!hdb) { - ERR("Unable to allocate handle\n"); - return ERROR_OUTOFMEMORY; - } - - rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo ); - MsiCloseHandle(hdb); - if (rc != ERROR_SUCCESS) - { - ERR("Unable to open Summary Information\n"); - return rc; - } - - rc = MsiSummaryInfoGetPropertyW( suminfo, PID_PAGECOUNT, NULL, - &count, NULL, NULL, NULL ); - if (rc != ERROR_SUCCESS) - { - WARN("Unable to query page count: %d\n", rc); - goto done; - } - - /* load package code property */ - len = 0; - rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL, - NULL, NULL, NULL, &len ); - if (rc != ERROR_MORE_DATA) - { - WARN("Unable to query revision number: %d\n", rc); - rc = ERROR_FUNCTION_FAILED; - goto done; - } - - len++; - package_code = msi_alloc( len * sizeof(WCHAR) ); - rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL, - NULL, NULL, package_code, &len ); - if (rc != ERROR_SUCCESS) - { - WARN("Unable to query rev number: %d\n", rc); - goto done; - } - - msi_set_property( package->db, szPackageCode, package_code ); - msi_free( package_code ); - - /* load package attributes */ - count = 0; - MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL, - &count, NULL, NULL, NULL ); - package->WordCount = count; - -done: - MsiCloseHandle(suminfo); - return rc; -} - -static MSIPACKAGE *msi_alloc_package( void ) -{ - MSIPACKAGE *package; - - package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), - MSI_FreePackage ); - if( package ) - { - list_init( &package->components ); - list_init( &package->features ); - list_init( &package->files ); - list_init( &package->filepatches ); - list_init( &package->tempfiles ); - list_init( &package->folders ); - list_init( &package->subscriptions ); - list_init( &package->appids ); - list_init( &package->classes ); - list_init( &package->mimes ); - list_init( &package->extensions ); - list_init( &package->progids ); - list_init( &package->RunningActions ); - list_init( &package->sourcelist_info ); - list_init( &package->sourcelist_media ); - list_init( &package->binaries ); - list_init( &package->cabinet_streams ); - } - - return package; -} - -static UINT msi_load_admin_properties(MSIPACKAGE *package) -{ -#if 0 - BYTE *data; - UINT r, sz; - - static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0}; - - r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz); - if (r != ERROR_SUCCESS) - return r; - - r = msi_parse_command_line(package, (WCHAR *)data, TRUE); - - msi_free(data); - return r; -#endif -} - -MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) -{ - static const WCHAR fmtW[] = {'%','u',0}; - MSIPACKAGE *package; - WCHAR uilevel[11]; - UINT r; - - TRACE("%p\n", db); - - package = msi_alloc_package(); - if (package) - { - msiobj_addref( &db->hdr ); - package->db = db; - - package->WordCount = 0; - package->PackagePath = strdupW( db->path ); - package->BaseURL = strdupW( base_url ); - - package->ProductCode = msi_dup_property( package->db, szProductCode ); - package->script = msi_alloc_zero( sizeof(MSISCRIPT) ); - - package->ui_level = gUILevel; - sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); - msi_set_property(package->db, szUILevel, uilevel); - - r = msi_load_summary_properties( package ); - if (r != ERROR_SUCCESS) - { - msiobj_release( &package->hdr ); - return NULL; - } - - if (package->WordCount & msidbSumInfoSourceTypeAdminImage) - msi_load_admin_properties( package ); - - package->log_file = INVALID_HANDLE_VALUE; - } - return package; -} - -UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) -{ - static const WCHAR szInstaller[] = { - '\\','I','n','s','t','a','l','l','e','r','\\',0}; - static const WCHAR fmt[] = {'%','x',0}; - DWORD time, len, i, offset; - HANDLE handle; - - time = GetTickCount(); - GetWindowsDirectoryW( path, MAX_PATH ); - strcatW( path, szInstaller ); - CreateDirectoryW( path, NULL ); - - len = strlenW(path); - for (i = 0; i < 0x10000; i++) - { - offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff ); - memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) ); - handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, - CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); - if (handle != INVALID_HANDLE_VALUE) - { - CloseHandle(handle); - break; - } - if (GetLastError() != ERROR_FILE_EXISTS && - GetLastError() != ERROR_SHARING_VIOLATION) - return ERROR_FUNCTION_FAILED; - } - - return ERROR_SUCCESS; -} - -static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package ) -{ - WCHAR *template, *p, *q; - DWORD i, count; - - package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); - TRACE("version: %d\n", package->version); - - template = msi_suminfo_dup_string( si, PID_TEMPLATE ); - if (!template) - return ERROR_SUCCESS; /* native accepts missing template property */ - - TRACE("template: %s\n", debugstr_w(template)); - - p = strchrW( template, ';' ); - if (!p) - { - WARN("invalid template string %s\n", debugstr_w(template)); - msi_free( template ); - return ERROR_PATCH_PACKAGE_INVALID; - } - *p = 0; - if ((q = strchrW( template, ',' ))) *q = 0; - if (!template[0] || !strcmpW( template, szIntel )) - package->platform = PLATFORM_INTEL; - else if (!strcmpW( template, szIntel64 )) - package->platform = PLATFORM_INTEL64; - else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 )) - package->platform = PLATFORM_X64; - else if (!strcmpW( template, szARM )) - package->platform = PLATFORM_ARM; - else - { - WARN("unknown platform %s\n", debugstr_w(template)); - msi_free( template ); - return ERROR_INSTALL_PLATFORM_UNSUPPORTED; - } - p++; - if (!*p) - { - msi_free( template ); - return ERROR_SUCCESS; - } - count = 1; - for (q = p; (q = strchrW( q, ',' )); q++) count++; - - package->langids = msi_alloc( count * sizeof(LANGID) ); - if (!package->langids) - { - msi_free( template ); - return ERROR_OUTOFMEMORY; - } - - i = 0; - while (*p) - { - q = strchrW( p, ',' ); - if (q) *q = 0; - package->langids[i] = atoiW( p ); - if (!q) break; - p = q + 1; - i++; - } - package->num_langids = i + 1; - - msi_free( template ); - return ERROR_SUCCESS; -} - -static UINT validate_package( MSIPACKAGE *package ) -{ - UINT i; - - if (package->platform == PLATFORM_INTEL64) - return ERROR_INSTALL_PLATFORM_UNSUPPORTED; -#ifndef __arm__ - if (package->platform == PLATFORM_ARM) - return ERROR_INSTALL_PLATFORM_UNSUPPORTED; -#endif - if (package->platform == PLATFORM_X64) - { - if (!is_64bit && !is_wow64) - return ERROR_INSTALL_PLATFORM_UNSUPPORTED; - if (package->version < 200) - return ERROR_INSTALL_PACKAGE_INVALID; - } - if (!package->num_langids) - { - return ERROR_SUCCESS; - } - for (i = 0; i < package->num_langids; i++) - { - LANGID langid = package->langids[i]; - - if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) - { - langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); - } - if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) - { - langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); - } - if (IsValidLocale( langid, LCID_INSTALLED )) - return ERROR_SUCCESS; - } - return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; -} - -int msi_track_tempfile( MSIPACKAGE *package, const WCHAR *path ) -{ - MSITEMPFILE *temp; - - TRACE("%s\n", debugstr_w(path)); - - LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry ) - { - if (!strcmpW( path, temp->Path )) return 0; - } - if (!(temp = msi_alloc_zero( sizeof (MSITEMPFILE) ))) return -1; - list_add_head( &package->tempfiles, &temp->entry ); - temp->Path = strdupW( path ); - return 0; -} - -UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) -{ - MSIDATABASE *db; - MSIPACKAGE *package; - MSIHANDLE handle; - LPWSTR base_url = NULL; - UINT r; - WCHAR localfile[MAX_PATH]; - LPCWSTR file = szPackage; - MSISUMMARYINFO *si; - BOOL delete_on_close = FALSE; - - TRACE("%s %p\n", debugstr_w(szPackage), pPackage); - - localfile[0] = 0; - if( szPackage[0] == '#' ) - { - handle = atoiW(&szPackage[1]); - db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); - if( !db ) - return ERROR_INVALID_HANDLE; - } - else - { - r = MSI_OpenDatabaseW( file, MSIDBOPEN_TRANSACT, &db ); - if (r != ERROR_SUCCESS) - return r; - } - package = MSI_CreatePackage( db, base_url ); - msi_free( base_url ); - msiobj_release( &db->hdr ); - if (!package) return ERROR_INSTALL_PACKAGE_INVALID; - package->localfile = strdupW( localfile ); - package->delete_on_close = delete_on_close; - - si = MSI_GetSummaryInformationW( db->storage, 0 ); - if (!si) - { - WARN("failed to load summary info\n"); - msiobj_release( &package->hdr ); - return ERROR_INSTALL_PACKAGE_INVALID; - } - r = msi_parse_summary( si, package ); - msiobj_release( &si->hdr ); - if (r != ERROR_SUCCESS) - { - WARN("failed to parse summary info %u\n", r); - msiobj_release( &package->hdr ); - return r; - } - r = validate_package( package ); - if (r != ERROR_SUCCESS) - { - msiobj_release( &package->hdr ); - return r; - } - msi_set_property( package->db, szDatabase, db->path ); - - if( szPackage[0] == '#' ) - msi_set_property( package->db, szOriginalDatabase, db->path ); - else - { - WCHAR fullpath[MAX_PATH]; - - GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL ); - msi_set_property( package->db, szOriginalDatabase, fullpath ); - } - - if (gszLogFile) - package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - *pPackage = package; - return ERROR_SUCCESS; -} - -UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) -{ - MSIPACKAGE *package = NULL; - UINT ret; - - TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage ); - - if( !szPackage || !phPackage ) - return ERROR_INVALID_PARAMETER; - - if ( !*szPackage ) - { - FIXME("Should create an empty database and package\n"); - return ERROR_FUNCTION_FAILED; - } - - if( dwOptions ) - FIXME("dwOptions %08x not supported\n", dwOptions); - - ret = MSI_OpenPackageW( szPackage, &package ); - if( ret == ERROR_SUCCESS ) - { - *phPackage = alloc_msihandle( &package->hdr ); - if (! *phPackage) - ret = ERROR_NOT_ENOUGH_MEMORY; - msiobj_release( &package->hdr ); - } - - return ret; -} - -UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) -{ - return MsiOpenPackageExW( szPackage, 0, phPackage ); -} - -UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) -{ - LPWSTR szwPack = NULL; - UINT ret; - - if( szPackage ) - { - szwPack = strdupAtoW( szPackage ); - if( !szwPack ) - return ERROR_OUTOFMEMORY; - } - - ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); - - msi_free( szwPack ); - - return ret; -} - -UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) -{ - return MsiOpenPackageExA( szPackage, 0, phPackage ); -} - -MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) -{ - MSIPACKAGE *package; - MSIHANDLE handle = 0; - - TRACE("(%d)\n",hInstall); - - package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); - if( package) - { - handle = alloc_msihandle( &package->db->hdr ); - msiobj_release( &package->hdr ); - } - - return handle; -} - -/* property code */ - -UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) -{ - LPWSTR szwName = NULL, szwValue = NULL; - UINT r = ERROR_OUTOFMEMORY; - - szwName = strdupAtoW( szName ); - if( szName && !szwName ) - goto end; - - szwValue = strdupAtoW( szValue ); - if( szValue && !szwValue ) - goto end; - - r = MsiSetPropertyW( hInstall, szwName, szwValue); - -end: - msi_free( szwName ); - msi_free( szwValue ); - - return r; -} - -void msi_reset_folders( MSIPACKAGE *package, BOOL source ) -{ - MSIFOLDER *folder; - - LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) - { - if ( source ) - { - msi_free( folder->ResolvedSource ); - folder->ResolvedSource = NULL; - } - else - { - msi_free( folder->ResolvedTarget ); - folder->ResolvedTarget = NULL; - } - } -} - -UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue ) -{ - static const WCHAR insert_query[] = { - 'I','N','S','E','R','T',' ','I','N','T','O',' ', - '`','_','P','r','o','p','e','r','t','y','`',' ', - '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', - 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; - static const WCHAR update_query[] = { - 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', - 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ', - '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; - static const WCHAR delete_query[] = { - 'D','E','L','E','T','E',' ','F','R','O','M',' ', - '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', - '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; - MSIQUERY *view; - MSIRECORD *row = NULL; - DWORD sz = 0; - WCHAR query[1024]; - UINT rc; - - TRACE("%p %s %s\n", db, debugstr_w(szName), debugstr_w(szValue)); - - if (!szName) - return ERROR_INVALID_PARAMETER; - - /* this one is weird... */ - if (!szName[0]) - return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; - - rc = msi_get_property(db, szName, 0, &sz); - if (!szValue || !*szValue) - { - sprintfW(query, delete_query, szName); - } - else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) - { - sprintfW(query, update_query, szName); - - row = MSI_CreateRecord(1); - MSI_RecordSetStringW(row, 1, szValue); - } - else - { - strcpyW(query, insert_query); - - row = MSI_CreateRecord(2); - MSI_RecordSetStringW(row, 1, szName); - MSI_RecordSetStringW(row, 2, szValue); - } - - rc = MSI_DatabaseOpenViewW(db, query, &view); - if (rc == ERROR_SUCCESS) - { - rc = MSI_ViewExecute(view, row); - MSI_ViewClose(view); - msiobj_release(&view->hdr); - } - if (row) msiobj_release(&row->hdr); - return rc; -} - -UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) -{ - MSIPACKAGE *package; - UINT ret; - - package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); - if( !package ) - return ERROR_INVALID_HANDLE; - ret = msi_set_property( package->db, szName, szValue ); - if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) - msi_reset_folders( package, TRUE ); - - msiobj_release( &package->hdr ); - return ret; -} - -static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) -{ - static const WCHAR query[]= { - 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', - 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ', - 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0}; - MSIRECORD *rec, *row = NULL; - MSIQUERY *view; - UINT r; - - if (!name || !*name) - return NULL; - - rec = MSI_CreateRecord(1); - if (!rec) - return NULL; - - MSI_RecordSetStringW(rec, 1, name); - - r = MSI_DatabaseOpenViewW(db, query, &view); - if (r == ERROR_SUCCESS) - { - MSI_ViewExecute(view, rec); - MSI_ViewFetch(view, &row); - MSI_ViewClose(view); - msiobj_release(&view->hdr); - } - msiobj_release(&rec->hdr); - return row; -} - -/* internal function, not compatible with MsiGetPropertyW */ -UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, - LPWSTR szValueBuf, LPDWORD pchValueBuf ) -{ - MSIRECORD *row; - UINT rc = ERROR_FUNCTION_FAILED; - - row = msi_get_property_row( db, szName ); - - if (*pchValueBuf > 0) - szValueBuf[0] = 0; - - if (row) - { - rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); - msiobj_release(&row->hdr); - } - - if (rc == ERROR_SUCCESS) - TRACE("returning %s for property %s\n", debugstr_w(szValueBuf), - debugstr_w(szName)); - else if (rc == ERROR_MORE_DATA) - TRACE("need %d sized buffer for %s\n", *pchValueBuf, - debugstr_w(szName)); - else - { - *pchValueBuf = 0; - TRACE("property %s not found\n", debugstr_w(szName)); - } - - return rc; -} - -LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) -{ - DWORD sz = 0; - LPWSTR str; - UINT r; - - r = msi_get_property(db, prop, NULL, &sz); - if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) - return NULL; - - sz++; - str = msi_alloc(sz * sizeof(WCHAR)); - r = msi_get_property(db, prop, str, &sz); - if (r != ERROR_SUCCESS) - { - msi_free(str); - str = NULL; - } - - return str; -} - -int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) -{ - LPWSTR str = msi_dup_property( db, prop ); - int val = str ? atoiW(str) : def; - msi_free(str); - return val; -} - -static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, - awstring *szValueBuf, LPDWORD pchValueBuf ) -{ - MSIPACKAGE *package; - MSIRECORD *row = NULL; - UINT r = ERROR_FUNCTION_FAILED; - LPCWSTR val = NULL; - - TRACE("%u %s %p %p\n", handle, debugstr_w(name), - szValueBuf->str.w, pchValueBuf ); - - if (!name) - return ERROR_INVALID_PARAMETER; - - package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); - if (!package) - return ERROR_INVALID_HANDLE; - row = msi_get_property_row( package->db, name ); - if (row) - val = MSI_RecordGetString( row, 1 ); - - if (!val) - val = szEmpty; - - r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf ); - - if (row) - msiobj_release( &row->hdr ); - msiobj_release( &package->hdr ); - - return r; -} - -UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName, - LPSTR szValueBuf, LPDWORD pchValueBuf ) -{ - awstring val; - LPWSTR name; - UINT r; - - val.unicode = FALSE; - val.str.a = szValueBuf; - - name = strdupAtoW( szName ); - if (szName && !name) - return ERROR_OUTOFMEMORY; - - r = MSI_GetProperty( hInstall, name, &val, pchValueBuf ); - msi_free( name ); - return r; -} - -UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, - LPWSTR szValueBuf, LPDWORD pchValueBuf ) -{ - awstring val; - - val.unicode = TRUE; - val.str.w = szValueBuf; - - return MSI_GetProperty( hInstall, szName, &val, pchValueBuf ); -} - -UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, - LPCWSTR property, LPWSTR value) -{ - MSISOURCELISTINFO *info; - - LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) - { - if (!strcmpW( info->value, value )) return ERROR_SUCCESS; - } - - info = msi_alloc(sizeof(MSISOURCELISTINFO)); - if (!info) - return ERROR_OUTOFMEMORY; - - info->context = context; - info->options = options; - info->property = property; - info->value = strdupW(value); - list_add_head(&package->sourcelist_info, &info->entry); - - return ERROR_SUCCESS; -} - -UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, - DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) -{ - MSIMEDIADISK *disk; - - LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) - { - if (disk->disk_id == disk_id) return ERROR_SUCCESS; - } - - disk = msi_alloc(sizeof(MSIMEDIADISK)); - if (!disk) - return ERROR_OUTOFMEMORY; - - disk->context = context; - disk->options = options; - disk->disk_id = disk_id; - disk->volume_label = strdupW(volume_label); - disk->disk_prompt = strdupW(disk_prompt); - list_add_head(&package->sourcelist_media, &disk->entry); - - return ERROR_SUCCESS; -} |