action.c
来自「一个类似windows」· C语言 代码 · 共 2,053 行 · 第 1/5 页
C
2,053 行
{
TRACE("Component %s already loaded\n", debugstr_w(component) );
add_feature_component( ilfs->feature, comp );
return ERROR_SUCCESS;
}
rc = MSI_OpenQuery(ilfs->package->db, &view, Query, component);
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords(view, NULL, iterate_component_check, ilfs);
msiobj_release( &view->hdr );
return ERROR_SUCCESS;
}
static UINT load_feature(MSIRECORD * row, LPVOID param)
{
MSIPACKAGE* package = (MSIPACKAGE*)param;
MSIFEATURE* feature;
static const WCHAR Query1[] =
{'S','E','L','E','C','T',' ',
'`','C','o','m','p','o','n','e','n','t','_','`',
' ','F','R','O','M',' ','`','F','e','a','t','u','r','e',
'C','o','m','p','o','n','e','n','t','s','`',' ',
'W','H','E','R','E',' ',
'`','F','e', 'a','t','u','r','e','_','`',' ','=','\'','%','s','\'',0};
MSIQUERY * view;
UINT rc;
_ilfs ilfs;
/* fill in the data */
feature = msi_alloc_zero( sizeof (MSIFEATURE) );
if (!feature)
return ERROR_NOT_ENOUGH_MEMORY;
list_init( &feature->Components );
feature->Feature = msi_dup_record_field( row, 1 );
TRACE("Loading feature %s\n",debugstr_w(feature->Feature));
feature->Feature_Parent = msi_dup_record_field( row, 2 );
feature->Title = msi_dup_record_field( row, 3 );
feature->Description = msi_dup_record_field( row, 4 );
if (!MSI_RecordIsNull(row,5))
feature->Display = MSI_RecordGetInteger(row,5);
feature->Level= MSI_RecordGetInteger(row,6);
feature->Directory = msi_dup_record_field( row, 7 );
feature->Attributes = MSI_RecordGetInteger(row,8);
feature->Installed = INSTALLSTATE_ABSENT;
feature->Action = INSTALLSTATE_UNKNOWN;
feature->ActionRequest = INSTALLSTATE_UNKNOWN;
list_add_tail( &package->features, &feature->entry );
/* load feature components */
rc = MSI_OpenQuery( package->db, &view, Query1, feature->Feature );
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
ilfs.package = package;
ilfs.feature = feature;
MSI_IterateRecords(view, NULL, iterate_load_featurecomponents , &ilfs);
msiobj_release(&view->hdr);
return ERROR_SUCCESS;
}
static UINT load_file(MSIRECORD *row, LPVOID param)
{
MSIPACKAGE* package = (MSIPACKAGE*)param;
LPCWSTR component;
MSIFILE *file;
/* fill in the data */
file = msi_alloc_zero( sizeof (MSIFILE) );
if (!file)
return ERROR_NOT_ENOUGH_MEMORY;
file->File = msi_dup_record_field( row, 1 );
component = MSI_RecordGetString( row, 2 );
file->Component = get_loaded_component( package, component );
if (!file->Component)
ERR("Unfound Component %s\n",debugstr_w(component));
file->FileName = msi_dup_record_field( row, 3 );
reduce_to_longfilename( file->FileName );
file->ShortName = msi_dup_record_field( row, 3 );
reduce_to_shortfilename( file->ShortName );
file->FileSize = MSI_RecordGetInteger( row, 4 );
file->Version = msi_dup_record_field( row, 5 );
file->Language = msi_dup_record_field( row, 6 );
file->Attributes = MSI_RecordGetInteger( row, 7 );
file->Sequence = MSI_RecordGetInteger( row, 8 );
file->state = msifs_invalid;
TRACE("File Loaded (%s)\n",debugstr_w(file->File));
list_add_tail( &package->files, &file->entry );
return ERROR_SUCCESS;
}
static UINT load_all_files(MSIPACKAGE *package)
{
MSIQUERY * view;
UINT rc;
static const WCHAR Query[] =
{'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
'`','F','i','l','e','`',' ', 'O','R','D','E','R',' ','B','Y',' ',
'`','S','e','q','u','e','n','c','e','`', 0};
if (!package)
return ERROR_INVALID_HANDLE;
rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords(view, NULL, load_file, package);
msiobj_release(&view->hdr);
return ERROR_SUCCESS;
}
/*
* I am not doing any of the costing functionality yet.
* Mostly looking at doing the Component and Feature loading
*
* The native MSI does A LOT of modification to tables here. Mostly adding
* a lot of temporary columns to the Feature and Component tables.
*
* note: Native msi also tracks the short filename. But I am only going to
* track the long ones. Also looking at this directory table
* it appears that the directory table does not get the parents
* resolved base on property only based on their entries in the
* directory table.
*/
static UINT ACTION_CostInitialize(MSIPACKAGE *package)
{
MSIQUERY * view;
UINT rc;
static const WCHAR Query_all[] =
{'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
'`','F','e','a','t','u','r','e','`',0};
static const WCHAR szCosting[] =
{'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
static const WCHAR szZero[] = { '0', 0 };
if ( 1 == msi_get_property_int( package, szCosting, 0 ) )
return ERROR_SUCCESS;
MSI_SetPropertyW(package, szCosting, szZero);
MSI_SetPropertyW(package, cszRootDrive , c_colon);
rc = MSI_DatabaseOpenViewW(package->db,Query_all,&view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MSI_IterateRecords(view, NULL, load_feature, package);
msiobj_release(&view->hdr);
load_all_files(package);
return ERROR_SUCCESS;
}
static UINT execute_script(MSIPACKAGE *package, UINT script )
{
int i;
UINT rc = ERROR_SUCCESS;
TRACE("Executing Script %i\n",script);
for (i = 0; i < package->script->ActionCount[script]; i++)
{
LPWSTR action;
action = package->script->Actions[script][i];
ui_actionstart(package, action);
TRACE("Executing Action (%s)\n",debugstr_w(action));
rc = ACTION_PerformAction(package, action, TRUE);
msi_free(package->script->Actions[script][i]);
if (rc != ERROR_SUCCESS)
break;
}
msi_free(package->script->Actions[script]);
package->script->ActionCount[script] = 0;
package->script->Actions[script] = NULL;
return rc;
}
static UINT ACTION_FileCost(MSIPACKAGE *package)
{
return ERROR_SUCCESS;
}
static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir )
{
static const WCHAR Query[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','D','i','r','e','c', 't','o','r','y','`',' ',
'W','H','E','R','E',' ', '`', 'D','i','r','e','c','t', 'o','r','y','`',
' ','=',' ','\'','%','s','\'',
0};
LPWSTR ptargetdir, targetdir, srcdir;
LPCWSTR parent;
LPWSTR shortname = NULL;
MSIRECORD * row = 0;
MSIFOLDER *folder;
TRACE("Looking for dir %s\n",debugstr_w(dir));
folder = get_loaded_folder( package, dir );
if (folder)
return folder;
TRACE("Working to load %s\n",debugstr_w(dir));
folder = msi_alloc_zero( sizeof (MSIFOLDER) );
if (!folder)
return NULL;
folder->Directory = strdupW(dir);
row = MSI_QueryGetRecord(package->db, Query, dir);
if (!row)
return NULL;
ptargetdir = targetdir = msi_dup_record_field(row,3);
/* split src and target dir */
if (strchrW(targetdir,':'))
{
srcdir=strchrW(targetdir,':');
*srcdir=0;
srcdir ++;
}
else
srcdir=NULL;
/* for now only pick long filename versions */
if (strchrW(targetdir,'|'))
{
shortname = targetdir;
targetdir = strchrW(targetdir,'|');
*targetdir = 0;
targetdir ++;
}
/* for the sourcedir pick the short filename */
if (srcdir && strchrW(srcdir,'|'))
{
LPWSTR p = strchrW(srcdir,'|');
*p = 0;
}
/* now check for root dirs */
if (targetdir[0] == '.' && targetdir[1] == 0)
targetdir = NULL;
if (targetdir)
{
TRACE(" TargetDefault = %s\n",debugstr_w(targetdir));
msi_free( folder->TargetDefault);
folder->TargetDefault = strdupW(targetdir);
}
if (srcdir)
folder->SourceDefault = strdupW(srcdir);
else if (shortname)
folder->SourceDefault = strdupW(shortname);
else if (targetdir)
folder->SourceDefault = strdupW(targetdir);
msi_free(ptargetdir);
TRACE(" SourceDefault = %s\n", debugstr_w( folder->SourceDefault ));
parent = MSI_RecordGetString(row,2);
if (parent)
{
folder->Parent = load_folder( package, parent );
if ( folder->Parent )
TRACE("loaded parent %p %s\n", folder->Parent,
debugstr_w(folder->Parent->Directory));
else
ERR("failed to load parent folder %s\n", debugstr_w(parent));
}
folder->Property = msi_dup_property( package, dir );
msiobj_release(&row->hdr);
list_add_tail( &package->folders, &folder->entry );
TRACE("%s returning %p\n",debugstr_w(dir),folder);
return folder;
}
/* scan for and update current install states */
static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
{
MSICOMPONENT *comp;
MSIFEATURE *feature;
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{
INSTALLSTATE res;
res = MsiGetComponentPathW( package->ProductCode,
comp->ComponentId, NULL, NULL);
if (res < 0)
res = INSTALLSTATE_ABSENT;
comp->Installed = res;
}
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
ComponentList *cl;
INSTALLSTATE res = -10;
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{
comp= cl->component;
if (res == -10)
res = comp->Installed;
else
{
if (res == comp->Installed)
continue;
if (res != comp->Installed)
res = INSTALLSTATE_INCOMPLETE;
}
}
feature->Installed = res;
}
}
static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property,
INSTALLSTATE state)
{
static const WCHAR all[]={'A','L','L',0};
LPWSTR override;
MSIFEATURE *feature;
override = msi_dup_property( package, property );
if (!override)
return FALSE;
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
if (strcmpiW(override,all)==0)
{
feature->ActionRequest= state;
feature->Action = state;
}
else
{
LPWSTR ptr = override;
LPWSTR ptr2 = strchrW(override,',');
while (ptr)
{
if ((ptr2 && strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
|| (!ptr2 && strcmpW(ptr,feature->Feature)==0))
{
feature->ActionRequest= state;
feature->Action = state;
break;
}
if (ptr2)
{
ptr=ptr2+1;
ptr2 = strchrW(ptr,',');
}
else
break;
}
}
}
msi_free(override);
return TRUE;
}
static UINT SetFeatureStates(MSIPACKAGE *package)
{
int install_level;
static const WCHAR szlevel[] =
{'I','N','S','T','A','L','L','L','E','V','E','L',0};
static const WCHAR szAddLocal[] =
{'A','D','D','L','O','C','A','L',0};
static const WCHAR szRemove[] =
{'R','E','M','O','V','E',0};
static const WCHAR szReinstall[] =
{'R','E','I','N','S','T','A','L','L',0};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?