From a8361b5fd3774ba66dae76a56ba0ebd51c3631e8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 22 Oct 2012 15:44:18 +0200 Subject: kill package.c and more --- libmsi/Makefile.am | 3 +- libmsi/media.c | 618 --------------------------- libmsi/msi.c | 217 ---------- libmsi/msi_main.c | 48 --- libmsi/package.c | 1195 ---------------------------------------------------- 5 files changed, 1 insertion(+), 2080 deletions(-) delete mode 100644 libmsi/media.c delete mode 100644 libmsi/msi_main.c delete mode 100644 libmsi/package.c diff --git a/libmsi/Makefile.am b/libmsi/Makefile.am index 565fa48..25bd8a0 100644 --- a/libmsi/Makefile.am +++ b/libmsi/Makefile.am @@ -13,8 +13,7 @@ noinst_HEADERS = \ query.h libmsi_la_SOURCES = alter.c create.c database.c delete.c distinct.c \ - drop.c handle.c insert.c media.c msi.c msi_main.c msiquery.c \ - package.c record.c select.c \ + drop.c handle.c insert.c msi.c msiquery.c record.c select.c \ storages.c streams.c string.c suminfo.c table.c tokenize.c update.c \ where.c \ sql-parser.y \ diff --git a/libmsi/media.c b/libmsi/media.c deleted file mode 100644 index 10d7fe8..0000000 --- a/libmsi/media.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2008 James Hawkins - * - * 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 - */ - -#include - -#define COBJMACROS - -#include "windef.h" -#include "winerror.h" -#include "wine/debug.h" -#include "fdi.h" -#include "msipriv.h" -#include "wingdi.h" -#include "winuser.h" -#include "winreg.h" -#include "shlwapi.h" -#include "objidl.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - -/* from msvcrt/fcntl.h */ -#define _O_RDONLY 0 -#define _O_WRONLY 1 -#define _O_RDWR 2 -#define _O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR) -#define _O_APPEND 0x0008 -#define _O_RANDOM 0x0010 -#define _O_SEQUENTIAL 0x0020 -#define _O_TEMPORARY 0x0040 -#define _O_NOINHERIT 0x0080 -#define _O_CREAT 0x0100 -#define _O_TRUNC 0x0200 -#define _O_EXCL 0x0400 -#define _O_SHORT_LIVED 0x1000 -#define _O_TEXT 0x4000 -#define _O_BINARY 0x8000 - -static MSICABINETSTREAM *msi_get_cabinet_stream( MSIPACKAGE *package, UINT disk_id ) -{ - MSICABINETSTREAM *cab; - - LIST_FOR_EACH_ENTRY( cab, &package->cabinet_streams, MSICABINETSTREAM, entry ) - { - if (cab->disk_id == disk_id) return cab; - } - return NULL; -} - -static void * CDECL cabinet_alloc(ULONG cb) -{ - return msi_alloc(cb); -} - -static void CDECL cabinet_free(void *pv) -{ - msi_free(pv); -} - -static INT_PTR CDECL cabinet_open(char *pszFile, int oflag, int pmode) -{ - HANDLE handle; - DWORD dwAccess = 0; - DWORD dwShareMode = 0; - DWORD dwCreateDisposition = OPEN_EXISTING; - - switch (oflag & _O_ACCMODE) - { - case _O_RDONLY: - dwAccess = GENERIC_READ; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE; - break; - case _O_WRONLY: - dwAccess = GENERIC_WRITE; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - break; - case _O_RDWR: - dwAccess = GENERIC_READ | GENERIC_WRITE; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - break; - } - - if ((oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) - dwCreateDisposition = CREATE_NEW; - else if (oflag & _O_CREAT) - dwCreateDisposition = CREATE_ALWAYS; - - handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL, - dwCreateDisposition, 0, NULL); - if (handle == INVALID_HANDLE_VALUE) - return 0; - - return (INT_PTR)handle; -} - -static UINT CDECL cabinet_read(INT_PTR hf, void *pv, UINT cb) -{ - HANDLE handle = (HANDLE)hf; - DWORD read; - - if (ReadFile(handle, pv, cb, &read, NULL)) - return read; - - return 0; -} - -static UINT CDECL cabinet_write(INT_PTR hf, void *pv, UINT cb) -{ - HANDLE handle = (HANDLE)hf; - DWORD written; - - if (WriteFile(handle, pv, cb, &written, NULL)) - return written; - - return 0; -} - -static int CDECL cabinet_close(INT_PTR hf) -{ - HANDLE handle = (HANDLE)hf; - return CloseHandle(handle) ? 0 : -1; -} - -static LONG CDECL cabinet_seek(INT_PTR hf, LONG dist, int seektype) -{ - HANDLE handle = (HANDLE)hf; - /* flags are compatible and so are passed straight through */ - return SetFilePointer(handle, dist, NULL, seektype); -} - -struct package_disk -{ - MSIPACKAGE *package; - UINT id; -}; - -static struct package_disk package_disk; - -static INT_PTR CDECL cabinet_open_stream( char *pszFile, int oflag, int pmode ) -{ - MSICABINETSTREAM *cab; - IStream *stream; - WCHAR *encoded; - HRESULT hr; - - cab = msi_get_cabinet_stream( package_disk.package, package_disk.id ); - if (!cab) - { - WARN("failed to get cabinet stream\n"); - return 0; - } - if (!cab->stream[0] || !(encoded = encode_streamname( FALSE, cab->stream + 1 ))) - { - WARN("failed to encode stream name\n"); - return 0; - } - if (msi_clone_open_stream( package_disk.package->db, cab->storage, encoded, &stream ) != ERROR_SUCCESS) - { - hr = IStorage_OpenStream( cab->storage, encoded, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stream ); - if (FAILED(hr)) - { - WARN("failed to open stream 0x%08x\n", hr); - msi_free( encoded ); - return 0; - } - } - msi_free( encoded ); - return (INT_PTR)stream; -} - -static UINT CDECL cabinet_read_stream( INT_PTR hf, void *pv, UINT cb ) -{ - IStream *stm = (IStream *)hf; - DWORD read; - HRESULT hr; - - hr = IStream_Read( stm, pv, cb, &read ); - if (hr == S_OK || hr == S_FALSE) - return read; - - return 0; -} - -static int CDECL cabinet_close_stream( INT_PTR hf ) -{ - IStream *stm = (IStream *)hf; - IStream_Release( stm ); - return 0; -} - -static LONG CDECL cabinet_seek_stream( INT_PTR hf, LONG dist, int seektype ) -{ - IStream *stm = (IStream *)hf; - LARGE_INTEGER move; - ULARGE_INTEGER newpos; - HRESULT hr; - - move.QuadPart = dist; - hr = IStream_Seek( stm, move, seektype, &newpos ); - if (SUCCEEDED(hr)) - { - if (newpos.QuadPart <= MAXLONG) return newpos.QuadPart; - ERR("Too big!\n"); - } - return -1; -} - -static UINT CDECL msi_media_get_disk_info(MSIPACKAGE *package, MSIMEDIAINFO *mi) -{ - MSIRECORD *row; - - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', - '`','M','e','d','i','a','`',' ','W','H','E','R','E',' ', - '`','D','i','s','k','I','d','`',' ','=',' ','%','i',0}; - - row = MSI_QueryGetRecord(package->db, query, mi->disk_id); - if (!row) - { - TRACE("Unable to query row\n"); - return ERROR_FUNCTION_FAILED; - } - - mi->disk_prompt = strdupW(MSI_RecordGetString(row, 3)); - mi->cabinet = strdupW(MSI_RecordGetString(row, 4)); - mi->volume_label = strdupW(MSI_RecordGetString(row, 5)); - - if (!mi->first_volume) - mi->first_volume = strdupW(mi->volume_label); - - msiobj_release(&row->hdr); - return ERROR_SUCCESS; -} - -static INT_PTR cabinet_partial_file(FDINOTIFICATIONTYPE fdint, - PFDINOTIFICATION pfdin) -{ - MSICABDATA *data = pfdin->pv; - data->mi->is_continuous = FALSE; - return 0; -} - -static WCHAR *get_cabinet_filename(MSIMEDIAINFO *mi) -{ - int len; - WCHAR *ret; - - len = strlenW(mi->sourcedir) + strlenW(mi->cabinet) + 1; - if (!(ret = msi_alloc(len * sizeof(WCHAR)))) return NULL; - strcpyW(ret, mi->sourcedir); - strcatW(ret, mi->cabinet); - return ret; -} - -static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint, - PFDINOTIFICATION pfdin) -{ - MSICABDATA *data = pfdin->pv; - MSIMEDIAINFO *mi = data->mi; - LPWSTR cabinet_file = NULL, cab = strdupAtoW(pfdin->psz1); - INT_PTR res = -1; - UINT rc; - - msi_free(mi->disk_prompt); - msi_free(mi->cabinet); - msi_free(mi->volume_label); - mi->disk_prompt = NULL; - mi->cabinet = NULL; - mi->volume_label = NULL; - - mi->disk_id++; - mi->is_continuous = TRUE; - - rc = msi_media_get_disk_info(data->package, mi); - if (rc != ERROR_SUCCESS) - { - ERR("Failed to get next cabinet information: %d\n", rc); - goto done; - } - - if (strcmpiW( mi->cabinet, cab )) - { - ERR("Continuous cabinet does not match the next cabinet in the Media table\n"); - goto done; - } - - if (!(cabinet_file = get_cabinet_filename(mi))) - goto done; - - TRACE("Searching for %s\n", debugstr_w(cabinet_file)); - - res = 0; - if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES) - res = -1; - -done: - msi_free(cab); - msi_free(cabinet_file); - return res; -} - -static INT_PTR cabinet_next_cabinet_stream( FDINOTIFICATIONTYPE fdint, - PFDINOTIFICATION pfdin ) -{ - MSICABDATA *data = pfdin->pv; - MSIMEDIAINFO *mi = data->mi; - UINT rc; - - msi_free( mi->disk_prompt ); - msi_free( mi->cabinet ); - msi_free( mi->volume_label ); - mi->disk_prompt = NULL; - mi->cabinet = NULL; - mi->volume_label = NULL; - - mi->disk_id++; - mi->is_continuous = TRUE; - - rc = msi_media_get_disk_info( data->package, mi ); - if (rc != ERROR_SUCCESS) - { - ERR("Failed to get next cabinet information: %u\n", rc); - return -1; - } - package_disk.id = mi->disk_id; - - TRACE("next cabinet is %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id); - return 0; -} - -static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint, - PFDINOTIFICATION pfdin) -{ - MSICABDATA *data = pfdin->pv; - HANDLE handle = 0; - LPWSTR path = NULL; - DWORD attrs; - - data->curfile = strdupAtoW(pfdin->psz1); - if (!data->cb(data->package, data->curfile, MSICABEXTRACT_BEGINEXTRACT, &path, - &attrs, data->user)) - { - /* We're not extracting this file, so free the filename. */ - msi_free(data->curfile); - data->curfile = NULL; - goto done; - } - - TRACE("extracting %s -> %s\n", debugstr_w(data->curfile), debugstr_w(path)); - - attrs = attrs & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); - if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL; - - handle = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, - NULL, CREATE_ALWAYS, attrs, NULL); - if (handle == INVALID_HANDLE_VALUE) - { - DWORD err = GetLastError(); - DWORD attrs2 = GetFileAttributesW(path); - - if (attrs2 == INVALID_FILE_ATTRIBUTES) - { - ERR("failed to create %s (error %d)\n", debugstr_w(path), err); - goto done; - } - else if (err == ERROR_ACCESS_DENIED && (attrs2 & FILE_ATTRIBUTE_READONLY)) - { - TRACE("removing read-only attribute on %s\n", debugstr_w(path)); - SetFileAttributesW( path, attrs2 & ~FILE_ATTRIBUTE_READONLY ); - handle = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, attrs2, NULL); - - if (handle != INVALID_HANDLE_VALUE) goto done; - err = GetLastError(); - } - if (err == ERROR_SHARING_VIOLATION || err == ERROR_USER_MAPPED_FILE) - { - WCHAR *tmpfileW, *tmppathW, *p; - DWORD len; - - TRACE("file in use, scheduling rename operation\n"); - - if (!(tmppathW = strdupW( path ))) return ERROR_OUTOFMEMORY; - if ((p = strrchrW(tmppathW, '\\'))) *p = 0; - len = strlenW( tmppathW ) + 16; - if (!(tmpfileW = msi_alloc(len * sizeof(WCHAR)))) - { - msi_free( tmppathW ); - return ERROR_OUTOFMEMORY; - } - if (!GetTempFileNameW(tmppathW, szMsi, 0, tmpfileW)) tmpfileW[0] = 0; - msi_free( tmppathW ); - - handle = CreateFileW(tmpfileW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, attrs, NULL); - - if (handle != INVALID_HANDLE_VALUE && - MoveFileExW(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) && - MoveFileExW(tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT)) - { - data->package->need_reboot_at_end = 1; - } - else - { - WARN("failed to schedule rename operation %s (error %d)\n", debugstr_w(path), GetLastError()); - DeleteFileW( tmpfileW ); - } - msi_free(tmpfileW); - } - else - WARN("failed to create %s (error %d)\n", debugstr_w(path), err); - } - -done: - msi_free(path); - - return (INT_PTR)handle; -} - -static INT_PTR cabinet_close_file_info(FDINOTIFICATIONTYPE fdint, - PFDINOTIFICATION pfdin) -{ - MSICABDATA *data = pfdin->pv; - FILETIME ft; - FILETIME ftLocal; - HANDLE handle = (HANDLE)pfdin->hf; - - data->mi->is_continuous = FALSE; - - if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft)) - return -1; - if (!LocalFileTimeToFileTime(&ft, &ftLocal)) - return -1; - if (!SetFileTime(handle, &ftLocal, 0, &ftLocal)) - return -1; - - CloseHandle(handle); - - data->cb(data->package, data->curfile, MSICABEXTRACT_FILEEXTRACTED, NULL, NULL, - data->user); - - msi_free(data->curfile); - data->curfile = NULL; - - return 1; -} - -static INT_PTR CDECL cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) -{ - switch (fdint) - { - case fdintPARTIAL_FILE: - return cabinet_partial_file(fdint, pfdin); - - case fdintNEXT_CABINET: - return cabinet_next_cabinet(fdint, pfdin); - - case fdintCOPY_FILE: - return cabinet_copy_file(fdint, pfdin); - - case fdintCLOSE_FILE_INFO: - return cabinet_close_file_info(fdint, pfdin); - - default: - return 0; - } -} - -static INT_PTR CDECL cabinet_notify_stream( FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin ) -{ - switch (fdint) - { - case fdintPARTIAL_FILE: - return cabinet_partial_file( fdint, pfdin ); - - case fdintNEXT_CABINET: - return cabinet_next_cabinet_stream( fdint, pfdin ); - - case fdintCOPY_FILE: - return cabinet_copy_file( fdint, pfdin ); - - case fdintCLOSE_FILE_INFO: - return cabinet_close_file_info( fdint, pfdin ); - - case fdintCABINET_INFO: - return 0; - - default: - ERR("Unexpected notification %d\n", fdint); - return 0; - } -} - -static BOOL extract_cabinet( MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data ) -{ - LPSTR cabinet, cab_path = NULL; - HFDI hfdi; - ERF erf; - BOOL ret = FALSE; - - TRACE("extracting %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id); - - hfdi = FDICreate( cabinet_alloc, cabinet_free, cabinet_open, cabinet_read, - cabinet_write, cabinet_close, cabinet_seek, 0, &erf ); - if (!hfdi) - { - ERR("FDICreate failed\n"); - return FALSE; - } - - cabinet = strdupWtoA( mi->cabinet ); - if (!cabinet) - goto done; - - cab_path = strdupWtoA( mi->sourcedir ); - if (!cab_path) - goto done; - - ret = FDICopy( hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, data ); - if (!ret) - ERR("FDICopy failed\n"); - -done: - FDIDestroy( hfdi ); - msi_free(cabinet ); - msi_free( cab_path ); - - if (ret) - mi->is_extracted = TRUE; - - return ret; -} - -static BOOL extract_cabinet_stream( MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data ) -{ - static char filename[] = {'<','S','T','R','E','A','M','>',0}; - HFDI hfdi; - ERF erf; - BOOL ret = FALSE; - - TRACE("extracting %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id); - - hfdi = FDICreate( cabinet_alloc, cabinet_free, cabinet_open_stream, cabinet_read_stream, - cabinet_write, cabinet_close_stream, cabinet_seek_stream, 0, &erf ); - if (!hfdi) - { - ERR("FDICreate failed\n"); - return FALSE; - } - - package_disk.package = package; - package_disk.id = mi->disk_id; - - ret = FDICopy( hfdi, filename, NULL, 0, cabinet_notify_stream, NULL, data ); - if (!ret) ERR("FDICopy failed\n"); - - FDIDestroy( hfdi ); - if (ret) mi->is_extracted = TRUE; - return ret; -} - -/*********************************************************************** - * msi_cabextract - * - * Extract files from a cabinet file or stream. - */ -BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data) -{ - if (mi->cabinet[0] == '#') - { - return extract_cabinet_stream( package, mi, data ); - } - return extract_cabinet( package, mi, data ); -} - -UINT msi_add_cabinet_stream( MSIPACKAGE *package, UINT disk_id, IStorage *storage, const WCHAR *name ) -{ - MSICABINETSTREAM *cab, *item; - - TRACE("%p, %u, %p, %s\n", package, disk_id, storage, debugstr_w(name)); - - LIST_FOR_EACH_ENTRY( item, &package->cabinet_streams, MSICABINETSTREAM, entry ) - { - if (item->disk_id == disk_id) - { - TRACE("duplicate disk id %u\n", disk_id); - return ERROR_FUNCTION_FAILED; - } - } - if (!(cab = msi_alloc( sizeof(*cab) ))) return ERROR_OUTOFMEMORY; - if (!(cab->stream = msi_alloc( (strlenW( name ) + 1) * sizeof(WCHAR ) ))) - { - msi_free( cab ); - return ERROR_OUTOFMEMORY; - } - strcpyW( cab->stream, name ); - cab->disk_id = disk_id; - cab->storage = storage; - IStorage_AddRef( storage ); - list_add_tail( &package->cabinet_streams, &cab->entry ); - - return ERROR_SUCCESS; -} diff --git a/libmsi/msi.c b/libmsi/msi.c index 4ebf576..0a388b5 100644 --- a/libmsi/msi.c +++ b/libmsi/msi.c @@ -85,204 +85,6 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz ) return r; } -UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes) -{ - LPWSTR szwLogFile = NULL; - UINT r; - - TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes); - - if( szLogFile ) - { - szwLogFile = strdupAtoW( szLogFile ); - if( !szwLogFile ) - return ERROR_OUTOFMEMORY; - } - r = MsiEnableLogW( dwLogMode, szwLogFile, attributes ); - msi_free( szwLogFile ); - return r; -} - -UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes) -{ - TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes); - - msi_free(gszLogFile); - gszLogFile = NULL; - if (szLogFile) - { - HANDLE file; - - if (!(attributes & INSTALLLOGATTRIBUTES_APPEND)) - DeleteFileW(szLogFile); - file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); - if (file != INVALID_HANDLE_VALUE) - { - gszLogFile = strdupW(szLogFile); - CloseHandle(file); - } - else - ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile), GetLastError()); - } - - return ERROR_SUCCESS; -} - -UINT WINAPI MsiEnumComponentCostsA( MSIHANDLE handle, LPCSTR component, DWORD index, - INSTALLSTATE state, LPSTR drive, DWORD *buflen, - int *cost, int *temp ) -{ - UINT r; - DWORD len; - WCHAR *driveW, *componentW = NULL; - - TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_a(component), index, - state, drive, buflen, cost, temp); - - if (!drive || !buflen) return ERROR_INVALID_PARAMETER; - if (component && !(componentW = strdupAtoW( component ))) return ERROR_OUTOFMEMORY; - - len = *buflen; - if (!(driveW = msi_alloc( len * sizeof(WCHAR) ))) - { - msi_free( componentW ); - return ERROR_OUTOFMEMORY; - } - r = MsiEnumComponentCostsW( handle, componentW, index, state, driveW, buflen, cost, temp ); - if (!r) - { - WideCharToMultiByte( CP_ACP, 0, driveW, -1, drive, len, NULL, NULL ); - } - msi_free( componentW ); - msi_free( driveW ); - return r; -} - -static UINT set_drive( WCHAR *buffer, WCHAR letter ) -{ - buffer[0] = letter; - buffer[1] = ':'; - buffer[2] = 0; - return 2; -} - -UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, LPCWSTR component, DWORD index, - INSTALLSTATE state, LPWSTR drive, DWORD *buflen, - int *cost, int *temp ) -{ - UINT r = ERROR_NO_MORE_ITEMS; - MSICOMPONENT *comp = NULL; - MSIPACKAGE *package; - MSIFILE *file; - STATSTG stat = {0}; - WCHAR path[MAX_PATH]; - - TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_w(component), index, - state, drive, buflen, cost, temp); - - if (!drive || !buflen || !cost || !temp) return ERROR_INVALID_PARAMETER; - package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); - if ( !package ) - return ERROR_INVALID_HANDLE; - - if (!msi_get_property_int( package->db, szCostingComplete, 0 )) - { - msiobj_release( &package->hdr ); - return ERROR_FUNCTION_NOT_CALLED; - } - if (component && component[0] && !(comp = msi_get_loaded_component( package, component ))) - { - msiobj_release( &package->hdr ); - return ERROR_UNKNOWN_COMPONENT; - } - if (*buflen < 3) - { - *buflen = 2; - msiobj_release( &package->hdr ); - return ERROR_MORE_DATA; - } - if (index) - { - msiobj_release( &package->hdr ); - return ERROR_NO_MORE_ITEMS; - } - - drive[0] = 0; - *cost = *temp = 0; - GetWindowsDirectoryW( path, MAX_PATH ); - if (component && component[0]) - { - if (comp->assembly && !comp->assembly->application) *temp = comp->Cost; - if (!comp->Enabled || !comp->KeyPath) - { - *cost = 0; - *buflen = set_drive( drive, path[0] ); - r = ERROR_SUCCESS; - } - else if ((file = msi_get_loaded_file( package, comp->KeyPath ))) - { - *cost = max( 8, comp->Cost / 512 ); - *buflen = set_drive( drive, file->TargetPath[0] ); - r = ERROR_SUCCESS; - } - } - else if (IStorage_Stat( package->db->storage, &stat, STATFLAG_NONAME ) == S_OK) - { - *temp = max( 8, stat.cbSize.QuadPart / 512 ); - *buflen = set_drive( drive, path[0] ); - r = ERROR_SUCCESS; - } - msiobj_release( &package->hdr ); - return r; -} - -INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd) -{ - INSTALLUILEVEL old = gUILevel; - HWND oldwnd = gUIhwnd; - - TRACE("%08x %p\n", dwUILevel, phWnd); - - gUILevel = dwUILevel; - if (phWnd) - { - gUIhwnd = *phWnd; - *phWnd = oldwnd; - } - return old; -} - -INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, - DWORD dwMessageFilter, LPVOID pvContext) -{ - INSTALLUI_HANDLERA prev = gUIHandlerA; - - TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext); - - gUIHandlerA = puiHandler; - gUIHandlerW = NULL; - gUIFilter = dwMessageFilter; - gUIContext = pvContext; - - return prev; -} - -INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler, - DWORD dwMessageFilter, LPVOID pvContext) -{ - INSTALLUI_HANDLERW prev = gUIHandlerW; - - TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext); - - gUIHandlerA = NULL; - gUIHandlerW = puiHandler; - gUIFilter = dwMessageFilter; - gUIContext = pvContext; - - return prev; -} - /****************************************************************** * MsiGetProductPropertyA [MSI.@] */ @@ -585,25 +387,6 @@ UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions, return r; } -/*********************************************************************** - * MsiSetExternalUIRecord [MSI.@] - */ -UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler, - DWORD filter, LPVOID context, - PINSTALLUI_HANDLER_RECORD prev ) -{ - TRACE("%p %08x %p %p\n", handler, filter, context, prev); - - if (prev) - *prev = gUIHandlerRecord; - - gUIHandlerRecord = handler; - gUIFilter = filter; - gUIContext = context; - - return ERROR_SUCCESS; -} - /*********************************************************************** * MsiInstallMissingComponentA [MSI.@] */ diff --git a/libmsi/msi_main.c b/libmsi/msi_main.c deleted file mode 100644 index 17c3238..0000000 --- a/libmsi/msi_main.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2006 Mike McCormack 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 - */ - -#include - -#define COBJMACROS -#define NONAMELESSUNION - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "shlwapi.h" -#include "oleauto.h" -#include "rpcproxy.h" -#include "msipriv.h" -#include "msiserver.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - -/* the UI level */ -INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC; -HWND gUIhwnd = 0; -INSTALLUI_HANDLERA gUIHandlerA = NULL; -INSTALLUI_HANDLERW gUIHandlerW = NULL; -INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL; -DWORD gUIFilter = 0; -LPVOID gUIContext = NULL; -WCHAR *gszLogFile = NULL; -HINSTANCE msi_hInstance; 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 -#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; -} -- cgit