* Sync to Wine 1.5.4.

svn path=/trunk/; revision=56588
This commit is contained in:
Amine Khaldi 2012-05-14 21:41:31 +00:00
parent 87fa6c0693
commit 1ead8de25d
22 changed files with 1390 additions and 790 deletions

View file

@ -7,7 +7,6 @@ add_definitions(-D__WINESRC__ -DMSIRUNMODE=MSIRUNMODE_T)
remove_definitions(-D_WIN32_WINNT=0x502) remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600) add_definitions(-D_WIN32_WINNT=0x600)
set_rc_compiler()
spec2def(msi.dll msi.spec ADD_IMPORTLIB) spec2def(msi.dll msi.spec ADD_IMPORTLIB)
generate_idl_iids(msiserver.idl) generate_idl_iids(msiserver.idl)
@ -98,5 +97,3 @@ add_pch(msi msipriv.h)
add_cd_file(TARGET msi DESTINATION reactos/system32 FOR all) add_cd_file(TARGET msi DESTINATION reactos/system32 FOR all)
endif(NOT MSVC) endif(NOT MSVC)

View file

@ -222,7 +222,6 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
switch (*p) switch (*p)
{ {
case ' ': case ' ':
if (!count) goto done;
in_quotes = 1; in_quotes = 1;
ignore = 1; ignore = 1;
len++; len++;
@ -234,8 +233,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
break; break;
default: default:
state = state_token; state = state_token;
if (!count) in_quotes = 0; in_quotes = 1;
else in_quotes = 1;
len++; len++;
break; break;
} }
@ -482,8 +480,7 @@ UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
static BOOL needs_ui_sequence(MSIPACKAGE *package) static BOOL needs_ui_sequence(MSIPACKAGE *package)
{ {
INT level = msi_get_property_int(package->db, szUILevel, 0); return (package->ui_level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED;
return (level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED;
} }
UINT msi_set_context(MSIPACKAGE *package) UINT msi_set_context(MSIPACKAGE *package)
@ -539,6 +536,12 @@ static UINT ITERATE_Actions(MSIRECORD *row, LPVOID param)
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
ERR("Execution halted, action %s returned %i\n", debugstr_w(action), rc); ERR("Execution halted, action %s returned %i\n", debugstr_w(action), rc);
if (package->need_reboot_now)
{
TRACE("action %s asked for immediate reboot, suspending installation\n",
debugstr_w(action));
rc = ACTION_ForceReboot( package );
}
return rc; return rc;
} }
@ -881,6 +884,20 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package)
return rc; return rc;
} }
static void remove_persistent_folder( MSIFOLDER *folder )
{
FolderList *fl;
LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
{
remove_persistent_folder( fl->folder );
}
if (folder->persistent && folder->State != FOLDER_STATE_REMOVED)
{
if (RemoveDirectoryW( folder->ResolvedTarget )) folder->State = FOLDER_STATE_REMOVED;
}
}
static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param ) static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
{ {
MSIPACKAGE *package = param; MSIPACKAGE *package = param;
@ -924,9 +941,8 @@ static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
msi_ui_actiondata( package, szRemoveFolders, uirow ); msi_ui_actiondata( package, szRemoveFolders, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
RemoveDirectoryW( full_path );
folder = msi_get_loaded_folder( package, dir ); folder = msi_get_loaded_folder( package, dir );
folder->State = FOLDER_STATE_REMOVED; remove_persistent_folder( folder );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -1617,16 +1633,19 @@ static void ACTION_GetComponentInstallStates(MSIPACKAGE *package)
r = MsiQueryComponentStateW( package->ProductCode, NULL, r = MsiQueryComponentStateW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED, comp->ComponentId, MSIINSTALLCONTEXT_USERMANAGED, comp->ComponentId,
&comp->Installed ); &comp->Installed );
if (r != ERROR_SUCCESS) if (r == ERROR_SUCCESS) continue;
r = MsiQueryComponentStateW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED, comp->ComponentId, r = MsiQueryComponentStateW( package->ProductCode, NULL,
&comp->Installed ); MSIINSTALLCONTEXT_USERUNMANAGED, comp->ComponentId,
if (r != ERROR_SUCCESS) &comp->Installed );
r = MsiQueryComponentStateW( package->ProductCode, NULL, if (r == ERROR_SUCCESS) continue;
MSIINSTALLCONTEXT_MACHINE, comp->ComponentId,
&comp->Installed ); r = MsiQueryComponentStateW( package->ProductCode, NULL,
if (r != ERROR_SUCCESS) MSIINSTALLCONTEXT_MACHINE, comp->ComponentId,
comp->Installed = INSTALLSTATE_ABSENT; &comp->Installed );
if (r == ERROR_SUCCESS) continue;
comp->Installed = INSTALLSTATE_ABSENT;
} }
} }
@ -1795,6 +1814,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
} }
else if (fl->feature->Attributes & msidbFeatureAttributesFollowParent) else if (fl->feature->Attributes & msidbFeatureAttributesFollowParent)
{ {
TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Action = feature->Action; fl->feature->Action = feature->Action;
fl->feature->ActionRequest = feature->ActionRequest; fl->feature->ActionRequest = feature->ActionRequest;
} }
@ -1825,12 +1847,14 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{ {
FeatureList *fl; FeatureList *fl;
if (!is_feature_selected( feature, level )) continue;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry ) LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
{ {
if (fl->feature->Attributes & msidbFeatureAttributesFollowParent) if (fl->feature->Attributes & msidbFeatureAttributesFollowParent &&
(!(feature->Attributes & msidbFeatureAttributesFavorAdvertise)))
{ {
TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Action = feature->Action; fl->feature->Action = feature->Action;
fl->feature->ActionRequest = feature->ActionRequest; fl->feature->ActionRequest = feature->ActionRequest;
} }
@ -1843,7 +1867,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{ {
ComponentList *cl; ComponentList *cl;
TRACE("Examining Feature %s (Level %d Installed %d Request %d Action %d)\n", TRACE("examining feature %s (level %d installed %d request %d action %d)\n",
debugstr_w(feature->Feature), feature->Level, feature->Installed, debugstr_w(feature->Feature), feature->Level, feature->Installed,
feature->ActionRequest, feature->Action); feature->ActionRequest, feature->Action);
@ -1958,7 +1982,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
component->ActionRequest = INSTALLSTATE_UNKNOWN; component->ActionRequest = INSTALLSTATE_UNKNOWN;
} }
TRACE("Result: Component %s (Installed %d Request %d Action %d)\n", TRACE("component %s (installed %d request %d action %d)\n",
debugstr_w(component->Component), component->Installed, component->ActionRequest, component->Action); debugstr_w(component->Component), component->Installed, component->ActionRequest, component->Action);
} }
@ -2214,11 +2238,15 @@ static UINT calculate_file_cost( MSIPACKAGE *package )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
void msi_clean_path( WCHAR *p ) WCHAR *msi_normalize_path( const WCHAR *in )
{ {
WCHAR *q = p; const WCHAR *p = in;
int n, len = 0; WCHAR *q, *ret;
int n, len = strlenW( in ) + 2;
if (!(q = ret = msi_alloc( len * sizeof(WCHAR) ))) return NULL;
len = 0;
while (1) while (1)
{ {
/* copy until the end of the string or a space */ /* copy until the end of the string or a space */
@ -2245,32 +2273,20 @@ void msi_clean_path( WCHAR *p )
else /* copy n spaces */ else /* copy n spaces */
while (n && (*q++ = *p++)) n--; while (n && (*q++ = *p++)) n--;
} }
} while (q - ret > 0 && q[-1] == ' ') q--;
if (q - ret > 0 && q[-1] != '\\')
static WCHAR *get_target_dir_property( MSIDATABASE *db )
{
int len;
WCHAR *path, *target_dir = msi_dup_property( db, szTargetDir );
if (!target_dir) return NULL;
len = strlenW( target_dir );
if (target_dir[len - 1] == '\\') return target_dir;
if ((path = msi_alloc( (len + 2) * sizeof(WCHAR) )))
{ {
strcpyW( path, target_dir ); q[0] = '\\';
path[len] = '\\'; q[1] = 0;
path[len + 1] = 0;
} }
msi_free( target_dir ); return ret;
return path;
} }
void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL load_prop ) void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL load_prop )
{ {
FolderList *fl; FolderList *fl;
MSIFOLDER *folder, *parent, *child; MSIFOLDER *folder, *parent, *child;
WCHAR *path; WCHAR *path, *normalized_path;
TRACE("resolving %s\n", debugstr_w(name)); TRACE("resolving %s\n", debugstr_w(name));
@ -2278,7 +2294,7 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
if (!strcmpW( folder->Directory, szTargetDir )) /* special resolving for target root dir */ if (!strcmpW( folder->Directory, szTargetDir )) /* special resolving for target root dir */
{ {
if (!load_prop || !(path = get_target_dir_property( package->db ))) if (!load_prop || !(path = msi_dup_property( package->db, szTargetDir )))
{ {
path = msi_dup_property( package->db, szRootDrive ); path = msi_dup_property( package->db, szRootDrive );
} }
@ -2293,16 +2309,17 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
else else
path = msi_build_directory_name( 2, folder->TargetDefault, NULL ); path = msi_build_directory_name( 2, folder->TargetDefault, NULL );
} }
msi_clean_path( path ); normalized_path = msi_normalize_path( path );
if (folder->ResolvedTarget && !strcmpiW( path, folder->ResolvedTarget )) msi_free( path );
if (folder->ResolvedTarget && !strcmpiW( normalized_path, folder->ResolvedTarget ))
{ {
TRACE("%s already resolved to %s\n", debugstr_w(name), debugstr_w(folder->ResolvedTarget)); TRACE("%s already resolved to %s\n", debugstr_w(name), debugstr_w(folder->ResolvedTarget));
msi_free( path ); msi_free( normalized_path );
return; return;
} }
msi_set_property( package->db, folder->Directory, path ); msi_set_property( package->db, folder->Directory, normalized_path );
msi_free( folder->ResolvedTarget ); msi_free( folder->ResolvedTarget );
folder->ResolvedTarget = path; folder->ResolvedTarget = normalized_path;
LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry ) LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
{ {
@ -2953,7 +2970,7 @@ static UINT ITERATE_LaunchConditions(MSIRECORD *row, LPVOID param)
r = MSI_EvaluateConditionW(package,cond); r = MSI_EvaluateConditionW(package,cond);
if (r == MSICONDITION_FALSE) if (r == MSICONDITION_FALSE)
{ {
if ((gUILevel & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE) if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
{ {
LPWSTR deformated; LPWSTR deformated;
message = MSI_RecordGetString(row,2); message = MSI_RecordGetString(row,2);
@ -3608,25 +3625,9 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
target = MSI_RecordGetString(row, 5); target = MSI_RecordGetString(row, 5);
if (strchrW(target, '[')) if (strchrW(target, '['))
{ {
int len; deformat_string( package, target, &path );
WCHAR *format_string, *p;
if (!(p = strchrW( target, ']' ))) goto err;
len = p - target + 1;
format_string = msi_alloc( (len + 1) * sizeof(WCHAR) );
memcpy( format_string, target, len * sizeof(WCHAR) );
format_string[len] = 0;
deformat_string( package, format_string, &deformated );
msi_free( format_string );
path = msi_alloc( (strlenW( deformated ) + strlenW( p + 1 ) + 2) * sizeof(WCHAR) );
strcpyW( path, deformated );
PathAddBackslashW( path );
strcatW( path, p + 1 );
TRACE("target path is %s\n", debugstr_w(path)); TRACE("target path is %s\n", debugstr_w(path));
IShellLinkW_SetPath( sl, path ); IShellLinkW_SetPath( sl, path );
msi_free( deformated );
msi_free( path ); msi_free( path );
} }
else else
@ -4479,7 +4480,7 @@ static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
MSIFILE *file; MSIFILE *file;
MSIRECORD *uirow; MSIRECORD *uirow;
filename = MSI_RecordGetString(row,1); filename = MSI_RecordGetString( row, 1 );
file = msi_get_loaded_file( package, filename ); file = msi_get_loaded_file( package, filename );
if (!file) if (!file)
{ {
@ -4497,7 +4498,7 @@ static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
register_dll( file->TargetPath, FALSE ); register_dll( file->TargetPath, FALSE );
uirow = MSI_CreateRecord( 2 ); uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, filename ); MSI_RecordSetStringW( uirow, 1, file->File );
MSI_RecordSetStringW( uirow, 2, file->Component->Directory ); MSI_RecordSetStringW( uirow, 2, file->Component->Directory );
msi_ui_actiondata( package, szSelfRegModules, uirow ); msi_ui_actiondata( package, szSelfRegModules, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
@ -4547,7 +4548,7 @@ static UINT ITERATE_SelfUnregModules( MSIRECORD *row, LPVOID param )
register_dll( file->TargetPath, TRUE ); register_dll( file->TargetPath, TRUE );
uirow = MSI_CreateRecord( 2 ); uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, filename ); MSI_RecordSetStringW( uirow, 1, file->File );
MSI_RecordSetStringW( uirow, 2, file->Component->Directory ); MSI_RecordSetStringW( uirow, 2, file->Component->Directory );
msi_ui_actiondata( package, szSelfUnregModules, uirow ); msi_ui_actiondata( package, szSelfUnregModules, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
@ -5933,28 +5934,25 @@ static UINT ITERATE_DeleteService( MSIRECORD *rec, LPVOID param )
MSIPACKAGE *package = param; MSIPACKAGE *package = param;
MSICOMPONENT *comp; MSICOMPONENT *comp;
MSIRECORD *uirow; MSIRECORD *uirow;
LPCWSTR component;
LPWSTR name = NULL, display_name = NULL; LPWSTR name = NULL, display_name = NULL;
DWORD event, len; DWORD event, len;
SC_HANDLE scm = NULL, service = NULL; SC_HANDLE scm = NULL, service = NULL;
event = MSI_RecordGetInteger( rec, 3 ); comp = msi_get_loaded_component( package, MSI_RecordGetString(rec, 6) );
if (!(event & msidbServiceControlEventDelete))
return ERROR_SUCCESS;
component = MSI_RecordGetString(rec, 6);
comp = msi_get_loaded_component(package, component);
if (!comp) if (!comp)
return ERROR_SUCCESS; return ERROR_SUCCESS;
event = MSI_RecordGetInteger( rec, 3 );
deformat_string( package, MSI_RecordGetString(rec, 2), &name );
comp->Action = msi_get_component_action( package, comp ); comp->Action = msi_get_component_action( package, comp );
if (comp->Action != INSTALLSTATE_ABSENT) if (!(comp->Action == INSTALLSTATE_LOCAL && (event & msidbServiceControlEventDelete)) &&
!(comp->Action == INSTALLSTATE_ABSENT && (event & msidbServiceControlEventUninstallDelete)))
{ {
TRACE("component not scheduled for removal %s\n", debugstr_w(component)); TRACE("service %s not scheduled for removal\n", debugstr_w(name));
msi_free( name );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
deformat_string( package, MSI_RecordGetString(rec, 2), &name );
stop_service( name ); stop_service( name );
scm = OpenSCManagerW( NULL, NULL, SC_MANAGER_ALL_ACCESS ); scm = OpenSCManagerW( NULL, NULL, SC_MANAGER_ALL_ACCESS );
@ -6084,6 +6082,11 @@ static UINT ITERATE_InstallODBCDriver( MSIRECORD *rec, LPVOID param )
ptr += lstrlenW(ptr) + 1; ptr += lstrlenW(ptr) + 1;
*ptr = '\0'; *ptr = '\0';
if (!driver_file->TargetPath)
{
const WCHAR *dir = msi_get_target_folder( package, driver_file->Component->Directory );
driver_file->TargetPath = msi_build_directory_name( 2, dir, driver_file->FileName );
}
driver_path = strdupW(driver_file->TargetPath); driver_path = strdupW(driver_file->TargetPath);
ptr = strrchrW(driver_path, '\\'); ptr = strrchrW(driver_path, '\\');
if (ptr) *ptr = '\0'; if (ptr) *ptr = '\0';
@ -6907,7 +6910,7 @@ static UINT ACTION_ValidateProductID( MSIPACKAGE *package )
static UINT ACTION_ScheduleReboot( MSIPACKAGE *package ) static UINT ACTION_ScheduleReboot( MSIPACKAGE *package )
{ {
TRACE("\n"); TRACE("\n");
package->need_reboot = 1; package->need_reboot_at_end = 1;
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -7532,7 +7535,7 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
} }
msi_free( reinstall ); msi_free( reinstall );
if (rc == ERROR_SUCCESS && package->need_reboot) if (rc == ERROR_SUCCESS && package->need_reboot_at_end)
return ERROR_SUCCESS_REBOOT_REQUIRED; return ERROR_SUCCESS_REBOOT_REQUIRED;
return rc; return rc;

View file

@ -608,6 +608,65 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
msi_free(deformatted); msi_free(deformatted);
} }
static LANGID *parse_languages( const WCHAR *languages, DWORD *num_ids )
{
UINT i, count = 1;
WCHAR *str = strdupW( languages ), *p, *q;
LANGID *ret;
if (!str) return NULL;
for (p = q = str; (q = strchrW( q, ',' )); q++) count++;
if (!(ret = msi_alloc( count * sizeof(LANGID) )))
{
msi_free( str );
return NULL;
}
i = 0;
while (*p)
{
q = strchrW( p, ',' );
if (q) *q = 0;
ret[i] = atoiW( p );
if (!q) break;
p = q + 1;
i++;
}
msi_free( str );
*num_ids = count;
return ret;
}
static BOOL match_languages( const void *version, const WCHAR *languages )
{
struct lang
{
USHORT id;
USHORT codepage;
} *lang;
DWORD len, num_ids, i, j;
BOOL found = FALSE;
LANGID *ids;
if (!languages || !languages[0]) return TRUE;
if (!VerQueryValueW( version, szLangResource, (void **)&lang, &len )) return FALSE;
if (!(ids = parse_languages( languages, &num_ids ))) return FALSE;
for (i = 0; i < num_ids; i++)
{
found = FALSE;
for (j = 0; j < len / sizeof(struct lang); j++)
{
if (!ids[i] || ids[i] == lang[j].id) found = TRUE;
}
if (!found) goto done;
}
done:
msi_free( ids );
return found;
}
/* Sets *matches to whether the file (whose path is filePath) matches the /* Sets *matches to whether the file (whose path is filePath) matches the
* versions set in sig. * versions set in sig.
* Return ERROR_SUCCESS in case of success (whether or not the file matches), * Return ERROR_SUCCESS in case of success (whether or not the file matches),
@ -616,69 +675,55 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
static UINT ACTION_FileVersionMatches(const MSISIGNATURE *sig, LPCWSTR filePath, static UINT ACTION_FileVersionMatches(const MSISIGNATURE *sig, LPCWSTR filePath,
BOOL *matches) BOOL *matches)
{ {
UINT rc = ERROR_SUCCESS; UINT len;
void *version;
VS_FIXEDFILEINFO *info = NULL;
DWORD zero, size = GetFileVersionInfoSizeW( filePath, &zero );
*matches = FALSE; *matches = FALSE;
if (sig->Languages)
{
FIXME(": need to check version for languages %s\n",
debugstr_w(sig->Languages));
}
else
{
DWORD zero, size = GetFileVersionInfoSizeW(filePath, &zero);
if (size) if (!size) return ERROR_SUCCESS;
if (!(version = msi_alloc( size ))) return ERROR_OUTOFMEMORY;
if (GetFileVersionInfoW( filePath, 0, size, version ))
VerQueryValueW( version, szBackSlash, (void **)&info, &len );
if (info)
{
TRACE("comparing file version %d.%d.%d.%d:\n",
HIWORD(info->dwFileVersionMS),
LOWORD(info->dwFileVersionMS),
HIWORD(info->dwFileVersionLS),
LOWORD(info->dwFileVersionLS));
if (info->dwFileVersionMS < sig->MinVersionMS
|| (info->dwFileVersionMS == sig->MinVersionMS &&
info->dwFileVersionLS < sig->MinVersionLS))
{ {
LPVOID buf = msi_alloc( size); TRACE("less than minimum version %d.%d.%d.%d\n",
HIWORD(sig->MinVersionMS),
if (buf) LOWORD(sig->MinVersionMS),
{ HIWORD(sig->MinVersionLS),
UINT versionLen; LOWORD(sig->MinVersionLS));
LPVOID subBlock = NULL;
if (GetFileVersionInfoW(filePath, 0, size, buf))
VerQueryValueW(buf, szBackSlash, &subBlock, &versionLen);
if (subBlock)
{
VS_FIXEDFILEINFO *info = subBlock;
TRACE("Comparing file version %d.%d.%d.%d:\n",
HIWORD(info->dwFileVersionMS),
LOWORD(info->dwFileVersionMS),
HIWORD(info->dwFileVersionLS),
LOWORD(info->dwFileVersionLS));
if (info->dwFileVersionMS < sig->MinVersionMS
|| (info->dwFileVersionMS == sig->MinVersionMS &&
info->dwFileVersionLS < sig->MinVersionLS))
{
TRACE("Less than minimum version %d.%d.%d.%d\n",
HIWORD(sig->MinVersionMS),
LOWORD(sig->MinVersionMS),
HIWORD(sig->MinVersionLS),
LOWORD(sig->MinVersionLS));
}
else if ((sig->MaxVersionMS || sig->MaxVersionLS) &&
(info->dwFileVersionMS > sig->MaxVersionMS ||
(info->dwFileVersionMS == sig->MaxVersionMS &&
info->dwFileVersionLS > sig->MaxVersionLS)))
{
TRACE("Greater than maximum version %d.%d.%d.%d\n",
HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS),
HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS));
}
else
*matches = TRUE;
}
msi_free( buf);
}
else
rc = ERROR_OUTOFMEMORY;
} }
else if ((sig->MaxVersionMS || sig->MaxVersionLS) &&
(info->dwFileVersionMS > sig->MaxVersionMS ||
(info->dwFileVersionMS == sig->MaxVersionMS &&
info->dwFileVersionLS > sig->MaxVersionLS)))
{
TRACE("greater than maximum version %d.%d.%d.%d\n",
HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS),
HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS));
}
else if (!match_languages( version, sig->Languages ))
{
TRACE("languages %s not supported\n", debugstr_w( sig->Languages ));
}
else *matches = TRUE;
} }
return rc; msi_free( version );
return ERROR_SUCCESS;
} }
/* Sets *matches to whether the file in findData matches that in sig. /* Sets *matches to whether the file in findData matches that in sig.

View file

@ -262,13 +262,13 @@ static BOOL is_assembly_installed( IAssemblyCache *cache, const WCHAR *display_n
memset( &info, 0, sizeof(info) ); memset( &info, 0, sizeof(info) );
info.cbAssemblyInfo = sizeof(info); info.cbAssemblyInfo = sizeof(info);
hr = IAssemblyCache_QueryAssemblyInfo( cache, QUERYASMINFO_FLAG_GETSIZE, display_name, &info ); hr = IAssemblyCache_QueryAssemblyInfo( cache, 0, display_name, &info );
if (hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER )) if (hr == S_OK /* sxs version */ || hr == HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
{ {
TRACE("QueryAssemblyInfo returned 0x%08x\n", hr); return (info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
return FALSE;
} }
return (info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED); TRACE("QueryAssemblyInfo returned 0x%08x\n", hr);
return FALSE;
} }
static const WCHAR clr_version_v10[] = {'v','1','.','0','.','3','7','0','5',0}; static const WCHAR clr_version_v10[] = {'v','1','.','0','.','3','7','0','5',0};
@ -425,6 +425,45 @@ UINT msi_install_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
UINT msi_uninstall_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
{
HRESULT hr;
IAssemblyCache *cache;
MSIASSEMBLY *assembly = comp->assembly;
MSIFEATURE *feature = NULL;
if (comp->assembly->feature)
feature = msi_get_loaded_feature( package, comp->assembly->feature );
if (assembly->application)
{
if (feature) feature->Action = INSTALLSTATE_ABSENT;
return ERROR_SUCCESS;
}
TRACE("removing %s\n", debugstr_w(assembly->display_name));
if (assembly->attributes == msidbAssemblyAttributesWin32)
{
cache = package->cache_sxs;
hr = IAssemblyCache_UninstallAssembly( cache, 0, assembly->display_name, NULL, NULL );
if (FAILED( hr )) WARN("failed to uninstall assembly 0x%08x\n", hr);
}
else
{
unsigned int i;
for (i = 0; i < CLR_VERSION_MAX; i++)
{
if (!assembly->clr_version[i]) continue;
cache = package->cache_net[i];
hr = IAssemblyCache_UninstallAssembly( cache, 0, assembly->display_name, NULL, NULL );
if (FAILED( hr )) WARN("failed to uninstall assembly 0x%08x\n", hr);
}
}
if (feature) feature->Action = INSTALLSTATE_ABSENT;
assembly->installed = FALSE;
return ERROR_SUCCESS;
}
static WCHAR *build_local_assembly_path( const WCHAR *filename ) static WCHAR *build_local_assembly_path( const WCHAR *filename )
{ {
UINT i; UINT i;

File diff suppressed because it is too large Load diff

View file

@ -903,11 +903,11 @@ static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source,
if( row ) if( row )
{ {
LPCWSTR error = MSI_RecordGetString( row, 1 ); LPCWSTR error = MSI_RecordGetString( row, 1 );
if ((gUILevel & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE) if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
MessageBoxW( NULL, error, NULL, MB_OK ); MessageBoxW( NULL, error, NULL, MB_OK );
msiobj_release( &row->hdr ); msiobj_release( &row->hdr );
} }
else if ((gUILevel & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE) else if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
MessageBoxW( NULL, deformated, NULL, MB_OK ); MessageBoxW( NULL, deformated, NULL, MB_OK );
msi_free( deformated ); msi_free( deformated );

View file

@ -3978,8 +3978,7 @@ UINT msi_spawn_error_dialog( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR er
'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0 'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
}; };
if ( (msi_get_property_int( package->db, szUILevel, 0 ) & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE ) if ((package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) return ERROR_SUCCESS;
return ERROR_SUCCESS;
if ( !error_dialog ) if ( !error_dialog )
{ {

View file

@ -215,7 +215,7 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
MoveFileExW(tmpfileW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT)) MoveFileExW(tmpfileW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT))
{ {
file->state = msifs_installed; file->state = msifs_installed;
package->need_reboot = 1; package->need_reboot_at_end = 1;
gle = ERROR_SUCCESS; gle = ERROR_SUCCESS;
} }
else else
@ -247,6 +247,17 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static MSIFILE *find_file( MSIPACKAGE *package, const WCHAR *filename )
{
MSIFILE *file;
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
if (file->state != msifs_installed && !strcmpiW( filename, file->File )) return file;
}
return NULL;
}
static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
LPWSTR *path, DWORD *attrs, PVOID user) LPWSTR *path, DWORD *attrs, PVOID user)
{ {
@ -255,8 +266,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
if (action == MSICABEXTRACT_BEGINEXTRACT) if (action == MSICABEXTRACT_BEGINEXTRACT)
{ {
f = msi_get_loaded_file(package, file); if (!(f = find_file( package, file )))
if (!f)
{ {
TRACE("unknown file in cabinet (%s)\n", debugstr_w(file)); TRACE("unknown file in cabinet (%s)\n", debugstr_w(file));
return FALSE; return FALSE;
@ -1298,22 +1308,26 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
msi_ui_actiondata( package, szRemoveFiles, uirow ); msi_ui_actiondata( package, szRemoveFiles, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
} }
msi_init_assembly_caches( package );
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry ) LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{ {
MSIFOLDER *folder;
comp->Action = msi_get_component_action( package, comp ); comp->Action = msi_get_component_action( package, comp );
if (comp->Action != INSTALLSTATE_ABSENT) continue; if (comp->Action != INSTALLSTATE_ABSENT) continue;
if (comp->assembly && !comp->assembly->application) continue;
if (comp->Attributes & msidbComponentAttributesPermanent) if (comp->Attributes & msidbComponentAttributesPermanent)
{ {
TRACE("permanent component, not removing directory\n"); TRACE("permanent component, not removing directory\n");
continue; continue;
} }
folder = msi_get_loaded_folder( package, comp->Directory ); if (comp->assembly && !comp->assembly->application)
remove_folder( folder ); msi_uninstall_assembly( package, comp );
else
{
MSIFOLDER *folder = msi_get_loaded_folder( package, comp->Directory );
remove_folder( folder );
}
} }
msi_destroy_assembly_caches( package );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View file

@ -347,16 +347,10 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf ); return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
} }
static WCHAR *get_source_root( MSIDATABASE *db ) static WCHAR *get_source_root( MSIPACKAGE *package )
{ {
WCHAR *path, *p; msi_set_sourcedir_props( package, FALSE );
return msi_dup_property( package->db, szSourceDir );
if ((path = msi_dup_property( db, szSourceDir ))) return path;
if ((path = msi_dup_property( db, szDatabase )))
{
if ((p = strrchrW( path, '\\' ))) p[1] = 0;
}
return path;
} }
WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder ) WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
@ -372,7 +366,7 @@ WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOL
/* special resolving for root dir */ /* special resolving for root dir */
if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource) if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource)
{ {
f->ResolvedSource = get_source_root( package->db ); f->ResolvedSource = get_source_root( package );
} }
if (folder) *folder = f; if (folder) *folder = f;
if (f->ResolvedSource) if (f->ResolvedSource)
@ -388,7 +382,7 @@ WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOL
p = msi_resolve_source_folder( package, parent, NULL ); p = msi_resolve_source_folder( package, parent, NULL );
if (package->WordCount & msidbSumInfoSourceTypeCompressed) if (package->WordCount & msidbSumInfoSourceTypeCompressed)
path = get_source_root( package->db ); path = get_source_root( package );
else if (package->WordCount & msidbSumInfoSourceTypeSFN) else if (package->WordCount & msidbSumInfoSourceTypeSFN)
path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL ); path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
else else
@ -559,8 +553,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
MSIFOLDER *child; MSIFOLDER *child;
WCHAR *target_path; WCHAR *target_path;
if (!(target_path = strdupW( path ))) return; if (!(target_path = msi_normalize_path( path ))) return;
msi_clean_path( target_path );
if (strcmpW( target_path, folder->ResolvedTarget )) if (strcmpW( target_path, folder->ResolvedTarget ))
{ {
msi_free( folder->ResolvedTarget ); msi_free( folder->ResolvedTarget );
@ -578,7 +571,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath ) UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
{ {
DWORD attrib, len; DWORD attrib;
MSIFOLDER *folder; MSIFOLDER *folder;
MSIFILE *file; MSIFILE *file;
@ -593,17 +586,7 @@ UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolder
} }
if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY; if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
len = strlenW( szFolderPath ); set_target_path( package, folder, szFolderPath );
if (len && szFolderPath[len - 1] != '\\')
{
WCHAR *path = msi_alloc( (len + 2) * sizeof(WCHAR) );
memcpy( path, szFolderPath, len * sizeof(WCHAR) );
path[len] = '\\';
path[len + 1] = 0;
set_target_path( package, folder, path );
msi_free( path );
}
else set_target_path( package, folder, szFolderPath );
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry ) LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{ {
@ -778,7 +761,11 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
break; break;
case MSIRUNMODE_REBOOTATEND: case MSIRUNMODE_REBOOTATEND:
r = package->need_reboot; r = package->need_reboot_at_end;
break;
case MSIRUNMODE_REBOOTNOW:
r = package->need_reboot_now;
break; break;
case MSIRUNMODE_LOGENABLED: case MSIRUNMODE_LOGENABLED:
@ -831,13 +818,13 @@ UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
switch (iRunMode) switch (iRunMode)
{ {
case MSIRUNMODE_REBOOTATEND: case MSIRUNMODE_REBOOTATEND:
package->need_reboot = 1; package->need_reboot_at_end = (fState != 0);
r = ERROR_SUCCESS; r = ERROR_SUCCESS;
break; break;
case MSIRUNMODE_REBOOTNOW: case MSIRUNMODE_REBOOTNOW:
FIXME("unimplemented run mode: %d\n", iRunMode); package->need_reboot_now = (fState != 0);
r = ERROR_FUNCTION_FAILED; r = ERROR_SUCCESS;
break; break;
default: default:

View file

@ -77,9 +77,8 @@ static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
static const WCHAR error_prop[] = {'E','r','r','o','r','D','i','a','l','o','g',0}; static const WCHAR error_prop[] = {'E','r','r','o','r','D','i','a','l','o','g',0};
if ((msi_get_property_int(package->db, szUILevel, 0) & INSTALLUILEVEL_MASK) == if ((package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE &&
INSTALLUILEVEL_NONE && !gUIHandlerA && !gUIHandlerW && !gUIHandlerRecord) !gUIHandlerA && !gUIHandlerW && !gUIHandlerRecord) return ERROR_SUCCESS;
return ERROR_SUCCESS;
error = msi_build_error_string(package, 1302, 1, mi->disk_prompt); error = msi_build_error_string(package, 1302, 1, mi->disk_prompt);
error_dialog = msi_dup_property(package->db, error_prop); error_dialog = msi_dup_property(package->db, error_prop);
@ -428,7 +427,7 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
goto done; goto done;
} }
TRACE("extracting %s\n", debugstr_w(path)); TRACE("extracting %s -> %s\n", debugstr_w(data->curfile), debugstr_w(path));
attrs = attrs & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); attrs = attrs & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL; if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL;
@ -478,7 +477,7 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
MoveFileExW(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) && MoveFileExW(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) &&
MoveFileExW(tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT)) MoveFileExW(tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT))
{ {
data->package->need_reboot = 1; data->package->need_reboot_at_end = 1;
} }
else else
{ {

View file

@ -42,6 +42,9 @@
#include "wintrust.h" #include "wintrust.h"
#include "softpub.h" #include "softpub.h"
#include "initguid.h"
#include "msxml2.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h" #include "wine/unicode.h"
@ -304,7 +307,6 @@ done:
return r; return r;
} }
static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes ) static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes )
{ {
MSIHANDLE patch, info = 0; MSIHANDLE patch, info = 0;
@ -580,17 +582,66 @@ static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
return r; return r;
} }
/* IXMLDOMDocument should be set to XPath mode already */
static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc )
{
static const WCHAR queryW[] = {'M','s','i','P','a','t','c','h','/',
'T','a','r','g','e','t','P','r','o','d','u','c','t','/',
'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0};
UINT r = ERROR_FUNCTION_FAILED;
IXMLDOMNodeList *list;
LPWSTR product_code;
IXMLDOMNode *node;
HRESULT hr;
BSTR s;
product_code = msi_dup_property( package->db, szProductCode );
if (!product_code)
{
/* FIXME: the property ProductCode should be written into the DB somewhere */
ERR("no product code to check\n");
return ERROR_SUCCESS;
}
s = SysAllocString(queryW);
hr = IXMLDOMDocument_selectNodes( desc, s, &list );
SysFreeString(s);
if (hr != S_OK)
return ERROR_INVALID_PATCH_XML;
while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS)
{
hr = IXMLDOMNode_get_text( node, &s );
IXMLDOMNode_Release( node );
if (hr == S_OK)
{
if (!strcmpW( s, product_code )) r = ERROR_SUCCESS;
SysFreeString( s );
}
}
IXMLDOMNodeList_Release( list );
if (r != ERROR_SUCCESS)
TRACE("patch not applicable\n");
msi_free( product_code );
return r;
}
static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info ) static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info )
{ {
IXMLDOMDocument *desc = NULL;
DWORD i; DWORD i;
if (count > 1)
FIXME("patch ordering not supported\n");
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
switch (info[i].ePatchDataType) switch (info[i].ePatchDataType)
{ {
case MSIPATCH_DATATYPE_PATCHFILE: case MSIPATCH_DATATYPE_PATCHFILE:
{ {
FIXME("patch ordering not supported\n");
if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS) if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS)
{ {
info[i].dwOrder = ~0u; info[i].dwOrder = ~0u;
@ -603,19 +654,72 @@ static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCH
} }
break; break;
} }
case MSIPATCH_DATATYPE_XMLPATH:
case MSIPATCH_DATATYPE_XMLBLOB:
{
VARIANT_BOOL b;
HRESULT hr;
BSTR s;
if (!desc)
{
hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
&IID_IXMLDOMDocument, (void**)&desc );
if (hr != S_OK)
{
ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr);
return ERROR_FUNCTION_FAILED;
}
}
s = SysAllocString( info[i].szPatchData );
if (info[i].ePatchDataType == MSIPATCH_DATATYPE_XMLPATH)
{
VARIANT src;
V_VT(&src) = VT_BSTR;
V_BSTR(&src) = s;
hr = IXMLDOMDocument_load( desc, src, &b );
}
else
hr = IXMLDOMDocument_loadXML( desc, s, &b );
SysFreeString( s );
if ( hr != S_OK )
{
ERR("failed to parse patch description\n");
IXMLDOMDocument_Release( desc );
break;
}
if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS)
{
info[i].dwOrder = ~0u;
info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
}
else
{
info[i].dwOrder = i;
info[i].uStatus = ERROR_SUCCESS;
}
break;
}
default: default:
{ {
FIXME("patch data type %u not supported\n", info[i].ePatchDataType); FIXME("unknown patch data type %u\n", info[i].ePatchDataType);
info[i].dwOrder = i; info[i].dwOrder = i;
info[i].uStatus = ERROR_SUCCESS; info[i].uStatus = ERROR_SUCCESS;
break; break;
} }
} }
TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData)); TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData));
TRACE("ePatchDataType: %u\n", info[i].ePatchDataType); TRACE("ePatchDataType: %u\n", info[i].ePatchDataType);
TRACE("dwOrder: %u\n", info[i].dwOrder); TRACE("dwOrder: %u\n", info[i].dwOrder);
TRACE("uStatus: %u\n", info[i].uStatus); TRACE("uStatus: %u\n", info[i].uStatus);
} }
if (desc) IXMLDOMDocument_Release( desc );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -2008,7 +2112,7 @@ UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context) static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
{ {
UINT r; UINT r;
HKEY hkey; HKEY hkey = NULL;
r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE); r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
RegCloseKey(hkey); RegCloseKey(hkey);
@ -2044,7 +2148,7 @@ static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
return (res == ERROR_SUCCESS); return (res == ERROR_SUCCESS);
} }
static BOOL msi_comp_find_prodcode(LPWSTR squished_pc, static UINT msi_comp_find_prodcode(LPWSTR squished_pc,
MSIINSTALLCONTEXT context, MSIINSTALLCONTEXT context,
LPCWSTR comp, LPWSTR val, DWORD *sz) LPCWSTR comp, LPWSTR val, DWORD *sz)
{ {
@ -2058,14 +2162,14 @@ static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE); r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
return FALSE; return r;
res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz); res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
return FALSE; return res;
RegCloseKey(hkey); RegCloseKey(hkey);
return TRUE; return res;
} }
UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode, UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
@ -2073,7 +2177,6 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
LPCWSTR szComponent, INSTALLSTATE *pdwState) LPCWSTR szComponent, INSTALLSTATE *pdwState)
{ {
WCHAR squished_pc[GUID_SIZE]; WCHAR squished_pc[GUID_SIZE];
WCHAR val[MAX_PATH];
BOOL found; BOOL found;
DWORD sz; DWORD sz;
@ -2104,21 +2207,29 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
*pdwState = INSTALLSTATE_UNKNOWN; *pdwState = INSTALLSTATE_UNKNOWN;
sz = MAX_PATH; sz = 0;
if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz)) if (msi_comp_find_prodcode(squished_pc, dwContext, szComponent, NULL, &sz))
return ERROR_UNKNOWN_COMPONENT; return ERROR_UNKNOWN_COMPONENT;
if (sz == 0) if (sz == 0)
*pdwState = INSTALLSTATE_NOTUSED; *pdwState = INSTALLSTATE_NOTUSED;
else else
{ {
WCHAR *val;
UINT r;
if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY;
if ((r = msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz)))
return r;
if (lstrlenW(val) > 2 && if (lstrlenW(val) > 2 &&
val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9') val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':')
{ {
*pdwState = INSTALLSTATE_SOURCE; *pdwState = INSTALLSTATE_SOURCE;
} }
else else
*pdwState = INSTALLSTATE_LOCAL; *pdwState = INSTALLSTATE_LOCAL;
msi_free( val );
} }
TRACE("-> %d\n", *pdwState); TRACE("-> %d\n", *pdwState);
@ -2476,6 +2587,7 @@ HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR path, DWORD flags, PCCER
data.dwProvFlags = 0; data.dwProvFlags = 0;
data.dwUIContext = WTD_UICONTEXT_INSTALL; data.dwUIContext = WTD_UICONTEXT_INSTALL;
hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data ); hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
*cert = NULL;
if (FAILED(hr)) goto done; if (FAILED(hr)) goto done;
if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 ))) if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 )))
@ -3021,11 +3133,7 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen,
WCHAR *langbuf, DWORD *langlen ) WCHAR *langbuf, DWORD *langlen )
{ {
static const WCHAR szVersionResource[] = {'\\',0}; static const WCHAR szVersionResource[] = {'\\',0};
static const WCHAR szVersionFormat[] = { static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
'%','d','.','%','d','.','%','d','.','%','d',0};
static const WCHAR szLangResource[] = {
'\\','V','a','r','F','i','l','e','I','n','f','o','\\',
'T','r','a','n','s','l','a','t','i','o','n',0};
static const WCHAR szLangFormat[] = {'%','d',0}; static const WCHAR szLangFormat[] = {'%','d',0};
UINT ret = ERROR_SUCCESS; UINT ret = ERROR_SUCCESS;
DWORD len, error; DWORD len, error;
@ -3100,18 +3208,18 @@ UINT WINAPI MsiGetFileVersionW( LPCWSTR path, LPWSTR verbuf, LPDWORD verlen,
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
ret = get_file_version( path, verbuf, verlen, langbuf, langlen ); ret = get_file_version( path, verbuf, verlen, langbuf, langlen );
if (ret == ERROR_RESOURCE_DATA_NOT_FOUND) if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen)
{ {
int len; int len;
WCHAR *version = msi_font_version_from_file( path ); WCHAR *version = msi_font_version_from_file( path );
if (!version) return ERROR_FILE_INVALID; if (!version) return ERROR_FILE_INVALID;
len = strlenW( version ); len = strlenW( version );
if (*verlen > len) if (len >= *verlen) ret = ERROR_MORE_DATA;
else if (verbuf)
{ {
strcpyW( verbuf, version ); strcpyW( verbuf, version );
ret = ERROR_SUCCESS; ret = ERROR_SUCCESS;
} }
else ret = ERROR_MORE_DATA;
*verlen = len; *verlen = len;
msi_free( version ); msi_free( version );
} }
@ -3909,24 +4017,34 @@ UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
} }
length = GetFileSize( handle, NULL ); length = GetFileSize( handle, NULL );
mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL ); if (length)
if (mapping)
{ {
p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length ); mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
if (p) if (mapping)
{ {
MD5_CTX ctx; p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
if (p)
{
MD5_CTX ctx;
MD5Init( &ctx ); MD5Init( &ctx );
MD5Update( &ctx, p, length ); MD5Update( &ctx, p, length );
MD5Final( &ctx ); MD5Final( &ctx );
UnmapViewOfFile( p ); UnmapViewOfFile( p );
memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData ); memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
r = ERROR_SUCCESS; r = ERROR_SUCCESS;
}
CloseHandle( mapping );
} }
CloseHandle( mapping );
} }
else
{
/* Empty file -> set hash to 0 */
memset( pHash->dwData, 0, sizeof pHash->dwData );
r = ERROR_SUCCESS;
}
CloseHandle( handle ); CloseHandle( handle );
return r; return r;

View file

@ -24,7 +24,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE STRINGTABLE
{ {
4 "The specified installation package could not be opened. Please check the file path and try again." 4 "The specified installation package could not be opened. Please check the file path and try again."
5 "path %s not found" 5 "path %s not found"
9 "insert disk %s" 9 "insert disk %s"
10 "Windows Installer %s\n\n\ 10 "Windows Installer %s\n\n\
@ -44,12 +44,12 @@ Advertise a product:\n\
Apply a patch:\n\ Apply a patch:\n\
\t/p patch_package [property]\n\ \t/p patch_package [property]\n\
\t/p patch_package /a package [property]\n\ \t/p patch_package /a package [property]\n\
Log and UI Modifiers for above commands:\n\ Log and user interface modifiers for the above commands:\n\
\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n\ \t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] log_file\n\
\t/q{|n|b|r|f|n+|b+|b-}\n\ \t/q{|n|b|r|f|n+|b+|b-}\n\
Register MSI Service:\n\ Register the MSI Service:\n\
\t/y\n\ \t/y\n\
Unregister MSI Service:\n\ Unregister the MSI Service:\n\
\t/z\n\ \t/z\n\
Display this help:\n\ Display this help:\n\
\t/help\n\ \t/help\n\
@ -82,9 +82,9 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#define WINE_FILEDESCRIPTION_STR "Wine MSI dll" #define WINE_FILEDESCRIPTION_STR "Wine MSI dll"
#define WINE_FILENAME_STR "msi.dll" #define WINE_FILENAME_STR "msi.dll"
#define WINE_FILEVERSION 4,5,6001,22159 #define WINE_FILEVERSION 4,5,6001,22299
#define WINE_FILEVERSION_STR "4.5.6001.22159" #define WINE_FILEVERSION_STR "4.5.6001.22299"
#define WINE_PRODUCTVERSION 4,5,6001,22159 #define WINE_PRODUCTVERSION 4,5,6001,22299
#define WINE_PRODUCTVERSION_STR "4.5.6001.22159" #define WINE_PRODUCTVERSION_STR "4.5.6001.22299"
#include "wine/wine_common_ver.rc" #include "wine/wine_common_ver.rc"

View file

@ -80,7 +80,7 @@ HKCR
{ {
CLSID = s '{000C101D-0000-0000-C000-000000000046}' CLSID = s '{000C101D-0000-0000-C000-000000000046}'
} }
NoRemove Typelib NoRemove Typelib
{ {
NoRemove '{000C1092-0000-0000-C000-000000000046}' NoRemove '{000C1092-0000-0000-C000-000000000046}'

View file

@ -282,8 +282,8 @@
286 stdcall MsiEndTransaction(long) 286 stdcall MsiEndTransaction(long)
287 stub MsiJoinTransaction 287 stub MsiJoinTransaction
288 stub MsiSetOfflineContextW 288 stub MsiSetOfflineContextW
289 stub MsiEnumComponentsExA 289 stdcall MsiEnumComponentsExA(str long long ptr ptr ptr ptr)
290 stub MsiEnumComponentsExW 290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr)
291 stub MsiEnumClientsExA 291 stub MsiEnumClientsExA
292 stub MsiEnumClientsExW 292 stub MsiEnumClientsExW
293 stub MsiGetComponentPathExA 293 stub MsiGetComponentPathExA

View file

@ -338,7 +338,8 @@ enum platform
{ {
PLATFORM_INTEL, PLATFORM_INTEL,
PLATFORM_INTEL64, PLATFORM_INTEL64,
PLATFORM_X64 PLATFORM_X64,
PLATFORM_ARM
}; };
enum clr_version enum clr_version
@ -388,6 +389,7 @@ typedef struct tagMSIPACKAGE
LPWSTR localfile; LPWSTR localfile;
BOOL delete_on_close; BOOL delete_on_close;
INSTALLUILEVEL ui_level;
UINT CurrentInstallState; UINT CurrentInstallState;
msi_dialog *dialog; msi_dialog *dialog;
LPWSTR next_dialog; LPWSTR next_dialog;
@ -405,7 +407,8 @@ typedef struct tagMSIPACKAGE
unsigned char scheduled_action_running : 1; unsigned char scheduled_action_running : 1;
unsigned char commit_action_running : 1; unsigned char commit_action_running : 1;
unsigned char rollback_action_running : 1; unsigned char rollback_action_running : 1;
unsigned char need_reboot : 1; unsigned char need_reboot_at_end : 1;
unsigned char need_reboot_now : 1;
unsigned char need_rollback : 1; unsigned char need_rollback : 1;
} MSIPACKAGE; } MSIPACKAGE;
@ -998,7 +1001,7 @@ extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD ) DECLSPEC
extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ) DECLSPEC_HIDDEN; extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ) DECLSPEC_HIDDEN;
extern WCHAR *msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder) DECLSPEC_HIDDEN; extern WCHAR *msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder) DECLSPEC_HIDDEN;
extern void msi_resolve_target_folder(MSIPACKAGE *package, const WCHAR *name, BOOL load_prop) DECLSPEC_HIDDEN; extern void msi_resolve_target_folder(MSIPACKAGE *package, const WCHAR *name, BOOL load_prop) DECLSPEC_HIDDEN;
extern void msi_clean_path( WCHAR *p ) DECLSPEC_HIDDEN; extern WCHAR *msi_normalize_path(const WCHAR *) DECLSPEC_HIDDEN;
extern WCHAR *msi_resolve_file_source(MSIPACKAGE *package, MSIFILE *file) DECLSPEC_HIDDEN; extern WCHAR *msi_resolve_file_source(MSIPACKAGE *package, MSIFILE *file) DECLSPEC_HIDDEN;
extern const WCHAR *msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name) DECLSPEC_HIDDEN; extern const WCHAR *msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name) DECLSPEC_HIDDEN;
extern void msi_reset_folders( MSIPACKAGE *package, BOOL source ) DECLSPEC_HIDDEN; extern void msi_reset_folders( MSIPACKAGE *package, BOOL source ) DECLSPEC_HIDDEN;
@ -1024,6 +1027,7 @@ extern UINT msi_create_empty_local_file(LPWSTR path, LPCWSTR suffix) DECLSPEC_HI
extern UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace) DECLSPEC_HIDDEN; extern UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace) DECLSPEC_HIDDEN;
extern MSIASSEMBLY *msi_load_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN; extern MSIASSEMBLY *msi_load_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN;
extern UINT msi_install_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN; extern UINT msi_install_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN;
extern UINT msi_uninstall_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN;
extern BOOL msi_init_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN; extern BOOL msi_init_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN;
extern void msi_destroy_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN; extern void msi_destroy_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN;
extern WCHAR *msi_font_version_from_file(const WCHAR *) DECLSPEC_HIDDEN; extern WCHAR *msi_font_version_from_file(const WCHAR *) DECLSPEC_HIDDEN;
@ -1077,6 +1081,7 @@ static const WCHAR szSOURCEDIR[] = {'S','O','U','R','C','E','D','I','R',0};
static const WCHAR szRootDrive[] = {'R','O','O','T','D','R','I','V','E',0}; static const WCHAR szRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
static const WCHAR szTargetDir[] = {'T','A','R','G','E','T','D','I','R',0}; static const WCHAR szTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
static const WCHAR szLocalSid[] = {'S','-','1','-','5','-','1','8',0}; static const WCHAR szLocalSid[] = {'S','-','1','-','5','-','1','8',0};
static const WCHAR szAllSid[] = {'S','-','1','-','1','-','0',0};
static const WCHAR szEmpty[] = {0}; static const WCHAR szEmpty[] = {0};
static const WCHAR szAll[] = {'A','L','L',0}; static const WCHAR szAll[] = {'A','L','L',0};
static const WCHAR szOne[] = {'1',0}; static const WCHAR szOne[] = {'1',0};
@ -1147,6 +1152,7 @@ static const WCHAR szIntel[] = {'I','n','t','e','l',0};
static const WCHAR szIntel64[] = {'I','n','t','e','l','6','4',0}; static const WCHAR szIntel64[] = {'I','n','t','e','l','6','4',0};
static const WCHAR szX64[] = {'x','6','4',0}; static const WCHAR szX64[] = {'x','6','4',0};
static const WCHAR szAMD64[] = {'A','M','D','6','4',0}; static const WCHAR szAMD64[] = {'A','M','D','6','4',0};
static const WCHAR szARM[] = {'A','r','m',0};
static const WCHAR szWow6432NodeCLSID[] = {'W','o','w','6','4','3','2','N','o','d','e','\\','C','L','S','I','D',0}; static const WCHAR szWow6432NodeCLSID[] = {'W','o','w','6','4','3','2','N','o','d','e','\\','C','L','S','I','D',0};
static const WCHAR szWow6432Node[] = {'W','o','w','6','4','3','2','N','o','d','e',0}; static const WCHAR szWow6432Node[] = {'W','o','w','6','4','3','2','N','o','d','e',0};
static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0}; static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0};
@ -1167,6 +1173,7 @@ static const WCHAR szAppDataFolder[] = {'A','p','p','D','a','t','a','F','o','l',
static const WCHAR szRollbackDisabled[] = {'R','o','l','l','b','a','c','k','D','i','s','a','b','l','e','d',0}; static const WCHAR szRollbackDisabled[] = {'R','o','l','l','b','a','c','k','D','i','s','a','b','l','e','d',0};
static const WCHAR szName[] = {'N','a','m','e',0}; static const WCHAR szName[] = {'N','a','m','e',0};
static const WCHAR szData[] = {'D','a','t','a',0}; static const WCHAR szData[] = {'D','a','t','a',0};
static const WCHAR szLangResource[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0};
/* memory allocation macro functions */ /* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1); static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);

View file

@ -884,10 +884,9 @@ static VOID set_installer_properties(MSIPACKAGE *package)
GetNativeSystemInfo( &sys_info ); GetNativeSystemInfo( &sys_info );
sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
msi_set_property( package->db, szIntel, bufstr );
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{ {
msi_set_property( package->db, szIntel, bufstr );
GetSystemDirectoryW( pth, MAX_PATH ); GetSystemDirectoryW( pth, MAX_PATH );
PathAddBackslashW( pth ); PathAddBackslashW( pth );
msi_set_property( package->db, szSystemFolder, pth ); msi_set_property( package->db, szSystemFolder, pth );
@ -1154,9 +1153,9 @@ void msi_adjust_privilege_properties( MSIPACKAGE *package )
MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
{ {
static const WCHAR szpi[] = {'%','i',0}; static const WCHAR fmtW[] = {'%','u',0};
MSIPACKAGE *package; MSIPACKAGE *package;
WCHAR uilevel[10]; WCHAR uilevel[11];
UINT r; UINT r;
TRACE("%p\n", db); TRACE("%p\n", db);
@ -1181,7 +1180,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
set_installed_prop( package ); set_installed_prop( package );
set_installer_properties( package ); set_installer_properties( package );
sprintfW(uilevel,szpi,gUILevel); package->ui_level = gUILevel;
sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
msi_set_property(package->db, szUILevel, uilevel); msi_set_property(package->db, szUILevel, uilevel);
r = msi_load_summary_properties( package ); r = msi_load_summary_properties( package );
@ -1297,6 +1297,8 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
package->platform = PLATFORM_INTEL64; package->platform = PLATFORM_INTEL64;
else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 )) else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 ))
package->platform = PLATFORM_X64; package->platform = PLATFORM_X64;
else if (!strcmpW( template, szARM ))
package->platform = PLATFORM_ARM;
else else
{ {
WARN("unknown platform %s\n", debugstr_w(template)); WARN("unknown platform %s\n", debugstr_w(template));
@ -1341,9 +1343,11 @@ static UINT validate_package( MSIPACKAGE *package )
UINT i; UINT i;
if (package->platform == PLATFORM_INTEL64) if (package->platform == PLATFORM_INTEL64)
{
return ERROR_INSTALL_PLATFORM_UNSUPPORTED; return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
} #ifndef __arm__
if (package->platform == PLATFORM_ARM)
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
#endif
IsWow64Process( GetCurrentProcess(), &is_wow64 ); IsWow64Process( GetCurrentProcess(), &is_wow64 );
if (package->platform == PLATFORM_X64) if (package->platform == PLATFORM_X64)
{ {
@ -1451,6 +1455,9 @@ static UINT get_registered_local_package( const WCHAR *product, const WCHAR *pac
if (!strcmpiW( package, unsquashed )) if (!strcmpiW( package, unsquashed ))
{ {
WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
if (!filename)
goto done;
strcpyW( localfile, filename ); strcpyW( localfile, filename );
msi_free( filename ); msi_free( filename );
r = ERROR_SUCCESS; r = ERROR_SUCCESS;
@ -1749,13 +1756,11 @@ MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
{ {
static const WCHAR szActionData[] = static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0};
{'A','c','t','i','o','n','D','a','t','a',0}; static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
static const WCHAR szSetProgress[] = static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0};
{'S','e','t','P','r','o','g','r','e','s','s',0}; MSIRECORD *uirow;
static const WCHAR szActionText[] = LPWSTR deformated, message;
{'A','c','t','i','o','n','T','e','x','t',0};
LPWSTR message;
DWORD i, len, total_len, log_type = 0; DWORD i, len, total_len, log_type = 0;
INT rc = 0; INT rc = 0;
char *msg; char *msg;
@ -1894,27 +1899,27 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
switch (eMessageType & 0xff000000) switch (eMessageType & 0xff000000)
{ {
case INSTALLMESSAGE_ACTIONDATA: case INSTALLMESSAGE_ACTIONDATA:
/* FIXME: format record here instead of in ui_actiondata to get the deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
* correct action data for external scripts */ uirow = MSI_CreateRecord(1);
ControlEvent_FireSubscribedEvent(package, szActionData, record); MSI_RecordSetStringW(uirow, 1, deformated);
break; msi_free(deformated);
case INSTALLMESSAGE_ACTIONSTART:
{ ControlEvent_FireSubscribedEvent(package, szActionData, uirow);
MSIRECORD *uirow;
LPWSTR deformated; msiobj_release(&uirow->hdr);
LPCWSTR action_text = MSI_RecordGetString(record, 2); break;
deformat_string(package, action_text, &deformated); case INSTALLMESSAGE_ACTIONSTART:
deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
uirow = MSI_CreateRecord(1); uirow = MSI_CreateRecord(1);
MSI_RecordSetStringW(uirow, 1, deformated); MSI_RecordSetStringW(uirow, 1, deformated);
TRACE("INSTALLMESSAGE_ACTIONSTART: %s\n", debugstr_w(deformated));
msi_free(deformated); msi_free(deformated);
ControlEvent_FireSubscribedEvent(package, szActionText, uirow); ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
msiobj_release(&uirow->hdr); msiobj_release(&uirow->hdr);
break; break;
}
case INSTALLMESSAGE_PROGRESS: case INSTALLMESSAGE_PROGRESS:
ControlEvent_FireSubscribedEvent(package, szSetProgress, record); ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
break; break;

View file

@ -1139,101 +1139,13 @@ UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid) UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
{ {
static const WCHAR pathW[] = {
'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','\\','P','r','o','d','u','c','t','s',0};
UINT r;
WCHAR szKeyName[SQUISH_GUID_SIZE];
HKEY key;
REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
DWORD machine_count, managed_count, unmanaged_count;
WCHAR keypath[MAX_PATH];
LPWSTR usersid = NULL;
static DWORD last_index;
TRACE("%d %p\n", index, lpguid); TRACE("%d %p\n", index, lpguid);
if (NULL == lpguid) if (NULL == lpguid)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
if (index && index - last_index != 1) return MsiEnumProductsExW( NULL, szAllSid, MSIINSTALLCONTEXT_ALL, index, lpguid,
return ERROR_INVALID_PARAMETER; NULL, NULL, NULL );
key = 0;
r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesProducts, 0, NULL, 0, access, NULL, &key, NULL);
if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &machine_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS ) goto failed;
if (machine_count && index <= machine_count)
{
r = RegEnumKeyW(key, index, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
{
unsquash_guid(szKeyName, lpguid);
last_index = index;
RegCloseKey(key);
return ERROR_SUCCESS;
}
}
RegCloseKey(key);
key = 0;
if (!(usersid = get_user_sid()))
{
ERR("Failed to retrieve user SID\n");
last_index = 0;
return ERROR_FUNCTION_FAILED;
}
sprintfW(keypath, szInstaller_LocalManaged_fmt, usersid);
LocalFree(usersid);
r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &key, NULL);
if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &managed_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS ) goto failed;
if (managed_count && index <= machine_count + managed_count)
{
r = RegEnumKeyW(key, index - machine_count, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
{
unsquash_guid(szKeyName, lpguid);
last_index = index;
RegCloseKey(key);
return ERROR_SUCCESS;
}
}
RegCloseKey(key);
key = 0;
r = RegCreateKeyW(HKEY_CURRENT_USER, pathW, &key);
if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &unmanaged_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS ) goto failed;
if (unmanaged_count && index <= machine_count + managed_count + unmanaged_count)
{
r = RegEnumKeyW(key, index - machine_count - managed_count, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
{
unsquash_guid(szKeyName, lpguid);
last_index = index;
RegCloseKey(key);
return ERROR_SUCCESS;
}
}
failed:
RegCloseKey(key);
last_index = 0;
return ERROR_NO_MORE_ITEMS;
} }
UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
@ -1293,7 +1205,9 @@ UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
DWORD r; DWORD r;
WCHAR szwGuid[GUID_SIZE]; WCHAR szwGuid[GUID_SIZE];
TRACE("%d %p\n", index, lpguid); TRACE("%u, %p\n", index, lpguid);
if (!lpguid) return ERROR_INVALID_PARAMETER;
r = MsiEnumComponentsW(index, szwGuid); r = MsiEnumComponentsW(index, szwGuid);
if( r == ERROR_SUCCESS ) if( r == ERROR_SUCCESS )
@ -1304,22 +1218,222 @@ UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid) UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
{ {
HKEY hkey; TRACE("%u, %p\n", index, lpguid);
REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
WCHAR szKeyName[SQUISH_GUID_SIZE];
DWORD r;
TRACE("%d %p\n", index, lpguid); if (!lpguid) return ERROR_INVALID_PARAMETER;
r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szInstaller_Components, 0, NULL, 0, access, NULL, &hkey, NULL); return MsiEnumComponentsExW( szAllSid, MSIINSTALLCONTEXT_ALL, index, lpguid, NULL, NULL, NULL );
if( r != ERROR_SUCCESS ) }
UINT WINAPI MsiEnumComponentsExA( LPCSTR user_sid, DWORD ctx, DWORD index, CHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPSTR sid, LPDWORD sid_len )
{
UINT r;
WCHAR *user_sidW = NULL, *sidW = NULL, guidW[GUID_SIZE];
TRACE("%s, %u, %u, %p, %p, %p, %p\n", debugstr_a(user_sid), ctx, index, guid, installed_ctx,
sid, sid_len);
if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
if (user_sid && !(user_sidW = strdupAtoW( user_sid ))) return ERROR_OUTOFMEMORY;
if (sid && !(sidW = msi_alloc( *sid_len * sizeof(WCHAR) )))
{
msi_free( user_sidW );
return ERROR_OUTOFMEMORY;
}
r = MsiEnumComponentsExW( user_sidW, ctx, index, guidW, installed_ctx, sidW, sid_len );
if (r == ERROR_SUCCESS)
{
if (guid) WideCharToMultiByte( CP_ACP, 0, guidW, GUID_SIZE, guid, GUID_SIZE, NULL, NULL );
if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
}
msi_free( user_sidW );
msi_free( sidW );
return r;
}
static UINT fetch_machine_component( DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
static const WCHAR componentsW[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
'S','-','1','-','5','-','1','8','\\','C','o','m','p','o','n','e','n','t','s',0};
UINT r = ERROR_SUCCESS;
WCHAR component[GUID_SIZE];
DWORD i = 0, len_component;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key_components;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, componentsW, 0, access, &key_components ))
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;
r = RegEnumKeyW(hkey, index, szKeyName, SQUISH_GUID_SIZE); len_component = sizeof(component)/sizeof(component[0]);
if( r == ERROR_SUCCESS ) while (!RegEnumKeyExW( key_components, i, component, &len_component, NULL, NULL, NULL, NULL ))
unsquash_guid(szKeyName, lpguid); {
if (*idx == index) goto found;
(*idx)++;
len_component = sizeof(component)/sizeof(component[0]);
i++;
}
RegCloseKey( key_components );
return ERROR_NO_MORE_ITEMS;
found:
if (sid_len)
{
if (*sid_len < 1)
{
*sid_len = 1;
r = ERROR_MORE_DATA;
}
else if (sid)
{
*sid_len = 0;
sid[0] = 0;
}
}
if (guid) unsquash_guid( component, guid );
if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
RegCloseKey( key_components );
return r;
}
static UINT fetch_user_component( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx,
WCHAR guid[39], MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid,
LPDWORD sid_len )
{
static const WCHAR userdataW[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a',0};
static const WCHAR componentsW[] = {'\\','C','o','m','p','o','n','e','n','t','s',0};
UINT r = ERROR_SUCCESS;
WCHAR path[MAX_PATH], component[GUID_SIZE], user[128];
DWORD i = 0, j = 0, len_component, len_user;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key_users, key_components;
if (ctx == MSIINSTALLCONTEXT_USERMANAGED) /* FIXME: were to find these? */
return ERROR_NO_MORE_ITEMS;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, userdataW, 0, access, &key_users ))
return ERROR_NO_MORE_ITEMS;
len_user = sizeof(user)/sizeof(user[0]);
while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
{
if ((strcmpW( usersid, szAllSid ) && strcmpW( usersid, user )) ||
!strcmpW( szLocalSid, user ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
strcpyW( path, user );
strcatW( path, componentsW );
if (RegOpenKeyExW( key_users, path, 0, access, &key_components ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
len_component = sizeof(component)/sizeof(component[0]);
while (!RegEnumKeyExW( key_components, j, component, &len_component, NULL, NULL, NULL, NULL ))
{
if (*idx == index) goto found;
(*idx)++;
len_component = sizeof(component)/sizeof(component[0]);
j++;
}
RegCloseKey( key_components );
len_user = sizeof(user)/sizeof(user[0]);
i++;
}
RegCloseKey( key_users );
return ERROR_NO_MORE_ITEMS;
found:
if (sid_len)
{
if (*sid_len < len_user + 1)
{
*sid_len = len_user + 1;
r = ERROR_MORE_DATA;
}
else if (sid)
{
*sid_len = len_user;
strcpyW( sid, user );
}
}
if (guid) unsquash_guid( component, guid );
if (installed_ctx) *installed_ctx = ctx;
RegCloseKey( key_components );
RegCloseKey( key_users );
return r;
}
static UINT enum_components( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
UINT r = ERROR_NO_MORE_ITEMS;
WCHAR *user = NULL;
if (!usersid)
{
usersid = user = get_user_sid();
if (!user) return ERROR_FUNCTION_FAILED;
}
if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
{
r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERMANAGED, index, idx, guid,
installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
{
r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index, idx, guid,
installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_MACHINE)
{
r = fetch_machine_component( MSIINSTALLCONTEXT_MACHINE, index, idx, guid, installed_ctx,
sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
done:
LocalFree( user );
return r;
}
UINT WINAPI MsiEnumComponentsExW( LPCWSTR user_sid, DWORD ctx, DWORD index, WCHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
UINT r;
DWORD idx = 0;
static DWORD last_index;
TRACE("%s, %u, %u, %p, %p, %p, %p\n", debugstr_w(user_sid), ctx, index, guid, installed_ctx,
sid, sid_len);
if ((sid && !sid_len) || !ctx || (user_sid && ctx == MSIINSTALLCONTEXT_MACHINE))
return ERROR_INVALID_PARAMETER;
if (index && index - last_index != 1)
return ERROR_INVALID_PARAMETER;
if (!index) last_index = 0;
r = enum_components( user_sid, ctx, index, &idx, guid, installed_ctx, sid, sid_len );
if (r == ERROR_SUCCESS)
last_index = index;
else
last_index = 0;
RegCloseKey(hkey);
return r; return r;
} }
@ -2113,22 +2227,252 @@ done:
return r; return r;
} }
UINT WINAPI MsiEnumProductsExA( LPCSTR szProductCode, LPCSTR szUserSid, UINT WINAPI MsiEnumProductsExA( LPCSTR product, LPCSTR usersid, DWORD ctx, DWORD index,
DWORD dwContext, DWORD dwIndex, CHAR szInstalledProductCode[39], CHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT* pdwInstalledContext, LPSTR szSid, LPDWORD pcchSid) MSIINSTALLCONTEXT *installed_ctx, LPSTR sid, LPDWORD sid_len )
{ {
FIXME("%s %s %d %d %p %p %p %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid), UINT r;
dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext, WCHAR installed_productW[GUID_SIZE], *productW = NULL, *usersidW = NULL, *sidW = NULL;
szSid, pcchSid);
return ERROR_NO_MORE_ITEMS; TRACE("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_a(product), debugstr_a(usersid),
ctx, index, installed_product, installed_ctx, sid, sid_len);
if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
if (usersid && !(usersidW = strdupAtoW( usersid )))
{
msi_free( productW );
return ERROR_OUTOFMEMORY;
}
if (sid && !(sidW = msi_alloc( *sid_len * sizeof(WCHAR) )))
{
msi_free( usersidW );
msi_free( productW );
return ERROR_OUTOFMEMORY;
}
r = MsiEnumProductsExW( productW, usersidW, ctx, index, installed_productW,
installed_ctx, sidW, sid_len );
if (r == ERROR_SUCCESS)
{
if (installed_product) WideCharToMultiByte( CP_ACP, 0, installed_productW, GUID_SIZE,
installed_product, GUID_SIZE, NULL, NULL );
if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
}
msi_free( productW );
msi_free( usersidW );
msi_free( sidW );
return r;
} }
UINT WINAPI MsiEnumProductsExW( LPCWSTR szProductCode, LPCWSTR szUserSid, static UINT fetch_machine_product( const WCHAR *match, DWORD index, DWORD *idx,
DWORD dwContext, DWORD dwIndex, WCHAR szInstalledProductCode[39], WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT* pdwInstalledContext, LPWSTR szSid, LPDWORD pcchSid) MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
{ {
FIXME("%s %s %d %d %p %p %p %p\n", debugstr_w(szProductCode), debugstr_w(szUserSid), static const WCHAR productsW[] =
dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext, {'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
szSid, pcchSid); 'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
UINT r;
WCHAR product[GUID_SIZE];
DWORD i = 0, len;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, productsW, 0, access, &key ))
return ERROR_NO_MORE_ITEMS;
len = sizeof(product)/sizeof(product[0]);
while (!RegEnumKeyExW( key, i, product, &len, NULL, NULL, NULL, NULL ))
{
if (match && strcmpW( match, product ))
{
i++;
len = sizeof(product)/sizeof(product[0]);
continue;
}
if (*idx == index) goto found;
(*idx)++;
len = sizeof(product)/sizeof(product[0]);
i++;
}
RegCloseKey( key );
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;
found:
if (sid_len && *sid_len < 1)
{
*sid_len = 1;
r = ERROR_MORE_DATA;
}
else
{
if (installed_product) unsquash_guid( product, installed_product );
if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
if (sid)
{
sid[0] = 0;
*sid_len = 0;
}
r = ERROR_SUCCESS;
}
RegCloseKey( key );
return r;
}
static UINT fetch_user_product( const WCHAR *match, const WCHAR *usersid, DWORD ctx, DWORD index,
DWORD *idx, WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
{
static const WCHAR managedW[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s',
'i','o','n','\\','I','n','s','t','a','l','l','e','r','\\','M','a','n','a','g','e','d',0};
static const WCHAR managed_productsW[] =
{'\\','I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
static const WCHAR unmanaged_productsW[] =
{'\\','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','\\','P','r','o','d','u','c','t','s',0};
UINT r;
const WCHAR *subkey;
WCHAR path[MAX_PATH], product[GUID_SIZE], user[128];
DWORD i = 0, j = 0, len_product, len_user;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key_users, key_products;
if (ctx == MSIINSTALLCONTEXT_USERMANAGED)
{
subkey = managed_productsW;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, managedW, 0, access, &key_users ))
return ERROR_NO_MORE_ITEMS;
}
else if (ctx == MSIINSTALLCONTEXT_USERUNMANAGED)
{
subkey = unmanaged_productsW;
if (RegOpenKeyExW( HKEY_USERS, NULL, 0, access, &key_users ))
return ERROR_NO_MORE_ITEMS;
}
else return ERROR_INVALID_PARAMETER;
len_user = sizeof(user)/sizeof(user[0]);
while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
{
if (strcmpW( usersid, user ) && strcmpW( usersid, szAllSid ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
strcpyW( path, user );
strcatW( path, subkey );
if (RegOpenKeyExW( key_users, path, 0, access, &key_products ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
len_product = sizeof(product)/sizeof(product[0]);
while (!RegEnumKeyExW( key_products, j, product, &len_product, NULL, NULL, NULL, NULL ))
{
if (match && strcmpW( match, product ))
{
j++;
len_product = sizeof(product)/sizeof(product[0]);
continue;
}
if (*idx == index) goto found;
(*idx)++;
len_product = sizeof(product)/sizeof(product[0]);
j++;
}
RegCloseKey( key_products );
len_user = sizeof(user)/sizeof(user[0]);
i++;
}
RegCloseKey( key_users );
return ERROR_NO_MORE_ITEMS;
found:
if (sid_len && *sid_len <= len_user)
{
*sid_len = len_user;
r = ERROR_MORE_DATA;
}
else
{
if (installed_product) unsquash_guid( product, installed_product );
if (installed_ctx) *installed_ctx = ctx;
if (sid)
{
strcpyW( sid, user );
*sid_len = len_user;
}
r = ERROR_SUCCESS;
}
RegCloseKey( key_products );
RegCloseKey( key_users );
return r;
}
static UINT enum_products( const WCHAR *product, const WCHAR *usersid, DWORD ctx, DWORD index,
DWORD *idx, WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
{
UINT r = ERROR_NO_MORE_ITEMS;
WCHAR *user = NULL;
if (!usersid)
{
usersid = user = get_user_sid();
if (!user) return ERROR_FUNCTION_FAILED;
}
if (ctx & MSIINSTALLCONTEXT_MACHINE)
{
r = fetch_machine_product( product, index, idx, installed_product, installed_ctx,
sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
{
r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index,
idx, installed_product, installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
{
r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERMANAGED, index,
idx, installed_product, installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
done:
LocalFree( user );
return r;
}
UINT WINAPI MsiEnumProductsExW( LPCWSTR product, LPCWSTR usersid, DWORD ctx, DWORD index,
WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
UINT r;
DWORD idx = 0;
static DWORD last_index;
TRACE("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_w(product), debugstr_w(usersid),
ctx, index, installed_product, installed_ctx, sid, sid_len);
if ((sid && !sid_len) || !ctx || (usersid && ctx == MSIINSTALLCONTEXT_MACHINE))
return ERROR_INVALID_PARAMETER;
if (index && index - last_index != 1)
return ERROR_INVALID_PARAMETER;
if (!index) last_index = 0;
r = enum_products( product, usersid, ctx, index, &idx, installed_product, installed_ctx,
sid, sid_len );
if (r == ERROR_SUCCESS)
last_index = index;
else
last_index = 0;
return r;
} }

View file

@ -88,10 +88,7 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
DISPID dispid; DISPID dispid;
CLSID clsid; CLSID clsid;
VARIANT var; VARIANT var;
DWORD ret = ERROR_INSTALL_FAILURE;
/* Return success by default (if Windows Script not installed) - not native behavior. This
* should be here until we implement wine scripting. */
DWORD ret = ERROR_SUCCESS;
CoInitialize(NULL); CoInitialize(NULL);
@ -126,9 +123,6 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
goto done; goto done;
} }
/* If we got this far, Windows Script is installed, so don't return success by default anymore */
ret = ERROR_INSTALL_FAILURE;
/* Get the IActiveScriptParse engine interface */ /* Get the IActiveScriptParse engine interface */
hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse, (void **)&pActiveScriptParse); hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse, (void **)&pActiveScriptParse);
if (FAILED(hr)) goto done; if (FAILED(hr)) goto done;
@ -142,7 +136,7 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
if (FAILED(hr)) goto done; if (FAILED(hr)) goto done;
/* Add the session object */ /* Add the session object */
hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_ISVISIBLE); hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS);
if (FAILED(hr)) goto done; if (FAILED(hr)) goto done;
/* Pass the script to the engine */ /* Pass the script to the engine */

View file

@ -156,7 +156,7 @@ static struct expr * EXPR_wildcard( void *info );
/* Line 189 of yacc.c */ /* Line 189 of yacc.c */
#line 153 "sql.tab.c" #line 161 "sql.tab.c"
/* Enabling traces. */ /* Enabling traces. */
#ifndef YYDEBUG #ifndef YYDEBUG
@ -267,7 +267,7 @@ typedef union YYSTYPE
/* Line 214 of yacc.c */ /* Line 214 of yacc.c */
#line 264 "sql.tab.c" #line 272 "sql.tab.c"
} YYSTYPE; } YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */

View file

@ -1766,7 +1766,7 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec, UINT row) MSIRECORD *rec, UINT row)
{ {
MSITABLEVIEW *tv = (MSITABLEVIEW*)view; MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT r, column; UINT r, frow, column;
TRACE("%p %d %p\n", view, eModifyMode, rec ); TRACE("%p %d %p\n", view, eModifyMode, rec );
@ -1811,8 +1811,18 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
r = msi_table_assign( view, rec ); r = msi_table_assign( view, rec );
break; break;
case MSIMODIFY_REPLACE:
case MSIMODIFY_MERGE: case MSIMODIFY_MERGE:
/* check row that matches this record */
r = msi_table_find_row( tv, rec, &frow, &column );
if (r != ERROR_SUCCESS)
{
r = table_validate_new( tv, rec, NULL );
if (r == ERROR_SUCCESS)
r = TABLE_insert_row( view, rec, -1, FALSE );
}
break;
case MSIMODIFY_REPLACE:
case MSIMODIFY_VALIDATE: case MSIMODIFY_VALIDATE:
case MSIMODIFY_VALIDATE_FIELD: case MSIMODIFY_VALIDATE_FIELD:
case MSIMODIFY_VALIDATE_DELETE: case MSIMODIFY_VALIDATE_DELETE:
@ -2185,9 +2195,6 @@ UINT MSI_CommitTables( MSIDATABASE *db )
} }
} }
/* force everything to reload next time */
free_cached_tables( db );
hr = IStorage_Commit( db->storage, 0 ); hr = IStorage_Commit( db->storage, 0 );
if (FAILED( hr )) if (FAILED( hr ))
{ {
@ -2501,14 +2508,12 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
string_table *st, TRANSFORMDATA *transform, string_table *st, TRANSFORMDATA *transform,
UINT bytes_per_strref ) UINT bytes_per_strref )
{ {
UINT rawsize = 0;
BYTE *rawdata = NULL; BYTE *rawdata = NULL;
MSITABLEVIEW *tv = NULL; MSITABLEVIEW *tv = NULL;
UINT r, n, sz, i, mask; UINT r, n, sz, i, mask, num_cols, colcol = 0, rawsize = 0;
MSIRECORD *rec = NULL; MSIRECORD *rec = NULL;
UINT colcol = 0;
WCHAR coltable[32]; WCHAR coltable[32];
LPWSTR name; const WCHAR *name;
if (!transform) if (!transform)
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -2539,18 +2544,18 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
debugstr_w(name), tv->num_cols, tv->row_size, rawsize ); debugstr_w(name), tv->num_cols, tv->row_size, rawsize );
/* interpret the data */ /* interpret the data */
for( n=0; n < rawsize; ) for (n = 0; n < rawsize;)
{ {
mask = rawdata[n] | (rawdata[n+1] << 8); mask = rawdata[n] | (rawdata[n + 1] << 8);
if (mask & 1)
if (mask&1)
{ {
/* /*
* if the low bit is set, columns are continuous and * if the low bit is set, columns are continuous and
* the number of columns is specified in the high byte * the number of columns is specified in the high byte
*/ */
sz = 2; sz = 2;
for( i=0; i<tv->num_cols; i++ ) num_cols = mask >> 8;
for (i = 0; i < num_cols; i++)
{ {
if( (tv->columns[i].type & MSITYPE_STRING) && if( (tv->columns[i].type & MSITYPE_STRING) &&
! MSITYPE_IS_BINARY(tv->columns[i].type) ) ! MSITYPE_IS_BINARY(tv->columns[i].type) )
@ -2570,12 +2575,13 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
* and it means that this row should be deleted. * and it means that this row should be deleted.
*/ */
sz = 2; sz = 2;
for( i=0; i<tv->num_cols; i++ ) num_cols = tv->num_cols;
for (i = 0; i < num_cols; i++)
{ {
if( (tv->columns[i].type & MSITYPE_KEY) || ((1<<i)&mask)) if ((tv->columns[i].type & MSITYPE_KEY) || ((1 << i) & mask))
{ {
if( (tv->columns[i].type & MSITYPE_STRING) && if ((tv->columns[i].type & MSITYPE_STRING) &&
! MSITYPE_IS_BINARY(tv->columns[i].type) ) !MSITYPE_IS_BINARY(tv->columns[i].type))
sz += bytes_per_strref; sz += bytes_per_strref;
else else
sz += bytes_per_column( tv->db, &tv->columns[i], bytes_per_strref ); sz += bytes_per_column( tv->db, &tv->columns[i], bytes_per_strref );
@ -2584,7 +2590,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
} }
/* check we didn't run of the end of the table */ /* check we didn't run of the end of the table */
if ( (n+sz) > rawsize ) if (n + sz > rawsize)
{ {
ERR("borked.\n"); ERR("borked.\n");
dump_table( st, (USHORT *)rawdata, rawsize ); dump_table( st, (USHORT *)rawdata, rawsize );

View file

@ -453,6 +453,12 @@ UINT WINAPI MsiEnumComponentsA(DWORD, LPSTR);
UINT WINAPI MsiEnumComponentsW(DWORD, LPWSTR); UINT WINAPI MsiEnumComponentsW(DWORD, LPWSTR);
#define MsiEnumComponents WINELIB_NAME_AW(MsiEnumComponents) #define MsiEnumComponents WINELIB_NAME_AW(MsiEnumComponents)
UINT WINAPI MsiEnumComponentsExA(LPCSTR, DWORD, DWORD, CHAR[39],
MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
UINT WINAPI MsiEnumComponentsExW(LPCWSTR, DWORD, DWORD, WCHAR[39],
MSIINSTALLCONTEXT *, LPWSTR, LPDWORD);
#define MsiEnumComponentsEx WINELIB_NAME_AW(MsiEnumComponentsEx)
UINT WINAPI MsiEnumClientsA(LPCSTR, DWORD, LPSTR); UINT WINAPI MsiEnumClientsA(LPCSTR, DWORD, LPSTR);
UINT WINAPI MsiEnumClientsW(LPCWSTR, DWORD, LPWSTR); UINT WINAPI MsiEnumClientsW(LPCWSTR, DWORD, LPWSTR);
#define MsiEnumClients WINELIB_NAME_AW(MsiEnumClients) #define MsiEnumClients WINELIB_NAME_AW(MsiEnumClients)

View file

@ -102,7 +102,7 @@ reactos/dll/win32/msg711.acm # Synced to Wine-1.3.37
reactos/dll/win32/msgsm32.acm # Synced to Wine-1.3.37 reactos/dll/win32/msgsm32.acm # Synced to Wine-1.3.37
reactos/dll/win32/mshtml # Autosync reactos/dll/win32/mshtml # Autosync
reactos/dll/win32/mshtml.tlb # Autosync reactos/dll/win32/mshtml.tlb # Autosync
reactos/dll/win32/msi # Synced to Wine-1.3.37 reactos/dll/win32/msi # Synced to Wine-1.5.4
reactos/dll/win32/msimg32 # Synced to Wine-1.3.37 reactos/dll/win32/msimg32 # Synced to Wine-1.3.37
reactos/dll/win32/msimtf # Synced to Wine-1.3.37 reactos/dll/win32/msimtf # Synced to Wine-1.3.37
reactos/dll/win32/msisip # Synced to Wine-1.3.37 reactos/dll/win32/msisip # Synced to Wine-1.3.37