mirror of
https://github.com/reactos/reactos.git
synced 2024-12-30 19:14:31 +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);
|
||||
/* FIXME: byte-order dependent? */
|
||||
*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
|
||||
|
@ -796,8 +796,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
|
|||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
|
||||
lstrcmpW(findData.cFileName, szDot) &&
|
||||
lstrcmpW(findData.cFileName, szDotDot))
|
||||
strcmpW( findData.cFileName, szDot ) &&
|
||||
strcmpW( findData.cFileName, szDotDot ))
|
||||
{
|
||||
lstrcpyW(subpath, dir);
|
||||
PathAppendW(subpath, findData.cFileName);
|
||||
|
@ -808,8 +808,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
|
|||
while (rc == ERROR_SUCCESS && !*appValue &&
|
||||
FindNextFileW(hFind, &findData) != 0)
|
||||
{
|
||||
if (!lstrcmpW(findData.cFileName, szDot) ||
|
||||
!lstrcmpW(findData.cFileName, szDotDot))
|
||||
if (!strcmpW( findData.cFileName, szDot ) ||
|
||||
!strcmpW( findData.cFileName, szDotDot ))
|
||||
continue;
|
||||
|
||||
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 */
|
||||
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);
|
||||
return appid;
|
||||
|
@ -192,7 +192,7 @@ static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
|
|||
/* check for progids already loaded */
|
||||
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 );
|
||||
return progid;
|
||||
|
@ -323,7 +323,7 @@ static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid)
|
|||
/* check for classes already loaded */
|
||||
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);
|
||||
return cls;
|
||||
|
@ -384,7 +384,7 @@ static MSIMIME *load_given_mime( MSIPACKAGE *package, LPCWSTR mime )
|
|||
/* check for mime already loaded */
|
||||
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);
|
||||
return mt;
|
||||
|
@ -458,7 +458,7 @@ static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR name )
|
|||
/* check for extensions already loaded */
|
||||
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);
|
||||
return ext;
|
||||
|
@ -578,7 +578,7 @@ static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
|
|||
|
||||
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
||||
{
|
||||
if (strcmpiW(extension,ext->Extension))
|
||||
if (strcmpiW(extension, ext->Extension))
|
||||
continue;
|
||||
if (comp == ext->Component)
|
||||
{
|
||||
|
@ -850,8 +850,7 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
|
|||
}
|
||||
feature->Action = feature->ActionRequest;
|
||||
|
||||
file = get_loaded_file( package, comp->KeyPath );
|
||||
if (!file)
|
||||
if (!comp->KeyPath || !(file = get_loaded_file( package, comp->KeyPath )))
|
||||
{
|
||||
TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
|
||||
continue;
|
||||
|
|
|
@ -2323,26 +2323,36 @@ static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
|
|||
switch (operator)
|
||||
{
|
||||
case COND_SS:
|
||||
return strstrW( a, b ) ? 1 : 0;
|
||||
return strstrW( a, b ) != 0;
|
||||
case COND_ISS:
|
||||
return strstriW( a, b ) ? 1 : 0;
|
||||
return strstriW( a, b ) != 0;
|
||||
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:
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
int l = strlenW( a );
|
||||
int r = strlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpW( a + (l - r), b );
|
||||
return !strncmpW( a + (l - r), b, r );
|
||||
}
|
||||
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:
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
int l = strlenW( a );
|
||||
int r = strlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpiW( a + (l - r), b );
|
||||
return !strncmpiW( a + (l - r), b, r );
|
||||
}
|
||||
default:
|
||||
ERR("invalid substring operator\n");
|
||||
|
@ -2367,29 +2377,29 @@ static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert )
|
|||
switch (operator)
|
||||
{
|
||||
case COND_LT:
|
||||
return -1 == lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) < 0;
|
||||
case COND_GT:
|
||||
return 1 == lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) > 0;
|
||||
case COND_EQ:
|
||||
return 0 == lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) == 0;
|
||||
case COND_NE:
|
||||
return 0 != lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) != 0;
|
||||
case COND_GE:
|
||||
return -1 != lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) >= 0;
|
||||
case COND_LE:
|
||||
return 1 != lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) <= 0;
|
||||
case COND_ILT:
|
||||
return -1 == lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) < 0;
|
||||
case COND_IGT:
|
||||
return 1 == lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) > 0;
|
||||
case COND_IEQ:
|
||||
return 0 == lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) == 0;
|
||||
case COND_INE:
|
||||
return 0 != lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) != 0;
|
||||
case COND_IGE:
|
||||
return -1 != lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) >= 0;
|
||||
case COND_ILE:
|
||||
return 1 != lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) <= 0;
|
||||
default:
|
||||
ERR("invalid string operator\n");
|
||||
return 0;
|
||||
|
|
|
@ -456,26 +456,36 @@ static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
|
|||
switch (operator)
|
||||
{
|
||||
case COND_SS:
|
||||
return strstrW( a, b ) ? 1 : 0;
|
||||
return strstrW( a, b ) != 0;
|
||||
case COND_ISS:
|
||||
return strstriW( a, b ) ? 1 : 0;
|
||||
return strstriW( a, b ) != 0;
|
||||
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:
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
int l = strlenW( a );
|
||||
int r = strlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpW( a + (l - r), b );
|
||||
return !strncmpW( a + (l - r), b, r );
|
||||
}
|
||||
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:
|
||||
{
|
||||
int l = lstrlenW( a );
|
||||
int r = lstrlenW( b );
|
||||
int l = strlenW( a );
|
||||
int r = strlenW( b );
|
||||
if (r > l) return 0;
|
||||
return 0 == lstrcmpiW( a + (l - r), b );
|
||||
return !strncmpiW( a + (l - r), b, r );
|
||||
}
|
||||
default:
|
||||
ERR("invalid substring operator\n");
|
||||
|
@ -500,29 +510,29 @@ static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert )
|
|||
switch (operator)
|
||||
{
|
||||
case COND_LT:
|
||||
return -1 == lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) < 0;
|
||||
case COND_GT:
|
||||
return 1 == lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) > 0;
|
||||
case COND_EQ:
|
||||
return 0 == lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) == 0;
|
||||
case COND_NE:
|
||||
return 0 != lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) != 0;
|
||||
case COND_GE:
|
||||
return -1 != lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) >= 0;
|
||||
case COND_LE:
|
||||
return 1 != lstrcmpW( a, b );
|
||||
return strcmpW( a, b ) <= 0;
|
||||
case COND_ILT:
|
||||
return -1 == lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) < 0;
|
||||
case COND_IGT:
|
||||
return 1 == lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) > 0;
|
||||
case COND_IEQ:
|
||||
return 0 == lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) == 0;
|
||||
case COND_INE:
|
||||
return 0 != lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) != 0;
|
||||
case COND_IGE:
|
||||
return -1 != lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) >= 0;
|
||||
case COND_ILE:
|
||||
return 1 != lstrcmpiW( a, b );
|
||||
return strcmpiW( a, b ) <= 0;
|
||||
default:
|
||||
ERR("invalid string operator\n");
|
||||
return 0;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "msi.h"
|
||||
#include "msiquery.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 */
|
||||
for( c1 = col_info; c1; c1 = c1->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_SUCCESS;
|
||||
|
|
|
@ -236,7 +236,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
|||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
@ -274,6 +274,12 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
|
|||
|
||||
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))
|
||||
{
|
||||
|
@ -355,60 +361,88 @@ end:
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static UINT store_binary_to_temp(MSIPACKAGE *package, LPCWSTR source,
|
||||
LPWSTR tmp_file)
|
||||
static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||
'`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
|
||||
'`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
|
||||
MSIRECORD *row = 0;
|
||||
MSIRECORD *row;
|
||||
MSIBINARY *binary;
|
||||
HANDLE file;
|
||||
CHAR buffer[1024];
|
||||
WCHAR fmt[MAX_PATH];
|
||||
DWORD sz = MAX_PATH;
|
||||
WCHAR fmt[MAX_PATH], tmpfile[MAX_PATH];
|
||||
DWORD sz = MAX_PATH, write;
|
||||
UINT r;
|
||||
|
||||
if (msi_get_property(package->db, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
|
||||
GetTempPathW(MAX_PATH, fmt);
|
||||
|
||||
if (GetTempFileNameW(fmt, szMsi, 0, tmp_file) == 0)
|
||||
if (!GetTempFileNameW( fmt, szMsi, 0, tmpfile ))
|
||||
{
|
||||
TRACE("Unable to create file\n");
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
TRACE("unable to create temp file %s (%u)\n", debugstr_w(tmpfile), GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
track_tempfile(package, tmp_file);
|
||||
|
||||
row = MSI_QueryGetRecord(package->db, query, source);
|
||||
if (!row)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
return NULL;
|
||||
|
||||
/* write out the file */
|
||||
file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
else
|
||||
if (!(binary = msi_alloc_zero( sizeof(MSIBINARY) )))
|
||||
{
|
||||
do
|
||||
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
|
||||
{
|
||||
sz = sizeof(buffer);
|
||||
r = MSI_RecordReadStream( row, 2, buffer, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
DWORD write;
|
||||
sz = sizeof buffer;
|
||||
r = MSI_RecordReadStream(row, 2, buffer, &sz);
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("Failed to get stream\n");
|
||||
break;
|
||||
}
|
||||
WriteFile(file, buffer, sz, &write, NULL);
|
||||
} while (sz == sizeof buffer);
|
||||
CloseHandle(file);
|
||||
ERR("Failed to get stream\n");
|
||||
break;
|
||||
}
|
||||
WriteFile( file, buffer, sz, &write, NULL );
|
||||
} while (sz == sizeof buffer);
|
||||
|
||||
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,
|
||||
|
@ -594,7 +628,7 @@ static void handle_msi_break( LPCWSTR target )
|
|||
if( !GetEnvironmentVariableW( MsiBreak, val, MAX_PATH ))
|
||||
return;
|
||||
|
||||
if( lstrcmpiW( val, target ))
|
||||
if( strcmpiW( val, target ))
|
||||
return;
|
||||
|
||||
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;
|
||||
HRESULT r;
|
||||
|
||||
r = DllGetClassObject( &CLSID_IWineMsiRemoteCustomAction,
|
||||
r = DllGetClassObject( &CLSID_WineMsiRemoteCustomAction,
|
||||
&IID_IClassFactory, (LPVOID *)&cf );
|
||||
if (FAILED(r))
|
||||
{
|
||||
|
@ -683,8 +717,8 @@ static DWORD ACTION_CallDllFunction( const GUID *guid )
|
|||
hModule = LoadLibraryW( dll );
|
||||
if (!hModule)
|
||||
{
|
||||
ERR("failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
|
||||
return r;
|
||||
WARN( "failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
proc = strdupWtoA( function );
|
||||
|
@ -875,20 +909,15 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
|
|||
LPCWSTR target, const INT type, LPCWSTR action)
|
||||
{
|
||||
msi_custom_action_info *info;
|
||||
WCHAR tmp_file[MAX_PATH];
|
||||
MSIBINARY *binary;
|
||||
UINT r;
|
||||
|
||||
r = store_binary_to_temp(package, source, tmp_file);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
if (!(binary = get_temp_binary( package, source, TRUE )))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
TRACE("Calling function %s from %s\n",debugstr_w(target),
|
||||
debugstr_w(tmp_file));
|
||||
TRACE("Calling function %s from %s\n", debugstr_w(target), debugstr_w(binary->tmpfile));
|
||||
|
||||
if (!strchrW(tmp_file,'.'))
|
||||
strcatW(tmp_file, szDot);
|
||||
|
||||
info = do_msidbCustomActionTypeDll( package, type, tmp_file, target, action );
|
||||
info = do_msidbCustomActionTypeDll( package, type, binary->tmpfile, target, action );
|
||||
|
||||
r = wait_thread_handle( 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,
|
||||
LPCWSTR target, const INT type, LPCWSTR action)
|
||||
{
|
||||
WCHAR tmp_file[MAX_PATH];
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION info;
|
||||
BOOL rc;
|
||||
|
@ -906,29 +934,27 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
|
|||
WCHAR *deformated = NULL;
|
||||
WCHAR *cmd;
|
||||
static const WCHAR spc[] = {' ',0};
|
||||
MSIBINARY *binary;
|
||||
UINT r;
|
||||
|
||||
memset(&si,0,sizeof(STARTUPINFOW));
|
||||
|
||||
r = store_binary_to_temp(package, source, tmp_file);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
if (!(binary = get_temp_binary( package, source, FALSE )))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
deformat_string(package,target,&deformated);
|
||||
|
||||
len = strlenW(tmp_file)+2;
|
||||
|
||||
len = strlenW( binary->tmpfile ) + 2;
|
||||
if (deformated)
|
||||
len += strlenW(deformated);
|
||||
|
||||
cmd = msi_alloc(sizeof(WCHAR)*len);
|
||||
|
||||
strcpyW(cmd,tmp_file);
|
||||
strcpyW( cmd, binary->tmpfile );
|
||||
if (deformated)
|
||||
{
|
||||
strcatW(cmd,spc);
|
||||
strcatW(cmd,deformated);
|
||||
|
||||
msi_free(deformated);
|
||||
}
|
||||
|
||||
|
@ -1121,8 +1147,7 @@ static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
|
|||
|
||||
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)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
|
@ -1161,13 +1186,13 @@ static DWORD ACTION_CallScript( const GUID *guid )
|
|||
{
|
||||
msi_custom_action_info *info;
|
||||
MSIHANDLE hPackage;
|
||||
UINT r = ERROR_FUNCTION_FAILED;
|
||||
UINT r;
|
||||
|
||||
info = find_action_by_guid( guid );
|
||||
if (!info)
|
||||
{
|
||||
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 ) );
|
||||
|
@ -1176,13 +1201,13 @@ static DWORD ACTION_CallScript( const GUID *guid )
|
|||
if (hPackage)
|
||||
{
|
||||
r = call_script( hPackage, info->type, info->source, info->target, info->action );
|
||||
TRACE("script returned %u\n", r);
|
||||
MsiCloseHandle( hPackage );
|
||||
}
|
||||
else
|
||||
ERR("failed to create handle for %p\n", info->package );
|
||||
|
||||
release_custom_action_data( info );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -1433,13 +1458,13 @@ void ACTION_FinishCustomActions(const MSIPACKAGE* package)
|
|||
}
|
||||
|
||||
typedef struct _msi_custom_remote_impl {
|
||||
const IWineMsiRemoteCustomActionVtbl *lpVtbl;
|
||||
IWineMsiRemoteCustomAction IWineMsiRemoteCustomAction_iface;
|
||||
LONG refs;
|
||||
} 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,
|
||||
|
@ -1458,14 +1483,14 @@ static HRESULT WINAPI mcr_QueryInterface( 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 );
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
r = InterlockedDecrement( &This->refs );
|
||||
|
@ -1508,7 +1533,7 @@ HRESULT create_msi_custom_remote( IUnknown *pOuter, LPVOID *ppObj )
|
|||
if (!This)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
This->lpVtbl = &msi_custom_remote_vtbl;
|
||||
This->IWineMsiRemoteCustomAction_iface.lpVtbl = &msi_custom_remote_vtbl;
|
||||
This->refs = 1;
|
||||
|
||||
*ppObj = This;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
|
@ -79,7 +80,7 @@ static UINT find_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm )
|
|||
continue;
|
||||
}
|
||||
|
||||
if( !lstrcmpW( name, stat.pwcsName ) )
|
||||
if( !strcmpW( name, stat.pwcsName ) )
|
||||
{
|
||||
TRACE("found %s\n", debugstr_w(name));
|
||||
*stm = stream->stm;
|
||||
|
@ -888,6 +889,8 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
|
||||
static const WCHAR suminfo[] =
|
||||
{'_','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) );
|
||||
|
||||
|
@ -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, &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)
|
||||
{
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
|
@ -1087,13 +1097,13 @@ static UINT msi_export_row( MSIRECORD *row, void *arg )
|
|||
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;
|
||||
|
||||
static const char data[] = "\r\n\r\n0\t_ForceCodepage\r\n";
|
||||
|
||||
FIXME("Read the codepage from the strings table!\n");
|
||||
sprintf( data, fmt, codepage );
|
||||
|
||||
sz = lstrlenA(data) + 1;
|
||||
if (!WriteFile(handle, data, sz, &sz, NULL))
|
||||
|
@ -1136,9 +1146,10 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
|||
if (handle == INVALID_HANDLE_VALUE)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1319,7 +1330,7 @@ static BOOL merge_type_match(LPCWSTR type1, LPCWSTR type2)
|
|||
((type2[0] == 'L') || (type2[0] == 'S')))
|
||||
return TRUE;
|
||||
|
||||
return !lstrcmpW(type1, type2);
|
||||
return !strcmpW( type1, type2 );
|
||||
}
|
||||
|
||||
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))
|
||||
break;
|
||||
|
||||
if (lstrcmpW(MSI_RecordGetString(dbrec, i),
|
||||
MSI_RecordGetString(mergerec, i)))
|
||||
if (strcmpW( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
|
||||
{
|
||||
r = ERROR_DATATYPE_MISMATCH;
|
||||
goto done;
|
||||
|
@ -1405,8 +1415,7 @@ static UINT merge_verify_primary_keys(MSIDATABASE *db, MSIDATABASE *mergedb,
|
|||
|
||||
for (i = 1; i <= count; i++)
|
||||
{
|
||||
if (lstrcmpW(MSI_RecordGetString(dbrec, i),
|
||||
MSI_RecordGetString(mergerec, i)))
|
||||
if (strcmpW( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
|
||||
{
|
||||
r = ERROR_DATATYPE_MISMATCH;
|
||||
goto done;
|
||||
|
@ -1434,7 +1443,7 @@ static LPWSTR get_key_value(MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
|
|||
do
|
||||
{
|
||||
str = msi_dup_record_field(colnames, ++i);
|
||||
cmp = lstrcmpW(key, str);
|
||||
cmp = strcmpW( key, str );
|
||||
msi_free(str);
|
||||
} while (cmp);
|
||||
|
||||
|
@ -2029,14 +2038,14 @@ MSIDBSTATE WINAPI MsiGetDatabaseState( MSIHANDLE handle )
|
|||
}
|
||||
|
||||
typedef struct _msi_remote_database_impl {
|
||||
const IWineMsiRemoteDatabaseVtbl *lpVtbl;
|
||||
IWineMsiRemoteDatabase IWineMsiRemoteDatabase_iface;
|
||||
MSIHANDLE database;
|
||||
LONG refs;
|
||||
} 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,
|
||||
|
@ -2055,14 +2064,14 @@ static HRESULT WINAPI mrd_QueryInterface( 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 );
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
r = InterlockedDecrement( &This->refs );
|
||||
|
@ -2077,7 +2086,7 @@ static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface )
|
|||
static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
||||
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);
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -2085,7 +2094,7 @@ static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface,
|
|||
static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
@ -2093,7 +2102,7 @@ static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface,
|
|||
static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
@ -2101,14 +2110,14 @@ static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface,
|
|||
static HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface,
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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;
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -2133,7 +2142,7 @@ HRESULT create_msi_remote_database( IUnknown *pOuter, LPVOID *ppObj )
|
|||
if (!This)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
This->lpVtbl = &msi_remote_database_vtbl;
|
||||
This->IWineMsiRemoteDatabase_iface.lpVtbl = &msi_remote_database_vtbl;
|
||||
This->database = 0;
|
||||
This->refs = 1;
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ struct msi_control_tag
|
|||
|
||||
typedef struct msi_font_tag
|
||||
{
|
||||
struct msi_font_tag *next;
|
||||
struct list entry;
|
||||
HFONT hfont;
|
||||
COLORREF color;
|
||||
WCHAR name[1];
|
||||
|
@ -90,7 +90,7 @@ struct msi_dialog_tag
|
|||
SIZE size;
|
||||
HWND hwnd;
|
||||
LPWSTR default_font;
|
||||
msi_font *font_list;
|
||||
struct list fonts;
|
||||
struct list controls;
|
||||
HWND hWndFocus;
|
||||
LPWSTR control_default;
|
||||
|
@ -310,8 +310,7 @@ static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param )
|
|||
name = MSI_RecordGetString( rec, 1 );
|
||||
font = msi_alloc( sizeof *font + strlenW( name )*sizeof (WCHAR) );
|
||||
strcpyW( font->name, name );
|
||||
font->next = dialog->font_list;
|
||||
dialog->font_list = font;
|
||||
list_add_head( &dialog->fonts, &font->entry );
|
||||
|
||||
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 )
|
||||
{
|
||||
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? */
|
||||
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 )
|
||||
{
|
||||
if ( !lstrcmpW( control->property, property ) && control->update )
|
||||
if ( control->property && !strcmpW( control->property, property ) && control->update )
|
||||
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 );
|
||||
if (!ctrl)
|
||||
return;
|
||||
if( !lstrcmpW(attribute, szText) )
|
||||
if( !strcmpW( attribute, szText ) )
|
||||
{
|
||||
font_text = MSI_RecordGetString( rec , 1 );
|
||||
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_dialog_check_messages( NULL );
|
||||
}
|
||||
else if( !lstrcmpW(attribute, szProgress) )
|
||||
else if( !strcmpW( attribute, szProgress ) )
|
||||
{
|
||||
DWORD func, val;
|
||||
|
||||
|
@ -640,12 +639,12 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if ( !lstrcmpW(attribute, szProperty) )
|
||||
else if ( !strcmpW( attribute, szProperty ) )
|
||||
{
|
||||
MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
|
||||
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 path;
|
||||
|
@ -1368,7 +1367,7 @@ static void msi_dialog_combobox_update( msi_dialog *dialog,
|
|||
for (j = 0; j < info->num_items; j++)
|
||||
{
|
||||
tmp = (LPWSTR) SendMessageW( control->hwnd, CB_GETITEMDATA, j, 0 );
|
||||
if (!lstrcmpW( value, tmp ))
|
||||
if (!strcmpW( value, tmp ))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1743,7 +1742,7 @@ static UINT msi_dialog_maskedit_control( msi_dialog *dialog, MSIRECORD *rec )
|
|||
font = msi_dialog_get_style( font_mask, &mask );
|
||||
if( !mask )
|
||||
{
|
||||
ERR("mask template is empty\n");
|
||||
WARN("mask template is empty\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -1988,7 +1987,7 @@ static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param )
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
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);
|
||||
|
||||
prop = MSI_RecordGetString( rec, 1 );
|
||||
|
@ -2126,9 +2125,9 @@ static void
|
|||
msi_seltree_update_feature_installstate( HWND hwnd, HTREEITEM hItem,
|
||||
MSIPACKAGE *package, MSIFEATURE *feature, INSTALLSTATE state )
|
||||
{
|
||||
msi_feature_set_state( package, feature, state );
|
||||
feature->ActionRequest = state;
|
||||
msi_seltree_sync_item_state( hwnd, feature, hItem );
|
||||
ACTION_UpdateComponentStates( package, feature->Feature );
|
||||
ACTION_UpdateComponentStates( package, feature );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2258,7 +2257,11 @@ msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
|
|||
|
||||
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;
|
||||
|
||||
if ( !feature->Title )
|
||||
|
@ -2373,14 +2376,19 @@ static UINT msi_dialog_seltree_handler( msi_dialog *dialog,
|
|||
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionDescription, rec );
|
||||
|
||||
dir = MSI_RecordGetString( row, 7 );
|
||||
folder = get_loaded_folder( dialog->package, dir );
|
||||
if (!folder)
|
||||
if (dir)
|
||||
{
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
goto done;
|
||||
folder = get_loaded_folder( dialog->package, dir );
|
||||
if (!folder)
|
||||
{
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
goto done;
|
||||
}
|
||||
MSI_RecordSetStringW( rec, 1, folder->ResolvedTarget );
|
||||
}
|
||||
else
|
||||
MSI_RecordSetStringW( rec, 1, NULL );
|
||||
|
||||
MSI_RecordSetStringW( rec, 1, folder->ResolvedTarget );
|
||||
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionPath, rec );
|
||||
|
||||
done:
|
||||
|
@ -2682,7 +2690,7 @@ static void msi_dialog_update_directory_list( msi_dialog *dialog, msi_control *c
|
|||
if ( wfd.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY )
|
||||
continue;
|
||||
|
||||
if ( !lstrcmpW( wfd.cFileName, szDot ) || !lstrcmpW( wfd.cFileName, szDotDot ) )
|
||||
if ( !strcmpW( wfd.cFileName, szDot ) || !strcmpW( wfd.cFileName, szDotDot ) )
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
/* empty braces or '0' hides the column */
|
||||
if ( !num[0] || !lstrcmpW( num, szZero ) )
|
||||
if ( !num[0] || !strcmpW( num, szZero ) )
|
||||
{
|
||||
count++;
|
||||
msi_free( num );
|
||||
|
@ -3151,15 +3159,15 @@ static UINT msi_dialog_set_control_condition( MSIRECORD *rec, LPVOID param )
|
|||
TRACE("%s control %s\n", debugstr_w(action), debugstr_w(name));
|
||||
|
||||
/* FIXME: case sensitive? */
|
||||
if(!lstrcmpW(action, szHide))
|
||||
if (!strcmpW( action, szHide ))
|
||||
ShowWindow(control->hwnd, SW_HIDE);
|
||||
else if(!strcmpW(action, szShow))
|
||||
else if (!strcmpW( action, szShow ))
|
||||
ShowWindow(control->hwnd, SW_SHOW);
|
||||
else if(!strcmpW(action, szDisable))
|
||||
else if (!strcmpW( action, szDisable ))
|
||||
EnableWindow(control->hwnd, FALSE);
|
||||
else if(!strcmpW(action, szEnable))
|
||||
else if (!strcmpW( action, szEnable ))
|
||||
EnableWindow(control->hwnd, TRUE);
|
||||
else if(!strcmpW(action, szDefault))
|
||||
else if (!strcmpW( action, szDefault ))
|
||||
SetFocus(control->hwnd);
|
||||
else
|
||||
FIXME("Unhandled action %s\n", debugstr_w(action));
|
||||
|
@ -3844,6 +3852,7 @@ msi_dialog *msi_dialog_create( MSIPACKAGE* package,
|
|||
dialog->event_handler = event_handler;
|
||||
dialog->finished = 0;
|
||||
list_init( &dialog->controls );
|
||||
list_init( &dialog->fonts );
|
||||
|
||||
/* verify that the dialog exists */
|
||||
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 )
|
||||
{
|
||||
msi_font *font, *next;
|
||||
|
||||
if( uiThreadId != GetCurrentThreadId() )
|
||||
{
|
||||
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 */
|
||||
while( dialog->font_list )
|
||||
LIST_FOR_EACH_ENTRY_SAFE( font, next, &dialog->fonts, msi_font, entry )
|
||||
{
|
||||
msi_font *t = dialog->font_list;
|
||||
dialog->font_list = t->next;
|
||||
DeleteObject( t->hfont );
|
||||
msi_free( t );
|
||||
list_remove( &font->entry );
|
||||
DeleteObject( font->hfont );
|
||||
msi_free( 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
|
||||
};
|
||||
|
||||
if ( lstrcmpW( event, end_dialog ) )
|
||||
if ( strcmpW( event, end_dialog ) )
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if ( !lstrcmpW( argument, error_abort ) || !lstrcmpW( argument, error_cancel ) ||
|
||||
!lstrcmpW( argument, error_no ) )
|
||||
if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) ||
|
||||
!strcmpW( argument, error_no ) )
|
||||
{
|
||||
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)
|
||||
r = ERROR_SUCCESS;
|
||||
|
||||
if ( !lstrcmpW( result, error_abort ) )
|
||||
if ( !strcmpW( result, error_abort ) )
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
|
||||
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,
|
||||
msi_dialog* dialog)
|
||||
{
|
||||
static const WCHAR szExit[] = {
|
||||
'E','x','i','t',0};
|
||||
static const WCHAR szRetry[] = {
|
||||
'R','e','t','r','y',0};
|
||||
static const WCHAR szIgnore[] = {
|
||||
'I','g','n','o','r','e',0};
|
||||
static const WCHAR szReturn[] = {
|
||||
'R','e','t','u','r','n',0};
|
||||
static const WCHAR szExit[] = {'E','x','i','t',0};
|
||||
static const WCHAR szRetry[] = {'R','e','t','r','y',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;
|
||||
else if (lstrcmpW(argument, szRetry) == 0)
|
||||
else if (!strcmpW( argument, szRetry ))
|
||||
package->CurrentInstallState = ERROR_INSTALL_SUSPEND;
|
||||
else if (lstrcmpW(argument, szIgnore) == 0)
|
||||
else if (!strcmpW( argument, szIgnore ))
|
||||
package->CurrentInstallState = ERROR_SUCCESS;
|
||||
else if (lstrcmpW(argument, szReturn) == 0)
|
||||
else if (!strcmpW( argument, szReturn ))
|
||||
{
|
||||
msi_dialog *parent = msi_dialog_get_parent(dialog);
|
||||
msi_free(package->next_dialog);
|
||||
|
@ -167,58 +163,50 @@ static UINT ControlEvent_DoAction(MSIPACKAGE* package, LPCWSTR argument,
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,
|
||||
msi_dialog* dialog)
|
||||
static UINT ControlEvent_AddLocal( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog )
|
||||
{
|
||||
MSIFEATURE *feature = NULL;
|
||||
MSIFEATURE *feature;
|
||||
|
||||
if (lstrcmpW(szAll,argument))
|
||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||
{
|
||||
MSI_SetFeatureStateW(package,argument,INSTALLSTATE_LOCAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||
msi_feature_set_state(package, feature, INSTALLSTATE_LOCAL);
|
||||
|
||||
ACTION_UpdateComponentStates(package,argument);
|
||||
if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
|
||||
{
|
||||
if (feature->ActionRequest != INSTALLSTATE_LOCAL)
|
||||
msi_set_property( package->db, szPreselected, szOne );
|
||||
MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_LOCAL );
|
||||
}
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument,
|
||||
msi_dialog* dialog)
|
||||
static UINT ControlEvent_Remove( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog )
|
||||
{
|
||||
MSIFEATURE *feature = NULL;
|
||||
MSIFEATURE *feature;
|
||||
|
||||
if (lstrcmpW(szAll,argument))
|
||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||
{
|
||||
MSI_SetFeatureStateW(package,argument,INSTALLSTATE_ABSENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||
msi_feature_set_state(package, feature, INSTALLSTATE_ABSENT);
|
||||
|
||||
ACTION_UpdateComponentStates(package,argument);
|
||||
if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
|
||||
{
|
||||
if (feature->ActionRequest != INSTALLSTATE_ABSENT)
|
||||
msi_set_property( package->db, szPreselected, szOne );
|
||||
MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_ABSENT );
|
||||
}
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument,
|
||||
msi_dialog* dialog)
|
||||
static UINT ControlEvent_AddSource( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog )
|
||||
{
|
||||
MSIFEATURE *feature = NULL;
|
||||
MSIFEATURE *feature;
|
||||
|
||||
if (lstrcmpW(szAll,argument))
|
||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||
{
|
||||
MSI_SetFeatureStateW(package,argument,INSTALLSTATE_SOURCE);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -284,10 +272,9 @@ VOID ControlEvent_FireSubscribedEvent( MSIPACKAGE *package, LPCWSTR event,
|
|||
|
||||
LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry )
|
||||
{
|
||||
if (lstrcmpiW(sub->event, event))
|
||||
if (strcmpiW( sub->event, event ))
|
||||
continue;
|
||||
msi_dialog_handle_event( sub->dialog, sub->control,
|
||||
sub->attribute, rec );
|
||||
msi_dialog_handle_event( sub->dialog, sub->control, sub->attribute, rec );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +287,7 @@ VOID ControlEvent_CleanupDialogSubscriptions(MSIPACKAGE *package, LPWSTR dialog)
|
|||
{
|
||||
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;
|
||||
|
||||
list_remove( &sub->entry );
|
||||
|
@ -441,7 +428,7 @@ UINT ControlEvent_HandleControlEvent(MSIPACKAGE *package, LPCWSTR event,
|
|||
while( Events[i].event != NULL)
|
||||
{
|
||||
LPWSTR wevent = strdupAtoW(Events[i].event);
|
||||
if (lstrcmpW(wevent,event)==0)
|
||||
if (!strcmpW( wevent, event ))
|
||||
{
|
||||
msi_free(wevent);
|
||||
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 );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
MSIFILE *file;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(file, &package->files, MSIFILE, entry)
|
||||
{
|
||||
if (file->Component->ActionRequest != INSTALLSTATE_LOCAL || !file->Component->Enabled)
|
||||
{
|
||||
TRACE("File %s is not scheduled for install\n", debugstr_w(file->File));
|
||||
MSICOMPONENT *comp = file->Component;
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
file->Component->Action = INSTALLSTATE_LOCAL;
|
||||
comp->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;
|
||||
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)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
|
@ -178,7 +255,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
|||
f = get_loaded_file(package, file);
|
||||
if (!f)
|
||||
{
|
||||
WARN("unknown file in cabinet (%s)\n", debugstr_w(file));
|
||||
TRACE("unknown file in cabinet (%s)\n", debugstr_w(file));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -186,8 +263,10 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
|||
return FALSE;
|
||||
|
||||
msi_file_update_ui(package, f, szInstallFiles);
|
||||
msi_create_directory(package, f->Component->Directory);
|
||||
|
||||
if (!f->Component->assembly || f->Component->assembly->application)
|
||||
{
|
||||
msi_create_directory(package, f->Component->Directory);
|
||||
}
|
||||
*path = strdupW(f->TargetPath);
|
||||
*attrs = f->Attributes;
|
||||
}
|
||||
|
@ -210,6 +289,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
|||
UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||
{
|
||||
MSIMEDIAINFO *mi;
|
||||
MSICOMPONENT *comp;
|
||||
UINT rc = ERROR_SUCCESS;
|
||||
MSIFILE *file;
|
||||
|
||||
|
@ -222,6 +302,20 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
|
||||
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)
|
||||
continue;
|
||||
|
||||
|
@ -230,13 +324,6 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
{
|
||||
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.package = package;
|
||||
data.cb = installfiles_cb;
|
||||
|
@ -247,7 +334,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
{
|
||||
ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
|
||||
rc = ERROR_INSTALL_FAILURE;
|
||||
break;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,12 +342,13 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
{
|
||||
LPWSTR source = resolve_file_source(package, file);
|
||||
|
||||
TRACE("file paths %s to %s\n", debugstr_w(source),
|
||||
debugstr_w(file->TargetPath));
|
||||
TRACE("copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
|
||||
|
||||
msi_file_update_ui(package, file, szInstallFiles);
|
||||
msi_create_directory(package, file->Component->Directory);
|
||||
|
||||
if (!file->Component->assembly || file->Component->assembly->application)
|
||||
{
|
||||
msi_create_directory(package, file->Component->Directory);
|
||||
}
|
||||
rc = copy_install_file(package, file, source);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
|
@ -268,19 +356,33 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
debugstr_w(file->TargetPath), rc);
|
||||
rc = ERROR_INSTALL_FAILURE;
|
||||
msi_free(source);
|
||||
break;
|
||||
goto done;
|
||||
}
|
||||
|
||||
msi_free(source);
|
||||
}
|
||||
else if (file->state != msifs_installed)
|
||||
{
|
||||
ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->TargetPath));
|
||||
rc = ERROR_INSTALL_FAILURE;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
msi_free_media_info(mi);
|
||||
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)
|
||||
{
|
||||
if (lstrcmpW(source, file->source) < 0)
|
||||
if (strcmpW( source, file->source ) < 0)
|
||||
{
|
||||
list_add_before(&file->entry, &new->entry);
|
||||
return TRUE;
|
||||
|
@ -663,7 +765,7 @@ static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const
|
|||
{
|
||||
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)
|
||||
{
|
||||
/* try a property */
|
||||
|
@ -861,25 +963,25 @@ static BOOL verify_comp_for_removal(MSICOMPONENT *comp, UINT install_mode)
|
|||
{
|
||||
INSTALLSTATE request = comp->ActionRequest;
|
||||
|
||||
if (request == INSTALLSTATE_UNKNOWN)
|
||||
return FALSE;
|
||||
/* special case */
|
||||
if (request != INSTALLSTATE_SOURCE &&
|
||||
comp->Attributes & msidbComponentAttributesSourceOnly &&
|
||||
(install_mode == msidbRemoveFileInstallModeOnRemove ||
|
||||
install_mode == msidbRemoveFileInstallModeOnBoth)) return TRUE;
|
||||
|
||||
if (install_mode == msidbRemoveFileInstallModeOnInstall &&
|
||||
(request == INSTALLSTATE_LOCAL || request == INSTALLSTATE_SOURCE))
|
||||
return TRUE;
|
||||
|
||||
if (request == INSTALLSTATE_ABSENT)
|
||||
switch (request)
|
||||
{
|
||||
if (!comp->ComponentId)
|
||||
return FALSE;
|
||||
|
||||
if (install_mode == msidbRemoveFileInstallModeOnRemove)
|
||||
return TRUE;
|
||||
case INSTALLSTATE_LOCAL:
|
||||
case INSTALLSTATE_SOURCE:
|
||||
if (install_mode == msidbRemoveFileInstallModeOnInstall ||
|
||||
install_mode == msidbRemoveFileInstallModeOnBoth) 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;
|
||||
}
|
||||
|
||||
|
@ -888,24 +990,17 @@ static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
|
|||
MSIPACKAGE *package = param;
|
||||
MSICOMPONENT *comp;
|
||||
MSIRECORD *uirow;
|
||||
LPCWSTR component, filename, dirprop;
|
||||
LPCWSTR component, dirprop;
|
||||
UINT install_mode;
|
||||
LPWSTR dir = NULL, path = NULL;
|
||||
LPWSTR dir = NULL, path = NULL, filename = NULL;
|
||||
DWORD size;
|
||||
UINT ret = ERROR_SUCCESS;
|
||||
|
||||
component = MSI_RecordGetString(row, 2);
|
||||
filename = MSI_RecordGetString(row, 3);
|
||||
dirprop = MSI_RecordGetString(row, 4);
|
||||
install_mode = MSI_RecordGetInteger(row, 5);
|
||||
|
||||
comp = get_loaded_component(package, component);
|
||||
if (!comp)
|
||||
{
|
||||
ERR("Invalid component: %s\n", debugstr_w(component));
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
if (!comp->Enabled)
|
||||
{
|
||||
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))
|
||||
{
|
||||
TRACE("Skipping removal due to missing conditions\n");
|
||||
TRACE("Skipping removal due to install mode\n");
|
||||
comp->Action = comp->Installed;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
if (comp->Attributes & msidbComponentAttributesPermanent)
|
||||
{
|
||||
TRACE("permanent component, not removing file\n");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
dir = msi_dup_property(package->db, dirprop);
|
||||
if (!dir)
|
||||
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;
|
||||
path = msi_alloc(size * sizeof(WCHAR));
|
||||
if (!path)
|
||||
|
@ -954,11 +1060,39 @@ done:
|
|||
ui_actiondata( package, szRemoveFiles, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
msi_free(filename);
|
||||
msi_free(path);
|
||||
msi_free(dir);
|
||||
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 )
|
||||
{
|
||||
MSIQUERY *view;
|
||||
|
@ -968,9 +1102,6 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
|||
static const WCHAR query[] = {
|
||||
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||
'`','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);
|
||||
if (r == ERROR_SUCCESS)
|
||||
|
@ -979,10 +1110,6 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
|||
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 )
|
||||
{
|
||||
MSIRECORD *uirow;
|
||||
|
@ -1002,6 +1129,12 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
|||
continue;
|
||||
}
|
||||
|
||||
if (file->Component->Attributes & msidbComponentAttributesPermanent)
|
||||
{
|
||||
TRACE("permanent component, not removing file\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file->Version)
|
||||
{
|
||||
ver = msi_get_disk_file_version( file->TargetPath );
|
||||
|
@ -1015,16 +1148,20 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
|||
}
|
||||
|
||||
TRACE("removing %s\n", debugstr_w(file->File) );
|
||||
|
||||
SetFileAttributesW( file->TargetPath, FILE_ATTRIBUTE_NORMAL );
|
||||
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 (r && (dir = strdupW( file->TargetPath )))
|
||||
else if (!has_persistent_dir( package, file->Component ))
|
||||
{
|
||||
if ((p = strrchrW( dir, '\\' ))) *p = 0;
|
||||
RemoveDirectoryW( dir );
|
||||
msi_free( dir );
|
||||
if ((dir = strdupW( file->TargetPath )))
|
||||
{
|
||||
if ((p = strrchrW( dir, '\\' ))) *p = 0;
|
||||
RemoveDirectoryW( dir );
|
||||
msi_free( dir );
|
||||
}
|
||||
}
|
||||
file->state = msifs_missing;
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ typedef struct _tagTT_NAME_TABLE_HEADER {
|
|||
* from start of the table */
|
||||
} TT_NAME_TABLE_HEADER;
|
||||
|
||||
#define NAME_ID_FULL_FONT_NAME 4
|
||||
#define NAME_ID_VERSION 5
|
||||
|
||||
typedef struct _tagTT_NAME_RECORD {
|
||||
USHORT uPlatformID;
|
||||
USHORT uEncodingID;
|
||||
|
@ -80,10 +83,8 @@ static const WCHAR regfont2[] =
|
|||
/*
|
||||
* Code based off of code located here
|
||||
* 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;
|
||||
BOOL bFound = FALSE;
|
||||
|
@ -142,30 +143,24 @@ static LPWSTR load_ttfname_from(LPCWSTR filename)
|
|||
break;
|
||||
|
||||
ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
|
||||
/* 4 is the Full Font Name */
|
||||
if(ttRecord.uNameID == 4)
|
||||
if (ttRecord.uNameID == id)
|
||||
{
|
||||
int nPos;
|
||||
LPSTR buf;
|
||||
static const char tt[] = " (TrueType)";
|
||||
|
||||
ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
|
||||
ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
|
||||
nPos = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
|
||||
SetFilePointer(handle, tblDir.uOffset +
|
||||
ttRecord.uStringOffset +
|
||||
ttNTHeader.uStorageOffset,
|
||||
NULL, FILE_BEGIN);
|
||||
buf = msi_alloc_zero( ttRecord.uStringLength + 1 + strlen(tt) );
|
||||
SetFilePointer(handle, tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset,
|
||||
NULL, FILE_BEGIN);
|
||||
buf = msi_alloc_zero( ttRecord.uStringLength + 1 );
|
||||
ReadFile(handle, buf, ttRecord.uStringLength, &dwRead, NULL);
|
||||
if (strlen(buf) > 0)
|
||||
{
|
||||
strcat(buf,tt);
|
||||
ret = strdupAtoW(buf);
|
||||
msi_free(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
msi_free(buf);
|
||||
SetFilePointer(handle,nPos, NULL, FILE_BEGIN);
|
||||
}
|
||||
|
@ -173,8 +168,36 @@ static LPWSTR load_ttfname_from(LPCWSTR filename)
|
|||
|
||||
end:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -212,7 +235,7 @@ static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
|
|||
RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2);
|
||||
|
||||
if (MSI_RecordIsNull(row,2))
|
||||
name = load_ttfname_from( file->TargetPath );
|
||||
name = font_name_from_file( file->TargetPath );
|
||||
else
|
||||
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 );
|
||||
|
||||
if (MSI_RecordIsNull( row, 2 ))
|
||||
name = load_ttfname_from( file->TargetPath );
|
||||
name = font_name_from_file( file->TargetPath );
|
||||
else
|
||||
name = msi_dup_record_field( row, 2 );
|
||||
|
||||
|
|
|
@ -185,7 +185,6 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
|
|||
{
|
||||
LPWSTR key, ret = NULL;
|
||||
MSICOMPONENT *comp;
|
||||
BOOL source;
|
||||
|
||||
key = msi_alloc((str->len + 1) * sizeof(WCHAR));
|
||||
lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
|
||||
|
@ -194,8 +193,10 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
|
|||
if (!comp)
|
||||
goto done;
|
||||
|
||||
source = (comp->Action == INSTALLSTATE_SOURCE) ? TRUE : FALSE;
|
||||
ret = resolve_folder(format->package, comp->Directory, source, FALSE, TRUE, NULL);
|
||||
if (comp->Action == INSTALLSTATE_SOURCE)
|
||||
ret = resolve_source_folder( format->package, comp->Directory, NULL );
|
||||
else
|
||||
ret = resolve_target_folder( format->package, comp->Directory, FALSE, TRUE, NULL );
|
||||
|
||||
done:
|
||||
msi_free(key);
|
||||
|
|
|
@ -104,7 +104,7 @@ MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component )
|
|||
|
||||
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
|
||||
{
|
||||
if (lstrcmpW(Component,comp->Component)==0)
|
||||
if (!strcmpW( Component, comp->Component ))
|
||||
return comp;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -116,7 +116,7 @@ MSIFEATURE* get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
|
|||
|
||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||
{
|
||||
if (lstrcmpW( Feature, feature->Feature )==0)
|
||||
if (!strcmpW( Feature, feature->Feature ))
|
||||
return feature;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -128,7 +128,7 @@ MSIFILE* get_loaded_file( MSIPACKAGE* package, LPCWSTR key )
|
|||
|
||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||
{
|
||||
if (lstrcmpW( key, file->File )==0)
|
||||
if (!strcmpW( key, file->File ))
|
||||
return file;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -141,7 +141,7 @@ int track_tempfile( MSIPACKAGE *package, LPCWSTR path )
|
|||
TRACE("%s\n", debugstr_w(path));
|
||||
|
||||
LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
|
||||
if (!lstrcmpW( path, temp->Path ))
|
||||
if (!strcmpW( path, temp->Path ))
|
||||
return 0;
|
||||
|
||||
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 )
|
||||
{
|
||||
if (lstrcmpW( dir, folder->Directory )==0)
|
||||
if (!strcmpW( dir, folder->Directory ))
|
||||
return folder;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -232,8 +232,7 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
|
|||
if (file->IsCompressed)
|
||||
return NULL;
|
||||
|
||||
p = resolve_folder(package, file->Component->Directory,
|
||||
TRUE, FALSE, TRUE, NULL);
|
||||
p = resolve_source_folder( package, file->Component->Directory, NULL );
|
||||
path = build_directory_name(2, p, file->ShortName);
|
||||
|
||||
if (file->LongName &&
|
||||
|
@ -245,24 +244,18 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
|
|||
|
||||
msi_free(p);
|
||||
|
||||
TRACE("file %s source resolves to %s\n", debugstr_w(file->File),
|
||||
debugstr_w(path));
|
||||
|
||||
TRACE("file %s source resolves to %s\n", debugstr_w(file->File), debugstr_w(path));
|
||||
return path;
|
||||
}
|
||||
|
||||
LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
||||
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder)
|
||||
LPWSTR resolve_source_folder( MSIPACKAGE *package, LPCWSTR name, MSIFOLDER **folder )
|
||||
{
|
||||
MSIFOLDER *f;
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
if (!lstrcmpW(name,cszSourceDir))
|
||||
if (!strcmpW( name, cszSourceDir ))
|
||||
name = cszTargetDir;
|
||||
|
||||
f = get_loaded_folder( package, name );
|
||||
|
@ -270,7 +263,58 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
|||
return NULL;
|
||||
|
||||
/* special resolving for Target and Source root dir */
|
||||
if (!strcmpW(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 );
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
/* special resolving for Target and Source root dir */
|
||||
if (!strcmpW( name, cszTargetDir ))
|
||||
{
|
||||
if (!f->ResolvedTarget && !f->Property)
|
||||
{
|
||||
|
@ -286,45 +330,33 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
|||
/* correct misbuilt target dir */
|
||||
path = build_directory_name(2, check_path, NULL);
|
||||
clean_spaces_from_path( path );
|
||||
if (strcmpiW(path,check_path)!=0)
|
||||
if (strcmpiW( path, check_path ))
|
||||
msi_set_property( package->db, cszTargetDir, path );
|
||||
msi_free(check_path);
|
||||
|
||||
f->ResolvedTarget = path;
|
||||
}
|
||||
|
||||
if (!f->ResolvedSource)
|
||||
f->ResolvedSource = get_source_root( package );
|
||||
}
|
||||
|
||||
if (folder)
|
||||
*folder = f;
|
||||
|
||||
if (!source && f->ResolvedTarget)
|
||||
if (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;
|
||||
}
|
||||
|
||||
if (source && f->ResolvedSource)
|
||||
{
|
||||
path = strdupW( f->ResolvedSource );
|
||||
TRACE(" (source)already resolved to %s\n",debugstr_w(path));
|
||||
return path;
|
||||
}
|
||||
|
||||
if (!source && f->Property)
|
||||
if (f->Property)
|
||||
{
|
||||
path = build_directory_name( 2, f->Property, NULL );
|
||||
|
||||
TRACE(" internally set to %s\n",debugstr_w(path));
|
||||
if (set_prop)
|
||||
msi_set_property( package->db, name, path );
|
||||
TRACE(" internally set to %s\n", debugstr_w(path));
|
||||
if (set_prop) msi_set_property( package->db, name, 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 );
|
||||
TRACE(" property set to %s\n", debugstr_w(path));
|
||||
|
@ -336,35 +368,18 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
|||
|
||||
parent = f->Parent;
|
||||
|
||||
TRACE(" ! Parent is %s\n", debugstr_w(parent));
|
||||
TRACE(" ! parent is %s\n", debugstr_w(parent));
|
||||
|
||||
p = resolve_folder(package, parent, source, set_prop, load_prop, NULL);
|
||||
if (!source)
|
||||
{
|
||||
TRACE(" TargetDefault = %s\n", debugstr_w(f->TargetDefault));
|
||||
p = resolve_target_folder( package, parent, set_prop, load_prop, NULL );
|
||||
|
||||
path = build_directory_name( 3, p, f->TargetDefault, NULL );
|
||||
clean_spaces_from_path( 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;
|
||||
TRACE(" TargetDefault = %s\n", debugstr_w(f->TargetDefault));
|
||||
path = build_directory_name( 3, p, f->TargetDefault, NULL );
|
||||
clean_spaces_from_path( path );
|
||||
f->ResolvedTarget = strdupW( path );
|
||||
|
||||
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("source -> %s\n", debugstr_w(path));
|
||||
f->ResolvedSource = strdupW( path );
|
||||
}
|
||||
msi_free(p);
|
||||
TRACE("-> %s\n", debugstr_w(path));
|
||||
if (set_prop) msi_set_property( package->db, name, path );
|
||||
msi_free( p );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@ -479,6 +494,8 @@ LPWSTR build_directory_name(DWORD count, ...)
|
|||
if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
|
||||
strcatW(dir, szBackSlash);
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
@ -561,7 +578,7 @@ void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
|
|||
MSIRECORD * row = 0;
|
||||
DWORD size;
|
||||
|
||||
if (!package->LastAction || strcmpW(package->LastAction,action))
|
||||
if (!package->LastAction || strcmpW(package->LastAction, action))
|
||||
{
|
||||
row = MSI_QueryGetRecord(package->db, Query_t, action);
|
||||
if (!row)
|
||||
|
@ -639,16 +656,11 @@ LPWSTR create_component_advertise_string(MSIPACKAGE* package,
|
|||
}
|
||||
|
||||
/* update component state based on a feature change */
|
||||
void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
||||
void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
|
||||
{
|
||||
INSTALLSTATE newstate;
|
||||
MSIFEATURE *feature;
|
||||
ComponentList *cl;
|
||||
|
||||
feature = get_loaded_feature(package,szFeature);
|
||||
if (!feature)
|
||||
return;
|
||||
|
||||
newstate = feature->ActionRequest;
|
||||
|
||||
if (newstate == INSTALLSTATE_ABSENT)
|
||||
|
@ -658,15 +670,17 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
|||
{
|
||||
MSICOMPONENT* component = cl->component;
|
||||
|
||||
if (!component->Enabled) continue;
|
||||
|
||||
TRACE("MODIFYING(%i): Component %s (Installed %i, Action %i, Request %i)\n",
|
||||
newstate, debugstr_w(component->Component), component->Installed,
|
||||
component->Action, component->ActionRequest);
|
||||
|
||||
if (!component->Enabled)
|
||||
continue;
|
||||
|
||||
if (newstate == INSTALLSTATE_LOCAL)
|
||||
msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ComponentList *clist;
|
||||
|
@ -674,9 +688,10 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
|||
|
||||
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 )
|
||||
{
|
||||
if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
|
||||
|
@ -697,14 +712,26 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
|
|||
if (component->Attributes & msidbComponentAttributesOptional)
|
||||
{
|
||||
if (f->Attributes & msidbFeatureAttributesFavorSource)
|
||||
msi_component_set_state(package, component, INSTALLSTATE_SOURCE);
|
||||
{
|
||||
component->Action = INSTALLSTATE_SOURCE;
|
||||
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||
}
|
||||
else
|
||||
msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
}
|
||||
else if (component->Attributes & msidbComponentAttributesSourceOnly)
|
||||
msi_component_set_state(package, component, INSTALLSTATE_SOURCE);
|
||||
{
|
||||
component->Action = INSTALLSTATE_SOURCE;
|
||||
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||
}
|
||||
else
|
||||
msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -747,7 +774,7 @@ BOOL check_unique_action(const MSIPACKAGE *package, LPCWSTR action)
|
|||
return FALSE;
|
||||
|
||||
for (i = 0; i < package->script->UniqueActionsCount; i++)
|
||||
if (!strcmpW(package->script->UniqueActions[i],action))
|
||||
if (!strcmpW(package->script->UniqueActions[i], action))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "msi.h"
|
||||
#include "msiquery.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->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(b);
|
||||
|
||||
|
@ -168,7 +169,7 @@ static UINT msi_arrange_record(MSIINSERTVIEW *iv, MSIRECORD **values)
|
|||
if (r != ERROR_SUCCESS)
|
||||
goto err;
|
||||
|
||||
res = lstrcmpW(a, b);
|
||||
res = strcmpW( a, b );
|
||||
msi_free(b);
|
||||
|
||||
if (res == 0)
|
||||
|
|
|
@ -282,7 +282,7 @@ done:
|
|||
return r;
|
||||
}
|
||||
|
||||
path = resolve_folder( package, szFolder, FALSE, FALSE, TRUE, NULL );
|
||||
path = resolve_target_folder( package, szFolder, FALSE, TRUE, NULL );
|
||||
msiobj_release( &package->hdr );
|
||||
|
||||
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,
|
||||
awstring *szPathBuf, LPDWORD pcchPathBuf )
|
||||
|
@ -413,10 +413,10 @@ done:
|
|||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
path = resolve_folder(package, szFolder, TRUE, FALSE, TRUE, NULL);
|
||||
path = resolve_source_folder( package, szFolder, NULL );
|
||||
msiobj_release( &package->hdr );
|
||||
|
||||
TRACE("path = %s\n",debugstr_w(path));
|
||||
TRACE("path = %s\n", debugstr_w(path));
|
||||
if (!path)
|
||||
return ERROR_DIRECTORY;
|
||||
|
||||
|
@ -512,14 +512,14 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
|
|||
attrib & FILE_ATTRIBUTE_READONLY))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
path = resolve_folder(package,szFolder,FALSE,FALSE,FALSE,&folder);
|
||||
path = resolve_target_folder( package, szFolder, FALSE, FALSE, &folder );
|
||||
if (!path)
|
||||
return ERROR_DIRECTORY;
|
||||
|
||||
msi_free(folder->Property);
|
||||
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
|
||||
|
@ -527,7 +527,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
|
|||
*/
|
||||
msi_free(folder->ResolvedTarget);
|
||||
folder->ResolvedTarget = NULL;
|
||||
path2 = resolve_folder(package,szFolder,FALSE,TRUE,FALSE,NULL);
|
||||
path2 = resolve_target_folder( package, szFolder, TRUE, FALSE, NULL );
|
||||
msi_free(path2);
|
||||
}
|
||||
else
|
||||
|
@ -542,23 +542,23 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||
{
|
||||
MSICOMPONENT *comp = file->Component;
|
||||
LPWSTR p;
|
||||
LPWSTR dir;
|
||||
|
||||
if (!comp)
|
||||
if (!comp->Enabled || (comp->assembly && !comp->assembly->application))
|
||||
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);
|
||||
|
||||
file->TargetPath = build_directory_name(2, p, file->FileName);
|
||||
msi_free(p);
|
||||
file->TargetPath = build_directory_name(2, dir, file->FileName);
|
||||
msi_free(dir);
|
||||
}
|
||||
}
|
||||
msi_free(path);
|
||||
|
@ -716,6 +716,10 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
|
|||
r = package->need_reboot;
|
||||
break;
|
||||
|
||||
case MSIRUNMODE_LOGENABLED:
|
||||
r = (package->log_file != INVALID_HANDLE_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME("unimplemented run mode: %d\n", iRunMode);
|
||||
r = TRUE;
|
||||
|
@ -821,14 +825,14 @@ UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
|
|||
feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -917,9 +921,9 @@ UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
|
|||
*piInstalled = feature->Installed;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1158,7 +1162,8 @@ static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
|
|||
if (!comp)
|
||||
return ERROR_UNKNOWN_COMPONENT;
|
||||
|
||||
comp->Installed = iState;
|
||||
if (comp->Enabled)
|
||||
comp->Action = iState;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -1176,13 +1181,22 @@ UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
|
|||
return ERROR_UNKNOWN_COMPONENT;
|
||||
|
||||
if (piInstalled)
|
||||
*piInstalled = comp->Installed;
|
||||
{
|
||||
if (comp->Enabled)
|
||||
*piInstalled = comp->Installed;
|
||||
else
|
||||
*piInstalled = INSTALLSTATE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (piAction)
|
||||
*piAction = comp->Action;
|
||||
{
|
||||
if (comp->Enabled)
|
||||
*piAction = comp->Action;
|
||||
else
|
||||
*piAction = INSTALLSTATE_UNKNOWN;
|
||||
}
|
||||
|
||||
TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ static BOOL source_matches_volume(MSIMEDIAINFO *mi, LPCWSTR source_root)
|
|||
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)
|
||||
|
@ -331,7 +331,7 @@ static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint,
|
|||
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");
|
||||
goto done;
|
||||
|
@ -656,7 +656,7 @@ static UINT get_drive_type(const WCHAR *path)
|
|||
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;
|
||||
LPWSTR source_dir;
|
||||
|
@ -748,23 +748,44 @@ static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi)
|
|||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
index = 0;
|
||||
volumesz = MAX_PATH;
|
||||
promptsz = MAX_PATH;
|
||||
|
||||
if (last_type[0] == 'n')
|
||||
{
|
||||
while (MsiSourceListEnumSourcesW(package->ProductCode, NULL,
|
||||
package->Context,
|
||||
MSISOURCETYPE_NETWORK, index++,
|
||||
volume, &volumesz) == ERROR_SUCCESS)
|
||||
WCHAR cabinet_file[MAX_PATH];
|
||||
BOOL check_all = FALSE;
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
if (!strncmpiW(source, volume, strlenW(source)))
|
||||
index = 0;
|
||||
volumesz = MAX_PATH;
|
||||
while (MsiSourceListEnumSourcesW(package->ProductCode, NULL,
|
||||
package->Context,
|
||||
MSISOURCETYPE_NETWORK, index++,
|
||||
volume, &volumesz) == ERROR_SUCCESS)
|
||||
{
|
||||
lstrcpyW(mi->sourcedir, source);
|
||||
TRACE("Found network source %s\n", debugstr_w(mi->sourcedir));
|
||||
return ERROR_SUCCESS;
|
||||
if (check_all || !strncmpiW(source, volume, strlenW(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));
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_all)
|
||||
check_all = TRUE;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -803,13 +824,6 @@ UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
|||
if (mi->is_continuous)
|
||||
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 */
|
||||
if (!mi->cabinet || mi->cabinet[0] == '#')
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -841,7 +855,7 @@ UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
|||
|
||||
/* check volume matches, change media if not */
|
||||
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);
|
||||
BOOL matches;
|
||||
|
|
|
@ -299,13 +299,14 @@ done:
|
|||
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;
|
||||
UINT r, type;
|
||||
DWORD size;
|
||||
static WCHAR empty[] = {0};
|
||||
WCHAR *codes;
|
||||
WCHAR *codes = NULL;
|
||||
|
||||
r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch );
|
||||
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 );
|
||||
if (r != ERROR_SUCCESS)
|
||||
msi_free( codes );
|
||||
else
|
||||
*product_codes = codes;
|
||||
if (r == ERROR_SUCCESS)
|
||||
*product_codes = msi_split_string( codes, ';' );
|
||||
|
||||
done:
|
||||
MsiCloseHandle( info );
|
||||
MsiCloseHandle( patch );
|
||||
msi_free( codes );
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
|
||||
{
|
||||
UINT r;
|
||||
UINT r, i;
|
||||
DWORD size;
|
||||
LPCWSTR cmd_ptr = szCommandLine;
|
||||
LPWSTR beg, end, cmd, codes = NULL;
|
||||
LPWSTR cmd, *codes = NULL;
|
||||
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};
|
||||
|
||||
if (!szPatchPackage || !szPatchPackage[0])
|
||||
|
@ -363,34 +363,27 @@ static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWS
|
|||
if (!szCommandLine)
|
||||
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));
|
||||
if (!cmd)
|
||||
{
|
||||
msi_free(codes);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
lstrcpyW(cmd, cmd_ptr);
|
||||
if (szCommandLine) lstrcatW(cmd, szSpace);
|
||||
lstrcatW(cmd, patcheq);
|
||||
lstrcatW(cmd, szPatchPackage);
|
||||
sprintfW(cmd, fmt, cmd_ptr, szPatchPackage);
|
||||
|
||||
if (szProductCode)
|
||||
r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
|
||||
else
|
||||
{
|
||||
beg = codes;
|
||||
while ((end = strchrW(beg, '}')))
|
||||
for (i = 0; codes[i]; i++)
|
||||
{
|
||||
*(end + 1) = '\0';
|
||||
r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
|
||||
r = MsiConfigureProductExW(codes[i], INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
TRACE("patch applied\n");
|
||||
succeeded = TRUE;
|
||||
}
|
||||
beg = end + 2;
|
||||
}
|
||||
|
||||
if (succeeded)
|
||||
|
@ -688,6 +681,8 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
|||
|
||||
static const WCHAR szInstalled[] = {
|
||||
' ','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[] = {
|
||||
' ','R','E','M','O','V','E','=','A','L','L',0};
|
||||
static const WCHAR szMachine[] = {
|
||||
|
@ -719,6 +714,9 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
|||
if (szCommandLine)
|
||||
sz += lstrlenW(szCommandLine);
|
||||
|
||||
if (eInstallState != INSTALLSTATE_DEFAULT)
|
||||
sz += lstrlenW(szInstallLevel);
|
||||
|
||||
if (eInstallState == INSTALLSTATE_ABSENT)
|
||||
sz += lstrlenW(szRemoveAll);
|
||||
|
||||
|
@ -736,6 +734,9 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
|
|||
if (szCommandLine)
|
||||
lstrcpyW(commandline,szCommandLine);
|
||||
|
||||
if (eInstallState != INSTALLSTATE_DEFAULT)
|
||||
lstrcatW(commandline, szInstallLevel);
|
||||
|
||||
if (eInstallState == INSTALLSTATE_ABSENT)
|
||||
lstrcatW(commandline, szRemoveAll);
|
||||
|
||||
|
@ -983,22 +984,22 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
|||
|
||||
MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
|
||||
|
||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
|
||||
if (!strcmpW( szAttribute, INSTALLPROPERTY_HELPLINKW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_PUBLISHERW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_REGOWNERW ))
|
||||
{
|
||||
if (!prodkey)
|
||||
{
|
||||
|
@ -1009,25 +1010,25 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
|||
if (!userdata)
|
||||
return ERROR_UNKNOWN_PROPERTY;
|
||||
|
||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
|
||||
if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
|
||||
szAttribute = display_name;
|
||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
|
||||
else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
|
||||
szAttribute = display_version;
|
||||
|
||||
val = msi_reg_get_value(userdata, szAttribute, &type);
|
||||
if (!val)
|
||||
val = empty;
|
||||
}
|
||||
else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
|
||||
else if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_LANGUAGEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) ||
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
|
||||
{
|
||||
if (!prodkey)
|
||||
{
|
||||
|
@ -1035,10 +1036,10 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
|
||||
if (!strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
|
||||
szAttribute = assignment;
|
||||
|
||||
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
|
||||
if (!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ))
|
||||
{
|
||||
res = RegOpenKeyW(prodkey, sourcelist, &source);
|
||||
if (res != ERROR_SUCCESS)
|
||||
|
@ -1061,7 +1062,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
|
|||
}
|
||||
|
||||
if (val != empty && type != REG_DWORD &&
|
||||
!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
|
||||
!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ))
|
||||
{
|
||||
if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
|
||||
badconfig = TRUE;
|
||||
|
@ -1324,23 +1325,23 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_HELPLINKW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_PUBLISHERW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONMINORW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTIDW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_REGCOMPANYW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
|
||||
{
|
||||
val = msi_reg_get_value(props, package, &type);
|
||||
if (!val)
|
||||
|
@ -1353,9 +1354,9 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
|||
|
||||
msi_free(val);
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
|
||||
szProperty = displayname;
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
|
||||
szProperty = displayversion;
|
||||
|
||||
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);
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_LANGUAGEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_PACKAGECODEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_VERSIONW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTICONW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
|
||||
{
|
||||
if (!prod && !classes)
|
||||
goto done;
|
||||
|
@ -1389,7 +1390,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
|||
|
||||
r = msi_copy_outval(val, szValue, pcchValue);
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTSTATEW ))
|
||||
{
|
||||
if (dwContext == MSIINSTALLCONTEXT_MACHINE)
|
||||
{
|
||||
|
@ -1423,7 +1424,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
|||
|
||||
r = msi_copy_outval(val, szValue, pcchValue);
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
|
||||
{
|
||||
if (!prod && !classes)
|
||||
goto done;
|
||||
|
@ -1554,7 +1555,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
|
|||
if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (!lstrcmpW(szUserSid, szLocalSid))
|
||||
if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
|
||||
|
@ -1575,7 +1576,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
|
|||
if (res != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ))
|
||||
{
|
||||
if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
|
||||
&prod, FALSE) != ERROR_SUCCESS)
|
||||
|
@ -1594,25 +1595,25 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
|
|||
&udpatch, FALSE) != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
|
||||
{
|
||||
if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
|
||||
szProperty = szManagedPackage;
|
||||
datakey = udpatch;
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ))
|
||||
{
|
||||
datakey = patch;
|
||||
szProperty = szInstalled;
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
|
||||
{
|
||||
datakey = udpatch;
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_UNINSTALLABLEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_PATCHSTATEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_DISPLAYNAMEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_MOREINFOURLW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_PATCHSTATEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_MOREINFOURLW ))
|
||||
{
|
||||
datakey = patch;
|
||||
}
|
||||
|
@ -1766,24 +1767,26 @@ UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR 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);
|
||||
|
||||
msi_free(gszLogFile);
|
||||
gszLogFile = NULL;
|
||||
if (szLogFile)
|
||||
{
|
||||
lstrcpyW(gszLogFile,szLogFile);
|
||||
HANDLE file;
|
||||
|
||||
if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
|
||||
DeleteFileW(szLogFile);
|
||||
file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
gszLogFile = strdupW(szLogFile);
|
||||
CloseHandle(file);
|
||||
}
|
||||
else
|
||||
ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
|
||||
ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile), GetLastError());
|
||||
}
|
||||
else
|
||||
gszLogFile[0] = '\0';
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -1944,6 +1947,7 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
|
|||
*pdwState = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
|
||||
TRACE("-> %d\n", *pdwState);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1982,6 +1986,11 @@ INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
|
|||
if (lstrlenW(szProduct) != GUID_SIZE - 1)
|
||||
return INSTALLSTATE_INVALIDARG;
|
||||
|
||||
if (szProduct[0] != '{' || szProduct[37] != '}')
|
||||
return INSTALLSTATE_UNKNOWN;
|
||||
|
||||
SetLastError( ERROR_SUCCESS );
|
||||
|
||||
if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
&prodkey, FALSE) != ERROR_SUCCESS &&
|
||||
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
|
@ -2015,6 +2024,7 @@ done:
|
|||
|
||||
RegCloseKey(prodkey);
|
||||
RegCloseKey(userdata);
|
||||
TRACE("-> %d\n", state);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -2631,6 +2641,8 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
|
|||
if (!squash_guid( szProduct, squishProduct ))
|
||||
return INSTALLSTATE_INVALIDARG;
|
||||
|
||||
SetLastError( ERROR_SUCCESS );
|
||||
|
||||
if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
|
||||
&hkey, FALSE) != ERROR_SUCCESS &&
|
||||
MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
|
||||
|
@ -2711,17 +2723,17 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
|
|||
|
||||
msi_free(path);
|
||||
}
|
||||
|
||||
TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
|
||||
msi_free(components);
|
||||
|
||||
if (missing)
|
||||
return INSTALLSTATE_ADVERTISED;
|
||||
r = INSTALLSTATE_ADVERTISED;
|
||||
else if (source)
|
||||
r = INSTALLSTATE_SOURCE;
|
||||
else
|
||||
r = INSTALLSTATE_LOCAL;
|
||||
|
||||
if (source)
|
||||
return INSTALLSTATE_SOURCE;
|
||||
|
||||
return INSTALLSTATE_LOCAL;
|
||||
TRACE("-> %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
@ -3543,8 +3555,8 @@ UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
|
|||
LPWSTR ptr;
|
||||
DWORD sz;
|
||||
|
||||
FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
|
||||
dwReinstallMode);
|
||||
FIXME("%s %s 0x%08x\n",
|
||||
debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode);
|
||||
|
||||
ptr = reinstallmode;
|
||||
|
||||
|
@ -3661,8 +3673,10 @@ UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
|
|||
handle = CreateFileW( szFilePath, GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WARN("can't open file %u\n", GetLastError());
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
|
||||
}
|
||||
length = GetFileSize( handle, NULL );
|
||||
|
||||
mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
|
||||
|
@ -3771,6 +3785,31 @@ UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler,
|
|||
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.@]
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<file>action.c</file>
|
||||
<file>alter.c</file>
|
||||
<file>appsearch.c</file>
|
||||
<file>assembly.c</file>
|
||||
<file>automation.c</file>
|
||||
<file>classes.c</file>
|
||||
<file>cond.tab.c</file>
|
||||
|
|
|
@ -19,45 +19,56 @@
|
|||
*/
|
||||
|
||||
#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"
|
||||
|
||||
#include "msi_Bg.rc"
|
||||
#include "msi_Da.rc"
|
||||
#include "msi_En.rc"
|
||||
#include "msi_Es.rc"
|
||||
#include "msi_Fi.rc"
|
||||
#include "msi_Hu.rc"
|
||||
#include "msi_Ko.rc"
|
||||
#include "msi_Nl.rc"
|
||||
#include "msi_No.rc"
|
||||
#include "msi_Pl.rc"
|
||||
#include "msi_Sv.rc"
|
||||
#include "msi_Tr.rc"
|
||||
#include "msi_Uk.rc"
|
||||
#include "msi_Zh.rc"
|
||||
|
||||
/* UTF-8 */
|
||||
#include "msi_De.rc"
|
||||
#include "msi_Fr.rc"
|
||||
#include "msi_It.rc"
|
||||
#include "msi_Lt.rc"
|
||||
#include "msi_Pt.rc"
|
||||
#include "msi_Ro.rc"
|
||||
#include "msi_Ru.rc"
|
||||
#include "msi_Si.rc"
|
||||
#include "msi_Sr.rc"
|
||||
STRINGTABLE
|
||||
{
|
||||
4 "The specified installation package could not be opened. Please check the file path and try again."
|
||||
5 "path %s not found"
|
||||
9 "insert disk %s"
|
||||
10 "Windows Installer %s\n\n" \
|
||||
"Usage:\n" \
|
||||
"msiexec command {required parameter} [optional parameter]\n\n" \
|
||||
"Install a product:\n" \
|
||||
"\t/i {package|product_code} [property]\n" \
|
||||
"\t/package {package|product_code} [property]\n" \
|
||||
"\t/a package [property]\n" \
|
||||
"Repair an installation:\n" \
|
||||
"\t/f[p|o|e|d|c|a|u|m|s|v] {package|product_code}\n" \
|
||||
"Uninstall a product:\n" \
|
||||
"\t/uninstall {package|product_code} [property]\n" \
|
||||
"\t/x {package|product_code} [property]\n" \
|
||||
"Advertise a product:\n" \
|
||||
"\t/j[u|m] package [/t transform] [/g languageid]\n" \
|
||||
"Apply a patch:\n" \
|
||||
"\t/p patch_package [property]\n" \
|
||||
"\t/p patch_package /a package [property]\n" \
|
||||
"Log and UI Modifiers for above commands:\n" \
|
||||
"\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
|
||||
"\t/q{|n|b|r|f|n+|b+|b-}\n" \
|
||||
"Register MSI Service:\n" \
|
||||
"\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
|
||||
|
||||
/* @makedep: msiserver.tlb */
|
||||
1 TYPELIB msiserver.tlb
|
||||
|
||||
/* @makedep: msiserver.rgs */
|
||||
1 WINE_REGISTRY msiserver.rgs
|
||||
|
||||
/* @makedep: instadvert.bmp */
|
||||
0x1001 BITMAP instadvert.bmp
|
||||
|
||||
|
@ -66,3 +77,12 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
|
||||
/* @makedep: 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)
|
||||
81 stdcall MsiGetUserInfoA(str 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)
|
||||
85 stub MsiInstallMissingFileA
|
||||
86 stub MsiInstallMissingFileW
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
#include "winreg.h"
|
||||
#include "shlwapi.h"
|
||||
#include "oleauto.h"
|
||||
#include "rpcproxy.h"
|
||||
#include "msipriv.h"
|
||||
#include "msiserver.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -44,7 +46,7 @@ INSTALLUI_HANDLERW gUIHandlerW = NULL;
|
|||
INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
|
||||
DWORD gUIFilter = 0;
|
||||
LPVOID gUIContext = NULL;
|
||||
WCHAR gszLogFile[MAX_PATH];
|
||||
WCHAR *gszLogFile = NULL;
|
||||
HINSTANCE msi_hInstance;
|
||||
|
||||
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 );
|
||||
msi_dialog_unregister_class();
|
||||
msi_free_handle_table();
|
||||
msi_free( gszLogFile );
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -117,14 +120,19 @@ ITypeLib *get_msi_typelib( LPWSTR *path )
|
|||
}
|
||||
|
||||
typedef struct tagIClassFactoryImpl {
|
||||
const IClassFactoryVtbl *lpVtbl;
|
||||
IClassFactory IClassFactory_iface;
|
||||
HRESULT (*create_object)( IUnknown*, LPVOID* );
|
||||
} IClassFactoryImpl;
|
||||
|
||||
static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
|
||||
REFIID riid,LPVOID *ppobj)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
||||
|
||||
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,
|
||||
LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
||||
IUnknown *unk = NULL;
|
||||
HRESULT r;
|
||||
|
||||
|
@ -189,9 +197,9 @@ static const IClassFactoryVtbl MsiCF_Vtbl =
|
|||
MsiCF_LockServer
|
||||
};
|
||||
|
||||
static IClassFactoryImpl MsiServer_CF = { &MsiCF_Vtbl, create_msiserver };
|
||||
static IClassFactoryImpl WineMsiCustomRemote_CF = { &MsiCF_Vtbl, create_msi_custom_remote };
|
||||
static IClassFactoryImpl WineMsiRemotePackage_CF = { &MsiCF_Vtbl, create_msi_remote_package };
|
||||
static IClassFactoryImpl MsiServer_CF = { { &MsiCF_Vtbl }, create_msiserver };
|
||||
static IClassFactoryImpl WineMsiCustomRemote_CF = { { &MsiCF_Vtbl }, create_msi_custom_remote };
|
||||
static IClassFactoryImpl WineMsiRemotePackage_CF = { { &MsiCF_Vtbl }, create_msi_remote_package };
|
||||
|
||||
/******************************************************************
|
||||
* 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);
|
||||
|
||||
if ( IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) )
|
||||
if ( IsEqualCLSID (rclsid, &CLSID_MsiInstaller) )
|
||||
{
|
||||
*ppv = &MsiServer_CF;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if ( IsEqualCLSID (rclsid, &CLSID_IWineMsiRemoteCustomAction) )
|
||||
if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemoteCustomAction) )
|
||||
{
|
||||
*ppv = &WineMsiCustomRemote_CF;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if ( IsEqualCLSID (rclsid, &CLSID_IWineMsiRemotePackage) )
|
||||
if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemotePackage) )
|
||||
{
|
||||
*ppv = &WineMsiRemotePackage_CF;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if( IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
|
||||
IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
|
||||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
|
||||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
|
||||
if( IsEqualCLSID (rclsid, &CLSID_MsiServerMessage) ||
|
||||
IsEqualCLSID (rclsid, &CLSID_MsiServer) ||
|
||||
IsEqualCLSID (rclsid, &CLSID_PSFactoryBuffer) ||
|
||||
IsEqualCLSID (rclsid, &CLSID_MsiServerX3) )
|
||||
{
|
||||
FIXME("create %s object\n", debugstr_guid( rclsid ));
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "msidefs.h"
|
||||
#include "objbase.h"
|
||||
#include "objidl.h"
|
||||
#include "fusion.h"
|
||||
#include "winnls.h"
|
||||
#include "winver.h"
|
||||
#include "wine/list.h"
|
||||
|
@ -162,6 +163,14 @@ typedef struct tagMSIPATCHINFO
|
|||
MSIPATCHSTATE state;
|
||||
} MSIPATCHINFO;
|
||||
|
||||
typedef struct tagMSIBINARY
|
||||
{
|
||||
struct list entry;
|
||||
WCHAR *source;
|
||||
WCHAR *tmpfile;
|
||||
HMODULE module;
|
||||
} MSIBINARY;
|
||||
|
||||
typedef struct _column_info
|
||||
{
|
||||
LPCWSTR table;
|
||||
|
@ -315,6 +324,13 @@ enum platform
|
|||
PLATFORM_X64
|
||||
};
|
||||
|
||||
enum clr_version
|
||||
{
|
||||
CLR_VERSION_V11,
|
||||
CLR_VERSION_V20,
|
||||
CLR_VERSION_MAX
|
||||
};
|
||||
|
||||
typedef struct tagMSIPACKAGE
|
||||
{
|
||||
MSIOBJECTHDR hdr;
|
||||
|
@ -329,8 +345,12 @@ typedef struct tagMSIPACKAGE
|
|||
struct list files;
|
||||
struct list tempfiles;
|
||||
struct list folders;
|
||||
struct list binaries;
|
||||
LPWSTR ActionFormat;
|
||||
LPWSTR LastAction;
|
||||
HANDLE log_file;
|
||||
IAssemblyCache *cache_net[CLR_VERSION_MAX];
|
||||
IAssemblyCache *cache_sxs;
|
||||
|
||||
struct list classes;
|
||||
struct list extensions;
|
||||
|
@ -401,6 +421,18 @@ typedef struct tagMSIFEATURE
|
|||
struct list Components;
|
||||
} 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
|
||||
{
|
||||
struct list entry;
|
||||
|
@ -419,6 +451,7 @@ typedef struct tagMSICOMPONENT
|
|||
INT RefCount;
|
||||
LPWSTR FullKeypath;
|
||||
LPWSTR AdvertiseString;
|
||||
MSIASSEMBLY *assembly;
|
||||
|
||||
unsigned int anyAbsent:1;
|
||||
unsigned int hasAdvertiseFeature:1;
|
||||
|
@ -466,6 +499,7 @@ typedef enum _msi_file_state {
|
|||
msifs_present,
|
||||
msifs_installed,
|
||||
msifs_skipped,
|
||||
msifs_hashmatch
|
||||
} msi_file_state;
|
||||
|
||||
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_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 */
|
||||
typedef struct {
|
||||
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 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_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 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_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid);
|
||||
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_DeleteLocalClassesProductKey(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 VS_FIXEDFILEINFO *msi_get_disk_file_version(LPCWSTR);
|
||||
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_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
|
||||
|
@ -879,7 +910,7 @@ extern INSTALLUI_HANDLERW gUIHandlerW;
|
|||
extern INSTALLUI_HANDLER_RECORD gUIHandlerRecord;
|
||||
extern DWORD gUIFilter;
|
||||
extern LPVOID gUIContext;
|
||||
extern WCHAR gszLogFile[MAX_PATH];
|
||||
extern WCHAR *gszLogFile;
|
||||
extern HINSTANCE msi_hInstance;
|
||||
|
||||
/* 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 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 */
|
||||
extern UINT ACTION_AppSearch(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_UnregisterMIMEInfo(MSIPACKAGE *package);
|
||||
extern UINT ACTION_UnregisterProgIdInfo(MSIPACKAGE *package);
|
||||
extern UINT ACTION_MsiPublishAssemblies(MSIPACKAGE *package);
|
||||
extern UINT ACTION_MsiUnpublishAssemblies(MSIPACKAGE *package);
|
||||
|
||||
/* Helpers */
|
||||
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_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD );
|
||||
extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def );
|
||||
extern LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
||||
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder);
|
||||
extern LPWSTR resolve_source_folder(MSIPACKAGE *package, LPCWSTR name, 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 void msi_reset_folders( MSIPACKAGE *package, BOOL source );
|
||||
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 void reduce_to_longfilename(WCHAR*);
|
||||
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 BOOL check_unique_action(const MSIPACKAGE *, LPCWSTR);
|
||||
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);
|
||||
extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix);
|
||||
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 */
|
||||
|
||||
|
@ -1053,6 +994,7 @@ typedef struct
|
|||
} MSICABDATA;
|
||||
|
||||
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 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 szIntel64[] = {'I','n','t','e','l','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 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 */
|
||||
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 );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
x = lstrcmpW( name, col_name );
|
||||
x = strcmpW( name, col_name );
|
||||
if( table_name )
|
||||
x |= lstrcmpW( table_name, haystack_table_name );
|
||||
x |= strcmpW( table_name, haystack_table_name );
|
||||
msi_free( col_name );
|
||||
msi_free( haystack_table_name );
|
||||
if( !x )
|
||||
|
|
|
@ -86,6 +86,99 @@ interface IWineMsiRemoteCustomAction : IUnknown
|
|||
[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) ]
|
||||
library WindowsInstaller
|
||||
{
|
||||
|
@ -452,4 +545,12 @@ library WindowsInstaller
|
|||
properties:
|
||||
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 );
|
||||
TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
|
||||
if (!DeleteFileW( temp->Path ))
|
||||
ERR("failed to delete %s\n", debugstr_w( temp->Path ));
|
||||
DeleteFileW( temp->Path );
|
||||
msi_free( temp->Path );
|
||||
msi_free( temp );
|
||||
}
|
||||
|
@ -111,6 +110,17 @@ static void free_extension( MSIEXTENSION *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 )
|
||||
{
|
||||
INT i;
|
||||
|
@ -154,6 +164,7 @@ static void free_package_structures( MSIPACKAGE *package )
|
|||
msi_free( comp->Condition );
|
||||
msi_free( comp->KeyPath );
|
||||
msi_free( comp->FullKeypath );
|
||||
if (comp->assembly) free_assembly( comp->assembly );
|
||||
msi_free( comp );
|
||||
}
|
||||
|
||||
|
@ -275,6 +286,20 @@ static void free_package_structures( MSIPACKAGE *package )
|
|||
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->PackagePath );
|
||||
msi_free( package->ProductCode );
|
||||
|
@ -288,13 +313,19 @@ static void free_package_structures( MSIPACKAGE *package )
|
|||
|
||||
static void MSI_FreePackage( MSIOBJECTHDR *arg)
|
||||
{
|
||||
MSIPACKAGE *package= (MSIPACKAGE*) arg;
|
||||
UINT i;
|
||||
MSIPACKAGE *package = (MSIPACKAGE *)arg;
|
||||
|
||||
if( package->dialog )
|
||||
msi_dialog_destroy( package->dialog );
|
||||
|
||||
msiobj_release( &package->db->hdr );
|
||||
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)
|
||||
|
@ -511,7 +542,7 @@ static LPWSTR get_fusion_filename(MSIPACKAGE *package)
|
|||
index++;
|
||||
|
||||
/* 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;
|
||||
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_media );
|
||||
list_init( &package->patches );
|
||||
list_init( &package->binaries );
|
||||
}
|
||||
|
||||
return package;
|
||||
|
@ -1121,6 +1153,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
|
|||
|
||||
if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
|
||||
msi_load_admin_properties( package );
|
||||
|
||||
package->log_file = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
return package;
|
||||
|
@ -1313,7 +1347,7 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
|
|||
package->platform = PLATFORM_INTEL;
|
||||
else if (!strcmpW( template, szIntel64 ))
|
||||
package->platform = PLATFORM_INTEL64;
|
||||
else if (!strcmpW( template, szX64 ))
|
||||
else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 ))
|
||||
package->platform = PLATFORM_X64;
|
||||
else
|
||||
{
|
||||
|
@ -1321,9 +1355,14 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
|
|||
msi_free( template );
|
||||
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
|
||||
}
|
||||
|
||||
p++;
|
||||
if (!*p)
|
||||
{
|
||||
msi_free( template );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
count = 1;
|
||||
for (q = ++p; (q = strchrW( q, ',' )); q++) count++;
|
||||
for (q = p; (q = strchrW( q, ',' )); q++) count++;
|
||||
|
||||
package->langids = msi_alloc( count * sizeof(LANGID) );
|
||||
if (!package->langids)
|
||||
|
@ -1367,7 +1406,17 @@ static UINT validate_package( MSIPACKAGE *package )
|
|||
}
|
||||
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_INSTALL_LANGUAGE_UNSUPPORTED;
|
||||
|
@ -1551,6 +1600,10 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
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;
|
||||
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};
|
||||
static const WCHAR szActionText[] =
|
||||
{'A','c','t','i','o','n','T','e','x','t',0};
|
||||
DWORD log_type = 0;
|
||||
LPWSTR message;
|
||||
DWORD sz;
|
||||
DWORD total_size = 0;
|
||||
INT i;
|
||||
INT rc;
|
||||
DWORD sz, total_size = 0, log_type = 0;
|
||||
INT i, rc = 0;
|
||||
char *msg;
|
||||
int len;
|
||||
|
||||
TRACE("%x\n", eMessageType);
|
||||
rc = 0;
|
||||
|
||||
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
|
||||
log_type |= INSTALLLOGMODE_ERROR;
|
||||
|
@ -1773,20 +1822,12 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
|
|||
MsiCloseHandle( rec );
|
||||
}
|
||||
|
||||
if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
|
||||
INSTALLMESSAGE_PROGRESS))
|
||||
if (!rc && package->log_file != INVALID_HANDLE_VALUE &&
|
||||
(eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
|
||||
{
|
||||
DWORD write;
|
||||
HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 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);
|
||||
}
|
||||
DWORD written;
|
||||
WriteFile( package->log_file, msg, len - 1, &written, NULL );
|
||||
WriteFile( package->log_file, "\n", 1, &written, NULL );
|
||||
}
|
||||
msi_free( msg );
|
||||
msi_free( message );
|
||||
|
@ -2248,14 +2289,14 @@ UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
|
|||
}
|
||||
|
||||
typedef struct _msi_remote_package_impl {
|
||||
const IWineMsiRemotePackageVtbl *lpVtbl;
|
||||
IWineMsiRemotePackage IWineMsiRemotePackage_iface;
|
||||
MSIHANDLE package;
|
||||
LONG refs;
|
||||
} 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,
|
||||
|
@ -2274,14 +2315,14 @@ static HRESULT WINAPI mrp_QueryInterface( 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 );
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
r = InterlockedDecrement( &This->refs );
|
||||
|
@ -2295,14 +2336,14 @@ static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
|
|||
|
||||
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;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
HRESULT hr;
|
||||
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 )
|
||||
{
|
||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||
UINT r;
|
||||
|
||||
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 )
|
||||
{
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
||||
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);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
@ -2450,7 +2491,7 @@ static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE
|
|||
BSTR *value)
|
||||
{
|
||||
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);
|
||||
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 )
|
||||
{
|
||||
msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
|
||||
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
|
||||
UINT r = MsiEvaluateConditionW(This->package, condition);
|
||||
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,
|
||||
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);
|
||||
return HRESULT_FROM_WIN32(r);
|
||||
}
|
||||
|
@ -2514,7 +2555,7 @@ HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
|
|||
if (!This)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
This->lpVtbl = &msi_remote_package_vtbl;
|
||||
This->IWineMsiRemotePackage_iface.lpVtbl = &msi_remote_package_vtbl;
|
||||
This->package = 0;
|
||||
This->refs = 1;
|
||||
|
||||
|
@ -2528,6 +2569,11 @@ UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
|
|||
{
|
||||
MSISOURCELISTINFO *info;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry )
|
||||
{
|
||||
if (!strcmpW( info->value, value )) return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
info = msi_alloc(sizeof(MSISOURCELISTINFO));
|
||||
if (!info)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
@ -2546,6 +2592,11 @@ UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD option
|
|||
{
|
||||
MSIMEDIADISK *disk;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry )
|
||||
{
|
||||
if (disk->disk_id == disk_id) return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
disk = msi_alloc(sizeof(MSIMEDIADISK));
|
||||
if (!disk)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "winuser.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "msi.h"
|
||||
#include "msiquery.h"
|
||||
#include "msipriv.h"
|
||||
|
@ -1016,7 +1017,7 @@ BOOL MSI_RecordsAreEqual(MSIRECORD *a, MSIRECORD *b)
|
|||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
|
|
|
@ -1182,6 +1182,21 @@ UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL cr
|
|||
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.@]
|
||||
*
|
||||
|
@ -1549,10 +1564,11 @@ UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
|
|||
sz = SQUISH_GUID_SIZE;
|
||||
r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
|
||||
if( r == ERROR_SUCCESS )
|
||||
{
|
||||
unsquash_guid(szValName, szProduct);
|
||||
|
||||
TRACE("-> %s\n", debugstr_w(szProduct));
|
||||
}
|
||||
RegCloseKey(hkeyComp);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2140,7 +2156,7 @@ UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
|
|||
if (!szProductCode || !squash_guid(szProductCode, squished_pc))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (!lstrcmpW(szUserSid, szLocalSid))
|
||||
if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
|
||||
|
|
|
@ -143,6 +143,7 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
|
|||
|
||||
/* Add the session object */
|
||||
hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_ISVISIBLE);
|
||||
if (FAILED(hr)) goto done;
|
||||
|
||||
/* Pass the script to the engine */
|
||||
hr = IActiveScriptParse64_ParseScriptText(pActiveScriptParse, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL);
|
||||
|
|
|
@ -330,7 +330,6 @@ UINT WINAPI MsiSourceListEnumMediaDisksW(LPCWSTR szProductCodeOrPatchCode,
|
|||
else
|
||||
size = lstrlenW(ptr);
|
||||
|
||||
size = lstrlenW(ptr);
|
||||
if (size >= *pcchDiskPrompt)
|
||||
r = ERROR_MORE_DATA;
|
||||
else if (szDiskPrompt)
|
||||
|
@ -592,8 +591,8 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
|
||||
{
|
||||
rc = OpenMediaSubkey(sourcekey, &media, FALSE);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
|
@ -602,14 +601,14 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
|
||||
szProperty = mediapack;
|
||||
|
||||
RegQueryValueExW(media, szProperty, 0, 0, (LPBYTE)szValue, pcchValue);
|
||||
RegCloseKey(media);
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDTYPEW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
|
||||
{
|
||||
rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
|
||||
0, 0, NULL, &size);
|
||||
|
@ -630,7 +629,7 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDTYPEW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
|
||||
{
|
||||
if (*source != 'n' && *source != 'u' && *source != 'm')
|
||||
{
|
||||
|
@ -662,7 +661,7 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
*pcchValue = lstrlenW(ptr);
|
||||
msi_free(source);
|
||||
}
|
||||
else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
|
||||
{
|
||||
*pcchValue = *pcchValue * sizeof(WCHAR);
|
||||
rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0,
|
||||
|
@ -815,22 +814,22 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
}
|
||||
|
||||
property = szProperty;
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
|
||||
property = media_package;
|
||||
|
||||
rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
if (lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW) &&
|
||||
if (strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) &&
|
||||
dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL))
|
||||
{
|
||||
RegCloseKey(sourcekey);
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) ||
|
||||
!lstrcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW))
|
||||
if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
|
||||
!strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
|
||||
{
|
||||
rc = OpenMediaSubkey(sourcekey, &media, TRUE);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
|
@ -839,7 +838,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
RegCloseKey(media);
|
||||
}
|
||||
}
|
||||
else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
|
||||
{
|
||||
DWORD size = (lstrlenW(szValue) + 1) * sizeof(WCHAR);
|
||||
rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
|
||||
|
@ -847,7 +846,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
if (rc != ERROR_SUCCESS)
|
||||
rc = ERROR_UNKNOWN_PROPERTY;
|
||||
}
|
||||
else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW))
|
||||
else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ))
|
||||
{
|
||||
if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
|
||||
rc = ERROR_INVALID_PARAMETER;
|
||||
|
@ -1130,6 +1129,12 @@ UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
RegCloseKey(sourcekey);
|
||||
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;
|
||||
if (szSource[lstrlenW(szSource) - 1] == *postfix)
|
||||
|
|
|
@ -2872,7 +2872,7 @@ static BOOL SQL_MarkPrimaryKeys( column_info **cols,
|
|||
found = FALSE;
|
||||
for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
|
||||
{
|
||||
if( lstrcmpW( k->column, c->column ) )
|
||||
if( strcmpW( k->column, c->column ) )
|
||||
continue;
|
||||
c->type |= MSITYPE_KEY;
|
||||
found = TRUE;
|
||||
|
|
|
@ -950,7 +950,7 @@ static BOOL SQL_MarkPrimaryKeys( column_info **cols,
|
|||
found = FALSE;
|
||||
for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
|
||||
{
|
||||
if( lstrcmpW( k->column, c->column ) )
|
||||
if( strcmpW( k->column, c->column ) )
|
||||
continue;
|
||||
c->type |= MSITYPE_KEY;
|
||||
found = TRUE;
|
||||
|
|
|
@ -58,15 +58,22 @@ struct string_table
|
|||
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 )
|
||||
{
|
||||
string_table *st;
|
||||
|
||||
if (codepage != CP_ACP && !IsValidCodePage(codepage))
|
||||
{
|
||||
ERR("invalid codepage %d\n", codepage);
|
||||
if (!validate_codepage( codepage ))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
st = msi_alloc( sizeof (string_table) );
|
||||
if( !st )
|
||||
|
@ -162,7 +169,7 @@ static int find_insert_index( const string_table *st, UINT string_id )
|
|||
while (low <= high)
|
||||
{
|
||||
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)
|
||||
high = i - 1;
|
||||
|
@ -402,7 +409,7 @@ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id )
|
|||
while (low <= high)
|
||||
{
|
||||
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)
|
||||
high = i - 1;
|
||||
|
@ -671,3 +678,18 @@ err:
|
|||
|
||||
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 )
|
||||
count = lstrlenW( in )+2;
|
||||
out = msi_alloc( count*sizeof(WCHAR) );
|
||||
if (!(out = msi_alloc( count*sizeof(WCHAR) ))) return NULL;
|
||||
p = out;
|
||||
|
||||
if( bTable )
|
||||
|
@ -512,7 +512,7 @@ static MSITABLE *find_cached_table( MSIDATABASE *db, LPCWSTR name )
|
|||
MSITABLE *t;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( t, &db->tables, MSITABLE, entry )
|
||||
if( !lstrcmpW( name, t->name ) )
|
||||
if( !strcmpW( name, t->name ) )
|
||||
return t;
|
||||
|
||||
return NULL;
|
||||
|
@ -731,7 +731,7 @@ static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
|
|||
table->persistent = MSICONDITION_TRUE;
|
||||
lstrcpyW( table->name, name );
|
||||
|
||||
if ( !lstrcmpW(name, szTables) || !lstrcmpW(name, szColumns) )
|
||||
if ( !strcmpW( name, szTables ) || !strcmpW( name, szColumns ) )
|
||||
table->persistent = MSICONDITION_NONE;
|
||||
|
||||
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 )
|
||||
{
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
ERR("string id %u out of range\n", id);
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
@ -864,12 +864,12 @@ static UINT get_defaulttablecolumns( MSIDATABASE *db, LPCWSTR name,
|
|||
|
||||
TRACE("%s\n", debugstr_w(name));
|
||||
|
||||
if (!lstrcmpW( name, szTables ))
|
||||
if (!strcmpW( name, szTables ))
|
||||
{
|
||||
p = _Tables_cols;
|
||||
n = 1;
|
||||
}
|
||||
else if (!lstrcmpW( name, szColumns ))
|
||||
else if (!strcmpW( name, szColumns ))
|
||||
{
|
||||
p = _Columns_cols;
|
||||
n = 4;
|
||||
|
@ -1037,11 +1037,8 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
|
|||
UINT r, table_id, i;
|
||||
MSITABLE *table;
|
||||
|
||||
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};
|
||||
|
||||
if( !lstrcmpW( name, szTables ) || !lstrcmpW( name, szColumns ) ||
|
||||
!lstrcmpW( name, szStreams ) || !lstrcmpW( name, szStorages ) )
|
||||
if( !strcmpW( name, szTables ) || !strcmpW( name, szColumns ) ||
|
||||
!strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) )
|
||||
return TRUE;
|
||||
|
||||
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;
|
||||
if ( type & MSITYPE_KEY )
|
||||
{
|
||||
WCHAR number[0x20];
|
||||
|
||||
r = TABLE_fetch_int( view, row, i+1, &ival );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
goto err;
|
||||
|
@ -1162,7 +1161,6 @@ static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname )
|
|||
else
|
||||
{
|
||||
static const WCHAR fmt[] = { '%','d',0 };
|
||||
WCHAR number[0x20];
|
||||
UINT n = bytes_per_column( tv->db, &tv->columns[i], LONG_STR_BYTES );
|
||||
|
||||
switch( n )
|
||||
|
@ -1346,10 +1344,13 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT
|
|||
else if ( columninfo.type & MSITYPE_STRING )
|
||||
{
|
||||
LPCWSTR sval = MSI_RecordGetString( rec, iField );
|
||||
|
||||
r = msi_string2idW(tv->db->strings, sval, pvalue);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_NOT_FOUND;
|
||||
if (sval)
|
||||
{
|
||||
r = msi_string2idW(tv->db->strings, sval, pvalue);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
else *pvalue = 0;
|
||||
}
|
||||
else if ( bytes_per_column( tv->db, &columninfo, LONG_STR_BYTES ) == 2 )
|
||||
{
|
||||
|
@ -1432,7 +1433,6 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
|
|||
LPCWSTR sval = MSI_RecordGetString( rec, i + 1 );
|
||||
val = msi_addstringW( tv->db->strings, sval, -1, 1,
|
||||
persistent ? StringPersistent : StringNonPersistent );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1630,6 +1630,8 @@ static int compare_record( MSITABLEVIEW *tv, UINT row, MSIRECORD *rec )
|
|||
|
||||
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 );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return 1;
|
||||
|
@ -1774,6 +1776,9 @@ static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
|
|||
if (row != new_row + 1)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2099,7 +2104,7 @@ static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number
|
|||
msitable = find_cached_table(tv->db, table);
|
||||
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);
|
||||
break;
|
||||
|
@ -2340,14 +2345,11 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
|
|||
MSITABLEVIEW *tv ;
|
||||
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 );
|
||||
|
||||
if ( !lstrcmpW( name, Streams ) )
|
||||
if ( !strcmpW( name, szStreams ) )
|
||||
return STREAMS_CreateView( db, view );
|
||||
else if ( !lstrcmpW( name, Storages ) )
|
||||
else if ( !strcmpW( name, szStorages ) )
|
||||
return STORAGES_CreateView( db, view );
|
||||
|
||||
sz = sizeof *tv + lstrlenW(name)*sizeof name[0] ;
|
||||
|
@ -2593,7 +2595,7 @@ static void dump_record( MSIRECORD *rec )
|
|||
n = MSI_RecordGetFieldCount( rec );
|
||||
for( i=1; i<=n; i++ )
|
||||
{
|
||||
LPCWSTR sval = MSI_RecordGetString( rec, i );
|
||||
LPCWSTR sval;
|
||||
|
||||
if( MSI_RecordIsNull( rec, i ) )
|
||||
TRACE("row -> []\n");
|
||||
|
@ -2634,15 +2636,19 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
|
|||
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||
{
|
||||
str = MSI_RecordGetString( rec, i+1 );
|
||||
r = msi_string2idW( tv->db->strings, str, &data[i] );
|
||||
|
||||
/* if there's no matching string in the string table,
|
||||
these keys can't match any record, so fail now. */
|
||||
if( ERROR_SUCCESS != r )
|
||||
if (str)
|
||||
{
|
||||
msi_free( data );
|
||||
return NULL;
|
||||
r = msi_string2idW( tv->db->strings, str, &data[i] );
|
||||
|
||||
/* if there's no matching string in the string table,
|
||||
these keys can't match any record, so fail now. */
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msi_free( data );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else data[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2818,7 +2824,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
UINT number = MSI_NULL_INTEGER;
|
||||
UINT row = 0;
|
||||
|
||||
if (!lstrcmpW( name, szColumns ))
|
||||
if (!strcmpW( name, szColumns ))
|
||||
{
|
||||
MSI_RecordGetStringW( rec, 1, table, &sz );
|
||||
number = MSI_RecordGetInteger( rec, 2 );
|
||||
|
@ -2830,7 +2836,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
if ( number == MSI_NULL_INTEGER )
|
||||
{
|
||||
/* reset the column number on a new table */
|
||||
if (lstrcmpW( coltable, table ))
|
||||
if (strcmpW( coltable, table ))
|
||||
{
|
||||
colcol = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
if (number != MSI_NULL_INTEGER && !lstrcmpW( name, szColumns ))
|
||||
if (number != MSI_NULL_INTEGER && !strcmpW( name, szColumns ))
|
||||
msi_update_table_columns( db, table );
|
||||
|
||||
msiobj_release( &rec->hdr );
|
||||
|
@ -2938,8 +2944,8 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
|
|||
if ( name[0] != 0x4840 )
|
||||
continue;
|
||||
|
||||
if ( !lstrcmpW( name+1, szStringPool ) ||
|
||||
!lstrcmpW( name+1, szStringData ) )
|
||||
if ( !strcmpW( name+1, szStringPool ) ||
|
||||
!strcmpW( name+1, szStringData ) )
|
||||
continue;
|
||||
|
||||
transform = msi_alloc_zero( sizeof(TRANSFORMDATA) );
|
||||
|
@ -2950,9 +2956,9 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
|
|||
|
||||
transform->name = strdupW( name + 1 );
|
||||
|
||||
if ( !lstrcmpW( transform->name, szTables ) )
|
||||
if ( !strcmpW( transform->name, szTables ) )
|
||||
tables = transform;
|
||||
else if (!lstrcmpW( transform->name, szColumns ) )
|
||||
else if (!strcmpW( transform->name, szColumns ) )
|
||||
columns = transform;
|
||||
|
||||
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 );
|
||||
|
||||
if ( lstrcmpW( transform->name, szColumns ) &&
|
||||
lstrcmpW( transform->name, szTables ) &&
|
||||
if ( strcmpW( transform->name, szColumns ) &&
|
||||
strcmpW( transform->name, szTables ) &&
|
||||
ret == ERROR_SUCCESS )
|
||||
{
|
||||
ret = msi_table_load_transform( db, stg, strings, transform, bytes_per_strref );
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "msi.h"
|
||||
#include "msiquery.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 )
|
||||
sr = -1;
|
||||
else
|
||||
sr = lstrcmpW( l_str, r_str );
|
||||
sr = strcmpW( l_str, r_str );
|
||||
|
||||
*val = ( cond->u.expr.op == OP_EQ && ( 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:
|
||||
r = wv->table->ops->fetch_int( wv->table, row, cond->u.col_number, &tval );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
*val = tval - 0x8000;
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case EXPR_COL_NUMBER32:
|
||||
r = wv->table->ops->fetch_int( wv->table, row, cond->u.col_number, &tval );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
*val = tval - 0x80000000;
|
||||
return r;
|
||||
|
||||
|
|
Loading…
Reference in a new issue