Start implementing Feature and Component level install control.

oldstable
Aric Stewart 2004-07-04 00:07:13 +00:00 committed by Alexandre Julliard
parent 1510cfc474
commit 36eee236ea
1 changed files with 253 additions and 10 deletions

View File

@ -132,6 +132,49 @@ UINT ACTION_DoTopLevelINSTALL(MSIHANDLE hPackage, LPCWSTR szPackagePath,
MsiSetPropertyW(hPackage, cszSourceDir, pth);
}
if (szCommandLine)
{
LPWSTR ptr,ptr2;
ptr = (LPWSTR)szCommandLine;
while (*ptr)
{
BOOL quote=FALSE;
WCHAR prop[0x100];
WCHAR val[0x100];
ptr2 = strchrW(ptr,'=');
if (ptr2)
{
DWORD len = 0;
strncpyW(prop,ptr,ptr2-ptr);
prop[ptr2-ptr]=0;
ptr2++;
ptr = ptr2;
while (*ptr && (!quote && *ptr!=' '))
{
if (*ptr == '"')
quote = !quote;
ptr++;
len++;
}
if (*ptr2=='"')
{
ptr2++;
len -= 2;
}
strncpyW(val,ptr2,len);
val[len]=0;
if (*ptr)
ptr++;
}
MsiSetPropertyW(hPackage,prop,val);
}
}
db = MsiGetActiveDatabase(hPackage);
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
MsiCloseHandle(db);
@ -514,6 +557,12 @@ static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
return ERROR_SUCCESS;
}
if (!strchrW(tmp_file,'.'))
{
static const WCHAR dot[]={'.',0};
strcatW(tmp_file,dot);
}
DLL = LoadLibraryW(tmp_file);
if (DLL)
{
@ -633,7 +682,7 @@ sizeof(WCHAR));
*/
static UINT ACTION_CreateFolders(MSIHANDLE hPackage)
{
static const CHAR *ExecSeqQuery = "select * from CreateFolder";
static const CHAR *ExecSeqQuery = "select Directory_ from CreateFolder";
UINT rc;
MSIHANDLE view;
MSIHANDLE db;
@ -865,12 +914,136 @@ static UINT resolve_directory(MSIHANDLE hPackage, const WCHAR* dir,
}
/*
* This is the action where all the features and components are loaded into
* memory... so when we start doing that that will be important.
*
* I am not doing any of the costing functionality yet.
* Mostly looking at doing the Component and Feature loading
*
* The native MSI does ALOT of modification to tables here. Mostly adding alot
* of temporary columns to the Feature and Component tables.
* Unfortinatly i cannot add temporary columns yet, nor can i really figure
* out what all the colums are for. So i am going to attack this another way
* and make some temporary tables to hold the data i think i need.
*
* WINE_Feature
* Feature Identifier : key into the Feature table
* Enabled Int : 1 if being installed, 0 if not
*/
static UINT ACTION_CostInitialize(MSIHANDLE hPackage)
{
MSIHANDLE db;
MSIHANDLE view;
MSIHANDLE row;
CHAR local[0x100];
WCHAR buffer[0x100];
DWORD sz;
static const CHAR CreateSql[] = "CREATE TABLE `WINE_Feature` ( `Feature`"
"CHAR(56) NOT NULL, `Enabled` INT NOT NULL PRIMARY KEY `Feature`)";
static const CHAR Insert[] =
"INSERT into `WINE_Feature` (`Feature`, `Enabled`) VALUES (?)";
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);
db = MsiGetActiveDatabase(hPackage);
MsiDatabaseOpenViewA(db,CreateSql,&view);
MsiViewExecute(view,0);
MsiViewClose(view);
MsiCloseHandle(view);
sz = 0x100;
if (MsiGetPropertyA(hPackage,"ADDLOCAL",local,&sz)==ERROR_SUCCESS)
{
if (strcasecmp(local,"ALL")==0)
{
MsiDatabaseOpenViewA(db,Query_all,&view);
MsiViewExecute(view,0);
while (1)
{
MSIHANDLE view2;
MSIHANDLE row2;
DWORD rc;
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
break;
row2 = MsiCreateRecord(2);
sz=0x100;
MsiRecordGetStringW(row,1,buffer,&sz);
MsiRecordSetStringW(row2,1,buffer);
MsiRecordSetInteger(row2,2,1);
MsiDatabaseOpenViewA(db,Insert,&view2);
MsiViewExecute(view2,row2);
MsiCloseHandle(row2);
MsiCloseHandle(row);
MsiViewClose(view2);
MsiCloseHandle(view2);
TRACE("Enabling feature %s\n",debugstr_w(buffer));
}
MsiViewClose(view);
MsiCloseHandle(view);
}
else
{
LPSTR ptr,ptr2;
ptr = local;
while (ptr && *ptr)
{
CHAR feature[0x100];
MSIHANDLE view2;
MSIHANDLE row2;
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(db,Query,&view);
MsiViewExecute(view,0);
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
break;
row2 = MsiCreateRecord(2);
sz=0x100;
MsiRecordGetStringW(row,1,buffer,&sz);
MsiRecordSetStringW(row2,1,buffer);
MsiRecordSetInteger(row2,2,1);
MsiDatabaseOpenViewA(db,Insert,&view2);
MsiViewExecute(view,row2);
MsiCloseHandle(row2);
MsiCloseHandle(row);
MsiViewClose(view2);
MsiCloseHandle(view2);
MsiViewClose(view);
MsiCloseHandle(view);
TRACE("Enabling feature %s\n",feature);
}
}
}
MsiCloseHandle(db);
return ERROR_SUCCESS;
}
@ -879,9 +1052,12 @@ static UINT ACTION_CostInitialize(MSIHANDLE hPackage)
* The costing needs to be implemented at some point but for now i am going
* to focus on the directory building
*
* Note about directory names: I know that directory names get processed into
* properties. I am still very unclear where the name_source
* part is used but I am preserving it just as a precaution
* WINE_Directory
* Directory Identifier: key into the Directory Table
* Source Path : resolved source path without SourceDir
* Target Path : resolved target path wihout TARGETDIR
* Created Int : 0 uncreated, 1 created but if empty remove, 2 created
*
*/
static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
{
@ -990,26 +1166,74 @@ end:
*
* Extract a file from a .cab file.
*/
static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root)
static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
static BOOL extract_cabinet_file_advpack( const WCHAR *cabinet,
const WCHAR *root)
{
static const WCHAR extW[] = {'.','c','a','b',0};
static HMODULE advpack;
char *cab_path, *cab_file;
int len = strlenW( cabinet );
/* make sure the cabinet file has a .cab extension */
if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
if (!pExtractFiles)
{
if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
{
ERR( "could not load advpack.dll\n" );
return FALSE;
}
if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles"
)))
{
ERR( "could not find ExtractFiles in advpack.dll\n" );
return FALSE;
}
}
if (!(cab_file = strdupWtoA( cabinet ))) return FALSE;
if (!(cab_path = strdupWtoA( root ))) return FALSE;
FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
HeapFree( GetProcessHeap(), 0, cab_file );
HeapFree( GetProcessHeap(), 0, cab_path );
return TRUE;
}
static BOOL extract_cabinet_file_cabinet( const WCHAR *cabinet,
const WCHAR *root)
{
static const WCHAR extW[] = {'.','c','a','b',0};
/* from cabinet.h */
struct ExtractFileList {
LPSTR filename;
struct ExtractFileList *next;
BOOL unknown; /* always 1L */
} ;
typedef struct {
long result1; /* 0x000 */
long unknown1[3]; /* 0x004 */
void* filelist; /* 0x010 */
struct ExtractFileList* filelist; /* 0x010 */
long filecount; /* 0x014 */
long unknown2; /* 0x018 */
char directory[0x104]; /* 0x01c */
char lastfile[0x20c]; /* 0x120 */
} EXTRACTdest;
extern HRESULT WINAPI Extract(EXTRACTdest*, LPCSTR);
HRESULT WINAPI Extract(EXTRACTdest *dest, LPCSTR what);
char *cab_path, *src_path;
int len = strlenW( cabinet );
EXTRACTdest exd;
struct ExtractFileList fl;
/* make sure the cabinet file has a .cab extension */
if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
@ -1019,12 +1243,27 @@ static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root)
memset(&exd,0,sizeof(exd));
strcpy(exd.directory,src_path);
exd.unknown2 = 0x1;
fl.filename = cab_path;
fl.next = NULL;
fl.unknown = 1;
exd.filelist = &fl;
FIXME( "awfuler hack: extracting cabinet %s\n", debugstr_a(cab_path) );
Extract(&exd,cab_path);
HeapFree( GetProcessHeap(), 0, cab_path );
HeapFree( GetProcessHeap(), 0, src_path );
return TRUE;
}
static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path)
{
if (!extract_cabinet_file_advpack(source,path))
return extract_cabinet_file_cabinet(source,path);
return TRUE;
}
static UINT ready_media_for_file(MSIHANDLE hPackage, UINT sequence,
WCHAR* path)
{
@ -1263,6 +1502,10 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
break;
}
reduce_to_longfilename(filename);
/* create the path */
create_full_pathW(install_path);
strcatW(install_path,filename);
TRACE("Installing file %s to %s\n",debugstr_w(src_path),