mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 05:58:13 +00:00
[msi]
-partial sync to wine 1.3.16 svn path=/trunk/; revision=51096
This commit is contained in:
parent
06afcd3dd6
commit
7dfa68869c
36 changed files with 2657 additions and 1638 deletions
File diff suppressed because it is too large
Load diff
|
@ -71,7 +71,7 @@ void msi_parse_version_string(LPCWSTR verStr, PDWORD ms, PDWORD ls)
|
||||||
x4 = atoiW(ptr + 1);
|
x4 = atoiW(ptr + 1);
|
||||||
/* FIXME: byte-order dependent? */
|
/* FIXME: byte-order dependent? */
|
||||||
*ms = x1 << 16 | x2;
|
*ms = x1 << 16 | x2;
|
||||||
*ls = x3 << 16 | x4;
|
if (ls) *ls = x3 << 16 | x4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fills in sig with the values from the Signature table, where name is the
|
/* Fills in sig with the values from the Signature table, where name is the
|
||||||
|
@ -796,8 +796,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
|
||||||
if (hFind != INVALID_HANDLE_VALUE)
|
if (hFind != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
|
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
|
||||||
lstrcmpW(findData.cFileName, szDot) &&
|
strcmpW( findData.cFileName, szDot ) &&
|
||||||
lstrcmpW(findData.cFileName, szDotDot))
|
strcmpW( findData.cFileName, szDotDot ))
|
||||||
{
|
{
|
||||||
lstrcpyW(subpath, dir);
|
lstrcpyW(subpath, dir);
|
||||||
PathAppendW(subpath, findData.cFileName);
|
PathAppendW(subpath, findData.cFileName);
|
||||||
|
@ -808,8 +808,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
|
||||||
while (rc == ERROR_SUCCESS && !*appValue &&
|
while (rc == ERROR_SUCCESS && !*appValue &&
|
||||||
FindNextFileW(hFind, &findData) != 0)
|
FindNextFileW(hFind, &findData) != 0)
|
||||||
{
|
{
|
||||||
if (!lstrcmpW(findData.cFileName, szDot) ||
|
if (!strcmpW( findData.cFileName, szDot ) ||
|
||||||
!lstrcmpW(findData.cFileName, szDotDot))
|
!strcmpW( findData.cFileName, szDotDot ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
lstrcpyW(subpath, dir);
|
lstrcpyW(subpath, dir);
|
||||||
|
|
629
reactos/dll/win32/msi/assembly.c
Normal file
629
reactos/dll/win32/msi/assembly.c
Normal file
|
@ -0,0 +1,629 @@
|
||||||
|
/*
|
||||||
|
* Implementation of the Microsoft Installer (msi.dll)
|
||||||
|
*
|
||||||
|
* Copyright 2010 Hans Leidekker 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 <stdarg.h>
|
||||||
|
|
||||||
|
#define COBJMACROS
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "msipriv.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||||
|
|
||||||
|
static HRESULT (WINAPI *pCreateAssemblyCacheNet11)( IAssemblyCache **, DWORD );
|
||||||
|
static HRESULT (WINAPI *pCreateAssemblyCacheNet20)( IAssemblyCache **, DWORD );
|
||||||
|
static HRESULT (WINAPI *pCreateAssemblyCacheSxs)( IAssemblyCache **, DWORD );
|
||||||
|
static HRESULT (WINAPI *pLoadLibraryShim)( LPCWSTR, LPCWSTR, LPVOID, HMODULE * );
|
||||||
|
static HRESULT (WINAPI *pGetFileVersion)( LPCWSTR, LPWSTR, DWORD, DWORD * );
|
||||||
|
|
||||||
|
static BOOL init_function_pointers( void )
|
||||||
|
{
|
||||||
|
static const WCHAR szFusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
|
||||||
|
static const WCHAR szVersion11[] = {'v','1','.','1','.','4','3','2','2',0};
|
||||||
|
static const WCHAR szVersion20[] = {'v','2','.','0','.','5','0','7','2','7',0};
|
||||||
|
HMODULE hfusion11 = NULL, hfusion20 = NULL, hmscoree, hsxs;
|
||||||
|
|
||||||
|
if (pCreateAssemblyCacheNet11 || pCreateAssemblyCacheNet20) return TRUE;
|
||||||
|
|
||||||
|
if (!(hmscoree = LoadLibraryA( "mscoree.dll" ))) return FALSE;
|
||||||
|
if (!(pGetFileVersion = (void *)GetProcAddress( hmscoree, "GetFileVersion" ))) goto error;
|
||||||
|
if (!(pLoadLibraryShim = (void *)GetProcAddress( hmscoree, "LoadLibraryShim" ))) goto error;
|
||||||
|
|
||||||
|
if (!pLoadLibraryShim( szFusion, szVersion11, NULL, &hfusion11 ))
|
||||||
|
pCreateAssemblyCacheNet11 = (void *)GetProcAddress( hfusion11, "CreateAssemblyCache" );
|
||||||
|
|
||||||
|
if (!pLoadLibraryShim( szFusion, szVersion20, NULL, &hfusion20 ))
|
||||||
|
pCreateAssemblyCacheNet20 = (void *)GetProcAddress( hfusion20, "CreateAssemblyCache" );
|
||||||
|
|
||||||
|
if (!pCreateAssemblyCacheNet11 && !pCreateAssemblyCacheNet20) goto error;
|
||||||
|
|
||||||
|
if (!(hsxs = LoadLibraryA( "sxs.dll" ))) goto error;
|
||||||
|
if (!(pCreateAssemblyCacheSxs = (void *)GetProcAddress( hsxs, "CreateAssemblyCache" ))) goto error;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
pCreateAssemblyCacheNet11 = NULL;
|
||||||
|
pCreateAssemblyCacheNet20 = NULL;
|
||||||
|
FreeLibrary( hfusion11 );
|
||||||
|
FreeLibrary( hfusion20 );
|
||||||
|
FreeLibrary( hmscoree );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL init_assembly_caches( MSIPACKAGE *package )
|
||||||
|
{
|
||||||
|
if (!init_function_pointers()) return FALSE;
|
||||||
|
if (package->cache_net[CLR_VERSION_V11] || package->cache_net[CLR_VERSION_V20]) return TRUE;
|
||||||
|
if (pCreateAssemblyCacheSxs( &package->cache_sxs, 0 ) != S_OK) return FALSE;
|
||||||
|
|
||||||
|
if (pCreateAssemblyCacheNet11) pCreateAssemblyCacheNet11( &package->cache_net[CLR_VERSION_V11], 0 );
|
||||||
|
if (pCreateAssemblyCacheNet20) pCreateAssemblyCacheNet20( &package->cache_net[CLR_VERSION_V20], 0 );
|
||||||
|
|
||||||
|
if (package->cache_net[CLR_VERSION_V11] || package->cache_net[CLR_VERSION_V20])
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (package->cache_net[CLR_VERSION_V11])
|
||||||
|
{
|
||||||
|
IAssemblyCache_Release( package->cache_net[CLR_VERSION_V11] );
|
||||||
|
package->cache_net[CLR_VERSION_V11] = NULL;
|
||||||
|
}
|
||||||
|
if (package->cache_net[CLR_VERSION_V20])
|
||||||
|
{
|
||||||
|
IAssemblyCache_Release( package->cache_net[CLR_VERSION_V20] );
|
||||||
|
package->cache_net[CLR_VERSION_V20] = NULL;
|
||||||
|
}
|
||||||
|
IAssemblyCache_Release( package->cache_sxs );
|
||||||
|
package->cache_sxs = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MSIRECORD *get_assembly_record( MSIPACKAGE *package, const WCHAR *comp )
|
||||||
|
{
|
||||||
|
static const WCHAR query[] = {
|
||||||
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'`','M','s','i','A','s','s','e','m','b','l','y','`',' ',
|
||||||
|
'W','H','E','R','E',' ','`','C','o','m','p','o','n','e','n','t','_','`',
|
||||||
|
' ','=',' ','\'','%','s','\'',0};
|
||||||
|
MSIQUERY *view;
|
||||||
|
MSIRECORD *rec;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
r = MSI_OpenQuery( package->db, &view, query, comp );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
r = MSI_ViewExecute( view, NULL );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
msiobj_release( &view->hdr );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
r = MSI_ViewFetch( view, &rec );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
msiobj_release( &view->hdr );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!MSI_RecordGetString( rec, 4 ))
|
||||||
|
TRACE("component is a global assembly\n");
|
||||||
|
|
||||||
|
msiobj_release( &view->hdr );
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct assembly_name
|
||||||
|
{
|
||||||
|
UINT count;
|
||||||
|
UINT index;
|
||||||
|
WCHAR **attrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
static UINT get_assembly_name_attribute( MSIRECORD *rec, LPVOID param )
|
||||||
|
{
|
||||||
|
static const WCHAR fmtW[] = {'%','s','=','"','%','s','"',0};
|
||||||
|
static const WCHAR nameW[] = {'n','a','m','e',0};
|
||||||
|
struct assembly_name *name = param;
|
||||||
|
const WCHAR *attr = MSI_RecordGetString( rec, 2 );
|
||||||
|
const WCHAR *value = MSI_RecordGetString( rec, 3 );
|
||||||
|
int len = strlenW( fmtW ) + strlenW( attr ) + strlenW( value );
|
||||||
|
|
||||||
|
if (!(name->attrs[name->index] = msi_alloc( len * sizeof(WCHAR) )))
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (!strcmpiW( attr, nameW )) strcpyW( name->attrs[name->index++], value );
|
||||||
|
else sprintfW( name->attrs[name->index++], fmtW, attr, value );
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WCHAR *get_assembly_display_name( MSIDATABASE *db, const WCHAR *comp, MSIASSEMBLY *assembly )
|
||||||
|
{
|
||||||
|
static const WCHAR commaW[] = {',',0};
|
||||||
|
static const WCHAR queryW[] = {
|
||||||
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'`','M','s','i','A','s','s','e','m','b','l','y','N','a','m','e','`',' ',
|
||||||
|
'W','H','E','R','E',' ','`','C','o','m','p','o','n','e','n','t','_','`',
|
||||||
|
' ','=',' ','\'','%','s','\'',0};
|
||||||
|
struct assembly_name name;
|
||||||
|
WCHAR *display_name = NULL;
|
||||||
|
MSIQUERY *view;
|
||||||
|
UINT i, r;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
r = MSI_OpenQuery( db, &view, queryW, comp );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
name.count = 0;
|
||||||
|
name.index = 0;
|
||||||
|
name.attrs = NULL;
|
||||||
|
MSI_IterateRecords( view, &name.count, NULL, NULL );
|
||||||
|
if (!name.count) goto done;
|
||||||
|
|
||||||
|
name.attrs = msi_alloc( name.count * sizeof(WCHAR *) );
|
||||||
|
if (!name.attrs) goto done;
|
||||||
|
|
||||||
|
MSI_IterateRecords( view, NULL, get_assembly_name_attribute, &name );
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
for (i = 0; i < name.count; i++) len += strlenW( name.attrs[i] ) + 1;
|
||||||
|
|
||||||
|
display_name = msi_alloc( (len + 1) * sizeof(WCHAR) );
|
||||||
|
if (display_name)
|
||||||
|
{
|
||||||
|
display_name[0] = 0;
|
||||||
|
for (i = 0; i < name.count; i++)
|
||||||
|
{
|
||||||
|
strcatW( display_name, name.attrs[i] );
|
||||||
|
if (i < name.count - 1) strcatW( display_name, commaW );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
msiobj_release( &view->hdr );
|
||||||
|
for (i = 0; i < name.count; i++) msi_free( name.attrs[i] );
|
||||||
|
msi_free( name.attrs );
|
||||||
|
return display_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL is_assembly_installed( IAssemblyCache *cache, const WCHAR *display_name )
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
ASSEMBLY_INFO info;
|
||||||
|
|
||||||
|
memset( &info, 0, sizeof(info) );
|
||||||
|
info.cbAssemblyInfo = sizeof(info);
|
||||||
|
hr = IAssemblyCache_QueryAssemblyInfo( cache, QUERYASMINFO_FLAG_GETSIZE, display_name, &info );
|
||||||
|
if (FAILED( hr ))
|
||||||
|
{
|
||||||
|
TRACE("QueryAssemblyInfo returned 0x%08x\n", hr);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return (info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const WCHAR clr_version_v11[] = {'v','1','.','1','.','4','3','2','2',0};
|
||||||
|
static const WCHAR clr_version_v20[] = {'v','2','.','0','.','5','0','7','2','7',0};
|
||||||
|
static const WCHAR clr_version_unknown[] = {'u','n','k','n','o','w','n',0};
|
||||||
|
|
||||||
|
static const WCHAR *clr_version[] =
|
||||||
|
{
|
||||||
|
clr_version_v11,
|
||||||
|
clr_version_v20
|
||||||
|
};
|
||||||
|
|
||||||
|
static const WCHAR *get_clr_version_str( enum clr_version version )
|
||||||
|
{
|
||||||
|
if (version >= sizeof(clr_version)/sizeof(clr_version[0])) return clr_version_unknown;
|
||||||
|
return clr_version[version];
|
||||||
|
}
|
||||||
|
|
||||||
|
MSIASSEMBLY *load_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
|
||||||
|
{
|
||||||
|
MSIRECORD *rec;
|
||||||
|
MSIASSEMBLY *a;
|
||||||
|
|
||||||
|
if (!(rec = get_assembly_record( package, comp->Component ))) return NULL;
|
||||||
|
if (!init_assembly_caches( package ))
|
||||||
|
{
|
||||||
|
ERR("can't initialize assembly caches\n");
|
||||||
|
msiobj_release( &rec->hdr );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(a = msi_alloc_zero( sizeof(MSIASSEMBLY) )))
|
||||||
|
{
|
||||||
|
msiobj_release( &rec->hdr );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
a->feature = strdupW( MSI_RecordGetString( rec, 2 ) );
|
||||||
|
TRACE("feature %s\n", debugstr_w(a->feature));
|
||||||
|
|
||||||
|
a->manifest = strdupW( MSI_RecordGetString( rec, 3 ) );
|
||||||
|
TRACE("manifest %s\n", debugstr_w(a->manifest));
|
||||||
|
|
||||||
|
a->application = strdupW( MSI_RecordGetString( rec, 4 ) );
|
||||||
|
TRACE("application %s\n", debugstr_w(a->application));
|
||||||
|
|
||||||
|
a->attributes = MSI_RecordGetInteger( rec, 5 );
|
||||||
|
TRACE("attributes %u\n", a->attributes);
|
||||||
|
|
||||||
|
if (!(a->display_name = get_assembly_display_name( package->db, comp->Component, a )))
|
||||||
|
{
|
||||||
|
WARN("can't get display name\n");
|
||||||
|
msiobj_release( &rec->hdr );
|
||||||
|
msi_free( a->feature );
|
||||||
|
msi_free( a->manifest );
|
||||||
|
msi_free( a->application );
|
||||||
|
msi_free( a );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
TRACE("display name %s\n", debugstr_w(a->display_name));
|
||||||
|
|
||||||
|
if (a->application)
|
||||||
|
{
|
||||||
|
/* We can't check the manifest here because the target path may still change.
|
||||||
|
So we assume that the assembly is not installed and lean on the InstallFiles
|
||||||
|
action to determine which files need to be installed.
|
||||||
|
*/
|
||||||
|
a->installed = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (a->attributes == msidbAssemblyAttributesWin32)
|
||||||
|
a->installed = is_assembly_installed( package->cache_sxs, a->display_name );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < CLR_VERSION_MAX; i++)
|
||||||
|
{
|
||||||
|
a->clr_version[i] = is_assembly_installed( package->cache_net[i], a->display_name );
|
||||||
|
if (a->clr_version[i])
|
||||||
|
{
|
||||||
|
TRACE("runtime version %s\n", debugstr_w(get_clr_version_str( i )));
|
||||||
|
a->installed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRACE("assembly is %s\n", a->installed ? "installed" : "not installed");
|
||||||
|
msiobj_release( &rec->hdr );
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum clr_version get_clr_version( const WCHAR *filename )
|
||||||
|
{
|
||||||
|
DWORD len;
|
||||||
|
HRESULT hr;
|
||||||
|
enum clr_version version = CLR_VERSION_V11;
|
||||||
|
WCHAR *strW;
|
||||||
|
|
||||||
|
hr = pGetFileVersion( filename, NULL, 0, &len );
|
||||||
|
if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) return CLR_VERSION_V11;
|
||||||
|
if ((strW = msi_alloc( len * sizeof(WCHAR) )))
|
||||||
|
{
|
||||||
|
hr = pGetFileVersion( filename, strW, len, &len );
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < CLR_VERSION_MAX; i++)
|
||||||
|
if (!strcmpW( strW, clr_version[i] )) version = i;
|
||||||
|
}
|
||||||
|
msi_free( strW );
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT install_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
const WCHAR *manifest;
|
||||||
|
IAssemblyCache *cache;
|
||||||
|
MSIASSEMBLY *assembly = comp->assembly;
|
||||||
|
MSIFEATURE *feature = NULL;
|
||||||
|
|
||||||
|
if (comp->assembly->feature)
|
||||||
|
feature = get_loaded_feature( package, comp->assembly->feature );
|
||||||
|
|
||||||
|
if (assembly->application)
|
||||||
|
{
|
||||||
|
if (feature) feature->Action = INSTALLSTATE_LOCAL;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
if (assembly->attributes == msidbAssemblyAttributesWin32)
|
||||||
|
{
|
||||||
|
if (!assembly->manifest)
|
||||||
|
{
|
||||||
|
WARN("no manifest\n");
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
manifest = get_loaded_file( package, assembly->manifest )->TargetPath;
|
||||||
|
cache = package->cache_sxs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
manifest = get_loaded_file( package, comp->KeyPath )->TargetPath;
|
||||||
|
cache = package->cache_net[get_clr_version( manifest )];
|
||||||
|
}
|
||||||
|
TRACE("installing assembly %s\n", debugstr_w(manifest));
|
||||||
|
|
||||||
|
hr = IAssemblyCache_InstallAssembly( cache, 0, manifest, NULL );
|
||||||
|
if (hr != S_OK)
|
||||||
|
{
|
||||||
|
ERR("Failed to install assembly %s (0x%08x)\n", debugstr_w(manifest), hr);
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
if (feature) feature->Action = INSTALLSTATE_LOCAL;
|
||||||
|
assembly->installed = TRUE;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WCHAR *build_local_assembly_path( const WCHAR *filename )
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
WCHAR *ret;
|
||||||
|
|
||||||
|
if (!(ret = msi_alloc( (strlenW( filename ) + 1) * sizeof(WCHAR) )))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; filename[i]; i++)
|
||||||
|
{
|
||||||
|
if (filename[i] == '\\' || filename[i] == '/') ret[i] = '|';
|
||||||
|
else ret[i] = filename[i];
|
||||||
|
}
|
||||||
|
ret[i] = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG open_assemblies_key( UINT context, BOOL win32, HKEY *hkey )
|
||||||
|
{
|
||||||
|
static const WCHAR path_win32[] =
|
||||||
|
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',0};
|
||||||
|
static const WCHAR path_dotnet[] =
|
||||||
|
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\',0};
|
||||||
|
static const WCHAR classes_path_win32[] =
|
||||||
|
{'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',0};
|
||||||
|
static const WCHAR classes_path_dotnet[] =
|
||||||
|
{'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\',0};
|
||||||
|
HKEY root;
|
||||||
|
const WCHAR *path;
|
||||||
|
|
||||||
|
if (context == MSIINSTALLCONTEXT_MACHINE)
|
||||||
|
{
|
||||||
|
root = HKEY_CLASSES_ROOT;
|
||||||
|
if (win32) path = classes_path_win32;
|
||||||
|
else path = classes_path_dotnet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root = HKEY_CURRENT_USER;
|
||||||
|
if (win32) path = path_win32;
|
||||||
|
else path = path_dotnet;
|
||||||
|
}
|
||||||
|
return RegCreateKeyW( root, path, hkey );
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG open_local_assembly_key( UINT context, BOOL win32, const WCHAR *filename, HKEY *hkey )
|
||||||
|
{
|
||||||
|
LONG res;
|
||||||
|
HKEY root;
|
||||||
|
WCHAR *path;
|
||||||
|
|
||||||
|
if (!(path = build_local_assembly_path( filename )))
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if ((res = open_assemblies_key( context, win32, &root )))
|
||||||
|
{
|
||||||
|
msi_free( path );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
res = RegCreateKeyW( root, path, hkey );
|
||||||
|
RegCloseKey( root );
|
||||||
|
msi_free( path );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG delete_local_assembly_key( UINT context, BOOL win32, const WCHAR *filename )
|
||||||
|
{
|
||||||
|
LONG res;
|
||||||
|
HKEY root;
|
||||||
|
WCHAR *path;
|
||||||
|
|
||||||
|
if (!(path = build_local_assembly_path( filename )))
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if ((res = open_assemblies_key( context, win32, &root )))
|
||||||
|
{
|
||||||
|
msi_free( path );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
res = RegDeleteKeyW( root, path );
|
||||||
|
RegCloseKey( root );
|
||||||
|
msi_free( path );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG open_global_assembly_key( UINT context, BOOL win32, HKEY *hkey )
|
||||||
|
{
|
||||||
|
static const WCHAR path_win32[] =
|
||||||
|
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',
|
||||||
|
'G','l','o','b','a','l',0};
|
||||||
|
static const WCHAR path_dotnet[] =
|
||||||
|
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\',
|
||||||
|
'G','l','o','b','a','l',0};
|
||||||
|
static const WCHAR classes_path_win32[] =
|
||||||
|
{'I','n','s','t','a','l','l','e','r','\\','W','i','n','3','2','A','s','s','e','m','b','l','i','e','s','\\',
|
||||||
|
'G','l','o','b','a','l',0};
|
||||||
|
static const WCHAR classes_path_dotnet[] =
|
||||||
|
{'I','n','s','t','a','l','l','e','r','\\','A','s','s','e','m','b','l','i','e','s','\\','G','l','o','b','a','l',0};
|
||||||
|
HKEY root;
|
||||||
|
const WCHAR *path;
|
||||||
|
|
||||||
|
if (context == MSIINSTALLCONTEXT_MACHINE)
|
||||||
|
{
|
||||||
|
root = HKEY_CLASSES_ROOT;
|
||||||
|
if (win32) path = classes_path_win32;
|
||||||
|
else path = classes_path_dotnet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root = HKEY_CURRENT_USER;
|
||||||
|
if (win32) path = path_win32;
|
||||||
|
else path = path_dotnet;
|
||||||
|
}
|
||||||
|
return RegCreateKeyW( root, path, hkey );
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
|
||||||
|
{
|
||||||
|
MSICOMPONENT *comp;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(comp, &package->components, MSICOMPONENT, entry)
|
||||||
|
{
|
||||||
|
LONG res;
|
||||||
|
HKEY hkey;
|
||||||
|
GUID guid;
|
||||||
|
DWORD size;
|
||||||
|
WCHAR buffer[43];
|
||||||
|
MSIRECORD *uirow;
|
||||||
|
MSIASSEMBLY *assembly = comp->assembly;
|
||||||
|
BOOL win32;
|
||||||
|
|
||||||
|
if (!assembly || !comp->ComponentId) continue;
|
||||||
|
|
||||||
|
if (!comp->Enabled)
|
||||||
|
{
|
||||||
|
TRACE("component is disabled: %s\n", debugstr_w(comp->Component));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp->ActionRequest != INSTALLSTATE_LOCAL)
|
||||||
|
{
|
||||||
|
TRACE("Component not scheduled for installation: %s\n", debugstr_w(comp->Component));
|
||||||
|
comp->Action = comp->Installed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
comp->Action = INSTALLSTATE_LOCAL;
|
||||||
|
|
||||||
|
TRACE("publishing %s\n", debugstr_w(comp->Component));
|
||||||
|
|
||||||
|
CLSIDFromString( package->ProductCode, &guid );
|
||||||
|
encode_base85_guid( &guid, buffer );
|
||||||
|
buffer[20] = '>';
|
||||||
|
CLSIDFromString( comp->ComponentId, &guid );
|
||||||
|
encode_base85_guid( &guid, buffer + 21 );
|
||||||
|
buffer[42] = 0;
|
||||||
|
|
||||||
|
win32 = assembly->attributes & msidbAssemblyAttributesWin32;
|
||||||
|
if (assembly->application)
|
||||||
|
{
|
||||||
|
MSIFILE *file = get_loaded_file( package, assembly->application );
|
||||||
|
if ((res = open_local_assembly_key( package->Context, win32, file->TargetPath, &hkey )))
|
||||||
|
{
|
||||||
|
WARN("failed to open local assembly key %d\n", res);
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((res = open_global_assembly_key( package->Context, win32, &hkey )))
|
||||||
|
{
|
||||||
|
WARN("failed to open global assembly key %d\n", res);
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size = sizeof(buffer);
|
||||||
|
if ((res = RegSetValueExW( hkey, assembly->display_name, 0, REG_MULTI_SZ, (const BYTE *)buffer, size )))
|
||||||
|
{
|
||||||
|
WARN("failed to set assembly value %d\n", res);
|
||||||
|
}
|
||||||
|
RegCloseKey( hkey );
|
||||||
|
|
||||||
|
uirow = MSI_CreateRecord( 2 );
|
||||||
|
MSI_RecordSetStringW( uirow, 2, assembly->display_name );
|
||||||
|
ui_actiondata( package, szMsiPublishAssemblies, uirow );
|
||||||
|
msiobj_release( &uirow->hdr );
|
||||||
|
}
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
|
||||||
|
{
|
||||||
|
MSICOMPONENT *comp;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(comp, &package->components, MSICOMPONENT, entry)
|
||||||
|
{
|
||||||
|
LONG res;
|
||||||
|
MSIRECORD *uirow;
|
||||||
|
MSIASSEMBLY *assembly = comp->assembly;
|
||||||
|
BOOL win32;
|
||||||
|
|
||||||
|
if (!assembly || !comp->ComponentId) continue;
|
||||||
|
|
||||||
|
if (!comp->Enabled)
|
||||||
|
{
|
||||||
|
TRACE("component is disabled: %s\n", debugstr_w(comp->Component));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp->ActionRequest != INSTALLSTATE_ABSENT)
|
||||||
|
{
|
||||||
|
TRACE("Component not scheduled for removal: %s\n", debugstr_w(comp->Component));
|
||||||
|
comp->Action = comp->Installed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
comp->Action = INSTALLSTATE_ABSENT;
|
||||||
|
|
||||||
|
TRACE("unpublishing %s\n", debugstr_w(comp->Component));
|
||||||
|
|
||||||
|
win32 = assembly->attributes & msidbAssemblyAttributesWin32;
|
||||||
|
if (assembly->application)
|
||||||
|
{
|
||||||
|
MSIFILE *file = get_loaded_file( package, assembly->application );
|
||||||
|
if ((res = delete_local_assembly_key( package->Context, win32, file->TargetPath )))
|
||||||
|
WARN("failed to delete local assembly key %d\n", res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HKEY hkey;
|
||||||
|
if ((res = open_global_assembly_key( package->Context, win32, &hkey )))
|
||||||
|
WARN("failed to delete global assembly key %d\n", res);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((res = RegDeleteValueW( hkey, assembly->display_name )))
|
||||||
|
WARN("failed to delete global assembly value %d\n", res);
|
||||||
|
RegCloseKey( hkey );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uirow = MSI_CreateRecord( 2 );
|
||||||
|
MSI_RecordSetStringW( uirow, 2, assembly->display_name );
|
||||||
|
ui_actiondata( package, szMsiPublishAssemblies, uirow );
|
||||||
|
msiobj_release( &uirow->hdr );
|
||||||
|
}
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
|
@ -87,7 +87,7 @@ static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name )
|
||||||
/* check for appids already loaded */
|
/* check for appids already loaded */
|
||||||
LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry )
|
LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpiW( appid->AppID, name )==0)
|
if (!strcmpiW( appid->AppID, name ))
|
||||||
{
|
{
|
||||||
TRACE("found appid %s %p\n", debugstr_w(name), appid);
|
TRACE("found appid %s %p\n", debugstr_w(name), appid);
|
||||||
return appid;
|
return appid;
|
||||||
|
@ -192,7 +192,7 @@ static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
|
||||||
/* check for progids already loaded */
|
/* check for progids already loaded */
|
||||||
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
|
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
|
||||||
{
|
{
|
||||||
if (strcmpiW( progid->ProgID,name )==0)
|
if (!strcmpiW( progid->ProgID, name ))
|
||||||
{
|
{
|
||||||
TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
|
TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
|
||||||
return progid;
|
return progid;
|
||||||
|
@ -323,7 +323,7 @@ static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid)
|
||||||
/* check for classes already loaded */
|
/* check for classes already loaded */
|
||||||
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpiW( cls->clsid, classid )==0)
|
if (!strcmpiW( cls->clsid, classid ))
|
||||||
{
|
{
|
||||||
TRACE("found class %s (%p)\n",debugstr_w(classid), cls);
|
TRACE("found class %s (%p)\n",debugstr_w(classid), cls);
|
||||||
return cls;
|
return cls;
|
||||||
|
@ -384,7 +384,7 @@ static MSIMIME *load_given_mime( MSIPACKAGE *package, LPCWSTR mime )
|
||||||
/* check for mime already loaded */
|
/* check for mime already loaded */
|
||||||
LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
|
LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
|
||||||
{
|
{
|
||||||
if (strcmpiW(mt->ContentType,mime)==0)
|
if (!strcmpiW( mt->ContentType, mime ))
|
||||||
{
|
{
|
||||||
TRACE("found mime %s (%p)\n",debugstr_w(mime), mt);
|
TRACE("found mime %s (%p)\n",debugstr_w(mime), mt);
|
||||||
return mt;
|
return mt;
|
||||||
|
@ -458,7 +458,7 @@ static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR name )
|
||||||
/* check for extensions already loaded */
|
/* check for extensions already loaded */
|
||||||
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
||||||
{
|
{
|
||||||
if (strcmpiW( ext->Extension, name )==0)
|
if (!strcmpiW( ext->Extension, name ))
|
||||||
{
|
{
|
||||||
TRACE("extension %s already loaded %p\n", debugstr_w(name), ext);
|
TRACE("extension %s already loaded %p\n", debugstr_w(name), ext);
|
||||||
return ext;
|
return ext;
|
||||||
|
@ -850,8 +850,7 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
|
||||||
}
|
}
|
||||||
feature->Action = feature->ActionRequest;
|
feature->Action = feature->ActionRequest;
|
||||||
|
|
||||||
file = get_loaded_file( package, comp->KeyPath );
|
if (!comp->KeyPath || !(file = get_loaded_file( package, comp->KeyPath )))
|
||||||
if (!file)
|
|
||||||
{
|
{
|
||||||
TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
|
TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -2323,26 +2323,36 @@ static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
|
||||||
switch (operator)
|
switch (operator)
|
||||||
{
|
{
|
||||||
case COND_SS:
|
case COND_SS:
|
||||||
return strstrW( a, b ) ? 1 : 0;
|
return strstrW( a, b ) != 0;
|
||||||
case COND_ISS:
|
case COND_ISS:
|
||||||
return strstriW( a, b ) ? 1 : 0;
|
return strstriW( a, b ) != 0;
|
||||||
case COND_LHS:
|
case COND_LHS:
|
||||||
return 0 == strncmpW( a, b, lstrlenW( b ) );
|
{
|
||||||
|
int l = strlenW( a );
|
||||||
|
int r = strlenW( b );
|
||||||
|
if (r > l) return 0;
|
||||||
|
return !strncmpW( a, b, r );
|
||||||
|
}
|
||||||
case COND_RHS:
|
case COND_RHS:
|
||||||
{
|
{
|
||||||
int l = lstrlenW( a );
|
int l = strlenW( a );
|
||||||
int r = lstrlenW( b );
|
int r = strlenW( b );
|
||||||
if (r > l) return 0;
|
if (r > l) return 0;
|
||||||
return 0 == lstrcmpW( a + (l - r), b );
|
return !strncmpW( a + (l - r), b, r );
|
||||||
}
|
}
|
||||||
case COND_ILHS:
|
case COND_ILHS:
|
||||||
return 0 == strncmpiW( a, b, lstrlenW( b ) );
|
{
|
||||||
|
int l = strlenW( a );
|
||||||
|
int r = strlenW( b );
|
||||||
|
if (r > l) return 0;
|
||||||
|
return !strncmpiW( a, b, r );
|
||||||
|
}
|
||||||
case COND_IRHS:
|
case COND_IRHS:
|
||||||
{
|
{
|
||||||
int l = lstrlenW( a );
|
int l = strlenW( a );
|
||||||
int r = lstrlenW( b );
|
int r = strlenW( b );
|
||||||
if (r > l) return 0;
|
if (r > l) return 0;
|
||||||
return 0 == lstrcmpiW( a + (l - r), b );
|
return !strncmpiW( a + (l - r), b, r );
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ERR("invalid substring operator\n");
|
ERR("invalid substring operator\n");
|
||||||
|
@ -2367,29 +2377,29 @@ static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert )
|
||||||
switch (operator)
|
switch (operator)
|
||||||
{
|
{
|
||||||
case COND_LT:
|
case COND_LT:
|
||||||
return -1 == lstrcmpW( a, b );
|
return strcmpW( a, b ) < 0;
|
||||||
case COND_GT:
|
case COND_GT:
|
||||||
return 1 == lstrcmpW( a, b );
|
return strcmpW( a, b ) > 0;
|
||||||
case COND_EQ:
|
case COND_EQ:
|
||||||
return 0 == lstrcmpW( a, b );
|
return strcmpW( a, b ) == 0;
|
||||||
case COND_NE:
|
case COND_NE:
|
||||||
return 0 != lstrcmpW( a, b );
|
return strcmpW( a, b ) != 0;
|
||||||
case COND_GE:
|
case COND_GE:
|
||||||
return -1 != lstrcmpW( a, b );
|
return strcmpW( a, b ) >= 0;
|
||||||
case COND_LE:
|
case COND_LE:
|
||||||
return 1 != lstrcmpW( a, b );
|
return strcmpW( a, b ) <= 0;
|
||||||
case COND_ILT:
|
case COND_ILT:
|
||||||
return -1 == lstrcmpiW( a, b );
|
return strcmpiW( a, b ) < 0;
|
||||||
case COND_IGT:
|
case COND_IGT:
|
||||||
return 1 == lstrcmpiW( a, b );
|
return strcmpiW( a, b ) > 0;
|
||||||
case COND_IEQ:
|
case COND_IEQ:
|
||||||
return 0 == lstrcmpiW( a, b );
|
return strcmpiW( a, b ) == 0;
|
||||||
case COND_INE:
|
case COND_INE:
|
||||||
return 0 != lstrcmpiW( a, b );
|
return strcmpiW( a, b ) != 0;
|
||||||
case COND_IGE:
|
case COND_IGE:
|
||||||
return -1 != lstrcmpiW( a, b );
|
return strcmpiW( a, b ) >= 0;
|
||||||
case COND_ILE:
|
case COND_ILE:
|
||||||
return 1 != lstrcmpiW( a, b );
|
return strcmpiW( a, b ) <= 0;
|
||||||
default:
|
default:
|
||||||
ERR("invalid string operator\n");
|
ERR("invalid string operator\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -456,26 +456,36 @@ static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
|
||||||
switch (operator)
|
switch (operator)
|
||||||
{
|
{
|
||||||
case COND_SS:
|
case COND_SS:
|
||||||
return strstrW( a, b ) ? 1 : 0;
|
return strstrW( a, b ) != 0;
|
||||||
case COND_ISS:
|
case COND_ISS:
|
||||||
return strstriW( a, b ) ? 1 : 0;
|
return strstriW( a, b ) != 0;
|
||||||
case COND_LHS:
|
case COND_LHS:
|
||||||
return 0 == strncmpW( a, b, lstrlenW( b ) );
|
{
|
||||||
|
int l = strlenW( a );
|
||||||
|
int r = strlenW( b );
|
||||||
|
if (r > l) return 0;
|
||||||
|
return !strncmpW( a, b, r );
|
||||||
|
}
|
||||||
case COND_RHS:
|
case COND_RHS:
|
||||||
{
|
{
|
||||||
int l = lstrlenW( a );
|
int l = strlenW( a );
|
||||||
int r = lstrlenW( b );
|
int r = strlenW( b );
|
||||||
if (r > l) return 0;
|
if (r > l) return 0;
|
||||||
return 0 == lstrcmpW( a + (l - r), b );
|
return !strncmpW( a + (l - r), b, r );
|
||||||
}
|
}
|
||||||
case COND_ILHS:
|
case COND_ILHS:
|
||||||
return 0 == strncmpiW( a, b, lstrlenW( b ) );
|
{
|
||||||
|
int l = strlenW( a );
|
||||||
|
int r = strlenW( b );
|
||||||
|
if (r > l) return 0;
|
||||||
|
return !strncmpiW( a, b, r );
|
||||||
|
}
|
||||||
case COND_IRHS:
|
case COND_IRHS:
|
||||||
{
|
{
|
||||||
int l = lstrlenW( a );
|
int l = strlenW( a );
|
||||||
int r = lstrlenW( b );
|
int r = strlenW( b );
|
||||||
if (r > l) return 0;
|
if (r > l) return 0;
|
||||||
return 0 == lstrcmpiW( a + (l - r), b );
|
return !strncmpiW( a + (l - r), b, r );
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ERR("invalid substring operator\n");
|
ERR("invalid substring operator\n");
|
||||||
|
@ -500,29 +510,29 @@ static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert )
|
||||||
switch (operator)
|
switch (operator)
|
||||||
{
|
{
|
||||||
case COND_LT:
|
case COND_LT:
|
||||||
return -1 == lstrcmpW( a, b );
|
return strcmpW( a, b ) < 0;
|
||||||
case COND_GT:
|
case COND_GT:
|
||||||
return 1 == lstrcmpW( a, b );
|
return strcmpW( a, b ) > 0;
|
||||||
case COND_EQ:
|
case COND_EQ:
|
||||||
return 0 == lstrcmpW( a, b );
|
return strcmpW( a, b ) == 0;
|
||||||
case COND_NE:
|
case COND_NE:
|
||||||
return 0 != lstrcmpW( a, b );
|
return strcmpW( a, b ) != 0;
|
||||||
case COND_GE:
|
case COND_GE:
|
||||||
return -1 != lstrcmpW( a, b );
|
return strcmpW( a, b ) >= 0;
|
||||||
case COND_LE:
|
case COND_LE:
|
||||||
return 1 != lstrcmpW( a, b );
|
return strcmpW( a, b ) <= 0;
|
||||||
case COND_ILT:
|
case COND_ILT:
|
||||||
return -1 == lstrcmpiW( a, b );
|
return strcmpiW( a, b ) < 0;
|
||||||
case COND_IGT:
|
case COND_IGT:
|
||||||
return 1 == lstrcmpiW( a, b );
|
return strcmpiW( a, b ) > 0;
|
||||||
case COND_IEQ:
|
case COND_IEQ:
|
||||||
return 0 == lstrcmpiW( a, b );
|
return strcmpiW( a, b ) == 0;
|
||||||
case COND_INE:
|
case COND_INE:
|
||||||
return 0 != lstrcmpiW( a, b );
|
return strcmpiW( a, b ) != 0;
|
||||||
case COND_IGE:
|
case COND_IGE:
|
||||||
return -1 != lstrcmpiW( a, b );
|
return strcmpiW( a, b ) >= 0;
|
||||||
case COND_ILE:
|
case COND_ILE:
|
||||||
return 1 != lstrcmpiW( a, b );
|
return strcmpiW( a, b ) <= 0;
|
||||||
default:
|
default:
|
||||||
ERR("invalid string operator\n");
|
ERR("invalid string operator\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
#include "msi.h"
|
#include "msi.h"
|
||||||
#include "msiquery.h"
|
#include "msiquery.h"
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
|
@ -153,7 +154,7 @@ static UINT check_columns( const column_info *col_info )
|
||||||
/* check for two columns with the same name */
|
/* check for two columns with the same name */
|
||||||
for( c1 = col_info; c1; c1 = c1->next )
|
for( c1 = col_info; c1; c1 = c1->next )
|
||||||
for( c2 = c1->next; c2; c2 = c2->next )
|
for( c2 = c1->next; c2; c2 = c2->next )
|
||||||
if (!lstrcmpW(c1->column, c2->column))
|
if (!strcmpW( c1->column, c2->column ))
|
||||||
return ERROR_BAD_QUERY_SYNTAX;
|
return ERROR_BAD_QUERY_SYNTAX;
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
|
@ -236,7 +236,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
||||||
}
|
}
|
||||||
else if (type & msidbCustomActionTypeRollback)
|
else if (type & msidbCustomActionTypeRollback)
|
||||||
{
|
{
|
||||||
FIXME("Deferring rollback only action... rollbacks not supported yet\n");
|
FIXME("Deferring rollback only action\n");
|
||||||
schedule_action(package, ROLLBACK_SCRIPT, deferred);
|
schedule_action(package, ROLLBACK_SCRIPT, deferred);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -274,6 +274,12 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
||||||
|
|
||||||
msi_free(actiondata);
|
msi_free(actiondata);
|
||||||
}
|
}
|
||||||
|
if (type & msidbCustomActionTypeRollback)
|
||||||
|
{
|
||||||
|
FIXME("Rollbacks not supported yet\n");
|
||||||
|
rc = ERROR_SUCCESS;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!check_execution_scheduling_options(package,action,type))
|
else if (!check_execution_scheduling_options(package,action,type))
|
||||||
{
|
{
|
||||||
|
@ -355,46 +361,48 @@ end:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
|
||||||
static UINT store_binary_to_temp(MSIPACKAGE *package, LPCWSTR source,
|
|
||||||
LPWSTR tmp_file)
|
|
||||||
{
|
{
|
||||||
static const WCHAR query[] = {
|
static const WCHAR query[] = {
|
||||||
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
'`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
|
'`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
|
||||||
'`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
|
'`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
|
||||||
MSIRECORD *row = 0;
|
MSIRECORD *row;
|
||||||
|
MSIBINARY *binary;
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
CHAR buffer[1024];
|
CHAR buffer[1024];
|
||||||
WCHAR fmt[MAX_PATH];
|
WCHAR fmt[MAX_PATH], tmpfile[MAX_PATH];
|
||||||
DWORD sz = MAX_PATH;
|
DWORD sz = MAX_PATH, write;
|
||||||
UINT r;
|
UINT r;
|
||||||
|
|
||||||
if (msi_get_property(package->db, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
|
if (msi_get_property(package->db, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
|
||||||
GetTempPathW(MAX_PATH, fmt);
|
GetTempPathW(MAX_PATH, fmt);
|
||||||
|
|
||||||
if (GetTempFileNameW(fmt, szMsi, 0, tmp_file) == 0)
|
if (!GetTempFileNameW( fmt, szMsi, 0, tmpfile ))
|
||||||
{
|
{
|
||||||
TRACE("Unable to create file\n");
|
TRACE("unable to create temp file %s (%u)\n", debugstr_w(tmpfile), GetLastError());
|
||||||
return ERROR_FUNCTION_FAILED;
|
return NULL;
|
||||||
}
|
}
|
||||||
track_tempfile(package, tmp_file);
|
|
||||||
|
|
||||||
row = MSI_QueryGetRecord(package->db, query, source);
|
row = MSI_QueryGetRecord(package->db, query, source);
|
||||||
if (!row)
|
if (!row)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return NULL;
|
||||||
|
|
||||||
/* write out the file */
|
if (!(binary = msi_alloc_zero( sizeof(MSIBINARY) )))
|
||||||
file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
|
||||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (file == INVALID_HANDLE_VALUE)
|
|
||||||
r = ERROR_FUNCTION_FAILED;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
msiobj_release( &row->hdr );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
file = CreateFileW( tmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||||
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
msiobj_release( &row->hdr );
|
||||||
|
msi_free( binary );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
DWORD write;
|
sz = sizeof(buffer);
|
||||||
sz = sizeof buffer;
|
|
||||||
r = MSI_RecordReadStream( row, 2, buffer, &sz );
|
r = MSI_RecordReadStream( row, 2, buffer, &sz );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -403,12 +411,38 @@ static UINT store_binary_to_temp(MSIPACKAGE *package, LPCWSTR source,
|
||||||
}
|
}
|
||||||
WriteFile( file, buffer, sz, &write, NULL );
|
WriteFile( file, buffer, sz, &write, NULL );
|
||||||
} while (sz == sizeof buffer);
|
} while (sz == sizeof buffer);
|
||||||
|
|
||||||
CloseHandle( file );
|
CloseHandle( file );
|
||||||
|
msiobj_release( &row->hdr );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DeleteFileW( tmpfile );
|
||||||
|
msi_free( binary );
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
msiobj_release(&row->hdr);
|
/* keep a reference to prevent the dll from being unloaded */
|
||||||
|
if (dll && !(binary->module = LoadLibraryW( tmpfile )))
|
||||||
|
{
|
||||||
|
WARN( "failed to load dll %s (%u)\n", debugstr_w( tmpfile ), GetLastError() );
|
||||||
|
}
|
||||||
|
binary->source = strdupW( source );
|
||||||
|
binary->tmpfile = strdupW( tmpfile );
|
||||||
|
list_add_tail( &package->binaries, &binary->entry );
|
||||||
|
return binary;
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
static MSIBINARY *get_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
|
||||||
|
{
|
||||||
|
MSIBINARY *binary;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( binary, &package->binaries, MSIBINARY, entry )
|
||||||
|
{
|
||||||
|
if (!strcmpW( binary->source, source ))
|
||||||
|
return binary;
|
||||||
|
}
|
||||||
|
|
||||||
|
return create_temp_binary( package, source, dll );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_running_action(MSIPACKAGE* package, HANDLE Handle,
|
static void file_running_action(MSIPACKAGE* package, HANDLE Handle,
|
||||||
|
@ -594,7 +628,7 @@ static void handle_msi_break( LPCWSTR target )
|
||||||
if( !GetEnvironmentVariableW( MsiBreak, val, MAX_PATH ))
|
if( !GetEnvironmentVariableW( MsiBreak, val, MAX_PATH ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( lstrcmpiW( val, target ))
|
if( strcmpiW( val, target ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
msg = msi_alloc( (lstrlenW(format) + 10) * sizeof(WCHAR) );
|
msg = msi_alloc( (lstrlenW(format) + 10) * sizeof(WCHAR) );
|
||||||
|
@ -615,7 +649,7 @@ static UINT get_action_info( const GUID *guid, INT *type, MSIHANDLE *handle,
|
||||||
IWineMsiRemoteCustomAction *rca = NULL;
|
IWineMsiRemoteCustomAction *rca = NULL;
|
||||||
HRESULT r;
|
HRESULT r;
|
||||||
|
|
||||||
r = DllGetClassObject( &CLSID_IWineMsiRemoteCustomAction,
|
r = DllGetClassObject( &CLSID_WineMsiRemoteCustomAction,
|
||||||
&IID_IClassFactory, (LPVOID *)&cf );
|
&IID_IClassFactory, (LPVOID *)&cf );
|
||||||
if (FAILED(r))
|
if (FAILED(r))
|
||||||
{
|
{
|
||||||
|
@ -683,8 +717,8 @@ static DWORD ACTION_CallDllFunction( const GUID *guid )
|
||||||
hModule = LoadLibraryW( dll );
|
hModule = LoadLibraryW( dll );
|
||||||
if (!hModule)
|
if (!hModule)
|
||||||
{
|
{
|
||||||
ERR("failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
|
WARN( "failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
|
||||||
return r;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc = strdupWtoA( function );
|
proc = strdupWtoA( function );
|
||||||
|
@ -875,20 +909,15 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
|
||||||
LPCWSTR target, const INT type, LPCWSTR action)
|
LPCWSTR target, const INT type, LPCWSTR action)
|
||||||
{
|
{
|
||||||
msi_custom_action_info *info;
|
msi_custom_action_info *info;
|
||||||
WCHAR tmp_file[MAX_PATH];
|
MSIBINARY *binary;
|
||||||
UINT r;
|
UINT r;
|
||||||
|
|
||||||
r = store_binary_to_temp(package, source, tmp_file);
|
if (!(binary = get_temp_binary( package, source, TRUE )))
|
||||||
if (r != ERROR_SUCCESS)
|
return ERROR_FUNCTION_FAILED;
|
||||||
return r;
|
|
||||||
|
|
||||||
TRACE("Calling function %s from %s\n",debugstr_w(target),
|
TRACE("Calling function %s from %s\n", debugstr_w(target), debugstr_w(binary->tmpfile));
|
||||||
debugstr_w(tmp_file));
|
|
||||||
|
|
||||||
if (!strchrW(tmp_file,'.'))
|
info = do_msidbCustomActionTypeDll( package, type, binary->tmpfile, target, action );
|
||||||
strcatW(tmp_file, szDot);
|
|
||||||
|
|
||||||
info = do_msidbCustomActionTypeDll( package, type, tmp_file, target, action );
|
|
||||||
|
|
||||||
r = wait_thread_handle( info );
|
r = wait_thread_handle( info );
|
||||||
release_custom_action_data( info );
|
release_custom_action_data( info );
|
||||||
|
@ -898,7 +927,6 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
|
||||||
static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
|
static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
|
||||||
LPCWSTR target, const INT type, LPCWSTR action)
|
LPCWSTR target, const INT type, LPCWSTR action)
|
||||||
{
|
{
|
||||||
WCHAR tmp_file[MAX_PATH];
|
|
||||||
STARTUPINFOW si;
|
STARTUPINFOW si;
|
||||||
PROCESS_INFORMATION info;
|
PROCESS_INFORMATION info;
|
||||||
BOOL rc;
|
BOOL rc;
|
||||||
|
@ -906,29 +934,27 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
|
||||||
WCHAR *deformated = NULL;
|
WCHAR *deformated = NULL;
|
||||||
WCHAR *cmd;
|
WCHAR *cmd;
|
||||||
static const WCHAR spc[] = {' ',0};
|
static const WCHAR spc[] = {' ',0};
|
||||||
|
MSIBINARY *binary;
|
||||||
UINT r;
|
UINT r;
|
||||||
|
|
||||||
memset(&si,0,sizeof(STARTUPINFOW));
|
memset(&si,0,sizeof(STARTUPINFOW));
|
||||||
|
|
||||||
r = store_binary_to_temp(package, source, tmp_file);
|
if (!(binary = get_temp_binary( package, source, FALSE )))
|
||||||
if (r != ERROR_SUCCESS)
|
return ERROR_FUNCTION_FAILED;
|
||||||
return r;
|
|
||||||
|
|
||||||
deformat_string(package,target,&deformated);
|
deformat_string(package,target,&deformated);
|
||||||
|
|
||||||
len = strlenW(tmp_file)+2;
|
len = strlenW( binary->tmpfile ) + 2;
|
||||||
|
|
||||||
if (deformated)
|
if (deformated)
|
||||||
len += strlenW(deformated);
|
len += strlenW(deformated);
|
||||||
|
|
||||||
cmd = msi_alloc(sizeof(WCHAR)*len);
|
cmd = msi_alloc(sizeof(WCHAR)*len);
|
||||||
|
|
||||||
strcpyW(cmd,tmp_file);
|
strcpyW( cmd, binary->tmpfile );
|
||||||
if (deformated)
|
if (deformated)
|
||||||
{
|
{
|
||||||
strcatW(cmd,spc);
|
strcatW(cmd,spc);
|
||||||
strcatW(cmd,deformated);
|
strcatW(cmd,deformated);
|
||||||
|
|
||||||
msi_free(deformated);
|
msi_free(deformated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1121,8 +1147,7 @@ static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
|
||||||
|
|
||||||
memset(&si, 0, sizeof(STARTUPINFOW));
|
memset(&si, 0, sizeof(STARTUPINFOW));
|
||||||
|
|
||||||
workingdir = resolve_folder(package, source, FALSE, FALSE, TRUE, NULL);
|
workingdir = resolve_target_folder( package, source, FALSE, TRUE, NULL );
|
||||||
|
|
||||||
if (!workingdir)
|
if (!workingdir)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
@ -1161,13 +1186,13 @@ static DWORD ACTION_CallScript( const GUID *guid )
|
||||||
{
|
{
|
||||||
msi_custom_action_info *info;
|
msi_custom_action_info *info;
|
||||||
MSIHANDLE hPackage;
|
MSIHANDLE hPackage;
|
||||||
UINT r = ERROR_FUNCTION_FAILED;
|
UINT r;
|
||||||
|
|
||||||
info = find_action_by_guid( guid );
|
info = find_action_by_guid( guid );
|
||||||
if (!info)
|
if (!info)
|
||||||
{
|
{
|
||||||
ERR("failed to find action %s\n", debugstr_guid( guid) );
|
ERR("failed to find action %s\n", debugstr_guid( guid) );
|
||||||
return r;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("function %s, script %s\n", debugstr_w( info->target ), debugstr_w( info->source ) );
|
TRACE("function %s, script %s\n", debugstr_w( info->target ), debugstr_w( info->source ) );
|
||||||
|
@ -1176,13 +1201,13 @@ static DWORD ACTION_CallScript( const GUID *guid )
|
||||||
if (hPackage)
|
if (hPackage)
|
||||||
{
|
{
|
||||||
r = call_script( hPackage, info->type, info->source, info->target, info->action );
|
r = call_script( hPackage, info->type, info->source, info->target, info->action );
|
||||||
|
TRACE("script returned %u\n", r);
|
||||||
MsiCloseHandle( hPackage );
|
MsiCloseHandle( hPackage );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ERR("failed to create handle for %p\n", info->package );
|
ERR("failed to create handle for %p\n", info->package );
|
||||||
|
|
||||||
release_custom_action_data( info );
|
release_custom_action_data( info );
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1433,13 +1458,13 @@ void ACTION_FinishCustomActions(const MSIPACKAGE* package)
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _msi_custom_remote_impl {
|
typedef struct _msi_custom_remote_impl {
|
||||||
const IWineMsiRemoteCustomActionVtbl *lpVtbl;
|
IWineMsiRemoteCustomAction IWineMsiRemoteCustomAction_iface;
|
||||||
LONG refs;
|
LONG refs;
|
||||||
} msi_custom_remote_impl;
|
} msi_custom_remote_impl;
|
||||||
|
|
||||||
static inline msi_custom_remote_impl* mcr_from_IWineMsiRemoteCustomAction( IWineMsiRemoteCustomAction* iface )
|
static inline msi_custom_remote_impl *impl_from_IWineMsiRemoteCustomAction( IWineMsiRemoteCustomAction *iface )
|
||||||
{
|
{
|
||||||
return (msi_custom_remote_impl*) iface;
|
return CONTAINING_RECORD(iface, msi_custom_remote_impl, IWineMsiRemoteCustomAction_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mcr_QueryInterface( IWineMsiRemoteCustomAction *iface,
|
static HRESULT WINAPI mcr_QueryInterface( IWineMsiRemoteCustomAction *iface,
|
||||||
|
@ -1458,14 +1483,14 @@ static HRESULT WINAPI mcr_QueryInterface( IWineMsiRemoteCustomAction *iface,
|
||||||
|
|
||||||
static ULONG WINAPI mcr_AddRef( IWineMsiRemoteCustomAction *iface )
|
static ULONG WINAPI mcr_AddRef( IWineMsiRemoteCustomAction *iface )
|
||||||
{
|
{
|
||||||
msi_custom_remote_impl* This = mcr_from_IWineMsiRemoteCustomAction( iface );
|
msi_custom_remote_impl* This = impl_from_IWineMsiRemoteCustomAction( iface );
|
||||||
|
|
||||||
return InterlockedIncrement( &This->refs );
|
return InterlockedIncrement( &This->refs );
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG WINAPI mcr_Release( IWineMsiRemoteCustomAction *iface )
|
static ULONG WINAPI mcr_Release( IWineMsiRemoteCustomAction *iface )
|
||||||
{
|
{
|
||||||
msi_custom_remote_impl* This = mcr_from_IWineMsiRemoteCustomAction( iface );
|
msi_custom_remote_impl* This = impl_from_IWineMsiRemoteCustomAction( iface );
|
||||||
ULONG r;
|
ULONG r;
|
||||||
|
|
||||||
r = InterlockedDecrement( &This->refs );
|
r = InterlockedDecrement( &This->refs );
|
||||||
|
@ -1508,7 +1533,7 @@ HRESULT create_msi_custom_remote( IUnknown *pOuter, LPVOID *ppObj )
|
||||||
if (!This)
|
if (!This)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
This->lpVtbl = &msi_custom_remote_vtbl;
|
This->IWineMsiRemoteCustomAction_iface.lpVtbl = &msi_custom_remote_vtbl;
|
||||||
This->refs = 1;
|
This->refs = 1;
|
||||||
|
|
||||||
*ppObj = This;
|
*ppObj = This;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#define NONAMELESSUNION
|
#define NONAMELESSUNION
|
||||||
|
@ -79,7 +80,7 @@ static UINT find_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !lstrcmpW( name, stat.pwcsName ) )
|
if( !strcmpW( name, stat.pwcsName ) )
|
||||||
{
|
{
|
||||||
TRACE("found %s\n", debugstr_w(name));
|
TRACE("found %s\n", debugstr_w(name));
|
||||||
*stm = stream->stm;
|
*stm = stream->stm;
|
||||||
|
@ -888,6 +889,8 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
|
|
||||||
static const WCHAR suminfo[] =
|
static const WCHAR suminfo[] =
|
||||||
{'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0};
|
{'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0};
|
||||||
|
static const WCHAR forcecodepage[] =
|
||||||
|
{'_','F','o','r','c','e','C','o','d','e','p','a','g','e',0};
|
||||||
|
|
||||||
TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
|
TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
|
||||||
|
|
||||||
|
@ -910,6 +913,13 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
msi_parse_line( &ptr, &types, &num_types );
|
msi_parse_line( &ptr, &types, &num_types );
|
||||||
msi_parse_line( &ptr, &labels, &num_labels );
|
msi_parse_line( &ptr, &labels, &num_labels );
|
||||||
|
|
||||||
|
if (num_columns == 1 && !columns[0][0] && num_labels == 1 && !labels[0][0] &&
|
||||||
|
num_types == 2 && !strcmpW( types[1], forcecodepage ))
|
||||||
|
{
|
||||||
|
r = msi_set_string_table_codepage( db->strings, atoiW( types[0] ) );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (num_columns != num_types)
|
if (num_columns != num_types)
|
||||||
{
|
{
|
||||||
r = ERROR_FUNCTION_FAILED;
|
r = ERROR_FUNCTION_FAILED;
|
||||||
|
@ -1087,13 +1097,13 @@ static UINT msi_export_row( MSIRECORD *row, void *arg )
|
||||||
return msi_export_record( arg, row, 1 );
|
return msi_export_record( arg, row, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_export_forcecodepage( HANDLE handle )
|
static UINT msi_export_forcecodepage( HANDLE handle, UINT codepage )
|
||||||
{
|
{
|
||||||
|
static const char fmt[] = "\r\n\r\n%u\t_ForceCodepage\r\n";
|
||||||
|
char data[sizeof(fmt) + 10];
|
||||||
DWORD sz;
|
DWORD sz;
|
||||||
|
|
||||||
static const char data[] = "\r\n\r\n0\t_ForceCodepage\r\n";
|
sprintf( data, fmt, codepage );
|
||||||
|
|
||||||
FIXME("Read the codepage from the strings table!\n");
|
|
||||||
|
|
||||||
sz = lstrlenA(data) + 1;
|
sz = lstrlenA(data) + 1;
|
||||||
if (!WriteFile(handle, data, sz, &sz, NULL))
|
if (!WriteFile(handle, data, sz, &sz, NULL))
|
||||||
|
@ -1136,9 +1146,10 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
if (!lstrcmpW( table, forcecodepage ))
|
if (!strcmpW( table, forcecodepage ))
|
||||||
{
|
{
|
||||||
r = msi_export_forcecodepage( handle );
|
UINT codepage = msi_get_string_table_codepage( db->strings );
|
||||||
|
r = msi_export_forcecodepage( handle, codepage );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,7 +1330,7 @@ static BOOL merge_type_match(LPCWSTR type1, LPCWSTR type2)
|
||||||
((type2[0] == 'L') || (type2[0] == 'S')))
|
((type2[0] == 'L') || (type2[0] == 'S')))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return !lstrcmpW(type1, type2);
|
return !strcmpW( type1, type2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
|
static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
|
||||||
|
@ -1341,8 +1352,7 @@ static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
|
||||||
if (!MSI_RecordGetString(mergerec, i))
|
if (!MSI_RecordGetString(mergerec, i))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (lstrcmpW(MSI_RecordGetString(dbrec, i),
|
if (strcmpW( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
|
||||||
MSI_RecordGetString(mergerec, i)))
|
|
||||||
{
|
{
|
||||||
r = ERROR_DATATYPE_MISMATCH;
|
r = ERROR_DATATYPE_MISMATCH;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1405,8 +1415,7 @@ static UINT merge_verify_primary_keys(MSIDATABASE *db, MSIDATABASE *mergedb,
|
||||||
|
|
||||||
for (i = 1; i <= count; i++)
|
for (i = 1; i <= count; i++)
|
||||||
{
|
{
|
||||||
if (lstrcmpW(MSI_RecordGetString(dbrec, i),
|
if (strcmpW( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
|
||||||
MSI_RecordGetString(mergerec, i)))
|
|
||||||
{
|
{
|
||||||
r = ERROR_DATATYPE_MISMATCH;
|
r = ERROR_DATATYPE_MISMATCH;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1434,7 +1443,7 @@ static LPWSTR get_key_value(MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
str = msi_dup_record_field(colnames, ++i);
|
str = msi_dup_record_field(colnames, ++i);
|
||||||
cmp = lstrcmpW(key, str);
|
cmp = strcmpW( key, str );
|
||||||
msi_free(str);
|
msi_free(str);
|
||||||
} while (cmp);
|
} while (cmp);
|
||||||
|
|
||||||
|
@ -2029,14 +2038,14 @@ MSIDBSTATE WINAPI MsiGetDatabaseState( MSIHANDLE handle )
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _msi_remote_database_impl {
|
typedef struct _msi_remote_database_impl {
|
||||||
const IWineMsiRemoteDatabaseVtbl *lpVtbl;
|
IWineMsiRemoteDatabase IWineMsiRemoteDatabase_iface;
|
||||||
MSIHANDLE database;
|
MSIHANDLE database;
|
||||||
LONG refs;
|
LONG refs;
|
||||||
} msi_remote_database_impl;
|
} msi_remote_database_impl;
|
||||||
|
|
||||||
static inline msi_remote_database_impl* mrd_from_IWineMsiRemoteDatabase( IWineMsiRemoteDatabase* iface )
|
static inline msi_remote_database_impl *impl_from_IWineMsiRemoteDatabase( IWineMsiRemoteDatabase *iface )
|
||||||
{
|
{
|
||||||
return (msi_remote_database_impl *)iface;
|
return CONTAINING_RECORD(iface, msi_remote_database_impl, IWineMsiRemoteDatabase_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrd_QueryInterface( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_QueryInterface( IWineMsiRemoteDatabase *iface,
|
||||||
|
@ -2055,14 +2064,14 @@ static HRESULT WINAPI mrd_QueryInterface( IWineMsiRemoteDatabase *iface,
|
||||||
|
|
||||||
static ULONG WINAPI mrd_AddRef( IWineMsiRemoteDatabase *iface )
|
static ULONG WINAPI mrd_AddRef( IWineMsiRemoteDatabase *iface )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl* This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl* This = impl_from_IWineMsiRemoteDatabase( iface );
|
||||||
|
|
||||||
return InterlockedIncrement( &This->refs );
|
return InterlockedIncrement( &This->refs );
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface )
|
static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl* This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl* This = impl_from_IWineMsiRemoteDatabase( iface );
|
||||||
ULONG r;
|
ULONG r;
|
||||||
|
|
||||||
r = InterlockedDecrement( &This->refs );
|
r = InterlockedDecrement( &This->refs );
|
||||||
|
@ -2077,7 +2086,7 @@ static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface )
|
||||||
static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
||||||
LPCWSTR table, MSICONDITION *persistent )
|
LPCWSTR table, MSICONDITION *persistent )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = impl_from_IWineMsiRemoteDatabase( iface );
|
||||||
*persistent = MsiDatabaseIsTablePersistentW(This->database, table);
|
*persistent = MsiDatabaseIsTablePersistentW(This->database, table);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -2085,7 +2094,7 @@ static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
||||||
static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
||||||
LPCWSTR table, MSIHANDLE *keys )
|
LPCWSTR table, MSIHANDLE *keys )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = impl_from_IWineMsiRemoteDatabase( iface );
|
||||||
UINT r = MsiDatabaseGetPrimaryKeysW(This->database, table, keys);
|
UINT r = MsiDatabaseGetPrimaryKeysW(This->database, table, keys);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
@ -2093,7 +2102,7 @@ static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
||||||
static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
||||||
UINT updatecount, MSIHANDLE *suminfo )
|
UINT updatecount, MSIHANDLE *suminfo )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = impl_from_IWineMsiRemoteDatabase( iface );
|
||||||
UINT r = MsiGetSummaryInformationW(This->database, NULL, updatecount, suminfo);
|
UINT r = MsiGetSummaryInformationW(This->database, NULL, updatecount, suminfo);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
@ -2101,14 +2110,14 @@ static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
||||||
static HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
|
static HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
|
||||||
LPCWSTR query, MSIHANDLE *view )
|
LPCWSTR query, MSIHANDLE *view )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl *This = impl_from_IWineMsiRemoteDatabase( iface );
|
||||||
UINT r = MsiDatabaseOpenViewW(This->database, query, view);
|
UINT r = MsiDatabaseOpenViewW(This->database, query, view);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrd_SetMsiHandle( IWineMsiRemoteDatabase *iface, MSIHANDLE handle )
|
static HRESULT WINAPI mrd_SetMsiHandle( IWineMsiRemoteDatabase *iface, MSIHANDLE handle )
|
||||||
{
|
{
|
||||||
msi_remote_database_impl* This = mrd_from_IWineMsiRemoteDatabase( iface );
|
msi_remote_database_impl* This = impl_from_IWineMsiRemoteDatabase( iface );
|
||||||
This->database = handle;
|
This->database = handle;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -2133,7 +2142,7 @@ HRESULT create_msi_remote_database( IUnknown *pOuter, LPVOID *ppObj )
|
||||||
if (!This)
|
if (!This)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
This->lpVtbl = &msi_remote_database_vtbl;
|
This->IWineMsiRemoteDatabase_iface.lpVtbl = &msi_remote_database_vtbl;
|
||||||
This->database = 0;
|
This->database = 0;
|
||||||
This->refs = 1;
|
This->refs = 1;
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ struct msi_control_tag
|
||||||
|
|
||||||
typedef struct msi_font_tag
|
typedef struct msi_font_tag
|
||||||
{
|
{
|
||||||
struct msi_font_tag *next;
|
struct list entry;
|
||||||
HFONT hfont;
|
HFONT hfont;
|
||||||
COLORREF color;
|
COLORREF color;
|
||||||
WCHAR name[1];
|
WCHAR name[1];
|
||||||
|
@ -90,7 +90,7 @@ struct msi_dialog_tag
|
||||||
SIZE size;
|
SIZE size;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
LPWSTR default_font;
|
LPWSTR default_font;
|
||||||
msi_font *font_list;
|
struct list fonts;
|
||||||
struct list controls;
|
struct list controls;
|
||||||
HWND hWndFocus;
|
HWND hWndFocus;
|
||||||
LPWSTR control_default;
|
LPWSTR control_default;
|
||||||
|
@ -310,8 +310,7 @@ static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param )
|
||||||
name = MSI_RecordGetString( rec, 1 );
|
name = MSI_RecordGetString( rec, 1 );
|
||||||
font = msi_alloc( sizeof *font + strlenW( name )*sizeof (WCHAR) );
|
font = msi_alloc( sizeof *font + strlenW( name )*sizeof (WCHAR) );
|
||||||
strcpyW( font->name, name );
|
strcpyW( font->name, name );
|
||||||
font->next = dialog->font_list;
|
list_add_head( &dialog->fonts, &font->entry );
|
||||||
dialog->font_list = font;
|
|
||||||
|
|
||||||
font->color = MSI_RecordGetInteger( rec, 4 );
|
font->color = MSI_RecordGetInteger( rec, 4 );
|
||||||
|
|
||||||
|
@ -346,9 +345,9 @@ static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param )
|
||||||
|
|
||||||
static msi_font *msi_dialog_find_font( msi_dialog *dialog, LPCWSTR name )
|
static msi_font *msi_dialog_find_font( msi_dialog *dialog, LPCWSTR name )
|
||||||
{
|
{
|
||||||
msi_font *font;
|
msi_font *font = NULL;
|
||||||
|
|
||||||
for( font = dialog->font_list; font; font = font->next )
|
LIST_FOR_EACH_ENTRY( font, &dialog->fonts, msi_font, entry )
|
||||||
if( !strcmpW( font->name, name ) ) /* FIXME: case sensitive? */
|
if( !strcmpW( font->name, name ) ) /* FIXME: case sensitive? */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -578,7 +577,7 @@ static void msi_dialog_update_controls( msi_dialog *dialog, LPCWSTR property )
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
|
LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
|
||||||
{
|
{
|
||||||
if ( !lstrcmpW( control->property, property ) && control->update )
|
if ( control->property && !strcmpW( control->property, property ) && control->update )
|
||||||
control->update( dialog, control );
|
control->update( dialog, control );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -601,7 +600,7 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
|
||||||
ctrl = msi_dialog_find_control( dialog, control );
|
ctrl = msi_dialog_find_control( dialog, control );
|
||||||
if (!ctrl)
|
if (!ctrl)
|
||||||
return;
|
return;
|
||||||
if( !lstrcmpW(attribute, szText) )
|
if( !strcmpW( attribute, szText ) )
|
||||||
{
|
{
|
||||||
font_text = MSI_RecordGetString( rec , 1 );
|
font_text = MSI_RecordGetString( rec , 1 );
|
||||||
font = msi_dialog_get_style( font_text, &text );
|
font = msi_dialog_get_style( font_text, &text );
|
||||||
|
@ -610,7 +609,7 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
|
||||||
msi_free( font );
|
msi_free( font );
|
||||||
msi_dialog_check_messages( NULL );
|
msi_dialog_check_messages( NULL );
|
||||||
}
|
}
|
||||||
else if( !lstrcmpW(attribute, szProgress) )
|
else if( !strcmpW( attribute, szProgress ) )
|
||||||
{
|
{
|
||||||
DWORD func, val;
|
DWORD func, val;
|
||||||
|
|
||||||
|
@ -640,12 +639,12 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( !lstrcmpW(attribute, szProperty) )
|
else if ( !strcmpW( attribute, szProperty ) )
|
||||||
{
|
{
|
||||||
MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
|
MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
|
||||||
msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory );
|
msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory );
|
||||||
}
|
}
|
||||||
else if ( !lstrcmpW(attribute, szSelectionPath) )
|
else if ( !strcmpW( attribute, szSelectionPath ) )
|
||||||
{
|
{
|
||||||
LPWSTR prop = msi_dialog_dup_property( dialog, ctrl->property, TRUE );
|
LPWSTR prop = msi_dialog_dup_property( dialog, ctrl->property, TRUE );
|
||||||
LPWSTR path;
|
LPWSTR path;
|
||||||
|
@ -1368,7 +1367,7 @@ static void msi_dialog_combobox_update( msi_dialog *dialog,
|
||||||
for (j = 0; j < info->num_items; j++)
|
for (j = 0; j < info->num_items; j++)
|
||||||
{
|
{
|
||||||
tmp = (LPWSTR) SendMessageW( control->hwnd, CB_GETITEMDATA, j, 0 );
|
tmp = (LPWSTR) SendMessageW( control->hwnd, CB_GETITEMDATA, j, 0 );
|
||||||
if (!lstrcmpW( value, tmp ))
|
if (!strcmpW( value, tmp ))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1743,7 +1742,7 @@ static UINT msi_dialog_maskedit_control( msi_dialog *dialog, MSIRECORD *rec )
|
||||||
font = msi_dialog_get_style( font_mask, &mask );
|
font = msi_dialog_get_style( font_mask, &mask );
|
||||||
if( !mask )
|
if( !mask )
|
||||||
{
|
{
|
||||||
ERR("mask template is empty\n");
|
WARN("mask template is empty\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1988,7 +1987,7 @@ static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param )
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
control->handler = msi_dialog_radiogroup_handler;
|
control->handler = msi_dialog_radiogroup_handler;
|
||||||
|
|
||||||
if (!lstrcmpW(control->name, group->propval))
|
if (group->propval && !strcmpW( control->name, group->propval ))
|
||||||
SendMessageW(control->hwnd, BM_SETCHECK, BST_CHECKED, 0);
|
SendMessageW(control->hwnd, BM_SETCHECK, BST_CHECKED, 0);
|
||||||
|
|
||||||
prop = MSI_RecordGetString( rec, 1 );
|
prop = MSI_RecordGetString( rec, 1 );
|
||||||
|
@ -2126,9 +2125,9 @@ static void
|
||||||
msi_seltree_update_feature_installstate( HWND hwnd, HTREEITEM hItem,
|
msi_seltree_update_feature_installstate( HWND hwnd, HTREEITEM hItem,
|
||||||
MSIPACKAGE *package, MSIFEATURE *feature, INSTALLSTATE state )
|
MSIPACKAGE *package, MSIFEATURE *feature, INSTALLSTATE state )
|
||||||
{
|
{
|
||||||
msi_feature_set_state( package, feature, state );
|
feature->ActionRequest = state;
|
||||||
msi_seltree_sync_item_state( hwnd, feature, hItem );
|
msi_seltree_sync_item_state( hwnd, feature, hItem );
|
||||||
ACTION_UpdateComponentStates( package, feature->Feature );
|
ACTION_UpdateComponentStates( package, feature );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2258,7 +2257,11 @@ msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
{
|
{
|
||||||
if ( lstrcmpW( parent, feature->Feature_Parent ) )
|
if ( parent && feature->Feature_Parent && strcmpW( parent, feature->Feature_Parent ))
|
||||||
|
continue;
|
||||||
|
else if ( parent && !feature->Feature_Parent )
|
||||||
|
continue;
|
||||||
|
else if ( !parent && feature->Feature_Parent )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( !feature->Title )
|
if ( !feature->Title )
|
||||||
|
@ -2373,14 +2376,19 @@ static UINT msi_dialog_seltree_handler( msi_dialog *dialog,
|
||||||
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionDescription, rec );
|
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionDescription, rec );
|
||||||
|
|
||||||
dir = MSI_RecordGetString( row, 7 );
|
dir = MSI_RecordGetString( row, 7 );
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
folder = get_loaded_folder( dialog->package, dir );
|
folder = get_loaded_folder( dialog->package, dir );
|
||||||
if (!folder)
|
if (!folder)
|
||||||
{
|
{
|
||||||
r = ERROR_FUNCTION_FAILED;
|
r = ERROR_FUNCTION_FAILED;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
MSI_RecordSetStringW( rec, 1, folder->ResolvedTarget );
|
MSI_RecordSetStringW( rec, 1, folder->ResolvedTarget );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MSI_RecordSetStringW( rec, 1, NULL );
|
||||||
|
|
||||||
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionPath, rec );
|
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionPath, rec );
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -2682,7 +2690,7 @@ static void msi_dialog_update_directory_list( msi_dialog *dialog, msi_control *c
|
||||||
if ( wfd.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY )
|
if ( wfd.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( !lstrcmpW( wfd.cFileName, szDot ) || !lstrcmpW( wfd.cFileName, szDotDot ) )
|
if ( !strcmpW( wfd.cFileName, szDot ) || !strcmpW( wfd.cFileName, szDotDot ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
item.mask = LVIF_TEXT;
|
item.mask = LVIF_TEXT;
|
||||||
|
@ -2846,7 +2854,7 @@ static void msi_dialog_vcl_add_columns( msi_dialog *dialog, msi_control *control
|
||||||
begin += end - begin + 1;
|
begin += end - begin + 1;
|
||||||
|
|
||||||
/* empty braces or '0' hides the column */
|
/* empty braces or '0' hides the column */
|
||||||
if ( !num[0] || !lstrcmpW( num, szZero ) )
|
if ( !num[0] || !strcmpW( num, szZero ) )
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
msi_free( num );
|
msi_free( num );
|
||||||
|
@ -3151,7 +3159,7 @@ static UINT msi_dialog_set_control_condition( MSIRECORD *rec, LPVOID param )
|
||||||
TRACE("%s control %s\n", debugstr_w(action), debugstr_w(name));
|
TRACE("%s control %s\n", debugstr_w(action), debugstr_w(name));
|
||||||
|
|
||||||
/* FIXME: case sensitive? */
|
/* FIXME: case sensitive? */
|
||||||
if(!lstrcmpW(action, szHide))
|
if (!strcmpW( action, szHide ))
|
||||||
ShowWindow(control->hwnd, SW_HIDE);
|
ShowWindow(control->hwnd, SW_HIDE);
|
||||||
else if (!strcmpW( action, szShow ))
|
else if (!strcmpW( action, szShow ))
|
||||||
ShowWindow(control->hwnd, SW_SHOW);
|
ShowWindow(control->hwnd, SW_SHOW);
|
||||||
|
@ -3844,6 +3852,7 @@ msi_dialog *msi_dialog_create( MSIPACKAGE* package,
|
||||||
dialog->event_handler = event_handler;
|
dialog->event_handler = event_handler;
|
||||||
dialog->finished = 0;
|
dialog->finished = 0;
|
||||||
list_init( &dialog->controls );
|
list_init( &dialog->controls );
|
||||||
|
list_init( &dialog->fonts );
|
||||||
|
|
||||||
/* verify that the dialog exists */
|
/* verify that the dialog exists */
|
||||||
rec = msi_get_dialog_record( dialog );
|
rec = msi_get_dialog_record( dialog );
|
||||||
|
@ -3960,6 +3969,8 @@ void msi_dialog_do_preview( msi_dialog *dialog )
|
||||||
|
|
||||||
void msi_dialog_destroy( msi_dialog *dialog )
|
void msi_dialog_destroy( msi_dialog *dialog )
|
||||||
{
|
{
|
||||||
|
msi_font *font, *next;
|
||||||
|
|
||||||
if( uiThreadId != GetCurrentThreadId() )
|
if( uiThreadId != GetCurrentThreadId() )
|
||||||
{
|
{
|
||||||
SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_DESTROY, 0, (LPARAM) dialog );
|
SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_DESTROY, 0, (LPARAM) dialog );
|
||||||
|
@ -3986,12 +3997,11 @@ void msi_dialog_destroy( msi_dialog *dialog )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* destroy the list of fonts */
|
/* destroy the list of fonts */
|
||||||
while( dialog->font_list )
|
LIST_FOR_EACH_ENTRY_SAFE( font, next, &dialog->fonts, msi_font, entry )
|
||||||
{
|
{
|
||||||
msi_font *t = dialog->font_list;
|
list_remove( &font->entry );
|
||||||
dialog->font_list = t->next;
|
DeleteObject( font->hfont );
|
||||||
DeleteObject( t->hfont );
|
msi_free( font );
|
||||||
msi_free( t );
|
|
||||||
}
|
}
|
||||||
msi_free( dialog->default_font );
|
msi_free( dialog->default_font );
|
||||||
|
|
||||||
|
@ -4022,11 +4032,11 @@ static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event,
|
||||||
'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
|
'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( lstrcmpW( event, end_dialog ) )
|
if ( strcmpW( event, end_dialog ) )
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
if ( !lstrcmpW( argument, error_abort ) || !lstrcmpW( argument, error_cancel ) ||
|
if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) ||
|
||||||
!lstrcmpW( argument, error_no ) )
|
!strcmpW( argument, error_no ) )
|
||||||
{
|
{
|
||||||
msi_set_property( package->db, result_prop, error_abort );
|
msi_set_property( package->db, result_prop, error_abort );
|
||||||
}
|
}
|
||||||
|
@ -4108,7 +4118,7 @@ UINT msi_spawn_error_dialog( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR er
|
||||||
if ( r != ERROR_SUCCESS)
|
if ( r != ERROR_SUCCESS)
|
||||||
r = ERROR_SUCCESS;
|
r = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ( !lstrcmpW( result, error_abort ) )
|
if ( !strcmpW( result, error_abort ) )
|
||||||
r = ERROR_FUNCTION_FAILED;
|
r = ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
|
@ -90,22 +90,18 @@ static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name, msi_dialog *pare
|
||||||
static UINT ControlEvent_EndDialog(MSIPACKAGE* package, LPCWSTR argument,
|
static UINT ControlEvent_EndDialog(MSIPACKAGE* package, LPCWSTR argument,
|
||||||
msi_dialog* dialog)
|
msi_dialog* dialog)
|
||||||
{
|
{
|
||||||
static const WCHAR szExit[] = {
|
static const WCHAR szExit[] = {'E','x','i','t',0};
|
||||||
'E','x','i','t',0};
|
static const WCHAR szRetry[] = {'R','e','t','r','y',0};
|
||||||
static const WCHAR szRetry[] = {
|
static const WCHAR szIgnore[] = {'I','g','n','o','r','e',0};
|
||||||
'R','e','t','r','y',0};
|
static const WCHAR szReturn[] = {'R','e','t','u','r','n',0};
|
||||||
static const WCHAR szIgnore[] = {
|
|
||||||
'I','g','n','o','r','e',0};
|
|
||||||
static const WCHAR szReturn[] = {
|
|
||||||
'R','e','t','u','r','n',0};
|
|
||||||
|
|
||||||
if (lstrcmpW(argument,szExit)==0)
|
if (!strcmpW( argument, szExit ))
|
||||||
package->CurrentInstallState = ERROR_INSTALL_USEREXIT;
|
package->CurrentInstallState = ERROR_INSTALL_USEREXIT;
|
||||||
else if (lstrcmpW(argument, szRetry) == 0)
|
else if (!strcmpW( argument, szRetry ))
|
||||||
package->CurrentInstallState = ERROR_INSTALL_SUSPEND;
|
package->CurrentInstallState = ERROR_INSTALL_SUSPEND;
|
||||||
else if (lstrcmpW(argument, szIgnore) == 0)
|
else if (!strcmpW( argument, szIgnore ))
|
||||||
package->CurrentInstallState = ERROR_SUCCESS;
|
package->CurrentInstallState = ERROR_SUCCESS;
|
||||||
else if (lstrcmpW(argument, szReturn) == 0)
|
else if (!strcmpW( argument, szReturn ))
|
||||||
{
|
{
|
||||||
msi_dialog *parent = msi_dialog_get_parent(dialog);
|
msi_dialog *parent = msi_dialog_get_parent(dialog);
|
||||||
msi_free(package->next_dialog);
|
msi_free(package->next_dialog);
|
||||||
|
@ -167,58 +163,50 @@ static UINT ControlEvent_DoAction(MSIPACKAGE* package, LPCWSTR argument,
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,
|
static UINT ControlEvent_AddLocal( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog )
|
||||||
msi_dialog* dialog)
|
|
||||||
{
|
{
|
||||||
MSIFEATURE *feature = NULL;
|
MSIFEATURE *feature;
|
||||||
|
|
||||||
if (lstrcmpW(szAll,argument))
|
|
||||||
{
|
|
||||||
MSI_SetFeatureStateW(package,argument,INSTALLSTATE_LOCAL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
msi_feature_set_state(package, feature, INSTALLSTATE_LOCAL);
|
{
|
||||||
|
if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
|
||||||
ACTION_UpdateComponentStates(package,argument);
|
{
|
||||||
|
if (feature->ActionRequest != INSTALLSTATE_LOCAL)
|
||||||
|
msi_set_property( package->db, szPreselected, szOne );
|
||||||
|
MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_LOCAL );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument,
|
static UINT ControlEvent_Remove( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog )
|
||||||
msi_dialog* dialog)
|
|
||||||
{
|
{
|
||||||
MSIFEATURE *feature = NULL;
|
MSIFEATURE *feature;
|
||||||
|
|
||||||
if (lstrcmpW(szAll,argument))
|
|
||||||
{
|
|
||||||
MSI_SetFeatureStateW(package,argument,INSTALLSTATE_ABSENT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
msi_feature_set_state(package, feature, INSTALLSTATE_ABSENT);
|
{
|
||||||
|
if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
|
||||||
ACTION_UpdateComponentStates(package,argument);
|
{
|
||||||
|
if (feature->ActionRequest != INSTALLSTATE_ABSENT)
|
||||||
|
msi_set_property( package->db, szPreselected, szOne );
|
||||||
|
MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_ABSENT );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument,
|
static UINT ControlEvent_AddSource( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog )
|
||||||
msi_dialog* dialog)
|
|
||||||
{
|
{
|
||||||
MSIFEATURE *feature = NULL;
|
MSIFEATURE *feature;
|
||||||
|
|
||||||
if (lstrcmpW(szAll,argument))
|
|
||||||
{
|
|
||||||
MSI_SetFeatureStateW(package,argument,INSTALLSTATE_SOURCE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
msi_feature_set_state(package, feature, INSTALLSTATE_SOURCE);
|
{
|
||||||
ACTION_UpdateComponentStates(package,argument);
|
if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
|
||||||
|
{
|
||||||
|
if (feature->ActionRequest != INSTALLSTATE_SOURCE)
|
||||||
|
msi_set_property( package->db, szPreselected, szOne );
|
||||||
|
MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_SOURCE );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -284,10 +272,9 @@ VOID ControlEvent_FireSubscribedEvent( MSIPACKAGE *package, LPCWSTR event,
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry )
|
LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpiW(sub->event, event))
|
if (strcmpiW( sub->event, event ))
|
||||||
continue;
|
continue;
|
||||||
msi_dialog_handle_event( sub->dialog, sub->control,
|
msi_dialog_handle_event( sub->dialog, sub->control, sub->attribute, rec );
|
||||||
sub->attribute, rec );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +287,7 @@ VOID ControlEvent_CleanupDialogSubscriptions(MSIPACKAGE *package, LPWSTR dialog)
|
||||||
{
|
{
|
||||||
sub = LIST_ENTRY( i, struct subscriber, entry );
|
sub = LIST_ENTRY( i, struct subscriber, entry );
|
||||||
|
|
||||||
if ( lstrcmpW( msi_dialog_get_name( sub->dialog ), dialog ))
|
if (strcmpW( msi_dialog_get_name( sub->dialog ), dialog ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
list_remove( &sub->entry );
|
list_remove( &sub->entry );
|
||||||
|
@ -441,7 +428,7 @@ UINT ControlEvent_HandleControlEvent(MSIPACKAGE *package, LPCWSTR event,
|
||||||
while( Events[i].event != NULL)
|
while( Events[i].event != NULL)
|
||||||
{
|
{
|
||||||
LPWSTR wevent = strdupAtoW(Events[i].event);
|
LPWSTR wevent = strdupAtoW(Events[i].event);
|
||||||
if (lstrcmpW(wevent,event)==0)
|
if (!strcmpW( wevent, event ))
|
||||||
{
|
{
|
||||||
msi_free(wevent);
|
msi_free(wevent);
|
||||||
rc = Events[i].handler(package,argument,dialog);
|
rc = Events[i].handler(package,argument,dialog);
|
||||||
|
|
|
@ -60,21 +60,98 @@ static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *ac
|
||||||
ui_progress( package, 2, f->FileSize, 0, 0 );
|
ui_progress( package, 2, f->FileSize, 0, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static msi_file_state calculate_install_state( MSIFILE *file )
|
||||||
|
{
|
||||||
|
MSICOMPONENT *comp = file->Component;
|
||||||
|
VS_FIXEDFILEINFO *file_version;
|
||||||
|
WCHAR *font_version;
|
||||||
|
msi_file_state state;
|
||||||
|
DWORD file_size;
|
||||||
|
|
||||||
|
if (comp->ActionRequest != INSTALLSTATE_LOCAL || !comp->Enabled ||
|
||||||
|
(comp->assembly && comp->assembly->installed))
|
||||||
|
{
|
||||||
|
TRACE("file %s is not scheduled for install\n", debugstr_w(file->File));
|
||||||
|
return msifs_skipped;
|
||||||
|
}
|
||||||
|
if ((comp->assembly && !comp->assembly->application && !comp->assembly->installed) ||
|
||||||
|
GetFileAttributesW( file->TargetPath ) == INVALID_FILE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
TRACE("file %s is missing\n", debugstr_w(file->File));
|
||||||
|
return msifs_missing;
|
||||||
|
}
|
||||||
|
if (file->Version)
|
||||||
|
{
|
||||||
|
if ((file_version = msi_get_disk_file_version( file->TargetPath )))
|
||||||
|
{
|
||||||
|
TRACE("new %s old %u.%u.%u.%u\n", debugstr_w(file->Version),
|
||||||
|
HIWORD(file_version->dwFileVersionMS),
|
||||||
|
LOWORD(file_version->dwFileVersionMS),
|
||||||
|
HIWORD(file_version->dwFileVersionLS),
|
||||||
|
LOWORD(file_version->dwFileVersionLS));
|
||||||
|
|
||||||
|
if (msi_compare_file_versions( file_version, file->Version ) < 0)
|
||||||
|
state = msifs_overwrite;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("destination file version equal or greater, not overwriting\n");
|
||||||
|
state = msifs_present;
|
||||||
|
}
|
||||||
|
msi_free( file_version );
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
else if ((font_version = font_version_from_file( file->TargetPath )))
|
||||||
|
{
|
||||||
|
TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(font_version));
|
||||||
|
|
||||||
|
if (msi_compare_font_versions( font_version, file->Version ) < 0)
|
||||||
|
state = msifs_overwrite;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("destination file version equal or greater, not overwriting\n");
|
||||||
|
state = msifs_present;
|
||||||
|
}
|
||||||
|
msi_free( font_version );
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((file_size = msi_get_disk_file_size( file->TargetPath )) != file->FileSize)
|
||||||
|
{
|
||||||
|
return msifs_overwrite;
|
||||||
|
}
|
||||||
|
if (file->hash.dwFileHashInfoSize)
|
||||||
|
{
|
||||||
|
if (msi_file_hash_matches( file ))
|
||||||
|
{
|
||||||
|
TRACE("file hashes match, not overwriting\n");
|
||||||
|
return msifs_hashmatch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("file hashes do not match, overwriting\n");
|
||||||
|
return msifs_overwrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* assume present */
|
||||||
|
return msifs_present;
|
||||||
|
}
|
||||||
|
|
||||||
static void schedule_install_files(MSIPACKAGE *package)
|
static void schedule_install_files(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
MSIFILE *file;
|
MSIFILE *file;
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(file, &package->files, MSIFILE, entry)
|
LIST_FOR_EACH_ENTRY(file, &package->files, MSIFILE, entry)
|
||||||
{
|
{
|
||||||
if (file->Component->ActionRequest != INSTALLSTATE_LOCAL || !file->Component->Enabled)
|
MSICOMPONENT *comp = file->Component;
|
||||||
{
|
|
||||||
TRACE("File %s is not scheduled for install\n", debugstr_w(file->File));
|
|
||||||
|
|
||||||
ui_progress(package,2,file->FileSize,0,0);
|
file->state = calculate_install_state( file );
|
||||||
|
if (file->state == msifs_overwrite && (comp->Attributes & msidbComponentAttributesNeverOverwrite))
|
||||||
|
{
|
||||||
|
TRACE("not overwriting %s\n", debugstr_w(file->TargetPath));
|
||||||
file->state = msifs_skipped;
|
file->state = msifs_skipped;
|
||||||
}
|
}
|
||||||
else
|
comp->Action = INSTALLSTATE_LOCAL;
|
||||||
file->Component->Action = INSTALLSTATE_LOCAL;
|
ui_progress( package, 2, file->FileSize, 0, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +231,7 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
|
||||||
MSIFOLDER *folder;
|
MSIFOLDER *folder;
|
||||||
WCHAR *install_path;
|
WCHAR *install_path;
|
||||||
|
|
||||||
install_path = resolve_folder( package, dir, FALSE, FALSE, TRUE, &folder );
|
install_path = resolve_target_folder( package, dir, FALSE, TRUE, &folder );
|
||||||
if (!install_path)
|
if (!install_path)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
@ -178,7 +255,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
||||||
f = get_loaded_file(package, file);
|
f = get_loaded_file(package, file);
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
WARN("unknown file in cabinet (%s)\n", debugstr_w(file));
|
TRACE("unknown file in cabinet (%s)\n", debugstr_w(file));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,8 +263,10 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
msi_file_update_ui(package, f, szInstallFiles);
|
msi_file_update_ui(package, f, szInstallFiles);
|
||||||
|
if (!f->Component->assembly || f->Component->assembly->application)
|
||||||
|
{
|
||||||
msi_create_directory(package, f->Component->Directory);
|
msi_create_directory(package, f->Component->Directory);
|
||||||
|
}
|
||||||
*path = strdupW(f->TargetPath);
|
*path = strdupW(f->TargetPath);
|
||||||
*attrs = f->Attributes;
|
*attrs = f->Attributes;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +289,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
||||||
UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
MSIMEDIAINFO *mi;
|
MSIMEDIAINFO *mi;
|
||||||
|
MSICOMPONENT *comp;
|
||||||
UINT rc = ERROR_SUCCESS;
|
UINT rc = ERROR_SUCCESS;
|
||||||
MSIFILE *file;
|
MSIFILE *file;
|
||||||
|
|
||||||
|
@ -222,6 +302,20 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||||
{
|
{
|
||||||
|
rc = msi_load_media_info( package, file, mi );
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc);
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
if (!file->Component->Enabled) continue;
|
||||||
|
|
||||||
|
if (file->state != msifs_hashmatch && (rc = ready_media( package, file, mi )))
|
||||||
|
{
|
||||||
|
ERR("Failed to ready media for %s\n", debugstr_w(file->File));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (file->state != msifs_missing && !mi->is_continuous && file->state != msifs_overwrite)
|
if (file->state != msifs_missing && !mi->is_continuous && file->state != msifs_overwrite)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -230,13 +324,6 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
MSICABDATA data;
|
MSICABDATA data;
|
||||||
|
|
||||||
rc = ready_media(package, file, mi);
|
|
||||||
if (rc != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
ERR("Failed to ready media for %s\n", debugstr_w(file->File));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.mi = mi;
|
data.mi = mi;
|
||||||
data.package = package;
|
data.package = package;
|
||||||
data.cb = installfiles_cb;
|
data.cb = installfiles_cb;
|
||||||
|
@ -247,7 +334,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
|
ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
|
||||||
rc = ERROR_INSTALL_FAILURE;
|
rc = ERROR_INSTALL_FAILURE;
|
||||||
break;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,12 +342,13 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
LPWSTR source = resolve_file_source(package, file);
|
LPWSTR source = resolve_file_source(package, file);
|
||||||
|
|
||||||
TRACE("file paths %s to %s\n", debugstr_w(source),
|
TRACE("copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
|
||||||
debugstr_w(file->TargetPath));
|
|
||||||
|
|
||||||
msi_file_update_ui(package, file, szInstallFiles);
|
msi_file_update_ui(package, file, szInstallFiles);
|
||||||
|
if (!file->Component->assembly || file->Component->assembly->application)
|
||||||
|
{
|
||||||
msi_create_directory(package, file->Component->Directory);
|
msi_create_directory(package, file->Component->Directory);
|
||||||
|
}
|
||||||
rc = copy_install_file(package, file, source);
|
rc = copy_install_file(package, file, source);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -268,19 +356,33 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
debugstr_w(file->TargetPath), rc);
|
debugstr_w(file->TargetPath), rc);
|
||||||
rc = ERROR_INSTALL_FAILURE;
|
rc = ERROR_INSTALL_FAILURE;
|
||||||
msi_free(source);
|
msi_free(source);
|
||||||
break;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
msi_free(source);
|
msi_free(source);
|
||||||
}
|
}
|
||||||
else if (file->state != msifs_installed)
|
else if (file->state != msifs_installed)
|
||||||
{
|
{
|
||||||
ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->TargetPath));
|
ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->TargetPath));
|
||||||
rc = ERROR_INSTALL_FAILURE;
|
rc = ERROR_INSTALL_FAILURE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
|
||||||
|
{
|
||||||
|
if (comp->ActionRequest == INSTALLSTATE_LOCAL && comp->Enabled &&
|
||||||
|
comp->assembly && !comp->assembly->installed)
|
||||||
|
{
|
||||||
|
rc = install_assembly( package, comp );
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Failed to install assembly\n");
|
||||||
|
rc = ERROR_INSTALL_FAILURE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
msi_free_media_info(mi);
|
msi_free_media_info(mi);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -406,7 +508,7 @@ static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(file, &files->entry, FILE_LIST, entry)
|
LIST_FOR_EACH_ENTRY(file, &files->entry, FILE_LIST, entry)
|
||||||
{
|
{
|
||||||
if (lstrcmpW(source, file->source) < 0)
|
if (strcmpW( source, file->source ) < 0)
|
||||||
{
|
{
|
||||||
list_add_before(&file->entry, &new->entry);
|
list_add_before(&file->entry, &new->entry);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -663,7 +765,7 @@ static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const
|
||||||
{
|
{
|
||||||
const WCHAR *dst_key = MSI_RecordGetString( row, 5 );
|
const WCHAR *dst_key = MSI_RecordGetString( row, 5 );
|
||||||
|
|
||||||
dst_path = resolve_folder( package, dst_key, FALSE, FALSE, TRUE, NULL );
|
dst_path = resolve_target_folder( package, dst_key, FALSE, TRUE, NULL );
|
||||||
if (!dst_path)
|
if (!dst_path)
|
||||||
{
|
{
|
||||||
/* try a property */
|
/* try a property */
|
||||||
|
@ -861,25 +963,25 @@ static BOOL verify_comp_for_removal(MSICOMPONENT *comp, UINT install_mode)
|
||||||
{
|
{
|
||||||
INSTALLSTATE request = comp->ActionRequest;
|
INSTALLSTATE request = comp->ActionRequest;
|
||||||
|
|
||||||
if (request == INSTALLSTATE_UNKNOWN)
|
/* special case */
|
||||||
return FALSE;
|
if (request != INSTALLSTATE_SOURCE &&
|
||||||
|
comp->Attributes & msidbComponentAttributesSourceOnly &&
|
||||||
|
(install_mode == msidbRemoveFileInstallModeOnRemove ||
|
||||||
|
install_mode == msidbRemoveFileInstallModeOnBoth)) return TRUE;
|
||||||
|
|
||||||
if (install_mode == msidbRemoveFileInstallModeOnInstall &&
|
switch (request)
|
||||||
(request == INSTALLSTATE_LOCAL || request == INSTALLSTATE_SOURCE))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
if (request == INSTALLSTATE_ABSENT)
|
|
||||||
{
|
{
|
||||||
if (!comp->ComponentId)
|
case INSTALLSTATE_LOCAL:
|
||||||
return FALSE;
|
case INSTALLSTATE_SOURCE:
|
||||||
|
if (install_mode == msidbRemoveFileInstallModeOnInstall ||
|
||||||
if (install_mode == msidbRemoveFileInstallModeOnRemove)
|
install_mode == msidbRemoveFileInstallModeOnBoth) return TRUE;
|
||||||
return TRUE;
|
break;
|
||||||
|
case INSTALLSTATE_ABSENT:
|
||||||
|
if (install_mode == msidbRemoveFileInstallModeOnRemove ||
|
||||||
|
install_mode == msidbRemoveFileInstallModeOnBoth) return TRUE;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (install_mode == msidbRemoveFileInstallModeOnBoth)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,24 +990,17 @@ static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
|
||||||
MSIPACKAGE *package = param;
|
MSIPACKAGE *package = param;
|
||||||
MSICOMPONENT *comp;
|
MSICOMPONENT *comp;
|
||||||
MSIRECORD *uirow;
|
MSIRECORD *uirow;
|
||||||
LPCWSTR component, filename, dirprop;
|
LPCWSTR component, dirprop;
|
||||||
UINT install_mode;
|
UINT install_mode;
|
||||||
LPWSTR dir = NULL, path = NULL;
|
LPWSTR dir = NULL, path = NULL, filename = NULL;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
UINT ret = ERROR_SUCCESS;
|
UINT ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
component = MSI_RecordGetString(row, 2);
|
component = MSI_RecordGetString(row, 2);
|
||||||
filename = MSI_RecordGetString(row, 3);
|
|
||||||
dirprop = MSI_RecordGetString(row, 4);
|
dirprop = MSI_RecordGetString(row, 4);
|
||||||
install_mode = MSI_RecordGetInteger(row, 5);
|
install_mode = MSI_RecordGetInteger(row, 5);
|
||||||
|
|
||||||
comp = get_loaded_component(package, component);
|
comp = get_loaded_component(package, component);
|
||||||
if (!comp)
|
|
||||||
{
|
|
||||||
ERR("Invalid component: %s\n", debugstr_w(component));
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!comp->Enabled)
|
if (!comp->Enabled)
|
||||||
{
|
{
|
||||||
TRACE("component is disabled\n");
|
TRACE("component is disabled\n");
|
||||||
|
@ -914,16 +1009,27 @@ static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
|
||||||
|
|
||||||
if (!verify_comp_for_removal(comp, install_mode))
|
if (!verify_comp_for_removal(comp, install_mode))
|
||||||
{
|
{
|
||||||
TRACE("Skipping removal due to missing conditions\n");
|
TRACE("Skipping removal due to install mode\n");
|
||||||
comp->Action = comp->Installed;
|
comp->Action = comp->Installed;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comp->Attributes & msidbComponentAttributesPermanent)
|
||||||
|
{
|
||||||
|
TRACE("permanent component, not removing file\n");
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
dir = msi_dup_property(package->db, dirprop);
|
dir = msi_dup_property(package->db, dirprop);
|
||||||
if (!dir)
|
if (!dir)
|
||||||
return ERROR_OUTOFMEMORY;
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
size = (filename != NULL) ? lstrlenW(filename) : 0;
|
size = 0;
|
||||||
|
if ((filename = strdupW( MSI_RecordGetString(row, 3) )))
|
||||||
|
{
|
||||||
|
reduce_to_longfilename( filename );
|
||||||
|
size = lstrlenW( filename );
|
||||||
|
}
|
||||||
size += lstrlenW(dir) + 2;
|
size += lstrlenW(dir) + 2;
|
||||||
path = msi_alloc(size * sizeof(WCHAR));
|
path = msi_alloc(size * sizeof(WCHAR));
|
||||||
if (!path)
|
if (!path)
|
||||||
|
@ -954,11 +1060,39 @@ done:
|
||||||
ui_actiondata( package, szRemoveFiles, uirow );
|
ui_actiondata( package, szRemoveFiles, uirow );
|
||||||
msiobj_release( &uirow->hdr );
|
msiobj_release( &uirow->hdr );
|
||||||
|
|
||||||
|
msi_free(filename);
|
||||||
msi_free(path);
|
msi_free(path);
|
||||||
msi_free(dir);
|
msi_free(dir);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL has_persistent_dir( MSIPACKAGE *package, MSICOMPONENT *comp )
|
||||||
|
{
|
||||||
|
MSIQUERY *view;
|
||||||
|
UINT r = ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
static const WCHAR query[] = {
|
||||||
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'`','C','r','e','a','t','e','F','o','l','d','e','r','`',' ','W','H','E','R','E',' ',
|
||||||
|
'`','C','o','m','p','o','n','e','n','t','_','`',' ','=','\'','%','s','\'',' ','A','N','D',' ',
|
||||||
|
'`','D','i','r','e','c','t','o','r','y','_','`',' ','=','\'','%','s','\'',0};
|
||||||
|
|
||||||
|
if (!MSI_OpenQuery( package->db, &view, query, comp->Component, comp->Directory ))
|
||||||
|
{
|
||||||
|
if (!MSI_ViewExecute( view, NULL ))
|
||||||
|
{
|
||||||
|
MSIRECORD *rec;
|
||||||
|
if (!(r = MSI_ViewFetch( view, &rec )))
|
||||||
|
{
|
||||||
|
TRACE("directory %s is persistent\n", debugstr_w(comp->Directory));
|
||||||
|
msiobj_release( &rec->hdr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msiobj_release( &view->hdr );
|
||||||
|
}
|
||||||
|
return (r == ERROR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
||||||
{
|
{
|
||||||
MSIQUERY *view;
|
MSIQUERY *view;
|
||||||
|
@ -968,9 +1102,6 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
||||||
static const WCHAR query[] = {
|
static const WCHAR query[] = {
|
||||||
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
'`','R','e','m','o','v','e','F','i','l','e','`',0};
|
'`','R','e','m','o','v','e','F','i','l','e','`',0};
|
||||||
static const WCHAR folder_query[] = {
|
|
||||||
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
|
||||||
'`','C','r','e','a','t','e','F','o','l','d','e','r','`',0};
|
|
||||||
|
|
||||||
r = MSI_DatabaseOpenViewW(package->db, query, &view);
|
r = MSI_DatabaseOpenViewW(package->db, query, &view);
|
||||||
if (r == ERROR_SUCCESS)
|
if (r == ERROR_SUCCESS)
|
||||||
|
@ -979,10 +1110,6 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
||||||
msiobj_release(&view->hdr);
|
msiobj_release(&view->hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = MSI_DatabaseOpenViewW(package->db, folder_query, &view);
|
|
||||||
if (r == ERROR_SUCCESS)
|
|
||||||
msiobj_release(&view->hdr);
|
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||||
{
|
{
|
||||||
MSIRECORD *uirow;
|
MSIRECORD *uirow;
|
||||||
|
@ -1002,6 +1129,12 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file->Component->Attributes & msidbComponentAttributesPermanent)
|
||||||
|
{
|
||||||
|
TRACE("permanent component, not removing file\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (file->Version)
|
if (file->Version)
|
||||||
{
|
{
|
||||||
ver = msi_get_disk_file_version( file->TargetPath );
|
ver = msi_get_disk_file_version( file->TargetPath );
|
||||||
|
@ -1015,17 +1148,21 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("removing %s\n", debugstr_w(file->File) );
|
TRACE("removing %s\n", debugstr_w(file->File) );
|
||||||
|
|
||||||
|
SetFileAttributesW( file->TargetPath, FILE_ATTRIBUTE_NORMAL );
|
||||||
if (!DeleteFileW( file->TargetPath ))
|
if (!DeleteFileW( file->TargetPath ))
|
||||||
{
|
{
|
||||||
WARN("failed to delete %s\n", debugstr_w(file->TargetPath));
|
WARN("failed to delete %s (%u)\n", debugstr_w(file->TargetPath), GetLastError());
|
||||||
}
|
}
|
||||||
/* FIXME: check persistence for each directory */
|
else if (!has_persistent_dir( package, file->Component ))
|
||||||
else if (r && (dir = strdupW( file->TargetPath )))
|
{
|
||||||
|
if ((dir = strdupW( file->TargetPath )))
|
||||||
{
|
{
|
||||||
if ((p = strrchrW( dir, '\\' ))) *p = 0;
|
if ((p = strrchrW( dir, '\\' ))) *p = 0;
|
||||||
RemoveDirectoryW( dir );
|
RemoveDirectoryW( dir );
|
||||||
msi_free( dir );
|
msi_free( dir );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
file->state = msifs_missing;
|
file->state = msifs_missing;
|
||||||
|
|
||||||
uirow = MSI_CreateRecord( 9 );
|
uirow = MSI_CreateRecord( 9 );
|
||||||
|
|
|
@ -52,6 +52,9 @@ typedef struct _tagTT_NAME_TABLE_HEADER {
|
||||||
* from start of the table */
|
* from start of the table */
|
||||||
} TT_NAME_TABLE_HEADER;
|
} TT_NAME_TABLE_HEADER;
|
||||||
|
|
||||||
|
#define NAME_ID_FULL_FONT_NAME 4
|
||||||
|
#define NAME_ID_VERSION 5
|
||||||
|
|
||||||
typedef struct _tagTT_NAME_RECORD {
|
typedef struct _tagTT_NAME_RECORD {
|
||||||
USHORT uPlatformID;
|
USHORT uPlatformID;
|
||||||
USHORT uEncodingID;
|
USHORT uEncodingID;
|
||||||
|
@ -80,10 +83,8 @@ static const WCHAR regfont2[] =
|
||||||
/*
|
/*
|
||||||
* Code based off of code located here
|
* Code based off of code located here
|
||||||
* http://www.codeproject.com/gdi/fontnamefromfile.asp
|
* http://www.codeproject.com/gdi/fontnamefromfile.asp
|
||||||
*
|
|
||||||
* Using string index 4 (full font name) instead of 1 (family name)
|
|
||||||
*/
|
*/
|
||||||
static LPWSTR load_ttfname_from(LPCWSTR filename)
|
WCHAR *load_ttf_name_id( const WCHAR *filename, DWORD id )
|
||||||
{
|
{
|
||||||
TT_TABLE_DIRECTORY tblDir;
|
TT_TABLE_DIRECTORY tblDir;
|
||||||
BOOL bFound = FALSE;
|
BOOL bFound = FALSE;
|
||||||
|
@ -142,30 +143,24 @@ static LPWSTR load_ttfname_from(LPCWSTR filename)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
|
ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
|
||||||
/* 4 is the Full Font Name */
|
if (ttRecord.uNameID == id)
|
||||||
if(ttRecord.uNameID == 4)
|
|
||||||
{
|
{
|
||||||
int nPos;
|
int nPos;
|
||||||
LPSTR buf;
|
LPSTR buf;
|
||||||
static const char tt[] = " (TrueType)";
|
|
||||||
|
|
||||||
ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
|
ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
|
||||||
ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
|
ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
|
||||||
nPos = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
|
nPos = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
|
||||||
SetFilePointer(handle, tblDir.uOffset +
|
SetFilePointer(handle, tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset,
|
||||||
ttRecord.uStringOffset +
|
|
||||||
ttNTHeader.uStorageOffset,
|
|
||||||
NULL, FILE_BEGIN);
|
NULL, FILE_BEGIN);
|
||||||
buf = msi_alloc_zero( ttRecord.uStringLength + 1 + strlen(tt) );
|
buf = msi_alloc_zero( ttRecord.uStringLength + 1 );
|
||||||
ReadFile(handle, buf, ttRecord.uStringLength, &dwRead, NULL);
|
ReadFile(handle, buf, ttRecord.uStringLength, &dwRead, NULL);
|
||||||
if (strlen(buf) > 0)
|
if (strlen(buf) > 0)
|
||||||
{
|
{
|
||||||
strcat(buf,tt);
|
|
||||||
ret = strdupAtoW(buf);
|
ret = strdupAtoW(buf);
|
||||||
msi_free(buf);
|
msi_free(buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
msi_free(buf);
|
msi_free(buf);
|
||||||
SetFilePointer(handle,nPos, NULL, FILE_BEGIN);
|
SetFilePointer(handle,nPos, NULL, FILE_BEGIN);
|
||||||
}
|
}
|
||||||
|
@ -173,8 +168,36 @@ static LPWSTR load_ttfname_from(LPCWSTR filename)
|
||||||
|
|
||||||
end:
|
end:
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
TRACE("Returning %s\n", debugstr_w(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("Returning fontname %s\n",debugstr_w(ret));
|
static WCHAR *font_name_from_file( const WCHAR *filename )
|
||||||
|
{
|
||||||
|
static const WCHAR truetypeW[] = {' ','(','T','r','u','e','T','y','p','e',')',0};
|
||||||
|
WCHAR *name, *ret = NULL;
|
||||||
|
|
||||||
|
if ((name = load_ttf_name_id( filename, NAME_ID_FULL_FONT_NAME )))
|
||||||
|
{
|
||||||
|
ret = msi_alloc( (strlenW( name ) + strlenW( truetypeW ) + 1 ) * sizeof(WCHAR) );
|
||||||
|
strcpyW( ret, name );
|
||||||
|
strcatW( ret, truetypeW );
|
||||||
|
msi_free( name );
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR *font_version_from_file( const WCHAR *filename )
|
||||||
|
{
|
||||||
|
WCHAR *version, *p, *ret = NULL;
|
||||||
|
|
||||||
|
if ((p = version = load_ttf_name_id( filename, NAME_ID_VERSION )))
|
||||||
|
{
|
||||||
|
while (*p && !isdigitW( *p )) p++;
|
||||||
|
ret = msi_alloc( (strlenW( p ) + 1) * sizeof(WCHAR) );
|
||||||
|
strcpyW( ret, p );
|
||||||
|
msi_free( version );
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +235,7 @@ static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
|
||||||
RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2);
|
RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2);
|
||||||
|
|
||||||
if (MSI_RecordIsNull(row,2))
|
if (MSI_RecordIsNull(row,2))
|
||||||
name = load_ttfname_from( file->TargetPath );
|
name = font_name_from_file( file->TargetPath );
|
||||||
else
|
else
|
||||||
name = msi_dup_record_field(row,2);
|
name = msi_dup_record_field(row,2);
|
||||||
|
|
||||||
|
@ -296,7 +319,7 @@ static UINT ITERATE_UnregisterFonts( MSIRECORD *row, LPVOID param )
|
||||||
RegCreateKeyW( HKEY_LOCAL_MACHINE, regfont2, &hkey2 );
|
RegCreateKeyW( HKEY_LOCAL_MACHINE, regfont2, &hkey2 );
|
||||||
|
|
||||||
if (MSI_RecordIsNull( row, 2 ))
|
if (MSI_RecordIsNull( row, 2 ))
|
||||||
name = load_ttfname_from( file->TargetPath );
|
name = font_name_from_file( file->TargetPath );
|
||||||
else
|
else
|
||||||
name = msi_dup_record_field( row, 2 );
|
name = msi_dup_record_field( row, 2 );
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,6 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
|
||||||
{
|
{
|
||||||
LPWSTR key, ret = NULL;
|
LPWSTR key, ret = NULL;
|
||||||
MSICOMPONENT *comp;
|
MSICOMPONENT *comp;
|
||||||
BOOL source;
|
|
||||||
|
|
||||||
key = msi_alloc((str->len + 1) * sizeof(WCHAR));
|
key = msi_alloc((str->len + 1) * sizeof(WCHAR));
|
||||||
lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
|
lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
|
||||||
|
@ -194,8 +193,10 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
|
||||||
if (!comp)
|
if (!comp)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
source = (comp->Action == INSTALLSTATE_SOURCE) ? TRUE : FALSE;
|
if (comp->Action == INSTALLSTATE_SOURCE)
|
||||||
ret = resolve_folder(format->package, comp->Directory, source, FALSE, TRUE, NULL);
|
ret = resolve_source_folder( format->package, comp->Directory, NULL );
|
||||||
|
else
|
||||||
|
ret = resolve_target_folder( format->package, comp->Directory, FALSE, TRUE, NULL );
|
||||||
|
|
||||||
done:
|
done:
|
||||||
msi_free(key);
|
msi_free(key);
|
||||||
|
|
|
@ -104,7 +104,7 @@ MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component )
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
|
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpW(Component,comp->Component)==0)
|
if (!strcmpW( Component, comp->Component ))
|
||||||
return comp;
|
return comp;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -116,7 +116,7 @@ MSIFEATURE* get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpW( Feature, feature->Feature )==0)
|
if (!strcmpW( Feature, feature->Feature ))
|
||||||
return feature;
|
return feature;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -128,7 +128,7 @@ MSIFILE* get_loaded_file( MSIPACKAGE* package, LPCWSTR key )
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpW( key, file->File )==0)
|
if (!strcmpW( key, file->File ))
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -141,7 +141,7 @@ int track_tempfile( MSIPACKAGE *package, LPCWSTR path )
|
||||||
TRACE("%s\n", debugstr_w(path));
|
TRACE("%s\n", debugstr_w(path));
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
|
LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
|
||||||
if (!lstrcmpW( path, temp->Path ))
|
if (!strcmpW( path, temp->Path ))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
temp = msi_alloc_zero( sizeof (MSITEMPFILE) );
|
temp = msi_alloc_zero( sizeof (MSITEMPFILE) );
|
||||||
|
@ -160,7 +160,7 @@ MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir )
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
|
LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpW( dir, folder->Directory )==0)
|
if (!strcmpW( dir, folder->Directory ))
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -232,8 +232,7 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
|
||||||
if (file->IsCompressed)
|
if (file->IsCompressed)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
p = resolve_folder(package, file->Component->Directory,
|
p = resolve_source_folder( package, file->Component->Directory, NULL );
|
||||||
TRUE, FALSE, TRUE, NULL);
|
|
||||||
path = build_directory_name(2, p, file->ShortName);
|
path = build_directory_name(2, p, file->ShortName);
|
||||||
|
|
||||||
if (file->LongName &&
|
if (file->LongName &&
|
||||||
|
@ -245,25 +244,70 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
|
||||||
|
|
||||||
msi_free(p);
|
msi_free(p);
|
||||||
|
|
||||||
TRACE("file %s source resolves to %s\n", debugstr_w(file->File),
|
TRACE("file %s source resolves to %s\n", debugstr_w(file->File), debugstr_w(path));
|
||||||
debugstr_w(path));
|
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
LPWSTR resolve_source_folder( MSIPACKAGE *package, LPCWSTR name, MSIFOLDER **folder )
|
||||||
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder)
|
|
||||||
{
|
{
|
||||||
MSIFOLDER *f;
|
MSIFOLDER *f;
|
||||||
LPWSTR p, path = NULL, parent;
|
LPWSTR p, path = NULL, parent;
|
||||||
|
|
||||||
TRACE("Working to resolve %s\n",debugstr_w(name));
|
TRACE("working to resolve %s\n", debugstr_w(name));
|
||||||
|
|
||||||
if (!name)
|
if (!strcmpW( name, cszSourceDir ))
|
||||||
|
name = cszTargetDir;
|
||||||
|
|
||||||
|
f = get_loaded_folder( package, name );
|
||||||
|
if (!f)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!lstrcmpW(name,cszSourceDir))
|
/* special resolving for Target and Source root dir */
|
||||||
name = cszTargetDir;
|
if (!strcmpW( name, cszTargetDir ))
|
||||||
|
{
|
||||||
|
if (!f->ResolvedSource)
|
||||||
|
f->ResolvedSource = get_source_root( package );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (folder)
|
||||||
|
*folder = f;
|
||||||
|
|
||||||
|
if (f->ResolvedSource)
|
||||||
|
{
|
||||||
|
path = strdupW( f->ResolvedSource );
|
||||||
|
TRACE(" already resolved to %s\n", debugstr_w(path));
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!f->Parent)
|
||||||
|
return path;
|
||||||
|
|
||||||
|
parent = f->Parent;
|
||||||
|
TRACE(" ! parent is %s\n", debugstr_w(parent));
|
||||||
|
|
||||||
|
p = resolve_source_folder( package, parent, NULL );
|
||||||
|
|
||||||
|
if (package->WordCount & msidbSumInfoSourceTypeCompressed)
|
||||||
|
path = get_source_root( package );
|
||||||
|
else if (package->WordCount & msidbSumInfoSourceTypeSFN)
|
||||||
|
path = build_directory_name( 3, p, f->SourceShortPath, NULL );
|
||||||
|
else
|
||||||
|
path = build_directory_name( 3, p, f->SourceLongPath, NULL );
|
||||||
|
|
||||||
|
TRACE("-> %s\n", debugstr_w(path));
|
||||||
|
f->ResolvedSource = strdupW( path );
|
||||||
|
msi_free( p );
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPWSTR resolve_target_folder( MSIPACKAGE *package, LPCWSTR name, BOOL set_prop, BOOL load_prop,
|
||||||
|
MSIFOLDER **folder )
|
||||||
|
{
|
||||||
|
MSIFOLDER *f;
|
||||||
|
LPWSTR p, path = NULL, parent;
|
||||||
|
|
||||||
|
TRACE("working to resolve %s\n", debugstr_w(name));
|
||||||
|
|
||||||
f = get_loaded_folder( package, name );
|
f = get_loaded_folder( package, name );
|
||||||
if (!f)
|
if (!f)
|
||||||
|
@ -286,45 +330,33 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
||||||
/* correct misbuilt target dir */
|
/* correct misbuilt target dir */
|
||||||
path = build_directory_name(2, check_path, NULL);
|
path = build_directory_name(2, check_path, NULL);
|
||||||
clean_spaces_from_path( path );
|
clean_spaces_from_path( path );
|
||||||
if (strcmpiW(path,check_path)!=0)
|
if (strcmpiW( path, check_path ))
|
||||||
msi_set_property( package->db, cszTargetDir, path );
|
msi_set_property( package->db, cszTargetDir, path );
|
||||||
msi_free(check_path);
|
msi_free(check_path);
|
||||||
|
|
||||||
f->ResolvedTarget = path;
|
f->ResolvedTarget = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!f->ResolvedSource)
|
|
||||||
f->ResolvedSource = get_source_root( package );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (folder)
|
if (folder)
|
||||||
*folder = f;
|
*folder = f;
|
||||||
|
|
||||||
if (!source && f->ResolvedTarget)
|
if (f->ResolvedTarget)
|
||||||
{
|
{
|
||||||
path = strdupW( f->ResolvedTarget );
|
path = strdupW( f->ResolvedTarget );
|
||||||
TRACE(" already resolved to %s\n", debugstr_w(path));
|
TRACE(" already resolved to %s\n", debugstr_w(path));
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source && f->ResolvedSource)
|
if (f->Property)
|
||||||
{
|
|
||||||
path = strdupW( f->ResolvedSource );
|
|
||||||
TRACE(" (source)already resolved to %s\n",debugstr_w(path));
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!source && f->Property)
|
|
||||||
{
|
{
|
||||||
path = build_directory_name( 2, f->Property, NULL );
|
path = build_directory_name( 2, f->Property, NULL );
|
||||||
|
|
||||||
TRACE(" internally set to %s\n", debugstr_w(path));
|
TRACE(" internally set to %s\n", debugstr_w(path));
|
||||||
if (set_prop)
|
if (set_prop) msi_set_property( package->db, name, path );
|
||||||
msi_set_property( package->db, name, path );
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!source && load_prop && (path = msi_dup_property( package->db, name )))
|
if (load_prop && (path = msi_dup_property( package->db, name )))
|
||||||
{
|
{
|
||||||
f->ResolvedTarget = strdupW( path );
|
f->ResolvedTarget = strdupW( path );
|
||||||
TRACE(" property set to %s\n", debugstr_w(path));
|
TRACE(" property set to %s\n", debugstr_w(path));
|
||||||
|
@ -336,34 +368,17 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
||||||
|
|
||||||
parent = f->Parent;
|
parent = f->Parent;
|
||||||
|
|
||||||
TRACE(" ! Parent is %s\n", debugstr_w(parent));
|
TRACE(" ! parent is %s\n", debugstr_w(parent));
|
||||||
|
|
||||||
|
p = resolve_target_folder( package, parent, set_prop, load_prop, NULL );
|
||||||
|
|
||||||
p = resolve_folder(package, parent, source, set_prop, load_prop, NULL);
|
|
||||||
if (!source)
|
|
||||||
{
|
|
||||||
TRACE(" TargetDefault = %s\n", debugstr_w(f->TargetDefault));
|
TRACE(" TargetDefault = %s\n", debugstr_w(f->TargetDefault));
|
||||||
|
|
||||||
path = build_directory_name( 3, p, f->TargetDefault, NULL );
|
path = build_directory_name( 3, p, f->TargetDefault, NULL );
|
||||||
clean_spaces_from_path( path );
|
clean_spaces_from_path( path );
|
||||||
f->ResolvedTarget = strdupW( path );
|
f->ResolvedTarget = strdupW( path );
|
||||||
TRACE("target -> %s\n", debugstr_w(path));
|
|
||||||
if (set_prop)
|
|
||||||
msi_set_property( package->db, name, path );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = NULL;
|
|
||||||
|
|
||||||
if (package->WordCount & msidbSumInfoSourceTypeCompressed)
|
TRACE("-> %s\n", debugstr_w(path));
|
||||||
path = get_source_root( package );
|
if (set_prop) msi_set_property( package->db, name, path );
|
||||||
else if (package->WordCount & msidbSumInfoSourceTypeSFN)
|
|
||||||
path = build_directory_name( 3, p, f->SourceShortPath, NULL );
|
|
||||||
else
|
|
||||||
path = build_directory_name( 3, p, f->SourceLongPath, NULL );
|
|
||||||
|
|
||||||
TRACE("source -> %s\n", debugstr_w(path));
|
|
||||||
f->ResolvedSource = strdupW( path );
|
|
||||||
}
|
|
||||||
msi_free( p );
|
msi_free( p );
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
|
@ -479,6 +494,8 @@ LPWSTR build_directory_name(DWORD count, ...)
|
||||||
if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
|
if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
|
||||||
strcatW(dir, szBackSlash);
|
strcatW(dir, szBackSlash);
|
||||||
}
|
}
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,16 +656,11 @@ LPWSTR create_component_advertise_string(MSIPACKAGE* package,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update component state based on a feature change */
|
/* update component state based on a feature change */
|
||||||
void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
|
||||||
{
|
{
|
||||||
INSTALLSTATE newstate;
|
INSTALLSTATE newstate;
|
||||||
MSIFEATURE *feature;
|
|
||||||
ComponentList *cl;
|
ComponentList *cl;
|
||||||
|
|
||||||
feature = get_loaded_feature(package,szFeature);
|
|
||||||
if (!feature)
|
|
||||||
return;
|
|
||||||
|
|
||||||
newstate = feature->ActionRequest;
|
newstate = feature->ActionRequest;
|
||||||
|
|
||||||
if (newstate == INSTALLSTATE_ABSENT)
|
if (newstate == INSTALLSTATE_ABSENT)
|
||||||
|
@ -658,15 +670,17 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
||||||
{
|
{
|
||||||
MSICOMPONENT* component = cl->component;
|
MSICOMPONENT* component = cl->component;
|
||||||
|
|
||||||
|
if (!component->Enabled) continue;
|
||||||
|
|
||||||
TRACE("MODIFYING(%i): Component %s (Installed %i, Action %i, Request %i)\n",
|
TRACE("MODIFYING(%i): Component %s (Installed %i, Action %i, Request %i)\n",
|
||||||
newstate, debugstr_w(component->Component), component->Installed,
|
newstate, debugstr_w(component->Component), component->Installed,
|
||||||
component->Action, component->ActionRequest);
|
component->Action, component->ActionRequest);
|
||||||
|
|
||||||
if (!component->Enabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (newstate == INSTALLSTATE_LOCAL)
|
if (newstate == INSTALLSTATE_LOCAL)
|
||||||
msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
|
{
|
||||||
|
component->Action = INSTALLSTATE_LOCAL;
|
||||||
|
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ComponentList *clist;
|
ComponentList *clist;
|
||||||
|
@ -674,9 +688,10 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
||||||
|
|
||||||
component->hasLocalFeature = FALSE;
|
component->hasLocalFeature = FALSE;
|
||||||
|
|
||||||
msi_component_set_state(package, component, newstate);
|
component->Action = newstate;
|
||||||
|
component->ActionRequest = newstate;
|
||||||
|
|
||||||
/*if any other feature wants is local we need to set it local*/
|
/* if any other feature wants it local we need to set it local */
|
||||||
LIST_FOR_EACH_ENTRY( f, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( f, &package->features, MSIFEATURE, entry )
|
||||||
{
|
{
|
||||||
if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
|
if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
|
||||||
|
@ -697,14 +712,26 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
||||||
if (component->Attributes & msidbComponentAttributesOptional)
|
if (component->Attributes & msidbComponentAttributesOptional)
|
||||||
{
|
{
|
||||||
if (f->Attributes & msidbFeatureAttributesFavorSource)
|
if (f->Attributes & msidbFeatureAttributesFavorSource)
|
||||||
msi_component_set_state(package, component, INSTALLSTATE_SOURCE);
|
{
|
||||||
|
component->Action = INSTALLSTATE_SOURCE;
|
||||||
|
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
|
{
|
||||||
|
component->Action = INSTALLSTATE_LOCAL;
|
||||||
|
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (component->Attributes & msidbComponentAttributesSourceOnly)
|
else if (component->Attributes & msidbComponentAttributesSourceOnly)
|
||||||
msi_component_set_state(package, component, INSTALLSTATE_SOURCE);
|
{
|
||||||
|
component->Action = INSTALLSTATE_SOURCE;
|
||||||
|
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
|
{
|
||||||
|
component->Action = INSTALLSTATE_LOCAL;
|
||||||
|
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
#include "msi.h"
|
#include "msi.h"
|
||||||
#include "msiquery.h"
|
#include "msiquery.h"
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
|
@ -117,7 +118,7 @@ static BOOL msi_columns_in_order(MSIINSERTVIEW *iv, UINT col_count)
|
||||||
iv->sv->ops->get_column_info(iv->sv, i, &a, NULL, NULL, NULL);
|
iv->sv->ops->get_column_info(iv->sv, i, &a, NULL, NULL, NULL);
|
||||||
iv->table->ops->get_column_info(iv->table, i, &b, NULL, NULL, NULL);
|
iv->table->ops->get_column_info(iv->table, i, &b, NULL, NULL, NULL);
|
||||||
|
|
||||||
res = lstrcmpW(a, b);
|
res = strcmpW( a, b );
|
||||||
msi_free(a);
|
msi_free(a);
|
||||||
msi_free(b);
|
msi_free(b);
|
||||||
|
|
||||||
|
@ -168,7 +169,7 @@ static UINT msi_arrange_record(MSIINSERTVIEW *iv, MSIRECORD **values)
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
res = lstrcmpW(a, b);
|
res = strcmpW( a, b );
|
||||||
msi_free(b);
|
msi_free(b);
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
|
|
|
@ -282,7 +282,7 @@ done:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = resolve_folder( package, szFolder, FALSE, FALSE, TRUE, NULL );
|
path = resolve_target_folder( package, szFolder, FALSE, TRUE, NULL );
|
||||||
msiobj_release( &package->hdr );
|
msiobj_release( &package->hdr );
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
|
@ -336,7 +336,7 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MsiGetSourcePath (internal)
|
* MSI_GetSourcePath (internal)
|
||||||
*/
|
*/
|
||||||
static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
|
static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
|
||||||
awstring *szPathBuf, LPDWORD pcchPathBuf )
|
awstring *szPathBuf, LPDWORD pcchPathBuf )
|
||||||
|
@ -413,7 +413,7 @@ done:
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = resolve_folder(package, szFolder, TRUE, FALSE, TRUE, NULL);
|
path = resolve_source_folder( package, szFolder, NULL );
|
||||||
msiobj_release( &package->hdr );
|
msiobj_release( &package->hdr );
|
||||||
|
|
||||||
TRACE("path = %s\n", debugstr_w(path));
|
TRACE("path = %s\n", debugstr_w(path));
|
||||||
|
@ -512,14 +512,14 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
|
||||||
attrib & FILE_ATTRIBUTE_READONLY))
|
attrib & FILE_ATTRIBUTE_READONLY))
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
path = resolve_folder(package,szFolder,FALSE,FALSE,FALSE,&folder);
|
path = resolve_target_folder( package, szFolder, FALSE, FALSE, &folder );
|
||||||
if (!path)
|
if (!path)
|
||||||
return ERROR_DIRECTORY;
|
return ERROR_DIRECTORY;
|
||||||
|
|
||||||
msi_free(folder->Property);
|
msi_free(folder->Property);
|
||||||
folder->Property = build_directory_name(2, szFolderPath, NULL);
|
folder->Property = build_directory_name(2, szFolderPath, NULL);
|
||||||
|
|
||||||
if (lstrcmpiW(path, folder->Property) == 0)
|
if (!strcmpiW( path, folder->Property ))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Resolved Target has not really changed, so just
|
* Resolved Target has not really changed, so just
|
||||||
|
@ -527,7 +527,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
|
||||||
*/
|
*/
|
||||||
msi_free(folder->ResolvedTarget);
|
msi_free(folder->ResolvedTarget);
|
||||||
folder->ResolvedTarget = NULL;
|
folder->ResolvedTarget = NULL;
|
||||||
path2 = resolve_folder(package,szFolder,FALSE,TRUE,FALSE,NULL);
|
path2 = resolve_target_folder( package, szFolder, TRUE, FALSE, NULL );
|
||||||
msi_free(path2);
|
msi_free(path2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -542,23 +542,23 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
|
LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
|
||||||
{
|
{
|
||||||
path2 = resolve_folder(package, f->Directory, FALSE, TRUE, FALSE, NULL);
|
path2 = resolve_target_folder( package, f->Directory, TRUE, FALSE, NULL );
|
||||||
msi_free(path2);
|
msi_free(path2);
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||||
{
|
{
|
||||||
MSICOMPONENT *comp = file->Component;
|
MSICOMPONENT *comp = file->Component;
|
||||||
LPWSTR p;
|
LPWSTR dir;
|
||||||
|
|
||||||
if (!comp)
|
if (!comp->Enabled || (comp->assembly && !comp->assembly->application))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
p = resolve_folder(package, comp->Directory, FALSE, FALSE, FALSE, NULL);
|
dir = resolve_target_folder( package, comp->Directory, FALSE, FALSE, NULL );
|
||||||
msi_free(file->TargetPath);
|
msi_free(file->TargetPath);
|
||||||
|
|
||||||
file->TargetPath = build_directory_name(2, p, file->FileName);
|
file->TargetPath = build_directory_name(2, dir, file->FileName);
|
||||||
msi_free(p);
|
msi_free(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msi_free(path);
|
msi_free(path);
|
||||||
|
@ -716,6 +716,10 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
|
||||||
r = package->need_reboot;
|
r = package->need_reboot;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSIRUNMODE_LOGENABLED:
|
||||||
|
r = (package->log_file != INVALID_HANDLE_VALUE);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FIXME("unimplemented run mode: %d\n", iRunMode);
|
FIXME("unimplemented run mode: %d\n", iRunMode);
|
||||||
r = TRUE;
|
r = TRUE;
|
||||||
|
@ -821,14 +825,14 @@ UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
|
||||||
feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
|
feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
msi_feature_set_state(package, feature, iState);
|
feature->ActionRequest = iState;
|
||||||
|
|
||||||
ACTION_UpdateComponentStates(package,szFeature);
|
ACTION_UpdateComponentStates( package, feature );
|
||||||
|
|
||||||
/* update all the features that are children of this feature */
|
/* update all the features that are children of this feature */
|
||||||
LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
|
||||||
{
|
{
|
||||||
if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
|
if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
|
||||||
MSI_SetFeatureStateW(package, child->Feature, iState);
|
MSI_SetFeatureStateW(package, child->Feature, iState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,9 +921,9 @@ UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
|
||||||
*piInstalled = feature->Installed;
|
*piInstalled = feature->Installed;
|
||||||
|
|
||||||
if (piAction)
|
if (piAction)
|
||||||
*piAction = feature->Action;
|
*piAction = feature->ActionRequest;
|
||||||
|
|
||||||
TRACE("returning %i %i\n", feature->Installed, feature->Action);
|
TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1158,7 +1162,8 @@ static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
|
||||||
if (!comp)
|
if (!comp)
|
||||||
return ERROR_UNKNOWN_COMPONENT;
|
return ERROR_UNKNOWN_COMPONENT;
|
||||||
|
|
||||||
comp->Installed = iState;
|
if (comp->Enabled)
|
||||||
|
comp->Action = iState;
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1176,13 +1181,22 @@ UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
|
||||||
return ERROR_UNKNOWN_COMPONENT;
|
return ERROR_UNKNOWN_COMPONENT;
|
||||||
|
|
||||||
if (piInstalled)
|
if (piInstalled)
|
||||||
|
{
|
||||||
|
if (comp->Enabled)
|
||||||
*piInstalled = comp->Installed;
|
*piInstalled = comp->Installed;
|
||||||
|
else
|
||||||
|
*piInstalled = INSTALLSTATE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
if (piAction)
|
if (piAction)
|
||||||
|
{
|
||||||
|
if (comp->Enabled)
|
||||||
*piAction = comp->Action;
|
*piAction = comp->Action;
|
||||||
|
else
|
||||||
|
*piAction = INSTALLSTATE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
|
TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ static BOOL source_matches_volume(MSIMEDIAINFO *mi, LPCWSTR source_root)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !lstrcmpW(mi->volume_label, volume_name);
|
return !strcmpW( mi->volume_label, volume_name );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
|
static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
|
||||||
|
@ -331,7 +331,7 @@ static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lstrcmpiW(mi->cabinet, cab))
|
if (strcmpiW( mi->cabinet, cab ))
|
||||||
{
|
{
|
||||||
ERR("Continuous cabinet does not match the next cabinet in the Media table\n");
|
ERR("Continuous cabinet does not match the next cabinet in the Media table\n");
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -656,7 +656,7 @@ static UINT get_drive_type(const WCHAR *path)
|
||||||
return GetDriveTypeW(root);
|
return GetDriveTypeW(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
||||||
{
|
{
|
||||||
MSIRECORD *row;
|
MSIRECORD *row;
|
||||||
LPWSTR source_dir;
|
LPWSTR source_dir;
|
||||||
|
@ -748,24 +748,45 @@ static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi)
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
index = 0;
|
|
||||||
volumesz = MAX_PATH;
|
|
||||||
promptsz = MAX_PATH;
|
|
||||||
|
|
||||||
if (last_type[0] == 'n')
|
if (last_type[0] == 'n')
|
||||||
{
|
{
|
||||||
|
WCHAR cabinet_file[MAX_PATH];
|
||||||
|
BOOL check_all = FALSE;
|
||||||
|
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
volumesz = MAX_PATH;
|
||||||
while (MsiSourceListEnumSourcesW(package->ProductCode, NULL,
|
while (MsiSourceListEnumSourcesW(package->ProductCode, NULL,
|
||||||
package->Context,
|
package->Context,
|
||||||
MSISOURCETYPE_NETWORK, index++,
|
MSISOURCETYPE_NETWORK, index++,
|
||||||
volume, &volumesz) == ERROR_SUCCESS)
|
volume, &volumesz) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
if (!strncmpiW(source, volume, strlenW(source)))
|
if (check_all || !strncmpiW(source, volume, strlenW(source)))
|
||||||
{
|
{
|
||||||
lstrcpyW(mi->sourcedir, source);
|
lstrcpyW(cabinet_file, volume);
|
||||||
|
PathAddBackslashW(cabinet_file);
|
||||||
|
lstrcatW(cabinet_file, mi->cabinet);
|
||||||
|
|
||||||
|
if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
volumesz = MAX_PATH;
|
||||||
|
if(!check_all)
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstrcpyW(mi->sourcedir, volume);
|
||||||
TRACE("Found network source %s\n", debugstr_w(mi->sourcedir));
|
TRACE("Found network source %s\n", debugstr_w(mi->sourcedir));
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!check_all)
|
||||||
|
check_all = TRUE;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
|
@ -803,13 +824,6 @@ UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
||||||
if (mi->is_continuous)
|
if (mi->is_continuous)
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
rc = msi_load_media_info(package, file, mi);
|
|
||||||
if (rc != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
ERR("Unable to load media info %u\n", rc);
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cabinet is internal, no checks needed */
|
/* cabinet is internal, no checks needed */
|
||||||
if (!mi->cabinet || mi->cabinet[0] == '#')
|
if (!mi->cabinet || mi->cabinet[0] == '#')
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
@ -841,7 +855,7 @@ UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
||||||
|
|
||||||
/* check volume matches, change media if not */
|
/* check volume matches, change media if not */
|
||||||
if (mi->volume_label && mi->disk_id > 1 &&
|
if (mi->volume_label && mi->disk_id > 1 &&
|
||||||
lstrcmpW(mi->first_volume, mi->volume_label))
|
strcmpW( mi->first_volume, mi->volume_label ))
|
||||||
{
|
{
|
||||||
LPWSTR source = msi_dup_property(package->db, cszSourceDir);
|
LPWSTR source = msi_dup_property(package->db, cszSourceDir);
|
||||||
BOOL matches;
|
BOOL matches;
|
||||||
|
|
|
@ -299,13 +299,14 @@ done:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR **product_codes )
|
|
||||||
|
static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes )
|
||||||
{
|
{
|
||||||
MSIHANDLE patch, info = 0;
|
MSIHANDLE patch, info = 0;
|
||||||
UINT r, type;
|
UINT r, type;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
static WCHAR empty[] = {0};
|
static WCHAR empty[] = {0};
|
||||||
WCHAR *codes;
|
WCHAR *codes = NULL;
|
||||||
|
|
||||||
r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch );
|
r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
|
@ -332,26 +333,25 @@ static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR **product_cod
|
||||||
}
|
}
|
||||||
|
|
||||||
r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, codes, &size );
|
r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, codes, &size );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r == ERROR_SUCCESS)
|
||||||
msi_free( codes );
|
*product_codes = msi_split_string( codes, ';' );
|
||||||
else
|
|
||||||
*product_codes = codes;
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
MsiCloseHandle( info );
|
MsiCloseHandle( info );
|
||||||
MsiCloseHandle( patch );
|
MsiCloseHandle( patch );
|
||||||
|
msi_free( codes );
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
|
static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
|
||||||
{
|
{
|
||||||
UINT r;
|
UINT r, i;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
LPCWSTR cmd_ptr = szCommandLine;
|
LPCWSTR cmd_ptr = szCommandLine;
|
||||||
LPWSTR beg, end, cmd, codes = NULL;
|
LPWSTR cmd, *codes = NULL;
|
||||||
BOOL succeeded = FALSE;
|
BOOL succeeded = FALSE;
|
||||||
|
|
||||||
static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
|
static const WCHAR fmt[] = {'%','s',' ','P','A','T','C','H','=','"','%','s','"',0};
|
||||||
static WCHAR empty[] = {0};
|
static WCHAR empty[] = {0};
|
||||||
|
|
||||||
if (!szPatchPackage || !szPatchPackage[0])
|
if (!szPatchPackage || !szPatchPackage[0])
|
||||||
|
@ -363,34 +363,27 @@ static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWS
|
||||||
if (!szCommandLine)
|
if (!szCommandLine)
|
||||||
cmd_ptr = empty;
|
cmd_ptr = empty;
|
||||||
|
|
||||||
size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
|
size = strlenW(cmd_ptr) + strlenW(fmt) + strlenW(szPatchPackage) + 1;
|
||||||
cmd = msi_alloc(size * sizeof(WCHAR));
|
cmd = msi_alloc(size * sizeof(WCHAR));
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
{
|
{
|
||||||
msi_free(codes);
|
msi_free(codes);
|
||||||
return ERROR_OUTOFMEMORY;
|
return ERROR_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
sprintfW(cmd, fmt, cmd_ptr, szPatchPackage);
|
||||||
lstrcpyW(cmd, cmd_ptr);
|
|
||||||
if (szCommandLine) lstrcatW(cmd, szSpace);
|
|
||||||
lstrcatW(cmd, patcheq);
|
|
||||||
lstrcatW(cmd, szPatchPackage);
|
|
||||||
|
|
||||||
if (szProductCode)
|
if (szProductCode)
|
||||||
r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
|
r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
beg = codes;
|
for (i = 0; codes[i]; i++)
|
||||||
while ((end = strchrW(beg, '}')))
|
|
||||||
{
|
{
|
||||||
*(end + 1) = '\0';
|
r = MsiConfigureProductExW(codes[i], INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
|
||||||
r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
|
|
||||||
if (r == ERROR_SUCCESS)
|
if (r == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
TRACE("patch applied\n");
|
TRACE("patch applied\n");
|
||||||
succeeded = TRUE;
|
succeeded = TRUE;
|
||||||
}
|
}
|
||||||
beg = end + 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (succeeded)
|
if (succeeded)
|
||||||
|
@ -688,6 +681,8 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
||||||
|
|
||||||
static const WCHAR szInstalled[] = {
|
static const WCHAR szInstalled[] = {
|
||||||
' ','I','n','s','t','a','l','l','e','d','=','1',0};
|
' ','I','n','s','t','a','l','l','e','d','=','1',0};
|
||||||
|
static const WCHAR szInstallLevel[] = {
|
||||||
|
' ','I','N','S','T','A','L','L','L','E','V','E','L','=','3','2','7','6','7',0};
|
||||||
static const WCHAR szRemoveAll[] = {
|
static const WCHAR szRemoveAll[] = {
|
||||||
' ','R','E','M','O','V','E','=','A','L','L',0};
|
' ','R','E','M','O','V','E','=','A','L','L',0};
|
||||||
static const WCHAR szMachine[] = {
|
static const WCHAR szMachine[] = {
|
||||||
|
@ -719,6 +714,9 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
||||||
if (szCommandLine)
|
if (szCommandLine)
|
||||||
sz += lstrlenW(szCommandLine);
|
sz += lstrlenW(szCommandLine);
|
||||||
|
|
||||||
|
if (eInstallState != INSTALLSTATE_DEFAULT)
|
||||||
|
sz += lstrlenW(szInstallLevel);
|
||||||
|
|
||||||
if (eInstallState == INSTALLSTATE_ABSENT)
|
if (eInstallState == INSTALLSTATE_ABSENT)
|
||||||
sz += lstrlenW(szRemoveAll);
|
sz += lstrlenW(szRemoveAll);
|
||||||
|
|
||||||
|
@ -736,6 +734,9 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
||||||
if (szCommandLine)
|
if (szCommandLine)
|
||||||
lstrcpyW(commandline,szCommandLine);
|
lstrcpyW(commandline,szCommandLine);
|
||||||
|
|
||||||
|
if (eInstallState != INSTALLSTATE_DEFAULT)
|
||||||
|
lstrcatW(commandline, szInstallLevel);
|
||||||
|
|
||||||
if (eInstallState == INSTALLSTATE_ABSENT)
|
if (eInstallState == INSTALLSTATE_ABSENT)
|
||||||
lstrcatW(commandline, szRemoveAll);
|
lstrcatW(commandline, szRemoveAll);
|
||||||
|
|
||||||
|
@ -983,22 +984,22 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
||||||
|
|
||||||
MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
|
MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
|
||||||
|
|
||||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
|
if (!strcmpW( szAttribute, INSTALLPROPERTY_HELPLINKW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_PUBLISHERW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
|
!strcmpW( szAttribute, INSTALLPROPERTY_REGOWNERW ))
|
||||||
{
|
{
|
||||||
if (!prodkey)
|
if (!prodkey)
|
||||||
{
|
{
|
||||||
|
@ -1009,25 +1010,25 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
||||||
if (!userdata)
|
if (!userdata)
|
||||||
return ERROR_UNKNOWN_PROPERTY;
|
return ERROR_UNKNOWN_PROPERTY;
|
||||||
|
|
||||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
|
if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
|
||||||
szAttribute = display_name;
|
szAttribute = display_name;
|
||||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
|
else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
|
||||||
szAttribute = display_version;
|
szAttribute = display_version;
|
||||||
|
|
||||||
val = msi_reg_get_value(userdata, szAttribute, &type);
|
val = msi_reg_get_value(userdata, szAttribute, &type);
|
||||||
if (!val)
|
if (!val)
|
||||||
val = empty;
|
val = empty;
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
|
else if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_LANGUAGEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
|
!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) ||
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
|
!strcmpW( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
|
||||||
{
|
{
|
||||||
if (!prodkey)
|
if (!prodkey)
|
||||||
{
|
{
|
||||||
|
@ -1035,10 +1036,10 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
|
if (!strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
|
||||||
szAttribute = assignment;
|
szAttribute = assignment;
|
||||||
|
|
||||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
|
if (!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ))
|
||||||
{
|
{
|
||||||
res = RegOpenKeyW(prodkey, sourcelist, &source);
|
res = RegOpenKeyW(prodkey, sourcelist, &source);
|
||||||
if (res != ERROR_SUCCESS)
|
if (res != ERROR_SUCCESS)
|
||||||
|
@ -1061,7 +1062,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val != empty && type != REG_DWORD &&
|
if (val != empty && type != REG_DWORD &&
|
||||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
|
!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ))
|
||||||
{
|
{
|
||||||
if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
|
if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
|
||||||
badconfig = TRUE;
|
badconfig = TRUE;
|
||||||
|
@ -1324,23 +1325,23 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
|
if (!strcmpW( szProperty, INSTALLPROPERTY_HELPLINKW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_PUBLISHERW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONMINORW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTIDW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_REGCOMPANYW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
|
!strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
|
||||||
{
|
{
|
||||||
val = msi_reg_get_value(props, package, &type);
|
val = msi_reg_get_value(props, package, &type);
|
||||||
if (!val)
|
if (!val)
|
||||||
|
@ -1353,9 +1354,9 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
||||||
|
|
||||||
msi_free(val);
|
msi_free(val);
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
|
if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
|
||||||
szProperty = displayname;
|
szProperty = displayname;
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
|
||||||
szProperty = displayversion;
|
szProperty = displayversion;
|
||||||
|
|
||||||
val = msi_reg_get_value(props, szProperty, &type);
|
val = msi_reg_get_value(props, szProperty, &type);
|
||||||
|
@ -1364,14 +1365,14 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
||||||
|
|
||||||
r = msi_copy_outval(val, szValue, pcchValue);
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_LANGUAGEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_PACKAGECODEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTICONW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
|
!strcmpW( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
|
||||||
{
|
{
|
||||||
if (!prod && !classes)
|
if (!prod && !classes)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1389,7 +1390,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
||||||
|
|
||||||
r = msi_copy_outval(val, szValue, pcchValue);
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTSTATEW ))
|
||||||
{
|
{
|
||||||
if (dwContext == MSIINSTALLCONTEXT_MACHINE)
|
if (dwContext == MSIINSTALLCONTEXT_MACHINE)
|
||||||
{
|
{
|
||||||
|
@ -1423,7 +1424,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
||||||
|
|
||||||
r = msi_copy_outval(val, szValue, pcchValue);
|
r = msi_copy_outval(val, szValue, pcchValue);
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
|
||||||
{
|
{
|
||||||
if (!prod && !classes)
|
if (!prod && !classes)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1554,7 +1555,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
|
||||||
if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
|
if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (!lstrcmpW(szUserSid, szLocalSid))
|
if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
|
if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
|
||||||
|
@ -1575,7 +1576,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
|
||||||
if (res != ERROR_SUCCESS)
|
if (res != ERROR_SUCCESS)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
|
if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ))
|
||||||
{
|
{
|
||||||
if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
|
if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
|
||||||
&prod, FALSE) != ERROR_SUCCESS)
|
&prod, FALSE) != ERROR_SUCCESS)
|
||||||
|
@ -1594,25 +1595,25 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
|
||||||
&udpatch, FALSE) != ERROR_SUCCESS)
|
&udpatch, FALSE) != ERROR_SUCCESS)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
|
if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
|
||||||
{
|
{
|
||||||
if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
|
if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
|
||||||
szProperty = szManagedPackage;
|
szProperty = szManagedPackage;
|
||||||
datakey = udpatch;
|
datakey = udpatch;
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW))
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ))
|
||||||
{
|
{
|
||||||
datakey = patch;
|
datakey = patch;
|
||||||
szProperty = szInstalled;
|
szProperty = szInstalled;
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
|
||||||
{
|
{
|
||||||
datakey = udpatch;
|
datakey = udpatch;
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_UNINSTALLABLEW) ||
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PATCHSTATEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_PATCHSTATEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_DISPLAYNAMEW) ||
|
!strcmpW( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_MOREINFOURLW))
|
!strcmpW( szProperty, INSTALLPROPERTY_MOREINFOURLW ))
|
||||||
{
|
{
|
||||||
datakey = patch;
|
datakey = patch;
|
||||||
}
|
}
|
||||||
|
@ -1766,24 +1767,26 @@ UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
|
||||||
|
|
||||||
UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
|
UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
|
||||||
{
|
{
|
||||||
HANDLE file = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
|
TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
|
||||||
|
|
||||||
|
msi_free(gszLogFile);
|
||||||
|
gszLogFile = NULL;
|
||||||
if (szLogFile)
|
if (szLogFile)
|
||||||
{
|
{
|
||||||
lstrcpyW(gszLogFile,szLogFile);
|
HANDLE file;
|
||||||
|
|
||||||
if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
|
if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
|
||||||
DeleteFileW(szLogFile);
|
DeleteFileW(szLogFile);
|
||||||
file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
|
file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
|
||||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (file != INVALID_HANDLE_VALUE)
|
if (file != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
gszLogFile = strdupW(szLogFile);
|
||||||
CloseHandle(file);
|
CloseHandle(file);
|
||||||
else
|
|
||||||
ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gszLogFile[0] = '\0';
|
ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile), GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1944,6 +1947,7 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
|
||||||
*pdwState = INSTALLSTATE_LOCAL;
|
*pdwState = INSTALLSTATE_LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("-> %d\n", *pdwState);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1982,6 +1986,11 @@ INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
|
||||||
if (lstrlenW(szProduct) != GUID_SIZE - 1)
|
if (lstrlenW(szProduct) != GUID_SIZE - 1)
|
||||||
return INSTALLSTATE_INVALIDARG;
|
return INSTALLSTATE_INVALIDARG;
|
||||||
|
|
||||||
|
if (szProduct[0] != '{' || szProduct[37] != '}')
|
||||||
|
return INSTALLSTATE_UNKNOWN;
|
||||||
|
|
||||||
|
SetLastError( ERROR_SUCCESS );
|
||||||
|
|
||||||
if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||||
&prodkey, FALSE) != ERROR_SUCCESS &&
|
&prodkey, FALSE) != ERROR_SUCCESS &&
|
||||||
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
|
@ -2015,6 +2024,7 @@ done:
|
||||||
|
|
||||||
RegCloseKey(prodkey);
|
RegCloseKey(prodkey);
|
||||||
RegCloseKey(userdata);
|
RegCloseKey(userdata);
|
||||||
|
TRACE("-> %d\n", state);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2631,6 +2641,8 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
|
||||||
if (!squash_guid( szProduct, squishProduct ))
|
if (!squash_guid( szProduct, squishProduct ))
|
||||||
return INSTALLSTATE_INVALIDARG;
|
return INSTALLSTATE_INVALIDARG;
|
||||||
|
|
||||||
|
SetLastError( ERROR_SUCCESS );
|
||||||
|
|
||||||
if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
|
if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
|
||||||
&hkey, FALSE) != ERROR_SUCCESS &&
|
&hkey, FALSE) != ERROR_SUCCESS &&
|
||||||
MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
|
MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||||
|
@ -2711,17 +2723,17 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
|
||||||
|
|
||||||
msi_free(path);
|
msi_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
|
|
||||||
msi_free(components);
|
msi_free(components);
|
||||||
|
|
||||||
if (missing)
|
if (missing)
|
||||||
return INSTALLSTATE_ADVERTISED;
|
r = INSTALLSTATE_ADVERTISED;
|
||||||
|
else if (source)
|
||||||
|
r = INSTALLSTATE_SOURCE;
|
||||||
|
else
|
||||||
|
r = INSTALLSTATE_LOCAL;
|
||||||
|
|
||||||
if (source)
|
TRACE("-> %d\n", r);
|
||||||
return INSTALLSTATE_SOURCE;
|
return r;
|
||||||
|
|
||||||
return INSTALLSTATE_LOCAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -3543,8 +3555,8 @@ UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
|
||||||
LPWSTR ptr;
|
LPWSTR ptr;
|
||||||
DWORD sz;
|
DWORD sz;
|
||||||
|
|
||||||
FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
|
FIXME("%s %s 0x%08x\n",
|
||||||
dwReinstallMode);
|
debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode);
|
||||||
|
|
||||||
ptr = reinstallmode;
|
ptr = reinstallmode;
|
||||||
|
|
||||||
|
@ -3661,8 +3673,10 @@ UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
|
||||||
handle = CreateFileW( szFilePath, GENERIC_READ,
|
handle = CreateFileW( szFilePath, GENERIC_READ,
|
||||||
FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
|
FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
WARN("can't open file %u\n", GetLastError());
|
||||||
return ERROR_FILE_NOT_FOUND;
|
return ERROR_FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
length = GetFileSize( handle, NULL );
|
length = GetFileSize( handle, NULL );
|
||||||
|
|
||||||
mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
|
mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
|
||||||
|
@ -3771,6 +3785,31 @@ UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler,
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MsiInstallMissingComponentA [MSI.@]
|
||||||
|
*/
|
||||||
|
UINT WINAPI MsiInstallMissingComponentA( LPCSTR product, LPCSTR component, INSTALLSTATE state )
|
||||||
|
{
|
||||||
|
UINT r;
|
||||||
|
WCHAR *productW = NULL, *componentW = NULL;
|
||||||
|
|
||||||
|
TRACE("%s, %s, %d\n", debugstr_a(product), debugstr_a(component), state);
|
||||||
|
|
||||||
|
if (product && !(productW = strdupAtoW( product )))
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (component && !(componentW = strdupAtoW( component )))
|
||||||
|
{
|
||||||
|
msi_free( productW );
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = MsiInstallMissingComponentW( productW, componentW, state );
|
||||||
|
msi_free( productW );
|
||||||
|
msi_free( componentW );
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MsiInstallMissingComponentW [MSI.@]
|
* MsiInstallMissingComponentW [MSI.@]
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<file>action.c</file>
|
<file>action.c</file>
|
||||||
<file>alter.c</file>
|
<file>alter.c</file>
|
||||||
<file>appsearch.c</file>
|
<file>appsearch.c</file>
|
||||||
|
<file>assembly.c</file>
|
||||||
<file>automation.c</file>
|
<file>automation.c</file>
|
||||||
<file>classes.c</file>
|
<file>classes.c</file>
|
||||||
<file>cond.tab.c</file>
|
<file>cond.tab.c</file>
|
||||||
|
|
|
@ -19,45 +19,56 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
|
||||||
#include "winuser.h"
|
|
||||||
#include "winnls.h"
|
|
||||||
|
|
||||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
|
||||||
|
|
||||||
#include "version.rc"
|
STRINGTABLE
|
||||||
|
{
|
||||||
#include "msi_Bg.rc"
|
4 "The specified installation package could not be opened. Please check the file path and try again."
|
||||||
#include "msi_Da.rc"
|
5 "path %s not found"
|
||||||
#include "msi_En.rc"
|
9 "insert disk %s"
|
||||||
#include "msi_Es.rc"
|
10 "Windows Installer %s\n\n" \
|
||||||
#include "msi_Fi.rc"
|
"Usage:\n" \
|
||||||
#include "msi_Hu.rc"
|
"msiexec command {required parameter} [optional parameter]\n\n" \
|
||||||
#include "msi_Ko.rc"
|
"Install a product:\n" \
|
||||||
#include "msi_Nl.rc"
|
"\t/i {package|product_code} [property]\n" \
|
||||||
#include "msi_No.rc"
|
"\t/package {package|product_code} [property]\n" \
|
||||||
#include "msi_Pl.rc"
|
"\t/a package [property]\n" \
|
||||||
#include "msi_Sv.rc"
|
"Repair an installation:\n" \
|
||||||
#include "msi_Tr.rc"
|
"\t/f[p|o|e|d|c|a|u|m|s|v] {package|product_code}\n" \
|
||||||
#include "msi_Uk.rc"
|
"Uninstall a product:\n" \
|
||||||
#include "msi_Zh.rc"
|
"\t/uninstall {package|product_code} [property]\n" \
|
||||||
|
"\t/x {package|product_code} [property]\n" \
|
||||||
/* UTF-8 */
|
"Advertise a product:\n" \
|
||||||
#include "msi_De.rc"
|
"\t/j[u|m] package [/t transform] [/g languageid]\n" \
|
||||||
#include "msi_Fr.rc"
|
"Apply a patch:\n" \
|
||||||
#include "msi_It.rc"
|
"\t/p patch_package [property]\n" \
|
||||||
#include "msi_Lt.rc"
|
"\t/p patch_package /a package [property]\n" \
|
||||||
#include "msi_Pt.rc"
|
"Log and UI Modifiers for above commands:\n" \
|
||||||
#include "msi_Ro.rc"
|
"\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
|
||||||
#include "msi_Ru.rc"
|
"\t/q{|n|b|r|f|n+|b+|b-}\n" \
|
||||||
#include "msi_Si.rc"
|
"Register MSI Service:\n" \
|
||||||
#include "msi_Sr.rc"
|
"\t/y\n" \
|
||||||
|
"Unregister MSI Service:\n" \
|
||||||
|
"\t/z\n" \
|
||||||
|
"Display this help:\n" \
|
||||||
|
"\t/help\n" \
|
||||||
|
"\t/?\n"
|
||||||
|
11 "enter which folder contains %s"
|
||||||
|
12 "install source for feature missing"
|
||||||
|
13 "network drive for feature missing"
|
||||||
|
14 "feature from:"
|
||||||
|
15 "choose which folder contains %s"
|
||||||
|
}
|
||||||
|
|
||||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
|
||||||
/* @makedep: msiserver.tlb */
|
/* @makedep: msiserver.tlb */
|
||||||
1 TYPELIB msiserver.tlb
|
1 TYPELIB msiserver.tlb
|
||||||
|
|
||||||
|
/* @makedep: msiserver.rgs */
|
||||||
|
1 WINE_REGISTRY msiserver.rgs
|
||||||
|
|
||||||
/* @makedep: instadvert.bmp */
|
/* @makedep: instadvert.bmp */
|
||||||
0x1001 BITMAP instadvert.bmp
|
0x1001 BITMAP instadvert.bmp
|
||||||
|
|
||||||
|
@ -66,3 +77,12 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
|
||||||
/* @makedep: instlocal.bmp */
|
/* @makedep: instlocal.bmp */
|
||||||
0x1003 BITMAP instlocal.bmp
|
0x1003 BITMAP instlocal.bmp
|
||||||
|
|
||||||
|
#define WINE_FILEDESCRIPTION_STR "Wine MSI dll"
|
||||||
|
#define WINE_FILENAME_STR "msi.dll"
|
||||||
|
#define WINE_FILEVERSION 4,5,6001,22159
|
||||||
|
#define WINE_FILEVERSION_STR "4.5.6001.22159"
|
||||||
|
#define WINE_PRODUCTVERSION 4,5,6001,22159
|
||||||
|
#define WINE_PRODUCTVERSION_STR "4.5.6001.22159"
|
||||||
|
|
||||||
|
#include "wine/wine_common_ver.rc"
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
80 stdcall MsiGetTargetPathW(long wstr ptr ptr)
|
80 stdcall MsiGetTargetPathW(long wstr ptr ptr)
|
||||||
81 stdcall MsiGetUserInfoA(str ptr ptr ptr ptr ptr ptr)
|
81 stdcall MsiGetUserInfoA(str ptr ptr ptr ptr ptr ptr)
|
||||||
82 stdcall MsiGetUserInfoW(wstr ptr ptr ptr ptr ptr ptr)
|
82 stdcall MsiGetUserInfoW(wstr ptr ptr ptr ptr ptr ptr)
|
||||||
83 stub MsiInstallMissingComponentA
|
83 stdcall MsiInstallMissingComponentA(str str long)
|
||||||
84 stdcall MsiInstallMissingComponentW(wstr wstr long)
|
84 stdcall MsiInstallMissingComponentW(wstr wstr long)
|
||||||
85 stub MsiInstallMissingFileA
|
85 stub MsiInstallMissingFileA
|
||||||
86 stub MsiInstallMissingFileW
|
86 stub MsiInstallMissingFileW
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
#include "winreg.h"
|
#include "winreg.h"
|
||||||
#include "shlwapi.h"
|
#include "shlwapi.h"
|
||||||
#include "oleauto.h"
|
#include "oleauto.h"
|
||||||
|
#include "rpcproxy.h"
|
||||||
#include "msipriv.h"
|
#include "msipriv.h"
|
||||||
|
#include "msiserver.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
@ -44,7 +46,7 @@ INSTALLUI_HANDLERW gUIHandlerW = NULL;
|
||||||
INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
|
INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
|
||||||
DWORD gUIFilter = 0;
|
DWORD gUIFilter = 0;
|
||||||
LPVOID gUIContext = NULL;
|
LPVOID gUIContext = NULL;
|
||||||
WCHAR gszLogFile[MAX_PATH];
|
WCHAR *gszLogFile = NULL;
|
||||||
HINSTANCE msi_hInstance;
|
HINSTANCE msi_hInstance;
|
||||||
|
|
||||||
static WCHAR msi_path[MAX_PATH];
|
static WCHAR msi_path[MAX_PATH];
|
||||||
|
@ -78,6 +80,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
if (msi_typelib) ITypeLib_Release( msi_typelib );
|
if (msi_typelib) ITypeLib_Release( msi_typelib );
|
||||||
msi_dialog_unregister_class();
|
msi_dialog_unregister_class();
|
||||||
msi_free_handle_table();
|
msi_free_handle_table();
|
||||||
|
msi_free( gszLogFile );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -117,14 +120,19 @@ ITypeLib *get_msi_typelib( LPWSTR *path )
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct tagIClassFactoryImpl {
|
typedef struct tagIClassFactoryImpl {
|
||||||
const IClassFactoryVtbl *lpVtbl;
|
IClassFactory IClassFactory_iface;
|
||||||
HRESULT (*create_object)( IUnknown*, LPVOID* );
|
HRESULT (*create_object)( IUnknown*, LPVOID* );
|
||||||
} IClassFactoryImpl;
|
} IClassFactoryImpl;
|
||||||
|
|
||||||
|
static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
|
static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
|
||||||
REFIID riid,LPVOID *ppobj)
|
REFIID riid,LPVOID *ppobj)
|
||||||
{
|
{
|
||||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
||||||
|
|
||||||
TRACE("%p %s %p\n",This,debugstr_guid(riid),ppobj);
|
TRACE("%p %s %p\n",This,debugstr_guid(riid),ppobj);
|
||||||
|
|
||||||
|
@ -153,7 +161,7 @@ static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
|
||||||
static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
|
static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
|
||||||
LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
|
LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
|
||||||
{
|
{
|
||||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
||||||
IUnknown *unk = NULL;
|
IUnknown *unk = NULL;
|
||||||
HRESULT r;
|
HRESULT r;
|
||||||
|
|
||||||
|
@ -189,9 +197,9 @@ static const IClassFactoryVtbl MsiCF_Vtbl =
|
||||||
MsiCF_LockServer
|
MsiCF_LockServer
|
||||||
};
|
};
|
||||||
|
|
||||||
static IClassFactoryImpl MsiServer_CF = { &MsiCF_Vtbl, create_msiserver };
|
static IClassFactoryImpl MsiServer_CF = { { &MsiCF_Vtbl }, create_msiserver };
|
||||||
static IClassFactoryImpl WineMsiCustomRemote_CF = { &MsiCF_Vtbl, create_msi_custom_remote };
|
static IClassFactoryImpl WineMsiCustomRemote_CF = { { &MsiCF_Vtbl }, create_msi_custom_remote };
|
||||||
static IClassFactoryImpl WineMsiRemotePackage_CF = { &MsiCF_Vtbl, create_msi_remote_package };
|
static IClassFactoryImpl WineMsiRemotePackage_CF = { { &MsiCF_Vtbl }, create_msi_remote_package };
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* DllGetClassObject [MSI.@]
|
* DllGetClassObject [MSI.@]
|
||||||
|
@ -200,28 +208,28 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
||||||
{
|
{
|
||||||
TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||||
|
|
||||||
if ( IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) )
|
if ( IsEqualCLSID (rclsid, &CLSID_MsiInstaller) )
|
||||||
{
|
{
|
||||||
*ppv = &MsiServer_CF;
|
*ppv = &MsiServer_CF;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( IsEqualCLSID (rclsid, &CLSID_IWineMsiRemoteCustomAction) )
|
if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemoteCustomAction) )
|
||||||
{
|
{
|
||||||
*ppv = &WineMsiCustomRemote_CF;
|
*ppv = &WineMsiCustomRemote_CF;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( IsEqualCLSID (rclsid, &CLSID_IWineMsiRemotePackage) )
|
if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemotePackage) )
|
||||||
{
|
{
|
||||||
*ppv = &WineMsiRemotePackage_CF;
|
*ppv = &WineMsiRemotePackage_CF;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
|
if( IsEqualCLSID (rclsid, &CLSID_MsiServerMessage) ||
|
||||||
IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
|
IsEqualCLSID (rclsid, &CLSID_MsiServer) ||
|
||||||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
|
IsEqualCLSID (rclsid, &CLSID_PSFactoryBuffer) ||
|
||||||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
|
IsEqualCLSID (rclsid, &CLSID_MsiServerX3) )
|
||||||
{
|
{
|
||||||
FIXME("create %s object\n", debugstr_guid( rclsid ));
|
FIXME("create %s object\n", debugstr_guid( rclsid ));
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "msidefs.h"
|
#include "msidefs.h"
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
#include "objidl.h"
|
#include "objidl.h"
|
||||||
|
#include "fusion.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
#include "winver.h"
|
#include "winver.h"
|
||||||
#include "wine/list.h"
|
#include "wine/list.h"
|
||||||
|
@ -162,6 +163,14 @@ typedef struct tagMSIPATCHINFO
|
||||||
MSIPATCHSTATE state;
|
MSIPATCHSTATE state;
|
||||||
} MSIPATCHINFO;
|
} MSIPATCHINFO;
|
||||||
|
|
||||||
|
typedef struct tagMSIBINARY
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
WCHAR *source;
|
||||||
|
WCHAR *tmpfile;
|
||||||
|
HMODULE module;
|
||||||
|
} MSIBINARY;
|
||||||
|
|
||||||
typedef struct _column_info
|
typedef struct _column_info
|
||||||
{
|
{
|
||||||
LPCWSTR table;
|
LPCWSTR table;
|
||||||
|
@ -315,6 +324,13 @@ enum platform
|
||||||
PLATFORM_X64
|
PLATFORM_X64
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum clr_version
|
||||||
|
{
|
||||||
|
CLR_VERSION_V11,
|
||||||
|
CLR_VERSION_V20,
|
||||||
|
CLR_VERSION_MAX
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct tagMSIPACKAGE
|
typedef struct tagMSIPACKAGE
|
||||||
{
|
{
|
||||||
MSIOBJECTHDR hdr;
|
MSIOBJECTHDR hdr;
|
||||||
|
@ -329,8 +345,12 @@ typedef struct tagMSIPACKAGE
|
||||||
struct list files;
|
struct list files;
|
||||||
struct list tempfiles;
|
struct list tempfiles;
|
||||||
struct list folders;
|
struct list folders;
|
||||||
|
struct list binaries;
|
||||||
LPWSTR ActionFormat;
|
LPWSTR ActionFormat;
|
||||||
LPWSTR LastAction;
|
LPWSTR LastAction;
|
||||||
|
HANDLE log_file;
|
||||||
|
IAssemblyCache *cache_net[CLR_VERSION_MAX];
|
||||||
|
IAssemblyCache *cache_sxs;
|
||||||
|
|
||||||
struct list classes;
|
struct list classes;
|
||||||
struct list extensions;
|
struct list extensions;
|
||||||
|
@ -401,6 +421,18 @@ typedef struct tagMSIFEATURE
|
||||||
struct list Components;
|
struct list Components;
|
||||||
} MSIFEATURE;
|
} MSIFEATURE;
|
||||||
|
|
||||||
|
typedef struct tagMSIASSEMBLY
|
||||||
|
{
|
||||||
|
LPWSTR feature;
|
||||||
|
LPWSTR manifest;
|
||||||
|
LPWSTR application;
|
||||||
|
DWORD attributes;
|
||||||
|
LPWSTR display_name;
|
||||||
|
LPWSTR tempdir;
|
||||||
|
BOOL installed;
|
||||||
|
BOOL clr_version[CLR_VERSION_MAX];
|
||||||
|
} MSIASSEMBLY;
|
||||||
|
|
||||||
typedef struct tagMSICOMPONENT
|
typedef struct tagMSICOMPONENT
|
||||||
{
|
{
|
||||||
struct list entry;
|
struct list entry;
|
||||||
|
@ -419,6 +451,7 @@ typedef struct tagMSICOMPONENT
|
||||||
INT RefCount;
|
INT RefCount;
|
||||||
LPWSTR FullKeypath;
|
LPWSTR FullKeypath;
|
||||||
LPWSTR AdvertiseString;
|
LPWSTR AdvertiseString;
|
||||||
|
MSIASSEMBLY *assembly;
|
||||||
|
|
||||||
unsigned int anyAbsent:1;
|
unsigned int anyAbsent:1;
|
||||||
unsigned int hasAdvertiseFeature:1;
|
unsigned int hasAdvertiseFeature:1;
|
||||||
|
@ -466,6 +499,7 @@ typedef enum _msi_file_state {
|
||||||
msifs_present,
|
msifs_present,
|
||||||
msifs_installed,
|
msifs_installed,
|
||||||
msifs_skipped,
|
msifs_skipped,
|
||||||
|
msifs_hashmatch
|
||||||
} msi_file_state;
|
} msi_file_state;
|
||||||
|
|
||||||
typedef struct tagMSIFILE
|
typedef struct tagMSIFILE
|
||||||
|
@ -625,14 +659,6 @@ DEFINE_GUID(CLSID_IMsiServerX2, 0x000C1090,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x0
|
||||||
DEFINE_GUID(CLSID_IMsiServerX3, 0x000C1094,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
DEFINE_GUID(CLSID_IMsiServerX3, 0x000C1094,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_IMsiServerMessage, 0x000C101D,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
DEFINE_GUID(CLSID_IMsiServerMessage, 0x000C101D,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_IWineMsiRemoteCustomAction,0xBA26E6FA,0x4F27,0x4f56,0x95,0x3A,0x3F,0x90,0x27,0x20,0x18,0xAA);
|
|
||||||
DEFINE_GUID(CLSID_IWineMsiRemotePackage,0x902b3592,0x9d08,0x4dfd,0xa5,0x93,0xd0,0x7c,0x52,0x54,0x64,0x21);
|
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_MsiTransform, 0x000c1082,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
|
||||||
DEFINE_GUID(CLSID_MsiDatabase, 0x000c1084,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
|
||||||
DEFINE_GUID(CLSID_MsiPatch, 0x000c1086,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
|
||||||
|
|
||||||
/* handle unicode/ascii output in the Msi* API functions */
|
/* handle unicode/ascii output in the Msi* API functions */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BOOL unicode;
|
BOOL unicode;
|
||||||
|
@ -688,6 +714,8 @@ extern const WCHAR *msi_string_lookup_id( const string_table *st, UINT id );
|
||||||
extern HRESULT msi_init_string_table( IStorage *stg );
|
extern HRESULT msi_init_string_table( IStorage *stg );
|
||||||
extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref );
|
extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref );
|
||||||
extern UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref );
|
extern UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref );
|
||||||
|
extern UINT msi_get_string_table_codepage( const string_table *st );
|
||||||
|
extern UINT msi_set_string_table_codepage( string_table *st, UINT codepage );
|
||||||
|
|
||||||
extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name );
|
extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name );
|
||||||
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table );
|
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table );
|
||||||
|
@ -823,6 +851,7 @@ extern UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct);
|
||||||
extern UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct);
|
extern UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct);
|
||||||
extern UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid);
|
extern UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid);
|
||||||
extern UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode);
|
extern UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode);
|
||||||
|
extern UINT MSIREG_DeleteClassesUpgradeCodesKey(LPCWSTR szUpgradeCode);
|
||||||
extern UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create);
|
extern UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create);
|
||||||
extern UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode);
|
extern UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode);
|
||||||
extern UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode);
|
extern UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode);
|
||||||
|
@ -834,7 +863,9 @@ extern DWORD msi_version_str_to_dword(LPCWSTR p);
|
||||||
extern void msi_parse_version_string(LPCWSTR, PDWORD, PDWORD);
|
extern void msi_parse_version_string(LPCWSTR, PDWORD, PDWORD);
|
||||||
extern VS_FIXEDFILEINFO *msi_get_disk_file_version(LPCWSTR);
|
extern VS_FIXEDFILEINFO *msi_get_disk_file_version(LPCWSTR);
|
||||||
extern int msi_compare_file_versions(VS_FIXEDFILEINFO *, const WCHAR *);
|
extern int msi_compare_file_versions(VS_FIXEDFILEINFO *, const WCHAR *);
|
||||||
|
extern int msi_compare_font_versions(const WCHAR *, const WCHAR *);
|
||||||
|
extern DWORD msi_get_disk_file_size(LPCWSTR);
|
||||||
|
extern BOOL msi_file_hash_matches(MSIFILE *);
|
||||||
|
|
||||||
extern LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
|
extern LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
|
||||||
extern LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
|
extern LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
|
||||||
|
@ -879,7 +910,7 @@ extern INSTALLUI_HANDLERW gUIHandlerW;
|
||||||
extern INSTALLUI_HANDLER_RECORD gUIHandlerRecord;
|
extern INSTALLUI_HANDLER_RECORD gUIHandlerRecord;
|
||||||
extern DWORD gUIFilter;
|
extern DWORD gUIFilter;
|
||||||
extern LPVOID gUIContext;
|
extern LPVOID gUIContext;
|
||||||
extern WCHAR gszLogFile[MAX_PATH];
|
extern WCHAR *gszLogFile;
|
||||||
extern HINSTANCE msi_hInstance;
|
extern HINSTANCE msi_hInstance;
|
||||||
|
|
||||||
/* action related functions */
|
/* action related functions */
|
||||||
|
@ -888,102 +919,6 @@ extern UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UIN
|
||||||
extern void ACTION_FinishCustomActions( const MSIPACKAGE* package);
|
extern void ACTION_FinishCustomActions( const MSIPACKAGE* package);
|
||||||
extern UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, UINT script, BOOL execute);
|
extern UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, UINT script, BOOL execute);
|
||||||
|
|
||||||
static inline void msi_feature_set_state(MSIPACKAGE *package,
|
|
||||||
MSIFEATURE *feature,
|
|
||||||
INSTALLSTATE state)
|
|
||||||
{
|
|
||||||
if (!package->ProductCode)
|
|
||||||
{
|
|
||||||
feature->ActionRequest = state;
|
|
||||||
feature->Action = state;
|
|
||||||
}
|
|
||||||
else if (state == INSTALLSTATE_ABSENT)
|
|
||||||
{
|
|
||||||
switch (feature->Installed)
|
|
||||||
{
|
|
||||||
case INSTALLSTATE_ABSENT:
|
|
||||||
feature->ActionRequest = INSTALLSTATE_UNKNOWN;
|
|
||||||
feature->Action = INSTALLSTATE_UNKNOWN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
feature->ActionRequest = state;
|
|
||||||
feature->Action = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (state == INSTALLSTATE_SOURCE)
|
|
||||||
{
|
|
||||||
switch (feature->Installed)
|
|
||||||
{
|
|
||||||
case INSTALLSTATE_ABSENT:
|
|
||||||
case INSTALLSTATE_SOURCE:
|
|
||||||
feature->ActionRequest = state;
|
|
||||||
feature->Action = state;
|
|
||||||
break;
|
|
||||||
case INSTALLSTATE_LOCAL:
|
|
||||||
feature->ActionRequest = INSTALLSTATE_LOCAL;
|
|
||||||
feature->Action = INSTALLSTATE_LOCAL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
feature->ActionRequest = INSTALLSTATE_UNKNOWN;
|
|
||||||
feature->Action = INSTALLSTATE_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
feature->ActionRequest = state;
|
|
||||||
feature->Action = state;
|
|
||||||
}
|
|
||||||
if (feature->Attributes & msidbFeatureAttributesUIDisallowAbsent)
|
|
||||||
{
|
|
||||||
feature->Action = INSTALLSTATE_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void msi_component_set_state(MSIPACKAGE *package,
|
|
||||||
MSICOMPONENT *comp,
|
|
||||||
INSTALLSTATE state)
|
|
||||||
{
|
|
||||||
if (!package->ProductCode)
|
|
||||||
{
|
|
||||||
comp->ActionRequest = state;
|
|
||||||
comp->Action = state;
|
|
||||||
}
|
|
||||||
else if (state == INSTALLSTATE_ABSENT)
|
|
||||||
{
|
|
||||||
switch (comp->Installed)
|
|
||||||
{
|
|
||||||
case INSTALLSTATE_LOCAL:
|
|
||||||
case INSTALLSTATE_SOURCE:
|
|
||||||
case INSTALLSTATE_DEFAULT:
|
|
||||||
comp->ActionRequest = state;
|
|
||||||
comp->Action = state;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
comp->ActionRequest = INSTALLSTATE_UNKNOWN;
|
|
||||||
comp->Action = INSTALLSTATE_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (state == INSTALLSTATE_SOURCE)
|
|
||||||
{
|
|
||||||
if (comp->Installed == INSTALLSTATE_ABSENT ||
|
|
||||||
(comp->Installed == INSTALLSTATE_SOURCE && comp->hasLocalFeature))
|
|
||||||
{
|
|
||||||
comp->ActionRequest = state;
|
|
||||||
comp->Action = state;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
comp->ActionRequest = INSTALLSTATE_UNKNOWN;
|
|
||||||
comp->Action = INSTALLSTATE_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
comp->ActionRequest = state;
|
|
||||||
comp->Action = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* actions in other modules */
|
/* actions in other modules */
|
||||||
extern UINT ACTION_AppSearch(MSIPACKAGE *package);
|
extern UINT ACTION_AppSearch(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_CCPSearch(MSIPACKAGE *package);
|
extern UINT ACTION_CCPSearch(MSIPACKAGE *package);
|
||||||
|
@ -1003,6 +938,8 @@ extern UINT ACTION_UnregisterExtensionInfo(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_UnregisterFonts(MSIPACKAGE *package);
|
extern UINT ACTION_UnregisterFonts(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_UnregisterMIMEInfo(MSIPACKAGE *package);
|
extern UINT ACTION_UnregisterMIMEInfo(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_UnregisterProgIdInfo(MSIPACKAGE *package);
|
extern UINT ACTION_UnregisterProgIdInfo(MSIPACKAGE *package);
|
||||||
|
extern UINT ACTION_MsiPublishAssemblies(MSIPACKAGE *package);
|
||||||
|
extern UINT ACTION_MsiUnpublishAssemblies(MSIPACKAGE *package);
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
|
extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
|
||||||
|
@ -1011,8 +948,8 @@ extern LPWSTR msi_dup_property( MSIDATABASE *db, LPCWSTR prop );
|
||||||
extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR );
|
extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR );
|
||||||
extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD );
|
extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD );
|
||||||
extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def );
|
extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def );
|
||||||
extern LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
extern LPWSTR resolve_source_folder(MSIPACKAGE *package, LPCWSTR name, MSIFOLDER **folder);
|
||||||
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder);
|
extern LPWSTR resolve_target_folder(MSIPACKAGE *package, LPCWSTR name, BOOL set_prop, BOOL load_prop, MSIFOLDER **folder);
|
||||||
extern LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file);
|
extern LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file);
|
||||||
extern void msi_reset_folders( MSIPACKAGE *package, BOOL source );
|
extern void msi_reset_folders( MSIPACKAGE *package, BOOL source );
|
||||||
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
|
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
|
||||||
|
@ -1027,7 +964,7 @@ extern LPWSTR build_directory_name(DWORD , ...);
|
||||||
extern BOOL create_full_pathW(const WCHAR *path);
|
extern BOOL create_full_pathW(const WCHAR *path);
|
||||||
extern void reduce_to_longfilename(WCHAR*);
|
extern void reduce_to_longfilename(WCHAR*);
|
||||||
extern LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
|
extern LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
|
||||||
extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
|
extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, MSIFEATURE *feature);
|
||||||
extern UINT register_unique_action(MSIPACKAGE *, LPCWSTR);
|
extern UINT register_unique_action(MSIPACKAGE *, LPCWSTR);
|
||||||
extern BOOL check_unique_action(const MSIPACKAGE *, LPCWSTR);
|
extern BOOL check_unique_action(const MSIPACKAGE *, LPCWSTR);
|
||||||
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
|
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
|
||||||
|
@ -1035,6 +972,10 @@ extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
|
||||||
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
|
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
|
||||||
extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix);
|
extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix);
|
||||||
extern UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace);
|
extern UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace);
|
||||||
|
extern MSIASSEMBLY *load_assembly(MSIPACKAGE *, MSICOMPONENT *);
|
||||||
|
extern UINT install_assembly(MSIPACKAGE *, MSICOMPONENT *);
|
||||||
|
extern WCHAR *font_version_from_file(const WCHAR *);
|
||||||
|
extern WCHAR **msi_split_string(const WCHAR *, WCHAR);
|
||||||
|
|
||||||
/* media */
|
/* media */
|
||||||
|
|
||||||
|
@ -1053,6 +994,7 @@ typedef struct
|
||||||
} MSICABDATA;
|
} MSICABDATA;
|
||||||
|
|
||||||
extern UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi);
|
extern UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi);
|
||||||
|
extern UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi);
|
||||||
extern void msi_free_media_info(MSIMEDIAINFO *mi);
|
extern void msi_free_media_info(MSIMEDIAINFO *mi);
|
||||||
extern BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data);
|
extern BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data);
|
||||||
|
|
||||||
|
@ -1149,8 +1091,12 @@ static const WCHAR szAdminUser[] = {'A','d','m','i','n','U','s','e','r',0};
|
||||||
static const WCHAR szIntel[] = {'I','n','t','e','l',0};
|
static const WCHAR szIntel[] = {'I','n','t','e','l',0};
|
||||||
static const WCHAR szIntel64[] = {'I','n','t','e','l','6','4',0};
|
static const WCHAR szIntel64[] = {'I','n','t','e','l','6','4',0};
|
||||||
static const WCHAR szX64[] = {'x','6','4',0};
|
static const WCHAR szX64[] = {'x','6','4',0};
|
||||||
|
static const WCHAR szAMD64[] = {'A','M','D','6','4',0};
|
||||||
static const WCHAR szWow6432NodeCLSID[] = {'W','o','w','6','4','3','2','N','o','d','e','\\','C','L','S','I','D',0};
|
static const WCHAR szWow6432NodeCLSID[] = {'W','o','w','6','4','3','2','N','o','d','e','\\','C','L','S','I','D',0};
|
||||||
static const WCHAR szWow6432Node[] = {'W','o','w','6','4','3','2','N','o','d','e',0};
|
static const WCHAR szWow6432Node[] = {'W','o','w','6','4','3','2','N','o','d','e',0};
|
||||||
|
static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0};
|
||||||
|
static const WCHAR szStorages[] = {'_','S','t','o','r','a','g','e','s',0};
|
||||||
|
static const WCHAR szMsiPublishAssemblies[] = {'M','s','i','P','u','b','l','i','s','h','A','s','s','e','m','b','l','i','e','s',0};
|
||||||
|
|
||||||
/* memory allocation macro functions */
|
/* memory allocation macro functions */
|
||||||
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
|
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
|
||||||
|
|
|
@ -75,9 +75,9 @@ UINT VIEW_find_column( MSIVIEW *table, LPCWSTR name, LPCWSTR table_name, UINT *n
|
||||||
NULL, &haystack_table_name );
|
NULL, &haystack_table_name );
|
||||||
if( r != ERROR_SUCCESS )
|
if( r != ERROR_SUCCESS )
|
||||||
return r;
|
return r;
|
||||||
x = lstrcmpW( name, col_name );
|
x = strcmpW( name, col_name );
|
||||||
if( table_name )
|
if( table_name )
|
||||||
x |= lstrcmpW( table_name, haystack_table_name );
|
x |= strcmpW( table_name, haystack_table_name );
|
||||||
msi_free( col_name );
|
msi_free( col_name );
|
||||||
msi_free( haystack_table_name );
|
msi_free( haystack_table_name );
|
||||||
if( !x )
|
if( !x )
|
||||||
|
|
|
@ -86,6 +86,99 @@ interface IWineMsiRemoteCustomAction : IUnknown
|
||||||
[out] BSTR *function, [out] IWineMsiRemotePackage **package );
|
[out] BSTR *function, [out] IWineMsiRemotePackage **package );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(000c101c-0000-0000-c000-000000000046),
|
||||||
|
oleautomation,
|
||||||
|
object
|
||||||
|
]
|
||||||
|
interface IMsiServer : IUnknown
|
||||||
|
{
|
||||||
|
/* FIXME: methods */
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(000c101d-0000-0000-c000-000000000046),
|
||||||
|
oleautomation,
|
||||||
|
object
|
||||||
|
]
|
||||||
|
interface IMsiMessage : IUnknown
|
||||||
|
{
|
||||||
|
/* FIXME: methods */
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(000c1025-0000-0000-c000-000000000046),
|
||||||
|
oleautomation,
|
||||||
|
object
|
||||||
|
]
|
||||||
|
interface IMsiCustomAction : IUnknown
|
||||||
|
{
|
||||||
|
/* FIXME: methods */
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(000c1033-0000-0000-c000-000000000046),
|
||||||
|
oleautomation,
|
||||||
|
object
|
||||||
|
]
|
||||||
|
interface IMsiRemoteAPI : IUnknown
|
||||||
|
{
|
||||||
|
/* FIXME: methods */
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Msi install server"),
|
||||||
|
progid("IMsiServer"),
|
||||||
|
uuid(000c101c-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
coclass MsiServer { interface IMsiServer; }
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Microsoft Windows Installer Message RPC"),
|
||||||
|
progid("WindowsInstaller.Message"),
|
||||||
|
uuid(000c101d-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
coclass MsiServerMessage { interface IMsiMessage; }
|
||||||
|
|
||||||
|
[
|
||||||
|
threading(both),
|
||||||
|
uuid(000c103e-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
coclass PSFactoryBuffer { interface IPSFactoryBuffer; }
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(000c1082-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
coclass MsiTransform { }
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(000c1084-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
coclass MsiDatabase { }
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(000c1086-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
coclass MsiPatch { }
|
||||||
|
|
||||||
|
[
|
||||||
|
threading(apartment),
|
||||||
|
uuid(000c1094-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
/* FIXME: unidentified class */
|
||||||
|
coclass MsiServerX3 { interface IMsiServer; }
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(ba26e6fa-4f27-4f56-953a-3f90272018aa)
|
||||||
|
]
|
||||||
|
coclass WineMsiRemoteCustomAction { interface WineMsiRemoteCustomAction; }
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(902b3592-9d08-4dfd-a593-d07c52546421)
|
||||||
|
]
|
||||||
|
coclass WineMsiRemotePackage { interface WineMsiRemotePackage; }
|
||||||
|
|
||||||
|
|
||||||
[ uuid(000C1092-0000-0000-C000-000000000046), version(1.0) ]
|
[ uuid(000C1092-0000-0000-C000-000000000046), version(1.0) ]
|
||||||
library WindowsInstaller
|
library WindowsInstaller
|
||||||
{
|
{
|
||||||
|
@ -452,4 +545,12 @@ library WindowsInstaller
|
||||||
properties:
|
properties:
|
||||||
methods:
|
methods:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Microsoft Windows Installer"),
|
||||||
|
threading(apartment),
|
||||||
|
progid("WindowsInstaller.Installer"),
|
||||||
|
uuid(000c1090-0000-0000-c000-000000000046)
|
||||||
|
]
|
||||||
|
coclass MsiInstaller { interface Installer; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,8 +59,7 @@ static void remove_tracked_tempfiles( MSIPACKAGE *package )
|
||||||
|
|
||||||
list_remove( &temp->entry );
|
list_remove( &temp->entry );
|
||||||
TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
|
TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
|
||||||
if (!DeleteFileW( temp->Path ))
|
DeleteFileW( temp->Path );
|
||||||
ERR("failed to delete %s\n", debugstr_w( temp->Path ));
|
|
||||||
msi_free( temp->Path );
|
msi_free( temp->Path );
|
||||||
msi_free( temp );
|
msi_free( temp );
|
||||||
}
|
}
|
||||||
|
@ -111,6 +110,17 @@ static void free_extension( MSIEXTENSION *ext )
|
||||||
msi_free( ext );
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
static void free_package_structures( MSIPACKAGE *package )
|
static void free_package_structures( MSIPACKAGE *package )
|
||||||
{
|
{
|
||||||
INT i;
|
INT i;
|
||||||
|
@ -154,6 +164,7 @@ static void free_package_structures( MSIPACKAGE *package )
|
||||||
msi_free( comp->Condition );
|
msi_free( comp->Condition );
|
||||||
msi_free( comp->KeyPath );
|
msi_free( comp->KeyPath );
|
||||||
msi_free( comp->FullKeypath );
|
msi_free( comp->FullKeypath );
|
||||||
|
if (comp->assembly) free_assembly( comp->assembly );
|
||||||
msi_free( comp );
|
msi_free( comp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +286,20 @@ static void free_package_structures( MSIPACKAGE *package )
|
||||||
msi_free( patch );
|
msi_free( patch );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
msi_free( package->BaseURL );
|
msi_free( package->BaseURL );
|
||||||
msi_free( package->PackagePath );
|
msi_free( package->PackagePath );
|
||||||
msi_free( package->ProductCode );
|
msi_free( package->ProductCode );
|
||||||
|
@ -288,6 +313,7 @@ static void free_package_structures( MSIPACKAGE *package )
|
||||||
|
|
||||||
static void MSI_FreePackage( MSIOBJECTHDR *arg)
|
static void MSI_FreePackage( MSIOBJECTHDR *arg)
|
||||||
{
|
{
|
||||||
|
UINT i;
|
||||||
MSIPACKAGE *package = (MSIPACKAGE *)arg;
|
MSIPACKAGE *package = (MSIPACKAGE *)arg;
|
||||||
|
|
||||||
if( package->dialog )
|
if( package->dialog )
|
||||||
|
@ -295,6 +321,11 @@ static void MSI_FreePackage( MSIOBJECTHDR *arg)
|
||||||
|
|
||||||
msiobj_release( &package->db->hdr );
|
msiobj_release( &package->db->hdr );
|
||||||
free_package_structures(package);
|
free_package_structures(package);
|
||||||
|
CloseHandle( package->log_file );
|
||||||
|
|
||||||
|
for (i = 0; i < CLR_VERSION_MAX; i++)
|
||||||
|
if (package->cache_net[i]) IAssemblyCache_Release( package->cache_net[i] );
|
||||||
|
if (package->cache_sxs) IAssemblyCache_Release( package->cache_sxs );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT create_temp_property_table(MSIPACKAGE *package)
|
static UINT create_temp_property_table(MSIPACKAGE *package)
|
||||||
|
@ -511,7 +542,7 @@ static LPWSTR get_fusion_filename(MSIPACKAGE *package)
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
/* verify existence of fusion.dll .Net 3.0 does not install a new one */
|
/* verify existence of fusion.dll .Net 3.0 does not install a new one */
|
||||||
if (lstrcmpW(ver, name) < 0)
|
if (strcmpW( ver, name ) < 0)
|
||||||
{
|
{
|
||||||
LPWSTR check;
|
LPWSTR check;
|
||||||
size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3;
|
size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3;
|
||||||
|
@ -1046,6 +1077,7 @@ static MSIPACKAGE *msi_alloc_package( void )
|
||||||
list_init( &package->sourcelist_info );
|
list_init( &package->sourcelist_info );
|
||||||
list_init( &package->sourcelist_media );
|
list_init( &package->sourcelist_media );
|
||||||
list_init( &package->patches );
|
list_init( &package->patches );
|
||||||
|
list_init( &package->binaries );
|
||||||
}
|
}
|
||||||
|
|
||||||
return package;
|
return package;
|
||||||
|
@ -1121,6 +1153,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
|
||||||
|
|
||||||
if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
|
if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
|
||||||
msi_load_admin_properties( package );
|
msi_load_admin_properties( package );
|
||||||
|
|
||||||
|
package->log_file = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return package;
|
return package;
|
||||||
|
@ -1313,7 +1347,7 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
|
||||||
package->platform = PLATFORM_INTEL;
|
package->platform = PLATFORM_INTEL;
|
||||||
else if (!strcmpW( template, szIntel64 ))
|
else if (!strcmpW( template, szIntel64 ))
|
||||||
package->platform = PLATFORM_INTEL64;
|
package->platform = PLATFORM_INTEL64;
|
||||||
else if (!strcmpW( template, szX64 ))
|
else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 ))
|
||||||
package->platform = PLATFORM_X64;
|
package->platform = PLATFORM_X64;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1321,9 +1355,14 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
|
||||||
msi_free( template );
|
msi_free( template );
|
||||||
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
|
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
p++;
|
||||||
|
if (!*p)
|
||||||
|
{
|
||||||
|
msi_free( template );
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
count = 1;
|
count = 1;
|
||||||
for (q = ++p; (q = strchrW( q, ',' )); q++) count++;
|
for (q = p; (q = strchrW( q, ',' )); q++) count++;
|
||||||
|
|
||||||
package->langids = msi_alloc( count * sizeof(LANGID) );
|
package->langids = msi_alloc( count * sizeof(LANGID) );
|
||||||
if (!package->langids)
|
if (!package->langids)
|
||||||
|
@ -1367,7 +1406,17 @@ static UINT validate_package( MSIPACKAGE *package )
|
||||||
}
|
}
|
||||||
for (i = 0; i < package->num_langids; i++)
|
for (i = 0; i < package->num_langids; i++)
|
||||||
{
|
{
|
||||||
if (!package->langids[i] || IsValidLocale( package->langids[i], LCID_INSTALLED ))
|
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_SUCCESS;
|
||||||
}
|
}
|
||||||
return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
|
return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
|
||||||
|
@ -1551,6 +1600,10 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
||||||
msi_adjust_privilege_properties( package );
|
msi_adjust_privilege_properties( package );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gszLogFile)
|
||||||
|
package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||||
|
|
||||||
*pPackage = package;
|
*pPackage = package;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1657,17 +1710,13 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
|
||||||
{'S','e','t','P','r','o','g','r','e','s','s',0};
|
{'S','e','t','P','r','o','g','r','e','s','s',0};
|
||||||
static const WCHAR szActionText[] =
|
static const WCHAR szActionText[] =
|
||||||
{'A','c','t','i','o','n','T','e','x','t',0};
|
{'A','c','t','i','o','n','T','e','x','t',0};
|
||||||
DWORD log_type = 0;
|
|
||||||
LPWSTR message;
|
LPWSTR message;
|
||||||
DWORD sz;
|
DWORD sz, total_size = 0, log_type = 0;
|
||||||
DWORD total_size = 0;
|
INT i, rc = 0;
|
||||||
INT i;
|
|
||||||
INT rc;
|
|
||||||
char *msg;
|
char *msg;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
TRACE("%x\n", eMessageType);
|
TRACE("%x\n", eMessageType);
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
|
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
|
||||||
log_type |= INSTALLLOGMODE_ERROR;
|
log_type |= INSTALLLOGMODE_ERROR;
|
||||||
|
@ -1773,20 +1822,12 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
|
||||||
MsiCloseHandle( rec );
|
MsiCloseHandle( rec );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
|
if (!rc && package->log_file != INVALID_HANDLE_VALUE &&
|
||||||
INSTALLMESSAGE_PROGRESS))
|
(eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
|
||||||
{
|
{
|
||||||
DWORD write;
|
DWORD written;
|
||||||
HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
|
WriteFile( package->log_file, msg, len - 1, &written, NULL );
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
WriteFile( package->log_file, "\n", 1, &written, NULL );
|
||||||
|
|
||||||
if (log_file != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
SetFilePointer(log_file,0, NULL, FILE_END);
|
|
||||||
WriteFile(log_file,msg,strlen(msg),&write,NULL);
|
|
||||||
WriteFile(log_file,"\n",1,&write,NULL);
|
|
||||||
CloseHandle(log_file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
msi_free( msg );
|
msi_free( msg );
|
||||||
msi_free( message );
|
msi_free( message );
|
||||||
|
@ -2248,14 +2289,14 @@ UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _msi_remote_package_impl {
|
typedef struct _msi_remote_package_impl {
|
||||||
const IWineMsiRemotePackageVtbl *lpVtbl;
|
IWineMsiRemotePackage IWineMsiRemotePackage_iface;
|
||||||
MSIHANDLE package;
|
MSIHANDLE package;
|
||||||
LONG refs;
|
LONG refs;
|
||||||
} msi_remote_package_impl;
|
} msi_remote_package_impl;
|
||||||
|
|
||||||
static inline msi_remote_package_impl* mrp_from_IWineMsiRemotePackage( IWineMsiRemotePackage* iface )
|
static inline msi_remote_package_impl *impl_from_IWineMsiRemotePackage( IWineMsiRemotePackage *iface )
|
||||||
{
|
{
|
||||||
return (msi_remote_package_impl*) iface;
|
return CONTAINING_RECORD(iface, msi_remote_package_impl, IWineMsiRemotePackage_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface,
|
static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface,
|
||||||
|
@ -2274,14 +2315,14 @@ static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface,
|
||||||
|
|
||||||
static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface )
|
static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
|
|
||||||
return InterlockedIncrement( &This->refs );
|
return InterlockedIncrement( &This->refs );
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
|
static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
ULONG r;
|
ULONG r;
|
||||||
|
|
||||||
r = InterlockedDecrement( &This->refs );
|
r = InterlockedDecrement( &This->refs );
|
||||||
|
@ -2295,14 +2336,14 @@ static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle )
|
static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
This->package = handle;
|
This->package = handle;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
|
static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
IWineMsiRemoteDatabase *rdb = NULL;
|
IWineMsiRemoteDatabase *rdb = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
MSIHANDLE hdb;
|
MSIHANDLE hdb;
|
||||||
|
@ -2329,7 +2370,7 @@ static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHA
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
|
static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r;
|
UINT r;
|
||||||
|
|
||||||
r = MsiGetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value, size);
|
r = MsiGetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value, size);
|
||||||
|
@ -2341,63 +2382,63 @@ static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR proper
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
|
static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetPropertyW(This->package, property, value);
|
UINT r = MsiSetPropertyW(This->package, property, value);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
|
static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiProcessMessage(This->package, message, record);
|
UINT r = MsiProcessMessage(This->package, message, record);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
|
static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiDoActionW(This->package, action);
|
UINT r = MsiDoActionW(This->package, action);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
|
static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSequenceW(This->package, table, sequence);
|
UINT r = MsiSequenceW(This->package, table, sequence);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
|
static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetTargetPathW(This->package, folder, value);
|
UINT r = MsiSetTargetPathW(This->package, folder, value);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
|
static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
*ret = MsiGetMode(This->package, mode);
|
*ret = MsiGetMode(This->package, mode);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state )
|
static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetMode(This->package, mode, state);
|
UINT r = MsiSetMode(This->package, mode, state);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
@ -2405,14 +2446,14 @@ static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode
|
||||||
static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
|
static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
|
||||||
INSTALLSTATE *installed, INSTALLSTATE *action )
|
INSTALLSTATE *installed, INSTALLSTATE *action )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiGetFeatureStateW(This->package, feature, installed, action);
|
UINT r = MsiGetFeatureStateW(This->package, feature, installed, action);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
|
static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetFeatureStateW(This->package, feature, state);
|
UINT r = MsiSetFeatureStateW(This->package, feature, state);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
@ -2420,28 +2461,28 @@ static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR fe
|
||||||
static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
|
static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
|
||||||
INSTALLSTATE *installed, INSTALLSTATE *action )
|
INSTALLSTATE *installed, INSTALLSTATE *action )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiGetComponentStateW(This->package, component, installed, action);
|
UINT r = MsiGetComponentStateW(This->package, component, installed, action);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
|
static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetComponentStateW(This->package, component, state);
|
UINT r = MsiSetComponentStateW(This->package, component, state);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
|
static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
*language = MsiGetLanguage(This->package);
|
*language = MsiGetLanguage(This->package);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
|
static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiSetInstallLevel(This->package, level);
|
UINT r = MsiSetInstallLevel(This->package, level);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
@ -2450,7 +2491,7 @@ static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE
|
||||||
BSTR *value)
|
BSTR *value)
|
||||||
{
|
{
|
||||||
DWORD size = 0;
|
DWORD size = 0;
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiFormatRecordW(This->package, record, NULL, &size);
|
UINT r = MsiFormatRecordW(This->package, record, NULL, &size);
|
||||||
if (r == ERROR_SUCCESS)
|
if (r == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -2465,7 +2506,7 @@ static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE
|
||||||
|
|
||||||
static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
|
static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiEvaluateConditionW(This->package, condition);
|
UINT r = MsiEvaluateConditionW(This->package, condition);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
@ -2473,7 +2514,7 @@ static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR
|
||||||
static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature,
|
static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature,
|
||||||
INT cost_tree, INSTALLSTATE state, INT *cost )
|
INT cost_tree, INSTALLSTATE state, INT *cost )
|
||||||
{
|
{
|
||||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||||
UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost);
|
UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost);
|
||||||
return HRESULT_FROM_WIN32(r);
|
return HRESULT_FROM_WIN32(r);
|
||||||
}
|
}
|
||||||
|
@ -2514,7 +2555,7 @@ HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
|
||||||
if (!This)
|
if (!This)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
This->lpVtbl = &msi_remote_package_vtbl;
|
This->IWineMsiRemotePackage_iface.lpVtbl = &msi_remote_package_vtbl;
|
||||||
This->package = 0;
|
This->package = 0;
|
||||||
This->refs = 1;
|
This->refs = 1;
|
||||||
|
|
||||||
|
@ -2528,6 +2569,11 @@ UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
|
||||||
{
|
{
|
||||||
MSISOURCELISTINFO *info;
|
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));
|
info = msi_alloc(sizeof(MSISOURCELISTINFO));
|
||||||
if (!info)
|
if (!info)
|
||||||
return ERROR_OUTOFMEMORY;
|
return ERROR_OUTOFMEMORY;
|
||||||
|
@ -2546,6 +2592,11 @@ UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD option
|
||||||
{
|
{
|
||||||
MSIMEDIADISK *disk;
|
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));
|
disk = msi_alloc(sizeof(MSIMEDIADISK));
|
||||||
if (!disk)
|
if (!disk)
|
||||||
return ERROR_OUTOFMEMORY;
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
#include "msi.h"
|
#include "msi.h"
|
||||||
#include "msiquery.h"
|
#include "msiquery.h"
|
||||||
#include "msipriv.h"
|
#include "msipriv.h"
|
||||||
|
@ -1016,7 +1017,7 @@ BOOL MSI_RecordsAreEqual(MSIRECORD *a, MSIRECORD *b)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSIFIELD_WSTR:
|
case MSIFIELD_WSTR:
|
||||||
if (lstrcmpW(a->fields[i].u.szwVal, b->fields[i].u.szwVal))
|
if (strcmpW(a->fields[i].u.szwVal, b->fields[i].u.szwVal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1182,6 +1182,21 @@ UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL cr
|
||||||
return RegOpenKeyW(HKEY_CLASSES_ROOT, keypath, key);
|
return RegOpenKeyW(HKEY_CLASSES_ROOT, keypath, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT MSIREG_DeleteClassesUpgradeCodesKey(LPCWSTR szUpgradeCode)
|
||||||
|
{
|
||||||
|
WCHAR squished_pc[GUID_SIZE];
|
||||||
|
WCHAR keypath[0x200];
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_w(szUpgradeCode));
|
||||||
|
if (!squash_guid(szUpgradeCode, squished_pc))
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
TRACE("squished (%s)\n", debugstr_w(squished_pc));
|
||||||
|
|
||||||
|
sprintfW(keypath, szInstaller_ClassesUpgrade_fmt, squished_pc);
|
||||||
|
|
||||||
|
return RegDeleteTreeW(HKEY_CLASSES_ROOT, keypath);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* MsiDecomposeDescriptorW [MSI.@]
|
* MsiDecomposeDescriptorW [MSI.@]
|
||||||
*
|
*
|
||||||
|
@ -1549,10 +1564,11 @@ UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
|
||||||
sz = SQUISH_GUID_SIZE;
|
sz = SQUISH_GUID_SIZE;
|
||||||
r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
|
r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
|
||||||
if( r == ERROR_SUCCESS )
|
if( r == ERROR_SUCCESS )
|
||||||
|
{
|
||||||
unsquash_guid(szValName, szProduct);
|
unsquash_guid(szValName, szProduct);
|
||||||
|
TRACE("-> %s\n", debugstr_w(szProduct));
|
||||||
|
}
|
||||||
RegCloseKey(hkeyComp);
|
RegCloseKey(hkeyComp);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2140,7 +2156,7 @@ UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
||||||
if (!szProductCode || !squash_guid(szProductCode, squished_pc))
|
if (!szProductCode || !squash_guid(szProductCode, squished_pc))
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (!lstrcmpW(szUserSid, szLocalSid))
|
if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
|
if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
|
||||||
|
|
|
@ -143,6 +143,7 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
|
||||||
|
|
||||||
/* Add the session object */
|
/* Add the session object */
|
||||||
hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_ISVISIBLE);
|
hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_ISVISIBLE);
|
||||||
|
if (FAILED(hr)) goto done;
|
||||||
|
|
||||||
/* Pass the script to the engine */
|
/* Pass the script to the engine */
|
||||||
hr = IActiveScriptParse64_ParseScriptText(pActiveScriptParse, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL);
|
hr = IActiveScriptParse64_ParseScriptText(pActiveScriptParse, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL);
|
||||||
|
|
|
@ -330,7 +330,6 @@ UINT WINAPI MsiSourceListEnumMediaDisksW(LPCWSTR szProductCodeOrPatchCode,
|
||||||
else
|
else
|
||||||
size = lstrlenW(ptr);
|
size = lstrlenW(ptr);
|
||||||
|
|
||||||
size = lstrlenW(ptr);
|
|
||||||
if (size >= *pcchDiskPrompt)
|
if (size >= *pcchDiskPrompt)
|
||||||
r = ERROR_MORE_DATA;
|
r = ERROR_MORE_DATA;
|
||||||
else if (szDiskPrompt)
|
else if (szDiskPrompt)
|
||||||
|
@ -592,8 +591,8 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) ||
|
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW))
|
!strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
|
||||||
{
|
{
|
||||||
rc = OpenMediaSubkey(sourcekey, &media, FALSE);
|
rc = OpenMediaSubkey(sourcekey, &media, FALSE);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
|
@ -602,14 +601,14 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW))
|
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
|
||||||
szProperty = mediapack;
|
szProperty = mediapack;
|
||||||
|
|
||||||
RegQueryValueExW(media, szProperty, 0, 0, (LPBYTE)szValue, pcchValue);
|
RegQueryValueExW(media, szProperty, 0, 0, (LPBYTE)szValue, pcchValue);
|
||||||
RegCloseKey(media);
|
RegCloseKey(media);
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW) ||
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDTYPEW))
|
!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
|
||||||
{
|
{
|
||||||
rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
|
rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
|
||||||
0, 0, NULL, &size);
|
0, 0, NULL, &size);
|
||||||
|
@ -630,7 +629,7 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDTYPEW))
|
if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
|
||||||
{
|
{
|
||||||
if (*source != 'n' && *source != 'u' && *source != 'm')
|
if (*source != 'n' && *source != 'u' && *source != 'm')
|
||||||
{
|
{
|
||||||
|
@ -662,7 +661,7 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
*pcchValue = lstrlenW(ptr);
|
*pcchValue = lstrlenW(ptr);
|
||||||
msi_free(source);
|
msi_free(source);
|
||||||
}
|
}
|
||||||
else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
|
||||||
{
|
{
|
||||||
*pcchValue = *pcchValue * sizeof(WCHAR);
|
*pcchValue = *pcchValue * sizeof(WCHAR);
|
||||||
rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0,
|
rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0,
|
||||||
|
@ -815,22 +814,22 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
}
|
}
|
||||||
|
|
||||||
property = szProperty;
|
property = szProperty;
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW))
|
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
|
||||||
property = media_package;
|
property = media_package;
|
||||||
|
|
||||||
rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
|
rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW) &&
|
if (strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) &&
|
||||||
dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL))
|
dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL))
|
||||||
{
|
{
|
||||||
RegCloseKey(sourcekey);
|
RegCloseKey(sourcekey);
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) ||
|
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
|
||||||
!lstrcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW))
|
!strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
|
||||||
{
|
{
|
||||||
rc = OpenMediaSubkey(sourcekey, &media, TRUE);
|
rc = OpenMediaSubkey(sourcekey, &media, TRUE);
|
||||||
if (rc == ERROR_SUCCESS)
|
if (rc == ERROR_SUCCESS)
|
||||||
|
@ -839,7 +838,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
RegCloseKey(media);
|
RegCloseKey(media);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
|
||||||
{
|
{
|
||||||
DWORD size = (lstrlenW(szValue) + 1) * sizeof(WCHAR);
|
DWORD size = (lstrlenW(szValue) + 1) * sizeof(WCHAR);
|
||||||
rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
|
rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
|
||||||
|
@ -847,7 +846,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
rc = ERROR_UNKNOWN_PROPERTY;
|
rc = ERROR_UNKNOWN_PROPERTY;
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW))
|
else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ))
|
||||||
{
|
{
|
||||||
if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
|
if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
|
||||||
rc = ERROR_INVALID_PARAMETER;
|
rc = ERROR_INVALID_PARAMETER;
|
||||||
|
@ -1130,6 +1129,12 @@ UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
||||||
RegCloseKey(sourcekey);
|
RegCloseKey(sourcekey);
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("can't open subkey %u\n", rc);
|
||||||
|
RegCloseKey(sourcekey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
postfix = (dwOptions & MSISOURCETYPE_NETWORK) ? szBackSlash : szForwardSlash;
|
postfix = (dwOptions & MSISOURCETYPE_NETWORK) ? szBackSlash : szForwardSlash;
|
||||||
if (szSource[lstrlenW(szSource) - 1] == *postfix)
|
if (szSource[lstrlenW(szSource) - 1] == *postfix)
|
||||||
|
|
|
@ -2872,7 +2872,7 @@ static BOOL SQL_MarkPrimaryKeys( column_info **cols,
|
||||||
found = FALSE;
|
found = FALSE;
|
||||||
for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
|
for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
|
||||||
{
|
{
|
||||||
if( lstrcmpW( k->column, c->column ) )
|
if( strcmpW( k->column, c->column ) )
|
||||||
continue;
|
continue;
|
||||||
c->type |= MSITYPE_KEY;
|
c->type |= MSITYPE_KEY;
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
|
|
|
@ -950,7 +950,7 @@ static BOOL SQL_MarkPrimaryKeys( column_info **cols,
|
||||||
found = FALSE;
|
found = FALSE;
|
||||||
for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
|
for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
|
||||||
{
|
{
|
||||||
if( lstrcmpW( k->column, c->column ) )
|
if( strcmpW( k->column, c->column ) )
|
||||||
continue;
|
continue;
|
||||||
c->type |= MSITYPE_KEY;
|
c->type |= MSITYPE_KEY;
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
|
|
|
@ -58,15 +58,22 @@ struct string_table
|
||||||
UINT *sorted; /* index */
|
UINT *sorted; /* index */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static BOOL validate_codepage( UINT codepage )
|
||||||
|
{
|
||||||
|
if (codepage != CP_ACP && !IsValidCodePage( codepage ))
|
||||||
|
{
|
||||||
|
WARN("invalid codepage %u\n", codepage);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static string_table *init_stringtable( int entries, UINT codepage )
|
static string_table *init_stringtable( int entries, UINT codepage )
|
||||||
{
|
{
|
||||||
string_table *st;
|
string_table *st;
|
||||||
|
|
||||||
if (codepage != CP_ACP && !IsValidCodePage(codepage))
|
if (!validate_codepage( codepage ))
|
||||||
{
|
|
||||||
ERR("invalid codepage %d\n", codepage);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
st = msi_alloc( sizeof (string_table) );
|
st = msi_alloc( sizeof (string_table) );
|
||||||
if( !st )
|
if( !st )
|
||||||
|
@ -162,7 +169,7 @@ static int find_insert_index( const string_table *st, UINT string_id )
|
||||||
while (low <= high)
|
while (low <= high)
|
||||||
{
|
{
|
||||||
i = (low + high) / 2;
|
i = (low + high) / 2;
|
||||||
c = lstrcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str );
|
c = strcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str );
|
||||||
|
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
high = i - 1;
|
high = i - 1;
|
||||||
|
@ -402,7 +409,7 @@ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id )
|
||||||
while (low <= high)
|
while (low <= high)
|
||||||
{
|
{
|
||||||
i = (low + high) / 2;
|
i = (low + high) / 2;
|
||||||
c = lstrcmpW( str, st->strings[st->sorted[i]].str );
|
c = strcmpW( str, st->strings[st->sorted[i]].str );
|
||||||
|
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
high = i - 1;
|
high = i - 1;
|
||||||
|
@ -671,3 +678,18 @@ err:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT msi_get_string_table_codepage( const string_table *st )
|
||||||
|
{
|
||||||
|
return st->codepage;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT msi_set_string_table_codepage( string_table *st, UINT codepage )
|
||||||
|
{
|
||||||
|
if (validate_codepage( codepage ))
|
||||||
|
{
|
||||||
|
st->codepage = codepage;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ LPWSTR encode_streamname(BOOL bTable, LPCWSTR in)
|
||||||
|
|
||||||
if( !bTable )
|
if( !bTable )
|
||||||
count = lstrlenW( in )+2;
|
count = lstrlenW( in )+2;
|
||||||
out = msi_alloc( count*sizeof(WCHAR) );
|
if (!(out = msi_alloc( count*sizeof(WCHAR) ))) return NULL;
|
||||||
p = out;
|
p = out;
|
||||||
|
|
||||||
if( bTable )
|
if( bTable )
|
||||||
|
@ -512,7 +512,7 @@ static MSITABLE *find_cached_table( MSIDATABASE *db, LPCWSTR name )
|
||||||
MSITABLE *t;
|
MSITABLE *t;
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( t, &db->tables, MSITABLE, entry )
|
LIST_FOR_EACH_ENTRY( t, &db->tables, MSITABLE, entry )
|
||||||
if( !lstrcmpW( name, t->name ) )
|
if( !strcmpW( name, t->name ) )
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -731,7 +731,7 @@ static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
|
||||||
table->persistent = MSICONDITION_TRUE;
|
table->persistent = MSICONDITION_TRUE;
|
||||||
lstrcpyW( table->name, name );
|
lstrcpyW( table->name, name );
|
||||||
|
|
||||||
if ( !lstrcmpW(name, szTables) || !lstrcmpW(name, szColumns) )
|
if ( !strcmpW( name, szTables ) || !strcmpW( name, szColumns ) )
|
||||||
table->persistent = MSICONDITION_NONE;
|
table->persistent = MSICONDITION_NONE;
|
||||||
|
|
||||||
r = table_get_column_info( db, name, &table->colinfo, &table->col_count);
|
r = table_get_column_info( db, name, &table->colinfo, &table->col_count);
|
||||||
|
@ -766,7 +766,8 @@ static UINT read_table_int(BYTE *const *data, UINT row, UINT col, UINT bytes)
|
||||||
static UINT save_table( MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref )
|
static UINT save_table( MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref )
|
||||||
{
|
{
|
||||||
BYTE *rawdata = NULL;
|
BYTE *rawdata = NULL;
|
||||||
UINT rawsize, r, i, j, row_size, row_count;
|
UINT rawsize, i, j, row_size, row_count;
|
||||||
|
UINT r = ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
/* Nothing to do for non-persistent tables */
|
/* Nothing to do for non-persistent tables */
|
||||||
if( t->persistent == MSICONDITION_FALSE )
|
if( t->persistent == MSICONDITION_FALSE )
|
||||||
|
@ -816,7 +817,6 @@ static UINT save_table( MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strre
|
||||||
if (id > 1 << bytes_per_strref * 8)
|
if (id > 1 << bytes_per_strref * 8)
|
||||||
{
|
{
|
||||||
ERR("string id %u out of range\n", id);
|
ERR("string id %u out of range\n", id);
|
||||||
r = ERROR_FUNCTION_FAILED;
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -864,12 +864,12 @@ static UINT get_defaulttablecolumns( MSIDATABASE *db, LPCWSTR name,
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_w(name));
|
TRACE("%s\n", debugstr_w(name));
|
||||||
|
|
||||||
if (!lstrcmpW( name, szTables ))
|
if (!strcmpW( name, szTables ))
|
||||||
{
|
{
|
||||||
p = _Tables_cols;
|
p = _Tables_cols;
|
||||||
n = 1;
|
n = 1;
|
||||||
}
|
}
|
||||||
else if (!lstrcmpW( name, szColumns ))
|
else if (!strcmpW( name, szColumns ))
|
||||||
{
|
{
|
||||||
p = _Columns_cols;
|
p = _Columns_cols;
|
||||||
n = 4;
|
n = 4;
|
||||||
|
@ -1037,11 +1037,8 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
|
||||||
UINT r, table_id, i;
|
UINT r, table_id, i;
|
||||||
MSITABLE *table;
|
MSITABLE *table;
|
||||||
|
|
||||||
static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0};
|
if( !strcmpW( name, szTables ) || !strcmpW( name, szColumns ) ||
|
||||||
static const WCHAR szStorages[] = {'_','S','t','o','r','a','g','e','s',0};
|
!strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) )
|
||||||
|
|
||||||
if( !lstrcmpW( name, szTables ) || !lstrcmpW( name, szColumns ) ||
|
|
||||||
!lstrcmpW( name, szStreams ) || !lstrcmpW( name, szStorages ) )
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
r = msi_string2idW( db->strings, name, &table_id );
|
r = msi_string2idW( db->strings, name, &table_id );
|
||||||
|
@ -1146,6 +1143,8 @@ static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname )
|
||||||
type = tv->columns[i].type;
|
type = tv->columns[i].type;
|
||||||
if ( type & MSITYPE_KEY )
|
if ( type & MSITYPE_KEY )
|
||||||
{
|
{
|
||||||
|
WCHAR number[0x20];
|
||||||
|
|
||||||
r = TABLE_fetch_int( view, row, i+1, &ival );
|
r = TABLE_fetch_int( view, row, i+1, &ival );
|
||||||
if ( r != ERROR_SUCCESS )
|
if ( r != ERROR_SUCCESS )
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1162,7 +1161,6 @@ static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static const WCHAR fmt[] = { '%','d',0 };
|
static const WCHAR fmt[] = { '%','d',0 };
|
||||||
WCHAR number[0x20];
|
|
||||||
UINT n = bytes_per_column( tv->db, &tv->columns[i], LONG_STR_BYTES );
|
UINT n = bytes_per_column( tv->db, &tv->columns[i], LONG_STR_BYTES );
|
||||||
|
|
||||||
switch( n )
|
switch( n )
|
||||||
|
@ -1346,11 +1344,14 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT
|
||||||
else if ( columninfo.type & MSITYPE_STRING )
|
else if ( columninfo.type & MSITYPE_STRING )
|
||||||
{
|
{
|
||||||
LPCWSTR sval = MSI_RecordGetString( rec, iField );
|
LPCWSTR sval = MSI_RecordGetString( rec, iField );
|
||||||
|
if (sval)
|
||||||
|
{
|
||||||
r = msi_string2idW(tv->db->strings, sval, pvalue);
|
r = msi_string2idW(tv->db->strings, sval, pvalue);
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
return ERROR_NOT_FOUND;
|
return ERROR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
else *pvalue = 0;
|
||||||
|
}
|
||||||
else if ( bytes_per_column( tv->db, &columninfo, LONG_STR_BYTES ) == 2 )
|
else if ( bytes_per_column( tv->db, &columninfo, LONG_STR_BYTES ) == 2 )
|
||||||
{
|
{
|
||||||
*pvalue = 0x8000 + MSI_RecordGetInteger( rec, iField );
|
*pvalue = 0x8000 + MSI_RecordGetInteger( rec, iField );
|
||||||
|
@ -1432,7 +1433,6 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
|
||||||
LPCWSTR sval = MSI_RecordGetString( rec, i + 1 );
|
LPCWSTR sval = MSI_RecordGetString( rec, i + 1 );
|
||||||
val = msi_addstringW( tv->db->strings, sval, -1, 1,
|
val = msi_addstringW( tv->db->strings, sval, -1, 1,
|
||||||
persistent ? StringPersistent : StringNonPersistent );
|
persistent ? StringPersistent : StringNonPersistent );
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1630,6 +1630,8 @@ static int compare_record( MSITABLEVIEW *tv, UINT row, MSIRECORD *rec )
|
||||||
|
|
||||||
for (i = 0; i < tv->num_cols; i++ )
|
for (i = 0; i < tv->num_cols; i++ )
|
||||||
{
|
{
|
||||||
|
if (!(tv->columns[i].type & MSITYPE_KEY)) continue;
|
||||||
|
|
||||||
r = get_table_value_from_record( tv, rec, i + 1, &ivalue );
|
r = get_table_value_from_record( tv, rec, i + 1, &ivalue );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1774,6 +1776,9 @@ static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
|
||||||
if (row != new_row + 1)
|
if (row != new_row + 1)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
if(tv->order)
|
||||||
|
new_row = tv->order->reorder[new_row];
|
||||||
|
|
||||||
return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1);
|
return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2099,7 +2104,7 @@ static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number
|
||||||
msitable = find_cached_table(tv->db, table);
|
msitable = find_cached_table(tv->db, table);
|
||||||
for (i = 0; i < msitable->col_count; i++)
|
for (i = 0; i < msitable->col_count; i++)
|
||||||
{
|
{
|
||||||
if (!lstrcmpW(msitable->colinfo[i].colname, column))
|
if (!strcmpW( msitable->colinfo[i].colname, column ))
|
||||||
{
|
{
|
||||||
InterlockedIncrement(&msitable->colinfo[i].ref_count);
|
InterlockedIncrement(&msitable->colinfo[i].ref_count);
|
||||||
break;
|
break;
|
||||||
|
@ -2340,14 +2345,11 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
|
||||||
MSITABLEVIEW *tv ;
|
MSITABLEVIEW *tv ;
|
||||||
UINT r, sz;
|
UINT r, sz;
|
||||||
|
|
||||||
static const WCHAR Streams[] = {'_','S','t','r','e','a','m','s',0};
|
|
||||||
static const WCHAR Storages[] = {'_','S','t','o','r','a','g','e','s',0};
|
|
||||||
|
|
||||||
TRACE("%p %s %p\n", db, debugstr_w(name), view );
|
TRACE("%p %s %p\n", db, debugstr_w(name), view );
|
||||||
|
|
||||||
if ( !lstrcmpW( name, Streams ) )
|
if ( !strcmpW( name, szStreams ) )
|
||||||
return STREAMS_CreateView( db, view );
|
return STREAMS_CreateView( db, view );
|
||||||
else if ( !lstrcmpW( name, Storages ) )
|
else if ( !strcmpW( name, szStorages ) )
|
||||||
return STORAGES_CreateView( db, view );
|
return STORAGES_CreateView( db, view );
|
||||||
|
|
||||||
sz = sizeof *tv + lstrlenW(name)*sizeof name[0] ;
|
sz = sizeof *tv + lstrlenW(name)*sizeof name[0] ;
|
||||||
|
@ -2593,7 +2595,7 @@ static void dump_record( MSIRECORD *rec )
|
||||||
n = MSI_RecordGetFieldCount( rec );
|
n = MSI_RecordGetFieldCount( rec );
|
||||||
for( i=1; i<=n; i++ )
|
for( i=1; i<=n; i++ )
|
||||||
{
|
{
|
||||||
LPCWSTR sval = MSI_RecordGetString( rec, i );
|
LPCWSTR sval;
|
||||||
|
|
||||||
if( MSI_RecordIsNull( rec, i ) )
|
if( MSI_RecordIsNull( rec, i ) )
|
||||||
TRACE("row -> []\n");
|
TRACE("row -> []\n");
|
||||||
|
@ -2634,16 +2636,20 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
|
||||||
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||||
{
|
{
|
||||||
str = MSI_RecordGetString( rec, i+1 );
|
str = MSI_RecordGetString( rec, i+1 );
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
r = msi_string2idW( tv->db->strings, str, &data[i] );
|
r = msi_string2idW( tv->db->strings, str, &data[i] );
|
||||||
|
|
||||||
/* if there's no matching string in the string table,
|
/* if there's no matching string in the string table,
|
||||||
these keys can't match any record, so fail now. */
|
these keys can't match any record, so fail now. */
|
||||||
if( ERROR_SUCCESS != r )
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
msi_free( data );
|
msi_free( data );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else data[i] = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data[i] = MSI_RecordGetInteger( rec, i+1 );
|
data[i] = MSI_RecordGetInteger( rec, i+1 );
|
||||||
|
@ -2818,7 +2824,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
||||||
UINT number = MSI_NULL_INTEGER;
|
UINT number = MSI_NULL_INTEGER;
|
||||||
UINT row = 0;
|
UINT row = 0;
|
||||||
|
|
||||||
if (!lstrcmpW( name, szColumns ))
|
if (!strcmpW( name, szColumns ))
|
||||||
{
|
{
|
||||||
MSI_RecordGetStringW( rec, 1, table, &sz );
|
MSI_RecordGetStringW( rec, 1, table, &sz );
|
||||||
number = MSI_RecordGetInteger( rec, 2 );
|
number = MSI_RecordGetInteger( rec, 2 );
|
||||||
|
@ -2830,7 +2836,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
||||||
if ( number == MSI_NULL_INTEGER )
|
if ( number == MSI_NULL_INTEGER )
|
||||||
{
|
{
|
||||||
/* reset the column number on a new table */
|
/* reset the column number on a new table */
|
||||||
if (lstrcmpW( coltable, table ))
|
if (strcmpW( coltable, table ))
|
||||||
{
|
{
|
||||||
colcol = 0;
|
colcol = 0;
|
||||||
lstrcpyW( coltable, table );
|
lstrcpyW( coltable, table );
|
||||||
|
@ -2876,7 +2882,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
||||||
WARN("failed to insert row %u\n", r);
|
WARN("failed to insert row %u\n", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (number != MSI_NULL_INTEGER && !lstrcmpW( name, szColumns ))
|
if (number != MSI_NULL_INTEGER && !strcmpW( name, szColumns ))
|
||||||
msi_update_table_columns( db, table );
|
msi_update_table_columns( db, table );
|
||||||
|
|
||||||
msiobj_release( &rec->hdr );
|
msiobj_release( &rec->hdr );
|
||||||
|
@ -2938,8 +2944,8 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
|
||||||
if ( name[0] != 0x4840 )
|
if ( name[0] != 0x4840 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( !lstrcmpW( name+1, szStringPool ) ||
|
if ( !strcmpW( name+1, szStringPool ) ||
|
||||||
!lstrcmpW( name+1, szStringData ) )
|
!strcmpW( name+1, szStringData ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
transform = msi_alloc_zero( sizeof(TRANSFORMDATA) );
|
transform = msi_alloc_zero( sizeof(TRANSFORMDATA) );
|
||||||
|
@ -2950,9 +2956,9 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
|
||||||
|
|
||||||
transform->name = strdupW( name + 1 );
|
transform->name = strdupW( name + 1 );
|
||||||
|
|
||||||
if ( !lstrcmpW( transform->name, szTables ) )
|
if ( !strcmpW( transform->name, szTables ) )
|
||||||
tables = transform;
|
tables = transform;
|
||||||
else if (!lstrcmpW( transform->name, szColumns ) )
|
else if (!strcmpW( transform->name, szColumns ) )
|
||||||
columns = transform;
|
columns = transform;
|
||||||
|
|
||||||
TRACE("transform contains stream %s\n", debugstr_w(name));
|
TRACE("transform contains stream %s\n", debugstr_w(name));
|
||||||
|
@ -2990,8 +2996,8 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
|
||||||
{
|
{
|
||||||
transform = LIST_ENTRY( list_head( &transforms ), TRANSFORMDATA, entry );
|
transform = LIST_ENTRY( list_head( &transforms ), TRANSFORMDATA, entry );
|
||||||
|
|
||||||
if ( lstrcmpW( transform->name, szColumns ) &&
|
if ( strcmpW( transform->name, szColumns ) &&
|
||||||
lstrcmpW( transform->name, szTables ) &&
|
strcmpW( transform->name, szTables ) &&
|
||||||
ret == ERROR_SUCCESS )
|
ret == ERROR_SUCCESS )
|
||||||
{
|
{
|
||||||
ret = msi_table_load_transform( db, stg, strings, transform, bytes_per_strref );
|
ret = msi_table_load_transform( db, stg, strings, transform, bytes_per_strref );
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
#include "msi.h"
|
#include "msi.h"
|
||||||
#include "msiquery.h"
|
#include "msiquery.h"
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
|
@ -306,7 +307,7 @@ static UINT STRCMP_Evaluate( MSIWHEREVIEW *wv, UINT row, const struct expr *cond
|
||||||
else if( r_str && ! l_str )
|
else if( r_str && ! l_str )
|
||||||
sr = -1;
|
sr = -1;
|
||||||
else
|
else
|
||||||
sr = lstrcmpW( l_str, r_str );
|
sr = strcmpW( l_str, r_str );
|
||||||
|
|
||||||
*val = ( cond->u.expr.op == OP_EQ && ( sr == 0 ) ) ||
|
*val = ( cond->u.expr.op == OP_EQ && ( sr == 0 ) ) ||
|
||||||
( cond->u.expr.op == OP_NE && ( sr != 0 ) );
|
( cond->u.expr.op == OP_NE && ( sr != 0 ) );
|
||||||
|
@ -327,11 +328,15 @@ static UINT WHERE_evaluate( MSIWHEREVIEW *wv, UINT row,
|
||||||
{
|
{
|
||||||
case EXPR_COL_NUMBER:
|
case EXPR_COL_NUMBER:
|
||||||
r = wv->table->ops->fetch_int( wv->table, row, cond->u.col_number, &tval );
|
r = wv->table->ops->fetch_int( wv->table, row, cond->u.col_number, &tval );
|
||||||
|
if( r != ERROR_SUCCESS )
|
||||||
|
return r;
|
||||||
*val = tval - 0x8000;
|
*val = tval - 0x8000;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
case EXPR_COL_NUMBER32:
|
case EXPR_COL_NUMBER32:
|
||||||
r = wv->table->ops->fetch_int( wv->table, row, cond->u.col_number, &tval );
|
r = wv->table->ops->fetch_int( wv->table, row, cond->u.col_number, &tval );
|
||||||
|
if( r != ERROR_SUCCESS )
|
||||||
|
return r;
|
||||||
*val = tval - 0x80000000;
|
*val = tval - 0x80000000;
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue