Activate features and components based on their various conditions.
This commit is contained in:
parent
ec688fb4e0
commit
7d3e5973fe
|
@ -76,6 +76,7 @@ typedef struct tagMSICOMPONENT
|
||||||
WCHAR KeyPath[96];
|
WCHAR KeyPath[96];
|
||||||
|
|
||||||
INSTALLSTATE State;
|
INSTALLSTATE State;
|
||||||
|
BOOL FeatureState;
|
||||||
BOOL Enabled;
|
BOOL Enabled;
|
||||||
INT Cost;
|
INT Cost;
|
||||||
}MSICOMPONENT;
|
}MSICOMPONENT;
|
||||||
|
@ -136,6 +137,8 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage);
|
||||||
static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage);
|
static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage);
|
||||||
static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage);
|
static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage);
|
||||||
static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action);
|
static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action);
|
||||||
|
static UINT ACTION_InstallInitialize(MSIHANDLE hPackage);
|
||||||
|
static UINT ACTION_InstallValidate(MSIHANDLE hPackage);
|
||||||
|
|
||||||
static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
|
static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
|
||||||
const LPWSTR target, const INT type);
|
const LPWSTR target, const INT type);
|
||||||
|
@ -205,6 +208,22 @@ inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
|
||||||
|
{
|
||||||
|
INT rc = -1;
|
||||||
|
INT i;
|
||||||
|
|
||||||
|
for (i = 0; i < package->loaded_features; i++)
|
||||||
|
{
|
||||||
|
if (strcmpW(Feature,package->features[i].Feature)==0)
|
||||||
|
{
|
||||||
|
rc = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static UINT track_tempfile(MSIHANDLE hPackage, LPCWSTR name, LPCWSTR path)
|
static UINT track_tempfile(MSIHANDLE hPackage, LPCWSTR name, LPCWSTR path)
|
||||||
{
|
{
|
||||||
MSIPACKAGE *package;
|
MSIPACKAGE *package;
|
||||||
|
@ -254,6 +273,19 @@ void ACTION_remove_tracked_tempfiles(MSIPACKAGE* package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void progress_message(MSIHANDLE hPackage, int a, int b, int c, int d )
|
||||||
|
{
|
||||||
|
MSIHANDLE row;
|
||||||
|
|
||||||
|
row = MsiCreateRecord(4);
|
||||||
|
MsiRecordSetInteger(row,1,a);
|
||||||
|
MsiRecordSetInteger(row,2,b);
|
||||||
|
MsiRecordSetInteger(row,3,c);
|
||||||
|
MsiRecordSetInteger(row,4,d);
|
||||||
|
MsiProcessMessage(hPackage, INSTALLMESSAGE_PROGRESS, row);
|
||||||
|
MsiCloseHandle(row);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* TOP level entry points
|
* TOP level entry points
|
||||||
*****************************************************/
|
*****************************************************/
|
||||||
|
@ -576,15 +608,27 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
|
||||||
{'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
|
{'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
|
||||||
const static WCHAR szFileCost[] =
|
const static WCHAR szFileCost[] =
|
||||||
{'F','i','l','e','C','o','s','t',0};
|
{'F','i','l','e','C','o','s','t',0};
|
||||||
|
const static WCHAR szInstallInitialize[] =
|
||||||
|
{'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
|
||||||
|
const static WCHAR szInstallValidate[] =
|
||||||
|
{'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
|
||||||
|
|
||||||
TRACE("Performing action (%s)\n",debugstr_w(action));
|
TRACE("Performing action (%s)\n",debugstr_w(action));
|
||||||
|
progress_message(hPackage,2,25,0,0);
|
||||||
|
|
||||||
|
/* pre install, setup and configureation block */
|
||||||
if (strcmpW(action,szCostInitialize)==0)
|
if (strcmpW(action,szCostInitialize)==0)
|
||||||
return ACTION_CostInitialize(hPackage);
|
return ACTION_CostInitialize(hPackage);
|
||||||
if (strcmpW(action,szFileCost)==0)
|
if (strcmpW(action,szFileCost)==0)
|
||||||
return ACTION_FileCost(hPackage);
|
return ACTION_FileCost(hPackage);
|
||||||
if (strcmpW(action,szCostFinalize)==0)
|
if (strcmpW(action,szCostFinalize)==0)
|
||||||
return ACTION_CostFinalize(hPackage);
|
return ACTION_CostFinalize(hPackage);
|
||||||
|
if (strcmpW(action,szInstallValidate)==0)
|
||||||
|
return ACTION_InstallValidate(hPackage);
|
||||||
|
|
||||||
|
/* install block */
|
||||||
|
if (strcmpW(action,szInstallInitialize)==0)
|
||||||
|
return ACTION_InstallInitialize(hPackage);
|
||||||
if (strcmpW(action,szCreateFolders)==0)
|
if (strcmpW(action,szCreateFolders)==0)
|
||||||
return ACTION_CreateFolders(hPackage);
|
return ACTION_CreateFolders(hPackage);
|
||||||
if (strcmpW(action,szInstallFiles)==0)
|
if (strcmpW(action,szInstallFiles)==0)
|
||||||
|
@ -593,6 +637,7 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
|
||||||
return ACTION_DuplicateFiles(hPackage);
|
return ACTION_DuplicateFiles(hPackage);
|
||||||
if (strcmpW(action,szWriteRegistryValues)==0)
|
if (strcmpW(action,szWriteRegistryValues)==0)
|
||||||
return ACTION_WriteRegistryValues(hPackage);
|
return ACTION_WriteRegistryValues(hPackage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Current called during itunes but unimplemented
|
Current called during itunes but unimplemented
|
||||||
|
|
||||||
|
@ -602,14 +647,11 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
|
||||||
CostInitialize
|
CostInitialize
|
||||||
MigrateFeatureStates
|
MigrateFeatureStates
|
||||||
ResolveSource (sets SourceDir)
|
ResolveSource (sets SourceDir)
|
||||||
FileCost
|
|
||||||
ValidateProductID (sets ProductID)
|
ValidateProductID (sets ProductID)
|
||||||
IsolateComponents (Empty)
|
IsolateComponents (Empty)
|
||||||
SetODBCFolders
|
SetODBCFolders
|
||||||
MigrateFeatureStates
|
MigrateFeatureStates
|
||||||
InstallValidate
|
|
||||||
RemoveExistingProducts
|
RemoveExistingProducts
|
||||||
InstallInitialize
|
|
||||||
AllocateRegistrySpace
|
AllocateRegistrySpace
|
||||||
ProcessComponents
|
ProcessComponents
|
||||||
UnpublishComponents
|
UnpublishComponents
|
||||||
|
@ -1092,6 +1134,7 @@ static int load_component(MSIPACKAGE* package, MSIHANDLE row)
|
||||||
|
|
||||||
package->components[index].State = INSTALLSTATE_UNKNOWN;
|
package->components[index].State = INSTALLSTATE_UNKNOWN;
|
||||||
package->components[index].Enabled = TRUE;
|
package->components[index].Enabled = TRUE;
|
||||||
|
package->components[index].FeatureState= FALSE;
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
@ -1518,19 +1561,6 @@ static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
|
||||||
|
|
||||||
TRACE("Working to resolve %s\n",debugstr_w(name));
|
TRACE("Working to resolve %s\n",debugstr_w(name));
|
||||||
|
|
||||||
for (i = 0; i < package->loaded_folders; i++)
|
|
||||||
{
|
|
||||||
if (strcmpW(package->folders[i].Directory,name)==0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i >= package->loaded_folders)
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
|
|
||||||
|
|
||||||
if (folder)
|
|
||||||
*folder = &(package->folders[i]);
|
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
@ -1548,6 +1578,8 @@ static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
|
||||||
if (set_prop)
|
if (set_prop)
|
||||||
MsiSetPropertyW(hPackage,cszTargetDir,path);
|
MsiSetPropertyW(hPackage,cszTargetDir,path);
|
||||||
}
|
}
|
||||||
|
if (folder)
|
||||||
|
*folder = &(package->folders[0]);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1568,10 +1600,24 @@ static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (folder)
|
||||||
|
*folder = &(package->folders[0]);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < package->loaded_folders; i++)
|
||||||
|
{
|
||||||
|
if (strcmpW(package->folders[i].Directory,name)==0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= package->loaded_folders)
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
if (folder)
|
||||||
|
*folder = &(package->folders[i]);
|
||||||
|
|
||||||
if (!source && package->folders[i].ResolvedTarget[0])
|
if (!source && package->folders[i].ResolvedTarget[0])
|
||||||
{
|
{
|
||||||
strcpyW(path,package->folders[i].ResolvedTarget);
|
strcpyW(path,package->folders[i].ResolvedTarget);
|
||||||
|
@ -1624,11 +1670,11 @@ static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
|
||||||
* The costing needs to be implemented at some point but for now I am going
|
* The costing needs to be implemented at some point but for now I am going
|
||||||
* to focus on the directory building
|
* to focus on the directory building
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
|
static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
|
||||||
{
|
{
|
||||||
static const CHAR *ExecSeqQuery = "select * from Directory";
|
static const CHAR *ExecSeqQuery = "select * from Directory";
|
||||||
|
static const CHAR *ConditionQuery = "select * from Condition";
|
||||||
UINT rc;
|
UINT rc;
|
||||||
MSIHANDLE view;
|
MSIHANDLE view;
|
||||||
MSIPACKAGE *package;
|
MSIPACKAGE *package;
|
||||||
|
@ -1637,6 +1683,7 @@ static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
|
||||||
TRACE("Building Directory properties\n");
|
TRACE("Building Directory properties\n");
|
||||||
|
|
||||||
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
||||||
|
|
||||||
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
|
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
|
||||||
|
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
|
@ -1742,8 +1789,77 @@ static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MsiSetPropertyA(hPackage,"CostingComplete","1");
|
TRACE("Evaluating Condition Table\n");
|
||||||
|
|
||||||
|
rc = MsiDatabaseOpenViewA(package->db, ConditionQuery, &view);
|
||||||
|
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = MsiViewExecute(view, 0);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
MsiViewClose(view);
|
||||||
|
MsiCloseHandle(view);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
WCHAR Feature[0x100];
|
||||||
|
WCHAR Condition[0x100];
|
||||||
|
MSIHANDLE row = 0;
|
||||||
|
DWORD sz;
|
||||||
|
int feature_index;
|
||||||
|
|
||||||
|
rc = MsiViewFetch(view,&row);
|
||||||
|
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
rc = ERROR_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = 0x100;
|
||||||
|
MsiRecordGetStringW(row,1,Feature,&sz);
|
||||||
|
sz = 0x100;
|
||||||
|
MsiRecordGetStringW(row,3,Condition,&sz);
|
||||||
|
|
||||||
|
feature_index = get_loaded_feature(package,Feature);
|
||||||
|
if (feature_index < 0)
|
||||||
|
ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (MsiEvaluateConditionW(hPackage,Condition) == MSICONDITION_TRUE)
|
||||||
|
{
|
||||||
|
int level = MsiRecordGetInteger(row,2);
|
||||||
|
TRACE("Reseting feature %s to level %i\n",debugstr_w(Feature),
|
||||||
|
level);
|
||||||
|
package->features[feature_index].Level = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MsiCloseHandle(row);
|
||||||
|
}
|
||||||
|
MsiViewClose(view);
|
||||||
|
MsiCloseHandle(view);
|
||||||
|
|
||||||
|
TRACE("Enabling or Disabling Components\n");
|
||||||
|
for (i = 0; i < package->loaded_components; i++)
|
||||||
|
{
|
||||||
|
if (package->components[i].Condition[0])
|
||||||
|
{
|
||||||
|
if (MsiEvaluateConditionW(hPackage,
|
||||||
|
package->components[i].Condition) == MSICONDITION_FALSE)
|
||||||
|
{
|
||||||
|
TRACE("Disabling component %s\n",
|
||||||
|
debugstr_w(package->components[i].Component));
|
||||||
|
package->components[i].Enabled = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MsiSetPropertyA(hPackage,"CostingComplete","1");
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2003,14 +2119,6 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
|
||||||
INT index;
|
INT index;
|
||||||
MSIPACKAGE *package;
|
MSIPACKAGE *package;
|
||||||
|
|
||||||
/* REALLY what we want to do is go through all the enabled
|
|
||||||
* features and check all the components of that feature and
|
|
||||||
* make sure that component is not already install and blah
|
|
||||||
* blah blah... I will do it that way some day.. really
|
|
||||||
* but for sheer gratification I am going to just brute force
|
|
||||||
* install all the files
|
|
||||||
*/
|
|
||||||
|
|
||||||
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
||||||
|
|
||||||
if (!package)
|
if (!package)
|
||||||
|
@ -2023,6 +2131,17 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
|
||||||
|
|
||||||
file = &package->files[index];
|
file = &package->files[index];
|
||||||
|
|
||||||
|
if (file->Temporary)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!package->components[file->ComponentIndex].Enabled ||
|
||||||
|
!package->components[file->ComponentIndex].FeatureState)
|
||||||
|
{
|
||||||
|
TRACE("File %s is not scheduled for install\n",
|
||||||
|
debugstr_w(file->File));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ((file->State == 1) || (file->State == 2))
|
if ((file->State == 1) || (file->State == 2))
|
||||||
{
|
{
|
||||||
TRACE("Installing %s\n",debugstr_w(file->File));
|
TRACE("Installing %s\n",debugstr_w(file->File));
|
||||||
|
@ -2048,6 +2167,7 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
|
||||||
TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
|
TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
|
||||||
debugstr_w(file->TargetPath));
|
debugstr_w(file->TargetPath));
|
||||||
|
|
||||||
|
progress_message(hPackage,2,1,0,0);
|
||||||
rc = !MoveFileW(file->SourcePath,file->TargetPath);
|
rc = !MoveFileW(file->SourcePath,file->TargetPath);
|
||||||
if (rc)
|
if (rc)
|
||||||
ERR("Unable to move file\n");
|
ERR("Unable to move file\n");
|
||||||
|
@ -2066,7 +2186,6 @@ inline static UINT get_file_target(MSIHANDLE hPackage, LPCWSTR file_key,
|
||||||
INT index;
|
INT index;
|
||||||
|
|
||||||
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
||||||
|
|
||||||
if (!package)
|
if (!package)
|
||||||
return ERROR_INVALID_HANDLE;
|
return ERROR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -2074,8 +2193,13 @@ inline static UINT get_file_target(MSIHANDLE hPackage, LPCWSTR file_key,
|
||||||
{
|
{
|
||||||
if (strcmpW(file_key,package->files[index].File)==0)
|
if (strcmpW(file_key,package->files[index].File)==0)
|
||||||
{
|
{
|
||||||
strcmpW(file_source,package->files[index].TargetPath);
|
if (package->files[index].State >= 3)
|
||||||
return ERROR_SUCCESS;
|
{
|
||||||
|
strcmpW(file_source,package->files[index].TargetPath);
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERROR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2088,16 +2212,13 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
|
||||||
MSIHANDLE view;
|
MSIHANDLE view;
|
||||||
MSIHANDLE row = 0;
|
MSIHANDLE row = 0;
|
||||||
static const CHAR *ExecSeqQuery = "select * from DuplicateFile";
|
static const CHAR *ExecSeqQuery = "select * from DuplicateFile";
|
||||||
MSIHANDLE db;
|
MSIPACKAGE* package;
|
||||||
|
|
||||||
|
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
||||||
|
if (!package)
|
||||||
|
return ERROR_INVALID_HANDLE;
|
||||||
|
|
||||||
/*
|
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
|
||||||
* Yes we should only do this for components that are installed
|
|
||||||
* but again I need to do that went I track components.
|
|
||||||
*/
|
|
||||||
db = MsiGetActiveDatabase(hPackage);
|
|
||||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
|
||||||
MsiCloseHandle(db);
|
|
||||||
|
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -2116,6 +2237,8 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
|
||||||
WCHAR file_source[MAX_PATH];
|
WCHAR file_source[MAX_PATH];
|
||||||
WCHAR dest_name[0x100];
|
WCHAR dest_name[0x100];
|
||||||
WCHAR dest_path[MAX_PATH];
|
WCHAR dest_path[MAX_PATH];
|
||||||
|
WCHAR component[0x100];
|
||||||
|
INT component_index;
|
||||||
|
|
||||||
DWORD sz=0x100;
|
DWORD sz=0x100;
|
||||||
|
|
||||||
|
@ -2126,6 +2249,24 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sz=0x100;
|
||||||
|
rc = MsiRecordGetStringW(row,2,component,&sz);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Unable to get component\n");
|
||||||
|
MsiCloseHandle(row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
component_index = get_loaded_component(package,component);
|
||||||
|
if (!package->components[component_index].Enabled ||
|
||||||
|
!package->components[component_index].FeatureState)
|
||||||
|
{
|
||||||
|
TRACE("Skipping copy due to disabled component\n");
|
||||||
|
MsiCloseHandle(row);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sz=0x100;
|
sz=0x100;
|
||||||
rc = MsiRecordGetStringW(row,3,file_key,&sz);
|
rc = MsiRecordGetStringW(row,3,file_key,&sz);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
|
@ -2283,14 +2424,13 @@ static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage)
|
||||||
MSIHANDLE view;
|
MSIHANDLE view;
|
||||||
MSIHANDLE row = 0;
|
MSIHANDLE row = 0;
|
||||||
static const CHAR *ExecSeqQuery = "select * from Registry";
|
static const CHAR *ExecSeqQuery = "select * from Registry";
|
||||||
MSIHANDLE db;
|
MSIPACKAGE *package;
|
||||||
|
|
||||||
/* Again here we want to key off of the components being installed...
|
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
||||||
* oh well
|
if (!package)
|
||||||
*/
|
return ERROR_INVALID_HANDLE;
|
||||||
db = MsiGetActiveDatabase(hPackage);
|
|
||||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
|
||||||
MsiCloseHandle(db);
|
|
||||||
|
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -2311,6 +2451,8 @@ static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage)
|
||||||
LPSTR value_data = NULL;
|
LPSTR value_data = NULL;
|
||||||
HKEY root_key, hkey;
|
HKEY root_key, hkey;
|
||||||
DWORD type,size;
|
DWORD type,size;
|
||||||
|
WCHAR component[0x100];
|
||||||
|
INT component_index;
|
||||||
|
|
||||||
INT root;
|
INT root;
|
||||||
DWORD sz=0x100;
|
DWORD sz=0x100;
|
||||||
|
@ -2322,6 +2464,18 @@ static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sz= 0x100;
|
||||||
|
MsiRecordGetStringW(row,6,component,&sz);
|
||||||
|
component_index = get_loaded_component(package,component);
|
||||||
|
|
||||||
|
if (!package->components[component_index].Enabled ||
|
||||||
|
!package->components[component_index].FeatureState)
|
||||||
|
{
|
||||||
|
TRACE("Skipping write due to disabled component\n");
|
||||||
|
MsiCloseHandle(row);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* null values have special meanings during uninstalls and such */
|
/* null values have special meanings during uninstalls and such */
|
||||||
|
|
||||||
if(MsiRecordIsNull(row,5))
|
if(MsiRecordIsNull(row,5))
|
||||||
|
@ -2380,6 +2534,7 @@ static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage)
|
||||||
RegSetValueExW(hkey, name, 0, type, value_data, size);
|
RegSetValueExW(hkey, name, 0, type, value_data, size);
|
||||||
HeapFree(GetProcessHeap(),0,value_data);
|
HeapFree(GetProcessHeap(),0,value_data);
|
||||||
}
|
}
|
||||||
|
progress_message(hPackage,2,1,0,0);
|
||||||
|
|
||||||
MsiCloseHandle(row);
|
MsiCloseHandle(row);
|
||||||
}
|
}
|
||||||
|
@ -2468,6 +2623,123 @@ static DWORD deformat_string(MSIHANDLE hPackage, WCHAR* ptr,WCHAR** data)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT ACTION_InstallInitialize(MSIHANDLE hPackage)
|
||||||
|
{
|
||||||
|
CHAR level[10000];
|
||||||
|
INT install_level;
|
||||||
|
DWORD sz;
|
||||||
|
MSIPACKAGE *package;
|
||||||
|
INT i,j;
|
||||||
|
/* I do not know if this is where it should happen.. but */
|
||||||
|
|
||||||
|
TRACE("Checking Install Level\n");
|
||||||
|
FIXME("The Attributes of the feature OVERRIDE THIS... unimplemented\n");
|
||||||
|
FIXME("As does the ALLLOCAL and such propertys\n");
|
||||||
|
|
||||||
|
sz = 10000;
|
||||||
|
if (MsiGetPropertyA(hPackage,"INSTALLLEVEL",level,&sz)==ERROR_SUCCESS)
|
||||||
|
install_level = atoi(level);
|
||||||
|
else
|
||||||
|
install_level = 1;
|
||||||
|
|
||||||
|
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
||||||
|
if (!package)
|
||||||
|
return ERROR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* components FeatureState defaults to FALSE. the idea is we want to
|
||||||
|
* enable the component is ANY feature that uses it is enabled to install
|
||||||
|
*/
|
||||||
|
for(i = 0; i < package->loaded_features; i++)
|
||||||
|
{
|
||||||
|
BOOL feature_state= ((package->features[i].Level > 0) &&
|
||||||
|
(package->features[i].Level <= install_level));
|
||||||
|
TRACE("Feature %s has a state of %i\n",
|
||||||
|
debugstr_w(package->features[i].Feature), feature_state);
|
||||||
|
for( j = 0; j < package->features[i].ComponentCount; j++)
|
||||||
|
{
|
||||||
|
package->components[package->features[i].Components[j]].FeatureState
|
||||||
|
|= feature_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* so basically we ONLY want to install a component if its Enabled AND
|
||||||
|
* FeatureState are both TRUE
|
||||||
|
*/
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT ACTION_InstallValidate(MSIHANDLE hPackage)
|
||||||
|
{
|
||||||
|
DWORD progress = 0;
|
||||||
|
static const CHAR q1[]="SELECT * FROM Registry";
|
||||||
|
static const CHAR q2[]=
|
||||||
|
"select Action from InstallExecuteSequence where Sequence > 0 order by Sequence";
|
||||||
|
UINT rc;
|
||||||
|
MSIHANDLE view;
|
||||||
|
MSIHANDLE row = 0;
|
||||||
|
MSIHANDLE db;
|
||||||
|
BOOL flipit= FALSE;
|
||||||
|
MSIPACKAGE* package;
|
||||||
|
|
||||||
|
TRACE(" InstallValidate \n");
|
||||||
|
|
||||||
|
db = MsiGetActiveDatabase(hPackage);
|
||||||
|
rc = MsiDatabaseOpenViewA(db, q2, &view);
|
||||||
|
rc = MsiViewExecute(view, 0);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
rc = MsiViewFetch(view,&row);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
rc = ERROR_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!flipit)
|
||||||
|
{
|
||||||
|
CHAR buf[0x100];
|
||||||
|
DWORD sz=0x100;
|
||||||
|
MsiRecordGetStringA(row,1,buf,&sz);
|
||||||
|
if (strcmp(buf,"InstallValidate")==0)
|
||||||
|
flipit=TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
progress +=25;
|
||||||
|
|
||||||
|
MsiCloseHandle(row);
|
||||||
|
}
|
||||||
|
MsiViewClose(view);
|
||||||
|
MsiCloseHandle(view);
|
||||||
|
|
||||||
|
rc = MsiDatabaseOpenViewA(db, q1, &view);
|
||||||
|
rc = MsiViewExecute(view, 0);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
rc = MsiViewFetch(view,&row);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
rc = ERROR_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
progress +=1;
|
||||||
|
|
||||||
|
MsiCloseHandle(row);
|
||||||
|
}
|
||||||
|
MsiViewClose(view);
|
||||||
|
MsiCloseHandle(view);
|
||||||
|
MsiCloseHandle(db);
|
||||||
|
|
||||||
|
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
|
||||||
|
progress_message(hPackage,0,progress+package->loaded_files,0,0);
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Msi functions that seem approperate here */
|
/* Msi functions that seem approperate here */
|
||||||
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
|
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,6 +145,9 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/prope
|
||||||
static VOID set_installer_properties(MSIHANDLE hPackage)
|
static VOID set_installer_properties(MSIHANDLE hPackage)
|
||||||
{
|
{
|
||||||
WCHAR pth[MAX_PATH];
|
WCHAR pth[MAX_PATH];
|
||||||
|
OSVERSIONINFOA OSVersion;
|
||||||
|
DWORD verval;
|
||||||
|
CHAR verstr[10];
|
||||||
|
|
||||||
static const WCHAR cszbs[]={'\\',0};
|
static const WCHAR cszbs[]={'\\',0};
|
||||||
static const WCHAR CFF[] =
|
static const WCHAR CFF[] =
|
||||||
|
@ -204,12 +207,6 @@ VirtualMemory
|
||||||
PhysicalMemory
|
PhysicalMemory
|
||||||
Intel
|
Intel
|
||||||
ShellAdvSupport
|
ShellAdvSupport
|
||||||
ServicePackLevel
|
|
||||||
WindowsBuild
|
|
||||||
Version9x
|
|
||||||
Version95
|
|
||||||
VersionNT
|
|
||||||
AdminUser
|
|
||||||
DefaultUIFont
|
DefaultUIFont
|
||||||
VersionMsi
|
VersionMsi
|
||||||
VersionDatabase
|
VersionDatabase
|
||||||
|
@ -268,6 +265,29 @@ Privilaged
|
||||||
|
|
||||||
GetTempPathW(MAX_PATH,pth);
|
GetTempPathW(MAX_PATH,pth);
|
||||||
MsiSetPropertyW(hPackage, TF, pth);
|
MsiSetPropertyW(hPackage, TF, pth);
|
||||||
|
|
||||||
|
/* in a wine enviroment the user is always admin and privlaged */
|
||||||
|
MsiSetPropertyA(hPackage,"AdminUser","1");
|
||||||
|
MsiSetPropertyA(hPackage,"Privileged","1");
|
||||||
|
|
||||||
|
/* set the os things */
|
||||||
|
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
||||||
|
GetVersionExA(&OSVersion);
|
||||||
|
verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
|
||||||
|
sprintf(verstr,"%li",verval);
|
||||||
|
switch (OSVersion.dwPlatformId)
|
||||||
|
{
|
||||||
|
case VER_PLATFORM_WIN32_WINDOWS:
|
||||||
|
MsiSetPropertyA(hPackage,"Version9X",verstr);
|
||||||
|
break;
|
||||||
|
case VER_PLATFORM_WIN32_NT:
|
||||||
|
MsiSetPropertyA(hPackage,"VersionNT",verstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sprintf(verstr,"%li",OSVersion.dwBuildNumber);
|
||||||
|
MsiSetPropertyA(hPackage,"WindowsBuild",verstr);
|
||||||
|
/* just fudge this */
|
||||||
|
MsiSetPropertyA(hPackage,"ServicePackLevel","6");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -377,6 +397,9 @@ INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
|
||||||
log_type |= INSTALLLOGMODE_ACTIONSTART;
|
log_type |= INSTALLLOGMODE_ACTIONSTART;
|
||||||
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
|
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
|
||||||
log_type |= INSTALLLOGMODE_ACTIONDATA;
|
log_type |= INSTALLLOGMODE_ACTIONDATA;
|
||||||
|
/* just a guess */
|
||||||
|
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
|
||||||
|
log_type |= 0x800;
|
||||||
|
|
||||||
message = HeapAlloc(GetProcessHeap(),0,1);
|
message = HeapAlloc(GetProcessHeap(),0,1);
|
||||||
message[0]=0;
|
message[0]=0;
|
||||||
|
@ -396,7 +419,7 @@ INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
|
||||||
|
|
||||||
if (msg_field > 1)
|
if (msg_field > 1)
|
||||||
{
|
{
|
||||||
sprintf(number,"%i: ",i);
|
sprintf(number," %i: ",i);
|
||||||
strcat(message,number);
|
strcat(message,number);
|
||||||
}
|
}
|
||||||
strcat(message,tmp);
|
strcat(message,tmp);
|
||||||
|
|
Loading…
Reference in New Issue