ReactOS 0.4.16-dev-136-g52192f1
table.c File Reference
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "winnls.h"
#include "msipriv.h"
#include "query.h"
#include "wine/debug.h"
Include dependency graph for table.c:

Go to the source code of this file.

Classes

struct  column_hash_entry
 
struct  column_info
 
struct  tagMSITABLE
 
struct  table_view
 
struct  transform_data
 

Macros

#define COBJMACROS
 
#define MSITABLE_HASH_TABLE_SIZE   37
 
#define MAX_STREAM_NAME   0x1f
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (msidb)
 
static UINT bytes_per_column (MSIDATABASE *db, const struct column_info *col, UINT bytes_per_strref)
 
static int utf2mime (int x)
 
LPWSTR encode_streamname (BOOL bTable, LPCWSTR in)
 
static int mime2utf (int x)
 
BOOL decode_streamname (LPCWSTR in, LPWSTR out)
 
void enum_stream_names (IStorage *stg)
 
UINT read_stream_data (IStorage *stg, LPCWSTR stname, BOOL table, BYTE **pdata, UINT *psz)
 
UINT write_stream_data (IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable)
 
static void free_colinfo (struct column_info *colinfo, UINT count)
 
static void free_table (MSITABLE *table)
 
static UINT table_get_row_size (MSIDATABASE *db, const struct column_info *cols, UINT count, UINT bytes_per_strref)
 
static UINT read_table_from_storage (MSIDATABASE *db, MSITABLE *t, IStorage *stg)
 
void free_cached_tables (MSIDATABASE *db)
 
static MSITABLEfind_cached_table (MSIDATABASE *db, LPCWSTR name)
 
static void table_calc_column_offsets (MSIDATABASE *db, struct column_info *colinfo, DWORD count)
 
static UINT get_defaulttablecolumns (MSIDATABASE *db, const WCHAR *name, struct column_info *colinfo, UINT *sz)
 
static UINT get_tablecolumns (MSIDATABASE *, const WCHAR *, struct column_info *, UINT *)
 
static UINT table_get_column_info (MSIDATABASE *db, const WCHAR *name, struct column_info **pcols, UINT *pcount)
 
static UINT get_table (MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret)
 
static UINT read_table_int (BYTE *const *data, UINT row, UINT col, UINT bytes)
 
UINT msi_create_table (MSIDATABASE *db, LPCWSTR name, column_info *col_info, MSICONDITION persistent, BOOL hold)
 
static UINT save_table (MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref)
 
static void update_table_columns (MSIDATABASE *db, const WCHAR *name)
 
BOOL TABLE_Exists (MSIDATABASE *db, LPCWSTR name)
 
static UINT TABLE_fetch_int (struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
 
static UINT get_stream_name (const struct table_view *tv, UINT row, WCHAR **pstname)
 
static UINT TABLE_fetch_stream (struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
 
static UINT table_set_bytes (struct table_view *tv, UINT row, UINT col, UINT val)
 
static UINT int_to_table_storage (const struct table_view *tv, UINT col, int val, UINT *ret)
 
static UINT TABLE_set_int (MSIVIEW *view, UINT row, UINT col, int val)
 
static UINT TABLE_set_string (MSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
 
static UINT TABLE_get_row (struct tagMSIVIEW *view, UINT row, MSIRECORD **rec)
 
static UINT add_stream (MSIDATABASE *db, const WCHAR *name, IStream *data)
 
static UINT TABLE_set_stream (MSIVIEW *view, UINT row, UINT col, IStream *stream)
 
static UINT get_table_value_from_record (struct table_view *tv, MSIRECORD *rec, UINT iField, UINT *pvalue)
 
static UINT TABLE_set_row (struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
 
static UINT table_create_new_row (struct tagMSIVIEW *view, UINT *num, BOOL temporary)
 
static UINT TABLE_execute (struct tagMSIVIEW *view, MSIRECORD *record)
 
static UINT TABLE_close (struct tagMSIVIEW *view)
 
static UINT TABLE_get_dimensions (struct tagMSIVIEW *view, UINT *rows, UINT *cols)
 
static UINT TABLE_get_column_info (struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
 
static UINT table_find_row (struct table_view *, MSIRECORD *, UINT *, UINT *)
 
static UINT table_validate_new (struct table_view *tv, MSIRECORD *rec, UINT *column)
 
static int compare_record (struct table_view *tv, UINT row, MSIRECORD *rec)
 
static int find_insert_index (struct table_view *tv, MSIRECORD *rec)
 
static UINT TABLE_insert_row (struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
 
static UINT TABLE_delete_row (struct tagMSIVIEW *view, UINT row)
 
static UINT table_update (struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
 
static UINT table_assign (struct tagMSIVIEW *view, MSIRECORD *rec)
 
static UINT refresh_record (struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
 
static UINT TABLE_modify (struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
 
static UINT TABLE_delete (struct tagMSIVIEW *view)
 
static UINT TABLE_add_ref (struct tagMSIVIEW *view)
 
static UINT TABLE_remove_column (struct tagMSIVIEW *view, UINT number)
 
static UINT TABLE_release (struct tagMSIVIEW *view)
 
static UINT TABLE_add_column (struct tagMSIVIEW *view, LPCWSTR column, INT type, BOOL hold)
 
static UINT TABLE_drop (struct tagMSIVIEW *view)
 
UINT TABLE_CreateView (MSIDATABASE *db, LPCWSTR name, MSIVIEW **view)
 
static WCHARcreate_key_string (struct table_view *tv, MSIRECORD *rec)
 
static UINT record_stream_name (const struct table_view *tv, MSIRECORD *rec, WCHAR *name, DWORD *len)
 
static UINT TransformView_fetch_int (MSIVIEW *view, UINT row, UINT col, UINT *val)
 
static UINT TransformView_fetch_stream (MSIVIEW *view, UINT row, UINT col, IStream **stm)
 
static UINT TransformView_set_row (MSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
 
static UINT TransformView_create_table (struct table_view *tv, MSIRECORD *rec)
 
static UINT TransformView_add_column (struct table_view *tv, MSIRECORD *rec)
 
static UINT TransformView_insert_row (MSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
 
static UINT TransformView_drop_table (struct table_view *tv, UINT row)
 
static UINT TransformView_delete_row (MSIVIEW *view, UINT row)
 
static UINT TransformView_execute (MSIVIEW *view, MSIRECORD *record)
 
static UINT TransformView_close (MSIVIEW *view)
 
static UINT TransformView_get_dimensions (MSIVIEW *view, UINT *rows, UINT *cols)
 
static UINT TransformView_get_column_info (MSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
 
static UINT TransformView_delete (MSIVIEW *view)
 
static UINT TransformView_Create (MSIDATABASE *db, string_table *st, LPCWSTR name, MSIVIEW **view)
 
UINT MSI_CommitTables (MSIDATABASE *db)
 
MSICONDITION MSI_DatabaseIsTablePersistent (MSIDATABASE *db, LPCWSTR table)
 
static UINT read_raw_int (const BYTE *data, UINT col, UINT bytes)
 
static UINT record_encoded_stream_name (const struct table_view *tv, MSIRECORD *rec, WCHAR **pstname)
 
static MSIRECORDget_transform_record (const struct table_view *tv, const string_table *st, IStorage *stg, const BYTE *rawdata, UINT bytes_per_strref)
 
static void dump_table (const string_table *st, const USHORT *rawdata, UINT rawsize)
 
static UINTrecord_to_row (const struct table_view *tv, MSIRECORD *rec)
 
static UINT row_matches (struct table_view *tv, UINT row, const UINT *data, UINT *column)
 
static UINT table_load_transform (MSIDATABASE *db, IStorage *stg, string_table *st, struct transform_data *transform, UINT bytes_per_strref, int err_cond)
 
UINT msi_table_apply_transform (MSIDATABASE *db, IStorage *stg, int err_cond)
 

Variables

static const struct column_info _Columns_cols [4]
 
static const struct column_info _Tables_cols [1]
 
static const MSIVIEWOPS table_ops
 
static const MSIVIEWOPS transform_view_ops
 

Macro Definition Documentation

◆ COBJMACROS

#define COBJMACROS

Definition at line 24 of file table.c.

◆ MAX_STREAM_NAME

#define MAX_STREAM_NAME   0x1f

Definition at line 87 of file table.c.

◆ MSITABLE_HASH_TABLE_SIZE

#define MSITABLE_HASH_TABLE_SIZE   37

Definition at line 41 of file table.c.

Function Documentation

◆ add_stream()

static UINT add_stream ( MSIDATABASE db,
const WCHAR name,
IStream data 
)
static

Definition at line 1290 of file table.c.

1291{
1292 MSIQUERY *query;
1293 MSIRECORD *rec;
1294 UINT r;
1295
1296 TRACE("%p %s %p\n", db, debugstr_w(name), data);
1297
1298 if (!(rec = MSI_CreateRecord( 2 )))
1299 return ERROR_OUTOFMEMORY;
1300
1301 r = MSI_RecordSetStringW( rec, 1, name );
1302 if (r != ERROR_SUCCESS)
1303 goto done;
1304
1305 r = MSI_RecordSetIStream( rec, 2, data );
1306 if (r != ERROR_SUCCESS)
1307 goto done;
1308
1309 r = MSI_DatabaseOpenViewW( db, L"INSERT INTO `_Streams` (`Name`,`Data`) VALUES (?,?)", &query );
1310 if (r != ERROR_SUCCESS)
1311 goto done;
1312
1313 r = MSI_ViewExecute( query, rec );
1314 msiobj_release( &query->hdr );
1315 if (r == ERROR_SUCCESS)
1316 goto done;
1317
1318 msiobj_release( &rec->hdr );
1319 if (!(rec = MSI_CreateRecord( 2 )))
1320 return ERROR_OUTOFMEMORY;
1321
1322 r = MSI_RecordSetIStream( rec, 1, data );
1323 if (r != ERROR_SUCCESS)
1324 goto done;
1325
1326 r = MSI_RecordSetStringW( rec, 2, name );
1327 if (r != ERROR_SUCCESS)
1328 goto done;
1329
1330 r = MSI_DatabaseOpenViewW( db, L"UPDATE `_Streams` SET `Data` = ? WHERE `Name` = ?", &query );
1331 if (r != ERROR_SUCCESS)
1332 goto done;
1333
1334 r = MSI_ViewExecute( query, rec );
1335 msiobj_release( &query->hdr );
1336
1337done:
1338 msiobj_release( &rec->hdr );
1339 return r;
1340}
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define debugstr_w
Definition: kernel32.h:32
UINT MSI_ViewExecute(MSIQUERY *, MSIRECORD *)
Definition: msiquery.c:502
UINT MSI_RecordSetIStream(MSIRECORD *, UINT, IStream *)
Definition: record.c:836
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **)
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR)
Definition: record.c:597
MSIRECORD * MSI_CreateRecord(UINT)
Definition: record.c:76
unsigned int UINT
Definition: ndis.h:50
#define L(x)
Definition: ntvdm.h:50
#define TRACE(s)
Definition: solgame.cpp:4
Definition: name.c:39
MSIOBJECTHDR hdr
Definition: msipriv.h:151

Referenced by TABLE_set_row(), and TABLE_set_stream().

◆ bytes_per_column()

static UINT bytes_per_column ( MSIDATABASE db,
const struct column_info col,
UINT  bytes_per_strref 
)
inlinestatic

Definition at line 89 of file table.c.

90{
91 if( MSITYPE_IS_BINARY(col->type) )
92 return 2;
93
94 if( col->type & MSITYPE_STRING )
95 return bytes_per_strref;
96
97 if( (col->type & 0xff) <= 2)
98 return 2;
99
100 if( (col->type & 0xff) != 4 )
101 ERR("Invalid column size %u\n", col->type & 0xff);
102
103 return 4;
104}
#define ERR(fmt,...)
Definition: precomp.h:57
#define MSITYPE_IS_BINARY(type)
Definition: msipriv.h:62
#define MSITYPE_STRING
Definition: msipriv.h:50
UINT type
Definition: table.c:55

Referenced by get_stream_name(), get_transform_record(), read_table_from_storage(), save_table(), table_calc_column_offsets(), TABLE_fetch_int(), table_get_row_size(), table_load_transform(), and table_set_bytes().

◆ compare_record()

static int compare_record ( struct table_view tv,
UINT  row,
MSIRECORD rec 
)
static

Definition at line 1650 of file table.c.

1651{
1652 UINT r, i, ivalue, x;
1653
1654 for (i = 0; i < tv->num_cols; i++ )
1655 {
1656 if (!(tv->columns[i].type & MSITYPE_KEY)) continue;
1657
1658 r = get_table_value_from_record( tv, rec, i + 1, &ivalue );
1659 if (r != ERROR_SUCCESS)
1660 return 1;
1661
1662 r = TABLE_fetch_int( &tv->view, row, i + 1, &x );
1663 if (r != ERROR_SUCCESS)
1664 {
1665 WARN("TABLE_fetch_int should not fail here %u\n", r);
1666 return -1;
1667 }
1668 if (ivalue > x)
1669 {
1670 return 1;
1671 }
1672 else if (ivalue == x)
1673 {
1674 if (i < tv->num_cols - 1) continue;
1675 return 0;
1676 }
1677 else
1678 return -1;
1679 }
1680 return 1;
1681}
#define WARN(fmt,...)
Definition: precomp.h:61
static UINT TABLE_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: table.c:1007
static UINT get_table_value_from_record(struct table_view *tv, MSIRECORD *rec, UINT iField, UINT *pvalue)
Definition: table.c:1358
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int JSAMPARRAY int int JDIMENSION num_cols
Definition: jpegint.h:421
#define MSITYPE_KEY
Definition: msipriv.h:52
UINT num_cols
Definition: table.c:1002
struct column_info * columns
Definition: table.c:1001
MSIVIEW view
Definition: table.c:998

Referenced by find_insert_index().

◆ create_key_string()

static WCHAR * create_key_string ( struct table_view tv,
MSIRECORD rec 
)
static

Definition at line 2233 of file table.c.

2234{
2235 DWORD i, p, len, key_len = 0;
2236 WCHAR *key;
2237
2238 for (i = 0; i < tv->num_cols; i++)
2239 {
2240 if (!(tv->columns[i].type & MSITYPE_KEY))
2241 continue;
2242 if (MSI_RecordGetStringW( rec, i+1, NULL, &len ) == ERROR_SUCCESS)
2243 key_len += len;
2244 key_len++;
2245 }
2246
2247 key = malloc( key_len * sizeof(WCHAR) );
2248 if(!key)
2249 return NULL;
2250
2251 p = 0;
2252 for (i = 0; i < tv->num_cols; i++)
2253 {
2254 if (!(tv->columns[i].type & MSITYPE_KEY))
2255 continue;
2256 if (p)
2257 key[p++] = '\t';
2258 len = key_len - p;
2259 if (MSI_RecordGetStringW( rec, i+1, key + p, &len ) == ERROR_SUCCESS)
2260 p += len;
2261 }
2262 return key;
2263}
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
unsigned long DWORD
Definition: ntddk_ex.h:95
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD)
Definition: copy.c:22
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by TransformView_delete_row(), TransformView_insert_row(), and TransformView_set_row().

◆ decode_streamname()

BOOL decode_streamname ( LPCWSTR  in,
LPWSTR  out 
)

Definition at line 180 of file table.c.

181{
182 WCHAR ch;
183 DWORD count = 0;
184
185 while ( (ch = *in++) )
186 {
187 if( (ch >= 0x3800 ) && (ch < 0x4840 ) )
188 {
189 if( ch >= 0x4800 )
190 ch = mime2utf(ch-0x4800);
191 else
192 {
193 ch -= 0x3800;
194 *out++ = mime2utf(ch&0x3f);
195 count++;
196 ch = mime2utf((ch>>6)&0x3f);
197 }
198 }
199 *out++ = ch;
200 count++;
201 }
202 *out = 0;
203 return count;
204}
static int mime2utf(int x)
Definition: table.c:167
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint in
Definition: glext.h:9616
static FILE * out
Definition: regtests2xml.c:44

Referenced by enum_stream_names(), load_streams(), and msi_table_apply_transform().

◆ dump_table()

static void dump_table ( const string_table st,
const USHORT rawdata,
UINT  rawsize 
)
static

Definition at line 3065 of file table.c.

3066{
3067 UINT i;
3068 for (i = 0; i < rawsize / 2; i++)
3069 {
3070 int len;
3071 const WCHAR *sval = msi_string_lookup( st, rawdata[i], &len );
3072 MESSAGE(" %04x %s\n", rawdata[i], debugstr_wn(sval, len) );
3073 }
3074}
#define debugstr_wn
Definition: kernel32.h:33
#define MESSAGE
Definition: options.h:86
const WCHAR * msi_string_lookup(const string_table *st, UINT id, int *len)
Definition: string.c:343

Referenced by table_load_transform().

◆ encode_streamname()

LPWSTR encode_streamname ( BOOL  bTable,
LPCWSTR  in 
)

Definition at line 121 of file table.c.

122{
124 DWORD ch, next;
125 LPWSTR out, p;
126
127 if( !bTable )
128 count = lstrlenW( in )+2;
129 if (!(out = malloc( count * sizeof(WCHAR) ))) return NULL;
130 p = out;
131
132 if( bTable )
133 {
134 *p++ = 0x4840;
135 count --;
136 }
137 while( count -- )
138 {
139 ch = *in++;
140 if( !ch )
141 {
142 *p = ch;
143 return out;
144 }
145 if( ( ch < 0x80 ) && ( utf2mime(ch) >= 0 ) )
146 {
147 ch = utf2mime(ch) + 0x4800;
148 next = *in;
149 if( next && (next<0x80) )
150 {
151 next = utf2mime(next);
152 if( next != -1 )
153 {
154 next += 0x3ffffc0;
155 ch += (next<<6);
156 in++;
157 }
158 }
159 }
160 *p++ = ch;
161 }
162 ERR("Failed to encode stream name (%s)\n",debugstr_w(in));
163 free( out );
164 return NULL;
165}
#define free
Definition: debug_ros.c:5
#define lstrlenW
Definition: compat.h:750
static int utf2mime(int x)
Definition: table.c:106
#define MAX_STREAM_NAME
Definition: table.c:87
static unsigned __int64 next
Definition: rand_nt.c:6
WCHAR * LPWSTR
Definition: xmlstorage.h:184

Referenced by read_stream_data(), record_encoded_stream_name(), and write_stream_data().

◆ enum_stream_names()

void enum_stream_names ( IStorage stg)

Definition at line 206 of file table.c.

207{
208 IEnumSTATSTG *stgenum = NULL;
209 HRESULT r;
210 STATSTG stat;
211 ULONG n, count;
212 WCHAR name[0x40];
213
214 r = IStorage_EnumElements( stg, 0, NULL, 0, &stgenum );
215 if( FAILED( r ) )
216 return;
217
218 n = 0;
219 while( 1 )
220 {
221 count = 0;
222 r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
223 if( FAILED( r ) || !count )
224 break;
225 decode_streamname( stat.pwcsName, name );
226 TRACE( "stream %2lu -> %s %s\n", n, debugstr_w(stat.pwcsName), debugstr_w(name) );
227 CoTaskMemFree( stat.pwcsName );
228 n++;
229 }
230
231 IEnumSTATSTG_Release( stgenum );
232}
#define stat
Definition: acwin.h:99
BOOL decode_streamname(LPCWSTR in, LPWSTR out)
Definition: table.c:180
GLdouble n
Definition: glext.h:7729
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
#define FAILED(hr)
Definition: intsafe.h:51
Definition: stat.h:55
uint32_t ULONG
Definition: typedefs.h:59

Referenced by MSI_DatabaseApplyTransformW(), and MSI_OpenDatabaseW().

◆ find_cached_table()

static MSITABLE * find_cached_table ( MSIDATABASE db,
LPCWSTR  name 
)
static

Definition at line 483 of file table.c.

484{
485 MSITABLE *t;
486
488 if( !wcscmp( name, t->name ) )
489 return t;
490
491 return NULL;
492}
GLdouble GLdouble t
Definition: gl.h:2047
uint32_t entry
Definition: isohybrid.c:63
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
WCHAR * name
Definition: name.c:42
struct list tables
Definition: msipriv.h:118

Referenced by get_table(), and update_table_columns().

◆ find_insert_index()

static int find_insert_index ( struct table_view tv,
MSIRECORD rec 
)
static

Definition at line 1683 of file table.c.

1684{
1685 int idx, c, low = 0, high = tv->table->row_count - 1;
1686
1687 TRACE("%p %p\n", tv, rec);
1688
1689 while (low <= high)
1690 {
1691 idx = (low + high) / 2;
1692 c = compare_record( tv, idx, rec );
1693
1694 if (c < 0)
1695 high = idx - 1;
1696 else if (c > 0)
1697 low = idx + 1;
1698 else
1699 {
1700 TRACE("found %u\n", idx);
1701 return idx;
1702 }
1703 }
1704 TRACE("found %u\n", high + 1);
1705 return high + 1;
1706}
unsigned int idx
Definition: utils.c:41
static int compare_record(struct table_view *tv, UINT row, MSIRECORD *rec)
Definition: table.c:1650
const GLubyte * c
Definition: glext.h:8905
#define c
Definition: ke_i.h:80
MSITABLE * table
Definition: table.c:1000
UINT row_count
Definition: table.c:64

Referenced by TABLE_insert_row().

◆ free_cached_tables()

void free_cached_tables ( MSIDATABASE db)

Definition at line 472 of file table.c.

473{
474 while( !list_empty( &db->tables ) )
475 {
477
478 list_remove( &t->entry );
479 free_table( t );
480 }
481}
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void free_table(MSITABLE *table)
Definition: table.c:364
Definition: list.h:15
#define LIST_ENTRY(type)
Definition: queue.h:175

Referenced by MSI_CloseDatabase().

◆ free_colinfo()

static void free_colinfo ( struct column_info colinfo,
UINT  count 
)
static

Definition at line 358 of file table.c.

359{
360 UINT i;
361 for (i = 0; i < count; i++) free( colinfo[i].hash_table );
362}

Referenced by free_table(), get_tablecolumns(), and update_table_columns().

◆ free_table()

static void free_table ( MSITABLE table)
static

Definition at line 364 of file table.c.

365{
366 UINT i;
367 for( i=0; i<table->row_count; i++ )
368 free( table->data[i] );
369 free( table->data );
370 free( table->data_persistent );
371 free_colinfo( table->colinfo, table->col_count );
372 free( table->colinfo );
373 free( table );
374}
static void free_colinfo(struct column_info *colinfo, UINT count)
Definition: table.c:358
BYTE * data

Referenced by create_signature_table(), free_cached_tables(), get_table(), msi_create_table(), release_table(), TABLE_drop(), and TABLE_release().

◆ get_defaulttablecolumns()

static UINT get_defaulttablecolumns ( MSIDATABASE db,
const WCHAR name,
struct column_info colinfo,
UINT sz 
)
static

Definition at line 511 of file table.c.

512{
513 const struct column_info *p;
514 DWORD i, n;
515
516 TRACE("%s\n", debugstr_w(name));
517
518 if (!wcscmp( name, L"_Tables" ))
519 {
520 p = _Tables_cols;
521 n = 1;
522 }
523 else if (!wcscmp( name, L"_Columns" ))
524 {
526 n = 4;
527 }
528 else return ERROR_FUNCTION_FAILED;
529
530 for (i = 0; i < n; i++)
531 {
532 if (colinfo && i < *sz) colinfo[i] = p[i];
533 if (colinfo && i >= *sz) break;
534 }
535 table_calc_column_offsets( db, colinfo, n );
536 *sz = n;
537 return ERROR_SUCCESS;
538}
static const struct column_info _Tables_cols[1]
Definition: table.c:82
static const struct column_info _Columns_cols[4]
Definition: table.c:74
static void table_calc_column_offsets(MSIDATABASE *db, struct column_info *colinfo, DWORD count)
Definition: table.c:494
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985

Referenced by get_tablecolumns().

◆ get_stream_name()

static UINT get_stream_name ( const struct table_view tv,
UINT  row,
WCHAR **  pstname 
)
static

Definition at line 1044 of file table.c.

1045{
1046 LPWSTR p, stname = NULL;
1047 UINT i, r, type, ival;
1048 DWORD len;
1049 LPCWSTR sval;
1050 MSIVIEW *view = (MSIVIEW *) tv;
1051
1052 TRACE("%p %d\n", tv, row);
1053
1054 len = lstrlenW( tv->name ) + 1;
1055 stname = malloc( len * sizeof(WCHAR) );
1056 if ( !stname )
1057 {
1059 goto err;
1060 }
1061
1062 lstrcpyW( stname, tv->name );
1063
1064 for ( i = 0; i < tv->num_cols; i++ )
1065 {
1066 type = tv->columns[i].type;
1067 if ( type & MSITYPE_KEY )
1068 {
1069 WCHAR number[0x20];
1070
1071 r = TABLE_fetch_int( view, row, i+1, &ival );
1072 if ( r != ERROR_SUCCESS )
1073 goto err;
1074
1075 if ( tv->columns[i].type & MSITYPE_STRING )
1076 {
1077 sval = msi_string_lookup( tv->db->strings, ival, NULL );
1078 if ( !sval )
1079 {
1081 goto err;
1082 }
1083 }
1084 else
1085 {
1086 UINT n = bytes_per_column( tv->db, &tv->columns[i], LONG_STR_BYTES );
1087
1088 switch( n )
1089 {
1090 case 2:
1091 swprintf( number, ARRAY_SIZE(number), L"%d", ival-0x8000 );
1092 break;
1093 case 4:
1094 swprintf( number, ARRAY_SIZE(number), L"%d", ival^0x80000000 );
1095 break;
1096 default:
1097 ERR( "oops - unknown column width %d\n", n );
1099 goto err;
1100 }
1101 sval = number;
1102 }
1103
1104 len += lstrlenW( L"." ) + lstrlenW( sval );
1105 p = realloc( stname, len * sizeof(WCHAR) );
1106 if ( !p )
1107 {
1109 goto err;
1110 }
1111 stname = p;
1112
1113 lstrcatW( stname, L"." );
1114 lstrcatW( stname, sval );
1115 }
1116 else
1117 continue;
1118 }
1119
1120 *pstname = stname;
1121 return ERROR_SUCCESS;
1122
1123err:
1124 free( stname );
1125 *pstname = NULL;
1126 return r;
1127}
#define ARRAY_SIZE(A)
Definition: main.h:20
#define realloc
Definition: debug_ros.c:6
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define lstrcpyW
Definition: compat.h:749
static UINT bytes_per_column(MSIDATABASE *db, const struct column_info *col, UINT bytes_per_strref)
Definition: table.c:89
#define swprintf
Definition: precomp.h:40
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
static unsigned int number
Definition: dsound.c:1479
#define LONG_STR_BYTES
Definition: msipriv.h:57
#define err(...)
MSIDATABASE * db
Definition: table.c:999
WCHAR name[1]
Definition: table.c:1004
string_table * strings
Definition: msipriv.h:110
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185

Referenced by TABLE_fetch_stream(), TABLE_set_row(), and TABLE_set_stream().

◆ get_table()

static UINT get_table ( MSIDATABASE db,
LPCWSTR  name,
MSITABLE **  table_ret 
)
static

Definition at line 575 of file table.c.

576{
578 UINT r;
579
580 /* first, see if the table is cached */
582 if (table)
583 {
584 *table_ret = table;
585 return ERROR_SUCCESS;
586 }
587
588 /* nonexistent tables should be interpreted as empty tables */
589 table = malloc( sizeof(MSITABLE) + wcslen( name ) * sizeof(WCHAR) );
590 if (!table)
592
593 table->row_count = 0;
594 table->data = NULL;
595 table->data_persistent = NULL;
596 table->colinfo = NULL;
597 table->col_count = 0;
598 table->persistent = MSICONDITION_TRUE;
599 lstrcpyW( table->name, name );
600
601 if (!wcscmp( name, L"_Tables" ) || !wcscmp( name, L"_Columns" ))
602 table->persistent = MSICONDITION_NONE;
603
604 r = table_get_column_info( db, name, &table->colinfo, &table->col_count );
605 if (r != ERROR_SUCCESS)
606 {
607 free_table( table );
608 return r;
609 }
611 if (r != ERROR_SUCCESS)
612 {
613 free_table( table );
614 return r;
615 }
616 list_add_head( &db->tables, &table->entry );
617 *table_ret = table;
618 return ERROR_SUCCESS;
619}
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static MSITABLE * find_cached_table(MSIDATABASE *db, LPCWSTR name)
Definition: table.c:483
static UINT table_get_column_info(MSIDATABASE *db, const WCHAR *name, struct column_info **pcols, UINT *pcount)
Definition: table.c:542
static UINT read_table_from_storage(MSIDATABASE *db, MSITABLE *t, IStorage *stg)
Definition: table.c:394
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
@ MSICONDITION_NONE
Definition: msiquery.h:28
@ MSICONDITION_TRUE
Definition: msiquery.h:27
const WCHAR * name
struct list entry
IStorage * storage
Definition: msipriv.h:109

Referenced by FT_DEFINE_SERVICE(), get_tablecolumns(), MSI_DatabaseIsTablePersistent(), TABLE_CreateView(), and TABLE_Exists().

◆ get_table_value_from_record()

static UINT get_table_value_from_record ( struct table_view tv,
MSIRECORD rec,
UINT  iField,
UINT pvalue 
)
static

Definition at line 1358 of file table.c.

1359{
1360 struct column_info columninfo;
1361 UINT r;
1362
1363 if (!iField || iField > tv->num_cols || MSI_RecordIsNull( rec, iField ))
1364 return ERROR_FUNCTION_FAILED;
1365
1366 columninfo = tv->columns[ iField - 1 ];
1367
1368 if ( MSITYPE_IS_BINARY(columninfo.type) )
1369 {
1370 *pvalue = 1; /* refers to the first key column */
1371 }
1372 else if ( columninfo.type & MSITYPE_STRING )
1373 {
1374 int len;
1375 const WCHAR *sval = msi_record_get_string( rec, iField, &len );
1376 if (sval)
1377 {
1378 r = msi_string2id( tv->db->strings, sval, len, pvalue );
1379 if (r != ERROR_SUCCESS)
1380 return ERROR_NOT_FOUND;
1381 }
1382 else *pvalue = 0;
1383 }
1384 else
1385 return int_to_table_storage( tv, iField, MSI_RecordGetInteger( rec, iField ), pvalue );
1386
1387 return ERROR_SUCCESS;
1388}
static UINT int_to_table_storage(const struct table_view *tv, UINT col, int val, UINT *ret)
Definition: table.c:1196
int MSI_RecordGetInteger(MSIRECORD *, UINT)
Definition: record.c:213
const WCHAR * msi_record_get_string(const MSIRECORD *, UINT, int *)
Definition: record.c:420
UINT msi_string2id(const string_table *st, const WCHAR *data, int len, UINT *id)
Definition: string.c:400
BOOL MSI_RecordIsNull(MSIRECORD *, UINT)
Definition: record.c:321
#define ERROR_NOT_FOUND
Definition: winerror.h:690

Referenced by compare_record(), and TABLE_set_row().

◆ get_tablecolumns()

static UINT get_tablecolumns ( MSIDATABASE db,
const WCHAR szTableName,
struct column_info colinfo,
UINT sz 
)
static

Definition at line 631 of file table.c.

632{
633 UINT r, i, n = 0, table_id, count, maxcount = *sz;
635
636 TRACE("%s\n", debugstr_w(szTableName));
637
638 /* first check if there is a default table with that name */
639 r = get_defaulttablecolumns( db, szTableName, colinfo, sz );
640 if (r == ERROR_SUCCESS && *sz)
641 return r;
642
643 r = get_table( db, L"_Columns", &table );
644 if (r != ERROR_SUCCESS)
645 {
646 ERR("couldn't load _Columns table\n");
648 }
649
650 /* convert table and column names to IDs from the string table */
651 r = msi_string2id( db->strings, szTableName, -1, &table_id );
652 if (r != ERROR_SUCCESS)
653 {
654 WARN("Couldn't find id for %s\n", debugstr_w(szTableName));
655 return r;
656 }
657 TRACE("Table id is %d, row count is %d\n", table_id, table->row_count);
658
659 /* Note: _Columns table doesn't have non-persistent data */
660
661 /* if maxcount is non-zero, assume it's exactly right for this table */
662 if (colinfo) memset( colinfo, 0, maxcount * sizeof(*colinfo) );
663 count = table->row_count;
664 for (i = 0; i < count; i++)
665 {
666 if (read_table_int( table->data, i, 0, LONG_STR_BYTES) != table_id) continue;
667 if (colinfo)
668 {
669 UINT id = read_table_int( table->data, i, table->colinfo[2].offset, LONG_STR_BYTES );
670 UINT col = read_table_int( table->data, i, table->colinfo[1].offset, sizeof(USHORT) ) - (1 << 15);
671
672 /* check the column number is in range */
673 if (col < 1 || col > maxcount)
674 {
675 ERR("column %d out of range (maxcount: %d)\n", col, maxcount);
676 continue;
677 }
678 /* check if this column was already set */
679 if (colinfo[col - 1].number)
680 {
681 ERR("duplicate column %d\n", col);
682 continue;
683 }
684 colinfo[col - 1].tablename = msi_string_lookup( db->strings, table_id, NULL );
685 colinfo[col - 1].number = col;
686 colinfo[col - 1].colname = msi_string_lookup( db->strings, id, NULL );
687 colinfo[col - 1].type = read_table_int( table->data, i, table->colinfo[3].offset,
688 sizeof(USHORT) ) - (1 << 15);
689 colinfo[col - 1].offset = 0;
690 colinfo[col - 1].hash_table = NULL;
691 }
692 n++;
693 }
694 TRACE("%s has %d columns\n", debugstr_w(szTableName), n);
695
696 if (colinfo && n != maxcount)
697 {
698 ERR("missing column in table %s\n", debugstr_w(szTableName));
699 free_colinfo( colinfo, maxcount );
701 }
702 table_calc_column_offsets( db, colinfo, n );
703 *sz = n;
704 return ERROR_SUCCESS;
705}
static UINT get_table(MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret)
Definition: table.c:575
static UINT read_table_int(BYTE *const *data, UINT row, UINT col, UINT bytes)
Definition: table.c:621
static UINT get_defaulttablecolumns(MSIDATABASE *db, const WCHAR *name, struct column_info *colinfo, UINT *sz)
Definition: table.c:511
unsigned short USHORT
Definition: pedump.c:61
#define memset(x, y, z)
Definition: compat.h:39
LPCWSTR tablename
Definition: table.c:52
UINT number
Definition: table.c:53
UINT offset
Definition: table.c:56
struct column_hash_entry ** hash_table
Definition: table.c:57
LPCWSTR colname
Definition: table.c:54

Referenced by table_get_column_info().

◆ get_transform_record()

static MSIRECORD * get_transform_record ( const struct table_view tv,
const string_table st,
IStorage stg,
const BYTE rawdata,
UINT  bytes_per_strref 
)
static

Definition at line 2977 of file table.c.

2979{
2980 UINT i, val, ofs = 0;
2981 USHORT mask;
2982 struct column_info *columns = tv->columns;
2983 MSIRECORD *rec;
2984
2985 mask = rawdata[0] | (rawdata[1] << 8);
2986 rawdata += 2;
2987
2988 rec = MSI_CreateRecord( tv->num_cols );
2989 if( !rec )
2990 return rec;
2991
2992 TRACE("row ->\n");
2993 for( i=0; i<tv->num_cols; i++ )
2994 {
2995 if ( (mask&1) && (i>=(mask>>8)) )
2996 break;
2997 /* all keys must be present */
2998 if ( (~mask&1) && (~columns[i].type & MSITYPE_KEY) && ((1<<i) & ~mask) )
2999 continue;
3000
3001 if( MSITYPE_IS_BINARY(tv->columns[i].type) )
3002 {
3003 LPWSTR encname;
3004 IStream *stm = NULL;
3005 UINT r;
3006
3007 ofs += bytes_per_column( tv->db, &columns[i], bytes_per_strref );
3008
3009 r = record_encoded_stream_name( tv, rec, &encname );
3010 if ( r != ERROR_SUCCESS )
3011 {
3012 msiobj_release( &rec->hdr );
3013 return NULL;
3014 }
3015 r = IStorage_OpenStream( stg, encname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
3016 if ( r != ERROR_SUCCESS )
3017 {
3018 msiobj_release( &rec->hdr );
3019 free( encname );
3020 return NULL;
3021 }
3022
3023 MSI_RecordSetStream( rec, i+1, stm );
3024 TRACE(" field %d [%s]\n", i+1, debugstr_w(encname));
3025 free( encname );
3026 }
3027 else if( columns[i].type & MSITYPE_STRING )
3028 {
3029 int len;
3030 const WCHAR *sval;
3031
3032 val = read_raw_int(rawdata, ofs, bytes_per_strref);
3033 sval = msi_string_lookup( st, val, &len );
3034 msi_record_set_string( rec, i+1, sval, len );
3035 TRACE(" field %d [%s]\n", i+1, debugstr_wn(sval, len));
3036 ofs += bytes_per_strref;
3037 }
3038 else
3039 {
3040 UINT n = bytes_per_column( tv->db, &columns[i], bytes_per_strref );
3041 switch( n )
3042 {
3043 case 2:
3044 val = read_raw_int(rawdata, ofs, n);
3045 if (val)
3046 MSI_RecordSetInteger( rec, i+1, val-0x8000 );
3047 TRACE(" field %d [0x%04x]\n", i+1, val );
3048 break;
3049 case 4:
3050 val = read_raw_int(rawdata, ofs, n);
3051 if (val)
3052 MSI_RecordSetInteger( rec, i+1, val^0x80000000 );
3053 TRACE(" field %d [0x%08x]\n", i+1, val );
3054 break;
3055 default:
3056 ERR("oops - unknown column width %d\n", n);
3057 break;
3058 }
3059 ofs += n;
3060 }
3061 }
3062 return rec;
3063}
static UINT record_encoded_stream_name(const struct table_view *tv, MSIRECORD *rec, WCHAR **pstname)
Definition: table.c:2948
static UINT read_raw_int(const BYTE *data, UINT col, UINT bytes)
Definition: table.c:2938
GLenum GLint GLuint mask
Definition: glext.h:6028
GLuint GLfloat * val
Definition: glext.h:7180
UINT msi_record_set_string(MSIRECORD *, UINT, const WCHAR *, int)
Definition: record.c:573
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int)
Definition: record.c:280
UINT MSI_RecordSetStream(MSIRECORD *, UINT, IStream *)
Definition: record.c:671
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_READ
Definition: objbase.h:917

Referenced by table_load_transform().

◆ int_to_table_storage()

static UINT int_to_table_storage ( const struct table_view tv,
UINT  col,
int  val,
UINT ret 
)
static

Definition at line 1196 of file table.c.

1197{
1198 if ((tv->columns[col-1].type & MSI_DATASIZEMASK) == 2)
1199 {
1200 if (val == MSI_NULL_INTEGER)
1201 *ret = 0;
1202 else if ((val + 0x8000) & 0xffff0000)
1203 {
1204 ERR("value %d out of range\n", val);
1205 return ERROR_FUNCTION_FAILED;
1206 }
1207 else
1208 *ret = val + 0x8000;
1209 }
1210 else
1211 *ret = val ^ 0x80000000;
1212
1213 return ERROR_SUCCESS;
1214}
#define MSI_DATASIZEMASK
Definition: msipriv.h:47
#define MSI_NULL_INTEGER
Definition: msiquery.h:32
int ret

Referenced by get_table_value_from_record(), record_to_row(), and TABLE_set_int().

◆ mime2utf()

static int mime2utf ( int  x)
static

Definition at line 167 of file table.c.

168{
169 if( x<10 )
170 return x + '0';
171 if( x<(10+26))
172 return x - 10 + 'A';
173 if( x<(10+26+26))
174 return x - 10 - 26 + 'a';
175 if( x == (10+26+26) )
176 return '.';
177 return '_';
178}

Referenced by decode_streamname().

◆ MSI_CommitTables()

UINT MSI_CommitTables ( MSIDATABASE db)

Definition at line 2886 of file table.c.

2887{
2888 UINT r, bytes_per_strref;
2889 HRESULT hr;
2890 MSITABLE *table = NULL;
2891
2892 TRACE("%p\n",db);
2893
2894 r = msi_save_string_table( db->strings, db->storage, &bytes_per_strref );
2895 if( r != ERROR_SUCCESS )
2896 {
2897 WARN("failed to save string table r=%08x\n",r);
2898 return r;
2899 }
2900
2902 {
2903 r = save_table( db, table, bytes_per_strref );
2904 if( r != ERROR_SUCCESS )
2905 {
2906 WARN("failed to save table %s (r=%08x)\n",
2907 debugstr_w(table->name), r);
2908 return r;
2909 }
2910 }
2911
2912 hr = IStorage_Commit( db->storage, 0 );
2913 if (FAILED( hr ))
2914 {
2915 WARN( "failed to commit changes %#lx\n", hr );
2917 }
2918 return r;
2919}
static UINT save_table(MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref)
Definition: table.c:860
UINT msi_save_string_table(const string_table *st, IStorage *storage, UINT *bytes_per_strref)
Definition: string.c:564
HRESULT hr
Definition: shlfolder.c:183

Referenced by MsiDatabaseCommit().

◆ msi_create_table()

UINT msi_create_table ( MSIDATABASE db,
LPCWSTR  name,
column_info col_info,
MSICONDITION  persistent,
BOOL  hold 
)

Definition at line 707 of file table.c.

709{
710 UINT r, nField;
711 MSIVIEW *tv = NULL;
712 MSIRECORD *rec = NULL;
713 column_info *col;
715 UINT i;
716
717 /* only add tables that don't exist already */
718 if( TABLE_Exists(db, name ) )
719 {
720 WARN("table %s exists\n", debugstr_w(name));
722 }
723
724 table = malloc( sizeof(MSITABLE) + wcslen(name) * sizeof(WCHAR) );
725 if( !table )
727
728 table->ref_count = 0;
729 table->row_count = 0;
730 table->data = NULL;
731 table->data_persistent = NULL;
732 table->colinfo = NULL;
733 table->col_count = 0;
734 table->persistent = persistent;
735 lstrcpyW( table->name, name );
736
737 if( hold )
738 table->ref_count++;
739
740 for( col = col_info; col; col = col->next )
741 table->col_count++;
742
743 table->colinfo = malloc( table->col_count * sizeof(*table->colinfo) );
744 if (!table->colinfo)
745 {
746 free_table( table );
748 }
749
750 for( i = 0, col = col_info; col; i++, col = col->next )
751 {
752 UINT table_id = msi_add_string( db->strings, col->table, -1, persistent );
753 UINT col_id = msi_add_string( db->strings, col->column, -1, persistent );
754
755 table->colinfo[ i ].tablename = msi_string_lookup( db->strings, table_id, NULL );
756 table->colinfo[ i ].number = i + 1;
757 table->colinfo[ i ].colname = msi_string_lookup( db->strings, col_id, NULL );
758 table->colinfo[ i ].type = col->type;
759 table->colinfo[ i ].offset = 0;
760 table->colinfo[ i ].hash_table = NULL;
761 }
762 table_calc_column_offsets( db, table->colinfo, table->col_count);
763
764 r = TABLE_CreateView( db, L"_Tables", &tv );
765 TRACE("CreateView returned %x\n", r);
766 if( r )
767 {
768 free_table( table );
769 return r;
770 }
771
772 r = tv->ops->execute( tv, 0 );
773 TRACE("tv execute returned %x\n", r);
774 if( r )
775 goto err;
776
777 rec = MSI_CreateRecord( 1 );
778 if( !rec )
779 goto err;
780
781 r = MSI_RecordSetStringW( rec, 1, name );
782 if( r )
783 goto err;
784
785 r = tv->ops->insert_row( tv, rec, -1, persistent == MSICONDITION_FALSE );
786 TRACE("insert_row returned %x\n", r);
787 if( r )
788 goto err;
789
790 tv->ops->delete( tv );
791 tv = NULL;
792
793 msiobj_release( &rec->hdr );
794 rec = NULL;
795
796 if( persistent != MSICONDITION_FALSE )
797 {
798 /* add each column to the _Columns table */
799 r = TABLE_CreateView( db, L"_Columns", &tv );
800 if( r )
801 goto err;
802
803 r = tv->ops->execute( tv, 0 );
804 TRACE("tv execute returned %x\n", r);
805 if( r )
806 goto err;
807
808 rec = MSI_CreateRecord( 4 );
809 if( !rec )
810 goto err;
811
812 r = MSI_RecordSetStringW( rec, 1, name );
813 if( r )
814 goto err;
815
816 /*
817 * need to set the table, column number, col name and type
818 * for each column we enter in the table
819 */
820 nField = 1;
821 for( col = col_info; col; col = col->next )
822 {
823 r = MSI_RecordSetInteger( rec, 2, nField );
824 if( r )
825 goto err;
826
827 r = MSI_RecordSetStringW( rec, 3, col->column );
828 if( r )
829 goto err;
830
831 r = MSI_RecordSetInteger( rec, 4, col->type );
832 if( r )
833 goto err;
834
835 r = tv->ops->insert_row( tv, rec, -1, FALSE );
836 if( r )
837 goto err;
838
839 nField++;
840 }
841 if( !col )
843 }
844
845err:
846 if (rec)
847 msiobj_release( &rec->hdr );
848 /* FIXME: remove values from the string table on error */
849 if( tv )
850 tv->ops->delete( tv );
851
852 if (r == ERROR_SUCCESS)
853 list_add_head( &db->tables, &table->entry );
854 else
855 free_table( table );
856
857 return r;
858}
#define FALSE
Definition: types.h:117
BOOL TABLE_Exists(MSIDATABASE *db, LPCWSTR name)
Definition: table.c:962
UINT TABLE_CreateView(MSIDATABASE *db, LPCWSTR name, MSIVIEW **view)
Definition: table.c:2191
BOOL msi_add_string(string_table *st, const WCHAR *data, int len, BOOL persistent)
Definition: string.c:303
@ MSICONDITION_FALSE
Definition: msiquery.h:26
UINT(* insert_row)(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: msipriv.h:283
UINT(* execute)(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: msipriv.h:293
UINT(* delete)(struct tagMSIVIEW *)
Definition: msipriv.h:324
const MSIVIEWOPS * ops
Definition: msipriv.h:355
#define ERROR_BAD_QUERY_SYNTAX
Definition: winerror.h:973

Referenced by CREATE_execute().

◆ MSI_DatabaseIsTablePersistent()

MSICONDITION MSI_DatabaseIsTablePersistent ( MSIDATABASE db,
LPCWSTR  table 
)

Definition at line 2921 of file table.c.

2922{
2923 MSITABLE *t;
2924 UINT r;
2925
2926 TRACE("%p %s\n", db, debugstr_w(table));
2927
2928 if (!table)
2929 return MSICONDITION_ERROR;
2930
2931 r = get_table( db, table, &t );
2932 if (r != ERROR_SUCCESS)
2933 return MSICONDITION_NONE;
2934
2935 return t->persistent;
2936}
@ MSICONDITION_ERROR
Definition: msiquery.h:29

Referenced by MsiDatabaseIsTablePersistentW().

◆ msi_table_apply_transform()

UINT msi_table_apply_transform ( MSIDATABASE db,
IStorage stg,
int  err_cond 
)

Definition at line 3368 of file table.c.

3369{
3370 struct list transforms;
3371 IEnumSTATSTG *stgenum = NULL;
3372 struct transform_data *transform;
3373 struct transform_data *tables = NULL, *columns = NULL;
3374 HRESULT hr;
3375 STATSTG stat;
3378 UINT bytes_per_strref;
3379 BOOL property_update = FALSE;
3381
3382 TRACE("%p %p\n", db, stg );
3383
3384 strings = msi_load_string_table( stg, &bytes_per_strref );
3385 if( !strings )
3386 goto end;
3387
3388 hr = IStorage_EnumElements( stg, 0, NULL, 0, &stgenum );
3389 if (FAILED( hr ))
3390 goto end;
3391
3392 list_init(&transforms);
3393
3394 while ( TRUE )
3395 {
3396 struct table_view *tv = NULL;
3397 WCHAR name[0x40];
3398 ULONG count = 0;
3399
3400 hr = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
3401 if (FAILED( hr ) || !count)
3402 break;
3403
3404 decode_streamname( stat.pwcsName, name );
3405 CoTaskMemFree( stat.pwcsName );
3406 if ( name[0] != 0x4840 )
3407 continue;
3408
3409 if ( !wcscmp( name+1, L"_StringPool" ) ||
3410 !wcscmp( name+1, L"_StringData" ) )
3411 continue;
3412
3413 transform = calloc( 1, sizeof(*transform) );
3414 if ( !transform )
3415 break;
3416
3417 list_add_tail( &transforms, &transform->entry );
3418
3419 transform->name = wcsdup( name + 1 );
3420
3421 if ( !wcscmp( transform->name, L"_Tables" ) )
3422 tables = transform;
3423 else if (!wcscmp( transform->name, L"_Columns" ) )
3425 else if (!wcscmp( transform->name, L"Property" ))
3426 property_update = TRUE;
3427
3428 TRACE("transform contains stream %s\n", debugstr_w(name));
3429
3430 /* load the table */
3431 if (TABLE_CreateView( db, transform->name, (MSIVIEW**) &tv ) != ERROR_SUCCESS)
3432 continue;
3433
3434 if (tv->view.ops->execute( &tv->view, NULL ) != ERROR_SUCCESS)
3435 {
3436 tv->view.ops->delete( &tv->view );
3437 continue;
3438 }
3439
3440 tv->view.ops->delete( &tv->view );
3441 }
3442
3443 if (err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM)
3444 {
3445 static const WCHAR create_query[] = L"CREATE TABLE `_TransformView` ( "
3446 L"`Table` CHAR(0) NOT NULL TEMPORARY, `Column` CHAR(0) NOT NULL TEMPORARY, "
3447 L"`Row` CHAR(0) TEMPORARY, `Data` CHAR(0) TEMPORARY, `Current` CHAR(0) TEMPORARY "
3448 L"PRIMARY KEY `Table`, `Column`, `Row` ) HOLD";
3449
3450 MSIQUERY *query;
3451 UINT r;
3452
3454 if (r != ERROR_SUCCESS)
3455 goto end;
3456
3458 if (r == ERROR_SUCCESS)
3460 msiobj_release( &query->hdr );
3462 goto end;
3463
3464 if (TABLE_CreateView(db, L"_TransformView", &transform_view) != ERROR_SUCCESS)
3465 goto end;
3466
3468 transform_view->ops->add_ref( transform_view );
3469
3470 r = transform_view->ops->add_column( transform_view, L"new",
3471 MSITYPE_TEMPORARY | MSITYPE_NULLABLE | 0x402 /* INT */, FALSE );
3472 if (r != ERROR_SUCCESS)
3473 goto end;
3474 }
3475
3476 /*
3477 * Apply _Tables and _Columns transforms first so that
3478 * the table metadata is correct, and empty tables exist.
3479 */
3480 ret = table_load_transform( db, stg, strings, tables, bytes_per_strref, err_cond );
3482 goto end;
3483
3484 ret = table_load_transform( db, stg, strings, columns, bytes_per_strref, err_cond );
3486 goto end;
3487
3489
3490 while ( !list_empty( &transforms ) )
3491 {
3492 transform = LIST_ENTRY( list_head( &transforms ), struct transform_data, entry );
3493
3494 if ( wcscmp( transform->name, L"_Columns" ) &&
3495 wcscmp( transform->name, L"_Tables" ) &&
3496 ret == ERROR_SUCCESS )
3497 {
3498 ret = table_load_transform( db, stg, strings, transform, bytes_per_strref, err_cond );
3499 }
3500
3501 list_remove( &transform->entry );
3502 free( transform->name );
3503 free( transform );
3504 }
3505
3506 if ( ret == ERROR_SUCCESS )
3507 {
3508 append_storage_to_db( db, stg );
3509 if (property_update) msi_clone_properties( db );
3510 }
3511
3512end:
3513 if ( stgenum )
3514 IEnumSTATSTG_Release( stgenum );
3515 if ( strings )
3517 if (transform_view)
3518 {
3519 struct tagMSITABLE *table = ((struct table_view *)transform_view)->table;
3520
3521 if (ret != ERROR_SUCCESS)
3522 transform_view->ops->release( transform_view );
3523
3524 if (!wcscmp(table->colinfo[table->col_count - 1].colname, L"new"))
3525 TABLE_remove_column( transform_view, table->colinfo[table->col_count - 1].number );
3526 transform_view->ops->delete( transform_view );
3527 }
3528
3529 return ret;
3530}
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_init(struct list_entry *head)
Definition: list.h:51
Definition: list.h:37
#define TRUE
Definition: types.h:120
static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:3964
void append_storage_to_db(MSIDATABASE *db, IStorage *stg)
Definition: database.c:76
static UINT table_load_transform(MSIDATABASE *db, IStorage *stg, string_table *st, struct transform_data *transform, UINT bytes_per_strref, int err_cond)
Definition: table.c:3175
static UINT TABLE_remove_column(struct tagMSIVIEW *view, UINT number)
Definition: table.c:1937
struct nls_table * tables
Definition: nls_base.c:22
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint GLuint end
Definition: gl.h:1545
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLsizei const GLchar *const * strings
Definition: glext.h:7622
UINT msi_clone_properties(MSIDATABASE *)
Definition: package.c:381
#define MSITYPE_TEMPORARY
Definition: msipriv.h:53
UINT MSI_ViewClose(MSIQUERY *)
Definition: msiquery.c:454
string_table * msi_load_string_table(IStorage *stg, UINT *bytes_per_strref)
Definition: string.c:478
#define MSITYPE_NULLABLE
Definition: msipriv.h:51
VOID msi_destroy_stringtable(string_table *st)
Definition: string.c:107
@ MSITRANSFORM_ERROR_VIEWTRANSFORM
Definition: msiquery.h:156
static struct query * create_query(void)
Definition: pdh_main.c:152
#define calloc
Definition: rosglue.h:14
_Check_return_ _CRTIMP wchar_t *__cdecl wcsdup(_In_z_ const wchar_t *_Str)
#define ERROR_INVALID_TABLE
Definition: winerror.h:986

Referenced by apply_substorage_transform(), and MSI_DatabaseApplyTransformW().

◆ read_raw_int()

static UINT read_raw_int ( const BYTE data,
UINT  col,
UINT  bytes 
)
static

Definition at line 2938 of file table.c.

2939{
2940 UINT ret = 0, i;
2941
2942 for (i = 0; i < bytes; i++)
2943 ret += (data[col + i] << i * 8);
2944
2945 return ret;
2946}
static unsigned char bytes[4]
Definition: adnsresfilter.c:74

Referenced by get_transform_record().

◆ read_stream_data()

UINT read_stream_data ( IStorage stg,
LPCWSTR  stname,
BOOL  table,
BYTE **  pdata,
UINT psz 
)

Definition at line 234 of file table.c.

236{
237 HRESULT r;
239 VOID *data;
240 ULONG sz, count;
241 IStream *stm = NULL;
242 STATSTG stat;
243 LPWSTR encname;
244
245 encname = encode_streamname(table, stname);
246
247 TRACE("%s -> %s\n",debugstr_w(stname),debugstr_w(encname));
248
249 r = IStorage_OpenStream(stg, encname, NULL,
251 free(encname);
252 if( FAILED( r ) )
253 {
254 WARN( "open stream failed r = %#lx - empty table?\n", r );
255 return ret;
256 }
257
258 r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
259 if( FAILED( r ) )
260 {
261 WARN( "open stream failed r = %#lx!\n", r );
262 goto end;
263 }
264
265 if( stat.cbSize.QuadPart >> 32 )
266 {
267 WARN("Too big!\n");
268 goto end;
269 }
270
271 sz = stat.cbSize.QuadPart;
272 data = malloc(sz);
273 if( !data )
274 {
275 WARN( "couldn't allocate memory r = %#lx!\n", r );
277 goto end;
278 }
279
280 r = IStream_Read(stm, data, sz, &count );
281 if( FAILED( r ) || ( count != sz ) )
282 {
283 free(data);
284 WARN("read stream failed r = %#lx!\n", r);
285 goto end;
286 }
287
288 *pdata = data;
289 *psz = sz;
291
292end:
293 IStream_Release( stm );
294
295 return ret;
296}
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
LPWSTR encode_streamname(BOOL bTable, LPCWSTR in)
Definition: table.c:121
static PROTOCOLDATA * pdata
Definition: protocol.c:158

Referenced by read_table_from_storage(), and table_load_transform().

◆ read_table_from_storage()

static UINT read_table_from_storage ( MSIDATABASE db,
MSITABLE t,
IStorage stg 
)
static

Definition at line 394 of file table.c.

395{
396 BYTE *rawdata = NULL;
397 UINT rawsize = 0, i, j, row_size, row_size_mem;
398
399 TRACE("%s\n",debugstr_w(t->name));
400
401 row_size = table_get_row_size( db, t->colinfo, t->col_count, db->bytes_per_strref );
402 row_size_mem = table_get_row_size( db, t->colinfo, t->col_count, LONG_STR_BYTES );
403
404 /* if we can't read the table, just assume that it's empty */
405 read_stream_data( stg, t->name, TRUE, &rawdata, &rawsize );
406 if( !rawdata )
407 return ERROR_SUCCESS;
408
409 TRACE("Read %d bytes\n", rawsize );
410
411 if( rawsize % row_size )
412 {
413 WARN("Table size is invalid %d/%d\n", rawsize, row_size );
414 goto err;
415 }
416
417 if ((t->row_count = rawsize / row_size))
418 {
419 if (!(t->data = calloc( t->row_count, sizeof(USHORT *) ))) goto err;
420 if (!(t->data_persistent = calloc( t->row_count, sizeof(BOOL) ))) goto err;
421 }
422
423 /* transpose all the data */
424 TRACE("Transposing data from %d rows\n", t->row_count );
425 for (i = 0; i < t->row_count; i++)
426 {
427 UINT ofs = 0, ofs_mem = 0;
428
429 t->data[i] = malloc( row_size_mem );
430 if( !t->data[i] )
431 goto err;
432 t->data_persistent[i] = TRUE;
433
434 for (j = 0; j < t->col_count; j++)
435 {
436 UINT m = bytes_per_column( db, &t->colinfo[j], LONG_STR_BYTES );
437 UINT n = bytes_per_column( db, &t->colinfo[j], db->bytes_per_strref );
438 UINT k;
439
440 if ( n != 2 && n != 3 && n != 4 )
441 {
442 ERR("oops - unknown column width %d\n", n);
443 goto err;
444 }
445 if (t->colinfo[j].type & MSITYPE_STRING && n < m)
446 {
447 for (k = 0; k < m; k++)
448 {
449 if (k < n)
450 t->data[i][ofs_mem + k] = rawdata[ofs * t->row_count + i * n + k];
451 else
452 t->data[i][ofs_mem + k] = 0;
453 }
454 }
455 else
456 {
457 for (k = 0; k < n; k++)
458 t->data[i][ofs_mem + k] = rawdata[ofs * t->row_count + i * n + k];
459 }
460 ofs_mem += m;
461 ofs += n;
462 }
463 }
464
465 free( rawdata );
466 return ERROR_SUCCESS;
467err:
468 free( rawdata );
470}
UINT read_stream_data(IStorage *stg, LPCWSTR stname, BOOL table, BYTE **pdata, UINT *psz)
Definition: table.c:234
static UINT table_get_row_size(MSIDATABASE *db, const struct column_info *cols, UINT count, UINT bytes_per_strref)
Definition: table.c:376
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
int k
Definition: mpi.c:3369
UINT bytes_per_strref
Definition: msipriv.h:111
unsigned char BYTE
Definition: xxhash.c:193

Referenced by get_table().

◆ read_table_int()

static UINT read_table_int ( BYTE *const data,
UINT  row,
UINT  col,
UINT  bytes 
)
static

Definition at line 621 of file table.c.

622{
623 UINT ret = 0, i;
624
625 for (i = 0; i < bytes; i++)
626 ret += data[row][col + i] << i * 8;
627
628 return ret;
629}

Referenced by get_tablecolumns(), save_table(), TABLE_Exists(), and TABLE_fetch_int().

◆ record_encoded_stream_name()

static UINT record_encoded_stream_name ( const struct table_view tv,
MSIRECORD rec,
WCHAR **  pstname 
)
static

Definition at line 2948 of file table.c.

2949{
2950 UINT r;
2951 DWORD len;
2952 WCHAR *name;
2953
2954 TRACE("%p %p\n", tv, rec);
2955
2956 r = record_stream_name( tv, rec, NULL, &len );
2957 if (r != ERROR_SUCCESS)
2958 return r;
2959 len++;
2960
2961 name = malloc( len * sizeof(WCHAR) );
2962 if (!name)
2963 return ERROR_OUTOFMEMORY;
2964
2965 r = record_stream_name( tv, rec, name, &len );
2966 if (r != ERROR_SUCCESS)
2967 {
2968 free( name );
2969 return r;
2970 }
2971
2972 *pstname = encode_streamname( FALSE, name );
2973 free( name );
2974 return ERROR_SUCCESS;
2975}
static UINT record_stream_name(const struct table_view *tv, MSIRECORD *rec, WCHAR *name, DWORD *len)
Definition: table.c:2265

Referenced by get_transform_record().

◆ record_stream_name()

static UINT record_stream_name ( const struct table_view tv,
MSIRECORD rec,
WCHAR name,
DWORD len 
)
static

Definition at line 2265 of file table.c.

2266{
2267 UINT p = 0, i, r;
2268 DWORD l;
2269
2270 l = wcslen( tv->name );
2271 if (name && *len > l)
2272 memcpy(name, tv->name, l * sizeof(WCHAR));
2273 p += l;
2274
2275 for ( i = 0; i < tv->num_cols; i++ )
2276 {
2277 if (!(tv->columns[i].type & MSITYPE_KEY))
2278 continue;
2279
2280 if (name && *len > p + 1)
2281 name[p] = '.';
2282 p++;
2283
2284 l = (*len > p ? *len - p : 0);
2285 r = MSI_RecordGetStringW( rec, i + 1, name ? name + p : NULL, &l );
2286 if (r != ERROR_SUCCESS)
2287 return r;
2288 p += l;
2289 }
2290
2291 if (name && *len > p)
2292 name[p] = 0;
2293
2294 *len = p;
2295 return ERROR_SUCCESS;
2296}
r l[0]
Definition: byte_order.h:168
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

Referenced by record_encoded_stream_name(), and TransformView_set_row().

◆ record_to_row()

static UINT * record_to_row ( const struct table_view tv,
MSIRECORD rec 
)
static

Definition at line 3076 of file table.c.

3077{
3078 UINT i, r, *data;
3079
3080 data = malloc( tv->num_cols * sizeof (UINT) );
3081 for( i=0; i<tv->num_cols; i++ )
3082 {
3083 data[i] = 0;
3084
3085 if ( ~tv->columns[i].type & MSITYPE_KEY )
3086 continue;
3087
3088 /* turn the transform column value into a row value */
3089 if ( ( tv->columns[i].type & MSITYPE_STRING ) &&
3090 ! MSITYPE_IS_BINARY(tv->columns[i].type) )
3091 {
3092 int len;
3093 const WCHAR *str = msi_record_get_string( rec, i+1, &len );
3094 if (str)
3095 {
3096 r = msi_string2id( tv->db->strings, str, len, &data[i] );
3097
3098 /* if there's no matching string in the string table,
3099 these keys can't match any record, so fail now. */
3100 if (r != ERROR_SUCCESS)
3101 {
3102 free( data );
3103 return NULL;
3104 }
3105 }
3106 else data[i] = 0;
3107 }
3108 else
3109 {
3110 if (int_to_table_storage( tv, i + 1, MSI_RecordGetInteger( rec, i + 1 ), &data[i] ))
3111 {
3112 free( data );
3113 return NULL;
3114 }
3115 }
3116 }
3117 return data;
3118}
const WCHAR * str
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList

Referenced by table_find_row().

◆ refresh_record()

static UINT refresh_record ( struct tagMSIVIEW view,
MSIRECORD rec,
UINT  row 
)
static

Definition at line 1820 of file table.c.

1821{
1822 MSIRECORD *curr;
1823 UINT r, i, count;
1824
1825 r = TABLE_get_row(view, row, &curr);
1826 if (r != ERROR_SUCCESS)
1827 return r;
1828
1829 /* Close the original record */
1830 MSI_CloseRecord(&rec->hdr);
1831
1833 for (i = 0; i < count; i++)
1834 MSI_RecordCopyField(curr, i + 1, rec, i + 1);
1835
1836 msiobj_release(&curr->hdr);
1837 return ERROR_SUCCESS;
1838}
static UINT TABLE_get_row(struct tagMSIVIEW *view, UINT row, MSIRECORD **rec)
Definition: table.c:1280
void MSI_CloseRecord(MSIOBJECTHDR *)
Definition: record.c:67
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT)
Definition: record.c:166
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec)
Definition: record.c:108

Referenced by TABLE_modify().

◆ row_matches()

static UINT row_matches ( struct table_view tv,
UINT  row,
const UINT data,
UINT column 
)
static

Definition at line 3120 of file table.c.

3121{
3123
3124 for( i=0; i<tv->num_cols; i++ )
3125 {
3126 if ( ~tv->columns[i].type & MSITYPE_KEY )
3127 continue;
3128
3129 /* turn the transform column value into a row value */
3130 r = TABLE_fetch_int( &tv->view, row, i+1, &x );
3131 if ( r != ERROR_SUCCESS )
3132 {
3133 ERR("TABLE_fetch_int shouldn't fail here\n");
3134 break;
3135 }
3136
3137 /* if this key matches, move to the next column */
3138 if ( x != data[i] )
3139 {
3141 break;
3142 }
3143 if (column) *column = i;
3145 }
3146 return ret;
3147}

Referenced by table_find_row().

◆ save_table()

static UINT save_table ( MSIDATABASE db,
const MSITABLE t,
UINT  bytes_per_strref 
)
static

Definition at line 860 of file table.c.

861{
862 BYTE *rawdata = NULL;
863 UINT rawsize, i, j, row_size, row_count;
865
866 /* Nothing to do for non-persistent tables */
867 if( t->persistent == MSICONDITION_FALSE )
868 return ERROR_SUCCESS;
869
870 TRACE("Saving %s\n", debugstr_w( t->name ) );
871
872 row_size = table_get_row_size( db, t->colinfo, t->col_count, bytes_per_strref );
873 row_count = t->row_count;
874 for (i = 0; i < t->row_count; i++)
875 {
876 if (!t->data_persistent[i])
877 {
878 row_count = 1; /* yes, this is bizarre */
879 break;
880 }
881 }
882 rawsize = row_count * row_size;
883 rawdata = calloc( 1, rawsize );
884 if( !rawdata )
885 {
887 goto err;
888 }
889
890 rawsize = 0;
891 for (i = 0; i < row_count; i++)
892 {
893 UINT ofs = 0, ofs_mem = 0;
894
895 if (!t->data_persistent[i]) break;
896
897 for (j = 0; j < t->col_count; j++)
898 {
899 UINT m = bytes_per_column( db, &t->colinfo[j], LONG_STR_BYTES );
900 UINT n = bytes_per_column( db, &t->colinfo[j], bytes_per_strref );
901 UINT k;
902
903 if (n != 2 && n != 3 && n != 4)
904 {
905 ERR("oops - unknown column width %d\n", n);
906 goto err;
907 }
908 if (t->colinfo[j].type & MSITYPE_STRING && n < m)
909 {
910 UINT id = read_table_int( t->data, i, ofs_mem, LONG_STR_BYTES );
911 if (id > 1 << bytes_per_strref * 8)
912 {
913 ERR("string id %u out of range\n", id);
914 goto err;
915 }
916 }
917 for (k = 0; k < n; k++)
918 {
919 rawdata[ofs * row_count + i * n + k] = t->data[i][ofs_mem + k];
920 }
921 ofs_mem += m;
922 ofs += n;
923 }
924 rawsize += row_size;
925 }
926
927 TRACE("writing %d bytes\n", rawsize);
928 r = write_stream_data( db->storage, t->name, rawdata, rawsize, TRUE );
929
930err:
931 free( rawdata );
932 return r;
933}
UINT write_stream_data(IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable)
Definition: table.c:298

Referenced by MSI_CommitTables().

◆ TABLE_add_column()

static UINT TABLE_add_column ( struct tagMSIVIEW view,
LPCWSTR  column,
INT  type,
BOOL  hold 
)
static

Definition at line 2025 of file table.c.

2027{
2028 UINT i, r, table_id, col_id, size, offset;
2029 BOOL temporary = type & MSITYPE_TEMPORARY;
2030 struct table_view *tv = (struct table_view *)view;
2031 struct column_info *colinfo;
2032
2033 if (temporary && !hold && !tv->table->ref_count)
2034 return ERROR_SUCCESS;
2035
2036 if (!temporary && tv->table->col_count &&
2037 tv->table->colinfo[tv->table->col_count-1].type & MSITYPE_TEMPORARY)
2039
2040 for (i = 0; i < tv->table->col_count; i++)
2041 {
2042 if (!wcscmp(tv->table->colinfo[i].colname, column))
2044 }
2045
2046 colinfo = realloc(tv->table->colinfo, sizeof(*tv->table->colinfo) * (tv->table->col_count + 1));
2047 if (!colinfo)
2048 return ERROR_OUTOFMEMORY;
2049 tv->table->colinfo = colinfo;
2050
2051 r = msi_string2id( tv->db->strings, tv->name, -1, &table_id );
2052 if (r != ERROR_SUCCESS)
2053 return r;
2054 col_id = msi_add_string( tv->db->strings, column, -1, !temporary );
2055
2056 colinfo[tv->table->col_count].tablename = msi_string_lookup( tv->db->strings, table_id, NULL );
2057 colinfo[tv->table->col_count].number = tv->table->col_count + 1;
2058 colinfo[tv->table->col_count].colname = msi_string_lookup( tv->db->strings, col_id, NULL );
2059 colinfo[tv->table->col_count].type = type;
2060 colinfo[tv->table->col_count].offset = 0;
2061 colinfo[tv->table->col_count].hash_table = NULL;
2062 tv->table->col_count++;
2063
2065
2067 offset = tv->table->colinfo[tv->table->col_count - 1].offset;
2068 for (i = 0; i < tv->table->row_count; i++)
2069 {
2070 BYTE *data = realloc(tv->table->data[i], size);
2071 if (!data)
2072 {
2073 tv->table->col_count--;
2074 return ERROR_OUTOFMEMORY;
2075 }
2076
2077 tv->table->data[i] = data;
2078 memset(data + offset, 0, size - offset);
2079 }
2080
2081 if (!temporary)
2082 {
2083 MSIVIEW *columns;
2084 MSIRECORD *rec;
2085
2086 rec = MSI_CreateRecord(4);
2087 if (!rec)
2088 {
2089 tv->table->col_count--;
2090 return ERROR_OUTOFMEMORY;
2091 }
2092
2093 MSI_RecordSetStringW(rec, 1, tv->name);
2094 MSI_RecordSetInteger(rec, 2, tv->table->col_count);
2096 MSI_RecordSetInteger(rec, 4, type);
2097
2098 r = TABLE_CreateView(tv->db, L"_Columns", &columns);
2099 if (r != ERROR_SUCCESS)
2100 {
2101 tv->table->col_count--;
2102 msiobj_release(&rec->hdr);
2103 return r;
2104 }
2105
2106 r = TABLE_insert_row(columns, rec, -1, FALSE);
2107 columns->ops->delete(columns);
2108 msiobj_release(&rec->hdr);
2109 if (r != ERROR_SUCCESS)
2110 {
2111 tv->table->col_count--;
2112 return r;
2113 }
2114 }
2115 if (hold)
2117 return ERROR_SUCCESS;
2118}
static UINT TABLE_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
Definition: table.c:1708
static UINT TABLE_add_ref(struct tagMSIVIEW *view)
Definition: table.c:1929
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
struct column_info * colinfo
Definition: table.c:66
BYTE ** data
Definition: table.c:62
LONG ref_count
Definition: table.c:69
UINT col_count
Definition: table.c:67

◆ TABLE_add_ref()

static UINT TABLE_add_ref ( struct tagMSIVIEW view)
static

Definition at line 1929 of file table.c.

1930{
1931 struct table_view *tv = (struct table_view *)view;
1932
1933 TRACE( "%p, %ld\n", view, tv->table->ref_count );
1934 return InterlockedIncrement(&tv->table->ref_count);
1935}
#define InterlockedIncrement
Definition: armddk.h:53

Referenced by TABLE_add_column().

◆ table_assign()

static UINT table_assign ( struct tagMSIVIEW view,
MSIRECORD rec 
)
static

Definition at line 1805 of file table.c.

1806{
1807 struct table_view *tv = (struct table_view *)view;
1808 UINT r, row;
1809
1810 if (!tv->table)
1812
1813 r = table_find_row(tv, rec, &row, NULL);
1814 if (r == ERROR_SUCCESS)
1815 return TABLE_set_row(view, row, rec, (1 << tv->num_cols) - 1);
1816 else
1817 return TABLE_insert_row( view, rec, -1, FALSE );
1818}
static UINT TABLE_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: table.c:1390
static UINT table_find_row(struct table_view *, MSIRECORD *, UINT *, UINT *)
Definition: table.c:3149

Referenced by TABLE_modify().

◆ table_calc_column_offsets()

static void table_calc_column_offsets ( MSIDATABASE db,
struct column_info colinfo,
DWORD  count 
)
static

Definition at line 494 of file table.c.

495{
496 DWORD i;
497
498 for (i = 0; colinfo && i < count; i++)
499 {
500 assert( i + 1 == colinfo[i].number );
501 if (i) colinfo[i].offset = colinfo[i - 1].offset +
502 bytes_per_column( db, &colinfo[i - 1], LONG_STR_BYTES );
503 else colinfo[i].offset = 0;
504
505 TRACE("column %d is [%s] with type %08x ofs %d\n",
506 colinfo[i].number, debugstr_w(colinfo[i].colname),
507 colinfo[i].type, colinfo[i].offset);
508 }
509}
#define assert(x)
Definition: debug.h:53

Referenced by get_defaulttablecolumns(), get_tablecolumns(), msi_create_table(), and TABLE_add_column().

◆ TABLE_close()

static UINT TABLE_close ( struct tagMSIVIEW view)
static

Definition at line 1545 of file table.c.

1546{
1547 TRACE("%p\n", view );
1548
1549 return ERROR_SUCCESS;
1550}

◆ table_create_new_row()

static UINT table_create_new_row ( struct tagMSIVIEW view,
UINT num,
BOOL  temporary 
)
static

Definition at line 1475 of file table.c.

1476{
1477 struct table_view *tv = (struct table_view *)view;
1478 BYTE **p, *row;
1479 BOOL *b;
1480 UINT sz;
1481 BYTE ***data_ptr;
1482 BOOL **data_persist_ptr;
1483 UINT *row_count;
1484
1485 TRACE("%p %s\n", view, temporary ? "TRUE" : "FALSE");
1486
1487 if( !tv->table )
1489
1490 row = calloc( 1, tv->row_size );
1491 if( !row )
1493
1494 row_count = &tv->table->row_count;
1495 data_ptr = &tv->table->data;
1496 data_persist_ptr = &tv->table->data_persistent;
1497 if (*num == -1)
1498 *num = tv->table->row_count;
1499
1500 sz = (*row_count + 1) * sizeof (BYTE*);
1501 if( *data_ptr )
1502 p = realloc( *data_ptr, sz );
1503 else
1504 p = malloc( sz );
1505 if( !p )
1506 {
1507 free( row );
1509 }
1510
1511 sz = (*row_count + 1) * sizeof (BOOL);
1512 if( *data_persist_ptr )
1513 b = realloc( *data_persist_ptr, sz );
1514 else
1515 b = malloc( sz );
1516 if( !b )
1517 {
1518 free( row );
1519 free( p );
1521 }
1522
1523 *data_ptr = p;
1524 (*data_ptr)[*row_count] = row;
1525
1526 *data_persist_ptr = b;
1527 (*data_persist_ptr)[*row_count] = !temporary;
1528
1529 (*row_count)++;
1530
1531 return ERROR_SUCCESS;
1532}
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLuint GLuint num
Definition: glext.h:9618
#define b
Definition: ke_i.h:79
UINT row_size
Definition: table.c:1003
BOOL * data_persistent
Definition: table.c:63

Referenced by TABLE_insert_row().

◆ TABLE_CreateView()

UINT TABLE_CreateView ( MSIDATABASE db,
LPCWSTR  name,
MSIVIEW **  view 
)

Definition at line 2191 of file table.c.

2192{
2193 struct table_view *tv ;
2194 UINT r, sz;
2195
2196 TRACE("%p %s %p\n", db, debugstr_w(name), view );
2197
2198 if ( !wcscmp( name, L"_Streams" ) )
2199 return STREAMS_CreateView( db, view );
2200 else if ( !wcscmp( name, L"_Storages" ) )
2201 return STORAGES_CreateView( db, view );
2202
2203 sz = FIELD_OFFSET( struct table_view, name[lstrlenW( name ) + 1] );
2204 tv = calloc( 1, sz );
2205 if( !tv )
2206 return ERROR_FUNCTION_FAILED;
2207
2208 r = get_table( db, name, &tv->table );
2209 if( r != ERROR_SUCCESS )
2210 {
2211 free( tv );
2212 WARN("table not found\n");
2213 return r;
2214 }
2215
2216 TRACE("table %p found with %d columns\n", tv->table, tv->table->col_count);
2217
2218 /* fill the structure */
2219 tv->view.ops = &table_ops;
2220 tv->db = db;
2221 tv->columns = tv->table->colinfo;
2222 tv->num_cols = tv->table->col_count;
2224
2225 TRACE("%s one row is %d bytes\n", debugstr_w(name), tv->row_size );
2226
2227 *view = (MSIVIEW*) tv;
2228 lstrcpyW( tv->name, name );
2229
2230 return ERROR_SUCCESS;
2231}
static const MSIVIEWOPS table_ops
Definition: table.c:2168
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
Definition: streams.c:539
UINT STORAGES_CreateView(MSIDATABASE *db, MSIVIEW **view)
Definition: storages.c:515
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Referenced by ALTER_CreateView(), DROP_CreateView(), INSERT_CreateView(), merge_table(), msi_create_table(), msi_table_apply_transform(), TABLE_add_column(), TABLE_drop(), table_load_transform(), TABLE_remove_column(), TransformView_Create(), UPDATE_CreateView(), and WHERE_CreateView().

◆ TABLE_delete()

static UINT TABLE_delete ( struct tagMSIVIEW view)
static

Definition at line 1915 of file table.c.

1916{
1917 struct table_view *tv = (struct table_view *)view;
1918
1919 TRACE("%p\n", view );
1920
1921 tv->table = NULL;
1922 tv->columns = NULL;
1923
1924 free( tv );
1925
1926 return ERROR_SUCCESS;
1927}

Referenced by TABLE_release(), and TransformView_delete().

◆ TABLE_delete_row()

static UINT TABLE_delete_row ( struct tagMSIVIEW view,
UINT  row 
)
static

Definition at line 1741 of file table.c.

1742{
1743 struct table_view *tv = (struct table_view *)view;
1745
1746 TRACE("%p %d\n", tv, row);
1747
1748 if ( !tv->table )
1750
1752 if ( r != ERROR_SUCCESS )
1753 return r;
1754
1755 if ( row >= num_rows )
1756 return ERROR_FUNCTION_FAILED;
1757
1758 num_rows = tv->table->row_count;
1759 tv->table->row_count--;
1760
1761 /* reset the hash tables */
1762 for (i = 0; i < tv->num_cols; i++)
1763 {
1764 free(tv->columns[i].hash_table);
1765 tv->columns[i].hash_table = NULL;
1766 }
1767
1768 for (i = row + 1; i < num_rows; i++)
1769 {
1770 memcpy(tv->table->data[i - 1], tv->table->data[i], tv->row_size);
1771 tv->table->data_persistent[i - 1] = tv->table->data_persistent[i];
1772 }
1773
1774 free(tv->table->data[num_rows - 1]);
1775
1776 return ERROR_SUCCESS;
1777}
static UINT TABLE_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: table.c:1552
int JSAMPARRAY int int num_rows
Definition: jpegint.h:421

Referenced by TABLE_drop(), TABLE_modify(), and TABLE_remove_column().

◆ TABLE_drop()

static UINT TABLE_drop ( struct tagMSIVIEW view)
static

Definition at line 2120 of file table.c.

2121{
2122 struct table_view *tv = (struct table_view *)view;
2123 MSIVIEW *tables = NULL;
2124 MSIRECORD *rec = NULL;
2125 UINT r, row;
2126 INT i;
2127
2128 TRACE("dropping table %s\n", debugstr_w(tv->name));
2129
2130 for (i = tv->table->col_count - 1; i >= 0; i--)
2131 {
2132 r = TABLE_remove_column(view, tv->table->colinfo[i].number);
2133 if (r != ERROR_SUCCESS)
2134 return r;
2135 }
2136
2137 rec = MSI_CreateRecord(1);
2138 if (!rec)
2139 return ERROR_OUTOFMEMORY;
2140
2141 MSI_RecordSetStringW(rec, 1, tv->name);
2142
2143 r = TABLE_CreateView(tv->db, L"_Tables", &tables);
2144 if (r != ERROR_SUCCESS)
2145 {
2146 msiobj_release(&rec->hdr);
2147 return r;
2148 }
2149
2150 r = table_find_row((struct table_view *)tables, rec, &row, NULL);
2151 if (r != ERROR_SUCCESS)
2152 goto done;
2153
2155 if (r != ERROR_SUCCESS)
2156 goto done;
2157
2158 list_remove(&tv->table->entry);
2159 free_table(tv->table);
2160
2161done:
2162 msiobj_release(&rec->hdr);
2163 tables->ops->delete(tables);
2164
2165 return r;
2166}
static UINT TABLE_delete_row(struct tagMSIVIEW *view, UINT row)
Definition: table.c:1741
struct list entry
Definition: table.c:65
int32_t INT
Definition: typedefs.h:58

◆ TABLE_execute()

static UINT TABLE_execute ( struct tagMSIVIEW view,
MSIRECORD record 
)
static

Definition at line 1534 of file table.c.

1535{
1536 struct table_view *tv = (struct table_view *)view;
1537
1538 TRACE("%p %p\n", tv, record);
1539
1540 TRACE("There are %d columns\n", tv->num_cols );
1541
1542 return ERROR_SUCCESS;
1543}

◆ TABLE_Exists()

BOOL TABLE_Exists ( MSIDATABASE db,
LPCWSTR  name 
)

Definition at line 962 of file table.c.

963{
964 UINT r, table_id, i;
966
967 if( !wcscmp( name, L"_Tables" ) || !wcscmp( name, L"_Columns" ) ||
968 !wcscmp( name, L"_Streams" ) || !wcscmp( name, L"_Storages" ) )
969 return TRUE;
970
971 r = msi_string2id( db->strings, name, -1, &table_id );
972 if( r != ERROR_SUCCESS )
973 {
974 TRACE("Couldn't find id for %s\n", debugstr_w(name));
975 return FALSE;
976 }
977
978 r = get_table( db, L"_Tables", &table );
979 if( r != ERROR_SUCCESS )
980 {
981 ERR("table _Tables not available\n");
982 return FALSE;
983 }
984
985 for( i = 0; i < table->row_count; i++ )
986 {
987 if( read_table_int( table->data, i, 0, LONG_STR_BYTES ) == table_id )
988 return TRUE;
989 }
990
991 return FALSE;
992}

Referenced by ACTION_ShowDialog(), merge_diff_row(), merge_diff_tables(), merge_table(), msi_create_table(), MSI_DatabaseGetPrimaryKeys(), MSI_DatabaseImport(), and update_merge_errors().

◆ TABLE_fetch_int()

static UINT TABLE_fetch_int ( struct tagMSIVIEW view,
UINT  row,
UINT  col,
UINT val 
)
static

Definition at line 1007 of file table.c.

1008{
1009 struct table_view *tv = (struct table_view *)view;
1010 UINT offset, n;
1011
1012 if( !tv->table )
1014
1015 if( (col==0) || (col>tv->num_cols) )
1017
1018 /* how many rows are there ? */
1019 if( row >= tv->table->row_count )
1020 return ERROR_NO_MORE_ITEMS;
1021
1022 if( tv->columns[col-1].offset >= tv->row_size )
1023 {
1024 ERR("Stuffed up %d >= %d\n", tv->columns[col-1].offset, tv->row_size );
1025 ERR("%p %p\n", tv, tv->columns );
1026 return ERROR_FUNCTION_FAILED;
1027 }
1028
1029 n = bytes_per_column( tv->db, &tv->columns[col - 1], LONG_STR_BYTES );
1030 if (n != 2 && n != 3 && n != 4)
1031 {
1032 ERR("oops! what is %d bytes per column?\n", n );
1033 return ERROR_FUNCTION_FAILED;
1034 }
1035
1036 offset = tv->columns[col-1].offset;
1037 *val = read_table_int(tv->table->data, row, offset, n);
1038
1039 /* TRACE("Data [%d][%d] = %d\n", row, col, *val ); */
1040
1041 return ERROR_SUCCESS;
1042}
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105

Referenced by compare_record(), get_stream_name(), row_matches(), TABLE_set_int(), TABLE_set_row(), TABLE_set_string(), TransformView_drop_table(), and TransformView_fetch_int().

◆ TABLE_fetch_stream()

static UINT TABLE_fetch_stream ( struct tagMSIVIEW view,
UINT  row,
UINT  col,
IStream **  stm 
)
static

Definition at line 1134 of file table.c.

1135{
1136 struct table_view *tv = (struct table_view *)view;
1137 UINT r;
1138 WCHAR *name;
1139
1140 if( !view->ops->fetch_int )
1142
1143 r = get_stream_name( tv, row, &name );
1144 if (r != ERROR_SUCCESS)
1145 {
1146 ERR("fetching stream, error = %u\n", r);
1147 return r;
1148 }
1149
1150 r = msi_get_stream( tv->db, name, stm );
1151 if (r != ERROR_SUCCESS)
1152 ERR("fetching stream %s, error = %u\n", debugstr_w(name), r);
1153
1154 free( name );
1155 return r;
1156}
static UINT get_stream_name(const struct table_view *tv, UINT row, WCHAR **pstname)
Definition: table.c:1044
UINT msi_get_stream(MSIDATABASE *, const WCHAR *, IStream **)
Definition: streams.c:499

Referenced by TransformView_fetch_stream().

◆ table_find_row()

static UINT table_find_row ( struct table_view tv,
MSIRECORD rec,
UINT row,
UINT column 
)
static

Definition at line 3149 of file table.c.

3150{
3152
3153 data = record_to_row( tv, rec );
3154 if( !data )
3155 return r;
3156 for( i = 0; i < tv->table->row_count; i++ )
3157 {
3158 r = row_matches( tv, i, data, column );
3159 if( r == ERROR_SUCCESS )
3160 {
3161 *row = i;
3162 break;
3163 }
3164 }
3165 free( data );
3166 return r;
3167}
static UINT * record_to_row(const struct table_view *tv, MSIRECORD *rec)
Definition: table.c:3076
static UINT row_matches(struct table_view *tv, UINT row, const UINT *data, UINT *column)
Definition: table.c:3120

Referenced by table_assign(), TABLE_drop(), table_load_transform(), TABLE_modify(), TABLE_remove_column(), table_update(), and table_validate_new().

◆ table_get_column_info()

static UINT table_get_column_info ( MSIDATABASE db,
const WCHAR name,
struct column_info **  pcols,
UINT pcount 
)
static

Definition at line 542 of file table.c.

543{
544 UINT r, column_count = 0;
545 struct column_info *columns;
546
547 /* get the number of columns in this table */
548 column_count = 0;
549 r = get_tablecolumns( db, name, NULL, &column_count );
550 if (r != ERROR_SUCCESS)
551 return r;
552
553 *pcount = column_count;
554
555 /* if there are no columns, there's no table */
556 if (!column_count)
558
559 TRACE("table %s found\n", debugstr_w(name));
560
561 columns = malloc( column_count * sizeof(*columns) );
562 if (!columns)
564
565 r = get_tablecolumns( db, name, columns, &column_count );
566 if (r != ERROR_SUCCESS)
567 {
568 free( columns );
570 }
571 *pcols = columns;
572 return r;
573}
static UINT get_tablecolumns(MSIDATABASE *, const WCHAR *, struct column_info *, UINT *)
Definition: table.c:631

Referenced by get_table(), and update_table_columns().

◆ TABLE_get_column_info()

static UINT TABLE_get_column_info ( struct tagMSIVIEW view,
UINT  n,
LPCWSTR name,
UINT type,
BOOL temporary,
LPCWSTR table_name 
)
static

Definition at line 1570 of file table.c.

1573{
1574 struct table_view *tv = (struct table_view *)view;
1575
1576 TRACE("%p %d %p %p\n", tv, n, name, type );
1577
1578 if( ( n == 0 ) || ( n > tv->num_cols ) )
1580
1581 if( name )
1582 {
1583 *name = tv->columns[n-1].colname;
1584 if( !*name )
1585 return ERROR_FUNCTION_FAILED;
1586 }
1587
1588 if( table_name )
1589 {
1590 *table_name = tv->columns[n-1].tablename;
1591 if( !*table_name )
1592 return ERROR_FUNCTION_FAILED;
1593 }
1594
1595 if( type )
1596 *type = tv->columns[n-1].type;
1597
1598 if( temporary )
1599 *temporary = (tv->columns[n-1].type & MSITYPE_TEMPORARY) != 0;
1600
1601 return ERROR_SUCCESS;
1602}

Referenced by TransformView_get_column_info().

◆ TABLE_get_dimensions()

static UINT TABLE_get_dimensions ( struct tagMSIVIEW view,
UINT rows,
UINT cols 
)
static

Definition at line 1552 of file table.c.

1553{
1554 struct table_view *tv = (struct table_view *)view;
1555
1556 TRACE("%p %p %p\n", view, rows, cols );
1557
1558 if( cols )
1559 *cols = tv->num_cols;
1560 if( rows )
1561 {
1562 if( !tv->table )
1564 *rows = tv->table->row_count;
1565 }
1566
1567 return ERROR_SUCCESS;
1568}

Referenced by TABLE_delete_row(), and TransformView_get_dimensions().

◆ TABLE_get_row()

static UINT TABLE_get_row ( struct tagMSIVIEW view,
UINT  row,
MSIRECORD **  rec 
)
static

Definition at line 1280 of file table.c.

1281{
1282 struct table_view *tv = (struct table_view *)view;
1283
1284 if (!tv->table)
1286
1287 return msi_view_get_row(tv->db, view, row, rec);
1288}
UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **)
Definition: msiquery.c:353

Referenced by refresh_record().

◆ table_get_row_size()

static UINT table_get_row_size ( MSIDATABASE db,
const struct column_info cols,
UINT  count,
UINT  bytes_per_strref 
)
static

Definition at line 376 of file table.c.

377{
378 const struct column_info *last_col;
379
380 if (!count)
381 return 0;
382
383 if (bytes_per_strref != LONG_STR_BYTES)
384 {
385 UINT i, size = 0;
386 for (i = 0; i < count; i++) size += bytes_per_column( db, &cols[i], bytes_per_strref );
387 return size;
388 }
389 last_col = &cols[count - 1];
390 return last_col->offset + bytes_per_column( db, last_col, bytes_per_strref );
391}

Referenced by read_table_from_storage(), save_table(), TABLE_add_column(), TABLE_CreateView(), and update_table_columns().

◆ TABLE_insert_row()

static UINT TABLE_insert_row ( struct tagMSIVIEW view,
MSIRECORD rec,
UINT  row,
BOOL  temporary 
)
static

Definition at line 1708 of file table.c.

1709{
1710 struct table_view *tv = (struct table_view *)view;
1711 UINT i, r;
1712
1713 TRACE("%p %p %s\n", tv, rec, temporary ? "TRUE" : "FALSE" );
1714
1715 /* check that the key is unique - can we find a matching row? */
1716 r = table_validate_new( tv, rec, NULL );
1717 if( r != ERROR_SUCCESS )
1718 return ERROR_FUNCTION_FAILED;
1719
1720 if (row == -1)
1721 row = find_insert_index( tv, rec );
1722
1723 r = table_create_new_row( view, &row, temporary );
1724 TRACE("insert_row returned %08x\n", r);
1725 if( r != ERROR_SUCCESS )
1726 return r;
1727
1728 /* shift the rows to make room for the new row */
1729 for (i = tv->table->row_count - 1; i > row; i--)
1730 {
1731 memmove(&(tv->table->data[i][0]),
1732 &(tv->table->data[i - 1][0]), tv->row_size);
1733 tv->table->data_persistent[i] = tv->table->data_persistent[i - 1];
1734 }
1735
1736 /* Re-set the persistence flag */
1737 tv->table->data_persistent[row] = !temporary;
1738 return TABLE_set_row( view, row, rec, (1<<tv->num_cols) - 1 );
1739}
static int find_insert_index(struct table_view *tv, MSIRECORD *rec)
Definition: table.c:1683
static UINT table_validate_new(struct table_view *tv, MSIRECORD *rec, UINT *column)
Definition: table.c:1606
static UINT table_create_new_row(struct tagMSIVIEW *view, UINT *num, BOOL temporary)
Definition: table.c:1475
#define memmove(s1, s2, n)
Definition: mkisofs.h:881

Referenced by TABLE_add_column(), table_assign(), and TABLE_modify().

◆ table_load_transform()

static UINT table_load_transform ( MSIDATABASE db,
IStorage stg,
string_table st,
struct transform_data transform,
UINT  bytes_per_strref,
int  err_cond 
)
static

Definition at line 3175 of file table.c.

3177{
3178 BYTE *rawdata = NULL;
3179 struct table_view *tv = NULL;
3180 UINT r, n, sz, i, mask, num_cols, colcol = 0, rawsize = 0;
3181 MSIRECORD *rec = NULL;
3182 WCHAR coltable[32];
3183 const WCHAR *name;
3184
3185 if (!transform)
3186 return ERROR_SUCCESS;
3187
3188 name = transform->name;
3189
3190 coltable[0] = 0;
3191 TRACE("%p %p %p %s\n", db, stg, st, debugstr_w(name) );
3192
3193 /* read the transform data */
3194 read_stream_data( stg, name, TRUE, &rawdata, &rawsize );
3195 if ( !rawdata )
3196 {
3197 TRACE("table %s empty\n", debugstr_w(name) );
3198 return ERROR_INVALID_TABLE;
3199 }
3200
3201 /* create a table view */
3202 if ( err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM )
3203 r = TransformView_Create( db, st, name, (MSIVIEW**) &tv );
3204 else
3205 r = TABLE_CreateView( db, name, (MSIVIEW**) &tv );
3206 if( r != ERROR_SUCCESS )
3207 goto err;
3208
3209 r = tv->view.ops->execute( &tv->view, NULL );
3210 if( r != ERROR_SUCCESS )
3211 goto err;
3212
3213 TRACE("name = %s columns = %u row_size = %u raw size = %u\n",
3214 debugstr_w(name), tv->num_cols, tv->row_size, rawsize );
3215
3216 /* interpret the data */
3217 for (n = 0; n < rawsize;)
3218 {
3219 mask = rawdata[n] | (rawdata[n + 1] << 8);
3220 if (mask & 1)
3221 {
3222 /*
3223 * if the low bit is set, columns are continuous and
3224 * the number of columns is specified in the high byte
3225 */
3226 sz = 2;
3227 num_cols = mask >> 8;
3228 if (num_cols > tv->num_cols)
3229 {
3230 ERR("excess columns in transform: %u > %u\n", num_cols, tv->num_cols);
3231 break;
3232 }
3233
3234 for (i = 0; i < num_cols; i++)
3235 {
3236 if( (tv->columns[i].type & MSITYPE_STRING) &&
3237 ! MSITYPE_IS_BINARY(tv->columns[i].type) )
3238 sz += bytes_per_strref;
3239 else
3240 sz += bytes_per_column( tv->db, &tv->columns[i], bytes_per_strref );
3241 }
3242 }
3243 else
3244 {
3245 /*
3246 * If the low bit is not set, mask is a bitmask.
3247 * Excepting for key fields, which are always present,
3248 * each bit indicates that a field is present in the transform record.
3249 *
3250 * mask == 0 is a special case ... only the keys will be present
3251 * and it means that this row should be deleted.
3252 */
3253 sz = 2;
3254 num_cols = tv->num_cols;
3255 for (i = 0; i < num_cols; i++)
3256 {
3257 if ((tv->columns[i].type & MSITYPE_KEY) || ((1 << i) & mask))
3258 {
3259 if ((tv->columns[i].type & MSITYPE_STRING) &&
3260 !MSITYPE_IS_BINARY(tv->columns[i].type))
3261 sz += bytes_per_strref;
3262 else
3263 sz += bytes_per_column( tv->db, &tv->columns[i], bytes_per_strref );
3264 }
3265 }
3266 }
3267
3268 /* check we didn't run of the end of the table */
3269 if (n + sz > rawsize)
3270 {
3271 ERR("borked.\n");
3272 dump_table( st, (USHORT *)rawdata, rawsize );
3273 break;
3274 }
3275
3276 rec = get_transform_record( tv, st, stg, &rawdata[n], bytes_per_strref );
3277 if (rec)
3278 {
3279 WCHAR table[32];
3280 DWORD sz = 32;
3282 UINT row = 0;
3283
3284 if (!wcscmp( name, L"_Columns" ))
3285 {
3286 MSI_RecordGetStringW( rec, 1, table, &sz );
3287 number = MSI_RecordGetInteger( rec, 2 );
3288
3289 /*
3290 * Native msi seems writes nul into the Number (2nd) column of
3291 * the _Columns table when there are new columns
3292 */
3293 if ( number == MSI_NULL_INTEGER )
3294 {
3295 /* reset the column number on a new table */
3296 if (wcscmp( coltable, table ))
3297 {
3298 colcol = 0;
3299 lstrcpyW( coltable, table );
3300 }
3301
3302 /* fix nul column numbers */
3303 MSI_RecordSetInteger( rec, 2, ++colcol );
3304 }
3305 }
3306
3307 if (TRACE_ON(msidb)) dump_record( rec );
3308
3309 if (tv->table)
3310 r = table_find_row( tv, rec, &row, NULL );
3311 else
3313 if (r == ERROR_SUCCESS)
3314 {
3315 if (!mask)
3316 {
3317 TRACE("deleting row [%d]:\n", row);
3318 r = tv->view.ops->delete_row( &tv->view, row );
3319 if (r != ERROR_SUCCESS)
3320 WARN("failed to delete row %u\n", r);
3321 }
3322 else if (mask & 1)
3323 {
3324 TRACE("modifying full row [%d]:\n", row);
3325 r = tv->view.ops->set_row( &tv->view, row, rec, (1 << tv->num_cols) - 1 );
3326 if (r != ERROR_SUCCESS)
3327 WARN("failed to modify row %u\n", r);
3328 }
3329 else
3330 {
3331 TRACE("modifying masked row [%d]:\n", row);
3332 r = tv->view.ops->set_row( &tv->view, row, rec, mask );
3333 if (r != ERROR_SUCCESS)
3334 WARN("failed to modify row %u\n", r);
3335 }
3336 }
3337 else
3338 {
3339 TRACE("inserting row\n");
3340 r = tv->view.ops->insert_row( &tv->view, rec, -1, FALSE );
3341 if (r != ERROR_SUCCESS)
3342 WARN("failed to insert row %u\n", r);
3343 }
3344
3345 if (!(err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM) && !wcscmp( name, L"_Columns" ))
3347
3348 msiobj_release( &rec->hdr );
3349 }
3350
3351 n += sz;
3352 }
3353
3354err:
3355 /* no need to free the table, it's associated with the database */
3356 free( rawdata );
3357 if( tv )
3358 tv->view.ops->delete( &tv->view );
3359
3360 return ERROR_SUCCESS;
3361}
#define TRACE_ON(x)
Definition: compat.h:75
static void dump_table(const string_table *st, const USHORT *rawdata, UINT rawsize)
Definition: table.c:3065
static MSIRECORD * get_transform_record(const struct table_view *tv, const string_table *st, IStorage *stg, const BYTE *rawdata, UINT bytes_per_strref)
Definition: table.c:2977
static UINT TransformView_Create(MSIDATABASE *db, string_table *st, LPCWSTR name, MSIVIEW **view)
Definition: table.c:2768
static void update_table_columns(MSIDATABASE *db, const WCHAR *name)
Definition: table.c:935
void dump_record(MSIRECORD *)
Definition: record.c:1028
UINT(* set_row)(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: msipriv.h:278
UINT(* delete_row)(struct tagMSIVIEW *view, UINT row)
Definition: msipriv.h:288

Referenced by msi_table_apply_transform().

◆ TABLE_modify()

static UINT TABLE_modify ( struct tagMSIVIEW view,
MSIMODIFY  eModifyMode,
MSIRECORD rec,
UINT  row 
)
static

Definition at line 1840 of file table.c.

1842{
1843 struct table_view *tv = (struct table_view *)view;
1844 UINT r, frow, column;
1845
1846 TRACE("%p %d %p\n", view, eModifyMode, rec );
1847
1848 switch (eModifyMode)
1849 {
1850 case MSIMODIFY_DELETE:
1851 r = TABLE_delete_row( view, row );
1852 break;
1854 r = table_validate_new( tv, rec, &column );
1855 if (r != ERROR_SUCCESS)
1856 {
1858 tv->view.error_column = tv->columns[column].colname;
1860 }
1861 break;
1862
1863 case MSIMODIFY_INSERT:
1864 r = table_validate_new( tv, rec, NULL );
1865 if (r != ERROR_SUCCESS)
1866 break;
1867 r = TABLE_insert_row( view, rec, -1, FALSE );
1868 break;
1869
1871 r = table_validate_new( tv, rec, NULL );
1872 if (r != ERROR_SUCCESS)
1873 break;
1874 r = TABLE_insert_row( view, rec, -1, TRUE );
1875 break;
1876
1877 case MSIMODIFY_REFRESH:
1878 r = refresh_record( view, rec, row );
1879 break;
1880
1881 case MSIMODIFY_UPDATE:
1882 r = table_update( view, rec, row );
1883 break;
1884
1885 case MSIMODIFY_ASSIGN:
1886 r = table_assign( view, rec );
1887 break;
1888
1889 case MSIMODIFY_MERGE:
1890 /* check row that matches this record */
1891 r = table_find_row( tv, rec, &frow, &column );
1892 if (r != ERROR_SUCCESS)
1893 {
1894 r = table_validate_new( tv, rec, NULL );
1895 if (r == ERROR_SUCCESS)
1896 r = TABLE_insert_row( view, rec, -1, FALSE );
1897 }
1898 break;
1899
1900 case MSIMODIFY_REPLACE:
1901 case MSIMODIFY_VALIDATE:
1904 FIXME("%p %d %p - mode not implemented\n", view, eModifyMode, rec );
1906 break;
1907
1908 default:
1910 }
1911
1912 return r;
1913}
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
static UINT table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: table.c:1779
static UINT refresh_record(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: table.c:1820
static UINT table_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
Definition: table.c:1805
@ MSIMODIFY_DELETE
Definition: msiquery.h:57
@ MSIMODIFY_REPLACE
Definition: msiquery.h:55
@ MSIMODIFY_MERGE
Definition: msiquery.h:56
@ MSIMODIFY_INSERT_TEMPORARY
Definition: msiquery.h:58
@ MSIMODIFY_UPDATE
Definition: msiquery.h:53
@ MSIMODIFY_VALIDATE_DELETE
Definition: msiquery.h:62
@ MSIMODIFY_ASSIGN
Definition: msiquery.h:54
@ MSIMODIFY_VALIDATE_NEW
Definition: msiquery.h:60
@ MSIMODIFY_INSERT
Definition: msiquery.h:52
@ MSIMODIFY_REFRESH
Definition: msiquery.h:51
@ MSIMODIFY_VALIDATE_FIELD
Definition: msiquery.h:61
@ MSIMODIFY_VALIDATE
Definition: msiquery.h:59
@ MSIDBERROR_DUPLICATEKEY
Definition: msiquery.h:110
MSIDBERROR error
Definition: msipriv.h:356
const WCHAR * error_column
Definition: msipriv.h:357
#define ERROR_INVALID_DATA
Definition: winerror.h:116

◆ TABLE_release()

static UINT TABLE_release ( struct tagMSIVIEW view)
static

Definition at line 1988 of file table.c.

1989{
1990 struct table_view *tv = (struct table_view *)view;
1991 INT ref = tv->table->ref_count;
1992 UINT r;
1993 INT i;
1994
1995 TRACE("%p %d\n", view, ref);
1996
1998 if (ref == 0)
1999 {
2000 for (i = tv->table->col_count - 1; i >= 0; i--)
2001 {
2002 if (tv->table->colinfo[i].type & MSITYPE_TEMPORARY)
2003 {
2004 r = TABLE_remove_column(view, tv->table->colinfo[i].number);
2005 if (r != ERROR_SUCCESS)
2006 break;
2007 }
2008 else
2009 {
2010 break;
2011 }
2012 }
2013
2014 if (!tv->table->col_count)
2015 {
2016 list_remove(&tv->table->entry);
2017 free_table(tv->table);
2019 }
2020 }
2021
2022 return ref;
2023}
#define InterlockedDecrement
Definition: armddk.h:52
static UINT TABLE_delete(struct tagMSIVIEW *view)
Definition: table.c:1915
Definition: send.c:48

◆ TABLE_remove_column()

static UINT TABLE_remove_column ( struct tagMSIVIEW view,
UINT  number 
)
static

Definition at line 1937 of file table.c.

1938{
1939 struct table_view *tv = (struct table_view *)view;
1940 MSIRECORD *rec = NULL;
1941 MSIVIEW *columns = NULL;
1942 UINT row, r;
1943
1944 if (tv->table->col_count != number)
1946
1947 if (tv->table->colinfo[number-1].type & MSITYPE_TEMPORARY)
1948 {
1949 UINT size = tv->table->colinfo[number-1].offset;
1950 tv->table->col_count--;
1951 tv->table->colinfo = realloc(tv->table->colinfo, sizeof(*tv->table->colinfo) * tv->table->col_count);
1952
1953 for (row = 0; row < tv->table->row_count; row++)
1954 tv->table->data[row] = realloc(tv->table->data[row], size);
1955 return ERROR_SUCCESS;
1956 }
1957
1958 rec = MSI_CreateRecord(2);
1959 if (!rec)
1960 return ERROR_OUTOFMEMORY;
1961
1962 MSI_RecordSetStringW(rec, 1, tv->name);
1964
1965 r = TABLE_CreateView(tv->db, L"_Columns", &columns);
1966 if (r != ERROR_SUCCESS)
1967 {
1968 msiobj_release(&rec->hdr);
1969 return r;
1970 }
1971
1972 r = table_find_row((struct table_view *)columns, rec, &row, NULL);
1973 if (r != ERROR_SUCCESS)
1974 goto done;
1975
1977 if (r != ERROR_SUCCESS)
1978 goto done;
1979
1980 update_table_columns(tv->db, tv->name);
1981
1982done:
1983 msiobj_release(&rec->hdr);
1984 columns->ops->delete(columns);
1985 return r;
1986}

Referenced by msi_table_apply_transform(), TABLE_drop(), and TABLE_release().

◆ table_set_bytes()

static UINT table_set_bytes ( struct table_view tv,
UINT  row,
UINT  col,
UINT  val 
)
static

Definition at line 1159 of file table.c.

1160{
1161 UINT offset, n, i;
1162
1163 if( !tv->table )
1165
1166 if( (col==0) || (col>tv->num_cols) )
1168
1169 if( row >= tv->table->row_count )
1171
1172 if( tv->columns[col-1].offset >= tv->row_size )
1173 {
1174 ERR("Stuffed up %d >= %d\n", tv->columns[col-1].offset, tv->row_size );
1175 ERR("%p %p\n", tv, tv->columns );
1176 return ERROR_FUNCTION_FAILED;
1177 }
1178
1179 free( tv->columns[col-1].hash_table );
1180 tv->columns[col-1].hash_table = NULL;
1181
1182 n = bytes_per_column( tv->db, &tv->columns[col - 1], LONG_STR_BYTES );
1183 if ( n != 2 && n != 3 && n != 4 )
1184 {
1185 ERR("oops! what is %d bytes per column?\n", n );
1186 return ERROR_FUNCTION_FAILED;
1187 }
1188
1189 offset = tv->columns[col-1].offset;
1190 for ( i = 0; i < n; i++ )
1191 tv->table->data[row][offset + i] = (val >> i * 8) & 0xff;
1192
1193 return ERROR_SUCCESS;
1194}

Referenced by TABLE_set_int(), TABLE_set_row(), and TABLE_set_string().

◆ TABLE_set_int()

static UINT TABLE_set_int ( MSIVIEW view,
UINT  row,
UINT  col,
int  val 
)
static

Definition at line 1216 of file table.c.

1217{
1218 struct table_view *tv = (struct table_view *)view;
1219 UINT r, table_int;
1220
1221 TRACE("row %u, col %u, val %d.\n", row, col, val);
1222
1223 if ((r = int_to_table_storage( tv, col, val, &table_int )))
1224 return r;
1225
1226 if (tv->columns[col-1].type & MSITYPE_KEY)
1227 {
1228 UINT key;
1229
1230 if ((r = TABLE_fetch_int( view, row, col, &key )))
1231 return r;
1232 if (key != table_int)
1233 {
1234 ERR("Cannot modify primary key %s.%s.\n",
1235 debugstr_w(tv->table->name), debugstr_w(tv->columns[col-1].colname));
1236 return ERROR_FUNCTION_FAILED;
1237 }
1238 }
1239
1240 return table_set_bytes( tv, row, col, table_int );
1241}
static UINT table_set_bytes(struct table_view *tv, UINT row, UINT col, UINT val)
Definition: table.c:1159
WCHAR name[1]
Definition: table.c:70

◆ TABLE_set_row()

static UINT TABLE_set_row ( struct tagMSIVIEW view,
UINT  row,
MSIRECORD rec,
UINT  mask 
)
static

Definition at line 1390 of file table.c.

1391{
1392 struct table_view *tv = (struct table_view *)view;
1393 UINT i, val, r = ERROR_SUCCESS;
1394
1395 if ( !tv->table )
1397
1398 /* test if any of the mask bits are invalid */
1399 if ( mask >= (1<<tv->num_cols) )
1401
1402 for ( i = 0; i < tv->num_cols; i++ )
1403 {
1404 BOOL persistent;
1405
1406 /* only update the fields specified in the mask */
1407 if ( !(mask&(1<<i)) )
1408 continue;
1409
1410 persistent = (tv->table->persistent != MSICONDITION_FALSE) &&
1411 (tv->table->data_persistent[row]);
1412 /* FIXME: should we allow updating keys? */
1413
1414 val = 0;
1415 if ( !MSI_RecordIsNull( rec, i + 1 ) )
1416 {
1417 r = get_table_value_from_record (tv, rec, i + 1, &val);
1418 if ( MSITYPE_IS_BINARY(tv->columns[ i ].type) )
1419 {
1420 IStream *stm;
1421 LPWSTR stname;
1422
1423 if ( r != ERROR_SUCCESS )
1424 return ERROR_FUNCTION_FAILED;
1425
1426 r = MSI_RecordGetIStream( rec, i + 1, &stm );
1427 if ( r != ERROR_SUCCESS )
1428 return r;
1429
1430 r = get_stream_name( tv, row, &stname );
1431 if ( r != ERROR_SUCCESS )
1432 {
1433 IStream_Release( stm );
1434 return r;
1435 }
1436
1437 r = add_stream( tv->db, stname, stm );
1438 IStream_Release( stm );
1439 free( stname );
1440
1441 if ( r != ERROR_SUCCESS )
1442 return r;
1443 }
1444 else if ( tv->columns[i].type & MSITYPE_STRING )
1445 {
1446 UINT x;
1447
1448 if ( r != ERROR_SUCCESS )
1449 {
1450 int len;
1451 const WCHAR *sval = msi_record_get_string( rec, i + 1, &len );
1452 val = msi_add_string( tv->db->strings, sval, len, persistent );
1453 }
1454 else
1455 {
1456 TABLE_fetch_int(&tv->view, row, i + 1, &x);
1457 if (val == x)
1458 continue;
1459 }
1460 }
1461 else
1462 {
1463 if ( r != ERROR_SUCCESS )
1464 return ERROR_FUNCTION_FAILED;
1465 }
1466 }
1467
1468 r = table_set_bytes( tv, row, i+1, val );
1469 if ( r != ERROR_SUCCESS )
1470 break;
1471 }
1472 return r;
1473}
static UINT add_stream(MSIDATABASE *db, const WCHAR *name, IStream *data)
Definition: table.c:1290
UINT MSI_RecordGetIStream(MSIRECORD *, UINT, IStream **)
Definition: record.c:852
MSICONDITION persistent
Definition: table.c:68

Referenced by table_assign(), TABLE_insert_row(), and table_update().

◆ TABLE_set_stream()

static UINT TABLE_set_stream ( MSIVIEW view,
UINT  row,
UINT  col,
IStream stream 
)
static

Definition at line 1342 of file table.c.

1343{
1344 struct table_view *tv = (struct table_view *)view;
1345 WCHAR *name;
1346 UINT r;
1347
1348 TRACE("row %u, col %u, stream %p.\n", row, col, stream);
1349
1350 if ((r = get_stream_name( tv, row - 1, &name )))
1351 return r;
1352
1353 r = add_stream( tv->db, name, stream );
1354 free( name );
1355 return r;
1356}
Definition: parse.h:23

◆ TABLE_set_string()

static UINT TABLE_set_string ( MSIVIEW view,
UINT  row,
UINT  col,
const WCHAR val,
int  len 
)
static

Definition at line 1243 of file table.c.

1244{
1245 struct table_view *tv = (struct table_view *)view;
1246 BOOL persistent;
1247 UINT id, r;
1248
1249 TRACE("row %u, col %u, val %s.\n", row, col, debugstr_wn(val, len));
1250
1251 persistent = (tv->table->persistent != MSICONDITION_FALSE)
1252 && tv->table->data_persistent[row];
1253
1254 if (val)
1255 {
1256 r = msi_string2id( tv->db->strings, val, len, &id );
1257 if (r != ERROR_SUCCESS)
1258 id = msi_add_string( tv->db->strings, val, len, persistent );
1259 }
1260 else
1261 id = 0;
1262
1263 if (tv->columns[col-1].type & MSITYPE_KEY)
1264 {
1265 UINT key;
1266
1267 if ((r = TABLE_fetch_int( view, row, col, &key )))
1268 return r;
1269 if (key != id)
1270 {
1271 ERR("Cannot modify primary key %s.%s.\n",
1272 debugstr_w(tv->table->name), debugstr_w(tv->columns[col-1].colname));
1273 return ERROR_FUNCTION_FAILED;
1274 }
1275 }
1276
1277 return table_set_bytes( tv, row, col, id );
1278}
GLuint id
Definition: glext.h:5910
if(dx< 0)
Definition: linetemp.h:194

◆ table_update()

static UINT table_update ( struct tagMSIVIEW view,
MSIRECORD rec,
UINT  row 
)
static

Definition at line 1779 of file table.c.

1780{
1781 struct table_view *tv = (struct table_view *)view;
1782 UINT r, new_row;
1783
1784 /* FIXME: MsiViewFetch should set rec index 0 to some ID that
1785 * sets the fetched record apart from other records
1786 */
1787
1788 if (!tv->table)
1790
1791 r = table_find_row(tv, rec, &new_row, NULL);
1792 if (r != ERROR_SUCCESS)
1793 {
1794 ERR("can't find row to modify\n");
1795 return ERROR_FUNCTION_FAILED;
1796 }
1797
1798 /* the row cannot be changed */
1799 if (row != new_row)
1800 return ERROR_FUNCTION_FAILED;
1801
1802 return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1);
1803}

Referenced by TABLE_modify().

◆ table_validate_new()

static UINT table_validate_new ( struct table_view tv,
MSIRECORD rec,
UINT column 
)
static

Definition at line 1606 of file table.c.

1607{
1608 UINT r, row, i;
1609
1610 /* check there are no null values where they're not allowed */
1611 for( i = 0; i < tv->num_cols; i++ )
1612 {
1613 if ( tv->columns[i].type & MSITYPE_NULLABLE )
1614 continue;
1615
1616 if ( MSITYPE_IS_BINARY(tv->columns[i].type) )
1617 TRACE("skipping binary column\n");
1618 else if ( tv->columns[i].type & MSITYPE_STRING )
1619 {
1620 int len;
1621 const WCHAR *str = msi_record_get_string( rec, i+1, &len );
1622
1623 if (!str || (!str[0] && !len))
1624 {
1625 if (column) *column = i;
1626 return ERROR_INVALID_DATA;
1627 }
1628 }
1629 else
1630 {
1631 UINT n;
1632
1633 n = MSI_RecordGetInteger( rec, i+1 );
1634 if (n == MSI_NULL_INTEGER)
1635 {
1636 if (column) *column = i;
1637 return ERROR_INVALID_DATA;
1638 }
1639 }
1640 }
1641
1642 /* check there are no duplicate keys */
1643 r = table_find_row( tv, rec, &row, column );
1644 if (r == ERROR_SUCCESS)
1645 return ERROR_FUNCTION_FAILED;
1646
1647 return ERROR_SUCCESS;
1648}

Referenced by TABLE_insert_row(), and TABLE_modify().

◆ TransformView_add_column()

static UINT TransformView_add_column ( struct table_view tv,
MSIRECORD rec 
)
static

Definition at line 2503 of file table.c.

2504{
2505 static const WCHAR query_pfx[] =
2506 L"INSERT INTO `_TransformView` (`new`, `Table`, `Current`, `Column`, `Data`) VALUES (1, '";
2507
2508 WCHAR buf[256], *query = buf;
2509 UINT i, p, r, qlen;
2510 DWORD len;
2511 MSIQUERY *q;
2512
2513 qlen = p = wcslen( query_pfx );
2514 for (i = 1; i <= 4; i++)
2515 {
2516 r = MSI_RecordGetStringW( rec, i, NULL, &len );
2517 if (r != ERROR_SUCCESS)
2518 return r;
2519 qlen += len + 3; /* strlen( "','" ) */
2520 }
2521
2522 if (qlen > ARRAY_SIZE(buf))
2523 {
2524 query = malloc( len * sizeof(WCHAR) );
2525 qlen = len;
2526 if (!query)
2527 return ERROR_OUTOFMEMORY;
2528 }
2529
2530 memcpy( query, query_pfx, p * sizeof(WCHAR) );
2531 for (i = 1; i <= 4; i++)
2532 {
2533 len = qlen - p;
2534 MSI_RecordGetStringW( rec, i, query + p, &len );
2535 p += len;
2536 query[p++] = '\'';
2537 if (i != 4)
2538 {
2539 query[p++] = ',';
2540 query[p++] = '\'';
2541 }
2542 }
2543 query[p++] = ')';
2544 query[p++] = 0;
2545
2546 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2547 if (query != buf)
2548 free( query );
2549 if (r != ERROR_SUCCESS)
2550 return r;
2551
2552 r = MSI_ViewExecute( q, NULL );
2553 msiobj_release( &q->hdr );
2554 return r;
2555}
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751

Referenced by TransformView_insert_row().

◆ TransformView_close()

static UINT TransformView_close ( MSIVIEW view)
static

Definition at line 2721 of file table.c.

2722{
2723 return ERROR_SUCCESS;
2724}

◆ TransformView_Create()

static UINT TransformView_Create ( MSIDATABASE db,
string_table st,
LPCWSTR  name,
MSIVIEW **  view 
)
static

Definition at line 2768 of file table.c.

2769{
2770 static const WCHAR query_pfx[] = L"SELECT `Column`, `Data`, `Current` FROM `_TransformView` WHERE `Table`='";
2771 static const WCHAR query_sfx[] = L"' AND `Row` IS NULL AND `Current` IS NOT NULL AND `new` = 1";
2772
2773 WCHAR buf[256], *query = buf;
2774 UINT r, len, name_len, size, add_col;
2775 struct column_info *colinfo;
2776 struct table_view *tv;
2777 MSIRECORD *rec;
2778 MSIQUERY *q;
2779
2780 name_len = wcslen( name );
2781
2782 r = TABLE_CreateView( db, name, (MSIVIEW **)&tv );
2784 {
2785 /* table does not exist */
2786 size = FIELD_OFFSET( struct table_view, name[name_len + 1] );
2787 tv = calloc( 1, size );
2788 if (!tv)
2789 return ERROR_OUTOFMEMORY;
2790
2791 tv->db = db;
2792 memcpy( tv->name, name, name_len * sizeof(WCHAR) );
2793 }
2794 else if (r != ERROR_SUCCESS)
2795 {
2796 return r;
2797 }
2798
2800
2801 len = ARRAY_SIZE(query_pfx) + name_len + ARRAY_SIZE(query_sfx) - 1;
2802 if (len > ARRAY_SIZE(buf))
2803 {
2804 query = malloc( len * sizeof(WCHAR) );
2805 if (!query)
2806 {
2807 free( tv );
2808 return ERROR_OUTOFMEMORY;
2809 }
2810 }
2811 memcpy( query, query_pfx, ARRAY_SIZE(query_pfx) * sizeof(WCHAR) );
2812 len = ARRAY_SIZE(query_pfx) - 1;
2813 memcpy( query + len, name, name_len * sizeof(WCHAR) );
2814 len += name_len;
2815 memcpy( query + len, query_sfx, ARRAY_SIZE(query_sfx) * sizeof(WCHAR) );
2816
2817 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2818 if (query != buf)
2819 free( query );
2820 if (r != ERROR_SUCCESS)
2821 {
2822 free( tv );
2823 return r;
2824 }
2825
2826 r = MSI_ViewExecute( q, NULL );
2827 if (r != ERROR_SUCCESS)
2828 {
2829 free( tv );
2830 return r;
2831 }
2832
2833 r = q->view->ops->get_dimensions( q->view, &add_col, NULL );
2834 if (r != ERROR_SUCCESS)
2835 {
2836 MSI_ViewClose( q );
2837 msiobj_release( &q->hdr );
2838 free( tv );
2839 return r;
2840 }
2841 if (!add_col)
2842 {
2843 MSI_ViewClose( q );
2844 msiobj_release( &q->hdr );
2845 *view = (MSIVIEW *)tv;
2846 return ERROR_SUCCESS;
2847 }
2848
2849 colinfo = calloc( add_col + tv->num_cols, sizeof(*colinfo) );
2850 if (!colinfo)
2851 {
2852 MSI_ViewClose( q );
2853 msiobj_release( &q->hdr );
2854 free( tv );
2855 return ERROR_OUTOFMEMORY;
2856 }
2857
2858 while (MSI_ViewFetch( q, &rec ) == ERROR_SUCCESS)
2859 {
2860 int name_len;
2861 const WCHAR *name = msi_record_get_string( rec, 1, &name_len );
2862 const WCHAR *type = msi_record_get_string( rec, 2, NULL );
2863 UINT name_id, idx;
2864
2865 idx = _wtoi( msi_record_get_string(rec, 3, NULL) );
2866 colinfo[idx - 1].number = idx;
2867 colinfo[idx - 1].type = _wtoi( type );
2868
2869 r = msi_string2id( st, name, name_len, &name_id );
2870 if (r == ERROR_SUCCESS)
2871 colinfo[idx - 1].colname = msi_string_lookup( st, name_id, NULL );
2872 else
2873 ERR( "column name %s is not defined in strings table\n", wine_dbgstr_w(name) );
2874 msiobj_release( &rec->hdr );
2875 }
2876 MSI_ViewClose( q );
2877 msiobj_release( &q->hdr );
2878
2879 memcpy( colinfo, tv->columns, tv->num_cols * sizeof(*colinfo) );
2880 tv->columns = colinfo;
2881 tv->num_cols += add_col;
2882 *view = (MSIVIEW *)tv;
2883 return ERROR_SUCCESS;
2884}
static const MSIVIEWOPS transform_view_ops
Definition: table.c:2745
_Check_return_ _CRTIMP int __cdecl _wtoi(_In_z_ const wchar_t *_Str)
#define wine_dbgstr_w
Definition: kernel32.h:34
UINT MSI_ViewFetch(MSIQUERY *, MSIRECORD **)
Definition: msiquery.c:377

Referenced by table_load_transform().

◆ TransformView_create_table()

static UINT TransformView_create_table ( struct table_view tv,
MSIRECORD rec 
)
static

Definition at line 2468 of file table.c.

2469{
2470 static const WCHAR query_fmt[] =
2471 L"INSERT INTO `_TransformView` (`Table`, `Column`, `new`) VALUES ('%s', 'CREATE', 1)";
2472
2473 WCHAR buf[256], *query = buf;
2474 const WCHAR *name;
2475 MSIQUERY *q;
2476 int len;
2477 UINT r;
2478
2479 name = msi_record_get_string( rec, 1, &len );
2480 if (!name)
2482
2483 len = _snwprintf( NULL, 0, query_fmt, name ) + 1;
2484 if (len > ARRAY_SIZE(buf))
2485 {
2486 query = malloc( len * sizeof(WCHAR) );
2487 if (!query)
2488 return ERROR_OUTOFMEMORY;
2489 }
2490 swprintf( query, len, query_fmt, name );
2491
2492 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2493 if (query != buf)
2494 free( query );
2495 if (r != ERROR_SUCCESS)
2496 return r;
2497
2498 r = MSI_ViewExecute( q, NULL );
2499 msiobj_release( &q->hdr );
2500 return r;
2501}
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
#define ERROR_INSTALL_TRANSFORM_FAILURE
Definition: winerror.h:982

Referenced by TransformView_insert_row().

◆ TransformView_delete()

static UINT TransformView_delete ( MSIVIEW view)
static

Definition at line 2737 of file table.c.

2738{
2739 struct table_view *tv = (struct table_view *)view;
2740 if (!tv->table || tv->columns != tv->table->colinfo)
2741 free( tv->columns );
2742 return TABLE_delete( view );
2743}

◆ TransformView_delete_row()

static UINT TransformView_delete_row ( MSIVIEW view,
UINT  row 
)
static

Definition at line 2650 of file table.c.

2651{
2652 static const WCHAR query_pfx[] = L"INSERT INTO `_TransformView` ( `new`, `Table`, `Column`, `Row`) VALUES ( 1, '";
2653 static const WCHAR query_column[] = L"', 'DELETE', '";
2654 static const WCHAR query_sfx[] = L"')";
2655
2656 struct table_view *tv = (struct table_view *)view;
2657 WCHAR *key, buf[256], *query = buf;
2658 UINT r, len, name_len, key_len;
2659 MSIRECORD *rec;
2660 MSIQUERY *q;
2661
2662 if (!wcscmp( tv->name, L"_Columns" ))
2663 {
2664 ERR("trying to remove column\n");
2666 }
2667
2668 if (!wcscmp( tv->name, L"_Tables" ))
2669 return TransformView_drop_table( tv, row );
2670
2671 r = msi_view_get_row( tv->db, view, row, &rec );
2672 if (r != ERROR_SUCCESS)
2673 return r;
2674
2675 key = create_key_string( tv, rec );
2676 msiobj_release( &rec->hdr );
2677 if (!key)
2678 return ERROR_OUTOFMEMORY;
2679
2680 name_len = wcslen( tv->name );
2681 key_len = wcslen( key );
2682 len = ARRAY_SIZE(query_pfx) + name_len + ARRAY_SIZE(query_column) + key_len + ARRAY_SIZE(query_sfx) - 2;
2683 if (len > ARRAY_SIZE(buf))
2684 {
2685 query = malloc( len * sizeof(WCHAR) );
2686 if (!query)
2687 {
2688 free( tv );
2689 free( key );
2690 return ERROR_OUTOFMEMORY;
2691 }
2692 }
2693
2694 memcpy( query, query_pfx, ARRAY_SIZE(query_pfx) * sizeof(WCHAR) );
2695 len = ARRAY_SIZE(query_pfx) - 1;
2696 memcpy( query + len, tv->name, name_len * sizeof(WCHAR) );
2697 len += name_len;
2698 memcpy( query + len, query_column, ARRAY_SIZE(query_column) * sizeof(WCHAR) );
2699 len += ARRAY_SIZE(query_column) - 1;
2700 memcpy( query + len, key, key_len * sizeof(WCHAR) );
2701 len += key_len;
2702 memcpy( query + len, query_sfx, ARRAY_SIZE(query_sfx) * sizeof(WCHAR) );
2703 free( key );
2704
2705 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2706 if (query != buf)
2707 free( query );
2708 if (r != ERROR_SUCCESS)
2709 return r;
2710
2711 r = MSI_ViewExecute( q, NULL );
2712 msiobj_release( &q->hdr );
2713 return r;
2714}
static WCHAR * create_key_string(struct table_view *tv, MSIRECORD *rec)
Definition: table.c:2233
static UINT TransformView_drop_table(struct table_view *tv, UINT row)
Definition: table.c:2606

◆ TransformView_drop_table()

static UINT TransformView_drop_table ( struct table_view tv,
UINT  row 
)
static

Definition at line 2606 of file table.c.

2607{
2608 static const WCHAR query_pfx[] = L"INSERT INTO `_TransformView` ( `new`, `Table`, `Column` ) VALUES ( 1, '";
2609 static const WCHAR query_sfx[] = L"', 'DROP' )";
2610
2611 WCHAR buf[256], *query = buf;
2612 UINT r, table_id, len;
2613 const WCHAR *table;
2614 int table_len;
2615 MSIQUERY *q;
2616
2617 r = TABLE_fetch_int( &tv->view, row, 1, &table_id );
2618 if (r != ERROR_SUCCESS)
2619 return r;
2620
2621 table = msi_string_lookup( tv->db->strings, table_id, &table_len );
2622 if (!table)
2624
2625 len = ARRAY_SIZE(query_pfx) - 1 + table_len + ARRAY_SIZE(query_sfx);
2626 if (len > ARRAY_SIZE(buf))
2627 {
2628 query = malloc( len * sizeof(WCHAR) );
2629 if (!query)
2630 return ERROR_OUTOFMEMORY;
2631 }
2632
2633 memcpy( query, query_pfx, ARRAY_SIZE(query_pfx) * sizeof(WCHAR) );
2634 len = ARRAY_SIZE(query_pfx) - 1;
2635 memcpy( query + len, table, table_len * sizeof(WCHAR) );
2636 len += table_len;
2637 memcpy( query + len, query_sfx, ARRAY_SIZE(query_sfx) * sizeof(WCHAR) );
2638
2639 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2640 if (query != buf)
2641 free( query );
2642 if (r != ERROR_SUCCESS)
2643 return r;
2644
2645 r = MSI_ViewExecute( q, NULL );
2646 msiobj_release( &q->hdr );
2647 return r;
2648}

Referenced by TransformView_delete_row().

◆ TransformView_execute()

static UINT TransformView_execute ( MSIVIEW view,
MSIRECORD record 
)
static

Definition at line 2716 of file table.c.

2717{
2718 return ERROR_SUCCESS;
2719}

◆ TransformView_fetch_int()

static UINT TransformView_fetch_int ( MSIVIEW view,
UINT  row,
UINT  col,
UINT val 
)
static

Definition at line 2298 of file table.c.

2299{
2300 struct table_view *tv = (struct table_view *)view;
2301
2302 if (!tv->table || col > tv->table->