Beginnings of costing and organizing into components and features.

This commit is contained in:
Aric Stewart 2004-07-04 00:35:52 +00:00 committed by Alexandre Julliard
parent e2d4ea8141
commit ec688fb4e0
5 changed files with 394 additions and 244 deletions

View File

@ -3,7 +3,7 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = msi.dll
IMPORTS = shell32 cabinet ole32 user32 advapi32 kernel32
IMPORTS = shell32 cabinet oleaut32 ole32 version user32 advapi32 kernel32
EXTRALIBS = -luuid $(LIBUNICODE)
C_SRCS = \

View File

@ -24,7 +24,6 @@
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/installexecutesequence_table.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/standard_actions_reference.asp
*/
#include <stdarg.h>
@ -44,6 +43,7 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/stand
#include "winuser.h"
#include "shlobj.h"
#include "wine/unicode.h"
#include "ver.h"
#define CUSTOM_ACTION_TYPE_MASK 0x3F
@ -62,7 +62,8 @@ typedef struct tagMSIFEATURE
INSTALLSTATE State;
INT ComponentCount;
INT Components[1024]; /* yes hardcoded limit.... */
INT Components[1024]; /* yes hardcoded limit.... I am bad */
INT Cost;
} MSIFEATURE;
typedef struct tagMSICOMPONENT
@ -76,6 +77,7 @@ typedef struct tagMSICOMPONENT
INSTALLSTATE State;
BOOL Enabled;
INT Cost;
}MSICOMPONENT;
typedef struct tagMSIFOLDER
@ -93,8 +95,32 @@ typedef struct tagMSIFOLDER
/* 1 = existing */
/* 2 = created remove if empty */
/* 3 = created persist if empty */
INT Cost;
INT Space;
}MSIFOLDER;
typedef struct tagMSIFILE
{
WCHAR File[72];
INT ComponentIndex;
WCHAR FileName[MAX_PATH];
INT FileSize;
WCHAR Version[72];
WCHAR Language[20];
INT Attributes;
INT Sequence;
INT State;
/* 0 = uninitialize */
/* 1 = not present */
/* 2 = present but replace */
/* 3 = present do not replace */
/* 4 = Installed */
WCHAR SourcePath[MAX_PATH];
WCHAR TargetPath[MAX_PATH];
BOOL Temporary;
}MSIFILE;
/*
* Prototypes
*/
@ -105,6 +131,7 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action);
static UINT ACTION_CostInitialize(MSIHANDLE hPackage);
static UINT ACTION_CreateFolders(MSIHANDLE hPackage);
static UINT ACTION_CostFinalize(MSIHANDLE hPackage);
static UINT ACTION_FileCost(MSIHANDLE hPackage);
static UINT ACTION_InstallFiles(MSIHANDLE hPackage);
static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage);
static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage);
@ -119,7 +146,8 @@ static DWORD deformat_string(MSIHANDLE hPackage, WCHAR* ptr,WCHAR** data);
static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
BOOL source, BOOL set_prop, MSIFOLDER **folder);
static UINT track_tempfile(MSIHANDLE hPackage, LPCWSTR name, LPCWSTR path);
/*
* consts and values used
*/
@ -138,6 +166,16 @@ static const WCHAR cszbs[]={'\\',0};
/********************************************************
* helper functions to get around current HACKS and such
********************************************************/
inline static void reduce_to_longfilename(WCHAR* filename)
{
if (strchrW(filename,'|'))
{
WCHAR newname[MAX_PATH];
strcpyW(newname,strchrW(filename,'|')+1);
strcpyW(filename,newname);
}
}
inline static char *strdupWtoA( const WCHAR *str )
{
char *ret = NULL;
@ -151,7 +189,7 @@ inline static char *strdupWtoA( const WCHAR *str )
return ret;
}
int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
{
INT rc = -1;
INT i;
@ -167,6 +205,55 @@ int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
return rc;
}
static UINT track_tempfile(MSIHANDLE hPackage, LPCWSTR name, LPCWSTR path)
{
MSIPACKAGE *package;
int i;
int index;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return -2;
for (i=0; i < package->loaded_files; i++)
if (strcmpW(package->files[i].File,name)==0)
return -1;
index = package->loaded_files;
package->loaded_files++;
if (package->loaded_files== 1)
package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
else
package->files = HeapReAlloc(GetProcessHeap(),0,
package->files , package->loaded_files * sizeof(MSIFILE));
memset(&package->files[index],0,sizeof(MSIFILE));
strcpyW(package->files[index].File,name);
strcpyW(package->files[index].TargetPath,path);
package->files[index].Temporary = TRUE;
TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File));
return 0;
}
void ACTION_remove_tracked_tempfiles(MSIPACKAGE* package)
{
int i;
if (!package)
return;
for (i = 0; i < package->loaded_files; i++)
{
if (package->files[i].Temporary)
DeleteFileW(package->files[i].TargetPath);
}
}
/****************************************************
* TOP level entry points
*****************************************************/
@ -487,15 +574,19 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
{'W','r','i','t','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0};
const static WCHAR szCostInitialize[] =
{'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
const static WCHAR szFileCost[] =
{'F','i','l','e','C','o','s','t',0};
TRACE("Performing action (%s)\n",debugstr_w(action));
if (strcmpW(action,szCostInitialize)==0)
return ACTION_CostInitialize(hPackage);
if (strcmpW(action,szCreateFolders)==0)
return ACTION_CreateFolders(hPackage);
if (strcmpW(action,szFileCost)==0)
return ACTION_FileCost(hPackage);
if (strcmpW(action,szCostFinalize)==0)
return ACTION_CostFinalize(hPackage);
if (strcmpW(action,szCreateFolders)==0)
return ACTION_CreateFolders(hPackage);
if (strcmpW(action,szInstallFiles)==0)
return ACTION_InstallFiles(hPackage);
if (strcmpW(action,szDuplicateFiles)==0)
@ -567,7 +658,7 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
.
*/
if (ACTION_CustomAction(hPackage,action) != ERROR_SUCCESS)
ERR("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
return ERROR_SUCCESS;
}
@ -642,7 +733,7 @@ static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action)
HeapFree(GetProcessHeap(),0,deformated);
break;
default:
ERR("UNHANDLED ACTION TYPE %i (%s %s)\n",
FIXME("UNHANDLED ACTION TYPE %i (%s %s)\n",
type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source),
debugstr_w(target));
}
@ -683,6 +774,9 @@ static UINT store_binary_to_temp(MSIHANDLE hPackage, const LPWSTR source,
CHAR buffer[1024];
MSIHANDLE db;
if (track_tempfile(hPackage, source, tmp_file)!=0)
FIXME("File Name in temp tracking collision\n");
the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
@ -758,7 +852,7 @@ static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
if (type & 0xc0)
{
ERR("Asynchronous execution.. UNHANDLED\n");
FIXME("Asynchronous execution.. UNHANDLED\n");
return ERROR_SUCCESS;
}
@ -943,6 +1037,7 @@ static UINT ACTION_CreateFolders(MSIHANDLE hPackage)
}
TRACE("Folder is %s\n",debugstr_w(full_path));
if (folder->State == 0)
create_full_pathW(full_path);
@ -956,7 +1051,6 @@ static UINT ACTION_CreateFolders(MSIHANDLE hPackage)
return rc;
}
static int load_component(MSIPACKAGE* package, MSIHANDLE row)
{
int index = package->loaded_components;
@ -1131,13 +1225,10 @@ static UINT ACTION_CostInitialize(MSIHANDLE hPackage)
{
MSIHANDLE view;
MSIHANDLE row;
CHAR local[0x100];
DWORD sz;
MSIPACKAGE *package;
static const CHAR Query_all[] = "SELECT * FROM Feature";
static const CHAR Query_one[] = "SELECT * FROM Feature WHERE Feature='%s'";
CHAR Query[1023];
MsiSetPropertyA(hPackage,"CostingComplete","0");
MsiSetPropertyW(hPackage, cszRootDrive , c_collen);
@ -1145,67 +1236,124 @@ static UINT ACTION_CostInitialize(MSIHANDLE hPackage)
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
sz = 0x100;
if (MsiGetPropertyA(hPackage,"ADDLOCAL",local,&sz)==ERROR_SUCCESS)
MsiDatabaseOpenViewA(package->db,Query_all,&view);
MsiViewExecute(view,0);
while (1)
{
if (strcasecmp(local,"ALL")==0)
{
MsiDatabaseOpenViewA(package->db,Query_all,&view);
MsiViewExecute(view,0);
while (1)
{
DWORD rc;
DWORD rc;
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
break;
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
break;
load_feature(package,row);
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
}
else
{
LPSTR ptr,ptr2;
ptr = local;
while (ptr && *ptr)
{
CHAR feature[0x100];
DWORD rc;
ptr2 = strchr(ptr,',');
if (ptr2)
{
strncpy(feature,ptr,ptr2-ptr);
feature[ptr2-ptr]=0;
ptr2++;
ptr = ptr2;
}
else
{
strcpy(feature,ptr);
ptr = NULL;
}
sprintf(Query,Query_one,feature);
MsiDatabaseOpenViewA(package->db,Query,&view);
MsiViewExecute(view,0);
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
break;
load_feature(package,row);
MsiCloseHandle(row);
MsiViewClose(view);
MsiCloseHandle(view);
}
}
load_feature(package,row);
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
return ERROR_SUCCESS;
}
static int load_file(MSIPACKAGE* package, MSIHANDLE row)
{
int index = package->loaded_files;
int i;
WCHAR buffer[0x100];
DWORD sz;
/* fill in the data */
package->loaded_files++;
if (package->loaded_files== 1)
package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
else
package->files = HeapReAlloc(GetProcessHeap(),0,
package->files , package->loaded_files * sizeof(MSIFILE));
memset(&package->files[index],0,sizeof(MSIFILE));
sz = 72;
MsiRecordGetStringW(row,1,package->files[index].File,&sz);
sz = 0x100;
MsiRecordGetStringW(row,2,buffer,&sz);
package->files[index].ComponentIndex = -1;
for (i = 0; i < package->loaded_components; i++)
if (strcmpW(package->components[i].Component,buffer)==0)
{
package->files[index].ComponentIndex = i;
break;
}
if (package->files[index].ComponentIndex == -1)
ERR("Unfound Component %s\n",debugstr_w(buffer));
sz = MAX_PATH;
MsiRecordGetStringW(row,3,package->files[index].FileName,&sz);
reduce_to_longfilename(package->files[index].FileName);
package->files[index].FileSize = MsiRecordGetInteger(row,4);
sz = 72;
if (!MsiRecordIsNull(row,5))
MsiRecordGetStringW(row,5,package->files[index].Version,&sz);
sz = 20;
if (!MsiRecordIsNull(row,6))
MsiRecordGetStringW(row,6,package->files[index].Language,&sz);
if (!MsiRecordIsNull(row,7))
package->files[index].Attributes= MsiRecordGetInteger(row,7);
package->files[index].Sequence= MsiRecordGetInteger(row,8);
package->files[index].Temporary = FALSE;
package->files[index].State = 0;
TRACE("File Loaded (%s)\n",debugstr_w(package->files[index].File));
return ERROR_SUCCESS;
}
static UINT ACTION_FileCost(MSIHANDLE hPackage)
{
MSIHANDLE view;
MSIHANDLE row;
MSIPACKAGE *package;
UINT rc;
static const CHAR Query[] = "SELECT * FROM File Order by Sequence";
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
rc = MsiDatabaseOpenViewA(package->db, Query, &view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
while (1)
{
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
rc = ERROR_SUCCESS;
break;
}
load_file(package,row);
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
return ERROR_SUCCESS;
}
@ -1370,6 +1518,22 @@ static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
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)
return rc;
/* special resolving for Target and Source root dir */
if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
{
@ -1379,6 +1543,7 @@ static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
rc = MsiGetPropertyW(hPackage,cszTargetDir,path,&sz);
if (rc != ERROR_SUCCESS)
{
sz = MAX_PATH;
rc = MsiGetPropertyW(hPackage,cszRootDrive,path,&sz);
if (set_prop)
MsiSetPropertyW(hPackage,cszTargetDir,path);
@ -1406,19 +1571,6 @@ static UINT resolve_folder(MSIHANDLE hPackage, LPCWSTR name, LPWSTR path,
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])
{
@ -1479,13 +1631,13 @@ static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
static const CHAR *ExecSeqQuery = "select * from Directory";
UINT rc;
MSIHANDLE view;
MSIHANDLE db;
MSIPACKAGE *package;
INT i;
TRACE("Building Directory properties\n");
db = MsiGetActiveDatabase(hPackage);
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
MsiCloseHandle(db);
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
return rc;
@ -1527,6 +1679,69 @@ static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
MsiViewClose(view);
MsiCloseHandle(view);
TRACE("File calculations %i files\n",package->loaded_files);
for (i = 0; i < package->loaded_files; i++)
{
MSICOMPONENT* comp = NULL;
MSIFILE* file= NULL;
file = &package->files[i];
if (file->ComponentIndex >= 0)
comp = &package->components[file->ComponentIndex];
if (comp)
{
/* calculate target */
resolve_folder(hPackage, comp->Directory, file->TargetPath, FALSE,
FALSE, NULL);
strcatW(file->TargetPath,file->FileName);
TRACE("file %s resolves to %s\n",
debugstr_w(file->File),debugstr_w(file->TargetPath));
if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
{
file->State = 1;
comp->Cost += file->FileSize;
}
else
{
if (file->Version[0])
{
DWORD handle;
DWORD versize;
UINT sz;
LPVOID version;
WCHAR filever[0x100];
static const WCHAR name[] =
{'\\','V','a','r','F','i','l','e','I','n','f','o',
'\\','F','i','l','e','V','e','r','s','i','o','n',0};
FIXME("Version comparison.. Untried Untested and most "
"likely very very wrong\n");
versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
version = HeapAlloc(GetProcessHeap(),0,versize);
GetFileVersionInfoW(file->TargetPath, 0, versize, version);
sz = 0x100;
VerQueryValueW(version,name,(LPVOID)filever,&sz);
HeapFree(GetProcessHeap(),0,version);
if (strcmpW(version,file->Version)<0)
{
file->State = 2;
FIXME("cost should be diff in size\n");
comp->Cost += file->FileSize;
}
else
file->State = 3;
}
else
file->State = 3;
}
}
}
MsiSetPropertyA(hPackage,"CostingComplete","1");
return ERROR_SUCCESS;
@ -1559,6 +1774,7 @@ static UINT writeout_cabinet_stream(MSIHANDLE hPackage, WCHAR* stream_name,
GetTempFileNameW(tmp,stream_name,0,source);
track_tempfile(hPackage,strrchrW(source,'\\'), source);
the_file = CreateFileW(source, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
@ -1662,7 +1878,6 @@ static BOOL extract_cabinet_file_cabinet( const WCHAR *cabinet,
return TRUE;
}
static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path)
{
TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path));
@ -1759,67 +1974,18 @@ static UINT ready_media_for_file(MSIHANDLE hPackage, UINT sequence,
return rc;
}
static void reduce_to_longfilename(WCHAR* filename)
{
if (strchrW(filename,'|'))
{
WCHAR newname[MAX_PATH];
strcpyW(newname,strchrW(filename,'|')+1);
strcpyW(filename,newname);
}
}
static UINT get_directory_for_component(MSIHANDLE hPackage,
const WCHAR* component, WCHAR* install_path)
inline static UINT create_component_directory (MSIHANDLE hPackage, MSIPACKAGE*
package, INT component)
{
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
WCHAR ExecSeqQuery[1023] =
{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','o','m'
,'p','o','n','e','n','t',' ','w','h','e','r','e',' ','C','o','m'
,'p','o','n','e','n','t',' ','=',' ','`',0};
static const WCHAR end[]={'`',0};
WCHAR dir[0x100];
DWORD sz=0x100;
MSIHANDLE db;
MSIFOLDER *folder;
WCHAR install_path[MAX_PATH];
strcatW(ExecSeqQuery,component);
strcatW(ExecSeqQuery,end);
db = MsiGetActiveDatabase(hPackage);
rc = MsiDatabaseOpenViewW(db, ExecSeqQuery, &view);
MsiCloseHandle(db);
rc = resolve_folder(hPackage, package->components[component].Directory,
install_path, FALSE, FALSE, &folder);
if (rc != ERROR_SUCCESS)
return rc;
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
MsiCloseHandle(row);
return rc;
}
sz=0x100;
MsiRecordGetStringW(row,3,dir,&sz);
sz=MAX_PATH;
rc = resolve_folder(hPackage, dir, install_path, FALSE, FALSE, &folder);
MsiCloseHandle(row);
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
/* create the path */
if (folder->State == 0)
@ -1833,12 +1999,9 @@ static UINT get_directory_for_component(MSIHANDLE hPackage,
static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
{
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
static const CHAR *ExecSeqQuery =
"select * from File order by Sequence";
MSIHANDLE db;
UINT rc = ERROR_SUCCESS;
INT index;
MSIPACKAGE *package;
/* REALLY what we want to do is go through all the enabled
* features and check all the components of that feature and
@ -1847,107 +2010,78 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
* but for sheer gratification I am going to just brute force
* install all the files
*/
db = MsiGetActiveDatabase(hPackage);
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
MsiCloseHandle(db);
if (rc != ERROR_SUCCESS)
return rc;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
if (!package)
return ERROR_INVALID_HANDLE;
for (index = 0; index < package->loaded_files; index++)
{
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
while (1)
{
INT seq = 0;
WCHAR component[0x100];
WCHAR install_path[MAX_PATH];
WCHAR path_to_source[MAX_PATH];
WCHAR src_path[MAX_PATH];
WCHAR filename[0x100];
WCHAR sourcename[0x100];
DWORD sz=0x100;
MSIFILE *file;
file = &package->files[index];
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
if ((file->State == 1) || (file->State == 2))
{
rc = ERROR_SUCCESS;
break;
TRACE("Installing %s\n",debugstr_w(file->File));
rc = ready_media_for_file(hPackage,file->Sequence,path_to_source);
/*
* WARNING!
* our file table could change here because a new temp file
* may have been created
*/
file = &package->files[index];
if (rc != ERROR_SUCCESS)
{
ERR("Unable to ready media\n");
rc = ERROR_FUNCTION_FAILED;
break;
}
create_component_directory(hPackage, package, file->ComponentIndex);
strcpyW(file->SourcePath, path_to_source);
strcatW(file->SourcePath, file->File);
TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
debugstr_w(file->TargetPath));
rc = !MoveFileW(file->SourcePath,file->TargetPath);
if (rc)
ERR("Unable to move file\n");
else
file->State = 4;
}
seq = MsiRecordGetInteger(row,8);
rc = ready_media_for_file(hPackage,seq,path_to_source);
if (rc != ERROR_SUCCESS)
{
ERR("Unable to ready media\n");
MsiCloseHandle(row);
break;
}
sz=0x100;
rc = MsiRecordGetStringW(row,2,component,&sz);
if (rc != ERROR_SUCCESS)
{
ERR("Unable to read component\n");
MsiCloseHandle(row);
break;
}
rc = get_directory_for_component(hPackage,component,install_path);
if (rc != ERROR_SUCCESS)
{
ERR("Unable to get directory\n");
MsiCloseHandle(row);
break;
}
sz=0x100;
rc = MsiRecordGetStringW(row,1,sourcename,&sz);
if (rc != ERROR_SUCCESS)
{
ERR("Unable to get sourcename\n");
MsiCloseHandle(row);
break;
}
strcpyW(src_path,path_to_source);
strcatW(src_path,sourcename);
sz=0x100;
rc = MsiRecordGetStringW(row,3,filename,&sz);
if (rc != ERROR_SUCCESS)
{
ERR("Unable to get filename\n");
MsiCloseHandle(row);
break;
}
reduce_to_longfilename(filename);
strcatW(install_path,filename);
TRACE("Installing file %s to %s\n",debugstr_w(src_path),
debugstr_w(install_path));
rc = !MoveFileW(src_path,install_path);
if (rc)
{
ERR("Unable to move file\n");
}
/* for future use lets keep track of this file and where it went */
MsiSetPropertyW(hPackage,sourcename,install_path);
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
inline static UINT get_file_target(MSIHANDLE hPackage, LPCWSTR file_key,
LPWSTR file_source)
{
MSIPACKAGE *package;
INT index;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
for (index = 0; index < package->loaded_files; index ++)
{
if (strcmpW(file_key,package->files[index].File)==0)
{
strcmpW(file_source,package->files[index].TargetPath);
return ERROR_SUCCESS;
}
}
return ERROR_FUNCTION_FAILED;
}
static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
{
UINT rc;
@ -2001,8 +2135,8 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
break;
}
sz = 0x100;
rc = MsiGetPropertyW(hPackage,file_key,file_source,&sz);
rc = get_file_target(hPackage,file_key,file_source);
if (rc != ERROR_SUCCESS)
{
ERR("Original file unknown %s\n",debugstr_w(file_key));
@ -2011,7 +2145,10 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
}
if (MsiRecordIsNull(row,4))
{
ERR("HERE target path %s\n",debugstr_w(file_source));
strcpyW(dest_name,strrchrW(file_source,'\\')+1);
}
else
{
sz=0x100;
@ -2030,7 +2167,7 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
sz=0x100;
MsiRecordGetStringW(row,5,destkey,&sz);
sz = 0x100;
rc = MsiGetPropertyW(hPackage, destkey, dest_path, &sz);
rc = resolve_folder(hPackage, destkey, dest_path,FALSE,FALSE,NULL);
if (rc != ERROR_SUCCESS)
{
ERR("Unable to get destination folder\n");
@ -2051,7 +2188,9 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
if (rc != ERROR_SUCCESS)
ERR("Failed to copy file\n");
FIXME("We should track these duplicate files as well\n");
MsiCloseHandle(row);
}
MsiViewClose(view);

View File

@ -573,7 +573,8 @@ static INT comp_ge_m2(INT a, LPWSTR b)
static int COND_IsAlpha( WCHAR x )
{
return( ( ( x >= 'A' ) && ( x <= 'Z' ) ) ||
( ( x >= 'a' ) && ( x <= 'z' ) ) );
( ( x >= 'a' ) && ( x <= 'z' ) ) ||
( ( x == '_' ) ) );
}
static int COND_IsNumber( WCHAR x )

View File

@ -149,6 +149,8 @@ typedef struct tagMSIPACKAGE
UINT loaded_folders;
struct tagMSICOMPONENT *components;
UINT loaded_components;
struct tagMSIFILE *files;
UINT loaded_files;
} MSIPACKAGE;
#define MSIHANDLETYPE_ANY 0
@ -220,6 +222,7 @@ UINT read_raw_stream_data( MSIHANDLE hdb, LPCWSTR stname,
USHORT **pdata, UINT *psz );
UINT ACTION_DoTopLevelINSTALL(MSIHANDLE hPackage, LPCWSTR szPackagePath,
LPCWSTR szCommandLine);
void ACTION_remove_tracked_tempfiles(MSIPACKAGE* hPackage);
/* record internals */
extern UINT WINAPI MSI_RecordSetIStream( MSIHANDLE handle,

View File

@ -56,6 +56,8 @@ void MSI_FreePackage( VOID *arg)
MsiCloseHandle(package->db);
ACTION_remove_tracked_tempfiles(package);
if (package->features && package->loaded_features > 0)
HeapFree(GetProcessHeap(),0,package->features);
@ -64,6 +66,9 @@ void MSI_FreePackage( VOID *arg)
if (package->components && package->loaded_components > 0)
HeapFree(GetProcessHeap(),0,package->components);
if (package->files && package->loaded_files > 0)
HeapFree(GetProcessHeap(),0,package->files);
}
UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
@ -299,9 +304,11 @@ UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
package->features = NULL;
package->folders = NULL;
package->components = NULL;
package->files = NULL;
package->loaded_features = 0;
package->loaded_folders = 0;
package->loaded_components= 0;
package->loaded_files = 0;
/* ok here is where we do a slew of things to the database to
* prep for all that is to come as a package */