Update MSI to current Wine version.

Autosync will be put in place very soon for this dll.

svn path=/trunk/; revision=23808
This commit is contained in:
Hervé Poussineau 2006-08-30 19:24:26 +00:00
parent 6d52441d10
commit 21aef1a7a7
48 changed files with 1564 additions and 726 deletions

View file

@ -1,75 +0,0 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = msi.dll
IMPORTLIB = libmsi.$(IMPLIBEXT)
IMPORTS = urlmon wininet comctl32 shell32 shlwapi cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32
EXTRALIBS = -luuid
C_SRCS = \
action.c \
appsearch.c \
classes.c \
create.c \
custom.c \
database.c \
delete.c \
dialog.c \
distinct.c \
events.c \
files.c \
format.c \
handle.c \
helpers.c \
insert.c \
install.c \
join.c \
msi.c \
msi_main.c \
msiquery.c \
order.c \
package.c \
preview.c \
record.c \
registry.c \
regsvr.c \
select.c \
source.c \
string.c \
suminfo.c \
table.c \
tokenize.c \
update.c \
upgrade.c \
where.c
RC_SRCS = msi.rc
RC_BINSRC = msi.rc
RC_BINARIES = \
instabsent.bmp \
instadvert.bmp \
instlocal.bmp
EXTRA_SRCS = sql.y cond.y
EXTRA_OBJS = sql.tab.o cond.tab.o
SUBDIRS = tests
@MAKE_DLL_RULES@
sql.tab.c sql.tab.h: sql.y
$(BISON) -p SQL_ -d $(SRCDIR)/sql.y -o sql.tab.c
cond.tab.c cond.tab.h: cond.y
$(BISON) -p COND_ -d $(SRCDIR)/cond.y -o cond.tab.c
# hack to allow parallel make
sql.tab.h: sql.tab.c
sql.tab.o: sql.tab.h
cond.tab.h: cond.tab.c
cond.tab.o: cond.tab.h
tokenize.o: sql.tab.h
### Dependencies:

View file

@ -1123,7 +1123,6 @@ static UINT load_component( MSIRECORD *row, LPVOID param )
switch (comp->Attributes)
{
case msidbComponentAttributesLocalOnly:
case msidbComponentAttributesOptional:
comp->Action = INSTALLSTATE_LOCAL;
comp->ActionRequest = INSTALLSTATE_LOCAL;
break;
@ -1131,9 +1130,13 @@ static UINT load_component( MSIRECORD *row, LPVOID param )
comp->Action = INSTALLSTATE_SOURCE;
comp->ActionRequest = INSTALLSTATE_SOURCE;
break;
case msidbComponentAttributesOptional:
comp->Action = INSTALLSTATE_DEFAULT;
comp->ActionRequest = INSTALLSTATE_DEFAULT;
break;
default:
comp->Action = INSTALLSTATE_UNKNOWN;
comp->ActionRequest = INSTALLSTATE_UNKNOWN;
comp->Action = INSTALLSTATE_LOCAL;
comp->ActionRequest = INSTALLSTATE_LOCAL;
}
return ERROR_SUCCESS;
@ -1324,6 +1327,29 @@ static UINT load_file(MSIRECORD *row, LPVOID param)
file->state = msifs_invalid;
/* if the compressed bits are not set in the file attributes,
* then read the information from the package word count property
*/
if (file->Attributes & msidbFileAttributesCompressed)
{
file->IsCompressed = TRUE;
}
else if (file->Attributes & msidbFileAttributesNoncompressed)
{
file->IsCompressed = FALSE;
}
else
{
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 );
@ -1708,16 +1734,20 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
}
else
{
if (feature->Action == INSTALLSTATE_LOCAL)
if (feature->Attributes == msidbFeatureAttributesFavorLocal)
{
component->Action = INSTALLSTATE_LOCAL;
component->ActionRequest = INSTALLSTATE_LOCAL;
if (!(component->Attributes & msidbComponentAttributesSourceOnly))
{
component->Action = INSTALLSTATE_LOCAL;
component->ActionRequest = INSTALLSTATE_LOCAL;
}
}
else if (feature->ActionRequest == INSTALLSTATE_SOURCE)
else if (feature->Attributes == msidbFeatureAttributesFavorSource)
{
if ((component->Action == INSTALLSTATE_UNKNOWN) ||
(component->Action == INSTALLSTATE_ABSENT) ||
(component->Action == INSTALLSTATE_ADVERTISED))
(component->Action == INSTALLSTATE_ADVERTISED) ||
(component->Action == INSTALLSTATE_DEFAULT))
{
component->Action = INSTALLSTATE_SOURCE;
@ -1743,6 +1773,12 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
}
}
}
if (component->ForceLocalState)
{
feature->Action = INSTALLSTATE_LOCAL;
feature->ActionRequest = INSTALLSTATE_LOCAL;
}
}
}
@ -2915,6 +2951,10 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
Path = build_icon_path(package,buffer);
index = MSI_RecordGetInteger(row,10);
/* no value means 0 */
if (index == MSI_NULL_INTEGER)
index = 0;
IShellLinkW_SetIconLocation(sl,Path,index);
msi_free(Path);
}
@ -2927,7 +2967,8 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
LPWSTR Path;
buffer = MSI_RecordGetString(row,12);
Path = resolve_folder(package, buffer, FALSE, FALSE, NULL);
IShellLinkW_SetWorkingDirectory(sl,Path);
if (Path)
IShellLinkW_SetWorkingDirectory(sl,Path);
msi_free(Path);
}
@ -3106,6 +3147,10 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
/* FIXME: Need to write more keys to the user registry */
hDb= alloc_msihandle( &package->db->hdr );
if (!hDb) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto end;
}
rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo);
MsiCloseHandle(hDb);
if (rc == ERROR_SUCCESS)

View file

@ -59,6 +59,7 @@ typedef struct tagMSICOMPONENT
INSTALLSTATE ActionRequest;
INSTALLSTATE Action;
BOOL ForceLocalState;
BOOL Enabled;
INT Cost;
INT RefCount;
@ -119,6 +120,7 @@ typedef struct tagMSIFILE
msi_file_state state;
LPWSTR SourcePath;
LPWSTR TargetPath;
BOOL IsCompressed;
} MSIFILE;
typedef struct tagMSITEMPFILE

View file

@ -0,0 +1,177 @@
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2006 Mike McCormack
*
* 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
*/
#include <stdarg.h>
#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 "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
typedef struct tagMSIALTERVIEW
{
MSIVIEW view;
MSIDATABASE *db;
} MSIALTERVIEW;
static UINT ALTER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %d %d %p\n", av, row, col, val );
return ERROR_FUNCTION_FAILED;
}
static UINT ALTER_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %d %d %p\n", av, row, col, stm );
return ERROR_FUNCTION_FAILED;
}
static UINT ALTER_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %d %d %04x\n", av, row, col, val );
return ERROR_FUNCTION_FAILED;
}
static UINT ALTER_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %p\n", av, record );
return ERROR_FUNCTION_FAILED;
}
static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
FIXME("%p %p\n", av, record);
return ERROR_SUCCESS;
}
static UINT ALTER_close( struct tagMSIVIEW *view )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p\n", av );
return ERROR_SUCCESS;
}
static UINT ALTER_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %p %p\n", av, rows, cols );
return ERROR_FUNCTION_FAILED;
}
static UINT ALTER_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %d %p %p\n", av, n, name, type );
return ERROR_FUNCTION_FAILED;
}
static UINT ALTER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %d %p\n", av, eModifyMode, rec );
return ERROR_FUNCTION_FAILED;
}
static UINT ALTER_delete( struct tagMSIVIEW *view )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p\n", av );
msi_free( av );
return ERROR_SUCCESS;
}
static UINT ALTER_find_matching_rows( struct tagMSIVIEW *view, UINT col,
UINT val, UINT *row, MSIITERHANDLE *handle )
{
TRACE("%p, %d, %u, %p\n", view, col, val, *handle);
return ERROR_FUNCTION_FAILED;
}
static const MSIVIEWOPS alter_ops =
{
ALTER_fetch_int,
ALTER_fetch_stream,
ALTER_set_int,
ALTER_insert_row,
ALTER_execute,
ALTER_close,
ALTER_get_dimensions,
ALTER_get_column_info,
ALTER_modify,
ALTER_delete,
ALTER_find_matching_rows
};
UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, int hold )
{
MSIALTERVIEW *av = NULL;
TRACE("%p\n", av );
av = msi_alloc_zero( sizeof *av );
if( !av )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
av->view.ops = &alter_ops;
av->db = db;
*view = &av->view;
return ERROR_SUCCESS;
}

View file

@ -798,7 +798,6 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
static const WCHAR szVIProgID[] = { 'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0 };
static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
static const WCHAR szSpace[] = {' ',0};
static const WCHAR szInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
HKEY hkey,hkey2,hkey3;
MSICLASS *cls;
@ -808,16 +807,11 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
if (rc != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
/* install_on_demand should be set if OLE supports install on demand OLE
* servers. For now i am defaulting to FALSE because i do not know how to
* check, and i am told our builtin OLE does not support it
*/
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
{
MSICOMPONENT *comp;
MSIFILE *file;
DWORD size, sz;
DWORD size;
LPWSTR argument;
MSIFEATURE *feature;
@ -827,17 +821,14 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
feature = cls->Feature;
/*
* yes. MSDN says that these are based on _Feature_ not on
* Component. So verify the feature is to be installed
/*
* MSDN says that these are based on Feature not on Component.
*/
if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ))
/* && !(install_on_demand &&
ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED ))) */
if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ) &&
!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED ))
{
TRACE("Skipping class %s reg due to disabled feature %s\n",
debugstr_w(cls->clsid),
debugstr_w(feature->Feature));
TRACE("Skipping class %s reg due to disabled feature %s\n",
debugstr_w(cls->clsid), debugstr_w(feature->Feature));
continue;
}
@ -855,63 +846,28 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
RegCreateKeyW( hkey2, cls->Context, &hkey3 );
file = get_loaded_file( package, comp->KeyPath );
/* the context server is a short path name
* except for if it is InprocServer32...
/*
* FIXME: Implement install on demand (advertised components).
*
* ole32.dll should call msi.MsiProvideComponentFromDescriptor()
* when it needs an InProcServer that doesn't exist.
* The component advertise string should be in the "InProcServer" value.
*/
if (strcmpiW( cls->Context, szInprocServer32 )!=0)
size = lstrlenW( file->TargetPath )+1;
if (cls->Argument)
size += lstrlenW(cls->Argument)+1;
argument = msi_alloc( size * sizeof(WCHAR) );
lstrcpyW( argument, file->TargetPath );
if (cls->Argument)
{
sz = GetShortPathNameW( file->TargetPath, NULL, 0 );
if (sz == 0)
{
ERR("Unable to find short path for CLSID COM Server\n");
argument = NULL;
}
else
{
size = sz * sizeof(WCHAR);
if (cls->Argument)
{
size += strlenW(cls->Argument) * sizeof(WCHAR);
size += sizeof(WCHAR);
}
argument = msi_alloc( size + sizeof(WCHAR));
GetShortPathNameW( file->TargetPath, argument, sz );
if (cls->Argument)
{
strcatW(argument,szSpace);
strcatW( argument, cls->Argument );
}
}
}
else
{
size = lstrlenW( file->TargetPath ) * sizeof(WCHAR);
if (cls->Argument)
{
size += strlenW(cls->Argument) * sizeof(WCHAR);
size += sizeof(WCHAR);
}
argument = msi_alloc( size + sizeof(WCHAR));
strcpyW( argument, file->TargetPath );
if (cls->Argument)
{
strcatW(argument,szSpace);
strcatW( argument, cls->Argument );
}
lstrcatW( argument, szSpace );
lstrcatW( argument, cls->Argument );
}
if (argument)
{
msi_reg_set_val_str( hkey3, NULL, argument );
msi_free(argument);
}
msi_reg_set_val_str( hkey3, NULL, argument );
msi_free(argument);
RegCloseKey(hkey3);
@ -934,7 +890,7 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
}
if (cls->AppID)
{
{
MSIAPPID *appid = cls->AppID;
msi_reg_set_val_str( hkey2, szAppID, appid->AppID );

View file

@ -396,8 +396,61 @@ static WCHAR *strstriW( const WCHAR *str, const WCHAR *sub )
return r;
}
static BOOL str_is_number( LPCWSTR str )
{
int i;
for (i = 0; i < lstrlenW( str ); i++)
if (!isdigitW(str[i]))
return FALSE;
return TRUE;
}
static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
{
int lhs, rhs;
/* substring operators return 0 if LHS is missing */
if (!a || !*a)
return 0;
/* substring operators return 1 if RHS is missing */
if (!b || !*b)
return 1;
/* if both strings contain only numbers, use integer comparison */
lhs = atoiW(a);
rhs = atoiW(b);
if (str_is_number(a) && str_is_number(b))
return compare_int( lhs, operator, rhs );
switch (operator)
{
case COND_SS:
return strstrW( a, b ) ? 1 : 0;
case COND_ISS:
return strstriW( a, b ) ? 1 : 0;
case COND_LHS:
return 0 == strncmpW( a, b, lstrlenW( b ) );
case COND_RHS:
return 0 == lstrcmpW( a + (lstrlenW( a ) - lstrlenW( b )), b );
case COND_ILHS:
return 0 == strncmpiW( a, b, lstrlenW( b ) );
case COND_IRHS:
return 0 == lstrcmpiW( a + (lstrlenW( a ) - lstrlenW( b )), b );
default:
ERR("invalid substring operator\n");
return 0;
}
return 0;
}
static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b )
{
if (operator >= COND_SS && operator <= COND_RHS)
return compare_substring( a, operator, b );
/* null and empty string are equivalent */
if (!a) a = szEmpty;
if (!b) b = szEmpty;
@ -417,8 +470,6 @@ static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b )
return -1 != lstrcmpW( a, b );
case COND_LE:
return 1 != lstrcmpW( a, b );
case COND_SS: /* substring */
return strstrW( a, b ) ? 1 : 0;
case COND_ILT:
return -1 == lstrcmpiW( a, b );
case COND_IGT:
@ -431,16 +482,8 @@ static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b )
return -1 != lstrcmpiW( a, b );
case COND_ILE:
return 1 != lstrcmpiW( a, b );
case COND_ISS:
return strstriW( a, b ) ? 1 : 0;
case COND_LHS:
case COND_RHS:
case COND_ILHS:
case COND_IRHS:
ERR("unimplemented string comparison\n");
break;
default:
ERR("invalid integer operator\n");
ERR("invalid string operator\n");
return 0;
}
return 0;
@ -508,10 +551,10 @@ static int COND_GetOperator( COND_input *cond )
{ {'>','=',0}, COND_GE },
{ {'>','<',0}, COND_SS },
{ {'<','<',0}, COND_LHS },
{ {'>',0}, COND_GT },
{ {'<','>',0}, COND_NE },
{ {'<','=',0}, COND_LE },
{ {'>','>',0}, COND_RHS },
{ {'>',0}, COND_GT },
{ {'<',0}, COND_LT },
{ {0}, 0 }
};

View file

@ -93,8 +93,10 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
r = StgOpenStorage( szDBPath, NULL,
STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
}
else if( szPersist == MSIDBOPEN_CREATE )
else if( szPersist == MSIDBOPEN_CREATE || szPersist == MSIDBOPEN_CREATEDIRECT )
{
/* FIXME: MSIDBOPEN_CREATE should case STGM_TRANSACTED flag to be
* used here: */
r = StgCreateDocfile( szDBPath,
STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
if( r == ERROR_SUCCESS )
@ -104,6 +106,13 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
}
}
else if( szPersist == MSIDBOPEN_TRANSACT )
{
/* FIXME: MSIDBOPEN_TRANSACT should case STGM_TRANSACTED flag to be
* used here: */
r = StgOpenStorage( szDBPath, NULL,
STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
}
else if( szPersist == MSIDBOPEN_DIRECT )
{
r = StgOpenStorage( szDBPath, NULL,
STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
@ -181,6 +190,8 @@ UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phD
if( ret == ERROR_SUCCESS )
{
*phDB = alloc_msihandle( &db->hdr );
if (! *phDB)
ret = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &db->hdr );
}

View file

@ -26,9 +26,9 @@
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "wingdi.h"
#include "msi.h"
#include "msipriv.h"
#include "msidefs.h"
@ -36,6 +36,8 @@
#include "olectl.h"
#include "richedit.h"
#include "commctrl.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
@ -64,6 +66,7 @@ struct msi_control_tag
HMODULE hDll;
float progress_current;
float progress_max;
DWORD attributes;
WCHAR name[1];
};
@ -136,6 +139,9 @@ static const WCHAR szSelectionTree[] = {
'S','e','l','e','c','t','i','o','n','T','r','e','e',0 };
static const WCHAR szGroupBox[] = { 'G','r','o','u','p','B','o','x',0 };
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 UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM );
static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * );
@ -191,6 +197,17 @@ static LPWSTR msi_get_deformatted_field( MSIPACKAGE *package, MSIRECORD *rec, in
return ret;
}
static LPWSTR msi_dialog_dup_property( msi_dialog *dialog, LPCWSTR property, BOOL indirect )
{
if (!property)
return NULL;
if (indirect)
return msi_dup_property( dialog->package, property );
return strdupW( property );
}
/*
* msi_dialog_get_style
*
@ -750,6 +767,9 @@ static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec )
{
TRACE("%p %p\n", dialog, rec);
/* line is exactly 2 units in height */
MSI_RecordSetInteger( rec, 7, 2 );
msi_dialog_add_control( dialog, rec, szStatic, SS_ETCHEDHORZ | SS_SUNKEN );
return ERROR_SUCCESS;
}
@ -1354,10 +1374,83 @@ static UINT msi_dialog_progress_bar( msi_dialog *dialog, MSIRECORD *rec )
/******************** Path Edit ********************************************/
static LPWSTR msi_get_window_text( HWND hwnd )
{
UINT sz, r;
LPWSTR buf;
sz = 0x20;
buf = msi_alloc( sz*sizeof(WCHAR) );
while ( buf )
{
r = GetWindowTextW( hwnd, buf, sz );
if ( r < (sz - 1) )
break;
sz *= 2;
buf = msi_realloc( buf, sz*sizeof(WCHAR) );
}
return buf;
}
static UINT msi_dialog_pathedit_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
LPWSTR buf, prop;
BOOL indirect;
if( HIWORD(param) != EN_KILLFOCUS )
return ERROR_SUCCESS;
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
/* FIXME: verify the new path */
buf = msi_get_window_text( control->hwnd );
MSI_SetPropertyW( dialog->package, prop, buf );
TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name),
debugstr_w(prop));
msi_free( buf );
msi_free( prop );
return ERROR_SUCCESS;
}
static void msi_dialog_update_pathedit( msi_dialog *dialog )
{
msi_control *control;
LPWSTR prop, path;
BOOL indirect;
control = msi_dialog_find_control( dialog, szPathEdit );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop );
SetWindowTextW( control->hwnd, path );
SendMessageW( control->hwnd, EM_SETSEL, 0, -1 );
msi_free( path );
msi_free( prop );
}
static UINT msi_dialog_pathedit_control( msi_dialog *dialog, MSIRECORD *rec )
{
FIXME("not implemented properly\n");
return msi_dialog_edit_control( dialog, rec );
msi_control *control;
LPCWSTR prop;
control = msi_dialog_add_control( dialog, rec, szEdit,
WS_BORDER | WS_TABSTOP );
control->handler = msi_dialog_pathedit_handler;
control->attributes = MSI_RecordGetInteger( rec, 8 );
prop = MSI_RecordGetString( rec, 9 );
control->property = msi_dialog_dup_property( dialog, prop, FALSE );
msi_dialog_update_pathedit( dialog );
return ERROR_SUCCESS;
}
/* radio buttons are a bit different from normal controls */
@ -1866,6 +1959,118 @@ static UINT msi_dialog_list_box( msi_dialog *dialog, MSIRECORD *rec )
return ERROR_SUCCESS;
}
/******************** Directory Combo ***************************************/
static void msi_dialog_update_directory_combo( msi_dialog *dialog )
{
msi_control *control;
LPWSTR prop, path;
BOOL indirect;
control = msi_dialog_find_control( dialog, szDirectoryCombo );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop );
PathStripPathW( path );
PathRemoveBackslashW( path );
SendMessageW( control->hwnd, CB_INSERTSTRING, 0, (LPARAM)path );
SendMessageW( control->hwnd, CB_SETCURSEL, 0, 0 );
msi_free( path );
msi_free( prop );
}
static UINT msi_dialog_directory_combo( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
LPCWSTR prop;
DWORD style;
/* FIXME: use CBS_OWNERDRAWFIXED and add owner draw code */
style = CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD |
WS_GROUP | WS_TABSTOP | WS_VSCROLL;
control = msi_dialog_add_control( dialog, rec, WC_COMBOBOXW, style );
if (!control)
return ERROR_FUNCTION_FAILED;
control->attributes = MSI_RecordGetInteger( rec, 8 );
prop = MSI_RecordGetString( rec, 9 );
control->property = msi_dialog_dup_property( dialog, prop, FALSE );
msi_dialog_update_directory_combo( dialog );
return ERROR_SUCCESS;
}
/******************** Directory List ***************************************/
UINT msi_dialog_directorylist_up( msi_dialog *dialog )
{
msi_control *control;
LPWSTR prop, path, ptr;
BOOL indirect;
control = msi_dialog_find_control( dialog, szDirectoryList );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop );
/* strip off the last directory */
ptr = PathFindFileNameW( path );
if (ptr != path) *(ptr - 1) = '\0';
PathAddBackslashW( path );
MSI_SetPropertyW( dialog->package, prop, path );
msi_dialog_update_directory_combo( dialog );
msi_dialog_update_pathedit( dialog );
msi_free( path );
msi_free( prop );
return ERROR_SUCCESS;
}
static UINT msi_dialog_directory_list( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
LPCWSTR prop;
DWORD style;
style = LVS_LIST | LVS_EDITLABELS | WS_VSCROLL | LVS_SHAREIMAGELISTS |
LVS_AUTOARRANGE | LVS_SINGLESEL | WS_BORDER |
LVS_SORTASCENDING | WS_CHILD | WS_GROUP | WS_TABSTOP;
control = msi_dialog_add_control( dialog, rec, WC_LISTVIEWW, style );
if (!control)
return ERROR_FUNCTION_FAILED;
control->attributes = MSI_RecordGetInteger( rec, 8 );
prop = MSI_RecordGetString( rec, 9 );
control->property = msi_dialog_dup_property( dialog, prop, FALSE );
return ERROR_SUCCESS;
}
/******************** VolumeCost List ***************************************/
static UINT msi_dialog_volumecost_list( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
DWORD style;
style = LVS_REPORT | WS_VSCROLL | WS_HSCROLL | LVS_SHAREIMAGELISTS |
LVS_AUTOARRANGE | LVS_SINGLESEL | WS_BORDER |
WS_CHILD | WS_TABSTOP | WS_GROUP;
control = msi_dialog_add_control( dialog, rec, WC_LISTVIEWW, style );
if (!control)
return ERROR_FUNCTION_FAILED;
return ERROR_SUCCESS;
}
static const struct control_handler msi_dialog_handler[] =
{
{ szText, msi_dialog_text_control },
@ -1884,6 +2089,9 @@ static const struct control_handler msi_dialog_handler[] =
{ szSelectionTree, msi_dialog_selection_tree },
{ szGroupBox, msi_dialog_group_box },
{ szListBox, msi_dialog_list_box },
{ szDirectoryCombo, msi_dialog_directory_combo },
{ szDirectoryList, msi_dialog_directory_list },
{ szVolumeCostList, msi_dialog_volumecost_list },
};
#define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0])
@ -2058,20 +2266,41 @@ static MSIRECORD *msi_get_dialog_record( msi_dialog *dialog )
return rec;
}
static void msi_dialog_adjust_dialog_size( msi_dialog *dialog, LPSIZE sz )
static void msi_dialog_adjust_dialog_pos( msi_dialog *dialog, MSIRECORD *rec, LPRECT pos )
{
RECT rect;
static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
UINT xres, yres;
POINT center;
SIZE sz;
LONG style;
/* turn the client size into the window rectangle */
rect.left = 0;
rect.top = 0;
rect.right = msi_dialog_scale_unit( dialog, sz->cx );
rect.bottom = msi_dialog_scale_unit( dialog, sz->cy );
center.x = MSI_RecordGetInteger( rec, 2 );
center.y = MSI_RecordGetInteger( rec, 3 );
sz.cx = MSI_RecordGetInteger( rec, 4 );
sz.cy = MSI_RecordGetInteger( rec, 5 );
sz.cx = msi_dialog_scale_unit( dialog, sz.cx );
sz.cy = msi_dialog_scale_unit( dialog, sz.cy );
xres = msi_get_property_int( dialog->package, szScreenX, 0 );
yres = msi_get_property_int( dialog->package, szScreenY, 0 );
center.x = MulDiv( center.x, xres, 100 );
center.y = MulDiv( center.y, yres, 100 );
/* turn the client pos into the window rectangle */
pos->left = center.x - sz.cx/2;
pos->right = pos->left + sz.cx;
pos->top = center.y - sz.cy/2;
pos->bottom = pos->top + sz.cy;
TRACE("%lu %lu %lu %lu\n", pos->left, pos->top, pos->right, pos->bottom);
style = GetWindowLongPtrW( dialog->hwnd, GWL_STYLE );
AdjustWindowRect( &rect, style, FALSE );
sz->cx = rect.right - rect.left;
sz->cy = rect.bottom - rect.top;
AdjustWindowRect( pos, style, FALSE );
}
static BOOL msi_control_set_next( msi_control *control, msi_control *next )
@ -2116,7 +2345,7 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
msi_dialog *dialog = (msi_dialog*) cs->lpCreateParams;
MSIRECORD *rec = NULL;
LPWSTR title = NULL;
SIZE size;
RECT pos;
TRACE("%p %p\n", dialog, dialog->package);
@ -2132,9 +2361,7 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
dialog->scale = msi_dialog_get_sans_serif_height(dialog->hwnd);
size.cx = MSI_RecordGetInteger( rec, 4 );
size.cy = MSI_RecordGetInteger( rec, 5 );
msi_dialog_adjust_dialog_size( dialog, &size );
msi_dialog_adjust_dialog_pos( dialog, rec, &pos );
dialog->attributes = MSI_RecordGetInteger( rec, 6 );
@ -2149,8 +2376,9 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
SetWindowTextW( hwnd, title );
msi_free( title );
SetWindowPos( hwnd, 0, 0, 0, size.cx, size.cy,
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW );
SetWindowPos( hwnd, 0, pos.left, pos.top,
pos.right - pos.left, pos.bottom - pos.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW );
msi_dialog_build_font_list( dialog );
msi_dialog_fill_controls( dialog );
@ -2320,7 +2548,6 @@ static UINT msi_dialog_checkbox_handler( msi_dialog *dialog,
static UINT msi_dialog_edit_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
UINT sz, r;
LPWSTR buf;
if( HIWORD(param) != EN_CHANGE )
@ -2329,17 +2556,7 @@ static UINT msi_dialog_edit_handler( msi_dialog *dialog,
TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name),
debugstr_w(control->property));
sz = 0x20;
buf = msi_alloc( sz*sizeof(WCHAR) );
while( buf )
{
r = GetWindowTextW( control->hwnd, buf, sz );
if( r < (sz-1) )
break;
sz *= 2;
buf = msi_realloc( buf, sz*sizeof(WCHAR) );
}
buf = msi_get_window_text( control->hwnd );
MSI_SetPropertyW( dialog->package, control->property, buf );
msi_free( buf );
@ -2598,7 +2815,7 @@ UINT msi_dialog_run_message_loop( msi_dialog *dialog )
{
while( !dialog->finished )
{
MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLEVENTS );
MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLINPUT );
msi_process_pending_messages( dialog->hwnd );
}
}

View file

@ -379,6 +379,12 @@ static UINT ControlEvent_SetInstallLevel(MSIPACKAGE* package, LPCWSTR argument,
return MSI_SetInstallLevel( package, iInstallLevel );
}
static UINT ControlEvent_DirectoryListUp(MSIPACKAGE *package, LPCWSTR argument,
msi_dialog *dialog)
{
return msi_dialog_directorylist_up( dialog );
}
static const struct _events Events[] = {
{ "EndDialog",ControlEvent_EndDialog },
{ "NewDialog",ControlEvent_NewDialog },
@ -391,6 +397,7 @@ static const struct _events Events[] = {
{ "SetTargetPath",ControlEvent_SetTargetPath },
{ "Reset",ControlEvent_Reset },
{ "SetInstallLevel",ControlEvent_SetInstallLevel },
{ "DirectoryListUp",ControlEvent_DirectoryListUp },
{ NULL,NULL },
};

View file

@ -42,6 +42,8 @@
#include "msvcrt/fcntl.h"
#include "msipriv.h"
#include "winuser.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wine/unicode.h"
#include "action.h"
@ -56,6 +58,7 @@ 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
@ -218,7 +221,7 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
if (!f)
{
ERR("Unknown File in Cabinet (%s)\n",debugstr_a(pfdin->psz1));
WARN("unknown file in cabinet (%s)\n",debugstr_a(pfdin->psz1));
return 0;
}
@ -280,6 +283,7 @@ static BOOL extract_cabinet_file(MSIPACKAGE* package, LPCWSTR source,
BOOL ret;
char *cabinet;
char *cab_path;
static CHAR empty[] = "";
CabData data;
TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path));
@ -314,7 +318,7 @@ static BOOL extract_cabinet_file(MSIPACKAGE* package, LPCWSTR source,
data.package = package;
data.cab_path = cab_path;
ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, &data);
ret = FDICopy(hfdi, cabinet, empty, 0, cabinet_notify, NULL, &data);
if (!ret)
ERR("FDICopy failed\n");
@ -330,7 +334,7 @@ static BOOL extract_cabinet_file(MSIPACKAGE* package, LPCWSTR source,
static VOID set_file_source(MSIPACKAGE* package, MSIFILE* file, MSICOMPONENT*
comp, LPCWSTR path)
{
if (file->Attributes & msidbFileAttributesNoncompressed)
if (!file->IsCompressed)
{
LPWSTR p, path;
p = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
@ -378,6 +382,52 @@ static void free_media_info( struct media_info *mi )
msi_free( mi );
}
/* downloads a remote cabinet and extracts it if it exists */
static UINT msi_extract_remote_cabinet( MSIPACKAGE *package, struct media_info *mi )
{
FDICABINETINFO cabinfo;
WCHAR temppath[MAX_PATH];
WCHAR src[MAX_PATH];
LPSTR cabpath;
LPCWSTR file;
LPWSTR ptr;
HFDI hfdi;
ERF erf;
int hf;
/* the URL is the path prefix of the package URL and the filename
* of the file to download
*/
ptr = strrchrW(package->PackagePath, '/');
lstrcpynW(src, package->PackagePath, ptr - package->PackagePath + 2);
ptr = strrchrW(mi->source, '\\');
lstrcatW(src, ptr + 1);
file = msi_download_file( src, temppath );
lstrcpyW(mi->source, file);
/* check if the remote cabinet still exists, ignore if it doesn't */
hfdi = FDICreate(cabinet_alloc, cabinet_free, cabinet_open, cabinet_read,
cabinet_write, cabinet_close, cabinet_seek, 0, &erf);
if (!hfdi)
{
ERR("FDICreate failed\n");
return ERROR_FUNCTION_FAILED;
}
cabpath = strdupWtoA(mi->source);
hf = cabinet_open(cabpath, _O_RDONLY, 0);
if (!FDIIsCabinet(hfdi, hf, &cabinfo))
{
WARN("Remote cabinet %s does not exist.\n", debugstr_w(mi->source));
msi_free(cabpath);
return ERROR_SUCCESS;
}
msi_free(cabpath);
return !extract_cabinet_file(package, mi->source, mi->last_path);
}
static UINT ready_media_for_file( MSIPACKAGE *package, struct media_info *mi,
MSIFILE *file )
{
@ -410,16 +460,13 @@ static UINT ready_media_for_file( MSIPACKAGE *package, struct media_info *mi,
return ERROR_FUNCTION_FAILED;
}
seq = MSI_RecordGetInteger(row,2);
mi->last_sequence = seq;
volume = MSI_RecordGetString(row, 5);
prompt = MSI_RecordGetString(row, 3);
msi_free(mi->last_path);
mi->last_path = NULL;
if (file->Attributes & msidbFileAttributesNoncompressed)
if (!file->IsCompressed)
{
mi->last_path = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
set_file_source(package,file,comp,mi->last_path);
@ -436,6 +483,9 @@ static UINT ready_media_for_file( MSIPACKAGE *package, struct media_info *mi,
return rc;
}
seq = MSI_RecordGetInteger(row,2);
mi->last_sequence = seq;
cab = MSI_RecordGetString(row,4);
if (cab)
{
@ -488,7 +538,17 @@ static UINT ready_media_for_file( MSIPACKAGE *package, struct media_info *mi,
GetTempPathW(MAX_PATH,mi->last_path);
}
}
rc = !extract_cabinet_file(package, mi->source, mi->last_path);
/* only download the remote cabinet file if a local copy does not exist */
if (GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES &&
UrlIsW(package->PackagePath, URLIS_URL))
{
rc = msi_extract_remote_cabinet(package, mi);
}
else
{
rc = !extract_cabinet_file(package, mi->source, mi->last_path);
}
}
else
{
@ -605,7 +665,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
continue;
/* compressed files are extracted in ready_media_for_file */
if (~file->Attributes & msidbFileAttributesNoncompressed)
if (file->IsCompressed)
{
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(file->TargetPath))
ERR("compressed file wasn't extracted (%s)\n",
@ -764,6 +824,24 @@ UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
return rc;
}
/* compares the version of a file read from the filesystem and
* the version specified in the File table
*/
static int msi_compare_file_version( MSIFILE *file )
{
WCHAR version[MAX_PATH];
DWORD size;
UINT r;
size = MAX_PATH;
version[0] = '\0';
r = MsiGetFileVersionW( file->TargetPath, version, &size, NULL, NULL );
if ( r != ERROR_SUCCESS )
return 0;
return lstrcmpW( version, file->Version );
}
UINT ACTION_RemoveFiles( MSIPACKAGE *package )
{
MSIFILE *file;
@ -784,6 +862,12 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
if ( file->state != msifs_present )
continue;
/* only remove a file if the version to be installed
* is strictly newer than the old file
*/
if ( msi_compare_file_version( file ) >= 0 )
continue;
TRACE("removing %s\n", debugstr_w(file->File) );
if ( !DeleteFileW( file->TargetPath ) )
ERR("failed to delete %s\n", debugstr_w(file->TargetPath) );

View file

@ -57,7 +57,15 @@ typedef struct msi_handle_info_t
DWORD dwThreadId;
} msi_handle_info;
static msi_handle_info msihandletable[MSIMAXHANDLES];
static msi_handle_info *msihandletable = NULL;
static int msihandletable_size = 0;
void msi_free_handle_table(void)
{
msi_free( msihandletable );
msihandletable = NULL;
msihandletable_size = 0;
}
MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj )
{
@ -67,11 +75,29 @@ MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj )
EnterCriticalSection( &MSI_handle_cs );
/* find a slot */
for(i=0; i<MSIMAXHANDLES; i++)
for(i=0; i<msihandletable_size; i++)
if( !msihandletable[i].obj )
break;
if( (i>=MSIMAXHANDLES) || msihandletable[i].obj )
goto out;
if( i==msihandletable_size )
{
msi_handle_info *p;
int newsize;
if (msihandletable_size == 0)
{
newsize = 256;
p = msi_alloc_zero(newsize*sizeof(msi_handle_info));
}
else
{
newsize = msihandletable_size * 2;
p = msi_realloc_zero(msihandletable,
newsize*sizeof(msi_handle_info));
}
if (!p)
goto out;
msihandletable = p;
msihandletable_size = newsize;
}
msiobj_addref( obj );
msihandletable[i].obj = obj;
@ -92,7 +118,7 @@ void *msihandle2msiinfo(MSIHANDLE handle, UINT type)
handle--;
if( handle<0 )
goto out;
if( handle>=MSIMAXHANDLES )
if( handle>=msihandletable_size )
goto out;
if( !msihandletable[handle].obj )
goto out;
@ -230,14 +256,18 @@ UINT WINAPI MsiCloseAllHandles(void)
TRACE("\n");
for(i=0; i<MSIMAXHANDLES; i++)
EnterCriticalSection( &MSI_handle_cs );
for(i=0; i<msihandletable_size; i++)
{
if(msihandletable[i].dwThreadId == GetCurrentThreadId())
{
LeaveCriticalSection( &MSI_handle_cs );
MsiCloseHandle( i+1 );
EnterCriticalSection( &MSI_handle_cs );
n++;
}
}
LeaveCriticalSection( &MSI_handle_cs );
return n;
}

View file

@ -72,35 +72,6 @@ LPWSTR msi_dup_record_field( MSIRECORD *row, INT index )
return strdupW( MSI_RecordGetString(row,index) );
}
LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop)
{
DWORD sz = 0;
LPWSTR str;
UINT r;
r = MSI_GetPropertyW(package, prop, NULL, &sz);
if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
return NULL;
sz++;
str = msi_alloc(sz*sizeof(WCHAR));
r = MSI_GetPropertyW(package, prop, str, &sz);
if (r != ERROR_SUCCESS)
{
msi_free(str);
str = NULL;
}
return str;
}
int msi_get_property_int( MSIPACKAGE *package, LPCWSTR prop, int def )
{
LPWSTR str = msi_dup_property( package, prop );
int val = str ? atoiW( str ) : def;
msi_free( str );
return val;
}
MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component )
{
MSICOMPONENT *comp;
@ -1009,3 +980,18 @@ WCHAR* generate_error_string(MSIPACKAGE *package, UINT error, DWORD count, ... )
data = NULL;
return data;
}
void msi_ui_error( DWORD msg_id, DWORD type )
{
WCHAR text[2048];
static const WCHAR title[] = {
'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0
};
if (!MsiLoadStringW( -1, msg_id, text, sizeof(text) / sizeof(text[0]),
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) ))
return;
MessageBoxW( NULL, text, title, type );
}

View file

@ -634,6 +634,30 @@ UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
return ret;
}
/***********************************************************************
* MsiGetFeatureCostA (MSI.@)
*/
UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
MSICOSTTREE iCostTree, INSTALLSTATE iState, INT *piCost)
{
FIXME("(%ld %s %i %i %p): stub\n", hInstall, debugstr_a(szFeature),
iCostTree, iState, piCost);
if (piCost) *piCost = 0;
return ERROR_SUCCESS;
}
/***********************************************************************
* MsiGetFeatureCostW (MSI.@)
*/
UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
MSICOSTTREE iCostTree, INSTALLSTATE iState, INT *piCost)
{
FIXME("(%ld %s %i %i %p): stub\n", hInstall, debugstr_w(szFeature),
iCostTree, iState, piCost);
if (piCost) *piCost = 0;
return ERROR_SUCCESS;
}
/***********************************************************************
* MsiSetComponentStateA (MSI.@)
*/

View file

@ -326,6 +326,8 @@ static UINT JOIN_delete( struct tagMSIVIEW *view )
msi_free( jv->pairs );
jv->pairs = NULL;
msi_free( jv );
return ERROR_SUCCESS;
}

View file

@ -125,6 +125,8 @@ UINT WINAPI MsiOpenProductW( LPCWSTR szProduct, MSIHANDLE *phProduct )
if( r == ERROR_SUCCESS )
{
*phProduct = alloc_msihandle( &package->hdr );
if (! *phProduct)
r = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &package->hdr );
}
return r;
@ -1092,7 +1094,7 @@ end:
* INSTALLSTATE_LOCAL Feature is installed and useable
* INSTALLSTATE_ABSENT Feature is absent
* INSTALLSTATE_ADVERTISED Feature should be installed on demand
* INSTALLSTATE_UNKNOWN An error occured
* INSTALLSTATE_UNKNOWN An error occurred
* INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
*
*/
@ -1441,6 +1443,7 @@ UINT WINAPI MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
else
rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
msi_free( info );
if (rc != INSTALLSTATE_LOCAL)
return ERROR_FILE_NOT_FOUND;

View file

@ -4,29 +4,29 @@
<include base="msi">.</include>
<include base="ReactOS">include/reactos/wine</include>
<define name="__REACTOS__" />
<define name="__USE_W32API" />
<define name="__WINESRC__" />
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<library>wine</library>
<library>uuid</library>
<library>ntdll</library>
<library>kernel32</library>
<library>urlmon</library>
<library>wininet</library>
<library>comctl32</library>
<library>shell32</library>
<library>shlwapi</library>
<library>cabinet</library>
<library>oleaut32</library>
<library>ole32</library>
<library>version</library>
<library>user32</library>
<library>gdi32</library>
<library>advapi32</library>
<library>shell32</library>
<library>shlwapi</library>
<library>winmm</library>
<library>cabinet</library>
<library>comctl32</library>
<library>ole32</library>
<library>oleaut32</library>
<library>version</library>
<library>wininet</library>
<library>urlmon</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
<file>action.c</file>
<file>alter.c</file>
<file>appsearch.c</file>
<file>classes.c</file>
<file>cond.tab.c</file>
@ -63,6 +63,6 @@
<file>update.c</file>
<file>upgrade.c</file>
<file>where.c</file>
<file>msi.spec</file>
<file>msi.rc</file>
<file>msi.spec</file>
</module>

View file

@ -46,8 +46,8 @@
50 stdcall MsiGetComponentStateA(long str ptr ptr)
51 stdcall MsiGetComponentStateW(long wstr ptr ptr)
52 stdcall MsiGetDatabaseState(long)
53 stub MsiGetFeatureCostA
54 stub MsiGetFeatureCostW
53 stdcall MsiGetFeatureCostA(long str long long ptr)
54 stdcall MsiGetFeatureCostW(long wstr long long ptr)
55 stub MsiGetFeatureInfoA
56 stub MsiGetFeatureInfoW
57 stdcall MsiGetFeatureStateA(long str ptr ptr)

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "пътят %s не е намерен"
9 "поставете диск %s"
10 "некоректни параметри"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Der Pfad %s wurde nicht gefunden."
9 "Bitte Disk %s einlegen."
10 "schlechte Parameter"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "path %s not found"
9 "insert disk %s"
10 "bad parameters"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Mi ne trovis la vojon %s"
9 "enþovu la diskon %s"
10 "nekorektaj parametroj"

View file

@ -22,6 +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."
5 "ruta %s no encontrada"
9 "inserte el disco %s"
10 "parámetros incorrectos"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Polkua %s ei löydy."
9 "Anna levy %s"
10 "Virheelliset parametrit."

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Le chemin %s est introuvable"
9 "insérez le disque %s"
10 "mauvais paramètres"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "%s útvonal nem található"
9 "helyezze be a lemezt: %s"
10 "rossz paraméterek"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "percorso %s non trovato"
9 "inserire disco %s"
10 "parametri incorretti"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 " 지정한 설치 패키지를 열 수 없습니다. 파일 경로를 확인하고 다시 시도하십시오."
5 "%s 경로를 찾을수 없습니다"
9 "디스크 %s 삽입"
10 "절못된 매개변수"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Pad %s niet gevonden"
9 "Plaats disk %s"
10 "Ongeldige parameters"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Fant ikke stien '%s'."
9 "Sett i disk '%s'"
10 "Gale parametere."

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_PORTUGUESE, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "caminho %s não encontrado"
9 "insira disco %s"
10 "parâmetros inválidos"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "путь %s не найден"
9 "вставьте диск %s"
10 "неверные параметры"

View file

@ -22,6 +22,7 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "%s yolu bulunamadı"
9 "%s nolu diski yerleştirin"
10 "bozuk parametreler"

View file

@ -1,180 +1,181 @@
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2006 Mike McCormack 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
*/
#include <stdarg.h>
#define COBJMACROS
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "msipriv.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
static LONG dll_count;
/* the UI level */
INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
HWND gUIhwnd = 0;
INSTALLUI_HANDLERA gUIHandlerA = NULL;
INSTALLUI_HANDLERW gUIHandlerW = NULL;
DWORD gUIFilter = 0;
LPVOID gUIContext = NULL;
WCHAR gszLogFile[MAX_PATH];
HINSTANCE msi_hInstance;
/*
* Dll lifetime tracking declaration
*/
static void LockModule(void)
{
InterlockedIncrement(&dll_count);
}
static void UnlockModule(void)
{
InterlockedDecrement(&dll_count);
}
/******************************************************************
* DllMain
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
msi_hInstance = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
msi_dialog_register_class();
break;
case DLL_PROCESS_DETACH:
msi_dialog_unregister_class();
break;
}
return TRUE;
}
typedef struct tagIClassFactoryImpl
{
const IClassFactoryVtbl *lpVtbl;
} IClassFactoryImpl;
static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
REFIID riid,LPVOID *ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("%p %s %p\n",This,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
{
LockModule();
return 2;
}
static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
{
UnlockModule();
return 1;
}
static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
return E_FAIL;
}
static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
{
TRACE("%p %d\n", iface, dolock);
if (dolock)
LockModule();
else
UnlockModule();
return S_OK;
}
static const IClassFactoryVtbl MsiCF_Vtbl =
{
MsiCF_QueryInterface,
MsiCF_AddRef,
MsiCF_Release,
MsiCF_CreateInstance,
MsiCF_LockServer
};
static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl };
/******************************************************************
* DllGetClassObject [MSI.@]
*/
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
{
*ppv = (LPVOID) &Msi_CF;
return S_OK;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
/******************************************************************
* DllGetVersion [MSI.@]
*/
HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi)
{
TRACE("%p\n",pdvi);
if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
return E_INVALIDARG;
pdvi->dwMajorVersion = MSI_MAJORVERSION;
pdvi->dwMinorVersion = MSI_MINORVERSION;
pdvi->dwBuildNumber = MSI_BUILDNUMBER;
pdvi->dwPlatformID = 1;
return S_OK;
}
/******************************************************************
* DllCanUnloadNow [MSI.@]
*/
HRESULT WINAPI DllCanUnloadNow(void)
{
return dll_count == 0 ? S_OK : S_FALSE;
}
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2006 Mike McCormack 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
*/
#include <stdarg.h>
#define COBJMACROS
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "msipriv.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
static LONG dll_count;
/* the UI level */
INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
HWND gUIhwnd = 0;
INSTALLUI_HANDLERA gUIHandlerA = NULL;
INSTALLUI_HANDLERW gUIHandlerW = NULL;
DWORD gUIFilter = 0;
LPVOID gUIContext = NULL;
WCHAR gszLogFile[MAX_PATH];
HINSTANCE msi_hInstance;
/*
* Dll lifetime tracking declaration
*/
static void LockModule(void)
{
InterlockedIncrement(&dll_count);
}
static void UnlockModule(void)
{
InterlockedDecrement(&dll_count);
}
/******************************************************************
* DllMain
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
msi_hInstance = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
msi_dialog_register_class();
break;
case DLL_PROCESS_DETACH:
msi_dialog_unregister_class();
msi_free_handle_table();
break;
}
return TRUE;
}
typedef struct tagIClassFactoryImpl
{
const IClassFactoryVtbl *lpVtbl;
} IClassFactoryImpl;
static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
REFIID riid,LPVOID *ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("%p %s %p\n",This,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
{
LockModule();
return 2;
}
static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
{
UnlockModule();
return 1;
}
static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
return E_FAIL;
}
static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
{
TRACE("%p %d\n", iface, dolock);
if (dolock)
LockModule();
else
UnlockModule();
return S_OK;
}
static const IClassFactoryVtbl MsiCF_Vtbl =
{
MsiCF_QueryInterface,
MsiCF_AddRef,
MsiCF_Release,
MsiCF_CreateInstance,
MsiCF_LockServer
};
static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl };
/******************************************************************
* DllGetClassObject [MSI.@]
*/
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) ||
IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
{
*ppv = (LPVOID) &Msi_CF;
return S_OK;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
/******************************************************************
* DllGetVersion [MSI.@]
*/
HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi)
{
TRACE("%p\n",pdvi);
if (pdvi->cbSize < sizeof(DLLVERSIONINFO))
return E_INVALIDARG;
pdvi->dwMajorVersion = MSI_MAJORVERSION;
pdvi->dwMinorVersion = MSI_MINORVERSION;
pdvi->dwBuildNumber = MSI_BUILDNUMBER;
pdvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
return S_OK;
}
/******************************************************************
* DllCanUnloadNow [MSI.@]
*/
HRESULT WINAPI DllCanUnloadNow(void)
{
return dll_count == 0 ? S_OK : S_FALSE;
}

View file

@ -39,6 +39,12 @@
#define MSITYPE_NULLABLE 0x1000
#define MSITYPE_KEY 0x2000
/* Word Count masks */
#define MSIWORDCOUNT_SHORTFILENAMES 0x0001
#define MSIWORDCOUNT_COMPRESSED 0x0002
#define MSIWORDCOUNT_ADMINISTRATIVE 0x0004
#define MSIWORDCOUNT_PRIVILEGES 0x0008
#define MSITYPE_IS_BINARY(type) (((type) & ~MSITYPE_NULLABLE) == (MSITYPE_STRING|MSITYPE_VALID))
struct tagMSITABLE;
@ -195,6 +201,8 @@ struct tagMSIVIEW
struct msi_dialog_tag;
typedef struct msi_dialog_tag msi_dialog;
#define PROPERTY_HASH_SIZE 67
typedef struct tagMSIPACKAGE
{
MSIOBJECTHDR hdr;
@ -212,7 +220,7 @@ typedef struct tagMSIPACKAGE
struct list progids;
struct list mimes;
struct list appids;
struct tagMSISCRIPT *script;
struct list RunningActions;
@ -223,7 +231,11 @@ typedef struct tagMSIPACKAGE
UINT CurrentInstallState;
msi_dialog *dialog;
LPWSTR next_dialog;
UINT WordCount;
struct list props[PROPERTY_HASH_SIZE];
struct list subscriptions;
} MSIPACKAGE;
@ -252,14 +264,13 @@ typedef struct tagMSISUMMARYINFO
#define MSIHANDLETYPE_PACKAGE 5
#define MSIHANDLETYPE_PREVIEW 6
#define MSI_MAJORVERSION 2
#define MSI_MINORVERSION 0
#define MSI_BUILDNUMBER 2600
#define MSI_MAJORVERSION 3
#define MSI_MINORVERSION 1
#define MSI_BUILDNUMBER 4000
#define GUID_SIZE 39
#define MSIHANDLE_MAGIC 0x4d434923
#define MSIMAXHANDLES 0xf0
DEFINE_GUID(CLSID_IMsiServer, 0x000C101C,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
DEFINE_GUID(CLSID_IMsiServerX1, 0x000C103E,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
@ -295,6 +306,7 @@ extern void msiobj_addref(MSIOBJECTHDR *);
extern int msiobj_release(MSIOBJECTHDR *);
extern void msiobj_lock(MSIOBJECTHDR *);
extern void msiobj_unlock(MSIOBJECTHDR *);
extern void msi_free_handle_table(void);
extern void free_cached_tables( MSIDATABASE *db );
extern void msi_free_transforms( MSIDATABASE *db );
@ -316,7 +328,7 @@ extern string_table *msi_init_stringtable( int entries, UINT codepage );
extern VOID msi_destroy_stringtable( string_table *st );
extern UINT msi_string_count( string_table *st );
extern UINT msi_id_refcount( string_table *st, UINT i );
extern UINT msi_string_totalsize( string_table *st, UINT *last );
extern UINT msi_string_totalsize( string_table *st, UINT *datasize, UINT *poolsize );
extern UINT msi_strcmp( string_table *st, UINT lval, UINT rval, UINT *res );
extern const WCHAR *msi_string_lookup_id( string_table *st, UINT id );
extern UINT msi_string_get_codepage( string_table *st );
@ -442,6 +454,7 @@ extern BOOL msi_dialog_register_class( void );
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 );
/* preview */
extern MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE * );

View file

@ -255,6 +255,8 @@ UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
if( ret == ERROR_SUCCESS )
{
*phView = alloc_msihandle( &query->hdr );
if (! *phView)
ret = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &query->hdr );
}
msiobj_release( &db->hdr );
@ -366,6 +368,8 @@ UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
if( ret == ERROR_SUCCESS )
{
*record = alloc_msihandle( &rec->hdr );
if (! *record)
ret = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &rec->hdr );
}
msiobj_release( &query->hdr );
@ -533,6 +537,8 @@ UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hR
}
*hRec = alloc_msihandle( &rec->hdr );
if (! *hRec)
r = ERROR_NOT_ENOUGH_MEMORY;
out:
msiobj_release( &query->hdr );
@ -831,6 +837,8 @@ UINT WINAPI MsiDatabaseGetPrimaryKeysW( MSIHANDLE hdb,
if( r == ERROR_SUCCESS )
{
*phRec = alloc_msihandle( &rec->hdr );
if (! *phRec)
r = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &rec->hdr );
}
msiobj_release( &db->hdr );

View file

@ -40,12 +40,17 @@
#include "shlobj.h"
#include "wine/unicode.h"
#include "objbase.h"
#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)
{
MSIPACKAGE *package= (MSIPACKAGE*) arg;
@ -54,42 +59,21 @@ static void MSI_FreePackage( MSIOBJECTHDR *arg)
msi_dialog_destroy( package->dialog );
ACTION_free_package_structures(package);
msi_free_properties( package );
msiobj_release( &package->db->hdr );
}
static UINT clone_properties(MSIDATABASE *db)
static UINT clone_properties( MSIPACKAGE *package )
{
MSIQUERY * view = NULL;
UINT rc;
static const WCHAR CreateSql[] = {
'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
'8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
static const WCHAR Query[] = {
'S','E','L','E','C','T',' ','*',' ',
'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',0};
static const WCHAR Insert[] = {
'I','N','S','E','R','T',' ','i','n','t','o',' ',
'`','_','P','r','o','p','e','r','t','y','`',' ',
'(','`','_','P','r','o','p','e','r','t','y','`',',',
'`','V','a','l','u','e','`',')',' ',
'V','A','L','U','E','S',' ','(','?',',','?',')',0};
/* create the temporary properties table */
rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MSI_ViewExecute(view,0);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
if (rc != ERROR_SUCCESS)
return rc;
/* clone the existing properties */
rc = MSI_DatabaseOpenViewW(db, Query, &view);
rc = MSI_DatabaseOpenViewW( package->db, Query, &view );
if (rc != ERROR_SUCCESS)
return rc;
@ -97,31 +81,27 @@ static UINT clone_properties(MSIDATABASE *db)
if (rc != ERROR_SUCCESS)
{
MSI_ViewClose(view);
msiobj_release(&view->hdr);
msiobj_release(&view->hdr);
return rc;
}
while (1)
{
MSIRECORD * row;
MSIQUERY * view2;
LPCWSTR name, value;
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
break;
rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
if (rc!= ERROR_SUCCESS)
continue;
rc = MSI_ViewExecute(view2,row);
MSI_ViewClose(view2);
msiobj_release(&view2->hdr);
if (rc == ERROR_SUCCESS)
msiobj_release(&row->hdr);
name = MSI_RecordGetString( row, 1 );
value = MSI_RecordGetString( row, 2 );
MSI_SetPropertyW( package, name, value );
msiobj_release( &row->hdr );
}
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
@ -232,6 +212,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
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 };
SYSTEM_INFO sys_info;
/*
@ -335,6 +316,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
/* in a wine environment the user is always admin and privileged */
MSI_SetPropertyW(package,szAdminUser,szOne);
MSI_SetPropertyW(package,szPriv,szOne);
MSI_SetPropertyW(package, szAllUsers, szOne);
/* set the os things */
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
@ -376,6 +358,38 @@ static VOID set_installer_properties(MSIPACKAGE *package)
ReleaseDC(0, dc);
}
static UINT msi_get_word_count( MSIPACKAGE *package )
{
UINT rc;
INT word_count;
MSIHANDLE suminfo;
MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
if (!hdb) {
ERR("Unable to allocate handle\n");
return 0;
}
rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
MsiCloseHandle(hdb);
if (rc != ERROR_SUCCESS)
{
ERR("Unable to open Summary Information\n");
return 0;
}
rc = MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
&word_count, NULL, NULL, NULL );
if (rc != ERROR_SUCCESS)
{
ERR("Unable to query word count\n");
MsiCloseHandle(suminfo);
return 0;
}
MsiCloseHandle(suminfo);
return word_count;
}
MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
{
static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
@ -384,6 +398,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
'P','r','o','d','u','c','t','C','o','d','e',0};
MSIPACKAGE *package = NULL;
WCHAR uilevel[10];
int i;
TRACE("%p\n", db);
@ -411,10 +426,15 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
list_init( &package->progids );
list_init( &package->RunningActions );
package->WordCount = msi_get_word_count( package );
/* OK, here is where we do a slew of things to the database to
* prep for all that is to come as a package */
clone_properties(db);
for (i=0; i<PROPERTY_HASH_SIZE; i++)
list_init( &package->props[i] );
clone_properties( package );
set_installer_properties(package);
sprintfW(uilevel,szpi,gUILevel);
MSI_SetPropertyW(package, szLevel, uilevel);
@ -454,7 +474,7 @@ static LPCWSTR copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
return filename;
}
static LPCWSTR msi_download_package( LPCWSTR szUrl, LPWSTR filename )
LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename )
{
LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
DWORD size = 0;
@ -508,7 +528,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
LPCWSTR file;
if ( UrlIsW( szPackage, URLIS_URL ) )
file = msi_download_package( szPackage, temppath );
file = msi_download_file( szPackage, temppath );
else
file = copy_package_to_temp( szPackage, temppath );
@ -518,7 +538,12 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
DeleteFileW( file );
if( r != ERROR_SUCCESS )
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
msi_ui_error( 4, MB_OK | MB_ICONWARNING );
return r;
}
}
package = MSI_CreatePackage( db );
@ -563,6 +588,8 @@ UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phP
if( ret == ERROR_SUCCESS )
{
*phPackage = alloc_msihandle( &package->hdr );
if (! *phPackage)
ret = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &package->hdr );
}
@ -668,6 +695,10 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
action = MSI_RecordGetString(record, 1);
action_text = MSI_RecordGetString(record, 2);
if (!action || !action_text)
return IDOK;
deformat_string(package, action_text, &deformatted);
len = strlenW(timet) + strlenW(action) + strlenW(template_s);
@ -805,6 +836,79 @@ out:
}
/* property code */
typedef struct msi_property {
struct list entry;
LPWSTR key;
LPWSTR value;
} msi_property;
static UINT msi_prop_makehash( const WCHAR *str )
{
UINT hash = 0;
if (str==NULL)
return hash;
while( *str )
{
hash ^= *str++;
hash *= 53;
hash = (hash<<5) | (hash>>27);
}
return hash % PROPERTY_HASH_SIZE;
}
static msi_property *msi_prop_find( MSIPACKAGE *package, LPCWSTR key )
{
UINT hash = msi_prop_makehash( key );
msi_property *prop;
LIST_FOR_EACH_ENTRY( prop, &package->props[hash], msi_property, entry )
if (!lstrcmpW( prop->key, key ))
return prop;
return NULL;
}
static msi_property *msi_prop_add( MSIPACKAGE *package, LPCWSTR key )
{
UINT hash = msi_prop_makehash( key );
msi_property *prop;
prop = msi_alloc( sizeof *prop );
if (prop)
{
prop->key = strdupW( key );
prop->value = NULL;
list_add_head( &package->props[hash], &prop->entry );
}
return prop;
}
static void msi_delete_property( msi_property *prop )
{
list_remove( &prop->entry );
msi_free( prop->key );
msi_free( prop->value );
msi_free( prop );
}
static void msi_free_properties( MSIPACKAGE *package )
{
int i;
for ( i=0; i<PROPERTY_HASH_SIZE; i++ )
{
while ( !list_empty(&package->props[i]) )
{
msi_property *prop;
prop = LIST_ENTRY( list_head( &package->props[i] ),
msi_property, entry );
msi_delete_property( prop );
}
}
}
UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
{
LPWSTR szwName = NULL, szwValue = NULL;
@ -829,21 +933,7 @@ end:
UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
{
MSIQUERY *view;
MSIRECORD *row;
UINT rc;
DWORD sz = 0;
static const WCHAR Insert[]=
{'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
,' ','(','?',',','?',')',0};
static const WCHAR Update[]=
{'U','P','D','A','T','E',' ','_','P','r','o','p','e'
,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
WCHAR Query[1024];
msi_property *prop;
TRACE("%p %s %s\n", package, debugstr_w(szName), debugstr_w(szValue));
@ -854,35 +944,22 @@ UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
if (!szName[0])
return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
rc = MSI_GetPropertyW(package,szName,0,&sz);
if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
prop = msi_prop_find( package, szName );
if (!prop)
prop = msi_prop_add( package, szName );
if (!prop)
return ERROR_OUTOFMEMORY;
if (szValue)
{
sprintfW(Query,Update,szName);
row = MSI_CreateRecord(1);
MSI_RecordSetStringW(row,1,szValue);
msi_free( prop->value );
prop->value = strdupW( szValue );
}
else
{
strcpyW(Query,Insert);
msi_delete_property( prop );
row = MSI_CreateRecord(2);
MSI_RecordSetStringW(row,1,szName);
MSI_RecordSetStringW(row,2,szValue);
}
rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
if (rc == ERROR_SUCCESS)
{
rc = MSI_ViewExecute(view,row);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
msiobj_release(&row->hdr);
return rc;
return ERROR_SUCCESS;
}
UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
@ -898,59 +975,79 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
return ret;
}
static MSIRECORD *MSI_GetPropertyRow( MSIPACKAGE *package, LPCWSTR name )
{
static const WCHAR query[]=
{'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
'=','\'','%','s','\'',0};
if (!name || !name[0])
return NULL;
return MSI_QueryGetRecord( package->db, query, name );
}
/* internal function, not compatible with MsiGetPropertyW */
UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf )
{
MSIRECORD *row;
UINT rc = ERROR_FUNCTION_FAILED;
row = MSI_GetPropertyRow( package, szName );
msi_property *prop;
UINT r, len;
if (*pchValueBuf > 0)
szValueBuf[0] = 0;
if (row)
{
rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
msiobj_release(&row->hdr);
}
if (rc == ERROR_SUCCESS)
TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
debugstr_w(szName));
else if (rc == ERROR_MORE_DATA)
TRACE("need %li sized buffer for %s\n", *pchValueBuf,
debugstr_w(szName));
else
prop = msi_prop_find( package, szName );
if (!prop)
{
*pchValueBuf = 0;
TRACE("property %s not found\n", debugstr_w(szName));
return ERROR_FUNCTION_FAILED;
}
return rc;
if (prop->value)
{
len = lstrlenW( prop->value );
lstrcpynW(szValueBuf, prop->value, *pchValueBuf);
}
else
{
len = 1;
if( *pchValueBuf > 0 )
szValueBuf[0] = 0;
}
TRACE("%s -> %s\n", debugstr_w(szName), debugstr_w(szValueBuf));
if ( *pchValueBuf <= len )
{
TRACE("have %lu, need %u -> ERROR_MORE_DATA\n", *pchValueBuf, len);
r = ERROR_MORE_DATA;
}
else
r = ERROR_SUCCESS;
*pchValueBuf = len;
return r;
}
static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
LPWSTR msi_dup_property( MSIPACKAGE *package, LPCWSTR szName )
{
msi_property *prop;
LPWSTR value = NULL;
prop = msi_prop_find( package, szName );
if (prop)
value = strdupW( prop->value );
return value;
}
int msi_get_property_int( MSIPACKAGE *package, LPCWSTR name, int value )
{
msi_property *prop;
prop = msi_prop_find( package, name );
if (prop)
value = atoiW( prop->value );
return value;
}
static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
awstring *szValueBuf, DWORD* pchValueBuf )
{
static const WCHAR empty[] = {0};
msi_property *prop;
MSIPACKAGE *package;
MSIRECORD *row = NULL;
UINT r;
LPCWSTR val = NULL;
@ -964,17 +1061,15 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
if (!package)
return ERROR_INVALID_HANDLE;
row = MSI_GetPropertyRow( package, name );
if (row)
val = MSI_RecordGetString( row, 1 );
prop = msi_prop_find( package, name );
if (prop)
val = prop->value;
if (!val)
val = empty;
r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
if (row)
msiobj_release( &row->hdr );
msiobj_release( &package->hdr );
return r;
@ -998,7 +1093,7 @@ UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
msi_free( name );
return r;
}
UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf )
{

View file

@ -76,6 +76,8 @@ UINT WINAPI MsiEnableUIPreview( MSIHANDLE hdb, MSIHANDLE* phPreview )
*phPreview = alloc_msihandle( &preview->hdr );
msiobj_release( &preview->hdr );
r = ERROR_SUCCESS;
if (! *phPreview)
r = ERROR_NOT_ENOUGH_MEMORY;
}
msiobj_release( &db->hdr );

View file

@ -121,6 +121,8 @@ UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view,
LPCWSTR left, LPCWSTR right,
struct expr *cond );
UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, int hold );
int sqliteGetToken(const WCHAR *z, int *tokenType);
#endif /* __WINE_MSI_QUERY_H */

View file

@ -307,7 +307,7 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, unsigned int iField,
NULL, 0 , NULL, NULL);
WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
szValue, *pcchValue, NULL, NULL);
if( *pcchValue && len>*pcchValue )
if( szValue && *pcchValue && len>*pcchValue )
szValue[*pcchValue-1] = 0;
if( len )
len--;
@ -321,7 +321,7 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, unsigned int iField,
break;
}
if( *pcchValue <= len )
if( szValue && *pcchValue <= len )
ret = ERROR_MORE_DATA;
*pcchValue = len;
@ -383,13 +383,13 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, unsigned int iField,
break;
case MSIFIELD_NULL:
len = 1;
if( *pcchValue > 0 )
if( szValue && *pcchValue > 0 )
szValue[0] = 0;
default:
break;
}
if( *pcchValue <= len )
if( szValue && *pcchValue <= len )
ret = ERROR_MORE_DATA;
*pcchValue = len;

View file

@ -919,6 +919,7 @@ UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
if (val_sz > val_max)
{
val_max = val_sz + sizeof (WCHAR);
msi_free( val );
val = msi_alloc( val_max * sizeof (WCHAR) );
if (!val)
goto end;

View file

@ -72,11 +72,15 @@ struct regsvr_coclass {
LPCSTR ips; /* can be NULL to omit */
LPCSTR ips32; /* can be NULL to omit */
LPCSTR ips32_tmodel; /* can be NULL to omit, if apartment, iph32 must be set */
DWORD flags;
LPCSTR progid; /* can be NULL to omit */
LPCSTR viprogid; /* can be NULL to omit */
LPCSTR progid_extra; /* can be NULL to omit */
};
/* flags for regsvr_coclass.flags */
#define PROGID_CLSID 0x00000010
static HRESULT register_coclasses(struct regsvr_coclass const *list);
static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
@ -296,7 +300,8 @@ static HRESULT register_coclasses(struct regsvr_coclass const *list) {
list->progid);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = register_progid(buf, list->progid, NULL,
res = register_progid(list->flags & PROGID_CLSID ? buf : NULL,
list->progid, NULL,
list->name, list->progid_extra);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
@ -306,7 +311,8 @@ static HRESULT register_coclasses(struct regsvr_coclass const *list) {
list->viprogid);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = register_progid(buf, list->viprogid, list->progid,
res = register_progid(list->flags & PROGID_CLSID ? buf : NULL,
list->viprogid, list->progid,
list->name, list->progid_extra);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
@ -526,7 +532,8 @@ static struct regsvr_coclass const coclass_list[] = {
NULL,
"msi.dll",
"Apartment",
"WindowsInstaller.Installer",
PROGID_CLSID,
"IMsiServer",
NULL
},
{
@ -536,6 +543,7 @@ static struct regsvr_coclass const coclass_list[] = {
NULL,
"msi.dll",
NULL,
PROGID_CLSID,
"WindowsInstaller.Message",
NULL
},
@ -546,6 +554,7 @@ static struct regsvr_coclass const coclass_list[] = {
NULL,
"msi.dll",
"Apartment",
0,
"WindowsInstaller.Installer",
NULL
},
@ -556,6 +565,7 @@ static struct regsvr_coclass const coclass_list[] = {
NULL,
"msi.dll",
"Apartment",
PROGID_CLSID,
"WindowsInstaller.Installer",
NULL
},
@ -566,6 +576,7 @@ static struct regsvr_coclass const coclass_list[] = {
NULL,
"msi.dll",
"Apartment",
0,
"WindowsInstaller.Installer",
NULL
},

View file

@ -408,14 +408,15 @@ UINT WINAPI MsiSourceListAddSourceW( LPCWSTR szProduct, LPCWSTR szUserName,
INT ret;
LPWSTR sidstr = NULL;
DWORD sidsize = 0;
DWORD domsize = 0;
TRACE("%s %s %s\n", debugstr_w(szProduct), debugstr_w(szUserName), debugstr_w(szSource));
if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, NULL, NULL))
if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, &domsize, NULL))
{
PSID psid = msi_alloc(sidsize);
if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, NULL, NULL))
if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, &domsize, NULL))
ConvertSidToStringSidW(psid, &sidstr);
msi_free(psid);

View file

@ -79,15 +79,15 @@ static struct expr * EXPR_wildcard( void *info );
int integer;
}
%token TK_ABORT TK_AFTER TK_AGG_FUNCTION TK_ALL TK_AND TK_AS TK_ASC
%token TK_ABORT TK_AFTER TK_AGG_FUNCTION TK_ALL TK_ALTER TK_AND TK_AS TK_ASC
%token TK_BEFORE TK_BEGIN TK_BETWEEN TK_BITAND TK_BITNOT TK_BITOR TK_BY
%token TK_CASCADE TK_CASE TK_CHAR TK_CHECK TK_CLUSTER TK_COLLATE TK_COLUMN
%token TK_COMMA TK_COMMENT TK_COMMIT TK_CONCAT TK_CONFLICT
%token TK_COMMA TK_COMMENT TK_COMMIT TK_CONCAT TK_CONFLICT
%token TK_CONSTRAINT TK_COPY TK_CREATE
%token TK_DEFAULT TK_DEFERRABLE TK_DEFERRED TK_DELETE TK_DELIMITERS TK_DESC
%token TK_DISTINCT TK_DOT TK_DROP TK_EACH
%token TK_ELSE TK_END TK_END_OF_FILE TK_EQ TK_EXCEPT TK_EXPLAIN
%token TK_FAIL TK_FLOAT TK_FOR TK_FOREIGN TK_FROM TK_FUNCTION
%token TK_FAIL TK_FLOAT TK_FOR TK_FOREIGN TK_FREE TK_FROM TK_FUNCTION
%token TK_GE TK_GLOB TK_GROUP TK_GT
%token TK_HAVING TK_HOLD
%token TK_IGNORE TK_ILLEGAL TK_IMMEDIATE TK_IN TK_INDEX TK_INITIALLY
@ -127,10 +127,10 @@ static struct expr * EXPR_wildcard( void *info );
%type <column_list> selcollist column column_and_type column_def table_def
%type <column_list> column_assignment update_assign_list constlist
%type <query> query multifrom from fromtable selectfrom unorderedsel
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter
%type <expr> expr val column_val const_val
%type <column_type> column_type data_type data_type_l data_count
%type <integer> number
%type <integer> number alterop
/* Reference: http://mates.ms.mff.cuni.cz/oracle/doc/ora815nt/server.815/a67779/operator.htm */
%left TK_OR
@ -156,6 +156,7 @@ onequery:
| oneinsert
| oneupdate
| onedelete
| onealter
;
oneinsert:
@ -235,6 +236,30 @@ onedelete:
}
;
onealter:
TK_ALTER TK_TABLE table alterop
{
SQL_input* sql = (SQL_input*) info;
MSIVIEW *alter = NULL;
ALTER_CreateView( sql->db, &alter, $3, $4 );
if( !alter )
YYABORT;
$$ = alter;
}
;
alterop:
TK_HOLD
{
$$ = 1;
}
| TK_FREE
{
$$ = -1;
}
;
table_def:
column_def TK_PRIMARY TK_KEY selcollist
{

View file

@ -435,13 +435,17 @@ UINT msi_id_refcount( string_table *st, UINT i )
return st->strings[i].refcount;
}
UINT msi_string_totalsize( string_table *st, UINT *total )
UINT msi_string_totalsize( string_table *st, UINT *datasize, UINT *poolsize )
{
UINT size = 0, i, len;
UINT i, len, max, holesize;
if( st->strings[0].str || st->strings[0].refcount )
ERR("oops. element 0 has a string\n");
*total = 0;
*poolsize = 4;
*datasize = 0;
max = 1;
holesize = 0;
for( i=1; i<st->maxcount; i++ )
{
if( st->strings[i].str )
@ -451,12 +455,18 @@ UINT msi_string_totalsize( string_table *st, UINT *total )
st->strings[i].str, -1, NULL, 0, NULL, NULL);
if( len )
len--;
size += len;
*total = (i+1);
(*datasize) += len;
if (len>0xffff)
(*poolsize) += 4;
max = i + 1;
(*poolsize) += holesize + 4;
holesize = 0;
}
else
holesize += 4;
}
TRACE("%u/%u strings %u bytes codepage %x\n", *total, st->maxcount, size, st->codepage );
return size;
TRACE("data %u pool %u codepage %x\n", *datasize, *poolsize, st->codepage );
return max;
}
UINT msi_string_get_codepage( string_table *st )

View file

@ -468,6 +468,8 @@ UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
*pHandle = alloc_msihandle( &si->hdr );
if( *pHandle )
ret = ERROR_SUCCESS;
else
ret = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &si->hdr );
}

View file

@ -686,7 +686,7 @@ string_table *load_string_table( IStorage *stg )
CHAR *data = NULL;
USHORT *pool = NULL;
UINT r, datasize = 0, poolsize = 0, codepage;
DWORD i, count, offset, len, n;
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[] = {
@ -708,38 +708,51 @@ string_table *load_string_table( IStorage *stg )
offset = 0;
n = 1;
for( i=1; i<count; i++ )
i = 1;
while( i<count )
{
len = pool[i*2];
/* the string reference count is always the second word */
refs = pool[i*2+1];
/* empty entries have two zeros, still have a string id */
if (pool[i*2] == 0 && refs == 0)
{
i++;
n++;
continue;
}
/*
* If a string is over 64k, the previous string entry is made null
* and its the high word of the length is inserted in the null string's
* reference count field.
*/
if( pool[i*2-2] == 0 && pool[i*2-1] )
len += pool[i*2+1] * 0x10000;
if( pool[i*2] == 0)
{
len = (pool[i*2+3] << 16) + pool[i*2+2];
i += 2;
}
else
{
len = pool[i*2];
i += 1;
}
if( (offset + len) > datasize )
if ( (offset + len) > datasize )
{
ERR("string table corrupt?\n");
break;
}
/* don't add the high word of a string's length as a string */
if ( len || !pool[i*2+1] )
{
r = msi_addstring( st, n, data+offset, len, pool[i*2+1] );
if( r != n )
ERR("Failed to add string %ld\n", n );
n++;
}
r = msi_addstring( st, n, data+offset, len, refs );
if( r != n )
ERR("Failed to add string %ld\n", n );
n++;
offset += len;
}
if ( datasize != offset )
ERR("string table load failed! (%08x != %08lx)\n", datasize, offset );
ERR("string table load failed! (%08x != %08lx), please report\n", datasize, offset );
TRACE("Loaded %ld strings\n", count);
@ -752,7 +765,7 @@ end:
static UINT save_string_table( MSIDATABASE *db )
{
UINT i, count, datasize, poolsize, sz, used, r, codepage;
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 };
@ -764,8 +777,9 @@ static UINT save_string_table( MSIDATABASE *db )
TRACE("\n");
/* construct the new table in memory first */
datasize = msi_string_totalsize( db->strings, &count );
poolsize = (count + 1)*2*sizeof(USHORT);
count = msi_string_totalsize( db->strings, &datasize, &poolsize );
TRACE("%u %u %u\n", count, datasize, poolsize );
pool = msi_alloc( poolsize );
if( ! pool )
@ -784,6 +798,7 @@ static UINT save_string_table( MSIDATABASE *db )
codepage = msi_string_get_codepage( db->strings );
pool[0]=codepage&0xffff;
pool[1]=(codepage>>16);
n = 1;
for( i=1; i<count; i++ )
{
sz = datasize - used;
@ -795,9 +810,20 @@ static UINT save_string_table( MSIDATABASE *db )
}
if( sz && (sz < (datasize - used ) ) )
sz--;
TRACE("adding %u bytes %s\n", sz, debugstr_a(data+used) );
pool[ i*2 ] = sz;
pool[ i*2 + 1 ] = msi_id_refcount( db->strings, i );
pool[ n*2 + 1 ] = msi_id_refcount( db->strings, i );
if (sz < 0x10000)
{
pool[ n*2 ] = sz;
n++;
}
else
{
pool[ n*2 ] = 0;
pool[ n*2 + 2 ] = sz&0xffff;
pool[ n*2 + 3 ] = (sz>>16);
n += 2;
}
used += sz;
if( used > datasize )
{

View file

@ -23,7 +23,7 @@
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
#include "winnls.h"
#include "wine/unicode.h"
#include "query.h"
#include "sql.tab.h"
@ -35,120 +35,230 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
*/
typedef struct Keyword Keyword;
struct Keyword {
const char *zName; /* The keyword name */
const WCHAR *zName; /* The keyword name */
int tokenType; /* The token value for this keyword */
};
static const WCHAR ABORT_W[] = { 'A','B','O','R','T',0 };
static const WCHAR AFTER_W[] = { 'A','F','T','E','R',0 };
static const WCHAR ALTER_W[] = { 'A','L','T','E','R',0 };
static const WCHAR ALL_W[] = { 'A','L','L',0 };
static const WCHAR AND_W[] = { 'A','N','D',0 };
static const WCHAR AS_W[] = { 'A','S',0 };
static const WCHAR ASC_W[] = { 'A','S','C',0 };
static const WCHAR BEFORE_W[] = { 'B','E','F','O','R','E',0 };
static const WCHAR BEGIN_W[] = { 'B','E','G','I','N','W',0 };
static const WCHAR BETWEEN_W[] = { 'B','E','T','W','E','E','N',0 };
static const WCHAR BY_W[] = { 'B','Y',0 };
static const WCHAR CASCADE_W[] = { 'C','A','S','C','A','D','E',0 };
static const WCHAR CASE_W[] = { 'C','A','S','E',0 };
static const WCHAR CHAR_W[] = { 'C','H','A','R',0 };
static const WCHAR CHARACTER_W[] = { 'C','H','A','R','A','C','T','E','R',0 };
static const WCHAR CHECK_W[] = { 'C','H','E','C','K',0 };
static const WCHAR CLUSTER_W[] = { 'C','L','U','S','T','E','R',0 };
static const WCHAR COLLATE_W[] = { 'C','O','L','L','A','T','E',0 };
static const WCHAR COMMIT_W[] = { 'C','O','M','M','I','T',0 };
static const WCHAR CONFLICT_W[] = { 'C','O','N','F','L','I','C','T',0 };
static const WCHAR CONSTRAINT_W[] = { 'C','O','N','S','T','R','A','I','N','T',0 };
static const WCHAR COPY_W[] = { 'C','O','P','Y',0 };
static const WCHAR CREATE_W[] = { 'C','R','E','A','T','E',0 };
static const WCHAR CROSS_W[] = { 'C','R','O','S','S',0 };
static const WCHAR DEFAULT_W[] = { 'D','E','F','A','U','L','T',0 };
static const WCHAR DEFERRED_W[] = { 'D','E','F','E','R','R','E','D',0 };
static const WCHAR DEFERRABLE_W[] = { 'D','E','F','E','R','R','A','B','L','E',0 };
static const WCHAR DELETE_W[] = { 'D','E','L','E','T','E',0 };
static const WCHAR DELIMITERS_W[] = { 'D','E','L','I','M','I','T','E','R','S',0 };
static const WCHAR DESC_W[] = { 'D','E','S','C',0 };
static const WCHAR DISTINCT_W[] = { 'D','I','S','T','I','N','C','T',0 };
static const WCHAR DROP_W[] = { 'D','R','O','P',0 };
static const WCHAR END_W[] = { 'E','N','D',0 };
static const WCHAR EACH_W[] = { 'E','A','C','H',0 };
static const WCHAR ELSE_W[] = { 'E','L','S','E',0 };
static const WCHAR EXCEPT_W[] = { 'E','X','C','E','P','T',0 };
static const WCHAR EXPLAIN_W[] = { 'E','X','P','L','A','I','N',0 };
static const WCHAR FAIL_W[] = { 'F','A','I','L',0 };
static const WCHAR FOR_W[] = { 'F','O','R',0 };
static const WCHAR FOREIGN_W[] = { 'F','O','R','E','I','G','N',0 };
static const WCHAR FREE_W[] = { 'F','R','E','E',0 };
static const WCHAR FROM_W[] = { 'F','R','O','M',0 };
static const WCHAR FULL_W[] = { 'F','U','L','L',0 };
static const WCHAR GLOB_W[] = { 'G','L','O','B',0 };
static const WCHAR GROUP_W[] = { 'G','R','O','U','P',0 };
static const WCHAR HAVING_W[] = { 'H','A','V','I','N','G',0 };
static const WCHAR HOLD_W[] = { 'H','O','L','D',0 };
static const WCHAR IGNORE_W[] = { 'I','G','N','O','R','E',0 };
static const WCHAR IMMEDIATE_W[] = { 'I','M','M','E','D','I','A','T','E',0 };
static const WCHAR IN_W[] = { 'I','N',0 };
static const WCHAR INDEX_W[] = { 'I','N','D','E','X',0 };
static const WCHAR INITIALLY_W[] = { 'I','N','I','T','I','A','L','L','Y',0 };
static const WCHAR INNER_W[] = { 'I','N','N','E','R',0 };
static const WCHAR INSERT_W[] = { 'I','N','S','E','R','T',0 };
static const WCHAR INSTEAD_W[] = { 'I','N','S','T','E','A','D',0 };
static const WCHAR INT_W[] = { 'I','N','T',0 };
static const WCHAR INTERSECT_W[] = { 'I','N','T','E','R','S','E','C','T',0 };
static const WCHAR INTO_W[] = { 'I','N','T','O',0 };
static const WCHAR IS_W[] = { 'I','S',0 };
static const WCHAR ISNULL_W[] = { 'I','S','N','U','L','L',0 };
static const WCHAR JOIN_W[] = { 'J','O','I','N',0 };
static const WCHAR KEY_W[] = { 'K','E','Y',0 };
static const WCHAR LEFT_W[] = { 'L','E','F','T',0 };
static const WCHAR LIKE_W[] = { 'L','I','K','E',0 };
static const WCHAR LIMIT_W[] = { 'L','I','M','I','T',0 };
static const WCHAR LOCALIZABLE_W[] = { 'L','O','C','A','L','I','Z','A','B','L','E',0 };
static const WCHAR LONG_W[] = { 'L','O','N','G',0 };
static const WCHAR LONGCHAR_W[] = { 'L','O','N','G','C','H','A','R',0 };
static const WCHAR MATCH_W[] = { 'M','A','T','C','H',0 };
static const WCHAR NATURAL_W[] = { 'N','A','T','U','R','A','L',0 };
static const WCHAR NOT_W[] = { 'N','O','T',0 };
static const WCHAR NOTNULL_W[] = { 'N','O','T','N','U','L','L',0 };
static const WCHAR NULL_W[] = { 'N','U','L','L',0 };
static const WCHAR OBJECT_W[] = { 'O','B','J','E','C','T',0 };
static const WCHAR OF_W[] = { 'O','F',0 };
static const WCHAR OFFSET_W[] = { 'O','F','F','S','E','T',0 };
static const WCHAR ON_W[] = { 'O','N',0 };
static const WCHAR OR_W[] = { 'O','R',0 };
static const WCHAR ORDER_W[] = { 'O','R','D','E','R',0 };
static const WCHAR OUTER_W[] = { 'O','U','T','E','R',0 };
static const WCHAR PRAGMA_W[] = { 'P','R','A','G','M','A',0 };
static const WCHAR PRIMARY_W[] = { 'P','R','I','M','A','R','Y',0 };
static const WCHAR RAISE_W[] = { 'R','A','I','S','E',0 };
static const WCHAR REFERENCES_W[] = { 'R','E','F','E','R','E','N','C','E','S',0 };
static const WCHAR REPLACE_W[] = { 'R','E','P','L','A','C','E',0 };
static const WCHAR RESTRICT_W[] = { 'R','E','S','T','R','I','C','T',0 };
static const WCHAR RIGHT_W[] = { 'R','I','G','H','T',0 };
static const WCHAR ROLLBACK_W[] = { 'R','O','L','L','B','A','C','K',0 };
static const WCHAR ROW_W[] = { 'R','O','W',0 };
static const WCHAR SELECT_W[] = { 'S','E','L','E','C','T',0 };
static const WCHAR SET_W[] = { 'S','E','T',0 };
static const WCHAR SHORT_W[] = { 'S','H','O','R','T',0 };
static const WCHAR STATEMENT_W[] = { 'S','T','A','T','E','M','E','N','T',0 };
static const WCHAR TABLE_W[] = { 'T','A','B','L','E',0 };
static const WCHAR TEMP_W[] = { 'T','E','M','P',0 };
static const WCHAR TEMPORARY_W[] = { 'T','E','M','P','O','R','A','R','Y',0 };
static const WCHAR THEN_W[] = { 'T','H','E','N',0 };
static const WCHAR TRANSACTION_W[] = { 'T','R','A','N','S','A','C','T','I','O','N',0 };
static const WCHAR TRIGGER_W[] = { 'T','R','I','G','G','E','R',0 };
static const WCHAR UNION_W[] = { 'U','N','I','O','N',0 };
static const WCHAR UNIQUE_W[] = { 'U','N','I','Q','U','E',0 };
static const WCHAR UPDATE_W[] = { 'U','P','D','A','T','E',0 };
static const WCHAR USING_W[] = { 'U','S','I','N','G',0 };
static const WCHAR VACUUM_W[] = { 'V','A','C','U','U','M',0 };
static const WCHAR VALUES_W[] = { 'V','A','L','U','E','S',0 };
static const WCHAR VIEW_W[] = { 'V','I','E','W',0 };
static const WCHAR WHEN_W[] = { 'W','H','E','N',0 };
static const WCHAR WHERE_W[] = { 'W','H','E','R','E',0 };
/*
** These are the keywords
*/
static const Keyword aKeywordTable[] = {
{ "ABORT", TK_ABORT },
{ "AFTER", TK_AFTER },
{ "ALL", TK_ALL },
{ "AND", TK_AND },
{ "AS", TK_AS },
{ "ASC", TK_ASC },
{ "BEFORE", TK_BEFORE },
{ "BEGIN", TK_BEGIN },
{ "BETWEEN", TK_BETWEEN },
{ "BY", TK_BY },
{ "CASCADE", TK_CASCADE },
{ "CASE", TK_CASE },
{ "CHAR", TK_CHAR },
{ "CHARACTER", TK_CHAR },
{ "CHECK", TK_CHECK },
{ "CLUSTER", TK_CLUSTER },
{ "COLLATE", TK_COLLATE },
{ "COMMIT", TK_COMMIT },
{ "CONFLICT", TK_CONFLICT },
{ "CONSTRAINT", TK_CONSTRAINT },
{ "COPY", TK_COPY },
{ "CREATE", TK_CREATE },
{ "CROSS", TK_JOIN_KW },
{ "DEFAULT", TK_DEFAULT },
{ "DEFERRED", TK_DEFERRED },
{ "DEFERRABLE", TK_DEFERRABLE },
{ "DELETE", TK_DELETE },
{ "DELIMITERS", TK_DELIMITERS },
{ "DESC", TK_DESC },
{ "DISTINCT", TK_DISTINCT },
{ "DROP", TK_DROP },
{ "END", TK_END },
{ "EACH", TK_EACH },
{ "ELSE", TK_ELSE },
{ "EXCEPT", TK_EXCEPT },
{ "EXPLAIN", TK_EXPLAIN },
{ "FAIL", TK_FAIL },
{ "FOR", TK_FOR },
{ "FOREIGN", TK_FOREIGN },
{ "FROM", TK_FROM },
{ "FULL", TK_JOIN_KW },
{ "GLOB", TK_GLOB },
{ "GROUP", TK_GROUP },
{ "HAVING", TK_HAVING },
{ "HOLD", TK_HOLD },
{ "IGNORE", TK_IGNORE },
{ "IMMEDIATE", TK_IMMEDIATE },
{ "IN", TK_IN },
{ "INDEX", TK_INDEX },
{ "INITIALLY", TK_INITIALLY },
{ "INNER", TK_JOIN_KW },
{ "INSERT", TK_INSERT },
{ "INSTEAD", TK_INSTEAD },
{ "INT", TK_INT },
{ "INTERSECT", TK_INTERSECT },
{ "INTO", TK_INTO },
{ "IS", TK_IS },
{ "ISNULL", TK_ISNULL },
{ "JOIN", TK_JOIN },
{ "KEY", TK_KEY },
{ "LEFT", TK_JOIN_KW },
{ "LIKE", TK_LIKE },
{ "LIMIT", TK_LIMIT },
{ "LOCALIZABLE", TK_LOCALIZABLE },
{ "LONG", TK_LONG },
{ "LONGCHAR", TK_LONGCHAR },
{ "MATCH", TK_MATCH },
{ "NATURAL", TK_JOIN_KW },
{ "NOT", TK_NOT },
{ "NOTNULL", TK_NOTNULL },
{ "NULL", TK_NULL },
{ "OBJECT", TK_OBJECT },
{ "OF", TK_OF },
{ "OFFSET", TK_OFFSET },
{ "ON", TK_ON },
{ "OR", TK_OR },
{ "ORDER", TK_ORDER },
{ "OUTER", TK_JOIN_KW },
{ "PRAGMA", TK_PRAGMA },
{ "PRIMARY", TK_PRIMARY },
{ "RAISE", TK_RAISE },
{ "REFERENCES", TK_REFERENCES },
{ "REPLACE", TK_REPLACE },
{ "RESTRICT", TK_RESTRICT },
{ "RIGHT", TK_JOIN_KW },
{ "ROLLBACK", TK_ROLLBACK },
{ "ROW", TK_ROW },
{ "SELECT", TK_SELECT },
{ "SET", TK_SET },
{ "SHORT", TK_SHORT },
{ "STATEMENT", TK_STATEMENT },
{ "TABLE", TK_TABLE },
{ "TEMP", TK_TEMP },
{ "TEMPORARY", TK_TEMP },
{ "THEN", TK_THEN },
{ "TRANSACTION", TK_TRANSACTION },
{ "TRIGGER", TK_TRIGGER },
{ "UNION", TK_UNION },
{ "UNIQUE", TK_UNIQUE },
{ "UPDATE", TK_UPDATE },
{ "USING", TK_USING },
{ "VACUUM", TK_VACUUM },
{ "VALUES", TK_VALUES },
{ "VIEW", TK_VIEW },
{ "WHEN", TK_WHEN },
{ "WHERE", TK_WHERE },
{ ABORT_W, TK_ABORT },
{ AFTER_W, TK_AFTER },
/*{ ALTER_W, TK_ALTER },*/
{ ALL_W, TK_ALL },
{ AND_W, TK_AND },
{ AS_W, TK_AS },
{ ASC_W, TK_ASC },
{ BEFORE_W, TK_BEFORE },
{ BEGIN_W, TK_BEGIN },
{ BETWEEN_W, TK_BETWEEN },
{ BY_W, TK_BY },
{ CASCADE_W, TK_CASCADE },
{ CASE_W, TK_CASE },
{ CHAR_W, TK_CHAR },
{ CHARACTER_W, TK_CHAR },
{ CHECK_W, TK_CHECK },
{ CLUSTER_W, TK_CLUSTER },
{ COLLATE_W, TK_COLLATE },
{ COMMIT_W, TK_COMMIT },
{ CONFLICT_W, TK_CONFLICT },
{ CONSTRAINT_W, TK_CONSTRAINT },
{ COPY_W, TK_COPY },
{ CREATE_W, TK_CREATE },
{ CROSS_W, TK_JOIN_KW },
{ DEFAULT_W, TK_DEFAULT },
{ DEFERRED_W, TK_DEFERRED },
{ DEFERRABLE_W, TK_DEFERRABLE },
{ DELETE_W, TK_DELETE },
{ DELIMITERS_W, TK_DELIMITERS },
{ DESC_W, TK_DESC },
{ DISTINCT_W, TK_DISTINCT },
{ DROP_W, TK_DROP },
{ END_W, TK_END },
{ EACH_W, TK_EACH },
{ ELSE_W, TK_ELSE },
{ EXCEPT_W, TK_EXCEPT },
{ EXPLAIN_W, TK_EXPLAIN },
{ FAIL_W, TK_FAIL },
{ FOR_W, TK_FOR },
{ FOREIGN_W, TK_FOREIGN },
{ FROM_W, TK_FROM },
{ FULL_W, TK_JOIN_KW },
{ GLOB_W, TK_GLOB },
{ GROUP_W, TK_GROUP },
{ HAVING_W, TK_HAVING },
{ HOLD_W, TK_HOLD },
{ IGNORE_W, TK_IGNORE },
{ IMMEDIATE_W, TK_IMMEDIATE },
{ IN_W, TK_IN },
{ INDEX_W, TK_INDEX },
{ INITIALLY_W, TK_INITIALLY },
{ INNER_W, TK_JOIN_KW },
{ INSERT_W, TK_INSERT },
{ INSTEAD_W, TK_INSTEAD },
{ INT_W, TK_INT },
{ INTERSECT_W, TK_INTERSECT },
{ INTO_W, TK_INTO },
{ IS_W, TK_IS },
{ ISNULL_W, TK_ISNULL },
{ JOIN_W, TK_JOIN },
{ KEY_W, TK_KEY },
{ LEFT_W, TK_JOIN_KW },
{ LIKE_W, TK_LIKE },
{ LIMIT_W, TK_LIMIT },
{ LOCALIZABLE_W, TK_LOCALIZABLE },
{ LONG_W, TK_LONG },
{ LONGCHAR_W, TK_LONGCHAR },
{ MATCH_W, TK_MATCH },
{ NATURAL_W, TK_JOIN_KW },
{ NOT_W, TK_NOT },
{ NOTNULL_W, TK_NOTNULL },
{ NULL_W, TK_NULL },
{ OBJECT_W, TK_OBJECT },
{ OF_W, TK_OF },
{ OFFSET_W, TK_OFFSET },
{ ON_W, TK_ON },
{ OR_W, TK_OR },
{ ORDER_W, TK_ORDER },
{ OUTER_W, TK_JOIN_KW },
{ PRAGMA_W, TK_PRAGMA },
{ PRIMARY_W, TK_PRIMARY },
{ RAISE_W, TK_RAISE },
{ REFERENCES_W, TK_REFERENCES },
{ REPLACE_W, TK_REPLACE },
{ RESTRICT_W, TK_RESTRICT },
{ RIGHT_W, TK_JOIN_KW },
{ ROLLBACK_W, TK_ROLLBACK },
{ ROW_W, TK_ROW },
{ SELECT_W, TK_SELECT },
{ SET_W, TK_SET },
{ SHORT_W, TK_SHORT },
{ STATEMENT_W, TK_STATEMENT },
{ TABLE_W, TK_TABLE },
{ TEMP_W, TK_TEMP },
{ TEMPORARY_W, TK_TEMP },
{ THEN_W, TK_THEN },
{ TRANSACTION_W, TK_TRANSACTION },
{ TRIGGER_W, TK_TRIGGER },
{ UNION_W, TK_UNION },
{ UNIQUE_W, TK_UNIQUE },
{ UPDATE_W, TK_UPDATE },
{ USING_W, TK_USING },
{ VACUUM_W, TK_VACUUM },
{ VALUES_W, TK_VALUES },
{ VIEW_W, TK_VIEW },
{ WHEN_W, TK_WHEN },
{ WHERE_W, TK_WHERE },
};
#define KEYWORD_COUNT ( sizeof aKeywordTable/sizeof (Keyword) )
@ -159,17 +269,13 @@ static const Keyword aKeywordTable[] = {
** returned. If the input is not a keyword, TK_ID is returned.
*/
static int sqliteKeywordCode(const WCHAR *z, int n){
UINT i, len;
char buffer[0x10];
UINT i;
len = WideCharToMultiByte( CP_ACP, 0, z, n, buffer, sizeof buffer, NULL, NULL );
for(i=0; i<len; i++)
buffer[i] = toupper(buffer[i]);
for(i=0; i<KEYWORD_COUNT; i++)
{
if(memcmp(buffer, aKeywordTable[i].zName, len))
if(strncmpiW(z, aKeywordTable[i].zName, n))
continue;
if(strlen(aKeywordTable[i].zName) == len )
if(lstrlenW(aKeywordTable[i].zName) == n )
return aKeywordTable[i].tokenType;
}
return TK_ID;

View file

@ -37,6 +37,14 @@ typedef enum tagMSICOLINFO
MSICOLINFO_TYPES = 1
} MSICOLINFO;
typedef enum tagMSICOSTTREE
{
MSICOSTTREE_SELFONLY = 0,
MSICOSTTREE_CHILDREN = 1,
MSICOSTTREE_PARENTS = 2,
MSICOSTTREE_PRODUCT = 3,
} MSICOSTTREE;
typedef enum tagMSIMODIFY
{
MSIMODIFY_REFRESH = 0,