Commit 6386edc5 authored by Mike McCormack's avatar Mike McCormack Committed by Alexandre Julliard

Partial implementation of the Microsoft Installer (msi.dll).

parent f6fab8c7
......@@ -1452,6 +1452,7 @@ dlls/msacm/msadp32/Makefile
dlls/msacm/msg711/Makefile
dlls/msacm/winemp3/Makefile
dlls/msdmo/Makefile
dlls/msi/Makefile
dlls/msimg32/Makefile
dlls/msisys/Makefile
dlls/msnet32/Makefile
......
......@@ -58,6 +58,7 @@ BASEDIRS = \
msacm/msg711 \
msacm/winemp3 \
msdmo \
msi \
msimg32 \
msisys \
msnet32 \
......@@ -247,6 +248,7 @@ SYMLINKS = \
msadp32.acm$(DLLEXT) \
msdmo.dll$(DLLEXT) \
msg711.acm$(DLLEXT) \
msi.dll$(DLLEXT) \
msimg32.dll$(DLLEXT) \
msisys.ocx$(DLLEXT) \
msnet32.dll$(DLLEXT) \
......@@ -482,6 +484,9 @@ msdmo.dll$(DLLEXT): msdmo/msdmo.dll$(DLLEXT)
msg711.acm$(DLLEXT): msacm/msg711/msg711.acm$(DLLEXT)
$(RM) $@ && $(LN_S) msacm/msg711/msg711.acm$(DLLEXT) $@
msi.dll$(DLLEXT): msi/msi.dll$(DLLEXT)
$(RM) $@ && $(LN_S) msi/msi.dll$(DLLEXT) $@
msimg32.dll$(DLLEXT): msimg32/msimg32.dll$(DLLEXT)
$(RM) $@ && $(LN_S) msimg32/msimg32.dll$(DLLEXT) $@
......@@ -719,6 +724,7 @@ IMPORT_LIBS = \
libmpr \
libmsacm32 \
libmsdmo \
libmsi \
libmsimg32 \
libmsnet32 \
libmsrle32 \
......@@ -994,6 +1000,11 @@ libmsdmo.def: msdmo/msdmo.spec.def
libmsdmo.a: msdmo/msdmo.spec.def
$(DLLTOOL) -k -l $@ -d msdmo/msdmo.spec.def
libmsi.def: msi/msi.spec.def
$(RM) $@ && $(LN_S) msi/msi.spec.def $@
libmsi.a: msi/msi.spec.def
$(DLLTOOL) -k -l $@ -d msi/msi.spec.def
libmsimg32.def: msimg32/msimg32.spec.def
$(RM) $@ && $(LN_S) msimg32/msimg32.spec.def $@
libmsimg32.a: msimg32/msimg32.spec.def
......@@ -1308,6 +1319,7 @@ mapi32/mapi32.spec.def: $(WINEBUILD)
mpr/mpr.spec.def: $(WINEBUILD)
msacm/msacm32.spec.def: $(WINEBUILD)
msdmo/msdmo.spec.def: $(WINEBUILD)
msi/msi.spec.def: $(WINEBUILD)
msimg32/msimg32.spec.def: $(WINEBUILD)
msnet32/msnet32.spec.def: $(WINEBUILD)
msvideo/msrle32/msrle32.spec.def: $(WINEBUILD)
......@@ -1424,6 +1436,7 @@ msacm/msacm32.dll$(DLLEXT): msacm
msacm/msadp32/msadp32.acm$(DLLEXT): msacm/msadp32
msdmo/msdmo.dll$(DLLEXT): msdmo
msacm/msg711/msg711.acm$(DLLEXT): msacm/msg711
msi/msi.dll$(DLLEXT): msi
msimg32/msimg32.dll$(DLLEXT): msimg32
msisys/msisys.ocx$(DLLEXT): msisys
msnet32/msnet32.dll$(DLLEXT): msnet32
......
Makefile
msi.dll.dbg.c
msi.spec.c
msi.spec.def
y.tab.c
y.tab.h
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = msi.dll
IMPORTS = ole32 user32 advapi32 kernel32
EXTRALIBS = $(LIBUUID) $(LIBUNICODE)
LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
distinct.c \
handle.c \
msi.c \
msiquery.c \
order.c \
record.c \
select.c \
suminfo.c \
table.c \
tokenize.c \
where.c
#RC_SRCS= msi_rc.rc
EXTRA_SRCS = sql.y
EXTRA_OBJS = y.tab.o
@MAKE_DLL_RULES@
y.tab.c y.tab.h: sql.y
$(YACC) -d -t $(SRCDIR)/sql.y
# hack to allow parallel make
y.tab.h: y.tab.c
y.tab.o: y.tab.h
### Dependencies:
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
#include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
typedef struct tagDISTINCTSET
{
UINT val;
UINT count;
UINT row;
struct tagDISTINCTSET *nextrow;
struct tagDISTINCTSET *nextcol;
} DISTINCTSET;
typedef struct tagMSIDISTINCTVIEW
{
MSIVIEW view;
MSIDATABASE *db;
MSIVIEW *table;
UINT row_count;
UINT *translation;
} MSIDISTINCTVIEW;
static DISTINCTSET ** distinct_insert( DISTINCTSET **x, UINT val, UINT row )
{
/* horrible O(n) find */
while( *x )
{
if( (*x)->val == val )
{
(*x)->count++;
return x;
}
x = &(*x)->nextrow;
}
/* nothing found, so add one */
*x = HeapAlloc( GetProcessHeap(), 0, sizeof (DISTINCTSET) );
if( *x )
{
(*x)->val = val;
(*x)->count = 1;
(*x)->row = row;
(*x)->nextrow = NULL;
(*x)->nextcol = NULL;
}
return x;
}
static void distinct_free( DISTINCTSET *x )
{
while( x )
{
DISTINCTSET *next = x->nextrow;
distinct_free( x->nextcol );
HeapFree( GetProcessHeap(), 0, x );
x = next;
}
}
static UINT DISTINCT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
TRACE("%p %d %d %p\n", dv, row, col, val );
if( !dv->table )
return ERROR_FUNCTION_FAILED;
if( row >= dv->row_count )
return ERROR_INVALID_PARAMETER;
row = dv->translation[ row ];
return dv->table->ops->fetch_int( dv->table, row, col, val );
}
static UINT DISTINCT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
UINT r, i, j, r_count, c_count;
DISTINCTSET *rowset = NULL;
TRACE("%p %ld\n", dv, record);
if( !dv->table )
return ERROR_FUNCTION_FAILED;
r = dv->table->ops->execute( dv->table, record );
if( r != ERROR_SUCCESS )
return r;
r = dv->table->ops->get_dimensions( dv->table, &r_count, &c_count );
if( r != ERROR_SUCCESS )
return r;
dv->translation = HeapAlloc( GetProcessHeap(), 0, r_count*sizeof(UINT) );
if( !dv->translation )
return ERROR_FUNCTION_FAILED;
/* build it */
for( i=0; i<r_count; i++ )
{
DISTINCTSET **x = &rowset;
for( j=1; j<=c_count; j++ )
{
UINT val = 0;
r = dv->table->ops->fetch_int( dv->table, i, j, &val );
if( r != ERROR_SUCCESS )
{
ERR("Failed to fetch int at %d %d\n", i, j );
distinct_free( rowset );
return r;
}
x = distinct_insert( x, val, i );
if( !*x )
{
ERR("Failed to insert at %d %d\n", i, j );
distinct_free( rowset );
return ERROR_FUNCTION_FAILED;
}
if( j != c_count )
x = &(*x)->nextcol;
}
/* check if it was distinct and if so, include it */
if( (*x)->row == i )
{
TRACE("Row %d -> %d\n", dv->row_count, i);
dv->translation[dv->row_count++] = i;
}
}
distinct_free( rowset );
return ERROR_SUCCESS;
}
static UINT DISTINCT_close( struct tagMSIVIEW *view )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
TRACE("%p\n", dv );
if( !dv->table )
return ERROR_FUNCTION_FAILED;
if( dv->translation )
HeapFree( GetProcessHeap(), 0, dv->translation );
dv->translation = NULL;
dv->row_count = 0;
return dv->table->ops->close( dv->table );
}
static UINT DISTINCT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
TRACE("%p %p %p\n", dv, rows, cols );
if( !dv->table )
return ERROR_FUNCTION_FAILED;
if( rows )
{
if( !dv->translation )
return ERROR_FUNCTION_FAILED;
*rows = dv->row_count;
}
return dv->table->ops->get_dimensions( dv->table, NULL, cols );
}
static UINT DISTINCT_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
TRACE("%p %d %p %p\n", dv, n, name, type );
if( !dv->table )
return ERROR_FUNCTION_FAILED;
return dv->table->ops->get_column_info( dv->table, n, name, type );
}
static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec)
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
TRACE("%p %d %ld\n", dv, eModifyMode, hrec );
if( !dv->table )
return ERROR_FUNCTION_FAILED;
return dv->table->ops->modify( dv->table, eModifyMode, hrec );
}
static UINT DISTINCT_delete( struct tagMSIVIEW *view )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
TRACE("%p\n", dv );
if( dv->table )
dv->table->ops->delete( dv->table );
if( dv->translation )
HeapFree( GetProcessHeap(), 0, dv->translation );
HeapFree( GetProcessHeap(), 0, dv );
return ERROR_SUCCESS;
}
MSIVIEWOPS distinct_ops =
{
DISTINCT_fetch_int,
DISTINCT_execute,
DISTINCT_close,
DISTINCT_get_dimensions,
DISTINCT_get_column_info,
DISTINCT_modify,
DISTINCT_delete
};
UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
{
MSIDISTINCTVIEW *dv = NULL;
UINT count = 0, r;
TRACE("%p\n", dv );
r = table->ops->get_dimensions( table, NULL, &count );
if( r != ERROR_SUCCESS )
{
ERR("can't get table dimensions\n");
return r;
}
dv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *dv );
if( !dv )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
dv->view.ops = &distinct_ops;
dv->db = db;
dv->table = table;
dv->translation = NULL;
dv->row_count = 0;
*view = (MSIVIEW*) dv;
return ERROR_SUCCESS;
}
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
MSIHANDLEINFO *msihandletable[MSIMAXHANDLES];
MSIHANDLE alloc_msihandle(UINT type, UINT size, msihandledestructor destroy)
{
MSIHANDLEINFO *info;
UINT i;
/* find a slot */
for(i=0; i<MSIMAXHANDLES; i++)
if( !msihandletable[i] )
break;
if( (i>=MSIMAXHANDLES) || msihandletable[i] )
return 0;
size += sizeof (MSIHANDLEINFO);
info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
if( !info )
return 0;
info->magic = MSIHANDLE_MAGIC;
info->type = type;
info->destructor = destroy;
msihandletable[i] = info;
return (MSIHANDLE) (i+1);
}
void *msihandle2msiinfo(MSIHANDLE handle, UINT type)
{
handle--;
if( handle<0 )
return NULL;
if( handle>=MSIMAXHANDLES )
return NULL;
if( !msihandletable[handle] )
return NULL;
if( msihandletable[handle]->magic != MSIHANDLE_MAGIC )
return NULL;
if( type && (msihandletable[handle]->type != type) )
return NULL;
return &msihandletable[handle][1];
}
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
{
MSIHANDLEINFO *info = msihandle2msiinfo(handle, 0);
TRACE("%lx\n",handle);
if( !info )
return ERROR_INVALID_HANDLE;
info--;
if( info->magic != MSIHANDLE_MAGIC )
{
ERR("Invalid handle!\n");
return ERROR_INVALID_HANDLE;
}
if( info->destructor )
info->destructor( &info[1] );
HeapFree( GetProcessHeap(), 0, info );
msihandletable[handle-1] = NULL;
TRACE("Destroyed\n");
return 0;
}
UINT WINAPI MsiCloseAllHandles(void)
{
UINT i;
TRACE("\n");
for(i=0; i<MSIMAXHANDLES; i++)
MsiCloseHandle( i+1 );
return 0;
}
This diff is collapsed. Click to expand it.
1 stdcall DllCanUnloadNow() MSI_DllCanUnloadNow
2 stub DllGetClassObject
3 stub DllRegisterServer
4 stub DllUnregisterServer
5 stub MsiAdvertiseProductA
6 stub MsiAdvertiseProductW
7 stdcall MsiCloseAllHandles() MsiCloseAllHandles
8 stdcall MsiCloseHandle(long) MsiCloseHandle
9 stub MsiCollectUserInfoA
10 stub MsiCollectUserInfoW
11 stub MsiConfigureFeatureA
12 stub MsiConfigureFeatureFromDescriptorA
13 stub MsiConfigureFeatureFromDescriptorW
14 stub MsiConfigureFeatureW
15 stdcall MsiConfigureProductA(str long long) MsiConfigureProductA
16 stdcall MsiConfigureProductW(wstr long long) MsiConfigureProductW
17 stdcall MsiCreateRecord(long) MsiCreateRecord
18 stdcall MsiDatabaseApplyTransformA(long str long) MsiDatabaseApplyTransformA
19 stdcall MsiDatabaseApplyTransformW(long wstr long) MsiDatabaseApplyTransformW
20 stdcall MsiDatabaseCommit(long) MsiDatabaseCommit
21 stub MsiDatabaseExportA
22 stub MsiDatabaseExportW
23 stdcall MsiDatabaseGenerateTransformA(long long str long long) MsiDatabaseGenerateTransformA
24 stdcall MsiDatabaseGenerateTransformW(long long wstr long long) MsiDatabaseGenerateTransformW
25 stdcall MsiDatabaseGetPrimaryKeysA(long str ptr) MsiDatabaseGetPrimaryKeysA
26 stdcall MsiDatabaseGetPrimaryKeysW(long wstr ptr) MsiDatabaseGetPrimaryKeysW
27 stdcall MsiDatabaseImportA(str str) MsiDatabaseImportA
28 stdcall MsiDatabaseImportW(wstr wstr) MsiDatabaseImportW
29 stub MsiDatabaseMergeA
30 stub MsiDatabaseMergeW
31 stdcall MsiDatabaseOpenViewA(str ptr) MsiDatabaseOpenViewA
32 stdcall MsiDatabaseOpenViewW(wstr ptr) MsiDatabaseOpenViewW
33 stdcall MsiDoActionA(long str) MsiDoActionA
34 stdcall MsiDoActionW(long wstr) MsiDoActionW
35 stub MsiEnableUIPreview
36 stdcall MsiEnumClientsA(long ptr) MsiEnumClientsA
37 stdcall MsiEnumClientsW(long ptr) MsiEnumClientsW
38 stub MsiEnumComponentQualifiersA
39 stub MsiEnumComponentQualifiersW
40 stdcall MsiEnumComponentsA(long ptr) MsiEnumComponentsA
41 stdcall MsiEnumComponentsW(long ptr) MsiEnumComponentsW
42 stdcall MsiEnumFeaturesA(str long ptr ptr) MsiEnumFeaturesA
43 stdcall MsiEnumFeaturesW(wstr long ptr ptr) MsiEnumFeaturesW
44 stdcall MsiEnumProductsA(long ptr) MsiEnumProductsA
45 stdcall MsiEnumProductsW(long ptr) MsiEnumProductsW
46 stub MsiEvaluateConditionA
47 stub MsiEvaluateConditionW
48 stub MsiGetLastErrorRecord
49 stub MsiGetActiveDatabase
50 stub MsiGetComponentStateA
51 stub MsiGetComponentStateW
52 stub MsiGetDatabaseState
53 stub MsiGetFeatureCostA
54 stub MsiGetFeatureCostW
55 stub MsiGetFeatureInfoA
56 stub MsiGetFeatureInfoW
57 stub MsiGetFeatureStateA
58 stub MsiGetFeatureStateW
59 stub MsiGetFeatureUsageA
60 stub MsiGetFeatureUsageW
61 stub MsiGetFeatureValidStatesA
62 stub MsiGetFeatureValidStatesW
63 stub MsiGetLanguage
64 stub MsiGetMode
65 stdcall MsiGetProductCodeA(str str) MsiGetProductCodeA
66 stdcall MsiGetProductCodeW(wstr wstr) MsiGetProductCodeW
67 stdcall MsiGetProductInfoA(str str str long) MsiGetProductInfoA
68 stub MsiGetProductInfoFromScriptA
69 stub MsiGetProductInfoFromScriptW
70 stdcall MsiGetProductInfoW(wstr wstr wstr long) MsiGetProductInfoW
71 stub MsiGetProductPropertyA
72 stub MsiGetProductPropertyW
73 stub MsiGetPropertyA
74 stub MsiGetPropertyW
75 stub MsiGetSourcePathA
76 stub MsiGetSourcePathW
77 stdcall MsiGetSummaryInformationA(str long ptr) MsiGetSummaryInformationA
78 stdcall MsiGetSummaryInformationW(wstr long ptr) MsiGetSummaryInformationW
79 stub MsiGetTargetPathA
80 stub MsiGetTargetPathW
81 stub MsiGetUserInfoA
82 stub MsiGetUserInfoW
83 stub MsiInstallMissingComponentA
84 stub MsiInstallMissingComponentW
85 stub MsiInstallMissingFileA
86 stub MsiInstallMissingFileW
87 stdcall MsiInstallProductA(str str) MsiInstallProductA
88 stdcall MsiInstallProductW(wstr wstr) MsiInstallProductW
89 stub MsiLocateComponentA
90 stub MsiLocateComponentW
91 stdcall MsiOpenDatabaseA(str str ptr) MsiOpenDatabaseA
92 stdcall MsiOpenDatabaseW(wstr wstr ptr) MsiOpenDatabaseW
93 stdcall MsiOpenPackageA(str ptr) MsiOpenPackageA
94 stdcall MsiOpenPackageW(wstr ptr) MsiOpenPackageW
95 stdcall MsiOpenProductA(str ptr) MsiOpenProductA
96 stdcall MsiOpenProductW(wstr ptr) MsiOpenProductW
97 stub MsiPreviewBillboardA
98 stub MsiPreviewBillboardW
99 stub MsiPreviewDialogA
100 stub MsiPreviewDialogW
101 stub MsiProcessAdvertiseScriptA
102 stub MsiProcessAdvertiseScriptW
103 stub MsiProcessMessage
104 stub MsiProvideComponentA
105 stdcall MsiProvideComponentFromDescriptorA(str ptr ptr ptr) MsiProvideComponentFromDescriptorA
106 stdcall MsiProvideComponentFromDescriptorW(wstr ptr ptr ptr) MsiProvideComponentFromDescriptorW
107 stub MsiProvideComponentW
108 stub MsiProvideQualifiedComponentA
109 stub MsiProvideQualifiedComponentW
110 stub MsiQueryFeatureStateA
111 stub MsiQueryFeatureStateW
112 stdcall MsiQueryProductStateA(str) MsiQueryProductStateA
113 stdcall MsiQueryProductStateW(wstr) MsiQueryProductStateW
114 stdcall MsiRecordDataSize(long long) MsiRecordDataSize
115 stdcall MsiRecordGetFieldCount(long) MsiRecordGetFieldCount
116 stdcall MsiRecordGetInteger(long long) MsiRecordGetInteger
117 stdcall MsiRecordGetStringA(long long ptr ptr) MsiRecordGetStringA
118 stdcall MsiRecordGetStringW(long long ptr ptr) MsiRecordGetStringW
119 stdcall MsiRecordIsNull(long long) MsiRecordIsNull
120 stdcall MsiRecordReadStream(long long ptr ptr) MsiRecordReadStream
121 stdcall MsiRecordSetInteger(long long long) MsiRecordSetInteger
122 stdcall MsiRecordSetStreamA(long long str) MsiRecordSetStreamA
123 stdcall MsiRecordSetStreamW(long long wstr) MsiRecordSetStreamW
124 stdcall MsiRecordSetStringA(long long str) MsiRecordSetStringA
125 stdcall MsiRecordSetStringW(long long wstr) MsiRecordSetStringW
126 stub MsiReinstallFeatureA
127 stub MsiReinstallFeatureFromDescriptorA
128 stub MsiReinstallFeatureFromDescriptorW
129 stub MsiReinstallFeatureW
130 stub MsiReinstallProductA
131 stub MsiReinstallProductW
132 stub MsiSequenceA
133 stub MsiSequenceW
134 stub MsiSetComponentStateA
135 stub MsiSetComponentStateW
136 stub MsiSetExternalUIA
137 stub MsiSetExternalUIW
138 stub MsiSetFeatureStateA
139 stub MsiSetFeatureStateW
140 stub MsiSetInstallLevel
141 stdcall MsiSetInternalUI(long ptr) MsiSetInternalUI
142 stub MsiVerifyDiskSpace
143 stub MsiSetMode
144 stub MsiSetPropertyA
145 stub MsiSetPropertyW
146 stub MsiSetTargetPathA
147 stub MsiSetTargetPathW
148 stdcall MsiSummaryInfoGetPropertyA(long long ptr ptr ptr ptr ptr) MsiSummaryInfoGetPropertyA
149 stdcall MsiSummaryInfoGetPropertyCount(long ptr) MsiSummaryInfoGetPropertyCount
150 stdcall MsiSummaryInfoGetPropertyW(long long ptr ptr ptr ptr ptr) MsiSummaryInfoGetPropertyW
151 stub MsiSummaryInfoPersist
152 stub MsiSummaryInfoSetPropertyA
153 stub MsiSummaryInfoSetPropertyW
154 stub MsiUseFeatureA
155 stub MsiUseFeatureW
156 stub MsiVerifyPackageA
157 stub MsiVerifyPackageW
158 stdcall MsiViewClose(long) MsiViewClose
159 stdcall MsiViewExecute(long long) MsiViewExecute
160 stdcall MsiViewFetch(long ptr) MsiViewFetch
161 stub MsiViewGetErrorA
162 stub MsiViewGetErrorW
163 stub MsiViewModify
164 stdcall MsiDatabaseIsTablePersistentA(long str) MsiDatabaseIsTablePersistentA
165 stdcall MsiDatabaseIsTablePersistentW(long wstr) MsiDatabaseIsTablePersistentW
166 stdcall MsiViewGetColumnInfo(long long ptr) MsiViewGetColumnInfo
167 stdcall MsiRecordClearData(long) MsiRecordClearData
168 stdcall MsiEnableLogA(long str long) MsiEnableLogA
169 stdcall MsiEnableLogW(long wstr long) MsiEnableLogW
170 stdcall MsiFormatRecordA(long long ptr ptr) MsiFormatRecordA
171 stdcall MsiFormatRecordW(long long ptr ptr) MsiFormatRecordW
172 stub MsiGetComponentPathA
173 stub MsiGetComponentPathW
174 stub MsiApplyPatchA
175 stub MsiApplyPatchW
176 stub MsiAdvertiseScriptA
177 stub MsiAdvertiseScriptW
178 stub MsiGetPatchInfoA
179 stub MsiGetPatchInfoW
180 stub MsiEnumPatchesA
181 stub MsiEnumPatchesW
182 stdcall DllGetVersion(ptr) MSI_DllGetVersion
183 stub MsiGetProductCodeFromPackageCodeA
184 stub MsiGetProductCodeFromPackageCodeW
185 stub MsiCreateTransformSummaryInfoA
186 stub MsiCreateTransformSummaryInfoW
187 stub MsiQueryFeatureStateFromDescriptorA
188 stub MsiQueryFeatureStateFromDescriptorW
189 stub MsiConfigureProductExA
190 stub MsiConfigureProductExW
191 stub MsiInvalidateFeatureCache
192 stub MsiUseFeatureExA
193 stub MsiUseFeatureExW
194 stub MsiGetFileVersionA
195 stub MsiGetFileVersionW
196 stdcall MsiLoadStringA(long long long long long long) MsiLoadStringA
197 stdcall MsiLoadStringW(long long long long long long) MsiLoadStringW
198 stdcall MsiMessageBoxA(long long long long long long) MsiMessageBoxA
199 stdcall MsiMessageBoxW(long long long long long long) MsiMessageBoxW
200 stub MsiDecomposeDescriptorA
201 stub MsiDecomposeDescriptorW
202 stub MsiProvideQualifiedComponentExA
203 stub MsiProvideQualifiedComponentExW
204 stub MsiEnumRelatedProductsA
205 stub MsiEnumRelatedProductsW
206 stub MsiSetFeatureAttributesA
207 stub MsiSetFeatureAttributesW
208 stub MsiSourceListClearAllA
209 stub MsiSourceListClearAllW
210 stub MsiSourceListAddSourceA
211 stub MsiSourceListAddSourceW
212 stub MsiSourceListForceResolutionA
213 stub MsiSourceListForceResolutionW
214 stub MsiIsProductElevatedA
215 stub MsiIsProductElevatedW
216 stub MsiGetShortcutTargetA
217 stub MsiGetShortcutTargetW
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MSI_PRIVATE__
#define __WINE_MSI_PRIVATE__
#include "msi.h"
#include "msiquery.h"
#include "objidl.h"
#define MSI_DATASIZEMASK 0x00ff
#define MSITYPE_VALID 0x0100
#define MSITYPE_STRING 0x0800
#define MSITYPE_NULLABLE 0x1000
#define MSITYPE_KEY 0x2000
struct tagMSITABLE;
typedef struct tagMSITABLE MSITABLE;
typedef struct pool_data_tag
{
USHORT *data;
UINT size;
} pool_data;
typedef struct string_data_tag
{
CHAR *data;
UINT size;
} string_data;
typedef struct string_table_tag
{
pool_data pool;
string_data info;
} string_table;
typedef struct tagMSIDATABASE
{
IStorage *storage;
string_table strings;
MSITABLE *first_table, *last_table;
} MSIDATABASE;
struct tagMSIVIEW;
typedef struct tagMSIVIEWOPS
{
/*
* fetch_int - reads one integer from {row,col} in the table
*
* This function should be called after the execute method.
* Data returned by the function should not change until
* close or delete is called.
* To get a string value, query the database's string table with
* the integer value returned from this function.
*/
UINT (*fetch_int)( struct tagMSIVIEW *, UINT row, UINT col, UINT *val );
/*
* execute - loads the underlying data into memory so it can be read
*/
UINT (*execute)( struct tagMSIVIEW *, MSIHANDLE );
/*
* close - clears the data read by execute from memory
*/
UINT (*close)( struct tagMSIVIEW * );
/*
* get_dimensions - returns the number of rows or columns in a table.
*
* The number of rows can only be queried after the execute method
* is called. The number of columns can be queried at any time.
*/
UINT (*get_dimensions)( struct tagMSIVIEW *, UINT *rows, UINT *cols );
/*
* get_column_info - returns the name and type of a specific column
*
* The name is HeapAlloc'ed by this function and should be freed by
* the caller.
* The column information can be queried at any time.
*/
UINT (*get_column_info)( struct tagMSIVIEW *, UINT n, LPWSTR *name, UINT *type );
/*
* modify - not yet implemented properly
*/
UINT (*modify)( struct tagMSIVIEW *, MSIMODIFY, MSIHANDLE );
/*
* delete - destroys the structure completely
*/
UINT (*delete)( struct tagMSIVIEW * );
} MSIVIEWOPS;
typedef struct tagMSIVIEW
{
MSIVIEWOPS *ops;
} MSIVIEW;
typedef struct tagMSISUMMARYINFO
{
IPropertyStorage *propstg;
} MSISUMMARYINFO;
typedef VOID (*msihandledestructor)( VOID * );
typedef struct tagMSIHANDLEINFO
{
UINT magic;
UINT type;
msihandledestructor destructor;
struct tagMSIHANDLEINFO *next;
struct tagMSIHANDLEINFO *prev;
} MSIHANDLEINFO;
#define MSIHANDLETYPE_ANY 0
#define MSIHANDLETYPE_DATABASE 1
#define MSIHANDLETYPE_SUMMARYINFO 2
#define MSIHANDLETYPE_VIEW 3
#define MSIHANDLETYPE_RECORD 4
#define MSI_MAJORVERSION 1
#define MSI_MINORVERSION 10
#define MSI_BUILDNUMBER 1029
#define GUID_SIZE 39
#define MSIHANDLE_MAGIC 0x4d434923
#define MSIMAXHANDLES 0x80
#define MSISUMINFO_OFFSET 0x30LL
extern void *msihandle2msiinfo(MSIHANDLE handle, UINT type);
MSIHANDLE alloc_msihandle(UINT type, UINT extra, msihandledestructor destroy);
/* add this table to the list of cached tables in the database */
extern void add_table(MSIDATABASE *db, MSITABLE *table);
extern void remove_table( MSIDATABASE *db, MSITABLE *table );
extern void free_table( MSIDATABASE *db, MSITABLE *table );
extern void free_cached_tables( MSIDATABASE *db );
extern UINT find_cached_table(MSIDATABASE *db, LPCWSTR name, MSITABLE **table);
extern UINT get_table(MSIDATABASE *db, LPCWSTR name, MSITABLE **table);
extern UINT dump_string_table(MSIDATABASE *db);
extern UINT load_string_table( MSIDATABASE *db, string_table *pst);
extern UINT msi_id2string( string_table *st, UINT string_no, LPWSTR buffer, UINT *sz );
extern LPWSTR MSI_makestring( MSIDATABASE *db, UINT stringid);
UINT VIEW_find_column( MSIVIEW *view, LPWSTR name, UINT *n );
/* FIXME! should get rid of that */
#include "winnls.h"
inline static LPWSTR HEAP_strdupAtoW( HANDLE heap, DWORD flags, LPCSTR str )
{
LPWSTR ret;
INT len;
if (!str) return NULL;
len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
ret = HeapAlloc( heap, flags, len * sizeof(WCHAR) );
if (ret) MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
return ret;
}
#endif /* __WINE_MSI_PRIVATE__ */
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
#include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
typedef struct tagMSIQUERY
{
MSIVIEW *view;
UINT row;
MSIDATABASE *db;
} MSIQUERY;
UINT WINAPI MsiDatabaseIsTablePersistentA(
MSIHANDLE hDatabase, LPSTR szTableName)
{
FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName));
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDatabaseIsTablePersistentW(
MSIHANDLE hDatabase, LPWSTR szTableName)
{
FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName));
return ERROR_CALL_NOT_IMPLEMENTED;
}
void MSI_CloseView( VOID *arg )
{
MSIQUERY *query = arg;
if( query->view && query->view->ops->delete )
query->view->ops->delete( query->view );
}
UINT VIEW_find_column( MSIVIEW *table, LPWSTR name, UINT *n )
{
LPWSTR col_name;
UINT i, count, r;
r = table->ops->get_dimensions( table, NULL, &count );
if( r != ERROR_SUCCESS )
return r;
for( i=1; i<=count; i++ )
{
INT x;
col_name = NULL;
r = table->ops->get_column_info( table, i, &col_name, NULL );
if( r != ERROR_SUCCESS )
return r;
x = lstrcmpW( name, col_name );
HeapFree( GetProcessHeap(), 0, col_name );
if( !x )
{
*n = i;
return ERROR_SUCCESS;
}
}
return ERROR_INVALID_PARAMETER;
}
UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
LPCSTR szQuery, MSIHANDLE *phView)
{
UINT r;
LPCWSTR szwQuery;
TRACE("%ld %s %p\n", hdb, debugstr_a(szQuery), phView);
if( szQuery )
{
szwQuery = HEAP_strdupAtoW( GetProcessHeap(), 0, szQuery );
if( !szwQuery )
return ERROR_FUNCTION_FAILED;
}
else
szwQuery = NULL;
r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
return r;
}
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
LPCWSTR szQuery, MSIHANDLE *phView)
{
MSIDATABASE *db;
MSIHANDLE handle;
MSIQUERY *query;
UINT r;
TRACE("%s %p\n", debugstr_w(szQuery), phView);
if( !szQuery)
return ERROR_INVALID_PARAMETER;
db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
if( !db )
return ERROR_INVALID_HANDLE;
/* pre allocate a handle to hold a pointer to the view */
handle = alloc_msihandle( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY), MSI_CloseView );
if( !handle )
return ERROR_FUNCTION_FAILED;
query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_FUNCTION_FAILED;
query->row = 0;
query->db = db;
query->view = NULL;
r = MSI_ParseSQL( db, szQuery, &query->view );
if( r != ERROR_SUCCESS )
{
MsiCloseHandle( handle );
return r;
}
*phView = handle;
return ERROR_SUCCESS;
}
UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
{
MSIQUERY *query;
MSIVIEW *view;
MSIHANDLE handle;
UINT row_count = 0, col_count = 0, i, ival, ret, type;
TRACE("%ld %p\n", hView, record);
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
view = query->view;
if( !view )
return ERROR_FUNCTION_FAILED;
ret = view->ops->get_dimensions( view, &row_count, &col_count );
if( ret )
return ret;
if( !col_count )
return ERROR_INVALID_PARAMETER;
if( query->row >= row_count )
return ERROR_NO_MORE_ITEMS;
handle = MsiCreateRecord( col_count );
if( !handle )
return ERROR_FUNCTION_FAILED;
for( i=1; i<=col_count; i++ )
{
ret = view->ops->get_column_info( view, i, NULL, &type );
if( ret )
{
ERR("Error getting column type for %d\n", i );
continue;
}
ret = view->ops->fetch_int( view, query->row, i, &ival );
if( ret )
{
ERR("Error fetching data for %d\n", i );
continue;
}
if( ! (type & MSITYPE_VALID ) )
ERR("Invalid type!\n");
/* check if it's nul (0) - if so, don't set anything */
if( !ival )
continue;
if( type & MSITYPE_STRING )
{
LPWSTR sval = MSI_makestring( query->db, ival );
MsiRecordSetStringW( handle, i, sval );
HeapFree( GetProcessHeap(), 0, sval );
}
else
{
if( (type & MSI_DATASIZEMASK) == 2 )
MsiRecordSetInteger( handle, i, ival - (1<<15) );
else
MsiRecordSetInteger( handle, i, ival - (1<<31) );
}
}
query->row ++;
*record = handle;
return ERROR_SUCCESS;
}
UINT WINAPI MsiViewClose(MSIHANDLE hView)
{
MSIQUERY *query;
MSIVIEW *view;
TRACE("%ld\n", hView );
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
view = query->view;
if( !view )
return ERROR_FUNCTION_FAILED;
if( !view->ops->close )
return ERROR_FUNCTION_FAILED;
return view->ops->close( view );
}
UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
{
MSIQUERY *query;
MSIVIEW *view;
TRACE("%ld %ld\n", hView, hRec);
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
view = query->view;
if( !view )
return ERROR_FUNCTION_FAILED;
if( !view->ops->execute )
return ERROR_FUNCTION_FAILED;
query->row = 0;
return view->ops->execute( view, hRec );
}
UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
{
MSIVIEW *view;
MSIQUERY *query;
MSIHANDLE handle;
UINT ret, i, count = 0, type;
LPWSTR name;
TRACE("%ld %d %p\n", hView, info, hRec);
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
view = query->view;
if( !view )
return ERROR_FUNCTION_FAILED;
if( !view->ops->get_dimensions )
return ERROR_FUNCTION_FAILED;
ret = view->ops->get_dimensions( view, NULL, &count );
if( ret )
return ret;
if( !count )
return ERROR_INVALID_PARAMETER;
handle = MsiCreateRecord( count );
if( !handle )
return ERROR_FUNCTION_FAILED;
for( i=0; i<count; i++ )
{
name = NULL;
ret = view->ops->get_column_info( view, i+1, &name, &type );
if( ret != ERROR_SUCCESS )
continue;
MsiRecordSetStringW( handle, i+1, name );
HeapFree( GetProcessHeap(), 0, name );
}
*hRec = handle;
return ERROR_SUCCESS;
}
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{
FIXME("%ld %s\n", hInstall, debugstr_a(szAction) );
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
{
FIXME("%ld %s\n", hInstall, debugstr_w(szAction) );
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb,
LPCSTR szTransformFile, int iErrorCond)
{
FIXME("%ld %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
LPCWSTR szTransformFile, int iErrorCond)
{
FIXME("%ld %s %d\n", hdb, debugstr_w(szTransformFile), iErrorCond);
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
LPCSTR szTransformFile, int iReserved1, int iReserved2 )
{
FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
debugstr_a(szTransformFile), iReserved1, iReserved2);
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
{
FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
debugstr_w(szTransformFile), iReserved1, iReserved2);
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
{
FIXME("%ld\n", hdb);
return ERROR_SUCCESS;
}
UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb,
LPCSTR table, MSIHANDLE* rec)
{
FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec);
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb,
LPCWSTR table, MSIHANDLE* rec)
{
FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
#include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
/* below is the query interface to a table */
typedef struct tagMSIORDERVIEW
{
MSIVIEW view;
MSIDATABASE *db;
MSIVIEW *table;
UINT *reorder;
UINT num_cols;
UINT cols[1];
} MSIORDERVIEW;
static UINT ORDER_compare( MSIORDERVIEW *ov, UINT a, UINT b, UINT *swap )
{
UINT r, i, a_val = 0, b_val = 0;
*swap = 0;
for( i=0; i<ov->num_cols; i++ )
{
r = ov->table->ops->fetch_int( ov->table, a, ov->cols[i], &a_val );
if( r != ERROR_SUCCESS )
return r;
r = ov->table->ops->fetch_int( ov->table, b, ov->cols[i], &b_val );
if( r != ERROR_SUCCESS )
return r;
if( a_val != b_val )
{
if( a_val > b_val )
*swap = 1;
break;
}
}
return ERROR_SUCCESS;
}
static UINT ORDER_mergesort( MSIORDERVIEW *ov, UINT left, UINT right )
{
UINT r, centre = (left + right)/2, temp, swap = 0, i, j;
UINT *array = ov->reorder;
if( left == right )
return ERROR_SUCCESS;
/* sort the left half */
r = ORDER_mergesort( ov, left, centre );
if( r != ERROR_SUCCESS )
return r;
/* sort the right half */
r = ORDER_mergesort( ov, centre+1, right );
if( r != ERROR_SUCCESS )
return r;
for( i=left, j=centre+1; (i<=centre) && (j<=right); i++ )
{
r = ORDER_compare( ov, array[i], array[j], &swap );
if( r != ERROR_SUCCESS )
return r;
if( swap )
{
temp = array[j];
memmove( &array[i+1], &array[i], (j-i)*sizeof (UINT) );
array[i] = temp;
j++;
centre++;
}
}
return ERROR_SUCCESS;
}
static UINT ORDER_verify( MSIORDERVIEW *ov, UINT num_rows )
{
UINT i, swap, r;
for( i=1; i<num_rows; i++ )
{
r = ORDER_compare( ov, ov->reorder[i-1], ov->reorder[i], &swap );
if( r != ERROR_SUCCESS )
return r;
if( !swap )
continue;
ERR("Bad order! %d\n", i);
return ERROR_FUNCTION_FAILED;
}
return ERROR_SUCCESS;
}
static UINT ORDER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
TRACE("%p %d %d %p\n", ov, row, col, val );
if( !ov->table )
return ERROR_FUNCTION_FAILED;
row = ov->reorder[ row ];
return ov->table->ops->fetch_int( ov->table, row, col, val );
}
static UINT ORDER_execute( struct tagMSIVIEW *view, MSIHANDLE record )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
UINT r, num_rows = 0, i;
TRACE("%p %ld\n", ov, record);
if( !ov->table )
return ERROR_FUNCTION_FAILED;
r = ov->table->ops->execute( ov->table, record );
if( r != ERROR_SUCCESS )
return r;
r = ov->table->ops->get_dimensions( ov->table, &num_rows, NULL );
if( r != ERROR_SUCCESS )
return r;
ov->reorder = HeapAlloc( GetProcessHeap(), 0, num_rows*sizeof(UINT) );
if( !ov->reorder )
return ERROR_FUNCTION_FAILED;
for( i=0; i<num_rows; i++ )
ov->reorder[i] = i;
r = ORDER_mergesort( ov, 0, num_rows - 1 );
if( r != ERROR_SUCCESS )
return r;
r = ORDER_verify( ov, num_rows );
if( r != ERROR_SUCCESS )
return r;
return ERROR_SUCCESS;
}
static UINT ORDER_close( struct tagMSIVIEW *view )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
TRACE("%p\n", ov );
if( !ov->table )
return ERROR_FUNCTION_FAILED;
if( ov->reorder )
HeapFree( GetProcessHeap(), 0, ov->reorder );
ov->reorder = NULL;
return ov->table->ops->close( ov->table );
}
static UINT ORDER_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
TRACE("%p %p %p\n", ov, rows, cols );
if( !ov->table )
return ERROR_FUNCTION_FAILED;
return ov->table->ops->get_dimensions( ov->table, rows, cols );
}
static UINT ORDER_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
TRACE("%p %d %p %p\n", ov, n, name, type );
if( !ov->table )
return ERROR_FUNCTION_FAILED;
return ov->table->ops->get_column_info( ov->table, n, name, type );
}
static UINT ORDER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec)
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
TRACE("%p %d %ld\n", ov, eModifyMode, hrec );
if( !ov->table )
return ERROR_FUNCTION_FAILED;
return ov->table->ops->modify( ov->table, eModifyMode, hrec );
}
static UINT ORDER_delete( struct tagMSIVIEW *view )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
TRACE("%p\n", ov );
if( ov->table )
ov->table->ops->delete( ov->table );
if( ov->reorder )
HeapFree( GetProcessHeap(), 0, ov->reorder );
ov->reorder = NULL;
HeapFree( GetProcessHeap(), 0, ov );
return ERROR_SUCCESS;
}
MSIVIEWOPS order_ops =
{
ORDER_fetch_int,
ORDER_execute,
ORDER_close,
ORDER_get_dimensions,
ORDER_get_column_info,
ORDER_modify,
ORDER_delete
};
UINT ORDER_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
{
MSIORDERVIEW *ov = NULL;
UINT count = 0, r;
TRACE("%p\n", ov );
r = table->ops->get_dimensions( table, NULL, &count );
if( r != ERROR_SUCCESS )
{
ERR("can't get table dimensions\n");
return r;
}
ov = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof *ov + sizeof (UINT) * count );
if( !ov )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
ov->view.ops = &order_ops;
ov->db = db;
ov->table = table;
ov->reorder = NULL;
ov->num_cols = 0;
*view = (MSIVIEW*) ov;
return ERROR_SUCCESS;
}
UINT ORDER_AddColumn( MSIVIEW *view, LPWSTR name )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
UINT n, count, r;
MSIVIEW *table;
TRACE("%p adding %s\n", ov, debugstr_w( name ) );
if( ov->view.ops != &order_ops )
return ERROR_FUNCTION_FAILED;
table = ov->table;
if( !table )
return ERROR_FUNCTION_FAILED;
if( !table->ops->get_dimensions )
return ERROR_FUNCTION_FAILED;
if( !table->ops->get_column_info )
return ERROR_FUNCTION_FAILED;
r = table->ops->get_dimensions( table, NULL, &count );
if( r != ERROR_SUCCESS )
return r;
if( ov->num_cols >= count )
return ERROR_FUNCTION_FAILED;
r = VIEW_find_column( table, name, &n );
if( r != ERROR_SUCCESS )
return r;
ov->cols[ov->num_cols] = n;
TRACE("Ordering by column %s (%d)\n", debugstr_w( name ), n);
ov->num_cols++;
return ERROR_SUCCESS;
}
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MSI_QUERY_H
#define __WINE_MSI_QUERY_H
#include "winbase.h"
#include "objidl.h"
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
#define OP_EQ 1
#define OP_AND 2
#define OP_OR 3
#define OP_GT 4
#define OP_LT 5
#define OP_LE 6
#define OP_GE 7
#define OP_NE 8
#define OP_ISNULL 9
#define OP_NOTNULL 10
#define EXPR_COMPLEX 1
#define EXPR_COLUMN 2
#define EXPR_COL_NUMBER 3
#define EXPR_IVAL 4
#define EXPR_SVAL 5
#define EXPR_UVAL 6
struct complex_expr
{
UINT op;
struct expr *left;
struct expr *right;
};
struct expr
{
int type;
union
{
struct complex_expr expr;
INT ival;
UINT uval;
LPWSTR sval;
LPWSTR column;
UINT col_number;
} u;
};
UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phView);
UINT TABLE_CreateView( MSIDATABASE *db, LPWSTR name, MSIVIEW **view );
UINT SELECT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table );
UINT SELECT_AddColumn( MSIVIEW *select, LPWSTR name );
UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table );
UINT ORDER_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table );
UINT ORDER_AddColumn( MSIVIEW *group, LPWSTR name );
UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table );
UINT WHERE_AddCondition( MSIVIEW *view, struct expr *condition );
int sqliteGetToken(const WCHAR *z, int *tokenType);
#endif /* __WINE_MSI_QUERY_H */
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
#include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
/* below is the query interface to a table */
typedef struct tagMSISELECTVIEW
{
MSIVIEW view;
MSIDATABASE *db;
MSIVIEW *table;
UINT num_cols;
UINT max_cols;
UINT cols[1];
} MSISELECTVIEW;
static UINT SELECT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p %d %d %p\n", sv, row, col, val );
if( !sv->table )
return ERROR_FUNCTION_FAILED;
if( (col==0) || (col>sv->num_cols) )
return ERROR_FUNCTION_FAILED;
col = sv->cols[ col - 1 ];
return sv->table->ops->fetch_int( sv->table, row, col, val );
}
static UINT SELECT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p %ld\n", sv, record);
if( !sv->table )
return ERROR_FUNCTION_FAILED;
return sv->table->ops->execute( sv->table, record );
}
static UINT SELECT_close( struct tagMSIVIEW *view )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p\n", sv );
if( !sv->table )
return ERROR_FUNCTION_FAILED;
return sv->table->ops->close( sv->table );
}
static UINT SELECT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p %p %p\n", sv, rows, cols );
if( !sv->table )
return ERROR_FUNCTION_FAILED;
if( cols )
*cols = sv->num_cols;
return sv->table->ops->get_dimensions( sv->table, rows, NULL );
}
static UINT SELECT_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p %d %p %p\n", sv, n, name, type );
if( !sv->table )
return ERROR_FUNCTION_FAILED;
if( (n==0) || (n>sv->num_cols) )
return ERROR_FUNCTION_FAILED;
n = sv->cols[ n - 1 ];
return sv->table->ops->get_column_info( sv->table, n, name, type );
}
static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec)
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p %d %ld\n", sv, eModifyMode, hrec );
if( !sv->table )
return ERROR_FUNCTION_FAILED;
return sv->table->ops->modify( sv->table, eModifyMode, hrec );
}
static UINT SELECT_delete( struct tagMSIVIEW *view )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p\n", sv );
if( sv->table )
sv->table->ops->delete( sv->table );
HeapFree( GetProcessHeap(), 0, sv );
return ERROR_SUCCESS;
}
MSIVIEWOPS select_ops =
{
SELECT_fetch_int,
SELECT_execute,
SELECT_close,
SELECT_get_dimensions,
SELECT_get_column_info,
SELECT_modify,
SELECT_delete
};
UINT SELECT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
{
MSISELECTVIEW *sv = NULL;
UINT count = 0, r;
TRACE("%p\n", sv );
r = table->ops->get_dimensions( table, NULL, &count );
if( r != ERROR_SUCCESS )
{
ERR("can't get table dimensions\n");
return r;
}
sv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof *sv + count*sizeof (UINT) );
if( !sv )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
sv->view.ops = &select_ops;
sv->db = db;
sv->table = table;
sv->num_cols = 0;
sv->max_cols = count;
*view = (MSIVIEW*) sv;
return ERROR_SUCCESS;
}
UINT SELECT_AddColumn( MSIVIEW *view, LPWSTR name )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
UINT r, n=0;
MSIVIEW *table;
TRACE("%p adding %s\n", sv, debugstr_w( name ) );
if( sv->view.ops != &select_ops )
return ERROR_FUNCTION_FAILED;
table = sv->table;
if( !table )
return ERROR_FUNCTION_FAILED;
if( !table->ops->get_dimensions )
return ERROR_FUNCTION_FAILED;
if( !table->ops->get_column_info )
return ERROR_FUNCTION_FAILED;
if( sv->num_cols >= sv->max_cols )
return ERROR_FUNCTION_FAILED;
r = VIEW_find_column( table, name, &n );
if( r != ERROR_SUCCESS )
return r;
sv->cols[sv->num_cols] = n;
TRACE("Translating column %s from %d -> %d\n",
debugstr_w( name ), sv->num_cols, n);
sv->num_cols++;
return ERROR_SUCCESS;
}
This diff is collapsed. Click to expand it.
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
#include "objidl.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y',
'I','n','f','o','r','m','a','t','i','o','n',0 };
static void MSI_CloseSummaryInfo( VOID *arg )
{
MSISUMMARYINFO *suminfo = (MSISUMMARYINFO *) arg;
IPropertyStorage_Release( suminfo->propstg );
}
UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase,
LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo)
{
LPWSTR szwDatabase = NULL;
UINT ret;
TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase),
uiUpdateCount, phSummaryInfo);
if( szDatabase )
{
szwDatabase = HEAP_strdupAtoW( GetProcessHeap(), 0, szDatabase );
if( !szwDatabase )
return ERROR_FUNCTION_FAILED;
}
ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, phSummaryInfo);
if( szwDatabase )
HeapFree( GetProcessHeap(), 0, szwDatabase );
return ret;
}
UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase,
LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo)
{
HRESULT r;
MSIHANDLE handle, hdb = hDatabase;
MSISUMMARYINFO *suminfo;
MSIDATABASE *db;
UINT ret = ERROR_SUCCESS;
IPropertySetStorage *psstg = NULL;
IPropertyStorage *ps = NULL;
DWORD grfMode;
TRACE("%ld %s %d %p\n", hDatabase, debugstr_w(szDatabase),
uiUpdateCount, phSummaryInfo);
if( !phSummaryInfo )
return ERROR_INVALID_PARAMETER;
if( szDatabase )
{
UINT res;
res = MsiOpenDatabaseW(szDatabase, NULL, &hdb);
if( res != ERROR_SUCCESS )
return res;
}
db = msihandle2msiinfo(hdb, MSIHANDLETYPE_DATABASE);
if( !db )
return ERROR_INVALID_PARAMETER;
r = IStorage_QueryInterface( db->storage,
&IID_IPropertySetStorage, (LPVOID)&psstg);
if( FAILED( r ) )
{
ERR("IStorage -> IPropertySetStorage failed\n");
return ERROR_FUNCTION_FAILED;
}
ERR("storage = %p propertysetstorage = %p\n", db->storage, psstg);
grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE;
r = IPropertySetStorage_Open( psstg, &FMTID_SummaryInformation, grfMode, &ps );
if( FAILED( r ) )
{
ERR("failed to get IPropertyStorage r=%08lx\n",r);
ret = ERROR_FUNCTION_FAILED;
goto end;
}
handle = alloc_msihandle( MSIHANDLETYPE_SUMMARYINFO,
sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
if( !handle )
{
ret = ERROR_FUNCTION_FAILED;
goto end;
}
suminfo = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
if( !suminfo )
{
ret = ERROR_FUNCTION_FAILED;
goto end;
}
IPropertyStorage_AddRef(ps);
suminfo->propstg = ps;
*phSummaryInfo = handle;
end:
if( ps )
IPropertyStorage_Release(ps);
if( psstg )
IPropertySetStorage_Release(psstg);
if( !hDatabase )
MsiCloseHandle( hdb );
return ret;
}
UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount)
{
MSISUMMARYINFO *suminfo;
FIXME("%ld %p\n",hSummaryInfo, pCount);
suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
if( !suminfo )
return ERROR_INVALID_HANDLE;
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiSummaryInfoGetPropertyA(
MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue,
FILETIME *pftValue, LPSTR szValueBuf, DWORD *pcchValueBuf)
{
MSISUMMARYINFO *suminfo;
HRESULT r;
PROPSPEC spec;
PROPVARIANT var;
TRACE("%ld %d %p %p %p %p %p\n",
hSummaryInfo, uiProperty, puiDataType, piValue,
pftValue, szValueBuf, pcchValueBuf);
suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
if( !suminfo )
return ERROR_INVALID_HANDLE;
spec.ulKind = PRSPEC_PROPID;
spec.DUMMYUNIONNAME.propid = uiProperty;
r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var);
if( FAILED(r) )
return ERROR_FUNCTION_FAILED;
if( puiDataType )
*puiDataType = var.vt;
switch( var.vt )
{
case VT_I4:
if( piValue )
*piValue = var.DUMMYUNIONNAME.lVal;
break;
case VT_LPSTR:
if( pcchValueBuf && szValueBuf )
{
lstrcpynA(szValueBuf, var.DUMMYUNIONNAME.pszVal, *pcchValueBuf );
*pcchValueBuf = lstrlenA( var.DUMMYUNIONNAME.pszVal );
}
break;
case VT_FILETIME:
if( pftValue )
memcpy(pftValue, &var.DUMMYUNIONNAME.filetime, sizeof (FILETIME) );
break;
case VT_EMPTY:
break;
default:
FIXME("Unknown property variant type\n");
break;
}
return ERROR_SUCCESS;
}
UINT WINAPI MsiSummaryInfoGetPropertyW(
MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue,
FILETIME *pftValue, LPWSTR szValueBuf, DWORD *pcchValueBuf)
{
FIXME("%ld %d %p %p %p %p %p\n",
hSummaryInfo, uiProperty, puiDataType, piValue,
pftValue, szValueBuf, pcchValueBuf);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
*/
#include "winbase.h"
#include <ctype.h>
#include <stdlib.h>
#include "wine/debug.h"
#include "winnls.h"
#include "query.h"
#include "y.tab.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
/*
** All the keywords of the SQL language are stored as in a hash
** table composed of instances of the following structure.
*/
typedef struct Keyword Keyword;
struct Keyword {
const char *zName; /* The keyword name */
int tokenType; /* The token value for this keyword */
};
/*
** 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 },
{ "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 },
{ "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 },
{ "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 },
{ "MATCH", TK_MATCH },
{ "NATURAL", TK_JOIN_KW },
{ "NOT", TK_NOT },
{ "NOTNULL", TK_NOTNULL },
{ "NULL", TK_NULL },
{ "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 },
{ "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 },
};
#define KEYWORD_COUNT ( sizeof aKeywordTable/sizeof (Keyword) )
/*
** This function looks up an identifier to determine if it is a
** keyword. If it is a keyword, the token code of that keyword is
** returned. If the input is not a keyword, TK_ID is returned.
*/
int sqliteKeywordCode(const WCHAR *z, int n){
int i, len;
char buffer[0x10];
len = WideCharToMultiByte( CP_ACP, 0, z, n, buffer, sizeof buffer, NULL, NULL );
for(i=0; i<KEYWORD_COUNT; i++)
{
if(memcmp(buffer, aKeywordTable[i].zName, len))
continue;
if(strlen(aKeywordTable[i].zName) == len )
return aKeywordTable[i].tokenType;
}
return TK_ID;
}
/*
** If X is a character that can be used in an identifier then
** isIdChar[X] will be 1. Otherwise isIdChar[X] will be 0.
**
** In this implementation, an identifier can be a string of
** alphabetic characters, digits, and "_" plus any character
** with the high-order bit set. The latter rule means that
** any sequence of UTF-8 characters or characters taken from
** an extended ISO8859 character set can form an identifier.
*/
static const char isIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Ax */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Bx */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Cx */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Dx */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Ex */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Fx */
};
/*
** Return the length of the token that begins at z[0]. Return
** -1 if the token is (or might be) incomplete. Store the token
** type in *tokenType before returning.
*/
int sqliteGetToken(const WCHAR *z, int *tokenType){
int i;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
for(i=1; isspace(z[i]); i++){}
*tokenType = TK_SPACE;
return i;
}
case '-': {
if( z[1]==0 ) return -1;
if( z[1]=='-' ){
for(i=2; z[i] && z[i]!='\n'; i++){}
*tokenType = TK_COMMENT;
return i;
}
*tokenType = TK_MINUS;
return 1;
}
case '(': {
if( z[1]=='+' && z[2]==')' ){
*tokenType = TK_ORACLE_OUTER_JOIN;
return 3;
}else{
*tokenType = TK_LP;
return 1;
}
}
case ')': {
*tokenType = TK_RP;
return 1;
}
case ';': {
*tokenType = TK_SEMI;
return 1;
}
case '+': {
*tokenType = TK_PLUS;
return 1;
}
case '*': {
*tokenType = TK_STAR;
return 1;
}
case '/': {
if( z[1]!='*' || z[2]==0 ){
*tokenType = TK_SLASH;
return 1;
}
for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){}
if( z[i] ) i++;
*tokenType = TK_COMMENT;
return i;
}
case '%': {
*tokenType = TK_REM;
return 1;
}
case '=': {
*tokenType = TK_EQ;
return 1 + (z[1]=='=');
}
case '<': {
if( z[1]=='=' ){
*tokenType = TK_LE;
return 2;
}else if( z[1]=='>' ){
*tokenType = TK_NE;
return 2;
}else if( z[1]=='<' ){
*tokenType = TK_LSHIFT;
return 2;
}else{
*tokenType = TK_LT;
return 1;
}
}
case '>': {
if( z[1]=='=' ){
*tokenType = TK_GE;
return 2;
}else if( z[1]=='>' ){
*tokenType = TK_RSHIFT;
return 2;
}else{
*tokenType = TK_GT;
return 1;
}
}
case '!': {
if( z[1]!='=' ){
*tokenType = TK_ILLEGAL;
return 2;
}else{
*tokenType = TK_NE;
return 2;
}
}
case '|': {
if( z[1]!='|' ){
*tokenType = TK_BITOR;
return 1;
}else{
*tokenType = TK_CONCAT;
return 2;
}
}
case ',': {
*tokenType = TK_COMMA;
return 1;
}
case '&': {
*tokenType = TK_BITAND;
return 1;
}
case '~': {
*tokenType = TK_BITNOT;
return 1;
}
case '`': case '\'': case '"': {
int delim = z[0];
for(i=1; z[i]; i++){
if( z[i]==delim ){
if( z[i+1]==delim ){
i++;
}else{
break;
}
}
}
if( z[i] ) i++;
*tokenType = TK_STRING;
return i;
}
case '.': {
if( !isdigit(z[1]) ){
*tokenType = TK_DOT;
return 1;
}
/* Fall thru into the next case */
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
*tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){}
if( z[i]=='.' ){
i++;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
if( (z[i]=='e' || z[i]=='E') &&
( isdigit(z[i+1])
|| ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
)
){
i += 2;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}else if( z[0]=='.' ){
*tokenType = TK_FLOAT;
}
return i;
}
case '[': {
for(i=1; z[i] && z[i-1]!=']'; i++){}
*tokenType = TK_ID;
return i;
}
default: {
if( !isIdChar[*z] ){
break;
}
for(i=1; isIdChar[z[i]]; i++){}
*tokenType = sqliteKeywordCode(z, i);
return i;
}
}
*tokenType = TK_ILLEGAL;
return 1;
}
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
#include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
/* below is the query interface to a table */
typedef struct tagMSIWHEREVIEW
{
MSIVIEW view;
MSIDATABASE *db;
MSIVIEW *table;
UINT row_count;
UINT *reorder;
struct expr *cond;
} MSIWHEREVIEW;
static UINT WHERE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %d %d %p\n", wv, row, col, val );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
if( row > wv->row_count )
return ERROR_NO_MORE_ITEMS;
row = wv->reorder[ row ];
return wv->table->ops->fetch_int( wv->table, row, col, val );
}
static UINT INT_evaluate( UINT lval, UINT op, UINT rval )
{
switch( op )
{
case OP_EQ:
return ( lval == rval );
case OP_AND:
return ( lval && rval );
case OP_OR:
return ( lval || rval );
case OP_GT:
return ( lval > rval );
case OP_LT:
return ( lval < rval );
case OP_LE:
return ( lval <= rval );
case OP_GE:
return ( lval >= rval );
case OP_NE:
return ( lval != rval );
case OP_ISNULL:
return ( !lval );
case OP_NOTNULL:
return ( lval );
default:
ERR("Unknown operator %d\n", op );
}
return 0;
}
static UINT WHERE_evaluate( MSIVIEW *table, UINT row,
struct expr *cond, UINT *val )
{
UINT r, lval, rval;
if( !cond )
return ERROR_SUCCESS;
switch( cond->type )
{
case EXPR_COL_NUMBER:
return table->ops->fetch_int( table, row, cond->u.col_number, val );
/* case EXPR_IVAL:
*val = cond->u.ival;
return ERROR_SUCCESS; */
case EXPR_UVAL:
*val = cond->u.uval;
return ERROR_SUCCESS;
case EXPR_COMPLEX:
r = WHERE_evaluate( table, row, cond->u.expr.left, &lval );
if( r != ERROR_SUCCESS )
return r;
r = WHERE_evaluate( table, row, cond->u.expr.right, &rval );
if( r != ERROR_SUCCESS )
return r;
*val = INT_evaluate( lval, cond->u.expr.op, rval );
return ERROR_SUCCESS;
default:
ERR("Invalid expression type\n");
break;
}
return ERROR_SUCCESS;
}
static UINT WHERE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
UINT count = 0, r, val, i;
MSIVIEW *table = wv->table;
TRACE("%p %ld\n", wv, record);
if( !table )
return ERROR_FUNCTION_FAILED;
r = table->ops->execute( table, record );
if( r != ERROR_SUCCESS )
return r;
r = table->ops->get_dimensions( table, &count, NULL );
if( r != ERROR_SUCCESS )
return r;
wv->reorder = HeapAlloc( GetProcessHeap(), 0, count*sizeof(UINT) );
if( !wv->reorder )
return ERROR_FUNCTION_FAILED;
for( i=0; i<count; i++ )
{
val = 0;
r = WHERE_evaluate( table, i, wv->cond, &val );
if( r != ERROR_SUCCESS )
return r;
if( val )
wv->reorder[ wv->row_count ++ ] = i;
}
return ERROR_SUCCESS;
}
static UINT WHERE_close( struct tagMSIVIEW *view )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p\n", wv );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
if( wv->reorder )
HeapFree( GetProcessHeap(), 0, wv->reorder );
wv->reorder = NULL;
return wv->table->ops->close( wv->table );
}
static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %p %p\n", wv, rows, cols );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
if( rows )
{
if( !wv->reorder )
return ERROR_FUNCTION_FAILED;
*rows = wv->row_count;
}
return wv->table->ops->get_dimensions( wv->table, NULL, cols );
}
static UINT WHERE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %d %p %p\n", wv, n, name, type );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
return wv->table->ops->get_column_info( wv->table, n, name, type );
}
static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec)
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %d %ld\n", wv, eModifyMode, hrec );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
return wv->table->ops->modify( wv->table, eModifyMode, hrec );
}
static void WHERE_delete_expr( struct expr *e )
{
if( !e )
return;
if( e->type == EXPR_COMPLEX )
{
WHERE_delete_expr( e->u.expr.left );
WHERE_delete_expr( e->u.expr.right );
}
HeapFree( GetProcessHeap(), 0, e );
}
static UINT WHERE_delete( struct tagMSIVIEW *view )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p\n", wv );
if( wv->table )
wv->table->ops->delete( wv->table );
if( wv->reorder )
HeapFree( GetProcessHeap(), 0, wv->reorder );
wv->reorder = NULL;
wv->row_count = 0;
WHERE_delete_expr( wv->cond );
HeapFree( GetProcessHeap(), 0, wv );
return ERROR_SUCCESS;
}
MSIVIEWOPS where_ops =
{
WHERE_fetch_int,
WHERE_execute,
WHERE_close,
WHERE_get_dimensions,
WHERE_get_column_info,
WHERE_modify,
WHERE_delete
};
UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
{
MSIWHEREVIEW *wv = NULL;
UINT count = 0, r;
TRACE("%p\n", wv );
r = table->ops->get_dimensions( table, NULL, &count );
if( r != ERROR_SUCCESS )
{
ERR("can't get table dimensions\n");
return r;
}
wv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *wv );
if( !wv )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
wv->view.ops = &where_ops;
wv->db = db;
wv->table = table;
wv->row_count = 0;
wv->reorder = NULL;
*view = (MSIVIEW*) wv;
return ERROR_SUCCESS;
}
static UINT WHERE_VerifyCondition( MSIVIEW *table, struct expr *cond,
UINT *valid )
{
UINT r, col = 0;
switch( cond->type )
{
case EXPR_COLUMN:
r = VIEW_find_column( table, cond->u.column, &col );
if( r == ERROR_SUCCESS )
{
*valid = 1;
cond->type = EXPR_COL_NUMBER;
cond->u.col_number = col;
}
else
{
*valid = 0;
ERR("Couldn't find column %s\n", debugstr_w( cond->u.column ) );
}
break;
case EXPR_COMPLEX:
r = WHERE_VerifyCondition( table, cond->u.expr.left, valid );
if( r != ERROR_SUCCESS )
return r;
if( !*valid )
return ERROR_SUCCESS;
r = WHERE_VerifyCondition( table, cond->u.expr.right, valid );
if( r != ERROR_SUCCESS )
return r;
break;
case EXPR_IVAL:
*valid = 1;
cond->type = EXPR_UVAL;
cond->u.uval = cond->u.ival + (1<<15);
break;
case EXPR_SVAL:
*valid = 0;
FIXME("can't deal with string values yet\n");
break;
default:
ERR("Invalid expression type\n");
*valid = 0;
break;
}
return ERROR_SUCCESS;
}
UINT WHERE_AddCondition( MSIVIEW *view, struct expr *cond )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW *) view;
UINT r, valid = 0;
if( wv->view.ops != &where_ops )
return ERROR_FUNCTION_FAILED;
if( !wv->table )
return ERROR_INVALID_PARAMETER;
if( !cond )
return ERROR_SUCCESS;
TRACE("Adding condition\n");
r = WHERE_VerifyCondition( wv->table, cond, &valid );
if( r != ERROR_SUCCESS )
ERR("condition evaluation failed\n");
TRACE("condition is %s\n", valid ? "valid" : "invalid" );
if( !valid )
{
WHERE_delete_expr( cond );
return ERROR_FUNCTION_FAILED;
}
wv->cond = cond;
return ERROR_SUCCESS;
}
......@@ -107,6 +107,8 @@ WINDOWS_INCLUDES = \
mmsystem.h \
msacm.h \
msacmdlg.h \
msi.h \
msiquery.h \
mssip.h \
mswsock.h \
nb30.h \
......
/*
* Copyright (C) 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MSI_H
#define __WINE_MSI_H
typedef unsigned long MSIHANDLE;
typedef enum tagINSTALLSTATE
{
INSTALLSTATE_BADCONFIG = -6,
INSTALLSTATE_INCOMPLETE = -5,
INSTALLSTATE_SOURCEABSENT = -4,
INSTALLSTATE_MOREDATA = -3,
INSTALLSTATE_INVALIDARG = -2,
INSTALLSTATE_UNKNOWN = -1,
INSTALLSTATE_BROKEN = 0,
INSTALLSTATE_ADVERTISED = 1,
INSTALLSTATE_ABSENT = 2,
INSTALLSTATE_LOCAL = 3,
INSTALLSTATE_SOURCE = 4,
INSTALLSTATE_DEFAULT = 5
} INSTALLSTATE;
typedef enum tagINSTALLUILEVEL
{
INSTALLUILEVEL_NOCHANGE = 0,
INSTALLUILEVEL_DEFAULT = 1,
INSTALLUILEVEL_NONE = 2,
INSTALLUILEVEL_BASIC = 3,
INSTALLUILEVEL_REDUCED = 4,
INSTALLUILEVEL_FULL = 5
} INSTALLUILEVEL;
#define MSIDBOPEN_READONLY 0
#define MSIDBOPEN_TRANSACT 1
#define MSIDBOPEN_DIRECT 2
#define MSIDBOPEN_CREATE 3
UINT WINAPI MsiInstallProductA(LPCSTR, LPCSTR);
UINT WINAPI MsiInstallProductW(LPCWSTR, LPCWSTR);
UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid);
UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid);
UINT WINAPI MsiEnumFeaturesA(LPCSTR, DWORD, LPSTR, LPSTR);
UINT WINAPI MsiEnumFeaturesW(LPCWSTR, DWORD, LPWSTR, LPWSTR);
UINT WINAPI MsiEnumComponentsA(DWORD, LPSTR);
UINT WINAPI MsiEnumComponentsW(DWORD, LPWSTR);
UINT WINAPI MsiEnumClientsA(LPCSTR, DWORD, LPSTR);
UINT WINAPI MsiEnumClientsW(LPCWSTR, DWORD, LPWSTR);
UINT WINAPI MsiOpenDatabaseA(LPCSTR, LPCSTR, MSIHANDLE *);
UINT WINAPI MsiOpenDatabaseW(LPCWSTR, LPCWSTR, MSIHANDLE *);
UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE, LPCSTR, UINT, MSIHANDLE *);
UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE, LPCWSTR, UINT, MSIHANDLE *);
UINT WINAPI MsiSummaryInfoGetPropertyA(MSIHANDLE,UINT,UINT*,INT*,FILETIME*,LPSTR,DWORD*);
UINT WINAPI MsiSummaryInfoGetPropertyW(MSIHANDLE,UINT,UINT*,INT*,FILETIME*,LPWSTR,DWORD*);
UINT WINAPI MsiCloseHandle(MSIHANDLE);
UINT WINAPI MsiCloseAllHandles();
UINT WINAPI MsiProvideComponentFromDescriptorA(LPCSTR,LPSTR,DWORD*,DWORD*);
UINT WINAPI MsiProvideComponentFromDescriptorW(LPCWSTR,LPWSTR,DWORD*,DWORD*);
#endif /* __WINE_MSI_H */
/*
* Copyright (C) 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MSIQUERY_H
#define __WINE_MSIQUERY_H
#include "msi.h"
typedef enum tagMSICONDITION
{
MSICONDITION_FALSE = 0,
MSICONDITION_TRUE = 1,
MSICONDITION_NONE = 2,
MSICONDITION_ERROR = 3,
} MSICONDITION;
#define MSI_NULL_INTEGER 0x80000000
typedef enum tagMSICOLINFO
{
MSICOLINFO_NAMES = 0,
MSICOLINFO_TYPES = 1
} MSICOLINFO;
typedef enum tagMSIMODIFY
{
MSIMODIFY_REFRESH = 0,
MSIMODIFY_INSERT = 1,
MSIMODIFY_UPDATE = 2,
MSIMODIFY_ASSIGN = 3,
MSIMODIFY_REPLACE = 4,
MSIMODIFY_MERGE = 5,
MSIMODIFY_DELETE = 6,
MSIMODIFY_INSERT_TEMPORARY = 7,
MSIMODIFY_VALIDATE = 8,
MSIMODIFY_VALIDATE_NEW = 9,
MSIMODIFY_VALIDATE_FIELD = 10,
MSIMODIFY_VALIDATE_DELETE = 11
} MSIMODIFY;
#define MSI_NULL_INTEGER 0x80000000
/* view manipulation */
UINT WINAPI MsiViewFetch(MSIHANDLE,MSIHANDLE*);
UINT WINAPI MsiViewExecute(MSIHANDLE,MSIHANDLE);
UINT WINAPI MsiViewClose(MSIHANDLE);
UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE,LPCSTR,MSIHANDLE*);
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE,LPCWSTR,MSIHANDLE*);
/* record manipulation */
MSIHANDLE WINAPI MsiCreateRecord(unsigned int);
UINT WINAPI MsiRecordClearData(MSIHANDLE);
UINT WINAPI MsiRecordSetInteger(MSIHANDLE,unsigned int,int);
UINT WINAPI MsiRecordSetStringA(MSIHANDLE,unsigned int,LPCSTR);
UINT WINAPI MsiRecordSetStringW(MSIHANDLE,unsigned int,LPCWSTR);
UINT WINAPI MsiRecordGetStringA(MSIHANDLE,unsigned int,LPSTR,DWORD*);
UINT WINAPI MsiRecordGetStringW(MSIHANDLE,unsigned int,LPWSTR,DWORD*);
UINT WINAPI MsiRecordGetFieldCount(MSIHANDLE);
int WINAPI MsiRecordGetInteger(MSIHANDLE,unsigned int);
UINT WINAPI MsiRecordDataSize(MSIHANDLE,unsigned int);
BOOL WINAPI MsiRecordIsNull(MSIHANDLE,unsigned int);
UINT WINAPI MsiFormatRecordA(MSIHANDLE,MSIHANDLE,LPSTR,DWORD*);
UINT WINAPI MsiFormatRecordW(MSIHANDLE,MSIHANDLE,LPWSTR,DWORD*);
UINT WINAPI MsiRecordSetStreamA(MSIHANDLE,unsigned int,LPCSTR);
UINT WINAPI MsiRecordSetStreamW(MSIHANDLE,unsigned int,LPCWSTR);
UINT WINAPI MsiRecordReadStream(MSIHANDLE,unsigned int,char*,DWORD *);
UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE,LPCSTR,MSIHANDLE*);
UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE,LPCWSTR,MSIHANDLE*);
/* installing */
UINT WINAPI MsiDoActionA(MSIHANDLE,LPCSTR );
UINT WINAPI MsiDoActionW(MSIHANDLE,LPCWSTR );
/* database transforms */
UINT WINAPI MsiDatabaseApplyTransformA(MSIHANDLE,LPCSTR,int);
UINT WINAPI MsiDatabaseApplyTransformW(MSIHANDLE,LPCWSTR,int);
UINT WINAPI MsiDatabaseGenerateTransformA(MSIHANDLE,MSIHANDLE,LPCSTR,int,int);
UINT WINAPI MsiDatabaseGenerateTransformW(MSIHANDLE,MSIHANDLE,LPCWSTR,int,int);
UINT WINAPI MsiDatabaseCommit(MSIHANDLE);
#endif /* __WINE_MSIQUERY_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment