-partial sync to wine 1.3.16

svn path=/trunk/; revision=51096
This commit is contained in:
Christoph von Wittich 2011-03-20 08:47:41 +00:00
parent 06afcd3dd6
commit 7dfa68869c
36 changed files with 2657 additions and 1638 deletions

File diff suppressed because it is too large Load diff

View file

@ -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);

View 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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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:

View file

@ -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);

View file

@ -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;

View file

@ -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 );

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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;

View file

@ -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.@]
*/

View file

@ -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>

View 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"

View file

@ -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

View file

@ -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 ));
}

View file

@ -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);

View file

@ -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 )

View file

@ -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; }
}

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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 );

View file

@ -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;