Autosyncing with Wine HEAD

svn path=/trunk/; revision=24610
This commit is contained in:
The Wine Synchronizer 2006-10-22 20:23:59 +00:00
parent d8762edcd7
commit f332d881af
30 changed files with 1719 additions and 723 deletions

View file

@ -35,6 +35,7 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/stand
#include "winbase.h" #include "winbase.h"
#include "winerror.h" #include "winerror.h"
#include "winreg.h" #include "winreg.h"
#include "winsvc.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "msidefs.h" #include "msidefs.h"
#include "msipriv.h" #include "msipriv.h"
@ -42,7 +43,6 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/stand
#include "shlobj.h" #include "shlobj.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "winver.h" #include "winver.h"
#include "action.h"
#define REG_PROGRESS_VALUE 13200 #define REG_PROGRESS_VALUE 13200
#define COMPONENT_PROGRESS_VALUE 24000 #define COMPONENT_PROGRESS_VALUE 24000
@ -365,6 +365,7 @@ static UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine )
static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep ) static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep )
{ {
LPCWSTR pc;
LPWSTR p, *ret = NULL; LPWSTR p, *ret = NULL;
UINT count = 0; UINT count = 0;
@ -372,11 +373,11 @@ static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep )
return ret; return ret;
/* count the number of substrings */ /* count the number of substrings */
for ( p = (LPWSTR)str, count = 0; p; count++ ) for ( pc = str, count = 0; pc; count++ )
{ {
p = strchrW( p, sep ); pc = strchrW( pc, sep );
if (p) if (pc)
p++; pc++;
} }
/* allocate space for an array of substring pointers and the substrings */ /* allocate space for an array of substring pointers and the substrings */
@ -574,7 +575,6 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
{ {
LPWSTR p, check, path; LPWSTR p, check, path;
package->PackagePath = strdupW(szPackagePath);
path = strdupW(szPackagePath); path = strdupW(szPackagePath);
p = strrchrW(path,'\\'); p = strrchrW(path,'\\');
if (p) if (p)
@ -593,8 +593,15 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
check = msi_dup_property( package, cszSourceDir ); check = msi_dup_property( package, cszSourceDir );
if (!check) if (!check)
MSI_SetPropertyW(package, cszSourceDir, path); MSI_SetPropertyW(package, cszSourceDir, path);
check = msi_dup_property( package, cszSOURCEDIR );
if (!check)
MSI_SetPropertyW(package, cszSOURCEDIR, path);
msi_free( package->PackagePath );
package->PackagePath = path;
msi_free(check); msi_free(check);
msi_free(path);
} }
msi_parse_command_line( package, szCommandLine ); msi_parse_command_line( package, szCommandLine );
@ -1118,26 +1125,9 @@ static UINT load_component( MSIRECORD *row, LPVOID param )
comp->Condition = msi_dup_record_field( row, 5 ); comp->Condition = msi_dup_record_field( row, 5 );
comp->KeyPath = msi_dup_record_field( row, 6 ); comp->KeyPath = msi_dup_record_field( row, 6 );
comp->Installed = INSTALLSTATE_ABSENT; comp->Installed = INSTALLSTATE_UNKNOWN;
comp->Action = INSTALLSTATE_UNKNOWN;
switch (comp->Attributes) comp->ActionRequest = INSTALLSTATE_UNKNOWN;
{
case msidbComponentAttributesLocalOnly:
comp->Action = INSTALLSTATE_LOCAL;
comp->ActionRequest = INSTALLSTATE_LOCAL;
break;
case msidbComponentAttributesSourceOnly:
comp->Action = INSTALLSTATE_SOURCE;
comp->ActionRequest = INSTALLSTATE_SOURCE;
break;
case msidbComponentAttributesOptional:
comp->Action = INSTALLSTATE_DEFAULT;
comp->ActionRequest = INSTALLSTATE_DEFAULT;
break;
default:
comp->Action = INSTALLSTATE_LOCAL;
comp->ActionRequest = INSTALLSTATE_LOCAL;
}
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -1180,6 +1170,19 @@ static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT add_feature_child( MSIFEATURE *parent, MSIFEATURE *child )
{
FeatureList *fl;
fl = msi_alloc( sizeof(*fl) );
if ( !fl )
return ERROR_NOT_ENOUGH_MEMORY;
fl->feature = child;
list_add_tail( &parent->Children, &fl->entry );
return ERROR_SUCCESS;
}
static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param) static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
{ {
_ilfs* ilfs= (_ilfs*)param; _ilfs* ilfs= (_ilfs*)param;
@ -1202,6 +1205,19 @@ static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static MSIFEATURE *find_feature_by_name( MSIPACKAGE *package, LPCWSTR name )
{
MSIFEATURE *feature;
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
if ( !lstrcmpW( feature->Feature, name ) )
return feature;
}
return NULL;
}
static UINT load_feature(MSIRECORD * row, LPVOID param) static UINT load_feature(MSIRECORD * row, LPVOID param)
{ {
MSIPACKAGE* package = (MSIPACKAGE*)param; MSIPACKAGE* package = (MSIPACKAGE*)param;
@ -1223,6 +1239,7 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
if (!feature) if (!feature)
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
list_init( &feature->Children );
list_init( &feature->Components ); list_init( &feature->Components );
feature->Feature = msi_dup_record_field( row, 1 ); feature->Feature = msi_dup_record_field( row, 1 );
@ -1240,7 +1257,7 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
feature->Directory = msi_dup_record_field( row, 7 ); feature->Directory = msi_dup_record_field( row, 7 );
feature->Attributes = MSI_RecordGetInteger(row,8); feature->Attributes = MSI_RecordGetInteger(row,8);
feature->Installed = INSTALLSTATE_ABSENT; feature->Installed = INSTALLSTATE_UNKNOWN;
feature->Action = INSTALLSTATE_UNKNOWN; feature->Action = INSTALLSTATE_UNKNOWN;
feature->ActionRequest = INSTALLSTATE_UNKNOWN; feature->ActionRequest = INSTALLSTATE_UNKNOWN;
@ -1261,6 +1278,26 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT find_feature_children(MSIRECORD * row, LPVOID param)
{
MSIPACKAGE* package = (MSIPACKAGE*)param;
MSIFEATURE *parent, *child;
child = find_feature_by_name( package, MSI_RecordGetString( row, 1 ) );
if (!child)
return ERROR_FUNCTION_FAILED;
if (!child->Feature_Parent)
return ERROR_SUCCESS;
parent = find_feature_by_name( package, child->Feature_Parent );
if (!parent)
return ERROR_FUNCTION_FAILED;
add_feature_child( parent, child );
return ERROR_SUCCESS;
}
static UINT load_all_features( MSIPACKAGE *package ) static UINT load_all_features( MSIPACKAGE *package )
{ {
static const WCHAR query[] = { static const WCHAR query[] = {
@ -1278,7 +1315,12 @@ static UINT load_all_features( MSIPACKAGE *package )
return r; return r;
r = MSI_IterateRecords( view, NULL, load_feature, package ); r = MSI_IterateRecords( view, NULL, load_feature, package );
if (r != ERROR_SUCCESS)
return r;
r = MSI_IterateRecords( view, NULL, find_feature_children, package );
msiobj_release( &view->hdr ); msiobj_release( &view->hdr );
return r; return r;
} }
@ -1343,13 +1385,6 @@ static UINT load_file(MSIRECORD *row, LPVOID param)
file->IsCompressed = package->WordCount & MSIWORDCOUNT_COMPRESSED; file->IsCompressed = package->WordCount & MSIWORDCOUNT_COMPRESSED;
} }
if (file->IsCompressed)
{
file->Component->ForceLocalState = TRUE;
file->Component->Action = INSTALLSTATE_LOCAL;
file->Component->ActionRequest = INSTALLSTATE_LOCAL;
}
TRACE("File Loaded (%s)\n",debugstr_w(file->File)); TRACE("File Loaded (%s)\n",debugstr_w(file->File));
list_add_tail( &package->files, &file->entry ); list_add_tail( &package->files, &file->entry );
@ -1546,9 +1581,16 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
MSICOMPONENT *comp; MSICOMPONENT *comp;
MSIFEATURE *feature; MSIFEATURE *feature;
/* FIXME: component's installed state should be determined
* by the component's registration
*/
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry ) LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{ {
INSTALLSTATE res; INSTALLSTATE res;
if (!comp->ComponentId)
continue;
res = MsiGetComponentPathW( package->ProductCode, res = MsiGetComponentPathW( package->ProductCode,
comp->ComponentId, NULL, NULL); comp->ComponentId, NULL, NULL);
if (res < 0) if (res < 0)
@ -1559,23 +1601,32 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
ComponentList *cl; ComponentList *cl;
INSTALLSTATE res = -10; INSTALLSTATE res = INSTALLSTATE_ABSENT;
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry ) LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{ {
comp= cl->component; comp= cl->component;
if (res == -10) if (!comp->ComponentId)
{
res = INSTALLSTATE_ABSENT;
break;
}
if (res == INSTALLSTATE_ABSENT)
res = comp->Installed; res = comp->Installed;
else else
{ {
if (res == comp->Installed) if (res == comp->Installed)
continue; continue;
if (res != comp->Installed) if (res != INSTALLSTATE_DEFAULT || res != INSTALLSTATE_LOCAL ||
res != INSTALLSTATE_SOURCE)
{
res = INSTALLSTATE_INCOMPLETE; res = INSTALLSTATE_INCOMPLETE;
} }
} }
}
feature->Installed = res; feature->Installed = res;
} }
} }
@ -1649,7 +1700,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
install_level = msi_get_property_int( package, szlevel, 1 ); install_level = msi_get_property_int( package, szlevel, 1 );
/* ok hereis the _real_ rub /* ok here is the _real_ rub
* all these activation/deactivation things happen in order and things * all these activation/deactivation things happen in order and things
* later on the list override things earlier on the list. * later on the list override things earlier on the list.
* 1) INSTALLLEVEL processing * 1) INSTALLLEVEL processing
@ -1701,6 +1752,21 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
} }
} }
} }
/* disable child features of unselected parent features */
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
FeatureList *fl;
if (feature->Level > 0 && feature->Level <= install_level)
continue;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
{
fl->feature->ActionRequest = INSTALLSTATE_UNKNOWN;
fl->feature->Action = INSTALLSTATE_UNKNOWN;
}
}
} }
else else
{ {
@ -1727,6 +1793,31 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{ {
component = cl->component; component = cl->component;
switch (component->Attributes)
{
case msidbComponentAttributesLocalOnly:
component->Action = INSTALLSTATE_LOCAL;
component->ActionRequest = INSTALLSTATE_LOCAL;
break;
case msidbComponentAttributesSourceOnly:
component->Action = INSTALLSTATE_SOURCE;
component->ActionRequest = INSTALLSTATE_SOURCE;
break;
case msidbComponentAttributesOptional:
component->Action = INSTALLSTATE_DEFAULT;
component->ActionRequest = INSTALLSTATE_DEFAULT;
break;
default:
component->Action = INSTALLSTATE_LOCAL;
component->ActionRequest = INSTALLSTATE_LOCAL;
}
if (component->ForceLocalState)
{
component->Action = INSTALLSTATE_LOCAL;
component->ActionRequest = INSTALLSTATE_LOCAL;
}
if (!component->Enabled) if (!component->Enabled)
{ {
component->Action = INSTALLSTATE_UNKNOWN; component->Action = INSTALLSTATE_UNKNOWN;
@ -1772,9 +1863,14 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
component->ActionRequest = INSTALLSTATE_ABSENT; component->ActionRequest = INSTALLSTATE_ABSENT;
} }
} }
else if (feature->ActionRequest == INSTALLSTATE_UNKNOWN)
{
component->Action = INSTALLSTATE_UNKNOWN;
component->ActionRequest = INSTALLSTATE_UNKNOWN;
}
} }
if (component->ForceLocalState) if (component->ForceLocalState && feature->Action == INSTALLSTATE_SOURCE)
{ {
feature->Action = INSTALLSTATE_LOCAL; feature->Action = INSTALLSTATE_LOCAL;
feature->ActionRequest = INSTALLSTATE_LOCAL; feature->ActionRequest = INSTALLSTATE_LOCAL;
@ -1837,7 +1933,6 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
/* /*
* A lot is done in this function aside from just the costing. * A lot is done in this function aside from just the costing.
* 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
@ -1886,6 +1981,9 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
if (!comp) if (!comp)
continue; continue;
if (file->IsCompressed)
comp->ForceLocalState = TRUE;
/* calculate target */ /* calculate target */
p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL); p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
@ -2037,7 +2135,7 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
} }
msi_free(deformated); msi_free(deformated);
TRACE("Data %li bytes(%i)\n",*size,count); TRACE("Data %i bytes(%i)\n",*size,count);
} }
else else
{ {
@ -2063,7 +2161,7 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
if (deformated[0] == '-') if (deformated[0] == '-')
d = -d; d = -d;
*(LPDWORD)data = d; *(LPDWORD)data = d;
TRACE("DWORD %li\n",*(LPDWORD)data); TRACE("DWORD %i\n",*(LPDWORD)data);
msi_free(deformated); msi_free(deformated);
} }
@ -3540,7 +3638,7 @@ static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey )
if (!r) if (!r)
{ {
ERR("Unable to copy package (%s -> %s) (error %ld)\n", ERR("Unable to copy package (%s -> %s) (error %d)\n",
debugstr_w(msiFilePath), debugstr_w(packagefile), GetLastError()); debugstr_w(msiFilePath), debugstr_w(packagefile), GetLastError());
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
@ -3751,10 +3849,12 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package)
return ERROR_INSTALL_SUSPEND; return ERROR_INSTALL_SUSPEND;
} }
UINT ACTION_ResolveSource(MSIPACKAGE* package) static UINT ACTION_ResolveSource(MSIPACKAGE* package)
{ {
DWORD attrib; DWORD attrib, len;
LPWSTR ptr, source;
UINT rc; UINT rc;
/* /*
* we are currently doing what should be done here in the top level Install * we are currently doing what should be done here in the top level Install
* however for Adminastrative and uninstalls this step will be needed * however for Adminastrative and uninstalls this step will be needed
@ -3762,6 +3862,19 @@ UINT ACTION_ResolveSource(MSIPACKAGE* package)
if (!package->PackagePath) if (!package->PackagePath)
return ERROR_SUCCESS; return ERROR_SUCCESS;
ptr = strrchrW(package->PackagePath, '\\');
if (!ptr)
return ERROR_SUCCESS;
len = ptr - package->PackagePath + 2;
source = msi_alloc(len * sizeof(WCHAR));
lstrcpynW(source, package->PackagePath, len);
MSI_SetPropertyW(package, cszSourceDir, source);
MSI_SetPropertyW(package, cszSOURCEDIR, source);
msi_free(source);
attrib = GetFileAttributesW(package->PackagePath); attrib = GetFileAttributesW(package->PackagePath);
if (attrib == INVALID_FILE_ATTRIBUTES) if (attrib == INVALID_FILE_ATTRIBUTES)
{ {
@ -3956,6 +4069,100 @@ static UINT ACTION_PublishComponents(MSIPACKAGE *package)
return rc; return rc;
} }
static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
{
MSIPACKAGE *package = (MSIPACKAGE*)param;
MSIRECORD *row;
MSIFILE *file;
SC_HANDLE hscm, service = NULL;
LPCWSTR name, disp, comp, depends, pass;
LPCWSTR load_order, serv_name, key;
DWORD serv_type, start_type;
DWORD err_control;
static const WCHAR query[] =
{'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','`',' ',
'=','\'','%','s','\'',0};
hscm = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASEW, GENERIC_WRITE);
if (!hscm)
{
ERR("Failed to open the SC Manager!\n");
goto done;
}
start_type = MSI_RecordGetInteger(rec, 5);
if (start_type == SERVICE_BOOT_START || start_type == SERVICE_SYSTEM_START)
goto done;
depends = MSI_RecordGetString(rec, 8);
if (depends && *depends)
FIXME("Dependency list unhandled!\n");
name = MSI_RecordGetString(rec, 2);
disp = MSI_RecordGetString(rec, 3);
serv_type = MSI_RecordGetInteger(rec, 4);
err_control = MSI_RecordGetInteger(rec, 6);
load_order = MSI_RecordGetString(rec, 7);
serv_name = MSI_RecordGetString(rec, 9);
pass = MSI_RecordGetString(rec, 10);
comp = MSI_RecordGetString(rec, 12);
/* fetch the service path */
row = MSI_QueryGetRecord(package->db, query, comp);
if (!row)
{
ERR("Control query failed!\n");
goto done;
}
key = MSI_RecordGetString(row, 6);
msiobj_release(&row->hdr);
file = get_loaded_file(package, key);
if (!file)
{
ERR("Failed to load the service file\n");
goto done;
}
service = CreateServiceW(hscm, name, disp, GENERIC_ALL, serv_type,
start_type, err_control, file->TargetPath,
load_order, NULL, NULL, serv_name, pass);
if (!service)
{
if (GetLastError() != ERROR_SERVICE_EXISTS)
ERR("Failed to create service %s: %d\n", debugstr_w(name), GetLastError());
}
done:
CloseServiceHandle(service);
CloseServiceHandle(hscm);
return ERROR_SUCCESS;
}
static UINT ACTION_InstallServices( MSIPACKAGE *package )
{
UINT rc;
MSIQUERY * view;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'S','e','r','v','i','c','e','I','n','s','t','a','l','l',0};
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords(view, NULL, ITERATE_InstallService, package);
msiobj_release(&view->hdr);
return rc;
}
static UINT msi_unimplemented_action_stub( MSIPACKAGE *package, static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
LPCSTR action, LPCWSTR table ) LPCSTR action, LPCWSTR table )
{ {
@ -3974,7 +4181,7 @@ static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
} }
if (count) if (count)
FIXME("%s -> %lu ignored %s table values\n", FIXME("%s -> %u ignored %s table values\n",
action, count, debugstr_w(table)); action, count, debugstr_w(table));
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -4030,13 +4237,6 @@ static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
return msi_unimplemented_action_stub( package, "SelfUnregModules", table ); return msi_unimplemented_action_stub( package, "SelfUnregModules", table );
} }
static UINT ACTION_InstallServices( MSIPACKAGE *package )
{
static const WCHAR table[] = {
'S','e','r','v','i','c','e','I','n','s','t','a','l','l',0 };
return msi_unimplemented_action_stub( package, "InstallServices", table );
}
static UINT ACTION_StartServices( MSIPACKAGE *package ) static UINT ACTION_StartServices( MSIPACKAGE *package )
{ {
static const WCHAR table[] = { static const WCHAR table[] = {

View file

@ -1,307 +0,0 @@
/*
* Common prototypes for Action handlers
*
* 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
*/
#ifndef __MSI_ACTION_H__
#define __MSI_ACTION_H__
#include "wine/list.h"
typedef struct tagMSIFEATURE
{
struct list entry;
LPWSTR Feature;
LPWSTR Feature_Parent;
LPWSTR Title;
LPWSTR Description;
INT Display;
INT Level;
LPWSTR Directory;
INT Attributes;
INSTALLSTATE Installed;
INSTALLSTATE ActionRequest;
INSTALLSTATE Action;
struct list Components;
INT Cost;
} MSIFEATURE;
typedef struct tagMSICOMPONENT
{
struct list entry;
DWORD magic;
LPWSTR Component;
LPWSTR ComponentId;
LPWSTR Directory;
INT Attributes;
LPWSTR Condition;
LPWSTR KeyPath;
INSTALLSTATE Installed;
INSTALLSTATE ActionRequest;
INSTALLSTATE Action;
BOOL ForceLocalState;
BOOL Enabled;
INT Cost;
INT RefCount;
LPWSTR FullKeypath;
LPWSTR AdvertiseString;
} MSICOMPONENT;
typedef struct tagComponentList
{
struct list entry;
MSICOMPONENT *component;
} ComponentList;
typedef struct tagMSIFOLDER
{
struct list entry;
LPWSTR Directory;
LPWSTR TargetDefault;
LPWSTR SourceLongPath;
LPWSTR SourceShortPath;
LPWSTR ResolvedTarget;
LPWSTR ResolvedSource;
LPWSTR Property; /* initially set property */
struct tagMSIFOLDER *Parent;
INT State;
/* 0 = uninitialized */
/* 1 = existing */
/* 2 = created remove if empty */
/* 3 = created persist if empty */
INT Cost;
INT Space;
} MSIFOLDER;
typedef enum _msi_file_state {
msifs_invalid,
msifs_missing,
msifs_overwrite,
msifs_present,
msifs_installed,
msifs_skipped,
} msi_file_state;
typedef struct tagMSIFILE
{
struct list entry;
LPWSTR File;
MSICOMPONENT *Component;
LPWSTR FileName;
LPWSTR ShortName;
LPWSTR LongName;
INT FileSize;
LPWSTR Version;
LPWSTR Language;
INT Attributes;
INT Sequence;
msi_file_state state;
LPWSTR SourcePath;
LPWSTR TargetPath;
BOOL IsCompressed;
} MSIFILE;
typedef struct tagMSITEMPFILE
{
struct list entry;
LPWSTR File;
LPWSTR Path;
} MSITEMPFILE;
typedef struct tagMSIAPPID
{
struct list entry;
LPWSTR AppID; /* Primary key */
LPWSTR RemoteServerName;
LPWSTR LocalServer;
LPWSTR ServiceParameters;
LPWSTR DllSurrogate;
BOOL ActivateAtStorage;
BOOL RunAsInteractiveUser;
} MSIAPPID;
typedef struct tagMSIPROGID MSIPROGID;
typedef struct tagMSICLASS
{
struct list entry;
LPWSTR clsid; /* Primary Key */
LPWSTR Context; /* Primary Key */
MSICOMPONENT *Component;
MSIPROGID *ProgID;
LPWSTR ProgIDText;
LPWSTR Description;
MSIAPPID *AppID;
LPWSTR FileTypeMask;
LPWSTR IconPath;
LPWSTR DefInprocHandler;
LPWSTR DefInprocHandler32;
LPWSTR Argument;
MSIFEATURE *Feature;
INT Attributes;
/* not in the table, set during installation */
BOOL Installed;
} MSICLASS;
typedef struct tagMSIMIME MSIMIME;
typedef struct tagMSIEXTENSION
{
struct list entry;
LPWSTR Extension; /* Primary Key */
MSICOMPONENT *Component;
MSIPROGID *ProgID;
LPWSTR ProgIDText;
MSIMIME *Mime;
MSIFEATURE *Feature;
/* not in the table, set during installation */
BOOL Installed;
struct list verbs;
} MSIEXTENSION;
struct tagMSIPROGID
{
struct list entry;
LPWSTR ProgID; /* Primary Key */
MSIPROGID *Parent;
MSICLASS *Class;
LPWSTR Description;
LPWSTR IconPath;
/* not in the table, set during installation */
BOOL InstallMe;
MSIPROGID *CurVer;
MSIPROGID *VersionInd;
};
typedef struct tagMSIVERB
{
struct list entry;
LPWSTR Verb;
INT Sequence;
LPWSTR Command;
LPWSTR Argument;
} MSIVERB;
struct tagMSIMIME
{
struct list entry;
LPWSTR ContentType; /* Primary Key */
MSIEXTENSION *Extension;
LPWSTR clsid;
MSICLASS *Class;
/* not in the table, set during installation */
BOOL InstallMe;
};
enum SCRIPTS {
INSTALL_SCRIPT = 0,
COMMIT_SCRIPT = 1,
ROLLBACK_SCRIPT = 2,
TOTAL_SCRIPTS = 3
};
#define SEQUENCE_UI 0x1
#define SEQUENCE_EXEC 0x2
#define SEQUENCE_INSTALL 0x10
typedef struct tagMSISCRIPT
{
LPWSTR *Actions[TOTAL_SCRIPTS];
UINT ActionCount[TOTAL_SCRIPTS];
BOOL ExecuteSequenceRun;
BOOL CurrentlyScripting;
UINT InWhatSequence;
LPWSTR *UniqueActions;
UINT UniqueActionsCount;
} MSISCRIPT;
extern UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force);
extern UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action);
extern void ACTION_FinishCustomActions( MSIPACKAGE* package);
extern UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute);
/* actions in other modules */
extern UINT ACTION_AppSearch(MSIPACKAGE *package);
extern UINT ACTION_FindRelatedProducts(MSIPACKAGE *package);
extern UINT ACTION_InstallFiles(MSIPACKAGE *package);
extern UINT ACTION_RemoveFiles(MSIPACKAGE *package);
extern UINT ACTION_DuplicateFiles(MSIPACKAGE *package);
extern UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterFonts(MSIPACKAGE *package);
/* Helpers */
extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
extern LPWSTR msi_dup_record_field(MSIRECORD *row, INT index);
extern LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop);
extern int msi_get_property_int( MSIPACKAGE *package, LPCWSTR prop, int def );
extern LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
BOOL set_prop, MSIFOLDER **folder);
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
extern MSIFEATURE *get_loaded_feature( MSIPACKAGE* package, LPCWSTR Feature );
extern MSIFILE *get_loaded_file( MSIPACKAGE* package, LPCWSTR file );
extern MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir );
extern int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
extern UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action);
extern LPWSTR build_icon_path(MSIPACKAGE *, LPCWSTR);
extern LPWSTR build_directory_name(DWORD , ...);
extern BOOL create_full_pathW(const WCHAR *path);
extern BOOL ACTION_VerifyComponentForAction(MSICOMPONENT*, INSTALLSTATE);
extern BOOL ACTION_VerifyFeatureForAction(MSIFEATURE*, INSTALLSTATE);
extern void reduce_to_longfilename(WCHAR*);
extern void reduce_to_shortfilename(WCHAR*);
extern LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
extern UINT register_unique_action(MSIPACKAGE *, LPCWSTR);
extern BOOL check_unique_action(MSIPACKAGE *, LPCWSTR);
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
extern UINT msi_create_component_directories( MSIPACKAGE *package );
/* control event stuff */
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
MSIRECORD *data);
extern VOID ControlEvent_CleanupSubscriptions(MSIPACKAGE *package);
extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, LPCWSTR event,
LPCWSTR control, LPCWSTR attribute);
extern VOID ControlEvent_UnSubscribeToEvent( MSIPACKAGE *package, LPCWSTR event,
LPCWSTR control, LPCWSTR attribute );
/* User Interface messages from the actions */
extern void ui_progress(MSIPACKAGE *, int, int, int, int);
extern void ui_actiondata(MSIPACKAGE *, LPCWSTR, MSIRECORD *);
/* string consts use a number of places and defined in helpers.c*/
extern const WCHAR cszSourceDir[];
extern const WCHAR szProductCode[];
extern const WCHAR cszRootDrive[];
extern const WCHAR cszbs[];
#endif /* __MSI_ACTION_H__ */

View file

@ -32,7 +32,6 @@
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "msipriv.h" #include "msipriv.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -155,7 +154,7 @@ static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
TRACE("MaxVersion is %d.%d.%d.%d\n", HIWORD(sig->MaxVersionMS), TRACE("MaxVersion is %d.%d.%d.%d\n", HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS), HIWORD(sig->MaxVersionLS), LOWORD(sig->MaxVersionMS), HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS)); LOWORD(sig->MaxVersionLS));
TRACE("MinSize is %ld, MaxSize is %ld;\n", sig->MinSize, sig->MaxSize); TRACE("MinSize is %d, MaxSize is %d;\n", sig->MinSize, sig->MaxSize);
TRACE("Languages is %s\n", debugstr_w(sig->Languages)); TRACE("Languages is %s\n", debugstr_w(sig->Languages));
end: end:
@ -255,7 +254,7 @@ static void ACTION_ConvertRegValue(DWORD regType, const BYTE *value, DWORD sz,
switch (regType) switch (regType)
{ {
case REG_SZ: case REG_SZ:
if (*(LPWSTR)value == '#') if (*(LPCWSTR)value == '#')
{ {
/* escape leading pound with another */ /* escape leading pound with another */
*appValue = msi_alloc(sz + sizeof(WCHAR)); *appValue = msi_alloc(sz + sizeof(WCHAR));
@ -287,7 +286,7 @@ static void ACTION_ConvertRegValue(DWORD regType, const BYTE *value, DWORD sz,
sprintfW(*appValue + i * 3, binFmt, value[i]); sprintfW(*appValue + i * 3, binFmt, value[i]);
break; break;
default: default:
WARN("unimplemented for values of type %ld\n", regType); WARN("unimplemented for values of type %d\n", regType);
*appValue = NULL; *appValue = NULL;
} }
} }
@ -398,6 +397,9 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue,
rc = ACTION_SearchDirectory(package, sig, (LPCWSTR)value, 0, rc = ACTION_SearchDirectory(package, sig, (LPCWSTR)value, 0,
appValue); appValue);
break; break;
case msidbLocatorTypeFileName:
*appValue = strdupW((LPCWSTR)value);
break;
case msidbLocatorTypeRawValue: case msidbLocatorTypeRawValue:
ACTION_ConvertRegValue(regType, value, sz, appValue); ACTION_ConvertRegValue(regType, value, sz, appValue);
break; break;
@ -528,7 +530,10 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
size_t copied = 0; size_t copied = 0;
if (!src || !dst || !len) if (!src || !dst || !len)
{
if (dst) *dst = '\0';
return; return;
}
/* Ignore the short portion of the path, don't think we can use it anyway */ /* Ignore the short portion of the path, don't think we can use it anyway */
if ((ptr = strchrW(src, '|'))) if ((ptr = strchrW(src, '|')))
@ -913,7 +918,7 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue,
msi_free(path); msi_free(path);
if (parent) if (parent)
{ {
path = msi_alloc(strlenW(parent) + strlenW(expanded) + 1); path = msi_alloc((strlenW(parent) + strlenW(expanded) + 1) * sizeof(WCHAR));
if (!path) if (!path)
goto end; goto end;
strcpyW(path, parent); strcpyW(path, parent);
@ -991,7 +996,7 @@ UINT ACTION_AppSearch(MSIPACKAGE *package)
while (!rc) while (!rc)
{ {
MSISIGNATURE sig; MSISIGNATURE sig;
LPWSTR value; LPWSTR value = NULL;
rc = MSI_ViewFetch(view,&row); rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)

View file

@ -40,7 +40,6 @@
#include "msipriv.h" #include "msipriv.h"
#include "winuser.h" #include "winuser.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);

View file

@ -35,7 +35,6 @@
#include "msi.h" #include "msi.h"
#include "msiquery.h" #include "msiquery.h"
#include "msipriv.h" #include "msipriv.h"
#include "action.h"
#define YYLEX_PARAM info #define YYLEX_PARAM info
#define YYPARSE_PARAM info #define YYPARSE_PARAM info

View file

@ -47,7 +47,6 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/summa
#include "shlobj.h" #include "shlobj.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "winver.h" #include "winver.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -120,7 +119,7 @@ static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR acti
/* stores the CustomActionData before the action: /* stores the CustomActionData before the action:
* [CustomActionData]Action * [CustomActionData]Action
*/ */
LPWSTR msi_get_deferred_action(LPCWSTR action, LPWSTR actiondata) static LPWSTR msi_get_deferred_action(LPCWSTR action, LPWSTR actiondata)
{ {
LPWSTR deferred; LPWSTR deferred;
DWORD len; DWORD len;
@ -167,7 +166,10 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
row = MSI_QueryGetRecord( package->db, ExecSeqQuery, action ); row = MSI_QueryGetRecord( package->db, ExecSeqQuery, action );
if (!row) if (!row)
{
msi_free(action_copy);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
}
type = MSI_RecordGetInteger(row,2); type = MSI_RecordGetInteger(row,2);
@ -382,7 +384,7 @@ static UINT process_action_return_value(UINT type, HANDLE ThreadHandle)
case ERROR_NO_MORE_ITEMS: case ERROR_NO_MORE_ITEMS:
return ERROR_SUCCESS; return ERROR_SUCCESS;
default: default:
ERR("Invalid Return Code %ld\n",rc); ERR("Invalid Return Code %d\n",rc);
return ERROR_INSTALL_FAILURE; return ERROR_INSTALL_FAILURE;
} }
} }
@ -503,13 +505,12 @@ static DWORD WINAPI DllThread(LPVOID info)
thread_struct *stuff; thread_struct *stuff;
DWORD rc = 0; DWORD rc = 0;
TRACE("MSI Thread (0x%lx) started for custom action\n", TRACE("MSI Thread (%x) started for custom action\n", GetCurrentThreadId());
GetCurrentThreadId());
stuff = (thread_struct*)info; stuff = (thread_struct*)info;
rc = ACTION_CallDllFunction(stuff); rc = ACTION_CallDllFunction(stuff);
TRACE("MSI Thread (0x%lx) finished (rc %li)\n",GetCurrentThreadId(), rc); TRACE("MSI Thread (%x) finished (rc %i)\n",GetCurrentThreadId(), rc);
/* clse all handles for this thread */ /* clse all handles for this thread */
MsiCloseAllHandles(); MsiCloseAllHandles();
return rc; return rc;

View file

@ -28,6 +28,7 @@
#include "winreg.h" #include "winreg.h"
#include "winnls.h" #include "winnls.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h"
#include "msi.h" #include "msi.h"
#include "msiquery.h" #include "msiquery.h"
#include "msipriv.h" #include "msipriv.h"
@ -58,12 +59,13 @@ static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
MSIDATABASE *db = (MSIDATABASE *) arg; MSIDATABASE *db = (MSIDATABASE *) arg;
DWORD r; DWORD r;
msi_free(db->path);
free_cached_tables( db ); free_cached_tables( db );
msi_free_transforms( db ); msi_free_transforms( db );
msi_destroy_stringtable( db->strings ); msi_destroy_stringtable( db->strings );
r = IStorage_Release( db->storage ); r = IStorage_Release( db->storage );
if( r ) if( r )
ERR("database reference count was not zero (%ld)\n", r); ERR("database reference count was not zero (%d)\n", r);
if (db->deletefile) if (db->deletefile)
{ {
DeleteFileW( db->deletefile ); DeleteFileW( db->deletefile );
@ -77,15 +79,19 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
HRESULT r; HRESULT r;
MSIDATABASE *db = NULL; MSIDATABASE *db = NULL;
UINT ret = ERROR_FUNCTION_FAILED; UINT ret = ERROR_FUNCTION_FAILED;
LPCWSTR szMode; LPCWSTR szMode, save_path;
STATSTG stat; STATSTG stat;
BOOL created = FALSE; BOOL created = FALSE;
WCHAR path[MAX_PATH];
static const WCHAR backslash[] = {'\\',0};
TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) ); TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
if( !pdb ) if( !pdb )
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
save_path = szDBPath;
szMode = szPersist; szMode = szPersist;
if( HIWORD( szPersist ) ) if( HIWORD( szPersist ) )
{ {
@ -135,7 +141,7 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
if( FAILED( r ) ) if( FAILED( r ) )
{ {
FIXME("open failed r = %08lx!\n",r); FIXME("open failed r = %08x!\n",r);
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
@ -162,6 +168,17 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
goto end; goto end;
} }
if (!strchrW( save_path, '\\' ))
{
GetCurrentDirectoryW( MAX_PATH, path );
lstrcatW( path, backslash );
lstrcatW( path, save_path );
}
else
lstrcpyW( path, save_path );
db->path = strdupW( path );
if( TRACE_ON( msi ) ) if( TRACE_ON( msi ) )
enum_stream_names( stg ); enum_stream_names( stg );
@ -245,14 +262,444 @@ end:
return r; return r;
} }
UINT MSI_DatabaseImport( MSIDATABASE *db, LPCWSTR folder, LPCWSTR file ) static LPWSTR msi_read_text_archive(LPCWSTR path)
{ {
FIXME("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) ); HANDLE file;
LPSTR data = NULL;
LPWSTR wdata = NULL;
DWORD read, size = 0;
file = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
if (file == INVALID_HANDLE_VALUE)
return NULL;
size = GetFileSize( file, NULL );
data = msi_alloc( size + 1 );
if (!data)
goto done;
if (!ReadFile( file, data, size, &read, NULL ))
goto done;
data[size] = '\0';
wdata = strdupAtoW( data );
done:
CloseHandle( file );
msi_free( data );
return wdata;
}
static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries)
{
LPWSTR ptr = *line, save;
DWORD i, count = 1;
*entries = NULL;
/* stay on this line */
while (*ptr && *ptr != '\n')
{
/* entries are separated by tabs */
if (*ptr == '\t')
count++;
ptr++;
}
*entries = msi_alloc(count * sizeof(LPWSTR));
if (!*entries)
return;
/* store pointers into the data */
for (i = 0, ptr = *line; i < count; i++)
{
save = ptr;
while (*ptr && *ptr != '\t' && *ptr != '\n') ptr++;
/* NULL-separate the data */
if (*ptr)
*ptr++ = '\0';
(*entries)[i] = save;
}
/* move to the next line if there's more, else EOF */
*line = ptr;
if (num_entries)
*num_entries = count;
}
static LPWSTR msi_build_createsql_prelude(LPWSTR table)
{
LPWSTR prelude;
DWORD size;
static const WCHAR create_fmt[] = {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','%','s','`',' ','(',' ',0};
size = sizeof(create_fmt) + lstrlenW(table) - 2;
prelude = msi_alloc(size * sizeof(WCHAR));
if (!prelude)
return NULL;
sprintfW(prelude, create_fmt, table);
return prelude;
}
static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
{
LPWSTR columns;
LPCWSTR type;
DWORD sql_size = 1, i, len;
WCHAR expanded[128], *ptr;
WCHAR size[10], comma[2], extra[10];
static const WCHAR column_fmt[] = {'`','%','s','`',' ','%','s','%','s','%','s','%','s',' ',0};
static const WCHAR size_fmt[] = {'(','%','s',')',0};
static const WCHAR type_char[] = {'C','H','A','R',0};
static const WCHAR type_int[] = {'I','N','T',0};
static const WCHAR type_long[] = {'L','O','N','G',0};
static const WCHAR type_notnull[] = {' ','N','O','T',' ','N','U','L','L',0};
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
for (i = 0; i < num_columns; i++)
{
type = NULL;
comma[1] = size[0] = extra[0] = '\0';
if (i == num_columns - 1)
comma[0] = '\0';
else
comma[0] = ',';
ptr = &types[i][1];
len = atolW(ptr);
switch (types[i][0])
{
case 'l': case 's':
lstrcpyW(extra, type_notnull);
case 'L': case 'S':
type = type_char;
sprintfW(size, size_fmt, ptr);
break;
case 'i':
lstrcpyW(extra, type_notnull);
case 'I':
if (len == 2)
type = type_int;
else
type = type_long;
break;
}
sprintfW(expanded, column_fmt, columns_data[i], type, size, extra, comma);
sql_size += lstrlenW(expanded);
columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
lstrcatW(columns, expanded);
}
return columns;
}
static LPWSTR msi_build_createsql_postlude(LPWSTR *primary_keys, DWORD num_keys)
{
LPWSTR postlude, keys, ptr;
DWORD size, key_size, i;
static const WCHAR key_fmt[] = {'`','%','s','`',',',' ',0};
static const WCHAR postlude_fmt[] = {'P','R','I','M','A','R','Y',' ','K','E','Y',' ','%','s',')',' ','H','O','L','D',0};
for (i = 0, size = 1; i < num_keys; i++)
size += lstrlenW(key_fmt) + lstrlenW(primary_keys[i]) - 2;
keys = msi_alloc(size * sizeof(WCHAR));
if (!keys)
return NULL;
for (i = 0, ptr = keys; i < num_keys; i++)
{
key_size = lstrlenW(key_fmt) + lstrlenW(primary_keys[i]) -2;
sprintfW(ptr, key_fmt, primary_keys[i]);
ptr += key_size;
}
/* remove final ', ' */
*(ptr - 2) = '\0';
size = lstrlenW(postlude_fmt) + size - 1;
postlude = msi_alloc(size * sizeof(WCHAR));
if (!postlude)
goto done;
sprintfW(postlude, postlude_fmt, keys);
done:
msi_free(keys);
return postlude;
}
static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, DWORD num_labels, DWORD num_columns)
{
UINT r;
DWORD size;
MSIQUERY *view;
LPWSTR create_sql;
LPWSTR prelude, columns_sql, postlude;
prelude = msi_build_createsql_prelude(labels[0]);
columns_sql = msi_build_createsql_columns(columns, types, num_columns);
postlude = msi_build_createsql_postlude(labels + 1, num_labels - 1); /* skip over table name */
if (!prelude || !columns_sql || !postlude)
return ERROR_OUTOFMEMORY;
size = lstrlenW(prelude) + lstrlenW(columns_sql) + lstrlenW(postlude) + 1;
create_sql = msi_alloc(size * sizeof(WCHAR));
if (!create_sql)
return ERROR_OUTOFMEMORY;
lstrcpyW(create_sql, prelude);
lstrcatW(create_sql, columns_sql);
lstrcatW(create_sql, postlude);
msi_free(prelude);
msi_free(columns_sql);
msi_free(postlude);
r = MSI_DatabaseOpenViewW( db, create_sql, &view );
msi_free(create_sql);
if (r != ERROR_SUCCESS)
return r;
r = MSI_ViewExecute(view, NULL);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return r;
}
static LPWSTR msi_build_insertsql_prelude(LPWSTR table)
{
LPWSTR prelude;
DWORD size;
static const WCHAR insert_fmt[] = {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','%','s','`',' ','(',' ',0};
size = sizeof(insert_fmt) + lstrlenW(table) - 2;
prelude = msi_alloc(size * sizeof(WCHAR));
if (!prelude)
return NULL;
sprintfW(prelude, insert_fmt, table);
return prelude;
}
static LPWSTR msi_build_insertsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
{
LPWSTR columns;
DWORD sql_size = 1, i;
WCHAR expanded[128];
static const WCHAR column_fmt[] = {'`','%','s','`',',',' ',0};
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
for (i = 0; i < num_columns; i++)
{
sprintfW(expanded, column_fmt, columns_data[i]);
sql_size += lstrlenW(expanded);
if (i == num_columns - 1)
{
sql_size -= 2;
expanded[lstrlenW(expanded) - 2] = '\0';
}
columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
lstrcatW(columns, expanded);
}
return columns;
}
static LPWSTR msi_build_insertsql_data(LPWSTR **records, LPWSTR *types, DWORD num_columns, DWORD irec)
{
LPWSTR columns;
DWORD sql_size = 1, i;
WCHAR expanded[128];
static const WCHAR str_fmt[] = {'\'','%','s','\'',',',' ',0};
static const WCHAR int_fmt[] = {'%','s',',',' ',0};
static const WCHAR empty[] = {'\'','\'',',',' ',0};
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
for (i = 0; i < num_columns; i++)
{
switch (types[i][0])
{
case 'L': case 'l': case 'S': case 's':
sprintfW(expanded, str_fmt, records[irec][i]);
break;
case 'I': case 'i':
if (*records[0][i])
sprintfW(expanded, int_fmt, records[irec][i]);
else
lstrcpyW(expanded, empty);
break;
default:
return NULL;
}
if (i == num_columns - 1)
expanded[lstrlenW(expanded) - 2] = '\0';
sql_size += lstrlenW(expanded);
columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
lstrcatW(columns, expanded);
}
return columns;
}
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
LPWSTR *labels, LPWSTR **records,
int num_columns, int num_records)
{
MSIQUERY *view;
LPWSTR insert_sql;
DWORD size, i;
UINT r = ERROR_SUCCESS;
static const WCHAR mid[] = {' ',')',' ','V','A','L','U','E','S',' ','(',' ',0};
static const WCHAR end[] = {' ',')',0};
LPWSTR prelude = msi_build_insertsql_prelude(labels[0]);
LPWSTR columns_sql = msi_build_insertsql_columns(columns, types, num_columns);
for (i = 0; i < num_records; i++)
{
LPWSTR data = msi_build_insertsql_data(records, types, num_columns, i);
size = lstrlenW(prelude) + lstrlenW(columns_sql) + sizeof(mid) + lstrlenW(data) + sizeof(end) - 1;
insert_sql = msi_alloc(size * sizeof(WCHAR));
if (!insert_sql)
return ERROR_OUTOFMEMORY;
lstrcpyW(insert_sql, prelude);
lstrcatW(insert_sql, columns_sql);
lstrcatW(insert_sql, mid);
lstrcatW(insert_sql, data);
lstrcatW(insert_sql, end);
msi_free(data);
r = MSI_DatabaseOpenViewW( db, insert_sql, &view );
msi_free(insert_sql);
if (r != ERROR_SUCCESS)
goto done;
r = MSI_ViewExecute(view, NULL);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
done:
msi_free(prelude);
msi_free(columns_sql);
return r;
}
UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
{
UINT r;
DWORD len, i;
DWORD num_labels;
DWORD num_columns, num_records = 0;
LPWSTR *columns, *types, *labels;
LPWSTR path, ptr, data;
LPWSTR **records;
static const WCHAR backslash[] = {'\\',0};
TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
if( folder == NULL || file == NULL ) if( folder == NULL || file == NULL )
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
return ERROR_CALL_NOT_IMPLEMENTED; len = lstrlenW(folder) + lstrlenW(backslash) + lstrlenW(file) + 1;
path = msi_alloc( len * sizeof(WCHAR) );
if (!path)
return ERROR_OUTOFMEMORY;
lstrcpyW( path, folder );
lstrcatW( path, backslash );
lstrcatW( path, file );
data = msi_read_text_archive( path );
ptr = data;
msi_parse_line( &ptr, &columns, &num_columns );
msi_parse_line( &ptr, &types, NULL );
msi_parse_line( &ptr, &labels, &num_labels );
records = msi_alloc(sizeof(LPWSTR *));
if (!records)
return ERROR_OUTOFMEMORY;
/* read in the table records */
while (*ptr)
{
msi_parse_line( &ptr, &records[num_records], NULL );
num_records++;
records = msi_realloc(records, (num_records + 1) * sizeof(LPWSTR *));
if (!records)
return ERROR_OUTOFMEMORY;
}
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
if (r != ERROR_SUCCESS)
goto done;
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
done:
msi_free(path);
msi_free(data);
msi_free(columns);
msi_free(types);
msi_free(labels);
for (i = 0; i < num_records; i++)
msi_free(records[i]);
msi_free(records);
return r;
} }
UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, LPCWSTR szFolder, LPCWSTR szFilename) UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, LPCWSTR szFolder, LPCWSTR szFilename)

View file

@ -42,8 +42,6 @@
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -82,6 +80,7 @@ typedef struct msi_font_tag
struct msi_dialog_tag struct msi_dialog_tag
{ {
MSIPACKAGE *package; MSIPACKAGE *package;
msi_dialog *parent;
msi_dialog_event_handler event_handler; msi_dialog_event_handler event_handler;
BOOL finished; BOOL finished;
INT scale; INT scale;
@ -144,6 +143,9 @@ static const WCHAR szListBox[] = { 'L','i','s','t','B','o','x',0 };
static const WCHAR szDirectoryCombo[] = { 'D','i','r','e','c','t','o','r','y','C','o','m','b','o',0 }; static const WCHAR szDirectoryCombo[] = { 'D','i','r','e','c','t','o','r','y','C','o','m','b','o',0 };
static const WCHAR szDirectoryList[] = { 'D','i','r','e','c','t','o','r','y','L','i','s','t',0 }; static const WCHAR szDirectoryList[] = { 'D','i','r','e','c','t','o','r','y','L','i','s','t',0 };
static const WCHAR szVolumeCostList[] = { 'V','o','l','u','m','e','C','o','s','t','L','i','s','t',0 }; static const WCHAR szVolumeCostList[] = { 'V','o','l','u','m','e','C','o','s','t','L','i','s','t',0 };
static const WCHAR szSelectionDescription[] = {'S','e','l','e','c','t','i','o','n','D','e','s','c','r','i','p','t','i','o','n',0};
static const WCHAR szSelectionPath[] = {'S','e','l','e','c','t','i','o','n','P','a','t','h',0};
static const WCHAR szProperty[] = {'P','r','o','p','e','r','t','y',0};
static UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM ); static UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM );
static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * ); static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * );
@ -152,7 +154,7 @@ static UINT msi_dialog_edit_handler( msi_dialog *, msi_control *, WPARAM );
static UINT msi_dialog_radiogroup_handler( msi_dialog *, msi_control *, WPARAM param ); static UINT msi_dialog_radiogroup_handler( msi_dialog *, msi_control *, WPARAM param );
static UINT msi_dialog_evaluate_control_conditions( msi_dialog *dialog ); static UINT msi_dialog_evaluate_control_conditions( msi_dialog *dialog );
static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static MSIFEATURE *msi_seltree_get_selected_feature( msi_control *control );
/* dialog sequencing */ /* dialog sequencing */
@ -213,42 +215,61 @@ static LPWSTR msi_get_deformatted_field( MSIPACKAGE *package, MSIRECORD *rec, in
static LPWSTR msi_dialog_dup_property( msi_dialog *dialog, LPCWSTR property, BOOL indirect ) static LPWSTR msi_dialog_dup_property( msi_dialog *dialog, LPCWSTR property, BOOL indirect )
{ {
LPWSTR prop = NULL;
if (!property) if (!property)
return NULL; return NULL;
if (indirect) if (indirect)
return msi_dup_property( dialog->package, property ); prop = msi_dup_property( dialog->package, property );
return strdupW( property ); if (!prop)
prop = strdupW( property );
return prop;
}
msi_dialog *msi_dialog_get_parent( msi_dialog *dialog )
{
return dialog->parent;
}
LPWSTR msi_dialog_get_name( msi_dialog *dialog )
{
return dialog->name;
} }
/* /*
* msi_dialog_get_style * msi_dialog_get_style
* *
* Extract the {\style} string from the front of the text to display and * Extract the {\style} string from the front of the text to display and
* update the pointer. * update the pointer. Only the last style in a list is applied.
*/ */
static LPWSTR msi_dialog_get_style( LPCWSTR p, LPCWSTR *rest ) static LPWSTR msi_dialog_get_style( LPCWSTR p, LPCWSTR *rest )
{ {
LPWSTR ret = NULL; LPWSTR ret;
LPCWSTR q, i; LPCWSTR q, i, first;
DWORD len; DWORD len;
q = NULL;
*rest = p; *rest = p;
if( !p ) if( !p )
return ret; return NULL;
if( *p++ != '{' )
return ret; while ((first = strchrW( p, '{' )) && (q = strchrW( first + 1, '}' )))
q = strchrW( p, '}' ); {
if( !q ) p = first + 1;
return ret;
if( *p == '\\' || *p == '&' ) if( *p == '\\' || *p == '&' )
p++; p++;
/* little bit of sanity checking to stop us getting confused with RTF */ /* little bit of sanity checking to stop us getting confused with RTF */
for( i=p; i<q; i++ ) for( i=p; i<q; i++ )
if( *i == '}' || *i == '\\' ) if( *i == '}' || *i == '\\' )
return ret; return NULL;
}
if (!p || !q)
return NULL;
*rest = ++q; *rest = ++q;
len = q - p; len = q - p;
@ -525,6 +546,8 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
LPCWSTR font_text, text = NULL; LPCWSTR font_text, text = NULL;
LPWSTR font; LPWSTR font;
static const WCHAR empty[] = {0};
ctrl = msi_dialog_find_control( dialog, control ); ctrl = msi_dialog_find_control( dialog, control );
if (!ctrl) if (!ctrl)
return; return;
@ -532,6 +555,7 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
{ {
font_text = MSI_RecordGetString( rec , 1 ); font_text = MSI_RecordGetString( rec , 1 );
font = msi_dialog_get_style( font_text, &text ); font = msi_dialog_get_style( font_text, &text );
if (!text) text = empty;
SetWindowTextW( ctrl->hwnd, text ); SetWindowTextW( ctrl->hwnd, text );
msi_free( font ); msi_free( font );
msi_dialog_check_messages( NULL ); msi_dialog_check_messages( NULL );
@ -558,10 +582,15 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
SendMessageW(ctrl->hwnd, PBM_SETPOS, 100*(ctrl->progress_current/ctrl->progress_max), 0); SendMessageW(ctrl->hwnd, PBM_SETPOS, 100*(ctrl->progress_current/ctrl->progress_max), 0);
break; break;
default: default:
ERR("Unknown progress message %ld\n", func); ERR("Unknown progress message %d\n", func);
break; break;
} }
} }
else if ( !lstrcmpW(attribute, szProperty) )
{
MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
MSI_SetPropertyW( dialog->package, ctrl->property, feature->Directory );
}
else else
{ {
FIXME("Attribute %s not being set\n", debugstr_w(attribute)); FIXME("Attribute %s not being set\n", debugstr_w(attribute));
@ -588,7 +617,7 @@ static void msi_dialog_map_events(msi_dialog* dialog, LPCWSTR control)
event = MSI_RecordGetString( row, 3 ); event = MSI_RecordGetString( row, 3 );
attribute = MSI_RecordGetString( row, 4 ); attribute = MSI_RecordGetString( row, 4 );
ControlEvent_SubscribeToEvent( dialog->package, event, control, attribute ); ControlEvent_SubscribeToEvent( dialog->package, dialog, event, control, attribute );
msiobj_release( &row->hdr ); msiobj_release( &row->hdr );
} }
@ -860,7 +889,7 @@ msi_richedit_stream_in( DWORD_PTR arg, LPBYTE buffer, LONG count, LONG *pcb )
*pcb = count; *pcb = count;
info->offset += count; info->offset += count;
TRACE("%ld/%ld\n", info->offset, info->length); TRACE("%d/%d\n", info->offset, info->length);
return 0; return 0;
} }
@ -1078,7 +1107,7 @@ static UINT msi_dialog_edit_control( msi_dialog *dialog, MSIRECORD *rec )
/******************** Masked Edit ********************************************/ /******************** Masked Edit ********************************************/
#define MASK_MAX_GROUPS 10 #define MASK_MAX_GROUPS 20
struct msi_mask_group struct msi_mask_group
{ {
@ -1443,8 +1472,8 @@ static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control
indirect = control->attributes & msidbControlAttributesIndirect; indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect ); prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dialog_dup_property( dialog, prop, TRUE );
path = msi_dup_property( dialog->package, prop );
SetWindowTextW( control->hwnd, path ); SetWindowTextW( control->hwnd, path );
SendMessageW( control->hwnd, EM_SETSEL, 0, -1 ); SendMessageW( control->hwnd, EM_SETSEL, 0, -1 );
@ -1645,19 +1674,24 @@ struct msi_selection_tree_info
msi_dialog *dialog; msi_dialog *dialog;
HWND hwnd; HWND hwnd;
WNDPROC oldproc; WNDPROC oldproc;
HTREEITEM selected;
}; };
static void static void
msi_seltree_sync_item_state( HWND hwnd, MSIFEATURE *feature, HTREEITEM hItem ) msi_seltree_sync_item_state( HWND hwnd, MSIFEATURE *feature, HTREEITEM hItem )
{ {
TVITEMW tvi; TVITEMW tvi;
DWORD index = feature->Action;
TRACE("Feature %s -> %d %d %d\n", debugstr_w(feature->Title), TRACE("Feature %s -> %d %d %d\n", debugstr_w(feature->Title),
feature->Installed, feature->Action, feature->ActionRequest); feature->Installed, feature->Action, feature->ActionRequest);
if (index == INSTALLSTATE_UNKNOWN)
index = INSTALLSTATE_ABSENT;
tvi.mask = TVIF_STATE; tvi.mask = TVIF_STATE;
tvi.hItem = hItem; tvi.hItem = hItem;
tvi.state = INDEXTOSTATEIMAGEMASK( feature->Action ); tvi.state = INDEXTOSTATEIMAGEMASK( index );
tvi.stateMask = TVIS_STATEIMAGEMASK; tvi.stateMask = TVIS_STATEIMAGEMASK;
SendMessageW( hwnd, TVM_SETITEMW, 0, (LPARAM) &tvi ); SendMessageW( hwnd, TVM_SETITEMW, 0, (LPARAM) &tvi );
@ -1700,8 +1734,9 @@ msi_seltree_feature_from_item( HWND hwnd, HTREEITEM hItem )
static LRESULT static LRESULT
msi_seltree_menu( HWND hwnd, HTREEITEM hItem ) msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
{ {
struct msi_selection_tree_info *info;
MSIFEATURE *feature; MSIFEATURE *feature;
ComponentList *cl; MSIPACKAGE *package;
union { union {
RECT rc; RECT rc;
POINT pt[2]; POINT pt[2];
@ -1709,6 +1744,9 @@ msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
} u; } u;
UINT r; UINT r;
info = GetPropW(hwnd, szButtonData);
package = info->dialog->package;
feature = msi_seltree_feature_from_item( hwnd, hItem ); feature = msi_seltree_feature_from_item( hwnd, hItem );
if (!feature) if (!feature)
{ {
@ -1737,17 +1775,17 @@ msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
/* update */ /* update */
msi_seltree_sync_item_state( hwnd, feature, hItem ); msi_seltree_sync_item_state( hwnd, feature, hItem );
ACTION_UpdateComponentStates( package, feature->Feature );
/* update the feature's components */
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{
cl->component->Action = feature->Action;
cl->component->ActionRequest = feature->ActionRequest;
}
return 0; return 0;
} }
static MSIFEATURE *msi_seltree_get_selected_feature( msi_control *control )
{
struct msi_selection_tree_info *info = GetPropW(control->hwnd, szButtonData);
return msi_seltree_feature_from_item( control->hwnd, info->selected );
}
static LRESULT WINAPI static LRESULT WINAPI
MSISelectionTree_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) MSISelectionTree_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
@ -1788,9 +1826,10 @@ static void
msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd, msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
LPCWSTR parent, HTREEITEM hParent ) LPCWSTR parent, HTREEITEM hParent )
{ {
struct msi_selection_tree_info *info = GetPropW( hwnd, szButtonData );
MSIFEATURE *feature; MSIFEATURE *feature;
TVINSERTSTRUCTW tvis; TVINSERTSTRUCTW tvis;
HTREEITEM hitem; HTREEITEM hitem, hfirst = NULL;
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
@ -1814,6 +1853,9 @@ msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
if (!hitem) if (!hitem)
continue; continue;
if (!hfirst)
hfirst = hitem;
msi_seltree_sync_item_state( hwnd, feature, hitem ); msi_seltree_sync_item_state( hwnd, feature, hitem );
msi_seltree_add_child_features( package, hwnd, msi_seltree_add_child_features( package, hwnd,
feature->Feature, hitem ); feature->Feature, hitem );
@ -1822,6 +1864,10 @@ msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
if ( feature->Display % 2 != 0 ) if ( feature->Display % 2 != 0 )
SendMessageW( hwnd, TVM_EXPAND, TVE_EXPAND, (LPARAM) hitem ); SendMessageW( hwnd, TVM_EXPAND, TVE_EXPAND, (LPARAM) hitem );
} }
/* select the first item */
SendMessageW( hwnd, TVM_SELECTITEM, TVGN_CARET | TVGN_DROPHILITE, (LPARAM) hfirst );
info->selected = hfirst;
} }
static void msi_seltree_create_imagelist( HWND hwnd ) static void msi_seltree_create_imagelist( HWND hwnd )
@ -1861,6 +1907,54 @@ static void msi_seltree_create_imagelist( HWND hwnd )
SendMessageW( hwnd, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)himl ); SendMessageW( hwnd, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)himl );
} }
static UINT msi_dialog_seltree_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
struct msi_selection_tree_info *info = GetPropW( control->hwnd, szButtonData );
LPNMTREEVIEWW tv = (LPNMTREEVIEWW)param;
MSIRECORD *row, *rec;
MSIFOLDER *folder;
LPCWSTR dir;
UINT r = ERROR_SUCCESS;
static const WCHAR select[] = {
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','F','e','a','t','u','r','e','`',' ','W','H','E','R','E',' ',
'`','T','i','t','l','e','`',' ','=',' ','\'','%','s','\'',0
};
if (tv->hdr.code != TVN_SELCHANGINGW)
return ERROR_SUCCESS;
info->selected = tv->itemNew.hItem;
row = MSI_QueryGetRecord( dialog->package->db, select, tv->itemNew.pszText );
if (!row)
return ERROR_FUNCTION_FAILED;
rec = MSI_CreateRecord( 1 );
MSI_RecordSetStringW( rec, 1, MSI_RecordGetString( row, 4 ) );
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionDescription, rec );
dir = MSI_RecordGetString( row, 7 );
folder = get_loaded_folder( dialog->package, dir );
if (!folder)
{
r = ERROR_FUNCTION_FAILED;
goto done;
}
MSI_RecordSetStringW( rec, 1, folder->ResolvedTarget );
ControlEvent_FireSubscribedEvent( dialog->package, szSelectionPath, rec );
done:
msiobj_release(&row->hdr);
msiobj_release(&rec->hdr);
return r;
}
static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec ) static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
{ {
msi_control *control; msi_control *control;
@ -1874,7 +1968,6 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
/* create the treeview control */ /* create the treeview control */
prop = MSI_RecordGetString( rec, 9 );
style = TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT; style = TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT;
style |= WS_GROUP | WS_VSCROLL; style |= WS_GROUP | WS_VSCROLL;
control = msi_dialog_add_control( dialog, rec, WC_TREEVIEWW, style ); control = msi_dialog_add_control( dialog, rec, WC_TREEVIEWW, style );
@ -1884,6 +1977,11 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
control->handler = msi_dialog_seltree_handler;
control->attributes = MSI_RecordGetInteger( rec, 8 );
prop = MSI_RecordGetString( rec, 9 );
control->property = msi_dialog_dup_property( dialog, prop, FALSE );
/* subclass */ /* subclass */
info->dialog = dialog; info->dialog = dialog;
info->hwnd = control->hwnd; info->hwnd = control->hwnd;
@ -1891,6 +1989,9 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
(LONG_PTR)MSISelectionTree_WndProc ); (LONG_PTR)MSISelectionTree_WndProc );
SetPropW( control->hwnd, szButtonData, info ); SetPropW( control->hwnd, szButtonData, info );
ControlEvent_SubscribeToEvent( dialog->package, dialog,
szSelectionPath, control->name, szProperty );
/* initialize it */ /* initialize it */
msi_seltree_create_imagelist( control->hwnd ); msi_seltree_create_imagelist( control->hwnd );
msi_seltree_add_child_features( package, control->hwnd, NULL, NULL ); msi_seltree_add_child_features( package, control->hwnd, NULL, NULL );
@ -2070,7 +2171,7 @@ static void msi_dialog_update_directory_combo( msi_dialog *dialog, msi_control *
indirect = control->attributes & msidbControlAttributesIndirect; indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect ); prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop ); path = msi_dialog_dup_property( dialog, prop, TRUE );
PathStripPathW( path ); PathStripPathW( path );
PathRemoveBackslashW( path ); PathRemoveBackslashW( path );
@ -2127,7 +2228,7 @@ static void msi_dialog_update_directory_list( msi_dialog *dialog, msi_control *c
indirect = control->attributes & msidbControlAttributesIndirect; indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect ); prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop ); path = msi_dialog_dup_property( dialog, prop, TRUE );
lstrcpyW( dir_spec, path ); lstrcpyW( dir_spec, path );
lstrcatW( dir_spec, asterisk ); lstrcatW( dir_spec, asterisk );
@ -2167,8 +2268,7 @@ UINT msi_dialog_directorylist_up( msi_dialog *dialog )
control = msi_dialog_find_control_by_type( dialog, szDirectoryList ); control = msi_dialog_find_control_by_type( dialog, szDirectoryList );
indirect = control->attributes & msidbControlAttributesIndirect; indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect ); prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dialog_dup_property( dialog, prop, TRUE );
path = msi_dup_property( dialog->package, prop );
/* strip off the last directory */ /* strip off the last directory */
ptr = PathFindFileNameW( path ); ptr = PathFindFileNameW( path );
@ -2217,7 +2317,7 @@ static UINT msi_dialog_dirlist_handler( msi_dialog *dialog,
indirect = control->attributes & msidbControlAttributesIndirect; indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect ); prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop ); path = msi_dialog_dup_property( dialog, prop, TRUE );
lstrcpyW( new_path, path ); lstrcpyW( new_path, path );
lstrcatW( new_path, text ); lstrcatW( new_path, text );
@ -2290,7 +2390,6 @@ static void msi_dialog_vcl_add_columns( msi_dialog *dialog, msi_control *control
WCHAR num[10]; WCHAR num[10];
LVCOLUMNW lvc; LVCOLUMNW lvc;
DWORD count = 0; DWORD count = 0;
LRESULT r;
static const WCHAR zero[] = {'0',0}; static const WCHAR zero[] = {'0',0};
static const WCHAR negative[] = {'-',0}; static const WCHAR negative[] = {'-',0};
@ -2316,20 +2415,20 @@ static void msi_dialog_vcl_add_columns( msi_dialog *dialog, msi_control *control
if ( !strncmpW( num, negative, 1 ) || !str_is_number( num ) ) if ( !strncmpW( num, negative, 1 ) || !str_is_number( num ) )
return; return;
lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_WIDTH | LVCF_TEXT; ZeroMemory( &lvc, sizeof(lvc) );
lvc.iOrder = count; lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
lvc.pszText = msi_dialog_get_uitext( dialog, column_keys[count++] );
lvc.cx = atolW( num ); lvc.cx = atolW( num );
lvc.fmt = LVCFMT_LEFT; lvc.pszText = msi_dialog_get_uitext( dialog, column_keys[count] );
r = SendMessageW( control->hwnd, LVM_INSERTCOLUMNW, 0, (LPARAM)&lvc ); SendMessageW( control->hwnd, LVM_INSERTCOLUMNW, count++, (LPARAM)&lvc );
msi_free( lvc.pszText ); msi_free( lvc.pszText );
if ( r ) return;
} }
} }
static void msi_dialog_vcl_add_drives( msi_dialog *dialog, msi_control *control ) static void msi_dialog_vcl_add_drives( msi_dialog *dialog, msi_control *control )
{ {
ULARGE_INTEGER total, free;
WCHAR size_text[MAX_PATH];
LPWSTR drives, ptr; LPWSTR drives, ptr;
LVITEMW lvitem; LVITEMW lvitem;
DWORD size; DWORD size;
@ -2353,6 +2452,20 @@ static void msi_dialog_vcl_add_drives( msi_dialog *dialog, msi_control *control
lvitem.cchTextMax = lstrlenW(ptr) + 1; lvitem.cchTextMax = lstrlenW(ptr) + 1;
SendMessageW( control->hwnd, LVM_INSERTITEMW, 0, (LPARAM)&lvitem ); SendMessageW( control->hwnd, LVM_INSERTITEMW, 0, (LPARAM)&lvitem );
GetDiskFreeSpaceExW(ptr, &free, &total, NULL);
StrFormatByteSizeW(total.QuadPart, size_text, MAX_PATH);
lvitem.iSubItem = 1;
lvitem.pszText = size_text;
lvitem.cchTextMax = lstrlenW(size_text) + 1;
SendMessageW( control->hwnd, LVM_SETITEMW, 0, (LPARAM)&lvitem );
StrFormatByteSizeW(free.QuadPart, size_text, MAX_PATH);
lvitem.iSubItem = 2;
lvitem.pszText = size_text;
lvitem.cchTextMax = lstrlenW(size_text) + 1;
SendMessageW( control->hwnd, LVM_SETITEMW, 0, (LPARAM)&lvitem );
ptr += lstrlenW(ptr) + 1; ptr += lstrlenW(ptr) + 1;
i++; i++;
} }
@ -2503,10 +2616,7 @@ static UINT msi_dialog_evaluate_control_conditions( msi_dialog *dialog )
/* query the Control table for all the elements of the control */ /* query the Control table for all the elements of the control */
r = MSI_OpenQuery( package->db, &view, query, dialog->name ); r = MSI_OpenQuery( package->db, &view, query, dialog->name );
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
{ return ERROR_SUCCESS;
ERR("query failed for dialog %s\n", debugstr_w(dialog->name));
return ERROR_INVALID_PARAMETER;
}
r = MSI_IterateRecords( view, 0, msi_dialog_set_control_condition, dialog ); r = MSI_IterateRecords( view, 0, msi_dialog_set_control_condition, dialog );
msiobj_release( &view->hdr ); msiobj_release( &view->hdr );
@ -2621,7 +2731,7 @@ static void msi_dialog_adjust_dialog_pos( msi_dialog *dialog, MSIRECORD *rec, LP
dialog->size.cx = sz.cx; dialog->size.cx = sz.cx;
dialog->size.cy = sz.cy; dialog->size.cy = sz.cy;
TRACE("%lu %lu %lu %lu\n", pos->left, pos->top, pos->right, pos->bottom); TRACE("%u %u %u %u\n", pos->left, pos->top, pos->right, pos->bottom);
style = GetWindowLongPtrW( dialog->hwnd, GWL_STYLE ); style = GetWindowLongPtrW( dialog->hwnd, GWL_STYLE );
AdjustWindowRect( pos, style, FALSE ); AdjustWindowRect( pos, style, FALSE );
@ -2776,6 +2886,38 @@ static UINT msi_dialog_control_event( MSIRECORD *rec, LPVOID param )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
struct rec_list
{
struct list entry;
MSIRECORD *rec;
};
static UINT add_rec_to_list( MSIRECORD *rec, LPVOID param )
{
struct rec_list *add_rec;
struct list *records = (struct list *)param;
msiobj_addref( &rec->hdr );
add_rec = msi_alloc( sizeof( *add_rec ) );
if (!add_rec)
{
msiobj_release( &rec->hdr );
return ERROR_OUTOFMEMORY;
}
add_rec->rec = rec;
list_add_tail( records, &add_rec->entry );
return ERROR_SUCCESS;
}
static inline void remove_rec_from_list( struct rec_list *rec_entry )
{
msiobj_release( &rec_entry->rec->hdr );
list_remove( &rec_entry->entry );
msi_free( rec_entry );
}
static UINT msi_dialog_button_handler( msi_dialog *dialog, static UINT msi_dialog_button_handler( msi_dialog *dialog,
msi_control *control, WPARAM param ) msi_control *control, WPARAM param )
{ {
@ -2789,11 +2931,15 @@ static UINT msi_dialog_button_handler( msi_dialog *dialog,
'O','R','D','E','R',' ','B','Y',' ','`','O','r','d','e','r','i','n','g','`',0 'O','R','D','E','R',' ','B','Y',' ','`','O','r','d','e','r','i','n','g','`',0
}; };
MSIQUERY *view = NULL; MSIQUERY *view = NULL;
struct rec_list *rec_entry, *next;
struct list events;
UINT r; UINT r;
if( HIWORD(param) != BN_CLICKED ) if( HIWORD(param) != BN_CLICKED )
return ERROR_SUCCESS; return ERROR_SUCCESS;
list_init( &events );
r = MSI_OpenQuery( dialog->package->db, &view, query, r = MSI_OpenQuery( dialog->package->db, &view, query,
dialog->name, control->name ); dialog->name, control->name );
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
@ -2802,8 +2948,41 @@ static UINT msi_dialog_button_handler( msi_dialog *dialog,
return 0; return 0;
} }
r = MSI_IterateRecords( view, 0, msi_dialog_control_event, dialog ); r = MSI_IterateRecords( view, 0, add_rec_to_list, &events );
msiobj_release( &view->hdr ); msiobj_release( &view->hdr );
if (r != ERROR_SUCCESS)
goto done;
/* handle all SetProperty events first */
LIST_FOR_EACH_ENTRY_SAFE( rec_entry, next, &events, struct rec_list, entry )
{
LPCWSTR event = MSI_RecordGetString( rec_entry->rec, 3 );
if ( event[0] != '[' )
continue;
r = msi_dialog_control_event( rec_entry->rec, dialog );
remove_rec_from_list( rec_entry );
if ( r != ERROR_SUCCESS )
goto done;
}
/* handle all other events */
LIST_FOR_EACH_ENTRY_SAFE( rec_entry, next, &events, struct rec_list, entry )
{
r = msi_dialog_control_event( rec_entry->rec, dialog );
remove_rec_from_list( rec_entry );
if ( r != ERROR_SUCCESS )
goto done;
}
done:
LIST_FOR_EACH_ENTRY_SAFE( rec_entry, next, &events, struct rec_list, entry )
{
remove_rec_from_list( rec_entry );
}
return r; return r;
} }
@ -2938,7 +3117,7 @@ static LRESULT msi_dialog_onnotify( msi_dialog *dialog, LPARAM param )
LPNMHDR nmhdr = (LPNMHDR) param; LPNMHDR nmhdr = (LPNMHDR) param;
msi_control *control = msi_dialog_find_control_by_hwnd( dialog, nmhdr->hwndFrom ); msi_control *control = msi_dialog_find_control_by_hwnd( dialog, nmhdr->hwndFrom );
TRACE("%p %p", dialog, nmhdr->hwndFrom); TRACE("%p %p\n", dialog, nmhdr->hwndFrom);
if ( control && control->handler ) if ( control && control->handler )
control->handler( dialog, control, param ); control->handler( dialog, control, param );
@ -3045,7 +3224,8 @@ static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg,
/* functions that interface to other modules within MSI */ /* functions that interface to other modules within MSI */
msi_dialog *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName, msi_dialog *msi_dialog_create( MSIPACKAGE* package,
LPCWSTR szDialogName, msi_dialog *parent,
msi_dialog_event_handler event_handler ) msi_dialog_event_handler event_handler )
{ {
MSIRECORD *rec = NULL; MSIRECORD *rec = NULL;
@ -3058,6 +3238,7 @@ msi_dialog *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
if( !dialog ) if( !dialog )
return NULL; return NULL;
strcpyW( dialog->name, szDialogName ); strcpyW( dialog->name, szDialogName );
dialog->parent = parent;
msiobj_addref( &package->hdr ); msiobj_addref( &package->hdr );
dialog->package = package; dialog->package = package;
dialog->event_handler = event_handler; dialog->event_handler = event_handler;

View file

@ -32,7 +32,6 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/contr
#include "winreg.h" #include "winreg.h"
#include "msi.h" #include "msi.h"
#include "msipriv.h" #include "msipriv.h"
#include "action.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h" #include "wine/unicode.h"
@ -48,6 +47,7 @@ struct _events {
struct subscriber { struct subscriber {
struct list entry; struct list entry;
msi_dialog *dialog;
LPWSTR event; LPWSTR event;
LPWSTR control; LPWSTR control;
LPWSTR attribute; LPWSTR attribute;
@ -58,13 +58,13 @@ UINT ControlEvent_HandleControlEvent(MSIPACKAGE *, LPCWSTR, LPCWSTR, msi_dialog*
/* /*
* Create a dialog box and run it if it's modal * Create a dialog box and run it if it's modal
*/ */
static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name, BOOL destroy_modeless ) static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name, msi_dialog *parent, BOOL destroy_modeless )
{ {
msi_dialog *dialog; msi_dialog *dialog;
UINT r; UINT r;
/* create a new dialog */ /* create a new dialog */
dialog = msi_dialog_create( package, name, dialog = msi_dialog_create( package, name, parent,
ControlEvent_HandleControlEvent ); ControlEvent_HandleControlEvent );
if( dialog ) if( dialog )
{ {
@ -111,7 +111,12 @@ static UINT ControlEvent_EndDialog(MSIPACKAGE* package, LPCWSTR argument,
else if (lstrcmpW(argument, szIgnore) == 0) else if (lstrcmpW(argument, szIgnore) == 0)
package->CurrentInstallState = -1; package->CurrentInstallState = -1;
else if (lstrcmpW(argument, szReturn) == 0) else if (lstrcmpW(argument, szReturn) == 0)
{
msi_dialog *parent = msi_dialog_get_parent(dialog);
msi_free(package->next_dialog);
package->next_dialog = (parent) ? strdupW(msi_dialog_get_name(parent)) : NULL;
package->CurrentInstallState = ERROR_SUCCESS; package->CurrentInstallState = ERROR_SUCCESS;
}
else else
{ {
ERR("Unknown argument string %s\n",debugstr_w(argument)); ERR("Unknown argument string %s\n",debugstr_w(argument));
@ -143,7 +148,7 @@ static UINT ControlEvent_SpawnDialog(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog *dialog) msi_dialog *dialog)
{ {
/* don't destroy a modeless dialogs that might be our parent */ /* don't destroy a modeless dialogs that might be our parent */
event_do_dialog( package, argument, FALSE ); event_do_dialog( package, argument, dialog, FALSE );
if( package->CurrentInstallState != ERROR_SUCCESS ) if( package->CurrentInstallState != ERROR_SUCCESS )
msi_dialog_end_dialog( dialog ); msi_dialog_end_dialog( dialog );
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -237,10 +242,18 @@ static UINT ControlEvent_SetTargetPath(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog) msi_dialog* dialog)
{ {
LPWSTR path = msi_dup_property( package, argument ); LPWSTR path = msi_dup_property( package, argument );
MSIRECORD *rec = MSI_CreateRecord( 1 );
UINT r; UINT r;
static const WCHAR szSelectionPath[] = {'S','e','l','e','c','t','i','o','n','P','a','t','h',0};
MSI_RecordSetStringW( rec, 1, path );
ControlEvent_FireSubscribedEvent( package, szSelectionPath, rec );
/* failure to set the path halts the executing of control events */ /* failure to set the path halts the executing of control events */
r = MSI_SetTargetPathW(package, argument, path); r = MSI_SetTargetPathW(package, argument, path);
msi_free(path); msi_free(path);
msi_free(&rec->hdr);
return r; return r;
} }
@ -262,14 +275,15 @@ static void free_subscriber( struct subscriber *sub )
msi_free(sub); msi_free(sub);
} }
VOID ControlEvent_SubscribeToEvent( MSIPACKAGE *package, LPCWSTR event, VOID ControlEvent_SubscribeToEvent( MSIPACKAGE *package, msi_dialog *dialog,
LPCWSTR control, LPCWSTR attribute ) LPCWSTR event, LPCWSTR control, LPCWSTR attribute )
{ {
struct subscriber *sub; struct subscriber *sub;
sub = msi_alloc(sizeof (*sub)); sub = msi_alloc(sizeof (*sub));
if( !sub ) if( !sub )
return; return;
sub->dialog = dialog;
sub->event = strdupW(event); sub->event = strdupW(event);
sub->control = strdupW(control); sub->control = strdupW(control);
sub->attribute = strdupW(attribute); sub->attribute = strdupW(attribute);
@ -304,14 +318,11 @@ VOID ControlEvent_FireSubscribedEvent( MSIPACKAGE *package, LPCWSTR event,
TRACE("Firing Event %s\n",debugstr_w(event)); TRACE("Firing Event %s\n",debugstr_w(event));
if (!package->dialog)
return;
LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry ) LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry )
{ {
if (lstrcmpiW(sub->event, event)) if (lstrcmpiW(sub->event, event))
continue; continue;
msi_dialog_handle_event( package->dialog, sub->control, msi_dialog_handle_event( sub->dialog, sub->control,
sub->attribute, rec ); sub->attribute, rec );
} }
} }
@ -353,13 +364,13 @@ UINT ACTION_DialogBox( MSIPACKAGE* package, LPCWSTR szDialogName )
* dialog, as it returns ERROR_IO_PENDING when we try to run * dialog, as it returns ERROR_IO_PENDING when we try to run
* its message loop. * its message loop.
*/ */
r = event_do_dialog( package, szDialogName, TRUE ); r = event_do_dialog( package, szDialogName, NULL, TRUE );
while( r == ERROR_SUCCESS && package->next_dialog ) while( r == ERROR_SUCCESS && package->next_dialog )
{ {
LPWSTR name = package->next_dialog; LPWSTR name = package->next_dialog;
package->next_dialog = NULL; package->next_dialog = NULL;
r = event_do_dialog( package, name, TRUE ); r = event_do_dialog( package, name, NULL, TRUE );
msi_free( name ); msi_free( name );
} }
@ -398,6 +409,7 @@ static const struct _events Events[] = {
{ "Reset",ControlEvent_Reset }, { "Reset",ControlEvent_Reset },
{ "SetInstallLevel",ControlEvent_SetInstallLevel }, { "SetInstallLevel",ControlEvent_SetInstallLevel },
{ "DirectoryListUp",ControlEvent_DirectoryListUp }, { "DirectoryListUp",ControlEvent_DirectoryListUp },
{ "SelectionBrowse",ControlEvent_SpawnDialog },
{ NULL,NULL }, { NULL,NULL },
}; };

View file

@ -45,7 +45,6 @@
#include "winreg.h" #include "winreg.h"
#include "shlwapi.h" #include "shlwapi.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -58,8 +57,6 @@ extern const WCHAR szRemoveFiles[];
static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0}; static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
extern LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename );
/* /*
* This is a helper function for handling embedded cabinet media * This is a helper function for handling embedded cabinet media
*/ */
@ -96,7 +93,7 @@ static UINT writeout_cabinet_stream(MSIPACKAGE *package, LPCWSTR stream_name,
WriteFile(the_file,data,size,&write,NULL); WriteFile(the_file,data,size,&write,NULL);
CloseHandle(the_file); CloseHandle(the_file);
TRACE("wrote %li bytes to %s\n",write,debugstr_w(source)); TRACE("wrote %i bytes to %s\n",write,debugstr_w(source));
end: end:
msi_free(data); msi_free(data);
return rc; return rc;
@ -242,7 +239,7 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
NULL, CREATE_ALWAYS, attrs, NULL ); NULL, CREATE_ALWAYS, attrs, NULL );
if ( handle == INVALID_HANDLE_VALUE ) if ( handle == INVALID_HANDLE_VALUE )
{ {
ERR("failed to create %s (error %ld)\n", ERR("failed to create %s (error %d)\n",
debugstr_w( f->TargetPath ), GetLastError() ); debugstr_w( f->TargetPath ), GetLastError() );
return 0; return 0;
} }
@ -793,7 +790,7 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
rc = ERROR_SUCCESS; rc = ERROR_SUCCESS;
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
ERR("Failed to copy file %s -> %s, last error %ld\n", ERR("Failed to copy file %s -> %s, last error %d\n",
debugstr_w(file->TargetPath), debugstr_w(dest_path), GetLastError()); debugstr_w(file->TargetPath), debugstr_w(dest_path), GetLastError());
FIXME("We should track these duplicate files as well\n"); FIXME("We should track these duplicate files as well\n");

View file

@ -26,7 +26,6 @@
#include "wine/debug.h" #include "wine/debug.h"
#include "msipriv.h" #include "msipriv.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);

View file

@ -36,7 +36,6 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/msifo
#include "msipriv.h" #include "msipriv.h"
#include "winnls.h" #include "winnls.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -471,7 +470,7 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr,
TRACE("after value %s\n", debugstr_wn((LPWSTR)newdata, TRACE("after value %s\n", debugstr_wn((LPWSTR)newdata,
size/sizeof(WCHAR))); size/sizeof(WCHAR)));
chunk = (len - (progress - ptr)) * sizeof(WCHAR); chunk = (len - (progress - ptr)) * sizeof(WCHAR);
TRACE("after chunk is %li + %li\n",size,chunk); TRACE("after chunk is %i + %i\n",size,chunk);
if (size) if (size)
nd2 = msi_realloc(newdata,(size+chunk)); nd2 = msi_realloc(newdata,(size+chunk));
else else
@ -583,7 +582,7 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr,
if (value!=NULL) if (value!=NULL)
{ {
LPBYTE nd2; LPBYTE nd2;
TRACE("value %s, chunk %li size %li\n",debugstr_w((LPWSTR)value), TRACE("value %s, chunk %i size %i\n",debugstr_w((LPWSTR)value),
chunk, size); chunk, size);
if (size) if (size)
nd2= msi_realloc(newdata,(size + chunk)); nd2= msi_realloc(newdata,(size + chunk));
@ -616,7 +615,7 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
DWORD len; DWORD len;
UINT rc = ERROR_INVALID_PARAMETER; UINT rc = ERROR_INVALID_PARAMETER;
TRACE("%p %p %p %li\n",package, record ,buffer, *size); TRACE("%p %p %p %i\n", package, record ,buffer, *size);
rec = msi_dup_record_field(record,0); rec = msi_dup_record_field(record,0);
if (!rec) if (!rec)
@ -663,7 +662,7 @@ UINT MSI_FormatRecordA( MSIPACKAGE* package, MSIRECORD* record, LPSTR buffer,
DWORD len,lenA; DWORD len,lenA;
UINT rc = ERROR_INVALID_PARAMETER; UINT rc = ERROR_INVALID_PARAMETER;
TRACE("%p %p %p %li\n",package, record ,buffer, *size); TRACE("%p %p %p %i\n", package, record ,buffer, *size);
rec = msi_dup_record_field(record,0); rec = msi_dup_record_field(record,0);
if (!rec) if (!rec)

View file

@ -33,7 +33,7 @@
#include "msipriv.h" #include "msipriv.h"
#include "winuser.h" #include "winuser.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h" #include "msidefs.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -41,6 +41,7 @@ static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0}; static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0}; const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
const WCHAR cszSOURCEDIR[] = {'S','O','U','R','C','E','D','I','R',0};
const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0}; const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
const WCHAR cszbs[]={'\\',0}; const WCHAR cszbs[]={'\\',0};
@ -217,10 +218,14 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
if (!name) if (!name)
return NULL; return NULL;
f = get_loaded_folder( package, name );
if (!f)
return NULL;
/* special resolving for Target and Source root dir */ /* special resolving for Target and Source root dir */
if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0) if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
{ {
if (!source) if (!f->ResolvedTarget && !f->Property)
{ {
LPWSTR check_path; LPWSTR check_path;
check_path = msi_dup_property( package, cszTargetDir ); check_path = msi_dup_property( package, cszTargetDir );
@ -237,17 +242,13 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
if (strcmpiW(path,check_path)!=0) if (strcmpiW(path,check_path)!=0)
MSI_SetPropertyW(package,cszTargetDir,path); MSI_SetPropertyW(package,cszTargetDir,path);
msi_free(check_path); msi_free(check_path);
}
else f->ResolvedTarget = path;
path = get_source_root( package );
if (folder)
*folder = get_loaded_folder( package, name );
return path;
} }
f = get_loaded_folder( package, name ); if (!f->ResolvedSource)
if (!f) f->ResolvedSource = get_source_root( package );
return NULL; }
if (folder) if (folder)
*folder = f; *folder = f;
@ -405,6 +406,13 @@ static void free_feature( MSIFEATURE *feature )
{ {
struct list *item, *cursor; struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
{
FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
list_remove( &fl->entry );
msi_free( fl );
}
LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
{ {
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
@ -419,7 +427,7 @@ static void free_feature( MSIFEATURE *feature )
msi_free( feature ); msi_free( feature );
} }
void free_extension( MSIEXTENSION *ext ) static void free_extension( MSIEXTENSION *ext )
{ {
struct list *item, *cursor; struct list *item, *cursor;
@ -843,6 +851,9 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
newstate = feature->ActionRequest; newstate = feature->ActionRequest;
if (newstate == INSTALLSTATE_ABSENT)
newstate = INSTALLSTATE_UNKNOWN;
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry ) LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{ {
MSICOMPONENT* component = cl->component; MSICOMPONENT* component = cl->component;
@ -870,20 +881,43 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
/*if any other feature wants is local we need to set it local*/ /*if any other feature wants is local we need to set it local*/
LIST_FOR_EACH_ENTRY( f, &package->features, MSIFEATURE, entry ) LIST_FOR_EACH_ENTRY( f, &package->features, MSIFEATURE, entry )
{ {
if ( component->ActionRequest != INSTALLSTATE_LOCAL ) if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
break; f->ActionRequest != INSTALLSTATE_SOURCE )
{
continue;
}
LIST_FOR_EACH_ENTRY( clist, &f->Components, ComponentList, entry ) LIST_FOR_EACH_ENTRY( clist, &f->Components, ComponentList, entry )
{ {
if ( clist->component == component ) if ( clist->component == component &&
{ (f->ActionRequest == INSTALLSTATE_LOCAL ||
if (f->ActionRequest == INSTALLSTATE_LOCAL) f->ActionRequest == INSTALLSTATE_SOURCE) )
{ {
TRACE("Saved by %s\n", debugstr_w(f->Feature)); TRACE("Saved by %s\n", debugstr_w(f->Feature));
component->ActionRequest = INSTALLSTATE_LOCAL;
component->Action = INSTALLSTATE_LOCAL; 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;
} }
break;
} }
} }
} }

View file

@ -78,7 +78,7 @@ static MSIRECORD *INSERT_merge_record( UINT fields, column_info *vl, MSIRECORD *
switch( vl->val->type ) switch( vl->val->type )
{ {
case EXPR_SVAL: case EXPR_SVAL:
TRACE("field %ld -> %s\n", i, debugstr_w(vl->val->u.sval)); TRACE("field %d -> %s\n", i, debugstr_w(vl->val->u.sval));
MSI_RecordSetStringW( merged, i, vl->val->u.sval ); MSI_RecordSetStringW( merged, i, vl->val->u.sval );
break; break;
case EXPR_IVAL: case EXPR_IVAL:

View file

@ -30,7 +30,6 @@
#include "msi.h" #include "msi.h"
#include "msidefs.h" #include "msidefs.h"
#include "msipriv.h" #include "msipriv.h"
#include "action.h"
#include "wine/unicode.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -138,7 +137,7 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
if (len) if (len)
len--; len--;
WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL ); WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
if ( *sz && (len >= *sz) ) if ( awbuf->str.a && *sz && (len >= *sz) )
awbuf->str.a[*sz - 1] = 0; awbuf->str.a[*sz - 1] = 0;
} }
@ -151,7 +150,7 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
/*********************************************************************** /***********************************************************************
* MsiGetTargetPath (internal) * MsiGetTargetPath (internal)
*/ */
UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder, static UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
awstring *szPathBuf, DWORD* pcchPathBuf ) awstring *szPathBuf, DWORD* pcchPathBuf )
{ {
MSIPACKAGE *package; MSIPACKAGE *package;

View file

@ -40,7 +40,6 @@
#include "shobjidl.h" #include "shobjidl.h"
#include "objidl.h" #include "objidl.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -151,7 +150,7 @@ UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath
UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
{ {
FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_a(szPackagePath), FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
debugstr_a(szScriptfilePath), debugstr_a(szTransforms), debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
lgidLanguage, dwPlatform, dwOptions); lgidLanguage, dwPlatform, dwOptions);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
@ -160,7 +159,7 @@ UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath
UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
{ {
FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_w(szPackagePath), FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
debugstr_w(szScriptfilePath), debugstr_w(szTransforms), debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
lgidLanguage, dwPlatform, dwOptions); lgidLanguage, dwPlatform, dwOptions);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
@ -215,13 +214,13 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode) UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
{ {
FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode); FIXME("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode) UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
{ {
FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode); FIXME("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
@ -432,7 +431,7 @@ UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
awstring *szValue, DWORD *pcchValueBuf) awstring *szValue, DWORD *pcchValueBuf)
{ {
UINT r; UINT r;
@ -590,7 +589,7 @@ UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
LPWSTR szwLogFile = NULL; LPWSTR szwLogFile = NULL;
UINT r; UINT r;
TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes); TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
if( szLogFile ) if( szLogFile )
{ {
@ -607,7 +606,7 @@ UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
{ {
HANDLE file = INVALID_HANDLE_VALUE; HANDLE file = INVALID_HANDLE_VALUE;
TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes); TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
if (szLogFile) if (szLogFile)
{ {
@ -709,7 +708,7 @@ INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
{ {
INSTALLUI_HANDLERA prev = gUIHandlerA; INSTALLUI_HANDLERA prev = gUIHandlerA;
TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext); TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
gUIHandlerA = puiHandler; gUIHandlerA = puiHandler;
gUIFilter = dwMessageFilter; gUIFilter = dwMessageFilter;
gUIContext = pvContext; gUIContext = pvContext;
@ -722,7 +721,7 @@ INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
{ {
INSTALLUI_HANDLERW prev = gUIHandlerW; INSTALLUI_HANDLERW prev = gUIHandlerW;
TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext); TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
gUIHandlerW = puiHandler; gUIHandlerW = puiHandler;
gUIFilter = dwMessageFilter; gUIFilter = dwMessageFilter;
gUIContext = pvContext; gUIContext = pvContext;
@ -848,16 +847,16 @@ INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
WORD wLanguageId, DWORD f) WORD wLanguageId, DWORD f)
{ {
FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption), FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
uType,wLanguageId,f); uType, wLanguageId, f);
return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId); return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
} }
UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
WORD wLanguageId, DWORD f) WORD wLanguageId, DWORD f)
{ {
FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption), FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
uType,wLanguageId,f); uType, wLanguageId, f);
return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId); return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
} }
@ -865,7 +864,7 @@ UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
DWORD* pcchPathBuf ) DWORD* pcchPathBuf )
{ {
FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName), FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
pcchPathBuf); pcchPathBuf);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
@ -875,7 +874,7 @@ UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
DWORD* pcchPathBuf ) DWORD* pcchPathBuf )
{ {
FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName), FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
pcchPathBuf); pcchPathBuf);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
@ -899,7 +898,7 @@ HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
DWORD* pcbHashData) DWORD* pcbHashData)
{ {
FIXME("%s %08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
ppcCertContext, pbHashData, pcbHashData); ppcCertContext, pbHashData, pcbHashData);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
@ -908,7 +907,7 @@ HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
DWORD* pcbHashData) DWORD* pcbHashData)
{ {
FIXME("%s %08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
ppcCertContext, pbHashData, pcbHashData); ppcCertContext, pbHashData, pcbHashData);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
@ -961,7 +960,7 @@ UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
return r; return r;
} }
INSTALLSTATE WINAPI MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, static INSTALLSTATE WINAPI MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
awstring* lpPathBuf, DWORD* pcchBuf) awstring* lpPathBuf, DWORD* pcchBuf)
{ {
WCHAR squished_pc[GUID_SIZE], squished_comp[GUID_SIZE]; WCHAR squished_pc[GUID_SIZE], squished_comp[GUID_SIZE];
@ -1244,7 +1243,7 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
UINT puLen; UINT puLen;
WCHAR tmp[32]; WCHAR tmp[32];
TRACE("%s %p %ld %p %ld\n", debugstr_w(szFilePath), TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0, lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
lpLangBuf, pcchLangBuf?*pcchLangBuf:0); lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
@ -1345,7 +1344,7 @@ INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
{ {
INSTALLSTATE state; INSTALLSTATE state;
TRACE("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature), TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
dwInstallMode, dwReserved); dwInstallMode, dwReserved);
state = MsiQueryFeatureStateW( szProduct, szFeature ); state = MsiQueryFeatureStateW( szProduct, szFeature );
@ -1371,7 +1370,7 @@ INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
INSTALLSTATE ret = INSTALLSTATE_UNKNOWN; INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
LPWSTR prod = NULL, feat = NULL; LPWSTR prod = NULL, feat = NULL;
TRACE("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature), TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
dwInstallMode, dwReserved); dwInstallMode, dwReserved);
prod = strdupAtoW( szProduct ); prod = strdupAtoW( szProduct );
@ -1410,7 +1409,7 @@ INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
/*********************************************************************** /***********************************************************************
* MSI_ProvideQualifiedComponentEx [internal] * MSI_ProvideQualifiedComponentEx [internal]
*/ */
UINT WINAPI MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent, static UINT WINAPI MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct, LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
DWORD Unused1, DWORD Unused2, awstring *lpPathBuf, DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
DWORD* pcchPathBuf) DWORD* pcchPathBuf)
@ -1422,7 +1421,7 @@ UINT WINAPI MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
DWORD sz; DWORD sz;
UINT rc; UINT rc;
TRACE("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent), TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct), debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
Unused1, Unused2, lpPathBuf, pcchPathBuf); Unused1, Unused2, lpPathBuf, pcchPathBuf);
@ -1480,7 +1479,7 @@ UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
UINT r = ERROR_OUTOFMEMORY; UINT r = ERROR_OUTOFMEMORY;
awstring path; awstring path;
TRACE("%s %s %lu %s %lu %lu %p %p\n", debugstr_a(szComponent), TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct), debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
Unused1, Unused2, lpPathBuf, pcchPathBuf); Unused1, Unused2, lpPathBuf, pcchPathBuf);
@ -1535,7 +1534,7 @@ UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
/*********************************************************************** /***********************************************************************
* MSI_GetUserInfo [internal] * MSI_GetUserInfo [internal]
*/ */
USERINFOSTATE WINAPI MSI_GetUserInfo(LPCWSTR szProduct, static USERINFOSTATE WINAPI MSI_GetUserInfo(LPCWSTR szProduct,
awstring *lpUserNameBuf, DWORD* pcchUserNameBuf, awstring *lpUserNameBuf, DWORD* pcchUserNameBuf,
awstring *lpOrgNameBuf, DWORD* pcchOrgNameBuf, awstring *lpOrgNameBuf, DWORD* pcchOrgNameBuf,
awstring *lpSerialBuf, DWORD* pcchSerialBuf) awstring *lpSerialBuf, DWORD* pcchSerialBuf)
@ -1775,11 +1774,11 @@ UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
{ {
WCHAR path[MAX_PATH]; WCHAR path[MAX_PATH];
TRACE("%ld\n", dwReserved); TRACE("%d\n", dwReserved);
if (dwReserved) if (dwReserved)
{ {
FIXME("dwReserved=%ld\n", dwReserved); FIXME("dwReserved=%d\n", dwReserved);
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
} }
@ -1896,7 +1895,7 @@ UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
LPWSTR ptr; LPWSTR ptr;
DWORD sz; DWORD sz;
FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature), FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
dwReinstallMode); dwReinstallMode);
ptr = reinstallmode; ptr = reinstallmode;
@ -1960,7 +1959,7 @@ UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
LPWSTR wszFeature; LPWSTR wszFeature;
UINT rc; UINT rc;
TRACE("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature), TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
dwReinstallMode); dwReinstallMode);
wszProduct = strdupAtoW(szProduct); wszProduct = strdupAtoW(szProduct);
@ -1996,7 +1995,7 @@ UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
DWORD length; DWORD length;
UINT r = ERROR_FUNCTION_FAILED; UINT r = ERROR_FUNCTION_FAILED;
TRACE("%s %08lx %p\n", debugstr_w(szFilePath), dwOptions, pHash ); TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
if (dwOptions) if (dwOptions)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -2044,7 +2043,7 @@ UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
LPWSTR file; LPWSTR file;
UINT r; UINT r;
TRACE("%s %08lx %p\n", debugstr_a(szFilePath), dwOptions, pHash ); TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
file = strdupAtoW( szFilePath ); file = strdupAtoW( szFilePath );
if (szFilePath && !file) if (szFilePath && !file)
@ -2061,7 +2060,7 @@ UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags, UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
PHKEY phRegData, BOOL fRemoveItems ) PHKEY phRegData, BOOL fRemoveItems )
{ {
FIXME("%s %08lx %p %d\n", FIXME("%s %08x %p %d\n",
debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems ); debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
@ -2072,7 +2071,7 @@ UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags, UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
PHKEY phRegData, BOOL fRemoveItems ) PHKEY phRegData, BOOL fRemoveItems )
{ {
FIXME("%s %08lx %p %d\n", FIXME("%s %08x %p %d\n",
debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems ); debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }

View file

@ -43,6 +43,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#include "msi_Ru.rc" #include "msi_Ru.rc"
#include "msi_Tr.rc" #include "msi_Tr.rc"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
/* BINRES instadvert.bmp */ /* BINRES instadvert.bmp */
0x1001 BITMAP instadvert.bmp 0x1001 BITMAP instadvert.bmp
/* { /* {

View file

@ -1,7 +1,7 @@
/* /*
* Spanish resources for MSI * Spanish resources for MSI
* *
* Copyright 2005 José Manuel Ferrer Ortiz * Copyright 2005, 2006 José Manuel Ferrer Ortiz
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -22,7 +22,7 @@ LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE STRINGTABLE DISCARDABLE
{ {
4 "The specified installation package could not be opened. Please check the file path and try again." 4 "No se ha podido abrir el paquete de instalación especificado. Por favor, compruebe la ruta del archivo y vuelva a intentarlo."
5 "ruta %s no encontrada" 5 "ruta %s no encontrada"
9 "inserte el disco %s" 9 "inserte el disco %s"
10 "parámetros incorrectos" 10 "parámetros incorrectos"

View file

@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT LANGUAGE LANG_KOREAN, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE STRINGTABLE DISCARDABLE
{ {

View file

@ -2,6 +2,7 @@
* Implementation of the Microsoft Installer (msi.dll) * Implementation of the Microsoft Installer (msi.dll)
* *
* Copyright 2002-2005 Mike McCormack for CodeWeavers * Copyright 2002-2005 Mike McCormack for CodeWeavers
* Copyright 2005 Aric Stewart for CodeWeavers
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -71,6 +72,7 @@ typedef struct tagMSIDATABASE
MSIOBJECTHDR hdr; MSIOBJECTHDR hdr;
IStorage *storage; IStorage *storage;
string_table *strings; string_table *strings;
LPWSTR path;
LPWSTR deletefile; LPWSTR deletefile;
LPCWSTR mode; LPCWSTR mode;
struct list tables; struct list tables;
@ -259,6 +261,221 @@ typedef struct tagMSISUMMARYINFO
PROPVARIANT property[MSI_MAX_PROPS]; PROPVARIANT property[MSI_MAX_PROPS];
} MSISUMMARYINFO; } MSISUMMARYINFO;
typedef struct tagMSIFEATURE
{
struct list entry;
LPWSTR Feature;
LPWSTR Feature_Parent;
LPWSTR Title;
LPWSTR Description;
INT Display;
INT Level;
LPWSTR Directory;
INT Attributes;
INSTALLSTATE Installed;
INSTALLSTATE ActionRequest;
INSTALLSTATE Action;
struct list Children;
struct list Components;
INT Cost;
} MSIFEATURE;
typedef struct tagMSICOMPONENT
{
struct list entry;
DWORD magic;
LPWSTR Component;
LPWSTR ComponentId;
LPWSTR Directory;
INT Attributes;
LPWSTR Condition;
LPWSTR KeyPath;
INSTALLSTATE Installed;
INSTALLSTATE ActionRequest;
INSTALLSTATE Action;
BOOL ForceLocalState;
BOOL Enabled;
INT Cost;
INT RefCount;
LPWSTR FullKeypath;
LPWSTR AdvertiseString;
} MSICOMPONENT;
typedef struct tagComponentList
{
struct list entry;
MSICOMPONENT *component;
} ComponentList;
typedef struct tagFeatureList
{
struct list entry;
MSIFEATURE *feature;
} FeatureList;
typedef struct tagMSIFOLDER
{
struct list entry;
LPWSTR Directory;
LPWSTR TargetDefault;
LPWSTR SourceLongPath;
LPWSTR SourceShortPath;
LPWSTR ResolvedTarget;
LPWSTR ResolvedSource;
LPWSTR Property; /* initially set property */
struct tagMSIFOLDER *Parent;
INT State;
/* 0 = uninitialized */
/* 1 = existing */
/* 2 = created remove if empty */
/* 3 = created persist if empty */
INT Cost;
INT Space;
} MSIFOLDER;
typedef enum _msi_file_state {
msifs_invalid,
msifs_missing,
msifs_overwrite,
msifs_present,
msifs_installed,
msifs_skipped,
} msi_file_state;
typedef struct tagMSIFILE
{
struct list entry;
LPWSTR File;
MSICOMPONENT *Component;
LPWSTR FileName;
LPWSTR ShortName;
LPWSTR LongName;
INT FileSize;
LPWSTR Version;
LPWSTR Language;
INT Attributes;
INT Sequence;
msi_file_state state;
LPWSTR SourcePath;
LPWSTR TargetPath;
BOOL IsCompressed;
} MSIFILE;
typedef struct tagMSITEMPFILE
{
struct list entry;
LPWSTR File;
LPWSTR Path;
} MSITEMPFILE;
typedef struct tagMSIAPPID
{
struct list entry;
LPWSTR AppID; /* Primary key */
LPWSTR RemoteServerName;
LPWSTR LocalServer;
LPWSTR ServiceParameters;
LPWSTR DllSurrogate;
BOOL ActivateAtStorage;
BOOL RunAsInteractiveUser;
} MSIAPPID;
typedef struct tagMSIPROGID MSIPROGID;
typedef struct tagMSICLASS
{
struct list entry;
LPWSTR clsid; /* Primary Key */
LPWSTR Context; /* Primary Key */
MSICOMPONENT *Component;
MSIPROGID *ProgID;
LPWSTR ProgIDText;
LPWSTR Description;
MSIAPPID *AppID;
LPWSTR FileTypeMask;
LPWSTR IconPath;
LPWSTR DefInprocHandler;
LPWSTR DefInprocHandler32;
LPWSTR Argument;
MSIFEATURE *Feature;
INT Attributes;
/* not in the table, set during installation */
BOOL Installed;
} MSICLASS;
typedef struct tagMSIMIME MSIMIME;
typedef struct tagMSIEXTENSION
{
struct list entry;
LPWSTR Extension; /* Primary Key */
MSICOMPONENT *Component;
MSIPROGID *ProgID;
LPWSTR ProgIDText;
MSIMIME *Mime;
MSIFEATURE *Feature;
/* not in the table, set during installation */
BOOL Installed;
struct list verbs;
} MSIEXTENSION;
struct tagMSIPROGID
{
struct list entry;
LPWSTR ProgID; /* Primary Key */
MSIPROGID *Parent;
MSICLASS *Class;
LPWSTR Description;
LPWSTR IconPath;
/* not in the table, set during installation */
BOOL InstallMe;
MSIPROGID *CurVer;
MSIPROGID *VersionInd;
};
typedef struct tagMSIVERB
{
struct list entry;
LPWSTR Verb;
INT Sequence;
LPWSTR Command;
LPWSTR Argument;
} MSIVERB;
struct tagMSIMIME
{
struct list entry;
LPWSTR ContentType; /* Primary Key */
MSIEXTENSION *Extension;
LPWSTR clsid;
MSICLASS *Class;
/* not in the table, set during installation */
BOOL InstallMe;
};
enum SCRIPTS {
INSTALL_SCRIPT = 0,
COMMIT_SCRIPT = 1,
ROLLBACK_SCRIPT = 2,
TOTAL_SCRIPTS = 3
};
#define SEQUENCE_UI 0x1
#define SEQUENCE_EXEC 0x2
#define SEQUENCE_INSTALL 0x10
typedef struct tagMSISCRIPT
{
LPWSTR *Actions[TOTAL_SCRIPTS];
UINT ActionCount[TOTAL_SCRIPTS];
BOOL ExecuteSequenceRun;
BOOL CurrentlyScripting;
UINT InWhatSequence;
LPWSTR *UniqueActions;
UINT UniqueActionsCount;
} MSISCRIPT;
#define MSIHANDLETYPE_ANY 0 #define MSIHANDLETYPE_ANY 0
#define MSIHANDLETYPE_DATABASE 1 #define MSIHANDLETYPE_DATABASE 1
#define MSIHANDLETYPE_SUMMARYINFO 2 #define MSIHANDLETYPE_SUMMARYINFO 2
@ -324,7 +541,6 @@ extern BOOL msi_addstringW( string_table *st, UINT string_no, const WCHAR *data,
extern UINT msi_id2stringW( string_table *st, UINT string_no, LPWSTR buffer, UINT *sz ); extern UINT msi_id2stringW( string_table *st, UINT string_no, LPWSTR buffer, UINT *sz );
extern UINT msi_id2stringA( string_table *st, UINT string_no, LPSTR buffer, UINT *sz ); extern UINT msi_id2stringA( string_table *st, UINT string_no, LPSTR buffer, UINT *sz );
extern LPWSTR MSI_makestring( MSIDATABASE *db, UINT stringid);
extern UINT msi_string2idW( string_table *st, LPCWSTR buffer, UINT *id ); extern UINT msi_string2idW( string_table *st, LPCWSTR buffer, UINT *id );
extern UINT msi_string2idA( string_table *st, LPCSTR str, UINT *id ); extern UINT msi_string2idA( string_table *st, LPCSTR str, UINT *id );
extern string_table *msi_init_stringtable( int entries, UINT codepage ); extern string_table *msi_init_stringtable( int entries, UINT codepage );
@ -414,6 +630,7 @@ extern MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *, LPCWSTR );
extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * ); extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * );
extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * ); extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * );
extern UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE*, LPCWSTR, INSTALLSTATE ); extern UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE*, LPCWSTR, INSTALLSTATE );
extern LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename );
/* for deformating */ /* for deformating */
extern UINT MSI_FormatRecordW( MSIPACKAGE *, MSIRECORD *, LPWSTR, DWORD * ); extern UINT MSI_FormatRecordW( MSIPACKAGE *, MSIRECORD *, LPWSTR, DWORD * );
@ -450,7 +667,7 @@ extern LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWS
/* msi dialog interface */ /* msi dialog interface */
typedef UINT (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, msi_dialog* ); typedef UINT (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, msi_dialog* );
extern msi_dialog *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog_event_handler ); extern msi_dialog *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog*, msi_dialog_event_handler );
extern UINT msi_dialog_run_message_loop( msi_dialog* ); extern UINT msi_dialog_run_message_loop( msi_dialog* );
extern void msi_dialog_end_dialog( msi_dialog* ); extern void msi_dialog_end_dialog( msi_dialog* );
extern void msi_dialog_check_messages( HANDLE ); extern void msi_dialog_check_messages( HANDLE );
@ -461,6 +678,8 @@ extern void msi_dialog_unregister_class( void );
extern void msi_dialog_handle_event( msi_dialog*, LPCWSTR, LPCWSTR, MSIRECORD * ); extern void msi_dialog_handle_event( msi_dialog*, LPCWSTR, LPCWSTR, MSIRECORD * );
extern UINT msi_dialog_reset( msi_dialog *dialog ); extern UINT msi_dialog_reset( msi_dialog *dialog );
extern UINT msi_dialog_directorylist_up( msi_dialog *dialog ); extern UINT msi_dialog_directorylist_up( msi_dialog *dialog );
extern msi_dialog *msi_dialog_get_parent( msi_dialog *dialog );
extern LPWSTR msi_dialog_get_name( msi_dialog *dialog );
/* preview */ /* preview */
extern MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE * ); extern MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE * );
@ -487,6 +706,72 @@ extern LPVOID gUIContext;
extern WCHAR gszLogFile[MAX_PATH]; extern WCHAR gszLogFile[MAX_PATH];
extern HINSTANCE msi_hInstance; extern HINSTANCE msi_hInstance;
/* action related functions */
extern UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force);
extern UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action);
extern void ACTION_FinishCustomActions( MSIPACKAGE* package);
extern UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute);
/* actions in other modules */
extern UINT ACTION_AppSearch(MSIPACKAGE *package);
extern UINT ACTION_FindRelatedProducts(MSIPACKAGE *package);
extern UINT ACTION_InstallFiles(MSIPACKAGE *package);
extern UINT ACTION_RemoveFiles(MSIPACKAGE *package);
extern UINT ACTION_DuplicateFiles(MSIPACKAGE *package);
extern UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterFonts(MSIPACKAGE *package);
/* Helpers */
extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
extern LPWSTR msi_dup_record_field(MSIRECORD *row, INT index);
extern LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop);
extern int msi_get_property_int( MSIPACKAGE *package, LPCWSTR prop, int def );
extern LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
BOOL set_prop, MSIFOLDER **folder);
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
extern MSIFEATURE *get_loaded_feature( MSIPACKAGE* package, LPCWSTR Feature );
extern MSIFILE *get_loaded_file( MSIPACKAGE* package, LPCWSTR file );
extern MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir );
extern int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
extern UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action);
extern LPWSTR build_icon_path(MSIPACKAGE *, LPCWSTR);
extern LPWSTR build_directory_name(DWORD , ...);
extern BOOL create_full_pathW(const WCHAR *path);
extern BOOL ACTION_VerifyComponentForAction(MSICOMPONENT*, INSTALLSTATE);
extern BOOL ACTION_VerifyFeatureForAction(MSIFEATURE*, INSTALLSTATE);
extern void reduce_to_longfilename(WCHAR*);
extern void reduce_to_shortfilename(WCHAR*);
extern LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
extern UINT register_unique_action(MSIPACKAGE *, LPCWSTR);
extern BOOL check_unique_action(MSIPACKAGE *, LPCWSTR);
extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
extern UINT msi_create_component_directories( MSIPACKAGE *package );
extern void msi_ui_error( DWORD msg_id, DWORD type );
/* control event stuff */
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
MSIRECORD *data);
extern VOID ControlEvent_CleanupSubscriptions(MSIPACKAGE *package);
extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, msi_dialog *dialog,
LPCWSTR event, LPCWSTR control, LPCWSTR attribute);
extern VOID ControlEvent_UnSubscribeToEvent( MSIPACKAGE *package, LPCWSTR event,
LPCWSTR control, LPCWSTR attribute );
/* User Interface messages from the actions */
extern void ui_progress(MSIPACKAGE *, int, int, int, int);
extern void ui_actiondata(MSIPACKAGE *, LPCWSTR, MSIRECORD *);
/* string consts use a number of places and defined in helpers.c*/
extern const WCHAR cszSourceDir[];
extern const WCHAR cszSOURCEDIR[];
extern const WCHAR szProductCode[];
extern const WCHAR cszRootDrive[];
extern const WCHAR cszbs[];
/* memory allocation macro functions */ /* memory allocation macro functions */
static inline void *msi_alloc( size_t len ) static inline void *msi_alloc( size_t len )
{ {

View file

@ -37,6 +37,8 @@
#include "query.h" #include "query.h"
#include "initguid.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
static void MSI_CloseView( MSIOBJECTHDR *arg ) static void MSI_CloseView( MSIOBJECTHDR *arg )
@ -314,11 +316,10 @@ UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
if( type & MSITYPE_STRING ) if( type & MSITYPE_STRING )
{ {
LPWSTR sval; LPCWSTR sval;
sval = MSI_makestring( query->db, ival ); sval = msi_string_lookup_id( query->db->strings, ival );
MSI_RecordSetStringW( rec, i, sval ); MSI_RecordSetStringW( rec, i, sval );
msi_free( sval );
} }
else else
{ {
@ -665,24 +666,34 @@ DEFINE_GUID( CLSID_MsiTransform, 0x000c1082, 0x0000, 0x0000, 0xc0,0x00,0x00,0x00
UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db, UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db,
LPCWSTR szTransformFile, int iErrorCond ) LPCWSTR szTransformFile, int iErrorCond )
{ {
UINT r; HRESULT r;
UINT ret = ERROR_FUNCTION_FAILED;
IStorage *stg = NULL; IStorage *stg = NULL;
STATSTG stat;
TRACE("%p %s %d\n", db, debugstr_w(szTransformFile), iErrorCond); TRACE("%p %s %d\n", db, debugstr_w(szTransformFile), iErrorCond);
r = StgOpenStorage( szTransformFile, NULL, r = StgOpenStorage( szTransformFile, NULL,
STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg); STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
if( r ) if ( FAILED(r) )
return r; return ret;
r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
if ( FAILED( r ) )
goto end;
if ( !IsEqualGUID( &stat.clsid, &CLSID_MsiTransform ) )
goto end;
if( TRACE_ON( msi ) ) if( TRACE_ON( msi ) )
enum_stream_names( stg ); enum_stream_names( stg );
r = msi_table_apply_transform( db, stg ); ret = msi_table_apply_transform( db, stg );
end:
IStorage_Release( stg ); IStorage_Release( stg );
return r; return ret;
} }
UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb, UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
@ -814,7 +825,7 @@ UINT MSI_DatabaseGetPrimaryKeys( MSIDATABASE *db,
r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info ); r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info );
if( r == ERROR_SUCCESS ) if( r == ERROR_SUCCESS )
{ {
TRACE("Found %ld primary keys\n", info.n ); TRACE("Found %d primary keys\n", info.n );
/* allocate a record and fill in the names of the tables */ /* allocate a record and fill in the names of the tables */
info.rec = MSI_CreateRecord( info.n ); info.rec = MSI_CreateRecord( info.n );

View file

@ -43,12 +43,9 @@
#include "msidefs.h" #include "msidefs.h"
#include "msipriv.h" #include "msipriv.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
extern void msi_ui_error( DWORD msg_id, DWORD type );
static void msi_free_properties( MSIPACKAGE *package ); static void msi_free_properties( MSIPACKAGE *package );
static void MSI_FreePackage( MSIOBJECTHDR *arg) static void MSI_FreePackage( MSIOBJECTHDR *arg)
@ -144,6 +141,9 @@ static VOID set_installer_properties(MSIPACKAGE *package)
DWORD verval; DWORD verval;
WCHAR verstr[10], bufstr[20]; WCHAR verstr[10], bufstr[20];
HDC dc; HDC dc;
LPWSTR check;
HKEY hkey;
LONG res;
static const WCHAR cszbs[]={'\\',0}; static const WCHAR cszbs[]={'\\',0};
static const WCHAR CFF[] = static const WCHAR CFF[] =
@ -213,6 +213,18 @@ static VOID set_installer_properties(MSIPACKAGE *package)
static const WCHAR szScreenFormat[] = {'%','d',0}; static const WCHAR szScreenFormat[] = {'%','d',0};
static const WCHAR szIntel[] = { 'I','n','t','e','l',0 }; static const WCHAR szIntel[] = { 'I','n','t','e','l',0 };
static const WCHAR szAllUsers[] = { 'A','L','L','U','S','E','R','S',0 }; static const WCHAR szAllUsers[] = { 'A','L','L','U','S','E','R','S',0 };
static const WCHAR szCurrentVersion[] = {
'S','O','F','T','W','A','R','E','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s',' ','N','T','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
};
static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0};
static const WCHAR szRegisteredOrg[] = {
'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0
};
static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0};
static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
SYSTEM_INFO sys_info; SYSTEM_INFO sys_info;
/* /*
@ -356,6 +368,32 @@ static VOID set_installer_properties(MSIPACKAGE *package)
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL )); sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
MSI_SetPropertyW( package, szColorBits, bufstr ); MSI_SetPropertyW( package, szColorBits, bufstr );
ReleaseDC(0, dc); ReleaseDC(0, dc);
/* USERNAME and COMPANYNAME */
res = RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey );
if (res != ERROR_SUCCESS)
return;
check = msi_dup_property( package, szUSERNAME );
if (!check)
{
LPWSTR user = msi_reg_get_val_str( hkey, szRegisteredUser );
MSI_SetPropertyW( package, szUSERNAME, user );
msi_free( user );
}
msi_free( check );
check = msi_dup_property( package, szCOMPANYNAME );
if (!check)
{
LPWSTR company = msi_reg_get_val_str( hkey, szRegisteredOrg );
MSI_SetPropertyW( package, szCOMPANYNAME, company );
msi_free( company );
}
msi_free( check );
CloseHandle( hkey );
} }
static UINT msi_get_word_count( MSIPACKAGE *package ) static UINT msi_get_word_count( MSIPACKAGE *package )
@ -427,6 +465,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
list_init( &package->RunningActions ); list_init( &package->RunningActions );
package->WordCount = msi_get_word_count( package ); package->WordCount = msi_get_word_count( package );
package->PackagePath = strdupW( db->path );
/* OK, here is where we do a slew of things to the database to /* OK, here is where we do a slew of things to the database to
* prep for all that is to come as a package */ * prep for all that is to come as a package */
@ -513,6 +552,10 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
MSIHANDLE handle; MSIHANDLE handle;
UINT r; UINT r;
static const WCHAR OriginalDatabase[] =
{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
TRACE("%s %p\n", debugstr_w(szPackage), pPackage); TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
if( szPackage[0] == '#' ) if( szPackage[0] == '#' )
@ -551,20 +594,16 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
if( !package ) if( !package )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
/*
* FIXME: I don't think this is right. Maybe we should be storing the
* name of the database in the MSIDATABASE structure and fetching this
* info from there, or maybe this is only relevant to cached databases.
*/
if( szPackage[0] != '#' ) if( szPackage[0] != '#' )
{ {
static const WCHAR OriginalDatabase[] =
{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
MSI_SetPropertyW( package, OriginalDatabase, szPackage ); MSI_SetPropertyW( package, OriginalDatabase, szPackage );
MSI_SetPropertyW( package, Database, szPackage ); MSI_SetPropertyW( package, Database, szPackage );
} }
else
{
MSI_SetPropertyW( package, OriginalDatabase, db->path );
MSI_SetPropertyW( package, Database, db->path );
}
*pPackage = package; *pPackage = package;
@ -576,13 +615,13 @@ UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phP
MSIPACKAGE *package = NULL; MSIPACKAGE *package = NULL;
UINT ret; UINT ret;
TRACE("%s %08lx %p\n", debugstr_w(szPackage), dwOptions, phPackage ); TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage );
if( szPackage == NULL ) if( szPackage == NULL )
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
if( dwOptions ) if( dwOptions )
FIXME("dwOptions %08lx not supported\n", dwOptions); FIXME("dwOptions %08x not supported\n", dwOptions);
ret = MSI_OpenPackageW( szPackage, &package ); ret = MSI_OpenPackageW( szPackage, &package );
if( ret == ERROR_SUCCESS ) if( ret == ERROR_SUCCESS )
@ -744,7 +783,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
} }
} }
TRACE("(%p %lx %lx %s)\n",gUIHandlerA, gUIFilter, log_type, TRACE("(%p %x %x %s)\n", gUIHandlerA, gUIFilter, log_type,
debugstr_w(message)); debugstr_w(message));
/* convert it to ASCII */ /* convert it to ASCII */
@ -1009,7 +1048,7 @@ UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName,
if ( *pchValueBuf <= len ) if ( *pchValueBuf <= len )
{ {
TRACE("have %lu, need %u -> ERROR_MORE_DATA\n", *pchValueBuf, len); TRACE("have %u, need %u -> ERROR_MORE_DATA\n", *pchValueBuf, len);
r = ERROR_MORE_DATA; r = ERROR_MORE_DATA;
} }
else else

View file

@ -103,7 +103,7 @@ UINT MSI_PreviewDialogW( MSIPREVIEW *preview, LPCWSTR szDialogName )
/* an empty name means we should just destroy the current preview dialog */ /* an empty name means we should just destroy the current preview dialog */
if( szDialogName ) if( szDialogName )
{ {
dialog = msi_dialog_create( preview->package, szDialogName, dialog = msi_dialog_create( preview->package, szDialogName, NULL,
preview_event_handler ); preview_event_handler );
if( dialog ) if( dialog )
msi_dialog_do_preview( dialog ); msi_dialog_do_preview( dialog );

View file

@ -641,7 +641,7 @@ static UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm)
ulSize.QuadPart = sz; ulSize.QuadPart = sz;
IStream_SetSize(*pstm, ulSize); IStream_SetSize(*pstm, ulSize);
TRACE("read %s, %ld bytes into IStream %p\n", debugstr_w(szFile), sz, *pstm); TRACE("read %s, %d bytes into IStream %p\n", debugstr_w(szFile), sz, *pstm);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View file

@ -335,7 +335,7 @@ LPWSTR msi_version_dword_to_str(DWORD version)
LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value ) LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
{ {
DWORD len = value ? (lstrlenW(value) + 1) * sizeof (WCHAR) : 0; DWORD len = value ? (lstrlenW(value) + 1) * sizeof (WCHAR) : 0;
return RegSetValueExW( hkey, name, 0, REG_SZ, (LPBYTE)value, len ); return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
} }
LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value ) LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
@ -343,7 +343,7 @@ LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
LPCWSTR p = value; LPCWSTR p = value;
while (*p) p += lstrlenW(p) + 1; while (*p) p += lstrlenW(p) + 1;
return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ, return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
(LPBYTE)value, (p + 1 - value) * sizeof(WCHAR) ); (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
} }
LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val ) LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
@ -687,7 +687,7 @@ UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
DWORD r; DWORD r;
WCHAR szwGuid[GUID_SIZE]; WCHAR szwGuid[GUID_SIZE];
TRACE("%ld %p\n",index,lpguid); TRACE("%d %p\n", index, lpguid);
if (NULL == lpguid) if (NULL == lpguid)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -704,7 +704,7 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
DWORD r; DWORD r;
WCHAR szKeyName[SQUISH_GUID_SIZE]; WCHAR szKeyName[SQUISH_GUID_SIZE];
TRACE("%ld %p\n",index,lpguid); TRACE("%d %p\n", index, lpguid);
if (NULL == lpguid) if (NULL == lpguid)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -728,7 +728,7 @@ UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE]; WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
LPWSTR szwProduct = NULL; LPWSTR szwProduct = NULL;
TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent); TRACE("%s %d %p %p\n", debugstr_a(szProduct), index, szFeature, szParent);
if( szProduct ) if( szProduct )
{ {
@ -757,7 +757,7 @@ UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
HKEY hkeyProduct = 0; HKEY hkeyProduct = 0;
DWORD r, sz; DWORD r, sz;
TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent); TRACE("%s %d %p %p\n", debugstr_w(szProduct), index, szFeature, szParent);
if( !szProduct ) if( !szProduct )
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -778,7 +778,7 @@ UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
DWORD r; DWORD r;
WCHAR szwGuid[GUID_SIZE]; WCHAR szwGuid[GUID_SIZE];
TRACE("%ld %p\n",index,lpguid); TRACE("%d %p\n", index, lpguid);
r = MsiEnumComponentsW(index, szwGuid); r = MsiEnumComponentsW(index, szwGuid);
if( r == ERROR_SUCCESS ) if( r == ERROR_SUCCESS )
@ -793,7 +793,7 @@ UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
DWORD r; DWORD r;
WCHAR szKeyName[SQUISH_GUID_SIZE]; WCHAR szKeyName[SQUISH_GUID_SIZE];
TRACE("%ld %p\n",index,lpguid); TRACE("%d %p\n", index, lpguid);
r = MSIREG_OpenComponents(&hkeyComponents); r = MSIREG_OpenComponents(&hkeyComponents);
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
@ -813,7 +813,7 @@ UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
WCHAR szwProduct[GUID_SIZE]; WCHAR szwProduct[GUID_SIZE];
LPWSTR szwComponent = NULL; LPWSTR szwComponent = NULL;
TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct); TRACE("%s %d %p\n", debugstr_a(szComponent), index, szProduct);
if( szComponent ) if( szComponent )
{ {
@ -840,7 +840,7 @@ UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
DWORD r, sz; DWORD r, sz;
WCHAR szValName[SQUISH_GUID_SIZE]; WCHAR szValName[SQUISH_GUID_SIZE];
TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct); TRACE("%s %d %p\n", debugstr_w(szComponent), index, szProduct);
r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE); r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE);
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
@ -856,7 +856,7 @@ UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
return r; return r;
} }
UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex, static UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
awstring *lpQualBuf, DWORD* pcchQual, awstring *lpQualBuf, DWORD* pcchQual,
awstring *lpAppBuf, DWORD* pcchAppBuf ) awstring *lpAppBuf, DWORD* pcchAppBuf )
{ {
@ -865,7 +865,7 @@ UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
UINT r, r2; UINT r, r2;
HKEY key; HKEY key;
TRACE("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf); lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
if (!szComponent) if (!szComponent)
@ -902,7 +902,7 @@ UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
if (type != REG_MULTI_SZ) if (type != REG_MULTI_SZ)
{ {
ERR("component data has wrong type (%ld)\n", type); ERR("component data has wrong type (%d)\n", type);
goto end; goto end;
} }
@ -925,7 +925,7 @@ UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
goto end; goto end;
continue; continue;
} }
ERR("should be enough data, but isn't %ld %ld\n", name_sz, val_sz ); ERR("should be enough data, but isn't %d %d\n", name_sz, val_sz );
goto end; goto end;
} }
@ -961,7 +961,7 @@ UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
LPWSTR comp; LPWSTR comp;
UINT r; UINT r;
TRACE("%s %08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, TRACE("%s %08x %p %p %p %p\n", debugstr_a(szComponent), iIndex,
lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
pcchApplicationDataBuf); pcchApplicationDataBuf);
@ -990,7 +990,7 @@ UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
{ {
awstring qual, appdata; awstring qual, appdata;
TRACE("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
pcchApplicationDataBuf); pcchApplicationDataBuf);
@ -1015,7 +1015,7 @@ UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
HKEY hkey; HKEY hkey;
WCHAR szKeyName[SQUISH_GUID_SIZE]; WCHAR szKeyName[SQUISH_GUID_SIZE];
TRACE("%s %lu %lu %p\n", debugstr_w(szUpgradeCode), dwReserved, TRACE("%s %u %u %p\n", debugstr_w(szUpgradeCode), dwReserved,
iProductIndex, lpProductBuf); iProductIndex, lpProductBuf);
if (NULL == szUpgradeCode) if (NULL == szUpgradeCode)
@ -1046,7 +1046,7 @@ UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
WCHAR productW[GUID_SIZE]; WCHAR productW[GUID_SIZE];
UINT r; UINT r;
TRACE("%s %lu %lu %p\n", debugstr_a(szUpgradeCode), dwReserved, TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
iProductIndex, lpProductBuf); iProductIndex, lpProductBuf);
if (szUpgradeCode) if (szUpgradeCode)
@ -1073,7 +1073,7 @@ UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex, UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
LPSTR lpPatchBuf, LPSTR lpTransformsBuf, DWORD* pcchTransformsBuf) LPSTR lpPatchBuf, LPSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
{ {
FIXME("%s %ld %p %p %p\n", debugstr_a(szProduct), FIXME("%s %d %p %p %p\n", debugstr_a(szProduct),
iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf); iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;
} }
@ -1084,7 +1084,7 @@ UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex, UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, DWORD* pcchTransformsBuf) LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
{ {
FIXME("%s %ld %p %p %p\n", debugstr_w(szProduct), FIXME("%s %d %p %p %p\n", debugstr_w(szProduct),
iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf); iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;
} }

View file

@ -285,7 +285,7 @@ static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int select_count_columns( column_info *col ) static int select_count_columns( column_info *col )
{ {
int n; int n;
for (n = 0; col; col = col->next) for (n = 0; col; col = col->next)

View file

@ -37,7 +37,6 @@
#include "winver.h" #include "winver.h"
#include "winuser.h" #include "winuser.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "action.h"
#include "sddl.h" #include "sddl.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -300,7 +299,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
HKEY sourcekey; HKEY sourcekey;
UINT rc; UINT rc;
TRACE("%s %s %x %lx %s %s\n", debugstr_w(szProduct), debugstr_w(szUserSid), TRACE("%s %s %x %x %s %s\n", debugstr_w(szProduct), debugstr_w(szUserSid),
dwContext, dwOptions, debugstr_w(szProperty), debugstr_w(szValue)); dwContext, dwOptions, debugstr_w(szProperty), debugstr_w(szValue));
if (!szProduct || lstrlenW(szProduct) > 39) if (!szProduct || lstrlenW(szProduct) > 39)
@ -334,7 +333,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
rc = OpenMediaSubkey(sourcekey, &key, FALSE); rc = OpenMediaSubkey(sourcekey, &key, FALSE);
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
rc = RegSetValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW, 0, rc = RegSetValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW, 0,
REG_SZ, (LPBYTE)szValue, size); REG_SZ, (const BYTE *)szValue, size);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
rc = ERROR_UNKNOWN_PROPERTY; rc = ERROR_UNKNOWN_PROPERTY;
RegCloseKey(key); RegCloseKey(key);
@ -346,7 +345,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
rc = OpenMediaSubkey(sourcekey, &key, FALSE); rc = OpenMediaSubkey(sourcekey, &key, FALSE);
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
rc = RegSetValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0, rc = RegSetValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0,
REG_SZ, (LPBYTE)szValue, size); REG_SZ, (const BYTE *)szValue, size);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
rc = ERROR_UNKNOWN_PROPERTY; rc = ERROR_UNKNOWN_PROPERTY;
RegCloseKey(key); RegCloseKey(key);
@ -369,7 +368,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
else if (dwOptions & MSISOURCETYPE_MEDIA) else if (dwOptions & MSISOURCETYPE_MEDIA)
typechar = 'm'; typechar = 'm';
else else
ERR("Unknown source type! 0x%lx\n",dwOptions); ERR("Unknown source type! %x\n", dwOptions);
size = (lstrlenW(szValue)+5)*sizeof(WCHAR); size = (lstrlenW(szValue)+5)*sizeof(WCHAR);
buffer = msi_alloc(size); buffer = msi_alloc(size);
@ -384,7 +383,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
{ {
DWORD size = lstrlenW(szValue)*sizeof(WCHAR); DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
REG_SZ, (LPBYTE)szValue, size); REG_SZ, (const BYTE *)szValue, size);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
rc = ERROR_UNKNOWN_PROPERTY; rc = ERROR_UNKNOWN_PROPERTY;
} }
@ -467,9 +466,8 @@ UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
UINT rc; UINT rc;
media_info source_struct; media_info source_struct;
TRACE("%s, %s, %x, %lx, %s, %li\n", debugstr_w(szProduct), TRACE("%s %s %x %x %s %i\n", debugstr_w(szProduct), debugstr_w(szUserSid),
debugstr_w(szUserSid), dwContext, dwOptions, debugstr_w(szSource), dwContext, dwOptions, debugstr_w(szSource), dwIndex);
dwIndex);
if (!szProduct) if (!szProduct)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -505,7 +503,7 @@ UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
rc = OpenMediaSubkey(sourcekey, &typekey, TRUE); rc = OpenMediaSubkey(sourcekey, &typekey, TRUE);
else else
{ {
ERR("unknown media type: %08lx\n", dwOptions); ERR("unknown media type: %08x\n", dwOptions);
RegCloseKey(sourcekey); RegCloseKey(sourcekey);
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
@ -533,7 +531,7 @@ UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
current_index ++; current_index ++;
sprintfW(source_struct.szIndex,fmt,current_index); sprintfW(source_struct.szIndex,fmt,current_index);
rc = RegSetValueExW(typekey, source_struct.szIndex, 0, REG_EXPAND_SZ, rc = RegSetValueExW(typekey, source_struct.szIndex, 0, REG_EXPAND_SZ,
(LPBYTE)szSource, size); (const BYTE *)szSource, size);
} }
RegCloseKey(typekey); RegCloseKey(typekey);
@ -559,7 +557,7 @@ UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid,
LPWSTR buffer; LPWSTR buffer;
DWORD size; DWORD size;
TRACE("%s %s %x %lx %li %s %s\n", debugstr_w(szProduct), TRACE("%s %s %x %x %i %s %s\n", debugstr_w(szProduct),
debugstr_w(szUserSid), dwContext, dwOptions, dwDiskId, debugstr_w(szUserSid), dwContext, dwOptions, dwDiskId,
debugstr_w(szVolumeLabel), debugstr_w(szDiskPrompt)); debugstr_w(szVolumeLabel), debugstr_w(szDiskPrompt));
@ -625,7 +623,7 @@ UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid,
*/ */
UINT WINAPI MsiSourceListClearAllA( LPCSTR szProduct, LPCSTR szUserName, DWORD dwReserved ) UINT WINAPI MsiSourceListClearAllA( LPCSTR szProduct, LPCSTR szUserName, DWORD dwReserved )
{ {
FIXME("(%s %s %ld) stub\n", debugstr_a(szProduct), debugstr_a(szUserName), dwReserved); FIXME("(%s %s %d)\n", debugstr_a(szProduct), debugstr_a(szUserName), dwReserved);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -634,6 +632,6 @@ UINT WINAPI MsiSourceListClearAllA( LPCSTR szProduct, LPCSTR szUserName, DWORD d
*/ */
UINT WINAPI MsiSourceListClearAllW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD dwReserved ) UINT WINAPI MsiSourceListClearAllW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD dwReserved )
{ {
FIXME("(%s %s %ld) stub\n", debugstr_w(szProduct), debugstr_w(szUserName), dwReserved); FIXME("(%s %s %d)\n", debugstr_w(szProduct), debugstr_w(szUserName), dwReserved);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View file

@ -163,7 +163,7 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
type = get_type( idofs[i].propid ); type = get_type( idofs[i].propid );
if( type == VT_EMPTY ) if( type == VT_EMPTY )
{ {
ERR("propid %ld has unknown type\n", idofs[i].propid); ERR("propid %d has unknown type\n", idofs[i].propid);
break; break;
} }
@ -172,7 +172,7 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
/* check the type is the same as we expect */ /* check the type is the same as we expect */
if( type != propdata->type ) if( type != propdata->type )
{ {
ERR("wrong type %d != %ld\n", type, propdata->type); ERR("wrong type %d != %d\n", type, propdata->type);
break; break;
} }
@ -188,7 +188,7 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
if( idofs[i].propid >= MSI_MAX_PROPS ) if( idofs[i].propid >= MSI_MAX_PROPS )
{ {
ERR("Unknown property ID %ld\n", idofs[i].propid ); ERR("Unknown property ID %d\n", idofs[i].propid );
break; break;
} }
@ -259,7 +259,7 @@ static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
if( section_hdr.cProperties > MSI_MAX_PROPS ) if( section_hdr.cProperties > MSI_MAX_PROPS )
{ {
ERR("too many properties %ld\n", section_hdr.cProperties); ERR("too many properties %d\n", section_hdr.cProperties);
return ret; return ret;
} }
@ -275,7 +275,7 @@ static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
if( SUCCEEDED(r) && count == sz ) if( SUCCEEDED(r) && count == sz )
read_properties_from_data( si->property, data, sz + SECT_HDR_SIZE ); read_properties_from_data( si->property, data, sz + SECT_HDR_SIZE );
else else
ERR("failed to read properties %ld %ld\n", count, sz); ERR("failed to read properties %d %d\n", count, sz);
msi_free( data ); msi_free( data );
return ret; return ret;
@ -506,7 +506,7 @@ UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount)
{ {
MSISUMMARYINFO *si; MSISUMMARYINFO *si;
TRACE("%ld %p\n",hSummaryInfo, pCount); TRACE("%ld %p\n", hSummaryInfo, pCount);
si = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); si = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
if( !si ) if( !si )

View file

@ -27,15 +27,17 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winerror.h" #include "winerror.h"
#include "wine/debug.h"
#include "msi.h" #include "msi.h"
#include "msiquery.h" #include "msiquery.h"
#include "objbase.h" #include "objbase.h"
#include "objidl.h" #include "objidl.h"
#include "msipriv.h"
#include "winnls.h" #include "winnls.h"
#include "msipriv.h"
#include "query.h" #include "query.h"
#include "assert.h"
#include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msidb); WINE_DEFAULT_DEBUG_CHANNEL(msidb);
@ -71,6 +73,11 @@ typedef struct tagMSITRANSFORM {
IStorage *stg; IStorage *stg;
} MSITRANSFORM; } MSITRANSFORM;
static const WCHAR szStringData[] = {
'_','S','t','r','i','n','g','D','a','t','a',0 };
static const WCHAR szStringPool[] = {
'_','S','t','r','i','n','g','P','o','o','l',0 };
#define MAX_STREAM_NAME 0x1f #define MAX_STREAM_NAME 0x1f
static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name, static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name,
@ -208,7 +215,7 @@ void enum_stream_names( IStorage *stg )
if( FAILED( r ) || !count ) if( FAILED( r ) || !count )
break; break;
decode_streamname( stat.pwcsName, name ); decode_streamname( stat.pwcsName, name );
TRACE("stream %2ld -> %s %s\n", n, TRACE("stream %2d -> %s %s\n", n,
debugstr_w(stat.pwcsName), debugstr_w(name) ); debugstr_w(stat.pwcsName), debugstr_w(name) );
n++; n++;
} }
@ -236,14 +243,14 @@ static UINT read_stream_data( IStorage *stg, LPCWSTR stname,
msi_free( encname ); msi_free( encname );
if( FAILED( r ) ) if( FAILED( r ) )
{ {
WARN("open stream failed r = %08lx - empty table?\n",r); WARN("open stream failed r = %08x - empty table?\n", r);
return ret; return ret;
} }
r = IStream_Stat(stm, &stat, STATFLAG_NONAME ); r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
if( FAILED( r ) ) if( FAILED( r ) )
{ {
WARN("open stream failed r = %08lx!\n",r); WARN("open stream failed r = %08x!\n", r);
goto end; goto end;
} }
@ -257,7 +264,7 @@ static UINT read_stream_data( IStorage *stg, LPCWSTR stname,
data = msi_alloc( sz ); data = msi_alloc( sz );
if( !data ) if( !data )
{ {
WARN("couldn't allocate memory r=%08lx!\n",r); WARN("couldn't allocate memory r=%08x!\n", r);
ret = ERROR_NOT_ENOUGH_MEMORY; ret = ERROR_NOT_ENOUGH_MEMORY;
goto end; goto end;
} }
@ -266,7 +273,7 @@ static UINT read_stream_data( IStorage *stg, LPCWSTR stname,
if( FAILED( r ) || ( count != sz ) ) if( FAILED( r ) || ( count != sz ) )
{ {
msi_free( data ); msi_free( data );
WARN("read stream failed r = %08lx!\n",r); WARN("read stream failed r = %08x!\n", r);
goto end; goto end;
} }
@ -326,7 +333,7 @@ UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
r = IStream_Stat(stm, &stat, STATFLAG_NONAME ); r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
if( FAILED( r ) ) if( FAILED( r ) )
{ {
WARN("open stream failed r = %08lx!\n",r); WARN("open stream failed r = %08x!\n", r);
goto end; goto end;
} }
@ -340,7 +347,7 @@ UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
data = msi_alloc( sz ); data = msi_alloc( sz );
if( !data ) if( !data )
{ {
WARN("couldn't allocate memory r=%08lx!\n",r); WARN("couldn't allocate memory r=%08x!\n", r);
ret = ERROR_NOT_ENOUGH_MEMORY; ret = ERROR_NOT_ENOUGH_MEMORY;
goto end; goto end;
} }
@ -349,7 +356,7 @@ UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
if( FAILED( r ) || ( count != sz ) ) if( FAILED( r ) || ( count != sz ) )
{ {
msi_free( data ); msi_free( data );
WARN("read stream failed r = %08lx!\n",r); WARN("read stream failed r = %08x!\n", r);
goto end; goto end;
} }
@ -385,7 +392,7 @@ static UINT write_stream_data( IStorage *stg, LPCWSTR stname,
msi_free( encname ); msi_free( encname );
if( FAILED( r ) ) if( FAILED( r ) )
{ {
WARN("open stream failed r = %08lx\n",r); WARN("open stream failed r = %08x\n", r);
return ret; return ret;
} }
@ -635,10 +642,6 @@ err:
HRESULT init_string_table( IStorage *stg ) HRESULT init_string_table( IStorage *stg )
{ {
HRESULT r; HRESULT r;
static const WCHAR szStringData[] = {
'_','S','t','r','i','n','g','D','a','t','a',0 };
static const WCHAR szStringPool[] = {
'_','S','t','r','i','n','g','P','o','o','l',0 };
USHORT zero[2] = { 0, 0 }; USHORT zero[2] = { 0, 0 };
ULONG count = 0; ULONG count = 0;
IStream *stm = NULL; IStream *stm = NULL;
@ -687,10 +690,6 @@ string_table *load_string_table( IStorage *stg )
USHORT *pool = NULL; USHORT *pool = NULL;
UINT r, datasize = 0, poolsize = 0, codepage; UINT r, datasize = 0, poolsize = 0, codepage;
DWORD i, count, offset, len, n, refs; DWORD i, count, offset, len, n, refs;
static const WCHAR szStringData[] = {
'_','S','t','r','i','n','g','D','a','t','a',0 };
static const WCHAR szStringPool[] = {
'_','S','t','r','i','n','g','P','o','o','l',0 };
r = read_stream_data( stg, szStringPool, &pool, &poolsize ); r = read_stream_data( stg, szStringPool, &pool, &poolsize );
if( r != ERROR_SUCCESS) if( r != ERROR_SUCCESS)
@ -746,15 +745,15 @@ string_table *load_string_table( IStorage *stg )
r = msi_addstring( st, n, data+offset, len, refs ); r = msi_addstring( st, n, data+offset, len, refs );
if( r != n ) if( r != n )
ERR("Failed to add string %ld\n", n ); ERR("Failed to add string %d\n", n );
n++; n++;
offset += len; offset += len;
} }
if ( datasize != offset ) if ( datasize != offset )
ERR("string table load failed! (%08x != %08lx), please report\n", datasize, offset ); ERR("string table load failed! (%08x != %08x), please report\n", datasize, offset );
TRACE("Loaded %ld strings\n", count); TRACE("Loaded %d strings\n", count);
end: end:
msi_free( pool ); msi_free( pool );
@ -767,10 +766,6 @@ static UINT save_string_table( MSIDATABASE *db )
{ {
UINT i, count, datasize = 0, poolsize = 0, sz, used, r, codepage, n; UINT i, count, datasize = 0, poolsize = 0, sz, used, r, codepage, n;
UINT ret = ERROR_FUNCTION_FAILED; UINT ret = ERROR_FUNCTION_FAILED;
static const WCHAR szStringData[] = {
'_','S','t','r','i','n','g','D','a','t','a',0 };
static const WCHAR szStringPool[] = {
'_','S','t','r','i','n','g','P','o','o','l',0 };
CHAR *data = NULL; CHAR *data = NULL;
USHORT *pool = NULL; USHORT *pool = NULL;
@ -811,7 +806,10 @@ static UINT save_string_table( MSIDATABASE *db )
if( sz && (sz < (datasize - used ) ) ) if( sz && (sz < (datasize - used ) ) )
sz--; sz--;
if (sz)
pool[ n*2 + 1 ] = msi_id_refcount( db->strings, i ); pool[ n*2 + 1 ] = msi_id_refcount( db->strings, i );
else
pool[ n*2 + 1 ] = 0;
if (sz < 0x10000) if (sz < 0x10000)
{ {
pool[ n*2 ] = sz; pool[ n*2 ] = sz;
@ -924,7 +922,7 @@ static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count )
} }
} }
LPWSTR MSI_makestring( MSIDATABASE *db, UINT stringid) static LPWSTR msi_makestring( MSIDATABASE *db, UINT stringid)
{ {
return strdupW(msi_string_lookup_id( db->strings, stringid )); return strdupW(msi_string_lookup_id( db->strings, stringid ));
} }
@ -935,6 +933,8 @@ static UINT get_tablecolumns( MSIDATABASE *db,
UINT r, i, n=0, table_id, count, maxcount = *sz; UINT r, i, n=0, table_id, count, maxcount = *sz;
MSITABLE *table = NULL; MSITABLE *table = NULL;
TRACE("%s\n", debugstr_w(szTableName));
/* first check if there is a default table with that name */ /* first check if there is a default table with that name */
r = get_defaulttablecolumns( szTableName, colinfo, sz ); r = get_defaulttablecolumns( szTableName, colinfo, sz );
if( ( r == ERROR_SUCCESS ) && *sz ) if( ( r == ERROR_SUCCESS ) && *sz )
@ -957,6 +957,8 @@ static UINT get_tablecolumns( MSIDATABASE *db,
TRACE("Table id is %d, row count is %d\n", table_id, table->row_count); TRACE("Table id is %d, row count is %d\n", table_id, table->row_count);
/* if maxcount is non-zero, assume it's exactly right for this table */
memset( colinfo, 0, maxcount*sizeof(*colinfo) );
count = table->row_count; count = table->row_count;
for( i=0; i<count; i++ ) for( i=0; i<count; i++ )
{ {
@ -965,31 +967,53 @@ static UINT get_tablecolumns( MSIDATABASE *db,
if( colinfo ) if( colinfo )
{ {
UINT id = table->data[ i ] [ 2 ]; UINT id = table->data[ i ] [ 2 ];
colinfo[n].tablename = MSI_makestring( db, table_id ); UINT col = table->data[ i ][ 1 ] - (1<<15);
colinfo[n].number = table->data[ i ][ 1 ] - (1<<15);
colinfo[n].colname = MSI_makestring( db, id ); /* check the column number is in range */
colinfo[n].type = table->data[ i ] [ 3 ] ^ 0x8000; if (col<1 || col>maxcount)
colinfo[n].hash_table = NULL;
/* this assumes that columns are in order in the table */
if( n )
colinfo[n].offset = colinfo[n-1].offset
+ bytes_per_column( &colinfo[n-1] );
else
colinfo[n].offset = 0;
TRACE("table %s column %d is [%s] (%d) with type %08x "
"offset %d at row %d\n", debugstr_w(szTableName),
colinfo[n].number, debugstr_w(colinfo[n].colname),
id, colinfo[n].type, colinfo[n].offset, i);
if( n != (colinfo[n].number-1) )
{ {
ERR("oops. data in the _Columns table isn't in the right " ERR("column %d out of range\n", col);
"order for table %s\n", debugstr_w(szTableName)); continue;
return ERROR_FUNCTION_FAILED;
} }
/* check if this column was already set */
if (colinfo[ col - 1 ].number)
{
ERR("duplicate column %d\n", col);
continue;
}
colinfo[ col - 1 ].tablename = msi_makestring( db, table_id );
colinfo[ col - 1 ].number = col;
colinfo[ col - 1 ].colname = msi_makestring( db, id );
colinfo[ col - 1 ].type = table->data[ i ] [ 3 ] - (1<<15);
colinfo[ col - 1 ].offset = 0;
colinfo[ col - 1 ].hash_table = NULL;
} }
n++; n++;
if( colinfo && ( n >= maxcount ) ) }
break;
TRACE("%s has %d columns\n", debugstr_w(szTableName), n);
if (maxcount && n != maxcount)
{
ERR("missing column in table %s\n", debugstr_w(szTableName));
msi_free_colinfo(colinfo, maxcount );
return ERROR_FUNCTION_FAILED;
}
/* calculate the offsets */
for( i=0; maxcount && (i<maxcount); i++ )
{
assert( (i+1) == colinfo[ i ].number );
if (i)
colinfo[i].offset = colinfo[ i - 1 ].offset
+ bytes_per_column( &colinfo[ i - 1 ] );
else
colinfo[i].offset = 0;
TRACE("column %d is [%s] with type %08x ofs %d\n",
colinfo[i].number, debugstr_w(colinfo[i].colname),
colinfo[i].type, colinfo[i].offset);
} }
*sz = n; *sz = n;
@ -1107,6 +1131,7 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
LPWSTR full_name; LPWSTR full_name;
DWORD len; DWORD len;
static const WCHAR szDot[] = { '.', 0 }; static const WCHAR szDot[] = { '.', 0 };
WCHAR number[0x20];
if( !view->ops->fetch_int ) if( !view->ops->fetch_int )
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -1121,15 +1146,31 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
return r; return r;
/* check the column value is in range */
if (ival < 0 || ival > tv->num_cols || ival == col)
{
ERR("bad column ref (%u) for stream\n", ival);
return ERROR_FUNCTION_FAILED;
}
if ( tv->columns[ival - 1].type & MSITYPE_STRING )
{
/* now get the column with the name of the stream */ /* now get the column with the name of the stream */
r = view->ops->fetch_int( view, row, ival, &refcol ); r = view->ops->fetch_int( view, row, ival, &refcol );
if( r != ERROR_SUCCESS ) if ( r != ERROR_SUCCESS )
return r; return r;
/* lookup the string value from the string table */ /* lookup the string value from the string table */
sval = msi_string_lookup_id( tv->db->strings, refcol ); sval = msi_string_lookup_id( tv->db->strings, refcol );
if( !sval ) if ( !sval )
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
}
else
{
static const WCHAR fmt[] = { '%','d',0 };
sprintfW( number, fmt, ival );
sval = number;
}
len = lstrlenW( tv->name ) + 2 + lstrlenW( sval ); len = lstrlenW( tv->name ) + 2 + lstrlenW( sval );
full_name = msi_alloc( len*sizeof(WCHAR) ); full_name = msi_alloc( len*sizeof(WCHAR) );
@ -1296,7 +1337,9 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
if ( tv->columns[i].type & MSITYPE_NULLABLE ) if ( tv->columns[i].type & MSITYPE_NULLABLE )
continue; continue;
if ( tv->columns[i].type & MSITYPE_STRING ) if ( MSITYPE_IS_BINARY(tv->columns[i].type) )
TRACE("skipping binary column\n");
else if ( tv->columns[i].type & MSITYPE_STRING )
{ {
LPCWSTR str; LPCWSTR str;
@ -1662,7 +1705,7 @@ static MSIRECORD *msi_get_transform_record( MSITABLEVIEW *tv, string_table *st,
if( !rec ) if( !rec )
return rec; return rec;
TRACE("row -> "); TRACE("row ->\n");
for( i=0; i<tv->num_cols; i++ ) for( i=0; i<tv->num_cols; i++ )
{ {
UINT n = bytes_per_column( &columns[i] ); UINT n = bytes_per_column( &columns[i] );
@ -1682,20 +1725,20 @@ static MSIRECORD *msi_get_transform_record( MSITABLEVIEW *tv, string_table *st,
{ {
LPCWSTR sval = msi_string_lookup_id( st, val ); LPCWSTR sval = msi_string_lookup_id( st, val );
MSI_RecordSetStringW( rec, i+1, sval ); MSI_RecordSetStringW( rec, i+1, sval );
TRACE("[%s]", debugstr_w(sval)); TRACE(" field %d [%s]\n", i+1, debugstr_w(sval));
} }
else else
{ {
val ^= 0x8000; if (val)
MSI_RecordSetInteger( rec, i+1, val ); MSI_RecordSetInteger( rec, i+1, val^0x8000 );
TRACE("[0x%04x]", val ); TRACE(" field %d [0x%04x]\n", i+1, val );
} }
break; break;
case 4: case 4:
val = rawdata[ofs] + (rawdata[ofs + 1]<<16); val = (rawdata[ofs] + (rawdata[ofs + 1]<<16));
/* val ^= 0x80000000; */ if (val)
MSI_RecordSetInteger( rec, i+1, val ); MSI_RecordSetInteger( rec, i+1, val^0x80000000 );
TRACE("[0x%08x]", val ); TRACE(" field %d [0x%08x]\n", i+1, val );
break; break;
default: default:
ERR("oops - unknown column width %d\n", n); ERR("oops - unknown column width %d\n", n);
@ -1703,7 +1746,6 @@ static MSIRECORD *msi_get_transform_record( MSITABLEVIEW *tv, string_table *st,
} }
ofs += n/2; ofs += n/2;
} }
TRACE("\n");
return rec; return rec;
} }
@ -1766,7 +1808,13 @@ static UINT* msi_record_to_row( MSITABLEVIEW *tv, MSIRECORD *rec )
} }
} }
else else
{
data[i] = MSI_RecordGetInteger( rec, i+1 ); data[i] = MSI_RecordGetInteger( rec, i+1 );
if ((tv->columns[i].type&0xff) == 2)
data[i] += 0x8000;
else
data[i] += 0x80000000;
}
} }
return data; return data;
} }
@ -1837,9 +1885,20 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
MSITABLEVIEW *tv = NULL; MSITABLEVIEW *tv = NULL;
UINT r, n, sz, i, mask; UINT r, n, sz, i, mask;
MSIRECORD *rec = NULL; MSIRECORD *rec = NULL;
UINT colcol = 0;
WCHAR coltable[32];
coltable[0] = 0;
TRACE("%p %p %p %s\n", db, stg, st, debugstr_w(name) ); TRACE("%p %p %p %s\n", db, stg, st, debugstr_w(name) );
/* read the transform data */
read_stream_data( stg, name, &rawdata, &rawsize );
if ( !rawdata )
{
TRACE("table %s empty\n", debugstr_w(name) );
return ERROR_INVALID_TABLE;
}
/* create a table view */ /* create a table view */
r = TABLE_CreateView( db, name, (MSIVIEW**) &tv ); r = TABLE_CreateView( db, name, (MSIVIEW**) &tv );
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
@ -1849,15 +1908,6 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
goto err; goto err;
/* read the transform data */
r = ERROR_FUNCTION_FAILED;
read_stream_data( stg, name, &rawdata, &rawsize );
if( !rawdata || (rawsize < 2) )
{
ERR("odd sized transform for table %s\n", debugstr_w(name));
goto err;
}
TRACE("name = %s columns = %u row_size = %u raw size = %u\n", TRACE("name = %s columns = %u row_size = %u raw size = %u\n",
debugstr_w(name), tv->num_cols, tv->row_size, rawsize ); debugstr_w(name), tv->num_cols, tv->row_size, rawsize );
@ -1903,32 +1953,61 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
rec = msi_get_transform_record( tv, st, &rawdata[n] ); rec = msi_get_transform_record( tv, st, &rawdata[n] );
if (rec) if (rec)
{
if ( mask & 1 )
{
TRACE("inserting record\n");
/*
* Native msi seems writes nul into the
* Number (2nd) column of the _Columns table.
* Not sure that it's deliberate...
*/
if (!lstrcmpW(name, szColumns))
{
WCHAR table[32];
DWORD sz = 32;
MSI_RecordGetStringW( rec, 1, table, &sz );
/* reset the column number on a new table */
if ( lstrcmpW(coltable, table) )
{
colcol = 0;
lstrcpyW( coltable, table );
}
/* fix nul column numbers */
MSI_RecordSetInteger( rec, 2, ++colcol );
}
r = TABLE_insert_row( &tv->view, rec );
if (r != ERROR_SUCCESS)
ERR("insert row failed\n");
}
else
{ {
UINT row = 0; UINT row = 0;
r = msi_table_find_row( tv, rec, &row ); r = msi_table_find_row( tv, rec, &row );
if (r != ERROR_SUCCESS)
if( rawdata[n] & 1) ERR("no matching row to transform\n");
else if ( mask )
{ {
TRACE("insert [%d]: ", row); TRACE("modifying row [%d]:\n", row);
TABLE_insert_row( &tv->view, rec );
}
else if( mask & 0xff )
{
TRACE("modify [%d]: ", row);
msi_table_modify_row( tv, rec, row, mask ); msi_table_modify_row( tv, rec, row, mask );
} }
else else
{ {
TRACE("delete [%d]: ", row); TRACE("deleting row [%d]:\n", row);
msi_delete_row( tv, row ); msi_delete_row( tv, row );
} }
}
if( TRACE_ON(msidb) ) dump_record( rec ); if( TRACE_ON(msidb) ) dump_record( rec );
msiobj_release( &rec->hdr ); msiobj_release( &rec->hdr );
} }
n += sz/2; n += sz/2;
} }
err: err:
@ -1950,7 +2029,7 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
IEnumSTATSTG *stgenum = NULL; IEnumSTATSTG *stgenum = NULL;
HRESULT r; HRESULT r;
STATSTG stat; STATSTG stat;
ULONG n, count; ULONG count;
WCHAR name[0x40]; WCHAR name[0x40];
string_table *strings; string_table *strings;
UINT ret = ERROR_FUNCTION_FAILED; UINT ret = ERROR_FUNCTION_FAILED;
@ -1965,7 +2044,18 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
if( FAILED( r ) ) if( FAILED( r ) )
goto end; goto end;
n = 0; /*
* Apply _Tables and _Coluimns transforms first so that
* the table metadata is correct, and empty tables exist.
*/
ret = msi_table_load_transform( db, stg, strings, szTables );
if (ret != ERROR_SUCCESS && ret != ERROR_INVALID_TABLE)
goto end;
ret = msi_table_load_transform( db, stg, strings, szColumns );
if (ret != ERROR_SUCCESS && ret != ERROR_INVALID_TABLE)
goto end;
ret = ERROR_SUCCESS; ret = ERROR_SUCCESS;
while( r == ERROR_SUCCESS ) while( r == ERROR_SUCCESS )
@ -1974,12 +2064,20 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count ); r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
if( FAILED( r ) || !count ) if( FAILED( r ) || !count )
break; break;
decode_streamname( stat.pwcsName, name ); decode_streamname( stat.pwcsName, name );
if( ( name[0] == 0x4840 ) && ( name[1] != '_' ) ) if ( name[0] != 0x4840 )
ret = msi_table_load_transform( db, stg, strings, name+1 ); continue;
else
TRACE("transform contains stream %s\n", debugstr_w(name)); TRACE("transform contains stream %s\n", debugstr_w(name));
n++;
if ( !lstrcmpW( name+1, szStringPool ) ||
!lstrcmpW( name+1, szStringData ) ||
!lstrcmpW( name+1, szColumns ) ||
!lstrcmpW( name+1, szTables ) )
continue;
ret = msi_table_load_transform( db, stg, strings, name+1 );
} }
if ( ret == ERROR_SUCCESS ) if ( ret == ERROR_SUCCESS )

View file

@ -36,7 +36,6 @@
#include "msidefs.h" #include "msidefs.h"
#include "msipriv.h" #include "msipriv.h"
#include "winuser.h" #include "winuser.h"
#include "action.h"
#include "wine/unicode.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -124,7 +123,7 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
while (rc == ERROR_SUCCESS) while (rc == ERROR_SUCCESS)
{ {
rc = RegEnumValueW(hkey, index, product, &sz, NULL, NULL, NULL, NULL); rc = RegEnumValueW(hkey, index, product, &sz, NULL, NULL, NULL, NULL);
TRACE("Looking at (%li) %s\n",index,debugstr_w(product)); TRACE("Looking at (%i) %s\n",index,debugstr_w(product));
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
{ {
WCHAR productid[GUID_SIZE]; WCHAR productid[GUID_SIZE];
@ -179,7 +178,7 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
(LPBYTE)&check, &sz); (LPBYTE)&check, &sz);
RegCloseKey(hukey); RegCloseKey(hukey);
language = MSI_RecordGetString(rec,4); language = MSI_RecordGetString(rec,4);
TRACE("Checking languages 0x%lx and %s\n", check, TRACE("Checking languages %x and %s\n", check,
debugstr_w(language)); debugstr_w(language));
if (!check_language(check, language, attributes)) if (!check_language(check, language, attributes))
{ {