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 "winerror.h"
#include "winreg.h"
#include "winsvc.h"
#include "wine/debug.h"
#include "msidefs.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 "wine/unicode.h"
#include "winver.h"
#include "action.h"
#define REG_PROGRESS_VALUE 13200
#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 )
{
LPCWSTR pc;
LPWSTR p, *ret = NULL;
UINT count = 0;
@ -372,11 +373,11 @@ static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep )
return ret;
/* count the number of substrings */
for ( p = (LPWSTR)str, count = 0; p; count++ )
for ( pc = str, count = 0; pc; count++ )
{
p = strchrW( p, sep );
if (p)
p++;
pc = strchrW( pc, sep );
if (pc)
pc++;
}
/* 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;
package->PackagePath = strdupW(szPackagePath);
path = strdupW(szPackagePath);
p = strrchrW(path,'\\');
if (p)
@ -593,8 +593,15 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
check = msi_dup_property( package, cszSourceDir );
if (!check)
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(path);
}
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->KeyPath = msi_dup_record_field( row, 6 );
comp->Installed = INSTALLSTATE_ABSENT;
switch (comp->Attributes)
{
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;
}
comp->Installed = INSTALLSTATE_UNKNOWN;
comp->Action = INSTALLSTATE_UNKNOWN;
comp->ActionRequest = INSTALLSTATE_UNKNOWN;
return ERROR_SUCCESS;
}
@ -1180,6 +1170,19 @@ static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp )
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)
{
_ilfs* ilfs= (_ilfs*)param;
@ -1202,6 +1205,19 @@ static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
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)
{
MSIPACKAGE* package = (MSIPACKAGE*)param;
@ -1223,6 +1239,7 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
if (!feature)
return ERROR_NOT_ENOUGH_MEMORY;
list_init( &feature->Children );
list_init( &feature->Components );
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->Attributes = MSI_RecordGetInteger(row,8);
feature->Installed = INSTALLSTATE_ABSENT;
feature->Installed = INSTALLSTATE_UNKNOWN;
feature->Action = INSTALLSTATE_UNKNOWN;
feature->ActionRequest = INSTALLSTATE_UNKNOWN;
@ -1261,6 +1278,26 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
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 const WCHAR query[] = {
@ -1278,7 +1315,12 @@ static UINT load_all_features( MSIPACKAGE *package )
return r;
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 );
return r;
}
@ -1343,13 +1385,6 @@ static UINT load_file(MSIRECORD *row, LPVOID param)
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));
list_add_tail( &package->files, &file->entry );
@ -1546,9 +1581,16 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
MSICOMPONENT *comp;
MSIFEATURE *feature;
/* FIXME: component's installed state should be determined
* by the component's registration
*/
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{
INSTALLSTATE res;
if (!comp->ComponentId)
continue;
res = MsiGetComponentPathW( package->ProductCode,
comp->ComponentId, NULL, NULL);
if (res < 0)
@ -1559,21 +1601,30 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
ComponentList *cl;
INSTALLSTATE res = -10;
INSTALLSTATE res = INSTALLSTATE_ABSENT;
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{
comp= cl->component;
if (res == -10)
if (!comp->ComponentId)
{
res = INSTALLSTATE_ABSENT;
break;
}
if (res == INSTALLSTATE_ABSENT)
res = comp->Installed;
else
{
if (res == comp->Installed)
continue;
if (res != comp->Installed)
res = INSTALLSTATE_INCOMPLETE;
if (res != INSTALLSTATE_DEFAULT || res != INSTALLSTATE_LOCAL ||
res != INSTALLSTATE_SOURCE)
{
res = INSTALLSTATE_INCOMPLETE;
}
}
}
feature->Installed = res;
@ -1649,7 +1700,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
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
* later on the list override things earlier on the list.
* 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
{
@ -1727,6 +1793,31 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{
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)
{
component->Action = INSTALLSTATE_UNKNOWN;
@ -1772,9 +1863,14 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
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->ActionRequest = INSTALLSTATE_LOCAL;
@ -1837,7 +1933,6 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
return ERROR_SUCCESS;
}
/*
* 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
@ -1886,6 +1981,9 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
if (!comp)
continue;
if (file->IsCompressed)
comp->ForceLocalState = TRUE;
/* calculate target */
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);
TRACE("Data %li bytes(%i)\n",*size,count);
TRACE("Data %i bytes(%i)\n",*size,count);
}
else
{
@ -2063,7 +2161,7 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
if (deformated[0] == '-')
d = -d;
*(LPDWORD)data = d;
TRACE("DWORD %li\n",*(LPDWORD)data);
TRACE("DWORD %i\n",*(LPDWORD)data);
msi_free(deformated);
}
@ -3540,7 +3638,7 @@ static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey )
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());
return ERROR_FUNCTION_FAILED;
}
@ -3751,10 +3849,12 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package)
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;
/*
* we are currently doing what should be done here in the top level Install
* however for Adminastrative and uninstalls this step will be needed
@ -3762,6 +3862,19 @@ UINT ACTION_ResolveSource(MSIPACKAGE* package)
if (!package->PackagePath)
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);
if (attrib == INVALID_FILE_ATTRIBUTES)
{
@ -3956,6 +4069,100 @@ static UINT ACTION_PublishComponents(MSIPACKAGE *package)
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,
LPCSTR action, LPCWSTR table )
{
@ -3974,7 +4181,7 @@ static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
}
if (count)
FIXME("%s -> %lu ignored %s table values\n",
FIXME("%s -> %u ignored %s table values\n",
action, count, debugstr_w(table));
return ERROR_SUCCESS;
@ -4030,13 +4237,6 @@ static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
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 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/debug.h"
#include "msipriv.h"
#include "action.h"
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),
LOWORD(sig->MaxVersionMS), HIWORD(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));
end:
@ -255,7 +254,7 @@ static void ACTION_ConvertRegValue(DWORD regType, const BYTE *value, DWORD sz,
switch (regType)
{
case REG_SZ:
if (*(LPWSTR)value == '#')
if (*(LPCWSTR)value == '#')
{
/* escape leading pound with another */
*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]);
break;
default:
WARN("unimplemented for values of type %ld\n", regType);
WARN("unimplemented for values of type %d\n", regType);
*appValue = NULL;
}
}
@ -398,6 +397,9 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue,
rc = ACTION_SearchDirectory(package, sig, (LPCWSTR)value, 0,
appValue);
break;
case msidbLocatorTypeFileName:
*appValue = strdupW((LPCWSTR)value);
break;
case msidbLocatorTypeRawValue:
ACTION_ConvertRegValue(regType, value, sz, appValue);
break;
@ -528,7 +530,10 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
size_t copied = 0;
if (!src || !dst || !len)
{
if (dst) *dst = '\0';
return;
}
/* Ignore the short portion of the path, don't think we can use it anyway */
if ((ptr = strchrW(src, '|')))
@ -913,7 +918,7 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue,
msi_free(path);
if (parent)
{
path = msi_alloc(strlenW(parent) + strlenW(expanded) + 1);
path = msi_alloc((strlenW(parent) + strlenW(expanded) + 1) * sizeof(WCHAR));
if (!path)
goto end;
strcpyW(path, parent);
@ -991,7 +996,7 @@ UINT ACTION_AppSearch(MSIPACKAGE *package)
while (!rc)
{
MSISIGNATURE sig;
LPWSTR value;
LPWSTR value = NULL;
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)

View file

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

View file

@ -35,7 +35,6 @@
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
#include "action.h"
#define YYLEX_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 "wine/unicode.h"
#include "winver.h"
#include "action.h"
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:
* [CustomActionData]Action
*/
LPWSTR msi_get_deferred_action(LPCWSTR action, LPWSTR actiondata)
static LPWSTR msi_get_deferred_action(LPCWSTR action, LPWSTR actiondata)
{
LPWSTR deferred;
DWORD len;
@ -167,7 +166,10 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
row = MSI_QueryGetRecord( package->db, ExecSeqQuery, action );
if (!row)
{
msi_free(action_copy);
return ERROR_CALL_NOT_IMPLEMENTED;
}
type = MSI_RecordGetInteger(row,2);
@ -382,7 +384,7 @@ static UINT process_action_return_value(UINT type, HANDLE ThreadHandle)
case ERROR_NO_MORE_ITEMS:
return ERROR_SUCCESS;
default:
ERR("Invalid Return Code %ld\n",rc);
ERR("Invalid Return Code %d\n",rc);
return ERROR_INSTALL_FAILURE;
}
}
@ -502,14 +504,13 @@ static DWORD WINAPI DllThread(LPVOID info)
{
thread_struct *stuff;
DWORD rc = 0;
TRACE("MSI Thread (0x%lx) started for custom action\n",
GetCurrentThreadId());
TRACE("MSI Thread (%x) started for custom action\n", GetCurrentThreadId());
stuff = (thread_struct*)info;
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 */
MsiCloseAllHandles();
return rc;

View file

@ -28,6 +28,7 @@
#include "winreg.h"
#include "winnls.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
@ -58,12 +59,13 @@ static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
MSIDATABASE *db = (MSIDATABASE *) arg;
DWORD r;
msi_free(db->path);
free_cached_tables( db );
msi_free_transforms( db );
msi_destroy_stringtable( db->strings );
r = IStorage_Release( db->storage );
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)
{
DeleteFileW( db->deletefile );
@ -77,15 +79,19 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
HRESULT r;
MSIDATABASE *db = NULL;
UINT ret = ERROR_FUNCTION_FAILED;
LPCWSTR szMode;
LPCWSTR szMode, save_path;
STATSTG stat;
BOOL created = FALSE;
WCHAR path[MAX_PATH];
static const WCHAR backslash[] = {'\\',0};
TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
if( !pdb )
return ERROR_INVALID_PARAMETER;
save_path = szDBPath;
szMode = szPersist;
if( HIWORD( szPersist ) )
{
@ -135,7 +141,7 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
if( FAILED( r ) )
{
FIXME("open failed r = %08lx!\n",r);
FIXME("open failed r = %08x!\n",r);
return ERROR_FUNCTION_FAILED;
}
@ -162,6 +168,17 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
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 ) )
enum_stream_names( stg );
@ -245,14 +262,444 @@ end:
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 )
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)

View file

@ -42,8 +42,6 @@
#include "wine/debug.h"
#include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -82,6 +80,7 @@ typedef struct msi_font_tag
struct msi_dialog_tag
{
MSIPACKAGE *package;
msi_dialog *parent;
msi_dialog_event_handler event_handler;
BOOL finished;
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 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 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 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_evaluate_control_conditions( msi_dialog *dialog );
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 */
@ -213,43 +215,62 @@ static LPWSTR msi_get_deformatted_field( MSIPACKAGE *package, MSIRECORD *rec, in
static LPWSTR msi_dialog_dup_property( msi_dialog *dialog, LPCWSTR property, BOOL indirect )
{
LPWSTR prop = NULL;
if (!property)
return NULL;
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
*
* 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 )
{
LPWSTR ret = NULL;
LPCWSTR q, i;
LPWSTR ret;
LPCWSTR q, i, first;
DWORD len;
q = NULL;
*rest = p;
if( !p )
return ret;
if( *p++ != '{' )
return ret;
q = strchrW( p, '}' );
if( !q )
return ret;
if( *p == '\\' || *p == '&' )
p++;
return NULL;
while ((first = strchrW( p, '{' )) && (q = strchrW( first + 1, '}' )))
{
p = first + 1;
if( *p == '\\' || *p == '&' )
p++;
/* little bit of sanity checking to stop us getting confused with RTF */
for( i=p; i<q; i++ )
if( *i == '}' || *i == '\\' )
return NULL;
}
if (!p || !q)
return NULL;
/* little bit of sanity checking to stop us getting confused with RTF */
for( i=p; i<q; i++ )
if( *i == '}' || *i == '\\' )
return ret;
*rest = ++q;
len = q - p;
@ -525,6 +546,8 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
LPCWSTR font_text, text = NULL;
LPWSTR font;
static const WCHAR empty[] = {0};
ctrl = msi_dialog_find_control( dialog, control );
if (!ctrl)
return;
@ -532,6 +555,7 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
{
font_text = MSI_RecordGetString( rec , 1 );
font = msi_dialog_get_style( font_text, &text );
if (!text) text = empty;
SetWindowTextW( ctrl->hwnd, text );
msi_free( font );
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);
break;
default:
ERR("Unknown progress message %ld\n", func);
ERR("Unknown progress message %d\n", func);
break;
}
}
else if ( !lstrcmpW(attribute, szProperty) )
{
MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
MSI_SetPropertyW( dialog->package, ctrl->property, feature->Directory );
}
else
{
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 );
attribute = MSI_RecordGetString( row, 4 );
ControlEvent_SubscribeToEvent( dialog->package, event, control, attribute );
ControlEvent_SubscribeToEvent( dialog->package, dialog, event, control, attribute );
msiobj_release( &row->hdr );
}
@ -860,7 +889,7 @@ msi_richedit_stream_in( DWORD_PTR arg, LPBYTE buffer, LONG count, LONG *pcb )
*pcb = count;
info->offset += count;
TRACE("%ld/%ld\n", info->offset, info->length);
TRACE("%d/%d\n", info->offset, info->length);
return 0;
}
@ -1078,7 +1107,7 @@ static UINT msi_dialog_edit_control( msi_dialog *dialog, MSIRECORD *rec )
/******************** Masked Edit ********************************************/
#define MASK_MAX_GROUPS 10
#define MASK_MAX_GROUPS 20
struct msi_mask_group
{
@ -1443,8 +1472,8 @@ static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control
indirect = control->attributes & msidbControlAttributesIndirect;
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 );
SendMessageW( control->hwnd, EM_SETSEL, 0, -1 );
@ -1645,19 +1674,24 @@ struct msi_selection_tree_info
msi_dialog *dialog;
HWND hwnd;
WNDPROC oldproc;
HTREEITEM selected;
};
static void
msi_seltree_sync_item_state( HWND hwnd, MSIFEATURE *feature, HTREEITEM hItem )
{
TVITEMW tvi;
DWORD index = feature->Action;
TRACE("Feature %s -> %d %d %d\n", debugstr_w(feature->Title),
feature->Installed, feature->Action, feature->ActionRequest);
if (index == INSTALLSTATE_UNKNOWN)
index = INSTALLSTATE_ABSENT;
tvi.mask = TVIF_STATE;
tvi.hItem = hItem;
tvi.state = INDEXTOSTATEIMAGEMASK( feature->Action );
tvi.state = INDEXTOSTATEIMAGEMASK( index );
tvi.stateMask = TVIS_STATEIMAGEMASK;
SendMessageW( hwnd, TVM_SETITEMW, 0, (LPARAM) &tvi );
@ -1700,8 +1734,9 @@ msi_seltree_feature_from_item( HWND hwnd, HTREEITEM hItem )
static LRESULT
msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
{
struct msi_selection_tree_info *info;
MSIFEATURE *feature;
ComponentList *cl;
MSIPACKAGE *package;
union {
RECT rc;
POINT pt[2];
@ -1709,6 +1744,9 @@ msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
} u;
UINT r;
info = GetPropW(hwnd, szButtonData);
package = info->dialog->package;
feature = msi_seltree_feature_from_item( hwnd, hItem );
if (!feature)
{
@ -1737,17 +1775,17 @@ msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
/* update */
msi_seltree_sync_item_state( hwnd, feature, hItem );
/* update the feature's components */
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{
cl->component->Action = feature->Action;
cl->component->ActionRequest = feature->ActionRequest;
}
ACTION_UpdateComponentStates( package, feature->Feature );
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
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,
LPCWSTR parent, HTREEITEM hParent )
{
struct msi_selection_tree_info *info = GetPropW( hwnd, szButtonData );
MSIFEATURE *feature;
TVINSERTSTRUCTW tvis;
HTREEITEM hitem;
HTREEITEM hitem, hfirst = NULL;
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
@ -1814,6 +1853,9 @@ msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
if (!hitem)
continue;
if (!hfirst)
hfirst = hitem;
msi_seltree_sync_item_state( hwnd, feature, hitem );
msi_seltree_add_child_features( package, hwnd,
feature->Feature, hitem );
@ -1822,6 +1864,10 @@ msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
if ( feature->Display % 2 != 0 )
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 )
@ -1861,6 +1907,54 @@ static void msi_seltree_create_imagelist( HWND hwnd )
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 )
{
msi_control *control;
@ -1874,7 +1968,6 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
return ERROR_FUNCTION_FAILED;
/* create the treeview control */
prop = MSI_RecordGetString( rec, 9 );
style = TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT;
style |= WS_GROUP | WS_VSCROLL;
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;
}
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 */
info->dialog = dialog;
info->hwnd = control->hwnd;
@ -1891,6 +1989,9 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec )
(LONG_PTR)MSISelectionTree_WndProc );
SetPropW( control->hwnd, szButtonData, info );
ControlEvent_SubscribeToEvent( dialog->package, dialog,
szSelectionPath, control->name, szProperty );
/* initialize it */
msi_seltree_create_imagelist( control->hwnd );
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;
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 );
PathRemoveBackslashW( path );
@ -2127,7 +2228,7 @@ static void msi_dialog_update_directory_list( msi_dialog *dialog, msi_control *c
indirect = control->attributes & msidbControlAttributesIndirect;
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 );
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 );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop );
path = msi_dialog_dup_property( dialog, prop, TRUE );
/* strip off the last directory */
ptr = PathFindFileNameW( path );
@ -2217,7 +2317,7 @@ static UINT msi_dialog_dirlist_handler( msi_dialog *dialog,
indirect = control->attributes & msidbControlAttributesIndirect;
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 );
lstrcatW( new_path, text );
@ -2290,7 +2390,6 @@ static void msi_dialog_vcl_add_columns( msi_dialog *dialog, msi_control *control
WCHAR num[10];
LVCOLUMNW lvc;
DWORD count = 0;
LRESULT r;
static const WCHAR zero[] = {'0',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 ) )
return;
lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_WIDTH | LVCF_TEXT;
lvc.iOrder = count;
lvc.pszText = msi_dialog_get_uitext( dialog, column_keys[count++] );
ZeroMemory( &lvc, sizeof(lvc) );
lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
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 );
if ( r ) return;
}
}
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;
LVITEMW lvitem;
DWORD size;
@ -2353,6 +2452,20 @@ static void msi_dialog_vcl_add_drives( msi_dialog *dialog, msi_control *control
lvitem.cchTextMax = lstrlenW(ptr) + 1;
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;
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 */
r = MSI_OpenQuery( package->db, &view, query, dialog->name );
if( r != ERROR_SUCCESS )
{
ERR("query failed for dialog %s\n", debugstr_w(dialog->name));
return ERROR_INVALID_PARAMETER;
}
return ERROR_SUCCESS;
r = MSI_IterateRecords( view, 0, msi_dialog_set_control_condition, dialog );
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.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 );
AdjustWindowRect( pos, style, FALSE );
@ -2776,6 +2886,38 @@ static UINT msi_dialog_control_event( MSIRECORD *rec, LPVOID param )
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,
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
};
MSIQUERY *view = NULL;
struct rec_list *rec_entry, *next;
struct list events;
UINT r;
if( HIWORD(param) != BN_CLICKED )
return ERROR_SUCCESS;
list_init( &events );
r = MSI_OpenQuery( dialog->package->db, &view, query,
dialog->name, control->name );
if( r != ERROR_SUCCESS )
@ -2802,8 +2948,41 @@ static UINT msi_dialog_button_handler( msi_dialog *dialog,
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 );
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;
}
@ -2938,7 +3117,7 @@ static LRESULT msi_dialog_onnotify( msi_dialog *dialog, LPARAM param )
LPNMHDR nmhdr = (LPNMHDR) param;
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 )
control->handler( dialog, control, param );
@ -3045,8 +3224,9 @@ static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg,
/* functions that interface to other modules within MSI */
msi_dialog *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
msi_dialog_event_handler event_handler )
msi_dialog *msi_dialog_create( MSIPACKAGE* package,
LPCWSTR szDialogName, msi_dialog *parent,
msi_dialog_event_handler event_handler )
{
MSIRECORD *rec = NULL;
msi_dialog *dialog;
@ -3058,6 +3238,7 @@ msi_dialog *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
if( !dialog )
return NULL;
strcpyW( dialog->name, szDialogName );
dialog->parent = parent;
msiobj_addref( &package->hdr );
dialog->package = package;
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 "msi.h"
#include "msipriv.h"
#include "action.h"
#include "wine/debug.h"
#include "wine/unicode.h"
@ -48,6 +47,7 @@ struct _events {
struct subscriber {
struct list entry;
msi_dialog *dialog;
LPWSTR event;
LPWSTR control;
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
*/
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;
UINT r;
/* create a new dialog */
dialog = msi_dialog_create( package, name,
dialog = msi_dialog_create( package, name, parent,
ControlEvent_HandleControlEvent );
if( dialog )
{
@ -111,7 +111,12 @@ static UINT ControlEvent_EndDialog(MSIPACKAGE* package, LPCWSTR argument,
else if (lstrcmpW(argument, szIgnore) == 0)
package->CurrentInstallState = -1;
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;
}
else
{
ERR("Unknown argument string %s\n",debugstr_w(argument));
@ -143,7 +148,7 @@ static UINT ControlEvent_SpawnDialog(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog *dialog)
{
/* 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 )
msi_dialog_end_dialog( dialog );
return ERROR_SUCCESS;
@ -237,10 +242,18 @@ static UINT ControlEvent_SetTargetPath(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog)
{
LPWSTR path = msi_dup_property( package, argument );
MSIRECORD *rec = MSI_CreateRecord( 1 );
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 */
r = MSI_SetTargetPathW(package, argument, path);
msi_free(path);
msi_free(&rec->hdr);
return r;
}
@ -262,14 +275,15 @@ static void free_subscriber( struct subscriber *sub )
msi_free(sub);
}
VOID ControlEvent_SubscribeToEvent( MSIPACKAGE *package, LPCWSTR event,
LPCWSTR control, LPCWSTR attribute )
VOID ControlEvent_SubscribeToEvent( MSIPACKAGE *package, msi_dialog *dialog,
LPCWSTR event, LPCWSTR control, LPCWSTR attribute )
{
struct subscriber *sub;
sub = msi_alloc(sizeof (*sub));
if( !sub )
return;
sub->dialog = dialog;
sub->event = strdupW(event);
sub->control = strdupW(control);
sub->attribute = strdupW(attribute);
@ -304,14 +318,11 @@ VOID ControlEvent_FireSubscribedEvent( MSIPACKAGE *package, LPCWSTR event,
TRACE("Firing Event %s\n",debugstr_w(event));
if (!package->dialog)
return;
LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry )
{
if (lstrcmpiW(sub->event, event))
continue;
msi_dialog_handle_event( package->dialog, sub->control,
msi_dialog_handle_event( sub->dialog, sub->control,
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
* 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 )
{
LPWSTR name = package->next_dialog;
package->next_dialog = NULL;
r = event_do_dialog( package, name, TRUE );
r = event_do_dialog( package, name, NULL, TRUE );
msi_free( name );
}
@ -398,6 +409,7 @@ static const struct _events Events[] = {
{ "Reset",ControlEvent_Reset },
{ "SetInstallLevel",ControlEvent_SetInstallLevel },
{ "DirectoryListUp",ControlEvent_DirectoryListUp },
{ "SelectionBrowse",ControlEvent_SpawnDialog },
{ NULL,NULL },
};

View file

@ -45,7 +45,6 @@
#include "winreg.h"
#include "shlwapi.h"
#include "wine/unicode.h"
#include "action.h"
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};
extern LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename );
/*
* 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);
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:
msi_free(data);
return rc;
@ -242,7 +239,7 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
NULL, CREATE_ALWAYS, attrs, NULL );
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() );
return 0;
}
@ -793,7 +790,7 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
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());
FIXME("We should track these duplicate files as well\n");

View file

@ -26,7 +26,6 @@
#include "wine/debug.h"
#include "msipriv.h"
#include "wine/unicode.h"
#include "action.h"
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 "winnls.h"
#include "wine/unicode.h"
#include "action.h"
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,
size/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)
nd2 = msi_realloc(newdata,(size+chunk));
else
@ -583,7 +582,7 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr,
if (value!=NULL)
{
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);
if (size)
nd2= msi_realloc(newdata,(size + chunk));
@ -616,7 +615,7 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
DWORD len;
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);
if (!rec)
@ -663,7 +662,7 @@ UINT MSI_FormatRecordA( MSIPACKAGE* package, MSIRECORD* record, LPSTR buffer,
DWORD len,lenA;
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);
if (!rec)

View file

@ -33,7 +33,7 @@
#include "msipriv.h"
#include "winuser.h"
#include "wine/unicode.h"
#include "action.h"
#include "msidefs.h"
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};
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 cszbs[]={'\\',0};
@ -217,10 +218,14 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
if (!name)
return NULL;
f = get_loaded_folder( package, name );
if (!f)
return NULL;
/* special resolving for Target and Source root dir */
if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
{
if (!source)
if (!f->ResolvedTarget && !f->Property)
{
LPWSTR check_path;
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)
MSI_SetPropertyW(package,cszTargetDir,path);
msi_free(check_path);
}
else
path = get_source_root( package );
if (folder)
*folder = get_loaded_folder( package, name );
return path;
}
f = get_loaded_folder( package, name );
if (!f)
return NULL;
f->ResolvedTarget = path;
}
if (!f->ResolvedSource)
f->ResolvedSource = get_source_root( package );
}
if (folder)
*folder = f;
@ -405,6 +406,13 @@ static void free_feature( MSIFEATURE *feature )
{
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 )
{
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
@ -419,7 +427,7 @@ static void free_feature( MSIFEATURE *feature )
msi_free( feature );
}
void free_extension( MSIEXTENSION *ext )
static void free_extension( MSIEXTENSION *ext )
{
struct list *item, *cursor;
@ -843,6 +851,9 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
newstate = feature->ActionRequest;
if (newstate == INSTALLSTATE_ABSENT)
newstate = INSTALLSTATE_UNKNOWN;
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{
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*/
LIST_FOR_EACH_ENTRY( f, &package->features, MSIFEATURE, entry )
{
if ( component->ActionRequest != INSTALLSTATE_LOCAL )
break;
if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
f->ActionRequest != INSTALLSTATE_SOURCE )
{
continue;
}
LIST_FOR_EACH_ENTRY( clist, &f->Components, ComponentList, entry )
{
if ( clist->component == component )
if ( clist->component == component &&
(f->ActionRequest == INSTALLSTATE_LOCAL ||
f->ActionRequest == INSTALLSTATE_SOURCE) )
{
if (f->ActionRequest == INSTALLSTATE_LOCAL)
TRACE("Saved by %s\n", debugstr_w(f->Feature));
if (component->Attributes & msidbComponentAttributesOptional)
{
TRACE("Saved by %s\n", debugstr_w(f->Feature));
component->ActionRequest = INSTALLSTATE_LOCAL;
component->Action = INSTALLSTATE_LOCAL;
if (f->Attributes & msidbFeatureAttributesFavorSource)
{
component->Action = INSTALLSTATE_SOURCE;
component->ActionRequest = INSTALLSTATE_SOURCE;
}
else
{
component->Action = INSTALLSTATE_LOCAL;
component->ActionRequest = INSTALLSTATE_LOCAL;
}
}
break;
else if (component->Attributes & msidbComponentAttributesSourceOnly)
{
component->Action = INSTALLSTATE_SOURCE;
component->ActionRequest = INSTALLSTATE_SOURCE;
}
else
{
component->Action = INSTALLSTATE_LOCAL;
component->ActionRequest = INSTALLSTATE_LOCAL;
}
}
}
}

View file

@ -78,7 +78,7 @@ static MSIRECORD *INSERT_merge_record( UINT fields, column_info *vl, MSIRECORD *
switch( vl->val->type )
{
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 );
break;
case EXPR_IVAL:

View file

@ -30,7 +30,6 @@
#include "msi.h"
#include "msidefs.h"
#include "msipriv.h"
#include "action.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -138,7 +137,7 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
if (len)
len--;
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;
}
@ -151,8 +150,8 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
/***********************************************************************
* MsiGetTargetPath (internal)
*/
UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
awstring *szPathBuf, DWORD* pcchPathBuf )
static UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
awstring *szPathBuf, DWORD* pcchPathBuf )
{
MSIPACKAGE *package;
LPWSTR path;

View file

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

View file

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

View file

@ -1,7 +1,7 @@
/*
* 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
* modify it under the terms of the GNU Lesser General Public
@ -22,7 +22,7 @@ LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
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"
9 "inserte el disco %s"
10 "parámetros incorrectos"

View file

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

View file

@ -2,6 +2,7 @@
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002-2005 Mike McCormack for CodeWeavers
* 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
@ -71,6 +72,7 @@ typedef struct tagMSIDATABASE
MSIOBJECTHDR hdr;
IStorage *storage;
string_table *strings;
LPWSTR path;
LPWSTR deletefile;
LPCWSTR mode;
struct list tables;
@ -115,7 +117,7 @@ typedef struct tagMSIVIEWOPS
* fetch_int - reads one integer from {row,col} in the table
*
* This function should be called after the execute method.
* Data returned by the function should not change until
* Data returned by the function should not change until
* close or delete is called.
* To get a string value, query the database's string table with
* the integer value returned from this function.
@ -182,7 +184,7 @@ typedef struct tagMSIVIEWOPS
/*
* find_matching_rows - iterates through rows that match a value
*
* If the column type is a string then a string ID should be passed in.
* If the column type is a string then a string ID should be passed in.
* If the value to be looked up is an integer then no transformation of
* the input value is required, except if the column is a string, in which
* case a string ID should be passed in.
@ -259,6 +261,221 @@ typedef struct tagMSISUMMARYINFO
PROPVARIANT property[MSI_MAX_PROPS];
} 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_DATABASE 1
#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_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_string2idA( string_table *st, LPCSTR str, UINT *id );
extern string_table *msi_init_stringtable( int entries, UINT codepage );
@ -345,7 +561,7 @@ extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname,
/* transform functions */
extern UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg );
extern UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db,
extern UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db,
LPCWSTR szTransformFile, int iErrorCond );
/* action internals */
@ -414,11 +630,12 @@ extern MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *, LPCWSTR );
extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * );
extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * );
extern UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE*, LPCWSTR, INSTALLSTATE );
extern LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename );
/* for deformating */
extern UINT MSI_FormatRecordW( MSIPACKAGE *, MSIRECORD *, LPWSTR, DWORD * );
extern UINT MSI_FormatRecordA( MSIPACKAGE *, MSIRECORD *, LPSTR, DWORD * );
/* registry data encoding/decoding functions */
extern BOOL unsquash_guid(LPCWSTR in, LPWSTR out);
extern BOOL squash_guid(LPCWSTR in, LPWSTR out);
@ -450,7 +667,7 @@ extern LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWS
/* msi dialog interface */
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 void msi_dialog_end_dialog( msi_dialog* );
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 UINT msi_dialog_reset( 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 */
extern MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE * );
@ -487,6 +706,72 @@ extern LPVOID gUIContext;
extern WCHAR gszLogFile[MAX_PATH];
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 */
static inline void *msi_alloc( size_t len )
{

View file

@ -37,6 +37,8 @@
#include "query.h"
#include "initguid.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
static void MSI_CloseView( MSIOBJECTHDR *arg )
@ -314,11 +316,10 @@ UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
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_free( sval );
}
else
{
@ -662,30 +663,40 @@ MSIHANDLE WINAPI MsiGetLastErrorRecord( void )
DEFINE_GUID( CLSID_MsiTransform, 0x000c1082, 0x0000, 0x0000, 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db,
UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db,
LPCWSTR szTransformFile, int iErrorCond )
{
UINT r;
HRESULT r;
UINT ret = ERROR_FUNCTION_FAILED;
IStorage *stg = NULL;
STATSTG stat;
TRACE("%p %s %d\n", db, debugstr_w(szTransformFile), iErrorCond);
r = StgOpenStorage( szTransformFile, NULL,
STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
if( r )
return r;
if ( FAILED(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 ) )
enum_stream_names( stg );
r = msi_table_apply_transform( db, stg );
ret = msi_table_apply_transform( db, stg );
end:
IStorage_Release( stg );
return r;
return ret;
}
UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
LPCWSTR szTransformFile, int iErrorCond)
{
MSIDATABASE *db;
@ -814,7 +825,7 @@ UINT MSI_DatabaseGetPrimaryKeys( MSIDATABASE *db,
r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info );
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 */
info.rec = MSI_CreateRecord( info.n );

View file

@ -43,12 +43,9 @@
#include "msidefs.h"
#include "msipriv.h"
#include "action.h"
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_FreePackage( MSIOBJECTHDR *arg)
@ -144,6 +141,9 @@ static VOID set_installer_properties(MSIPACKAGE *package)
DWORD verval;
WCHAR verstr[10], bufstr[20];
HDC dc;
LPWSTR check;
HKEY hkey;
LONG res;
static const WCHAR cszbs[]={'\\',0};
static const WCHAR CFF[] =
@ -213,6 +213,18 @@ static VOID set_installer_properties(MSIPACKAGE *package)
static const WCHAR szScreenFormat[] = {'%','d',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 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;
/*
@ -356,6 +368,32 @@ static VOID set_installer_properties(MSIPACKAGE *package)
sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
MSI_SetPropertyW( package, szColorBits, bufstr );
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 )
@ -427,6 +465,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
list_init( &package->RunningActions );
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
* prep for all that is to come as a package */
@ -513,6 +552,10 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
MSIHANDLE handle;
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);
if( szPackage[0] == '#' )
@ -551,20 +594,16 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
if( !package )
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] != '#' )
{
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, Database, szPackage );
}
else
{
MSI_SetPropertyW( package, OriginalDatabase, db->path );
MSI_SetPropertyW( package, Database, db->path );
}
*pPackage = package;
@ -576,13 +615,13 @@ UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phP
MSIPACKAGE *package = NULL;
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 )
return ERROR_INVALID_PARAMETER;
if( dwOptions )
FIXME("dwOptions %08lx not supported\n", dwOptions);
FIXME("dwOptions %08x not supported\n", dwOptions);
ret = MSI_OpenPackageW( szPackage, &package );
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));
/* convert it to ASCII */
@ -1009,7 +1048,7 @@ UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName,
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;
}
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 */
if( szDialogName )
{
dialog = msi_dialog_create( preview->package, szDialogName,
dialog = msi_dialog_create( preview->package, szDialogName, NULL,
preview_event_handler );
if( dialog )
msi_dialog_do_preview( dialog );

View file

@ -641,7 +641,7 @@ static UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm)
ulSize.QuadPart = sz;
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;
}

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 )
{
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 )
@ -343,7 +343,7 @@ LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
LPCWSTR p = value;
while (*p) p += lstrlenW(p) + 1;
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 )
@ -687,8 +687,8 @@ UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
DWORD r;
WCHAR szwGuid[GUID_SIZE];
TRACE("%ld %p\n",index,lpguid);
TRACE("%d %p\n", index, lpguid);
if (NULL == lpguid)
return ERROR_INVALID_PARAMETER;
r = MsiEnumProductsW(index, szwGuid);
@ -704,7 +704,7 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
DWORD r;
WCHAR szKeyName[SQUISH_GUID_SIZE];
TRACE("%ld %p\n",index,lpguid);
TRACE("%d %p\n", index, lpguid);
if (NULL == lpguid)
return ERROR_INVALID_PARAMETER;
@ -728,7 +728,7 @@ UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
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 )
{
@ -757,7 +757,7 @@ UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
HKEY hkeyProduct = 0;
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 )
return ERROR_INVALID_PARAMETER;
@ -778,7 +778,7 @@ UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
DWORD r;
WCHAR szwGuid[GUID_SIZE];
TRACE("%ld %p\n",index,lpguid);
TRACE("%d %p\n", index, lpguid);
r = MsiEnumComponentsW(index, szwGuid);
if( r == ERROR_SUCCESS )
@ -793,7 +793,7 @@ UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
DWORD r;
WCHAR szKeyName[SQUISH_GUID_SIZE];
TRACE("%ld %p\n",index,lpguid);
TRACE("%d %p\n", index, lpguid);
r = MSIREG_OpenComponents(&hkeyComponents);
if( r != ERROR_SUCCESS )
@ -813,7 +813,7 @@ UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
WCHAR szwProduct[GUID_SIZE];
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 )
{
@ -840,7 +840,7 @@ UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
DWORD r, sz;
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);
if( r != ERROR_SUCCESS )
@ -856,7 +856,7 @@ UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
return r;
}
UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
static UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
awstring *lpQualBuf, DWORD* pcchQual,
awstring *lpAppBuf, DWORD* pcchAppBuf )
{
@ -865,7 +865,7 @@ UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
UINT r, r2;
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);
if (!szComponent)
@ -902,7 +902,7 @@ UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
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;
}
@ -925,7 +925,7 @@ UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
goto end;
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;
}
@ -961,7 +961,7 @@ UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
LPWSTR comp;
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,
pcchApplicationDataBuf);
@ -990,7 +990,7 @@ UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
{
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,
pcchApplicationDataBuf);
@ -1015,7 +1015,7 @@ UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
HKEY hkey;
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);
if (NULL == szUpgradeCode)
@ -1046,7 +1046,7 @@ UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
WCHAR productW[GUID_SIZE];
UINT r;
TRACE("%s %lu %lu %p\n", debugstr_a(szUpgradeCode), dwReserved,
TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
iProductIndex, lpProductBuf);
if (szUpgradeCode)
@ -1070,10 +1070,10 @@ UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
/***********************************************************************
* MsiEnumPatchesA [MSI.@]
*/
UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
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);
return ERROR_NO_MORE_ITEMS;
}
@ -1081,10 +1081,10 @@ UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
/***********************************************************************
* MsiEnumPatchesW [MSI.@]
*/
UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
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);
return ERROR_NO_MORE_ITEMS;
}

View file

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

View file

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

View file

@ -163,7 +163,7 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
type = get_type( idofs[i].propid );
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;
}
@ -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 */
if( type != propdata->type )
{
ERR("wrong type %d != %ld\n", type, propdata->type);
ERR("wrong type %d != %d\n", type, propdata->type);
break;
}
@ -188,7 +188,7 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
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;
}
@ -259,7 +259,7 @@ static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
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;
}
@ -275,7 +275,7 @@ static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
if( SUCCEEDED(r) && count == sz )
read_properties_from_data( si->property, data, sz + SECT_HDR_SIZE );
else
ERR("failed to read properties %ld %ld\n", count, sz);
ERR("failed to read properties %d %d\n", count, sz);
msi_free( data );
return ret;
@ -506,7 +506,7 @@ UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount)
{
MSISUMMARYINFO *si;
TRACE("%ld %p\n",hSummaryInfo, pCount);
TRACE("%ld %p\n", hSummaryInfo, pCount);
si = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
if( !si )

View file

@ -27,15 +27,17 @@
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
#include "msipriv.h"
#include "query.h"
#include "assert.h"
#include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
@ -71,11 +73,16 @@ typedef struct tagMSITRANSFORM {
IStorage *stg;
} 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
static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name,
MSICOLUMNINFO **pcols, UINT *pcount );
static UINT get_tablecolumns( MSIDATABASE *db,
static UINT get_tablecolumns( MSIDATABASE *db,
LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz);
static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count );
@ -208,7 +215,7 @@ void enum_stream_names( IStorage *stg )
if( FAILED( r ) || !count )
break;
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) );
n++;
}
@ -236,14 +243,14 @@ static UINT read_stream_data( IStorage *stg, LPCWSTR stname,
msi_free( encname );
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;
}
r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
if( FAILED( r ) )
{
WARN("open stream failed r = %08lx!\n",r);
WARN("open stream failed r = %08x!\n", r);
goto end;
}
@ -257,7 +264,7 @@ static UINT read_stream_data( IStorage *stg, LPCWSTR stname,
data = msi_alloc( sz );
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;
goto end;
}
@ -266,7 +273,7 @@ static UINT read_stream_data( IStorage *stg, LPCWSTR stname,
if( FAILED( r ) || ( count != sz ) )
{
msi_free( data );
WARN("read stream failed r = %08lx!\n",r);
WARN("read stream failed r = %08x!\n", r);
goto end;
}
@ -326,7 +333,7 @@ UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
if( FAILED( r ) )
{
WARN("open stream failed r = %08lx!\n",r);
WARN("open stream failed r = %08x!\n", r);
goto end;
}
@ -340,7 +347,7 @@ UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
data = msi_alloc( sz );
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;
goto end;
}
@ -349,7 +356,7 @@ UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
if( FAILED( r ) || ( count != sz ) )
{
msi_free( data );
WARN("read stream failed r = %08lx!\n",r);
WARN("read stream failed r = %08x!\n", r);
goto end;
}
@ -385,7 +392,7 @@ static UINT write_stream_data( IStorage *stg, LPCWSTR stname,
msi_free( encname );
if( FAILED( r ) )
{
WARN("open stream failed r = %08lx\n",r);
WARN("open stream failed r = %08x\n", r);
return ret;
}
@ -635,10 +642,6 @@ err:
HRESULT init_string_table( IStorage *stg )
{
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 };
ULONG count = 0;
IStream *stm = NULL;
@ -687,10 +690,6 @@ string_table *load_string_table( IStorage *stg )
USHORT *pool = NULL;
UINT r, datasize = 0, poolsize = 0, codepage;
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 );
if( r != ERROR_SUCCESS)
@ -746,15 +745,15 @@ string_table *load_string_table( IStorage *stg )
r = msi_addstring( st, n, data+offset, len, refs );
if( r != n )
ERR("Failed to add string %ld\n", n );
ERR("Failed to add string %d\n", n );
n++;
offset += len;
}
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:
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 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;
USHORT *pool = NULL;
@ -811,7 +806,10 @@ static UINT save_string_table( MSIDATABASE *db )
if( sz && (sz < (datasize - used ) ) )
sz--;
pool[ n*2 + 1 ] = msi_id_refcount( db->strings, i );
if (sz)
pool[ n*2 + 1 ] = msi_id_refcount( db->strings, i );
else
pool[ n*2 + 1 ] = 0;
if (sz < 0x10000)
{
pool[ n*2 ] = sz;
@ -924,17 +922,19 @@ 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 ));
}
static UINT get_tablecolumns( MSIDATABASE *db,
static UINT get_tablecolumns( MSIDATABASE *db,
LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz)
{
UINT r, i, n=0, table_id, count, maxcount = *sz;
MSITABLE *table = NULL;
TRACE("%s\n", debugstr_w(szTableName));
/* first check if there is a default table with that name */
r = get_defaulttablecolumns( szTableName, colinfo, 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);
/* if maxcount is non-zero, assume it's exactly right for this table */
memset( colinfo, 0, maxcount*sizeof(*colinfo) );
count = table->row_count;
for( i=0; i<count; i++ )
{
@ -965,31 +967,53 @@ static UINT get_tablecolumns( MSIDATABASE *db,
if( colinfo )
{
UINT id = table->data[ i ] [ 2 ];
colinfo[n].tablename = MSI_makestring( db, table_id );
colinfo[n].number = table->data[ i ][ 1 ] - (1<<15);
colinfo[n].colname = MSI_makestring( db, id );
colinfo[n].type = table->data[ i ] [ 3 ] ^ 0x8000;
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) )
UINT col = table->data[ i ][ 1 ] - (1<<15);
/* check the column number is in range */
if (col<1 || col>maxcount)
{
ERR("oops. data in the _Columns table isn't in the right "
"order for table %s\n", debugstr_w(szTableName));
return ERROR_FUNCTION_FAILED;
ERR("column %d out of range\n", col);
continue;
}
/* 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++;
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;
@ -1107,6 +1131,7 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
LPWSTR full_name;
DWORD len;
static const WCHAR szDot[] = { '.', 0 };
WCHAR number[0x20];
if( !view->ops->fetch_int )
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 )
return r;
/* now get the column with the name of the stream */
r = view->ops->fetch_int( view, row, ival, &refcol );
if( r != ERROR_SUCCESS )
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;
}
/* lookup the string value from the string table */
sval = msi_string_lookup_id( tv->db->strings, refcol );
if( !sval )
return ERROR_INVALID_PARAMETER;
if ( tv->columns[ival - 1].type & MSITYPE_STRING )
{
/* now get the column with the name of the stream */
r = view->ops->fetch_int( view, row, ival, &refcol );
if ( r != ERROR_SUCCESS )
return r;
/* lookup the string value from the string table */
sval = msi_string_lookup_id( tv->db->strings, refcol );
if ( !sval )
return ERROR_INVALID_PARAMETER;
}
else
{
static const WCHAR fmt[] = { '%','d',0 };
sprintfW( number, fmt, ival );
sval = number;
}
len = lstrlenW( tv->name ) + 2 + lstrlenW( sval );
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 )
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;
@ -1662,7 +1705,7 @@ static MSIRECORD *msi_get_transform_record( MSITABLEVIEW *tv, string_table *st,
if( !rec )
return rec;
TRACE("row -> ");
TRACE("row ->\n");
for( i=0; i<tv->num_cols; 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 );
MSI_RecordSetStringW( rec, i+1, sval );
TRACE("[%s]", debugstr_w(sval));
TRACE(" field %d [%s]\n", i+1, debugstr_w(sval));
}
else
{
val ^= 0x8000;
MSI_RecordSetInteger( rec, i+1, val );
TRACE("[0x%04x]", val );
if (val)
MSI_RecordSetInteger( rec, i+1, val^0x8000 );
TRACE(" field %d [0x%04x]\n", i+1, val );
}
break;
case 4:
val = rawdata[ofs] + (rawdata[ofs + 1]<<16);
/* val ^= 0x80000000; */
MSI_RecordSetInteger( rec, i+1, val );
TRACE("[0x%08x]", val );
val = (rawdata[ofs] + (rawdata[ofs + 1]<<16));
if (val)
MSI_RecordSetInteger( rec, i+1, val^0x80000000 );
TRACE(" field %d [0x%08x]\n", i+1, val );
break;
default:
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;
}
TRACE("\n");
return rec;
}
@ -1766,7 +1808,13 @@ static UINT* msi_record_to_row( MSITABLEVIEW *tv, MSIRECORD *rec )
}
}
else
{
data[i] = MSI_RecordGetInteger( rec, i+1 );
if ((tv->columns[i].type&0xff) == 2)
data[i] += 0x8000;
else
data[i] += 0x80000000;
}
}
return data;
}
@ -1837,9 +1885,20 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
MSITABLEVIEW *tv = NULL;
UINT r, n, sz, i, mask;
MSIRECORD *rec = NULL;
UINT colcol = 0;
WCHAR coltable[32];
coltable[0] = 0;
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 */
r = TABLE_CreateView( db, name, (MSIVIEW**) &tv );
if( r != ERROR_SUCCESS )
@ -1849,15 +1908,6 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
if( r != ERROR_SUCCESS )
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",
debugstr_w(name), tv->num_cols, tv->row_size, rawsize );
@ -1904,31 +1954,60 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
rec = msi_get_transform_record( tv, st, &rawdata[n] );
if (rec)
{
UINT row = 0;
r = msi_table_find_row( tv, rec, &row );
if( rawdata[n] & 1)
if ( mask & 1 )
{
TRACE("insert [%d]: ", row);
TABLE_insert_row( &tv->view, rec );
}
else if( mask & 0xff )
{
TRACE("modify [%d]: ", row);
msi_table_modify_row( tv, rec, row, mask );
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
{
TRACE("delete [%d]: ", row);
msi_delete_row( tv, row );
UINT row = 0;
r = msi_table_find_row( tv, rec, &row );
if (r != ERROR_SUCCESS)
ERR("no matching row to transform\n");
else if ( mask )
{
TRACE("modifying row [%d]:\n", row);
msi_table_modify_row( tv, rec, row, mask );
}
else
{
TRACE("deleting row [%d]:\n", row);
msi_delete_row( tv, row );
}
}
if( TRACE_ON(msidb) ) dump_record( rec );
msiobj_release( &rec->hdr );
}
n += sz/2;
}
err:
@ -1950,7 +2029,7 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
IEnumSTATSTG *stgenum = NULL;
HRESULT r;
STATSTG stat;
ULONG n, count;
ULONG count;
WCHAR name[0x40];
string_table *strings;
UINT ret = ERROR_FUNCTION_FAILED;
@ -1965,7 +2044,18 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
if( FAILED( r ) )
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;
while( r == ERROR_SUCCESS )
@ -1974,12 +2064,20 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
if( FAILED( r ) || !count )
break;
decode_streamname( stat.pwcsName, name );
if( ( name[0] == 0x4840 ) && ( name[1] != '_' ) )
ret = msi_table_load_transform( db, stg, strings, name+1 );
else
TRACE("transform contains stream %s\n", debugstr_w(name));
n++;
if ( name[0] != 0x4840 )
continue;
TRACE("transform contains stream %s\n", debugstr_w(name));
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 )

View file

@ -36,7 +36,6 @@
#include "msidefs.h"
#include "msipriv.h"
#include "winuser.h"
#include "action.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -124,7 +123,7 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
while (rc == ERROR_SUCCESS)
{
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)
{
WCHAR productid[GUID_SIZE];
@ -179,7 +178,7 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
(LPBYTE)&check, &sz);
RegCloseKey(hukey);
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));
if (!check_language(check, language, attributes))
{