mirror of
https://github.com/reactos/reactos.git
synced 2025-08-01 18:43:30 +00:00
Autosyncing with Wine HEAD
svn path=/trunk/; revision=24610
This commit is contained in:
parent
d8762edcd7
commit
f332d881af
30 changed files with 1719 additions and 723 deletions
|
@ -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[] = {
|
||||
|
|
|
@ -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__ */
|
|
@ -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)
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "msipriv.h"
|
||||
#include "winuser.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "action.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "msi.h"
|
||||
#include "msiquery.h"
|
||||
#include "msipriv.h"
|
||||
#include "action.h"
|
||||
|
||||
#define YYLEX_PARAM info
|
||||
#define YYPARSE_PARAM info
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "wine/debug.h"
|
||||
#include "msipriv.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "action.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
/* {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue