msi: Get rid of helpers.c.
This commit is contained in:
parent
2afd65f69b
commit
0c43024af7
|
@ -22,7 +22,6 @@ C_SRCS = \
|
|||
font.c \
|
||||
format.c \
|
||||
handle.c \
|
||||
helpers.c \
|
||||
insert.c \
|
||||
install.c \
|
||||
join.c \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1063,7 +1063,7 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
|
|||
uirow = MSI_CreateRecord( 2 );
|
||||
MSI_RecordSetStringW( uirow, 1, propName );
|
||||
MSI_RecordSetStringW( uirow, 2, sigName );
|
||||
ui_actiondata( package, szAppSearch, uirow );
|
||||
msi_ui_actiondata( package, szAppSearch, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
return r;
|
||||
|
@ -1078,13 +1078,13 @@ UINT ACTION_AppSearch(MSIPACKAGE *package)
|
|||
MSIQUERY *view = NULL;
|
||||
UINT r;
|
||||
|
||||
if (check_unique_action(package, szAppSearch))
|
||||
if (msi_action_is_unique(package, szAppSearch))
|
||||
{
|
||||
TRACE("Skipping AppSearch action: already done in UI sequence\n");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
register_unique_action(package, szAppSearch);
|
||||
msi_register_unique_action(package, szAppSearch);
|
||||
|
||||
r = MSI_OpenQuery( package->db, &view, query );
|
||||
if (r != ERROR_SUCCESS)
|
||||
|
@ -1133,13 +1133,13 @@ UINT ACTION_CCPSearch(MSIPACKAGE *package)
|
|||
MSIQUERY *view = NULL;
|
||||
UINT r;
|
||||
|
||||
if (check_unique_action(package, szCCPSearch))
|
||||
if (msi_action_is_unique(package, szCCPSearch))
|
||||
{
|
||||
TRACE("Skipping AppSearch action: already done in UI sequence\n");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
register_unique_action(package, szCCPSearch);
|
||||
msi_register_unique_action(package, szCCPSearch);
|
||||
|
||||
r = MSI_OpenQuery(package->db, &view, query);
|
||||
if (r != ERROR_SUCCESS)
|
||||
|
|
|
@ -343,7 +343,7 @@ UINT install_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
|
|||
MSIFEATURE *feature = NULL;
|
||||
|
||||
if (comp->assembly->feature)
|
||||
feature = get_loaded_feature( package, comp->assembly->feature );
|
||||
feature = msi_get_loaded_feature( package, comp->assembly->feature );
|
||||
|
||||
if (assembly->application)
|
||||
{
|
||||
|
@ -357,12 +357,12 @@ UINT install_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
|
|||
WARN("no manifest\n");
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
manifest = get_loaded_file( package, assembly->manifest )->TargetPath;
|
||||
manifest = msi_get_loaded_file( package, assembly->manifest )->TargetPath;
|
||||
cache = package->cache_sxs;
|
||||
}
|
||||
else
|
||||
{
|
||||
manifest = get_loaded_file( package, comp->KeyPath )->TargetPath;
|
||||
manifest = msi_get_loaded_file( package, comp->KeyPath )->TargetPath;
|
||||
cache = package->cache_net[get_clr_version( manifest )];
|
||||
}
|
||||
TRACE("installing assembly %s\n", debugstr_w(manifest));
|
||||
|
@ -541,7 +541,7 @@ UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
|
|||
win32 = assembly->attributes & msidbAssemblyAttributesWin32;
|
||||
if (assembly->application)
|
||||
{
|
||||
MSIFILE *file = get_loaded_file( package, assembly->application );
|
||||
MSIFILE *file = msi_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);
|
||||
|
@ -565,7 +565,7 @@ UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
|
|||
|
||||
uirow = MSI_CreateRecord( 2 );
|
||||
MSI_RecordSetStringW( uirow, 2, assembly->display_name );
|
||||
ui_actiondata( package, szMsiPublishAssemblies, uirow );
|
||||
msi_ui_actiondata( package, szMsiPublishAssemblies, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -603,7 +603,7 @@ UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
|
|||
win32 = assembly->attributes & msidbAssemblyAttributesWin32;
|
||||
if (assembly->application)
|
||||
{
|
||||
MSIFILE *file = get_loaded_file( package, assembly->application );
|
||||
MSIFILE *file = msi_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);
|
||||
}
|
||||
|
@ -622,7 +622,7 @@ UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
|
|||
|
||||
uirow = MSI_CreateRecord( 2 );
|
||||
MSI_RecordSetStringW( uirow, 2, assembly->display_name );
|
||||
ui_actiondata( package, szMsiPublishAssemblies, uirow );
|
||||
msi_ui_actiondata( package, szMsiPublishAssemblies, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
|
|
|
@ -142,7 +142,7 @@ static MSIPROGID *load_progid( MSIPACKAGE* package, MSIRECORD *row )
|
|||
LPWSTR FilePath;
|
||||
static const WCHAR fmt[] = {'%','s',',','%','i',0};
|
||||
|
||||
FilePath = build_icon_path(package,FileName);
|
||||
FilePath = msi_build_icon_path(package, FileName);
|
||||
|
||||
progid->IconPath = msi_alloc( (strlenW(FilePath)+10)* sizeof(WCHAR) );
|
||||
|
||||
|
@ -154,7 +154,7 @@ static MSIPROGID *load_progid( MSIPACKAGE* package, MSIRECORD *row )
|
|||
{
|
||||
buffer = MSI_RecordGetString(row,5);
|
||||
if (buffer)
|
||||
progid->IconPath = build_icon_path(package,buffer);
|
||||
progid->IconPath = msi_build_icon_path(package, buffer);
|
||||
}
|
||||
|
||||
progid->CurVer = NULL;
|
||||
|
@ -227,7 +227,7 @@ static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
|
|||
TRACE("loading class %s\n",debugstr_w(cls->clsid));
|
||||
cls->Context = msi_dup_record_field( row, 2 );
|
||||
buffer = MSI_RecordGetString(row,3);
|
||||
cls->Component = get_loaded_component(package, buffer);
|
||||
cls->Component = msi_get_loaded_component( package, buffer );
|
||||
|
||||
cls->ProgIDText = msi_dup_record_field(row,4);
|
||||
cls->ProgID = load_given_progid(package, cls->ProgIDText);
|
||||
|
@ -248,7 +248,7 @@ static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
|
|||
LPWSTR FilePath;
|
||||
static const WCHAR fmt[] = {'%','s',',','%','i',0};
|
||||
|
||||
FilePath = build_icon_path(package,FileName);
|
||||
FilePath = msi_build_icon_path(package, FileName);
|
||||
|
||||
cls->IconPath = msi_alloc( (strlenW(FilePath)+5)* sizeof(WCHAR) );
|
||||
|
||||
|
@ -260,7 +260,7 @@ static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
|
|||
{
|
||||
buffer = MSI_RecordGetString(row,8);
|
||||
if (buffer)
|
||||
cls->IconPath = build_icon_path(package,buffer);
|
||||
cls->IconPath = msi_build_icon_path(package, buffer);
|
||||
}
|
||||
|
||||
if (!MSI_RecordIsNull(row,10))
|
||||
|
@ -287,15 +287,15 @@ static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
|
|||
}
|
||||
else
|
||||
{
|
||||
cls->DefInprocHandler32 = msi_dup_record_field( row, 10);
|
||||
reduce_to_longfilename(cls->DefInprocHandler32);
|
||||
cls->DefInprocHandler32 = msi_dup_record_field( row, 10 );
|
||||
msi_reduce_to_long_filename( cls->DefInprocHandler32 );
|
||||
}
|
||||
}
|
||||
buffer = MSI_RecordGetString(row,11);
|
||||
deformat_string(package,buffer,&cls->Argument);
|
||||
|
||||
buffer = MSI_RecordGetString(row,12);
|
||||
cls->Feature = get_loaded_feature(package,buffer);
|
||||
cls->Feature = msi_get_loaded_feature(package, buffer);
|
||||
|
||||
cls->Attributes = MSI_RecordGetInteger(row,13);
|
||||
|
||||
|
@ -420,7 +420,7 @@ static MSIEXTENSION *load_extension( MSIPACKAGE* package, MSIRECORD *row )
|
|||
TRACE("loading extension %s\n", debugstr_w(ext->Extension));
|
||||
|
||||
buffer = MSI_RecordGetString( row, 2 );
|
||||
ext->Component = get_loaded_component( package,buffer );
|
||||
ext->Component = msi_get_loaded_component( package, buffer );
|
||||
|
||||
ext->ProgIDText = msi_dup_record_field( row, 3 );
|
||||
ext->ProgID = load_given_progid( package, ext->ProgIDText );
|
||||
|
@ -429,7 +429,7 @@ static MSIEXTENSION *load_extension( MSIPACKAGE* package, MSIRECORD *row )
|
|||
ext->Mime = load_given_mime( package, buffer );
|
||||
|
||||
buffer = MSI_RecordGetString(row,5);
|
||||
ext->Feature = get_loaded_feature( package, buffer );
|
||||
ext->Feature = msi_get_loaded_feature( package, buffer );
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
@ -525,7 +525,7 @@ static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param)
|
|||
clsid = MSI_RecordGetString(rec,1);
|
||||
context = MSI_RecordGetString(rec,2);
|
||||
buffer = MSI_RecordGetString(rec,3);
|
||||
comp = get_loaded_component(package,buffer);
|
||||
comp = msi_get_loaded_component(package, buffer);
|
||||
|
||||
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
||||
{
|
||||
|
@ -574,7 +574,7 @@ static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
|
|||
|
||||
extension = MSI_RecordGetString(rec,1);
|
||||
buffer = MSI_RecordGetString(rec,2);
|
||||
comp = get_loaded_component(package,buffer);
|
||||
comp = msi_get_loaded_component(package, buffer);
|
||||
|
||||
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
||||
{
|
||||
|
@ -850,7 +850,7 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
|
|||
}
|
||||
feature->Action = feature->ActionRequest;
|
||||
|
||||
if (!comp->KeyPath || !(file = get_loaded_file( package, comp->KeyPath )))
|
||||
if (!comp->KeyPath || !(file = msi_get_loaded_file( package, comp->KeyPath )))
|
||||
{
|
||||
TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
|
||||
continue;
|
||||
|
@ -958,7 +958,7 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
|
|||
|
||||
uirow = MSI_CreateRecord(1);
|
||||
MSI_RecordSetStringW( uirow, 1, cls->clsid );
|
||||
ui_actiondata(package,szRegisterClassInfo,uirow);
|
||||
msi_ui_actiondata( package, szRegisterClassInfo, uirow );
|
||||
msiobj_release(&uirow->hdr);
|
||||
}
|
||||
|
||||
|
@ -1050,7 +1050,7 @@ UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
|
|||
|
||||
uirow = MSI_CreateRecord( 1 );
|
||||
MSI_RecordSetStringW( uirow, 1, cls->clsid );
|
||||
ui_actiondata( package, szUnregisterClassInfo, uirow );
|
||||
msi_ui_actiondata( package, szUnregisterClassInfo, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
|
||||
|
@ -1131,7 +1131,7 @@ UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
|
|||
|
||||
uirow = MSI_CreateRecord( 1 );
|
||||
MSI_RecordSetStringW( uirow, 1, progid->ProgID );
|
||||
ui_actiondata( package, szRegisterProgIdInfo, uirow );
|
||||
msi_ui_actiondata( package, szRegisterProgIdInfo, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
|
||||
|
@ -1166,7 +1166,7 @@ UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
|
|||
|
||||
uirow = MSI_CreateRecord( 1 );
|
||||
MSI_RecordSetStringW( uirow, 1, progid->ProgID );
|
||||
ui_actiondata( package, szUnregisterProgIdInfo, uirow );
|
||||
msi_ui_actiondata( package, szUnregisterProgIdInfo, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
|
||||
|
@ -1187,7 +1187,7 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
|
|||
DWORD size;
|
||||
LPWSTR advertise;
|
||||
|
||||
keyname = build_directory_name(4, progid, szShell, verb->Verb, szCommand);
|
||||
keyname = msi_build_directory_name(4, progid, szShell, verb->Verb, szCommand);
|
||||
|
||||
TRACE("Making Key %s\n",debugstr_w(keyname));
|
||||
RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
|
||||
|
@ -1205,9 +1205,8 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
|
|||
msi_reg_set_val_str( key, NULL, command );
|
||||
msi_free(command);
|
||||
|
||||
advertise = create_component_advertise_string(package, component,
|
||||
extension->Feature->Feature);
|
||||
|
||||
advertise = msi_create_component_advertise_string(package, component,
|
||||
extension->Feature->Feature);
|
||||
size = strlenW(advertise);
|
||||
|
||||
if (verb->Argument)
|
||||
|
@ -1232,7 +1231,7 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
|
|||
|
||||
if (verb->Command)
|
||||
{
|
||||
keyname = build_directory_name(3, progid, szShell, verb->Verb);
|
||||
keyname = msi_build_directory_name( 3, progid, szShell, verb->Verb );
|
||||
msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Command );
|
||||
msi_free(keyname);
|
||||
}
|
||||
|
@ -1242,7 +1241,7 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
|
|||
if (*Sequence == MSI_NULL_INTEGER || verb->Sequence < *Sequence)
|
||||
{
|
||||
*Sequence = verb->Sequence;
|
||||
keyname = build_directory_name(2, progid, szShell);
|
||||
keyname = msi_build_directory_name( 2, progid, szShell );
|
||||
msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Verb );
|
||||
msi_free(keyname);
|
||||
}
|
||||
|
@ -1362,7 +1361,7 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
|
|||
|
||||
uirow = MSI_CreateRecord(1);
|
||||
MSI_RecordSetStringW( uirow, 1, ext->Extension );
|
||||
ui_actiondata(package,szRegisterExtensionInfo,uirow);
|
||||
msi_ui_actiondata( package, szRegisterExtensionInfo, uirow );
|
||||
msiobj_release(&uirow->hdr);
|
||||
}
|
||||
|
||||
|
@ -1448,7 +1447,7 @@ UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
|
|||
|
||||
uirow = MSI_CreateRecord( 1 );
|
||||
MSI_RecordSetStringW( uirow, 1, ext->Extension );
|
||||
ui_actiondata( package, szUnregisterExtensionInfo, uirow );
|
||||
msi_ui_actiondata( package, szUnregisterExtensionInfo, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
|
||||
|
@ -1506,7 +1505,7 @@ UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
|
|||
uirow = MSI_CreateRecord( 2 );
|
||||
MSI_RecordSetStringW( uirow, 1, mt->ContentType );
|
||||
MSI_RecordSetStringW( uirow, 2, mt->suffix );
|
||||
ui_actiondata( package, szRegisterMIMEInfo, uirow );
|
||||
msi_ui_actiondata( package, szRegisterMIMEInfo, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
|
||||
|
@ -1551,7 +1550,7 @@ UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package )
|
|||
uirow = MSI_CreateRecord( 2 );
|
||||
MSI_RecordSetStringW( uirow, 1, mime->ContentType );
|
||||
MSI_RecordSetStringW( uirow, 2, mime->suffix );
|
||||
ui_actiondata( package, szUnregisterMIMEInfo, uirow );
|
||||
msi_ui_actiondata( package, szUnregisterMIMEInfo, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,62 @@ static CRITICAL_SECTION msi_custom_action_cs = { &msi_custom_action_cs_debug, -1
|
|||
|
||||
static struct list msi_pending_custom_actions = LIST_INIT( msi_pending_custom_actions );
|
||||
|
||||
static UINT schedule_action( MSIPACKAGE *package, UINT script, const WCHAR *action )
|
||||
{
|
||||
UINT count;
|
||||
WCHAR **newbuf = NULL;
|
||||
|
||||
if (script >= TOTAL_SCRIPTS)
|
||||
{
|
||||
FIXME("Unknown script requested %u\n", script);
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
TRACE("Scheduling action %s in script %u\n", debugstr_w(action), script);
|
||||
|
||||
count = package->script->ActionCount[script];
|
||||
package->script->ActionCount[script]++;
|
||||
if (count != 0) newbuf = msi_realloc( package->script->Actions[script],
|
||||
package->script->ActionCount[script] * sizeof(WCHAR *) );
|
||||
else newbuf = msi_alloc( sizeof(WCHAR *) );
|
||||
|
||||
newbuf[count] = strdupW( action );
|
||||
package->script->Actions[script] = newbuf;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT msi_register_unique_action( MSIPACKAGE *package, const WCHAR *action )
|
||||
{
|
||||
UINT count;
|
||||
WCHAR **newbuf = NULL;
|
||||
|
||||
if (!package->script) return FALSE;
|
||||
|
||||
TRACE("Registering %s as unique action\n", debugstr_w(action));
|
||||
|
||||
count = package->script->UniqueActionsCount;
|
||||
package->script->UniqueActionsCount++;
|
||||
if (count != 0) newbuf = msi_realloc( package->script->UniqueActions,
|
||||
package->script->UniqueActionsCount * sizeof(WCHAR *) );
|
||||
else newbuf = msi_alloc( sizeof(WCHAR *) );
|
||||
|
||||
newbuf[count] = strdupW( action );
|
||||
package->script->UniqueActions = newbuf;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL msi_action_is_unique( const MSIPACKAGE *package, const WCHAR *action )
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (!package->script) return FALSE;
|
||||
|
||||
for (i = 0; i < package->script->UniqueActionsCount; i++)
|
||||
{
|
||||
if (!strcmpW( package->script->UniqueActions[i], action )) return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options)
|
||||
{
|
||||
if (!package->script)
|
||||
|
@ -115,13 +171,13 @@ static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR acti
|
|||
}
|
||||
else if (options & msidbCustomActionTypeOncePerProcess)
|
||||
{
|
||||
if (check_unique_action(package,action))
|
||||
if (msi_action_is_unique(package, action))
|
||||
{
|
||||
TRACE("Skipping action due to msidbCustomActionTypeOncePerProcess option.\n");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
register_unique_action(package,action);
|
||||
msi_register_unique_action(package, action);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -982,7 +1038,7 @@ static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source,
|
|||
|
||||
TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
|
||||
|
||||
file = get_loaded_file( package, source );
|
||||
file = msi_get_loaded_file( package, source );
|
||||
if (!file)
|
||||
{
|
||||
ERR("invalid file key %s\n", debugstr_w( source ));
|
||||
|
@ -1010,7 +1066,7 @@ static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source,
|
|||
|
||||
memset(&si,0,sizeof(STARTUPINFOW));
|
||||
|
||||
file = get_loaded_file(package,source);
|
||||
file = msi_get_loaded_file(package, source);
|
||||
if( !file )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
|
@ -1325,7 +1381,7 @@ static UINT HANDLE_CustomType21_22(MSIPACKAGE *package, LPCWSTR source,
|
|||
|
||||
TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
|
||||
|
||||
file = get_loaded_file(package,source);
|
||||
file = msi_get_loaded_file(package, source);
|
||||
if (!file)
|
||||
{
|
||||
ERR("invalid file key %s\n", debugstr_w(source));
|
||||
|
|
|
@ -2378,7 +2378,7 @@ static UINT msi_dialog_seltree_handler( msi_dialog *dialog,
|
|||
dir = MSI_RecordGetString( row, 7 );
|
||||
if (dir)
|
||||
{
|
||||
folder = get_loaded_folder( dialog->package, dir );
|
||||
folder = msi_get_loaded_folder( dialog->package, dir );
|
||||
if (!folder)
|
||||
{
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
|
|
|
@ -58,9 +58,9 @@ static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *ac
|
|||
MSI_RecordSetStringW( uirow, 1, f->FileName );
|
||||
MSI_RecordSetStringW( uirow, 9, f->Component->Directory );
|
||||
MSI_RecordSetInteger( uirow, 6, f->FileSize );
|
||||
ui_actiondata( package, action, uirow );
|
||||
msi_ui_actiondata( package, action, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
ui_progress( package, 2, f->FileSize, 0, 0 );
|
||||
msi_ui_progress( package, 2, f->FileSize, 0, 0 );
|
||||
}
|
||||
|
||||
static msi_file_state calculate_install_state( MSIFILE *file )
|
||||
|
@ -154,7 +154,7 @@ static void schedule_install_files(MSIPACKAGE *package)
|
|||
file->state = msifs_skipped;
|
||||
}
|
||||
comp->Action = INSTALLSTATE_LOCAL;
|
||||
ui_progress( package, 2, file->FileSize, 0, 0 );
|
||||
msi_ui_progress( package, 2, file->FileSize, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,10 +237,10 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
|
|||
install_path = msi_get_target_folder( package, dir );
|
||||
if (!install_path) return ERROR_FUNCTION_FAILED;
|
||||
|
||||
folder = get_loaded_folder( package, dir );
|
||||
folder = msi_get_loaded_folder( package, dir );
|
||||
if (folder->State == 0)
|
||||
{
|
||||
create_full_pathW( install_path );
|
||||
msi_create_full_path( install_path );
|
||||
folder->State = 2;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -254,7 +254,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
|||
|
||||
if (action == MSICABEXTRACT_BEGINEXTRACT)
|
||||
{
|
||||
f = get_loaded_file(package, file);
|
||||
f = msi_get_loaded_file(package, file);
|
||||
if (!f)
|
||||
{
|
||||
TRACE("unknown file in cabinet (%s)\n", debugstr_w(file));
|
||||
|
@ -281,6 +281,27 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
WCHAR *msi_resolve_file_source( MSIPACKAGE *package, MSIFILE *file )
|
||||
{
|
||||
WCHAR *p, *path;
|
||||
|
||||
TRACE("Working to resolve source of file %s\n", debugstr_w(file->File));
|
||||
|
||||
if (file->IsCompressed) return NULL;
|
||||
|
||||
p = msi_resolve_source_folder( package, file->Component->Directory, NULL );
|
||||
path = msi_build_directory_name( 2, p, file->ShortName );
|
||||
|
||||
if (file->LongName && GetFileAttributesW( path ) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
msi_free( path );
|
||||
path = msi_build_directory_name( 2, p, file->LongName );
|
||||
}
|
||||
msi_free( p );
|
||||
TRACE("file %s source resolves to %s\n", debugstr_w(file->File), debugstr_w(path));
|
||||
return path;
|
||||
}
|
||||
|
||||
/*
|
||||
* ACTION_InstallFiles()
|
||||
*
|
||||
|
@ -296,10 +317,9 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
MSIFILE *file;
|
||||
|
||||
/* increment progress bar each time action data is sent */
|
||||
ui_progress(package,1,1,0,0);
|
||||
msi_ui_progress( package, 1, 1, 0, 0 );
|
||||
|
||||
schedule_install_files(package);
|
||||
|
||||
mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
|
||||
|
||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||
|
@ -343,7 +363,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
|
||||
if (!file->IsCompressed)
|
||||
{
|
||||
LPWSTR source = resolve_file_source(package, file);
|
||||
WCHAR *source = msi_resolve_file_source(package, file);
|
||||
|
||||
TRACE("copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
|
||||
|
||||
|
@ -426,7 +446,7 @@ static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
|
|||
if (temp_folder[0] == '\0')
|
||||
GetTempPathW(MAX_PATH, temp_folder);
|
||||
|
||||
p = get_loaded_filepatch(package, file);
|
||||
p = msi_get_loaded_filepatch(package, file);
|
||||
if (!p)
|
||||
{
|
||||
TRACE("unknown file in cabinet (%s)\n", debugstr_w(file));
|
||||
|
@ -477,7 +497,7 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
|
|||
TRACE("%p\n", package);
|
||||
|
||||
/* increment progress bar each time action data is sent */
|
||||
ui_progress(package,1,1,0,0);
|
||||
msi_ui_progress( package, 1, 1, 0, 0 );
|
||||
|
||||
mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
|
||||
|
||||
|
@ -739,6 +759,12 @@ done:
|
|||
return res;
|
||||
}
|
||||
|
||||
void msi_reduce_to_long_filename( WCHAR *filename )
|
||||
{
|
||||
WCHAR *p = strchrW( filename, '|' );
|
||||
if (p) memmove( filename, p + 1, (strlenW( p + 1 ) + 1) * sizeof(WCHAR) );
|
||||
}
|
||||
|
||||
static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
|
||||
{
|
||||
MSIPACKAGE *package = param;
|
||||
|
@ -751,7 +777,7 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
|
|||
BOOL ret, wildcards;
|
||||
|
||||
component = MSI_RecordGetString(rec, 2);
|
||||
comp = get_loaded_component(package, component);
|
||||
comp = msi_get_loaded_component(package, component);
|
||||
if (!comp)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
|
@ -816,8 +842,7 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
|
|||
else
|
||||
{
|
||||
destname = strdupW(MSI_RecordGetString(rec, 4));
|
||||
if (destname)
|
||||
reduce_to_longfilename(destname);
|
||||
if (destname) msi_reduce_to_long_filename(destname);
|
||||
}
|
||||
|
||||
size = 0;
|
||||
|
@ -856,7 +881,7 @@ done:
|
|||
MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString(rec, 1) );
|
||||
MSI_RecordSetInteger( uirow, 6, 1 ); /* FIXME */
|
||||
MSI_RecordSetStringW( uirow, 9, destdir );
|
||||
ui_actiondata( package, szMoveFiles, uirow );
|
||||
msi_ui_actiondata( package, szMoveFiles, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
msi_free(sourcedir);
|
||||
|
@ -903,7 +928,7 @@ static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const
|
|||
MSI_RecordGetStringW( row, 4, NULL, &len );
|
||||
if (!(dst_name = msi_alloc( ++len * sizeof(WCHAR) ))) return NULL;
|
||||
MSI_RecordGetStringW( row, 4, dst_name, &len );
|
||||
reduce_to_longfilename( dst_name );
|
||||
msi_reduce_to_long_filename( dst_name );
|
||||
}
|
||||
|
||||
if (MSI_RecordIsNull( row, 5 ))
|
||||
|
@ -931,8 +956,8 @@ static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const
|
|||
}
|
||||
}
|
||||
|
||||
dst = build_directory_name( 2, dst_path, dst_name );
|
||||
create_full_pathW( dst_path );
|
||||
dst = msi_build_directory_name( 2, dst_path, dst_name );
|
||||
msi_create_full_path( dst_path );
|
||||
|
||||
msi_free( dst_name );
|
||||
msi_free( dst_path );
|
||||
|
@ -949,7 +974,7 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
|
|||
MSIFILE *file;
|
||||
|
||||
component = MSI_RecordGetString(row,2);
|
||||
comp = get_loaded_component(package,component);
|
||||
comp = msi_get_loaded_component(package, component);
|
||||
if (!comp)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
|
@ -974,7 +999,7 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
file = get_loaded_file( package, file_key );
|
||||
file = msi_get_loaded_file( package, file_key );
|
||||
if (!file)
|
||||
{
|
||||
ERR("Original file unknown %s\n", debugstr_w(file_key));
|
||||
|
@ -1002,7 +1027,7 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
|
|||
MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString( row, 1 ) );
|
||||
MSI_RecordSetInteger( uirow, 6, file->FileSize );
|
||||
MSI_RecordSetStringW( uirow, 9, MSI_RecordGetString( row, 5 ) );
|
||||
ui_actiondata( package, szDuplicateFiles, uirow );
|
||||
msi_ui_actiondata( package, szDuplicateFiles, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
msi_free(dest);
|
||||
|
@ -1037,7 +1062,7 @@ static UINT ITERATE_RemoveDuplicateFiles( MSIRECORD *row, LPVOID param )
|
|||
MSIFILE *file;
|
||||
|
||||
component = MSI_RecordGetString( row, 2 );
|
||||
comp = get_loaded_component( package, component );
|
||||
comp = msi_get_loaded_component( package, component );
|
||||
if (!comp)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
|
@ -1062,7 +1087,7 @@ static UINT ITERATE_RemoveDuplicateFiles( MSIRECORD *row, LPVOID param )
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
file = get_loaded_file( package, file_key );
|
||||
file = msi_get_loaded_file( package, file_key );
|
||||
if (!file)
|
||||
{
|
||||
ERR("Original file unknown %s\n", debugstr_w(file_key));
|
||||
|
@ -1086,7 +1111,7 @@ static UINT ITERATE_RemoveDuplicateFiles( MSIRECORD *row, LPVOID param )
|
|||
uirow = MSI_CreateRecord( 9 );
|
||||
MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString( row, 1 ) );
|
||||
MSI_RecordSetStringW( uirow, 9, MSI_RecordGetString( row, 5 ) );
|
||||
ui_actiondata( package, szRemoveDuplicateFiles, uirow );
|
||||
msi_ui_actiondata( package, szRemoveDuplicateFiles, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
msi_free(dest);
|
||||
|
@ -1152,7 +1177,7 @@ static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
|
|||
dirprop = MSI_RecordGetString(row, 4);
|
||||
install_mode = MSI_RecordGetInteger(row, 5);
|
||||
|
||||
comp = get_loaded_component(package, component);
|
||||
comp = msi_get_loaded_component(package, component);
|
||||
if (!comp->Enabled)
|
||||
{
|
||||
TRACE("component is disabled\n");
|
||||
|
@ -1179,7 +1204,7 @@ static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
|
|||
size = 0;
|
||||
if ((filename = strdupW( MSI_RecordGetString(row, 3) )))
|
||||
{
|
||||
reduce_to_longfilename( filename );
|
||||
msi_reduce_to_long_filename( filename );
|
||||
size = lstrlenW( filename );
|
||||
}
|
||||
size += lstrlenW(dir) + 2;
|
||||
|
@ -1209,7 +1234,7 @@ done:
|
|||
uirow = MSI_CreateRecord( 9 );
|
||||
MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString(row, 1) );
|
||||
MSI_RecordSetStringW( uirow, 9, dir );
|
||||
ui_actiondata( package, szRemoveFiles, uirow );
|
||||
msi_ui_actiondata( package, szRemoveFiles, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
|
||||
msi_free(filename);
|
||||
|
@ -1320,9 +1345,9 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
|
|||
uirow = MSI_CreateRecord( 9 );
|
||||
MSI_RecordSetStringW( uirow, 1, file->FileName );
|
||||
MSI_RecordSetStringW( uirow, 9, file->Component->Directory );
|
||||
ui_actiondata( package, szRemoveFiles, uirow );
|
||||
msi_ui_actiondata( package, szRemoveFiles, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
/* FIXME: call ui_progress here? */
|
||||
/* FIXME: call msi_ui_progress here? */
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
|
|
@ -212,7 +212,7 @@ static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
|
|||
LPWSTR uipath, p;
|
||||
|
||||
filename = MSI_RecordGetString( row, 1 );
|
||||
file = get_loaded_file( package, filename );
|
||||
file = msi_get_loaded_file( package, filename );
|
||||
if (!file)
|
||||
{
|
||||
ERR("Unable to load file\n");
|
||||
|
@ -256,10 +256,10 @@ static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
|
|||
if (p) p++;
|
||||
else p = uipath;
|
||||
MSI_RecordSetStringW( uirow, 1, p );
|
||||
ui_actiondata( package, szRegisterFonts, uirow);
|
||||
msi_ui_actiondata( package, szRegisterFonts, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
msi_free( uipath );
|
||||
/* FIXME: call ui_progress? */
|
||||
/* FIXME: call msi_ui_progress? */
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ static UINT ITERATE_UnregisterFonts( MSIRECORD *row, LPVOID param )
|
|||
LPWSTR uipath, p;
|
||||
|
||||
filename = MSI_RecordGetString( row, 1 );
|
||||
file = get_loaded_file( package, filename );
|
||||
file = msi_get_loaded_file( package, filename );
|
||||
if (!file)
|
||||
{
|
||||
ERR("Unable to load file\n");
|
||||
|
@ -340,10 +340,10 @@ static UINT ITERATE_UnregisterFonts( MSIRECORD *row, LPVOID param )
|
|||
if (p) p++;
|
||||
else p = uipath;
|
||||
MSI_RecordSetStringW( uirow, 1, p );
|
||||
ui_actiondata( package, szUnregisterFonts, uirow );
|
||||
msi_ui_actiondata( package, szUnregisterFonts, uirow );
|
||||
msiobj_release( &uirow->hdr );
|
||||
msi_free( uipath );
|
||||
/* FIXME: call ui_progress? */
|
||||
/* FIXME: call msi_ui_progress? */
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -189,12 +189,12 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
|
|||
key = msi_alloc((str->len + 1) * sizeof(WCHAR));
|
||||
lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
|
||||
|
||||
comp = get_loaded_component(format->package, key);
|
||||
comp = msi_get_loaded_component(format->package, key);
|
||||
if (!comp)
|
||||
goto done;
|
||||
|
||||
if (comp->Action == INSTALLSTATE_SOURCE)
|
||||
ret = resolve_source_folder( format->package, comp->Directory, NULL );
|
||||
ret = msi_resolve_source_folder( format->package, comp->Directory, NULL );
|
||||
else
|
||||
ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) );
|
||||
|
||||
|
@ -212,7 +212,7 @@ static LPWSTR deformat_file(FORMAT *format, FORMSTR *str, BOOL shortname)
|
|||
key = msi_alloc((str->len + 1) * sizeof(WCHAR));
|
||||
lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
|
||||
|
||||
file = get_loaded_file(format->package, key);
|
||||
file = msi_get_loaded_file(format->package, key);
|
||||
if (!file)
|
||||
goto done;
|
||||
|
||||
|
@ -1020,3 +1020,26 @@ done:
|
|||
msi_free(value);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* wrapper to resist a need for a full rewrite right now */
|
||||
DWORD deformat_string( MSIPACKAGE *package, const WCHAR *ptr, WCHAR **data )
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
DWORD size = 0;
|
||||
MSIRECORD *rec = MSI_CreateRecord( 1 );
|
||||
|
||||
MSI_RecordSetStringW( rec, 0, ptr );
|
||||
MSI_FormatRecordW( package, rec, NULL, &size );
|
||||
|
||||
size++;
|
||||
*data = msi_alloc( size * sizeof(WCHAR) );
|
||||
if (size > 1) MSI_FormatRecordW( package, rec, *data, &size );
|
||||
else *data[0] = 0;
|
||||
|
||||
msiobj_release( &rec->hdr );
|
||||
return size * sizeof(WCHAR);
|
||||
}
|
||||
*data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,713 +0,0 @@
|
|||
/*
|
||||
* Implementation of the Microsoft Installer (msi.dll)
|
||||
*
|
||||
* Copyright 2005 Aric Stewart for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here are helper functions formally in action.c that are used by a variety of
|
||||
* actions and functions.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "wine/debug.h"
|
||||
#include "msipriv.h"
|
||||
#include "winuser.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "msidefs.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
LPWSTR build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name )
|
||||
{
|
||||
LPWSTR SystemFolder, dest, FilePath;
|
||||
|
||||
static const WCHAR szMicrosoft[] =
|
||||
{'M','i','c','r','o','s','o','f','t','\\',0};
|
||||
static const WCHAR szInstaller[] =
|
||||
{'I','n','s','t','a','l','l','e','r','\\',0};
|
||||
static const WCHAR szADFolder[] =
|
||||
{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR szWFolder[] =
|
||||
{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
|
||||
|
||||
if(package->Context == MSIINSTALLCONTEXT_MACHINE)
|
||||
SystemFolder = msi_dup_property( package->db, szWFolder );
|
||||
else
|
||||
{
|
||||
LPWSTR ADTgt = msi_dup_property( package->db, szADFolder );
|
||||
SystemFolder = build_directory_name(2, ADTgt, szMicrosoft);
|
||||
msi_free(ADTgt);
|
||||
}
|
||||
|
||||
dest = build_directory_name(3, SystemFolder, szInstaller, package->ProductCode);
|
||||
|
||||
create_full_pathW(dest);
|
||||
|
||||
FilePath = build_directory_name(2, dest, icon_name);
|
||||
|
||||
msi_free(SystemFolder);
|
||||
msi_free(dest);
|
||||
return FilePath;
|
||||
}
|
||||
|
||||
LPWSTR msi_dup_record_field( MSIRECORD *rec, INT field )
|
||||
{
|
||||
DWORD sz = 0;
|
||||
LPWSTR str;
|
||||
UINT r;
|
||||
|
||||
if (MSI_RecordIsNull( rec, field ))
|
||||
return NULL;
|
||||
|
||||
r = MSI_RecordGetStringW( rec, field, NULL, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
sz ++;
|
||||
str = msi_alloc( sz * sizeof (WCHAR) );
|
||||
if (!str)
|
||||
return str;
|
||||
str[0] = 0;
|
||||
r = MSI_RecordGetStringW( rec, field, str, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("failed to get string!\n");
|
||||
msi_free( str );
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component )
|
||||
{
|
||||
MSICOMPONENT *comp;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
|
||||
{
|
||||
if (!strcmpW( Component, comp->Component ))
|
||||
return comp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MSIFEATURE* get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
|
||||
{
|
||||
MSIFEATURE *feature;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||
{
|
||||
if (!strcmpW( Feature, feature->Feature ))
|
||||
return feature;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MSIFILE* get_loaded_file( MSIPACKAGE* package, LPCWSTR key )
|
||||
{
|
||||
MSIFILE *file;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||
{
|
||||
if (!strcmpW( key, file->File ))
|
||||
return file;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MSIFILEPATCH* get_loaded_filepatch( MSIPACKAGE* package, LPCWSTR key )
|
||||
{
|
||||
MSIFILEPATCH *patch;
|
||||
|
||||
/* FIXME: There might be more than one patch */
|
||||
|
||||
LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
|
||||
{
|
||||
if (!strcmpW( key, patch->File->File ))
|
||||
return patch;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int track_tempfile( MSIPACKAGE *package, LPCWSTR path )
|
||||
{
|
||||
MSITEMPFILE *temp;
|
||||
|
||||
TRACE("%s\n", debugstr_w(path));
|
||||
|
||||
LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
|
||||
if (!strcmpW( path, temp->Path ))
|
||||
return 0;
|
||||
|
||||
temp = msi_alloc_zero( sizeof (MSITEMPFILE) );
|
||||
if (!temp)
|
||||
return -1;
|
||||
|
||||
list_add_head( &package->tempfiles, &temp->entry );
|
||||
temp->Path = strdupW( path );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir )
|
||||
{
|
||||
MSIFOLDER *folder;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
|
||||
{
|
||||
if (!strcmpW( dir, folder->Directory ))
|
||||
return folder;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LPWSTR get_source_root( MSIPACKAGE *package )
|
||||
{
|
||||
LPWSTR path, p;
|
||||
|
||||
path = msi_dup_property( package->db, szSourceDir );
|
||||
if (path)
|
||||
return path;
|
||||
|
||||
path = msi_dup_property( package->db, szDatabase );
|
||||
if (path)
|
||||
{
|
||||
p = strrchrW(path,'\\');
|
||||
if (p)
|
||||
*(p+1) = 0;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
|
||||
{
|
||||
LPWSTR p, path;
|
||||
|
||||
TRACE("Working to resolve source of file %s\n", debugstr_w(file->File));
|
||||
|
||||
if (file->IsCompressed)
|
||||
return NULL;
|
||||
|
||||
p = resolve_source_folder( package, file->Component->Directory, NULL );
|
||||
path = build_directory_name(2, p, file->ShortName);
|
||||
|
||||
if (file->LongName &&
|
||||
GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
msi_free(path);
|
||||
path = build_directory_name(2, p, file->LongName);
|
||||
}
|
||||
|
||||
msi_free(p);
|
||||
|
||||
TRACE("file %s source resolves to %s\n", debugstr_w(file->File), debugstr_w(path));
|
||||
return path;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (!strcmpW( name, szSourceDir ))
|
||||
name = szTargetDir;
|
||||
|
||||
f = get_loaded_folder( package, name );
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
/* special resolving for Target and Source root dir */
|
||||
if (!strcmpW( name, szTargetDir ))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* wrapper to resist a need for a full rewrite right now */
|
||||
DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data )
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
MSIRECORD *rec = MSI_CreateRecord(1);
|
||||
DWORD size = 0;
|
||||
|
||||
MSI_RecordSetStringW(rec,0,ptr);
|
||||
MSI_FormatRecordW(package,rec,NULL,&size);
|
||||
|
||||
size++;
|
||||
*data = msi_alloc(size*sizeof(WCHAR));
|
||||
if (size > 1)
|
||||
MSI_FormatRecordW(package,rec,*data,&size);
|
||||
else
|
||||
*data[0] = 0;
|
||||
|
||||
msiobj_release( &rec->hdr );
|
||||
return sizeof(WCHAR)*size;
|
||||
}
|
||||
|
||||
*data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action)
|
||||
{
|
||||
UINT count;
|
||||
LPWSTR *newbuf = NULL;
|
||||
if (script >= TOTAL_SCRIPTS)
|
||||
{
|
||||
FIXME("Unknown script requested %i\n",script);
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
TRACE("Scheduling Action %s in script %i\n",debugstr_w(action), script);
|
||||
|
||||
count = package->script->ActionCount[script];
|
||||
package->script->ActionCount[script]++;
|
||||
if (count != 0)
|
||||
newbuf = msi_realloc( package->script->Actions[script],
|
||||
package->script->ActionCount[script]* sizeof(LPWSTR));
|
||||
else
|
||||
newbuf = msi_alloc( sizeof(LPWSTR));
|
||||
|
||||
newbuf[count] = strdupW(action);
|
||||
package->script->Actions[script] = newbuf;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
void msi_free_action_script(MSIPACKAGE *package, UINT script)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < package->script->ActionCount[script]; i++)
|
||||
msi_free(package->script->Actions[script][i]);
|
||||
|
||||
msi_free(package->script->Actions[script]);
|
||||
package->script->Actions[script] = NULL;
|
||||
package->script->ActionCount[script] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* build_directory_name()
|
||||
*
|
||||
* This function is to save messing round with directory names
|
||||
* It handles adding backslashes between path segments,
|
||||
* and can add \ at the end of the directory name if told to.
|
||||
*
|
||||
* It takes a variable number of arguments.
|
||||
* It always allocates a new string for the result, so make sure
|
||||
* to free the return value when finished with it.
|
||||
*
|
||||
* The first arg is the number of path segments that follow.
|
||||
* The arguments following count are a list of path segments.
|
||||
* A path segment may be NULL.
|
||||
*
|
||||
* Path segments will be added with a \ separating them.
|
||||
* A \ will not be added after the last segment, however if the
|
||||
* last segment is NULL, then the last character will be a \
|
||||
*
|
||||
*/
|
||||
LPWSTR build_directory_name(DWORD count, ...)
|
||||
{
|
||||
DWORD sz = 1, i;
|
||||
LPWSTR dir;
|
||||
va_list va;
|
||||
|
||||
va_start(va,count);
|
||||
for(i=0; i<count; i++)
|
||||
{
|
||||
LPCWSTR str = va_arg(va,LPCWSTR);
|
||||
if (str)
|
||||
sz += strlenW(str) + 1;
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
dir = msi_alloc(sz*sizeof(WCHAR));
|
||||
dir[0]=0;
|
||||
|
||||
va_start(va,count);
|
||||
for(i=0; i<count; i++)
|
||||
{
|
||||
LPCWSTR str = va_arg(va,LPCWSTR);
|
||||
if (!str)
|
||||
continue;
|
||||
strcatW(dir, str);
|
||||
if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
|
||||
strcatW(dir, szBackSlash);
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* create_full_pathW
|
||||
*
|
||||
* Recursively create all directories in the path.
|
||||
*
|
||||
* shamelessly stolen from setupapi/queue.c
|
||||
*/
|
||||
BOOL create_full_pathW(const WCHAR *path)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
int len;
|
||||
WCHAR *new_path;
|
||||
|
||||
new_path = msi_alloc( (strlenW(path) + 1) * sizeof(WCHAR));
|
||||
|
||||
strcpyW(new_path, path);
|
||||
|
||||
while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
|
||||
new_path[len - 1] = 0;
|
||||
|
||||
while(!CreateDirectoryW(new_path, NULL))
|
||||
{
|
||||
WCHAR *slash;
|
||||
DWORD last_error = GetLastError();
|
||||
if(last_error == ERROR_ALREADY_EXISTS)
|
||||
break;
|
||||
|
||||
if(last_error != ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!(slash = strrchrW(new_path, '\\')))
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
len = slash - new_path;
|
||||
new_path[len] = 0;
|
||||
if(!create_full_pathW(new_path))
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
new_path[len] = '\\';
|
||||
}
|
||||
|
||||
msi_free(new_path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d )
|
||||
{
|
||||
MSIRECORD * row;
|
||||
|
||||
row = MSI_CreateRecord(4);
|
||||
MSI_RecordSetInteger(row,1,a);
|
||||
MSI_RecordSetInteger(row,2,b);
|
||||
MSI_RecordSetInteger(row,3,c);
|
||||
MSI_RecordSetInteger(row,4,d);
|
||||
MSI_ProcessMessage(package, INSTALLMESSAGE_PROGRESS, row);
|
||||
msiobj_release(&row->hdr);
|
||||
|
||||
msi_dialog_check_messages(NULL);
|
||||
}
|
||||
|
||||
void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
|
||||
{
|
||||
static const WCHAR Query_t[] =
|
||||
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||
'`','A','c','t','i','o', 'n','T','e','x','t','`',' ',
|
||||
'W','H','E','R','E',' ', '`','A','c','t','i','o','n','`',' ','=',
|
||||
' ','\'','%','s','\'',0};
|
||||
WCHAR message[1024];
|
||||
MSIRECORD * row = 0;
|
||||
DWORD size;
|
||||
|
||||
if (!package->LastAction || strcmpW(package->LastAction, action))
|
||||
{
|
||||
row = MSI_QueryGetRecord(package->db, Query_t, action);
|
||||
if (!row)
|
||||
return;
|
||||
|
||||
if (MSI_RecordIsNull(row,3))
|
||||
{
|
||||
msiobj_release(&row->hdr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the cached actionformat */
|
||||
msi_free(package->ActionFormat);
|
||||
package->ActionFormat = msi_dup_record_field(row,3);
|
||||
|
||||
msi_free(package->LastAction);
|
||||
package->LastAction = strdupW(action);
|
||||
|
||||
msiobj_release(&row->hdr);
|
||||
}
|
||||
|
||||
MSI_RecordSetStringW(record,0,package->ActionFormat);
|
||||
size = 1024;
|
||||
MSI_FormatRecordW(package,record,message,&size);
|
||||
|
||||
row = MSI_CreateRecord(1);
|
||||
MSI_RecordSetStringW(row,1,message);
|
||||
|
||||
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, row);
|
||||
|
||||
msiobj_release(&row->hdr);
|
||||
}
|
||||
|
||||
void reduce_to_longfilename(WCHAR* filename)
|
||||
{
|
||||
LPWSTR p = strchrW(filename,'|');
|
||||
if (p)
|
||||
memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR));
|
||||
}
|
||||
|
||||
LPWSTR create_component_advertise_string(MSIPACKAGE* package,
|
||||
MSICOMPONENT* component, LPCWSTR feature)
|
||||
{
|
||||
static const WCHAR fmt[] = {'%','s','%','s','%','c','%','s',0};
|
||||
WCHAR productid_85[21], component_85[21];
|
||||
LPWSTR output = NULL;
|
||||
DWORD sz = 0;
|
||||
GUID clsid;
|
||||
|
||||
/* > is used if there is a component GUID and < if not. */
|
||||
|
||||
productid_85[0] = 0;
|
||||
component_85[0] = 0;
|
||||
|
||||
CLSIDFromString(package->ProductCode, &clsid);
|
||||
encode_base85_guid(&clsid, productid_85);
|
||||
|
||||
if (component)
|
||||
{
|
||||
CLSIDFromString(component->ComponentId, &clsid);
|
||||
encode_base85_guid(&clsid, component_85);
|
||||
}
|
||||
|
||||
TRACE("prod=%s feat=%s comp=%s\n", debugstr_w(productid_85),
|
||||
debugstr_w(feature), debugstr_w(component_85));
|
||||
|
||||
sz = 20 + lstrlenW(feature) + 20 + 3;
|
||||
|
||||
output = msi_alloc_zero(sz*sizeof(WCHAR));
|
||||
|
||||
sprintfW(output, fmt, productid_85, feature,
|
||||
component?'>':'<', component_85);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/* update component state based on a feature change */
|
||||
void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
|
||||
{
|
||||
INSTALLSTATE newstate;
|
||||
ComponentList *cl;
|
||||
|
||||
newstate = feature->ActionRequest;
|
||||
|
||||
if (newstate == INSTALLSTATE_ABSENT)
|
||||
newstate = INSTALLSTATE_UNKNOWN;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
|
||||
{
|
||||
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 (newstate == INSTALLSTATE_LOCAL)
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ComponentList *clist;
|
||||
MSIFEATURE *f;
|
||||
|
||||
component->hasLocalFeature = FALSE;
|
||||
|
||||
component->Action = newstate;
|
||||
component->ActionRequest = newstate;
|
||||
|
||||
/* 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 &&
|
||||
f->ActionRequest != INSTALLSTATE_SOURCE )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY( clist, &f->Components, ComponentList, entry )
|
||||
{
|
||||
if ( clist->component == component &&
|
||||
(f->ActionRequest == INSTALLSTATE_LOCAL ||
|
||||
f->ActionRequest == INSTALLSTATE_SOURCE) )
|
||||
{
|
||||
TRACE("Saved by %s\n", debugstr_w(f->Feature));
|
||||
component->hasLocalFeature = TRUE;
|
||||
|
||||
if (component->Attributes & msidbComponentAttributesOptional)
|
||||
{
|
||||
if (f->Attributes & msidbFeatureAttributesFavorSource)
|
||||
{
|
||||
component->Action = INSTALLSTATE_SOURCE;
|
||||
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
}
|
||||
else if (component->Attributes & msidbComponentAttributesSourceOnly)
|
||||
{
|
||||
component->Action = INSTALLSTATE_SOURCE;
|
||||
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TRACE("Result (%i): Component %s (Installed %i, Action %i, Request %i)\n",
|
||||
newstate, debugstr_w(component->Component), component->Installed,
|
||||
component->Action, component->ActionRequest);
|
||||
}
|
||||
}
|
||||
|
||||
UINT register_unique_action(MSIPACKAGE *package, LPCWSTR action)
|
||||
{
|
||||
UINT count;
|
||||
LPWSTR *newbuf = NULL;
|
||||
|
||||
if (!package->script)
|
||||
return FALSE;
|
||||
|
||||
TRACE("Registering %s as unique action\n", debugstr_w(action));
|
||||
|
||||
count = package->script->UniqueActionsCount;
|
||||
package->script->UniqueActionsCount++;
|
||||
if (count != 0)
|
||||
newbuf = msi_realloc( package->script->UniqueActions,
|
||||
package->script->UniqueActionsCount* sizeof(LPWSTR));
|
||||
else
|
||||
newbuf = msi_alloc( sizeof(LPWSTR));
|
||||
|
||||
newbuf[count] = strdupW(action);
|
||||
package->script->UniqueActions = newbuf;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL check_unique_action(const MSIPACKAGE *package, LPCWSTR action)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (!package->script)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < package->script->UniqueActionsCount; i++)
|
||||
if (!strcmpW(package->script->UniqueActions[i], action))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WCHAR* generate_error_string(MSIPACKAGE *package, UINT error, DWORD count, ... )
|
||||
{
|
||||
static const WCHAR query[] = {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ','F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ','`','E','r','r','o','r','`',' ','=',' ','%','i',0};
|
||||
|
||||
MSIRECORD *rec;
|
||||
MSIRECORD *row;
|
||||
DWORD size = 0;
|
||||
DWORD i;
|
||||
va_list va;
|
||||
LPCWSTR str;
|
||||
LPWSTR data;
|
||||
|
||||
row = MSI_QueryGetRecord(package->db, query, error);
|
||||
if (!row)
|
||||
return 0;
|
||||
|
||||
rec = MSI_CreateRecord(count+2);
|
||||
|
||||
str = MSI_RecordGetString(row,1);
|
||||
MSI_RecordSetStringW(rec,0,str);
|
||||
msiobj_release( &row->hdr );
|
||||
MSI_RecordSetInteger(rec,1,error);
|
||||
|
||||
va_start(va,count);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
str = va_arg(va,LPCWSTR);
|
||||
MSI_RecordSetStringW(rec,(i+2),str);
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
MSI_FormatRecordW(package,rec,NULL,&size);
|
||||
|
||||
size++;
|
||||
data = msi_alloc(size*sizeof(WCHAR));
|
||||
if (size > 1)
|
||||
MSI_FormatRecordW(package,rec,data,&size);
|
||||
else
|
||||
data[0] = 0;
|
||||
msiobj_release( &rec->hdr );
|
||||
return data;
|
||||
}
|
|
@ -214,7 +214,7 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
|
|||
|
||||
const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name )
|
||||
{
|
||||
MSIFOLDER *folder = get_loaded_folder( package, name );
|
||||
MSIFOLDER *folder = msi_get_loaded_folder( package, name );
|
||||
if (folder) return folder->ResolvedTarget;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -339,6 +339,60 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
|
|||
return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
|
||||
}
|
||||
|
||||
static WCHAR *get_source_root( MSIDATABASE *db )
|
||||
{
|
||||
WCHAR *path, *p;
|
||||
|
||||
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 )
|
||||
{
|
||||
MSIFOLDER *f;
|
||||
LPWSTR p, path = NULL, parent;
|
||||
|
||||
TRACE("working to resolve %s\n", debugstr_w(name));
|
||||
|
||||
if (!strcmpW( name, szSourceDir )) name = szTargetDir;
|
||||
if (!(f = msi_get_loaded_folder( package, name ))) return NULL;
|
||||
|
||||
/* special resolving for root dir */
|
||||
if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource)
|
||||
{
|
||||
f->ResolvedSource = get_source_root( package->db );
|
||||
}
|
||||
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 = msi_resolve_source_folder( package, parent, NULL );
|
||||
|
||||
if (package->WordCount & msidbSumInfoSourceTypeCompressed)
|
||||
path = get_source_root( package->db );
|
||||
else if (package->WordCount & msidbSumInfoSourceTypeSFN)
|
||||
path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
|
||||
else
|
||||
path = msi_build_directory_name( 3, p, f->SourceLongPath, NULL );
|
||||
|
||||
TRACE("-> %s\n", debugstr_w(path));
|
||||
f->ResolvedSource = strdupW( path );
|
||||
msi_free( p );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MSI_GetSourcePath (internal)
|
||||
*/
|
||||
|
@ -415,7 +469,7 @@ done:
|
|||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
path = resolve_source_folder( package, szFolder, NULL );
|
||||
path = msi_resolve_source_folder( package, szFolder, NULL );
|
||||
msiobj_release( &package->hdr );
|
||||
|
||||
TRACE("path = %s\n", debugstr_w(path));
|
||||
|
@ -523,7 +577,7 @@ UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolder
|
|||
{
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
if (!(folder = get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
|
||||
if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
|
||||
|
||||
len = strlenW( szFolderPath );
|
||||
if (len && szFolderPath[len - 1] != '\\')
|
||||
|
@ -546,7 +600,7 @@ UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolder
|
|||
|
||||
dir = msi_get_target_folder( package, comp->Directory );
|
||||
msi_free( file->TargetPath );
|
||||
file->TargetPath = build_directory_name( 2, dir, file->FileName );
|
||||
file->TargetPath = msi_build_directory_name( 2, dir, file->FileName );
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -792,17 +846,97 @@ UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* update component state based on a feature change */
|
||||
void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
|
||||
{
|
||||
INSTALLSTATE newstate;
|
||||
ComponentList *cl;
|
||||
|
||||
newstate = feature->ActionRequest;
|
||||
if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
|
||||
|
||||
UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
|
||||
INSTALLSTATE iState)
|
||||
LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
|
||||
{
|
||||
MSICOMPONENT *component = cl->component;
|
||||
|
||||
if (!component->Enabled) continue;
|
||||
|
||||
TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
|
||||
newstate, debugstr_w(component->Component), component->Installed,
|
||||
component->Action, component->ActionRequest);
|
||||
|
||||
if (newstate == INSTALLSTATE_LOCAL)
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ComponentList *clist;
|
||||
MSIFEATURE *f;
|
||||
|
||||
component->hasLocalFeature = FALSE;
|
||||
|
||||
component->Action = newstate;
|
||||
component->ActionRequest = newstate;
|
||||
/* 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 &&
|
||||
f->ActionRequest != INSTALLSTATE_SOURCE )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
|
||||
{
|
||||
if (clist->component == component &&
|
||||
(f->ActionRequest == INSTALLSTATE_LOCAL ||
|
||||
f->ActionRequest == INSTALLSTATE_SOURCE))
|
||||
{
|
||||
TRACE("Saved by %s\n", debugstr_w(f->Feature));
|
||||
component->hasLocalFeature = TRUE;
|
||||
|
||||
if (component->Attributes & msidbComponentAttributesOptional)
|
||||
{
|
||||
if (f->Attributes & msidbFeatureAttributesFavorSource)
|
||||
{
|
||||
component->Action = INSTALLSTATE_SOURCE;
|
||||
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
}
|
||||
else if (component->Attributes & msidbComponentAttributesSourceOnly)
|
||||
{
|
||||
component->Action = INSTALLSTATE_SOURCE;
|
||||
component->ActionRequest = INSTALLSTATE_SOURCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
component->Action = INSTALLSTATE_LOCAL;
|
||||
component->ActionRequest = INSTALLSTATE_LOCAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
|
||||
newstate, debugstr_w(component->Component), component->Installed,
|
||||
component->Action, component->ActionRequest);
|
||||
}
|
||||
}
|
||||
|
||||
UINT WINAPI MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
|
||||
{
|
||||
UINT rc = ERROR_SUCCESS;
|
||||
MSIFEATURE *feature, *child;
|
||||
|
||||
TRACE("%s %i\n", debugstr_w(szFeature), iState);
|
||||
|
||||
feature = get_loaded_feature(package,szFeature);
|
||||
feature = msi_get_loaded_feature( package, szFeature );
|
||||
if (!feature)
|
||||
return ERROR_UNKNOWN_FEATURE;
|
||||
|
||||
|
@ -898,7 +1032,7 @@ UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
|
|||
{
|
||||
MSIFEATURE *feature;
|
||||
|
||||
feature = get_loaded_feature(package,szFeature);
|
||||
feature = msi_get_loaded_feature(package,szFeature);
|
||||
if (!feature)
|
||||
return ERROR_UNKNOWN_FEATURE;
|
||||
|
||||
|
@ -1018,7 +1152,7 @@ UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE t
|
|||
const WCHAR *feature_parent = feature->Feature_Parent;
|
||||
for (;;)
|
||||
{
|
||||
MSIFEATURE *parent = get_loaded_feature( package, feature_parent );
|
||||
MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
|
||||
if (!parent)
|
||||
break;
|
||||
|
||||
|
@ -1091,7 +1225,7 @@ UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
feature = get_loaded_feature(package, szFeature);
|
||||
feature = msi_get_loaded_feature(package, szFeature);
|
||||
|
||||
if (feature)
|
||||
ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
|
||||
|
@ -1143,7 +1277,7 @@ static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
|
|||
|
||||
TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
|
||||
|
||||
comp = get_loaded_component(package, szComponent);
|
||||
comp = msi_get_loaded_component(package, szComponent);
|
||||
if (!comp)
|
||||
return ERROR_UNKNOWN_COMPONENT;
|
||||
|
||||
|
@ -1161,7 +1295,7 @@ UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
|
|||
TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
|
||||
piInstalled, piAction);
|
||||
|
||||
comp = get_loaded_component(package,szComponent);
|
||||
comp = msi_get_loaded_component(package,szComponent);
|
||||
if (!comp)
|
||||
return ERROR_UNKNOWN_COMPONENT;
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
|
|||
INSTALLUILEVEL_NONE && !gUIHandlerA && !gUIHandlerW && !gUIHandlerRecord)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
error = generate_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);
|
||||
source_dir = msi_dup_property(package->db, szSourceDir);
|
||||
|
||||
|
|
|
@ -1870,7 +1870,7 @@ UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, LPCWSTR component, DWORD i
|
|||
msiobj_release( &package->hdr );
|
||||
return ERROR_FUNCTION_NOT_CALLED;
|
||||
}
|
||||
if (component && component[0] && !(comp = get_loaded_component( package, component )))
|
||||
if (component && component[0] && !(comp = msi_get_loaded_component( package, component )))
|
||||
{
|
||||
msiobj_release( &package->hdr );
|
||||
return ERROR_UNKNOWN_COMPONENT;
|
||||
|
@ -1902,7 +1902,7 @@ UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, LPCWSTR component, DWORD i
|
|||
*buflen = 2;
|
||||
r = ERROR_SUCCESS;
|
||||
}
|
||||
else if ((file = get_loaded_file( package, comp->KeyPath )))
|
||||
else if ((file = msi_get_loaded_file( package, comp->KeyPath )))
|
||||
{
|
||||
*cost = max( 8, comp->Cost / 512 );
|
||||
drive[0] = file->TargetPath[0];
|
||||
|
|
|
@ -968,34 +968,33 @@ extern UINT ACTION_MsiUnpublishAssemblies(MSIPACKAGE *package) DECLSPEC_HIDDEN;
|
|||
|
||||
/* Helpers */
|
||||
extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data ) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR msi_dup_property( MSIDATABASE *db, LPCWSTR prop ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD ) DECLSPEC_HIDDEN;
|
||||
extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR resolve_source_folder(MSIPACKAGE *package, LPCWSTR 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_clean_path( WCHAR *p ) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR 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 void msi_reset_folders( MSIPACKAGE *package, BOOL source ) DECLSPEC_HIDDEN;
|
||||
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component ) DECLSPEC_HIDDEN;
|
||||
extern MSIFEATURE *get_loaded_feature( MSIPACKAGE* package, LPCWSTR Feature ) DECLSPEC_HIDDEN;
|
||||
extern MSIFILE *get_loaded_file( MSIPACKAGE* package, LPCWSTR file ) DECLSPEC_HIDDEN;
|
||||
extern MSIFILEPATCH *get_loaded_filepatch( MSIPACKAGE* package, LPCWSTR key ) DECLSPEC_HIDDEN;
|
||||
extern MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir ) DECLSPEC_HIDDEN;
|
||||
extern int track_tempfile(MSIPACKAGE *package, LPCWSTR path) DECLSPEC_HIDDEN;
|
||||
extern UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action) DECLSPEC_HIDDEN;
|
||||
extern MSICOMPONENT *msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component) DECLSPEC_HIDDEN;
|
||||
extern MSIFEATURE *msi_get_loaded_feature(MSIPACKAGE *package, const WCHAR *Feature) DECLSPEC_HIDDEN;
|
||||
extern MSIFILE *msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *file) DECLSPEC_HIDDEN;
|
||||
extern MSIFILEPATCH *msi_get_loaded_filepatch(MSIPACKAGE* package, const WCHAR *key) DECLSPEC_HIDDEN;
|
||||
extern MSIFOLDER *msi_get_loaded_folder(MSIPACKAGE *package, const WCHAR *dir) DECLSPEC_HIDDEN;
|
||||
extern int msi_track_tempfile(MSIPACKAGE *package, const WCHAR *path) DECLSPEC_HIDDEN;
|
||||
extern void msi_free_action_script(MSIPACKAGE *package, UINT script) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR build_icon_path(MSIPACKAGE *, LPCWSTR) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR build_directory_name(DWORD , ...) DECLSPEC_HIDDEN;
|
||||
extern BOOL create_full_pathW(const WCHAR *path) DECLSPEC_HIDDEN;
|
||||
extern void reduce_to_longfilename(WCHAR*) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *msi_build_icon_path(MSIPACKAGE *, const WCHAR *) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *msi_build_directory_name(DWORD , ...) DECLSPEC_HIDDEN;
|
||||
extern BOOL msi_create_full_path(const WCHAR *path) DECLSPEC_HIDDEN;
|
||||
extern void msi_reduce_to_long_filename(WCHAR *) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *msi_create_component_advertise_string(MSIPACKAGE *, MSICOMPONENT *, const WCHAR *) DECLSPEC_HIDDEN;
|
||||
extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, MSIFEATURE *feature) DECLSPEC_HIDDEN;
|
||||
extern UINT register_unique_action(MSIPACKAGE *, LPCWSTR) DECLSPEC_HIDDEN;
|
||||
extern BOOL check_unique_action(const MSIPACKAGE *, LPCWSTR) DECLSPEC_HIDDEN;
|
||||
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_register_unique_action(MSIPACKAGE *, const WCHAR *) DECLSPEC_HIDDEN;
|
||||
extern BOOL msi_action_is_unique(const MSIPACKAGE *, const WCHAR *) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *msi_build_error_string(MSIPACKAGE *, UINT, DWORD, ...) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
|
||||
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix) DECLSPEC_HIDDEN;
|
||||
|
@ -1043,9 +1042,9 @@ extern HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsi
|
|||
/* Scripting */
|
||||
extern DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) DECLSPEC_HIDDEN;
|
||||
|
||||
/* User Interface messages from the actions */
|
||||
extern void ui_progress(MSIPACKAGE *, int, int, int, int) DECLSPEC_HIDDEN;
|
||||
extern void ui_actiondata(MSIPACKAGE *, LPCWSTR, MSIRECORD *) DECLSPEC_HIDDEN;
|
||||
/* User interface messages from the actions */
|
||||
extern void msi_ui_progress(MSIPACKAGE *, int, int, int, int) DECLSPEC_HIDDEN;
|
||||
extern void msi_ui_actiondata(MSIPACKAGE *, const WCHAR *, MSIRECORD *) DECLSPEC_HIDDEN;
|
||||
|
||||
/* common strings */
|
||||
static const WCHAR szSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
|
||||
|
@ -1139,6 +1138,7 @@ static const WCHAR szStringData[] = {'_','S','t','r','i','n','g','D','a','t','a'
|
|||
static const WCHAR szStringPool[] = {'_','S','t','r','i','n','g','P','o','o','l',0};
|
||||
static const WCHAR szInstallLevel[] = {'I','N','S','T','A','L','L','L','E','V','E','L',0};
|
||||
static const WCHAR szCostInitialize[] = {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
|
||||
static const WCHAR szAppDataFolder[] = {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
|
||||
/* memory allocation macro functions */
|
||||
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
|
||||
|
|
|
@ -141,6 +141,17 @@ static void free_assembly( MSIASSEMBLY *assembly )
|
|||
msi_free( assembly );
|
||||
}
|
||||
|
||||
void msi_free_action_script( MSIPACKAGE *package, UINT script )
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < package->script->ActionCount[script]; i++)
|
||||
msi_free( package->script->Actions[script][i] );
|
||||
|
||||
msi_free( package->script->Actions[script] );
|
||||
package->script->Actions[script] = NULL;
|
||||
package->script->ActionCount[script] = 0;
|
||||
}
|
||||
|
||||
static void free_package_structures( MSIPACKAGE *package )
|
||||
{
|
||||
INT i;
|
||||
|
@ -684,7 +695,6 @@ static VOID set_installer_properties(MSIPACKAGE *package)
|
|||
static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
|
||||
static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR szAppDataFolder[] = {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0};
|
||||
static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
|
||||
static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
|
@ -1443,6 +1453,22 @@ static UINT validate_package( MSIPACKAGE *package )
|
|||
return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int msi_track_tempfile( MSIPACKAGE *package, const WCHAR *path )
|
||||
{
|
||||
MSITEMPFILE *temp;
|
||||
|
||||
TRACE("%s\n", debugstr_w(path));
|
||||
|
||||
LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
|
||||
{
|
||||
if (!strcmpW( path, temp->Path )) return 0;
|
||||
}
|
||||
if (!(temp = msi_alloc_zero( sizeof (MSITEMPFILE) ))) return -1;
|
||||
list_add_head( &package->tempfiles, &temp->entry );
|
||||
temp->Path = strdupW( path );
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
||||
{
|
||||
static const WCHAR dotmsi[] = {'.','m','s','i',0};
|
||||
|
@ -1552,7 +1578,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
}
|
||||
|
||||
if( file != szPackage )
|
||||
track_tempfile( package, file );
|
||||
msi_track_tempfile( package, file );
|
||||
|
||||
si = MSI_GetSummaryInformationW( db->storage, 0 );
|
||||
if (!si)
|
||||
|
|
|
@ -1029,3 +1029,29 @@ BOOL MSI_RecordsAreEqual(MSIRECORD *a, MSIRECORD *b)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WCHAR *msi_dup_record_field( MSIRECORD *rec, INT field )
|
||||
{
|
||||
DWORD sz = 0;
|
||||
WCHAR *str;
|
||||
UINT r;
|
||||
|
||||
if (MSI_RecordIsNull( rec, field )) return NULL;
|
||||
|
||||
r = MSI_RecordGetStringW( rec, field, NULL, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
sz++;
|
||||
str = msi_alloc( sz * sizeof(WCHAR) );
|
||||
if (!str) return NULL;
|
||||
str[0] = 0;
|
||||
r = MSI_RecordGetStringW( rec, field, str, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("failed to get string!\n");
|
||||
msi_free( str );
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
|
|||
action_property = MSI_RecordGetString(rec, 7);
|
||||
append_productcode(package, action_property, productid);
|
||||
MSI_RecordSetStringW(uirow, 1, productid);
|
||||
ui_actiondata(package, szFindRelatedProducts, uirow);
|
||||
msi_ui_actiondata(package, szFindRelatedProducts, uirow);
|
||||
}
|
||||
index ++;
|
||||
}
|
||||
|
@ -218,13 +218,13 @@ UINT ACTION_FindRelatedProducts(MSIPACKAGE *package)
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
if (check_unique_action(package, szFindRelatedProducts))
|
||||
if (msi_action_is_unique(package, szFindRelatedProducts))
|
||||
{
|
||||
TRACE("Skipping FindRelatedProducts action: already done in UI sequence\n");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
register_unique_action(package, szFindRelatedProducts);
|
||||
msi_register_unique_action(package, szFindRelatedProducts);
|
||||
|
||||
rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
|
|
Loading…
Reference in New Issue