ReactOS 0.4.15-dev-7660-g0086d05
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  tagMSICOLUMNHASHENTRY
 
struct  tagMSICOLUMNINFO
 
struct  tagMSITABLE
 
struct  tagMSITABLEVIEW
 
struct  TRANSFORMDATA
 

Macros

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

Typedefs

typedef struct tagMSICOLUMNHASHENTRY MSICOLUMNHASHENTRY
 
typedef struct tagMSICOLUMNINFO MSICOLUMNINFO
 
typedef struct tagMSITABLEVIEW MSITABLEVIEW
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (msidb)
 
static UINT bytes_per_column (MSIDATABASE *db, const MSICOLUMNINFO *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 msi_free_colinfo (MSICOLUMNINFO *colinfo, UINT count)
 
static void free_table (MSITABLE *table)
 
static UINT msi_table_get_row_size (MSIDATABASE *db, const MSICOLUMNINFO *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, MSICOLUMNINFO *colinfo, DWORD count)
 
static UINT get_defaulttablecolumns (MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO *colinfo, UINT *sz)
 
static UINT get_tablecolumns (MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz)
 
static UINT table_get_column_info (MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO **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 msi_update_table_columns (MSIDATABASE *db, LPCWSTR 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 MSITABLEVIEW *tv, UINT row, WCHAR **pstname)
 
static UINT TABLE_fetch_stream (struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
 
static UINT table_set_bytes (MSITABLEVIEW *tv, UINT row, UINT col, UINT val)
 
static UINT int_to_table_storage (const MSITABLEVIEW *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 (MSITABLEVIEW *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 msi_table_find_row (MSITABLEVIEW *tv, MSIRECORD *rec, UINT *row, UINT *column)
 
static UINT table_validate_new (MSITABLEVIEW *tv, MSIRECORD *rec, UINT *column)
 
static int compare_record (MSITABLEVIEW *tv, UINT row, MSIRECORD *rec)
 
static int find_insert_index (MSITABLEVIEW *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 msi_table_update (struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
 
static UINT msi_table_assign (struct tagMSIVIEW *view, MSIRECORD *rec)
 
static UINT msi_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 (MSITABLEVIEW *tv, MSIRECORD *rec)
 
static UINT msi_record_stream_name (const MSITABLEVIEW *tv, MSIRECORD *rec, LPWSTR 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 (MSITABLEVIEW *tv, MSIRECORD *rec)
 
static UINT TransformView_add_column (MSITABLEVIEW *tv, MSIRECORD *rec)
 
static UINT TransformView_insert_row (MSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
 
static UINT TransformView_drop_table (MSITABLEVIEW *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)
 
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 msi_record_encoded_stream_name (const MSITABLEVIEW *tv, MSIRECORD *rec, LPWSTR *pstname)
 
static MSIRECORDmsi_get_transform_record (const MSITABLEVIEW *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 UINTmsi_record_to_row (const MSITABLEVIEW *tv, MSIRECORD *rec)
 
static UINT msi_row_matches (MSITABLEVIEW *tv, UINT row, const UINT *data, UINT *column)
 
static UINT msi_table_load_transform (MSIDATABASE *db, IStorage *stg, string_table *st, TRANSFORMDATA *transform, UINT bytes_per_strref, int err_cond)
 
UINT msi_table_apply_transform (MSIDATABASE *db, IStorage *stg, int err_cond)
 

Variables

static const MSICOLUMNINFO _Columns_cols [4]
 
static const MSICOLUMNINFO _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 85 of file table.c.

◆ MSITABLE_HASH_TABLE_SIZE

#define MSITABLE_HASH_TABLE_SIZE   37

Definition at line 41 of file table.c.

Typedef Documentation

◆ MSICOLUMNHASHENTRY

◆ MSICOLUMNINFO

◆ MSITABLEVIEW

Function Documentation

◆ add_stream()

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

Definition at line 1288 of file table.c.

1289{
1290 MSIQUERY *query;
1291 MSIRECORD *rec;
1292 UINT r;
1293
1294 TRACE("%p %s %p\n", db, debugstr_w(name), data);
1295
1296 if (!(rec = MSI_CreateRecord( 2 )))
1297 return ERROR_OUTOFMEMORY;
1298
1299 r = MSI_RecordSetStringW( rec, 1, name );
1300 if (r != ERROR_SUCCESS)
1301 goto done;
1302
1303 r = MSI_RecordSetIStream( rec, 2, data );
1304 if (r != ERROR_SUCCESS)
1305 goto done;
1306
1307 r = MSI_DatabaseOpenViewW( db, L"INSERT INTO `_Streams` (`Name`,`Data`) VALUES (?,?)", &query );
1308 if (r != ERROR_SUCCESS)
1309 goto done;
1310
1311 r = MSI_ViewExecute( query, rec );
1312 msiobj_release( &query->hdr );
1313 if (r == ERROR_SUCCESS)
1314 goto done;
1315
1316 msiobj_release( &rec->hdr );
1317 if (!(rec = MSI_CreateRecord( 2 )))
1318 return ERROR_OUTOFMEMORY;
1319
1320 r = MSI_RecordSetIStream( rec, 1, data );
1321 if (r != ERROR_SUCCESS)
1322 goto done;
1323
1324 r = MSI_RecordSetStringW( rec, 2, name );
1325 if (r != ERROR_SUCCESS)
1326 goto done;
1327
1328 r = MSI_DatabaseOpenViewW( db, L"UPDATE `_Streams` SET `Data` = ? WHERE `Name` = ?", &query );
1329 if (r != ERROR_SUCCESS)
1330 goto done;
1331
1332 r = MSI_ViewExecute( query, rec );
1333 msiobj_release( &query->hdr );
1334
1335done:
1336 msiobj_release( &rec->hdr );
1337 return r;
1338}
#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_RecordSetIStream(MSIRECORD *, UINT, IStream *) DECLSPEC_HIDDEN
Definition: record.c:836
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **) DECLSPEC_HIDDEN
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
UINT MSI_ViewExecute(MSIQUERY *, MSIRECORD *) DECLSPEC_HIDDEN
Definition: msiquery.c:502
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 MSICOLUMNINFO col,
UINT  bytes_per_strref 
)
inlinestatic

Definition at line 87 of file table.c.

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

Referenced by get_stream_name(), msi_get_transform_record(), msi_table_get_row_size(), msi_table_load_transform(), read_table_from_storage(), save_table(), table_calc_column_offsets(), TABLE_fetch_int(), and table_set_bytes().

◆ compare_record()

static int compare_record ( MSITABLEVIEW tv,
UINT  row,
MSIRECORD rec 
)
static

Definition at line 1648 of file table.c.

1649{
1650 UINT r, i, ivalue, x;
1651
1652 for (i = 0; i < tv->num_cols; i++ )
1653 {
1654 if (!(tv->columns[i].type & MSITYPE_KEY)) continue;
1655
1656 r = get_table_value_from_record( tv, rec, i + 1, &ivalue );
1657 if (r != ERROR_SUCCESS)
1658 return 1;
1659
1660 r = TABLE_fetch_int( &tv->view, row, i + 1, &x );
1661 if (r != ERROR_SUCCESS)
1662 {
1663 WARN("TABLE_fetch_int should not fail here %u\n", r);
1664 return -1;
1665 }
1666 if (ivalue > x)
1667 {
1668 return 1;
1669 }
1670 else if (ivalue == x)
1671 {
1672 if (i < tv->num_cols - 1) continue;
1673 return 0;
1674 }
1675 else
1676 return -1;
1677 }
1678 return 1;
1679}
#define WARN(fmt,...)
Definition: debug.h:112
static UINT TABLE_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: table.c:1005
static UINT get_table_value_from_record(MSITABLEVIEW *tv, MSIRECORD *rec, UINT iField, UINT *pvalue)
Definition: table.c:1356
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
MSICOLUMNINFO * columns
Definition: table.c:999
MSIVIEW view
Definition: table.c:996
UINT num_cols
Definition: table.c:1000

Referenced by find_insert_index().

◆ create_key_string()

static WCHAR * create_key_string ( MSITABLEVIEW tv,
MSIRECORD rec 
)
static

Definition at line 2231 of file table.c.

2232{
2233 DWORD i, p, len, key_len = 0;
2234 WCHAR *key;
2235
2236 for (i = 0; i < tv->num_cols; i++)
2237 {
2238 if (!(tv->columns[i].type & MSITYPE_KEY))
2239 continue;
2240 if (MSI_RecordGetStringW( rec, i+1, NULL, &len ) == ERROR_SUCCESS)
2241 key_len += len;
2242 key_len++;
2243 }
2244
2245 key = msi_alloc( key_len * sizeof(WCHAR) );
2246 if(!key)
2247 return NULL;
2248
2249 p = 0;
2250 for (i = 0; i < tv->num_cols; i++)
2251 {
2252 if (!(tv->columns[i].type & MSITYPE_KEY))
2253 continue;
2254 if (p)
2255 key[p++] = '\t';
2256 len = key_len - p;
2257 if (MSI_RecordGetStringW( rec, i+1, key + p, &len ) == ERROR_SUCCESS)
2258 p += len;
2259 }
2260 return key;
2261}
#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) DECLSPEC_HIDDEN
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
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 178 of file table.c.

179{
180 WCHAR ch;
181 DWORD count = 0;
182
183 while ( (ch = *in++) )
184 {
185 if( (ch >= 0x3800 ) && (ch < 0x4840 ) )
186 {
187 if( ch >= 0x4800 )
188 ch = mime2utf(ch-0x4800);
189 else
190 {
191 ch -= 0x3800;
192 *out++ = mime2utf(ch&0x3f);
193 count++;
194 ch = mime2utf((ch>>6)&0x3f);
195 }
196 }
197 *out++ = ch;
198 count++;
199 }
200 *out = 0;
201 return count;
202}
static int mime2utf(int x)
Definition: table.c:165
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 3066 of file table.c.

3067{
3068 UINT i;
3069 for (i = 0; i < rawsize / 2; i++)
3070 {
3071 int len;
3072 const WCHAR *sval = msi_string_lookup( st, rawdata[i], &len );
3073 MESSAGE(" %04x %s\n", rawdata[i], debugstr_wn(sval, len) );
3074 }
3075}
#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) DECLSPEC_HIDDEN
Definition: string.c:343

Referenced by msi_table_load_transform().

◆ encode_streamname()

LPWSTR encode_streamname ( BOOL  bTable,
LPCWSTR  in 
)

Definition at line 119 of file table.c.

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

Referenced by cabinet_open_stream(), msi_commit_streams(), msi_get_stream(), msi_record_encoded_stream_name(), read_stream_data(), STREAMS_delete_row(), and write_stream_data().

◆ enum_stream_names()

void enum_stream_names ( IStorage stg)

Definition at line 204 of file table.c.

205{
206 IEnumSTATSTG *stgenum = NULL;
207 HRESULT r;
208 STATSTG stat;
209 ULONG n, count;
210 WCHAR name[0x40];
211
212 r = IStorage_EnumElements( stg, 0, NULL, 0, &stgenum );
213 if( FAILED( r ) )
214 return;
215
216 n = 0;
217 while( 1 )
218 {
219 count = 0;
220 r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
221 if( FAILED( r ) || !count )
222 break;
223 decode_streamname( stat.pwcsName, name );
224 TRACE( "stream %2lu -> %s %s\n", n, debugstr_w(stat.pwcsName), debugstr_w(name) );
225 CoTaskMemFree( stat.pwcsName );
226 n++;
227 }
228
229 IEnumSTATSTG_Release( stgenum );
230}
#define stat
Definition: acwin.h:99
BOOL decode_streamname(LPCWSTR in, LPWSTR out)
Definition: table.c:178
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 481 of file table.c.

482{
483 MSITABLE *t;
484
486 if( !wcscmp( name, t->name ) )
487 return t;
488
489 return NULL;
490}
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 msi_update_table_columns().

◆ find_insert_index()

static int find_insert_index ( MSITABLEVIEW tv,
MSIRECORD rec 
)
static

Definition at line 1681 of file table.c.

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

Referenced by TABLE_insert_row().

◆ free_cached_tables()

void free_cached_tables ( MSIDATABASE db)

Definition at line 470 of file table.c.

471{
472 while( !list_empty( &db->tables ) )
473 {
475
476 list_remove( &t->entry );
477 free_table( t );
478 }
479}
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:362
Definition: list.h:15
#define LIST_ENTRY(type)
Definition: queue.h:175

Referenced by MSI_CloseDatabase().

◆ free_table()

static void free_table ( MSITABLE table)
static

Definition at line 362 of file table.c.

363{
364 UINT i;
365 for( i=0; i<table->row_count; i++ )
366 msi_free( table->data[i] );
367 msi_free( table->data );
368 msi_free( table->data_persistent );
369 msi_free_colinfo( table->colinfo, table->col_count );
370 msi_free( table->colinfo );
371 msi_free( table );
372}
static void msi_free_colinfo(MSICOLUMNINFO *colinfo, UINT count)
Definition: table.c:356
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,
LPCWSTR  name,
MSICOLUMNINFO colinfo,
UINT sz 
)
static

Definition at line 509 of file table.c.

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

Referenced by get_tablecolumns().

◆ get_stream_name()

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

Definition at line 1042 of file table.c.

1043{
1044 LPWSTR p, stname = NULL;
1045 UINT i, r, type, ival;
1046 DWORD len;
1047 LPCWSTR sval;
1048 MSIVIEW *view = (MSIVIEW *) tv;
1049
1050 TRACE("%p %d\n", tv, row);
1051
1052 len = lstrlenW( tv->name ) + 1;
1053 stname = msi_alloc( len*sizeof(WCHAR) );
1054 if ( !stname )
1055 {
1057 goto err;
1058 }
1059
1060 lstrcpyW( stname, tv->name );
1061
1062 for ( i = 0; i < tv->num_cols; i++ )
1063 {
1064 type = tv->columns[i].type;
1065 if ( type & MSITYPE_KEY )
1066 {
1067 WCHAR number[0x20];
1068
1069 r = TABLE_fetch_int( view, row, i+1, &ival );
1070 if ( r != ERROR_SUCCESS )
1071 goto err;
1072
1073 if ( tv->columns[i].type & MSITYPE_STRING )
1074 {
1075 sval = msi_string_lookup( tv->db->strings, ival, NULL );
1076 if ( !sval )
1077 {
1079 goto err;
1080 }
1081 }
1082 else
1083 {
1084 UINT n = bytes_per_column( tv->db, &tv->columns[i], LONG_STR_BYTES );
1085
1086 switch( n )
1087 {
1088 case 2:
1089 swprintf( number, ARRAY_SIZE(number), L"%d", ival-0x8000 );
1090 break;
1091 case 4:
1092 swprintf( number, ARRAY_SIZE(number), L"%d", ival^0x80000000 );
1093 break;
1094 default:
1095 ERR( "oops - unknown column width %d\n", n );
1097 goto err;
1098 }
1099 sval = number;
1100 }
1101
1102 len += lstrlenW( L"." ) + lstrlenW( sval );
1103 p = msi_realloc ( stname, len*sizeof(WCHAR) );
1104 if ( !p )
1105 {
1107 goto err;
1108 }
1109 stname = p;
1110
1111 lstrcatW( stname, L"." );
1112 lstrcatW( stname, sval );
1113 }
1114 else
1115 continue;
1116 }
1117
1118 *pstname = stname;
1119 return ERROR_SUCCESS;
1120
1121err:
1122 msi_free( stname );
1123 *pstname = NULL;
1124 return r;
1125}
#define ARRAY_SIZE(A)
Definition: main.h:33
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define lstrcpyW
Definition: compat.h:749
static UINT bytes_per_column(MSIDATABASE *db, const MSICOLUMNINFO *col, UINT bytes_per_strref)
Definition: table.c:87
#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
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1154
#define LONG_STR_BYTES
Definition: msipriv.h:57
#define err(...)
string_table * strings
Definition: msipriv.h:110
MSIDATABASE * db
Definition: table.c:997
WCHAR name[1]
Definition: table.c:1002
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 573 of file table.c.

574{
576 UINT r;
577
578 /* first, see if the table is cached */
580 if (table)
581 {
582 *table_ret = table;
583 return ERROR_SUCCESS;
584 }
585
586 /* nonexistent tables should be interpreted as empty tables */
587 table = msi_alloc( sizeof(MSITABLE) + lstrlenW( name ) * sizeof(WCHAR) );
588 if (!table)
590
591 table->row_count = 0;
592 table->data = NULL;
593 table->data_persistent = NULL;
594 table->colinfo = NULL;
595 table->col_count = 0;
596 table->persistent = MSICONDITION_TRUE;
597 lstrcpyW( table->name, name );
598
599 if (!wcscmp( name, L"_Tables" ) || !wcscmp( name, L"_Columns" ))
600 table->persistent = MSICONDITION_NONE;
601
602 r = table_get_column_info( db, name, &table->colinfo, &table->col_count );
603 if (r != ERROR_SUCCESS)
604 {
605 free_table( table );
606 return r;
607 }
609 if (r != ERROR_SUCCESS)
610 {
611 free_table( table );
612 return r;
613 }
614 list_add_head( &db->tables, &table->entry );
615 *table_ret = table;
616 return ERROR_SUCCESS;
617}
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:481
static UINT table_get_column_info(MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO **pcols, UINT *pcount)
Definition: table.c:540
static UINT read_table_from_storage(MSIDATABASE *db, MSITABLE *t, IStorage *stg)
Definition: table.c:392
@ 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 ( MSITABLEVIEW tv,
MSIRECORD rec,
UINT  iField,
UINT pvalue 
)
static

Definition at line 1356 of file table.c.

1357{
1359 UINT r;
1360
1361 if (!iField || iField > tv->num_cols || MSI_RecordIsNull( rec, iField ))
1362 return ERROR_FUNCTION_FAILED;
1363
1364 columninfo = tv->columns[ iField - 1 ];
1365
1366 if ( MSITYPE_IS_BINARY(columninfo.type) )
1367 {
1368 *pvalue = 1; /* refers to the first key column */
1369 }
1370 else if ( columninfo.type & MSITYPE_STRING )
1371 {
1372 int len;
1373 const WCHAR *sval = msi_record_get_string( rec, iField, &len );
1374 if (sval)
1375 {
1376 r = msi_string2id( tv->db->strings, sval, len, pvalue );
1377 if (r != ERROR_SUCCESS)
1378 return ERROR_NOT_FOUND;
1379 }
1380 else *pvalue = 0;
1381 }
1382 else
1383 return int_to_table_storage( tv, iField, MSI_RecordGetInteger( rec, iField ), pvalue );
1384
1385 return ERROR_SUCCESS;
1386}
static UINT int_to_table_storage(const MSITABLEVIEW *tv, UINT col, int val, UINT *ret)
Definition: table.c:1194
UINT msi_string2id(const string_table *st, const WCHAR *data, int len, UINT *id) DECLSPEC_HIDDEN
Definition: string.c:400
const WCHAR * msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN
Definition: record.c:420
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
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,
LPCWSTR  szTableName,
MSICOLUMNINFO colinfo,
UINT sz 
)
static

Definition at line 629 of file table.c.

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

Referenced by table_get_column_info().

◆ int_to_table_storage()

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

Definition at line 1194 of file table.c.

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

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

◆ mime2utf()

static int mime2utf ( int  x)
static

Definition at line 165 of file table.c.

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

Referenced by decode_streamname().

◆ MSI_CommitTables()

UINT MSI_CommitTables ( MSIDATABASE db)

Definition at line 2887 of file table.c.

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

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

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

Referenced by MsiDatabaseIsTablePersistentW().

◆ msi_free_colinfo()

static void msi_free_colinfo ( MSICOLUMNINFO colinfo,
UINT  count 
)
static

Definition at line 356 of file table.c.

357{
358 UINT i;
359 for (i = 0; i < count; i++) msi_free( colinfo[i].hash_table );
360}

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

◆ msi_get_transform_record()

static MSIRECORD * msi_get_transform_record ( const MSITABLEVIEW tv,
const string_table st,
IStorage stg,
const BYTE rawdata,
UINT  bytes_per_strref 
)
static

Definition at line 2978 of file table.c.

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

Referenced by msi_table_load_transform().

◆ msi_record_encoded_stream_name()

static UINT msi_record_encoded_stream_name ( const MSITABLEVIEW tv,
MSIRECORD rec,
LPWSTR pstname 
)
static

Definition at line 2949 of file table.c.

2950{
2951 UINT r;
2952 DWORD len;
2953 WCHAR *name;
2954
2955 TRACE("%p %p\n", tv, rec);
2956
2957 r = msi_record_stream_name( tv, rec, NULL, &len );
2958 if (r != ERROR_SUCCESS)
2959 return r;
2960 len++;
2961
2962 name = msi_alloc( len * sizeof(WCHAR) );
2963 if (!name)
2964 return ERROR_OUTOFMEMORY;
2965
2966 r = msi_record_stream_name( tv, rec, name, &len );
2967 if (r != ERROR_SUCCESS)
2968 {
2969 msi_free( name );
2970 return r;
2971 }
2972
2973 *pstname = encode_streamname( FALSE, name );
2974 msi_free( name );
2975 return ERROR_SUCCESS;
2976}
LPWSTR encode_streamname(BOOL bTable, LPCWSTR in)
Definition: table.c:119
static UINT msi_record_stream_name(const MSITABLEVIEW *tv, MSIRECORD *rec, LPWSTR name, DWORD *len)
Definition: table.c:2263

Referenced by msi_get_transform_record().

◆ msi_record_stream_name()

static UINT msi_record_stream_name ( const MSITABLEVIEW tv,
MSIRECORD rec,
LPWSTR  name,
DWORD len 
)
static

Definition at line 2263 of file table.c.

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

Referenced by msi_record_encoded_stream_name(), and TransformView_set_row().

◆ msi_record_to_row()

static UINT * msi_record_to_row ( const MSITABLEVIEW tv,
MSIRECORD rec 
)
static

Definition at line 3077 of file table.c.

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

Referenced by msi_table_find_row().

◆ msi_refresh_record()

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

Definition at line 1818 of file table.c.

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

Referenced by TABLE_modify().

◆ msi_row_matches()

static UINT msi_row_matches ( MSITABLEVIEW tv,
UINT  row,
const UINT data,
UINT column 
)
static

Definition at line 3121 of file table.c.

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

Referenced by msi_table_find_row().

◆ msi_table_apply_transform()

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

Definition at line 3371 of file table.c.

3372{
3373 struct list transforms;
3374 IEnumSTATSTG *stgenum = NULL;
3376 TRANSFORMDATA *tables = NULL, *columns = NULL;
3377 HRESULT hr;
3378 STATSTG stat;
3381 UINT bytes_per_strref;
3382 BOOL property_update = FALSE;
3384
3385 TRACE("%p %p\n", db, stg );
3386
3387 strings = msi_load_string_table( stg, &bytes_per_strref );
3388 if( !strings )
3389 goto end;
3390
3391 hr = IStorage_EnumElements( stg, 0, NULL, 0, &stgenum );
3392 if (FAILED( hr ))
3393 goto end;
3394
3395 list_init(&transforms);
3396
3397 while ( TRUE )
3398 {
3399 MSITABLEVIEW *tv = NULL;
3400 WCHAR name[0x40];
3401 ULONG count = 0;
3402
3403 hr = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
3404 if (FAILED( hr ) || !count)
3405 break;
3406
3407 decode_streamname( stat.pwcsName, name );
3408 CoTaskMemFree( stat.pwcsName );
3409 if ( name[0] != 0x4840 )
3410 continue;
3411
3412 if ( !wcscmp( name+1, L"_StringPool" ) ||
3413 !wcscmp( name+1, L"_StringData" ) )
3414 continue;
3415
3417 if ( !transform )
3418 break;
3419
3420 list_add_tail( &transforms, &transform->entry );
3421
3422 transform->name = strdupW( name + 1 );
3423
3424 if ( !wcscmp( transform->name, L"_Tables" ) )
3425 tables = transform;
3426 else if (!wcscmp( transform->name, L"_Columns" ) )
3427 columns = transform;
3428 else if (!wcscmp( transform->name, L"Property" ))
3429 property_update = TRUE;
3430
3431 TRACE("transform contains stream %s\n", debugstr_w(name));
3432
3433 /* load the table */
3434 if (TABLE_CreateView( db, transform->name, (MSIVIEW**) &tv ) != ERROR_SUCCESS)
3435 continue;
3436
3437 if (tv->view.ops->execute( &tv->view, NULL ) != ERROR_SUCCESS)
3438 {
3439 tv->view.ops->delete( &tv->view );
3440 continue;
3441 }
3442
3443 tv->view.ops->delete( &tv->view );
3444 }
3445
3446 if (err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM)
3447 {
3448 static const WCHAR create_query[] = L"CREATE TABLE `_TransformView` ( "
3449 L"`Table` CHAR(0) NOT NULL TEMPORARY, `Column` CHAR(0) NOT NULL TEMPORARY, "
3450 L"`Row` CHAR(0) TEMPORARY, `Data` CHAR(0) TEMPORARY, `Current` CHAR(0) TEMPORARY "
3451 L"PRIMARY KEY `Table`, `Column`, `Row` ) HOLD";
3452
3453 MSIQUERY *query;
3454 UINT r;
3455
3457 if (r != ERROR_SUCCESS)
3458 goto end;
3459
3461 if (r == ERROR_SUCCESS)
3463 msiobj_release( &query->hdr );
3465 goto end;
3466
3467 if (TABLE_CreateView(db, L"_TransformView", &transform_view) != ERROR_SUCCESS)
3468 goto end;
3469
3471 transform_view->ops->add_ref( transform_view );
3472
3473 r = transform_view->ops->add_column( transform_view, L"new",
3474 MSITYPE_TEMPORARY | MSITYPE_NULLABLE | 0x402 /* INT */, FALSE );
3475 if (r != ERROR_SUCCESS)
3476 goto end;
3477 }
3478
3479 /*
3480 * Apply _Tables and _Columns transforms first so that
3481 * the table metadata is correct, and empty tables exist.
3482 */
3483 ret = msi_table_load_transform( db, stg, strings, tables, bytes_per_strref, err_cond );
3485 goto end;
3486
3487 ret = msi_table_load_transform( db, stg, strings, columns, bytes_per_strref, err_cond );
3489 goto end;
3490
3492
3493 while ( !list_empty( &transforms ) )
3494 {
3495 transform = LIST_ENTRY( list_head( &transforms ), TRANSFORMDATA, entry );
3496
3497 if ( wcscmp( transform->name, L"_Columns" ) &&
3498 wcscmp( transform->name, L"_Tables" ) &&
3499 ret == ERROR_SUCCESS )
3500 {
3501 ret = msi_table_load_transform( db, stg, strings, transform, bytes_per_strref, err_cond );
3502 }
3503
3504 list_remove( &transform->entry );
3505 msi_free( transform->name );
3507 }
3508
3509 if ( ret == ERROR_SUCCESS )
3510 {
3511 append_storage_to_db( db, stg );
3512 if (property_update) msi_clone_properties( db );
3513 }
3514
3515end:
3516 if ( stgenum )
3517 IEnumSTATSTG_Release( stgenum );
3518 if ( strings )
3520 if (transform_view)
3521 {
3522 struct tagMSITABLE *table = ((MSITABLEVIEW*)transform_view)->table;
3523
3524 if (ret != ERROR_SUCCESS)
3525 transform_view->ops->release( transform_view );
3526
3527 if (!wcscmp(table->colinfo[table->col_count - 1].colname, L"new"))
3528 TABLE_remove_column( transform_view, table->colinfo[table->col_count - 1].number );
3529 transform_view->ops->delete( transform_view );
3530 }
3531
3532 return ret;
3533}
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
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 msi_table_load_transform(MSIDATABASE *db, IStorage *stg, string_table *st, TRANSFORMDATA *transform, UINT bytes_per_strref, int err_cond)
Definition: table.c:3176
static UINT TABLE_remove_column(struct tagMSIVIEW *view, UINT number)
Definition: table.c:1935
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_ViewClose(MSIQUERY *) DECLSPEC_HIDDEN
Definition: msiquery.c:454
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
#define MSITYPE_TEMPORARY
Definition: msipriv.h:53
#define MSITYPE_NULLABLE
Definition: msipriv.h:51
VOID msi_destroy_stringtable(string_table *st) DECLSPEC_HIDDEN
Definition: string.c:107
string_table * msi_load_string_table(IStorage *stg, UINT *bytes_per_strref) DECLSPEC_HIDDEN
Definition: string.c:478
UINT msi_clone_properties(MSIDATABASE *) DECLSPEC_HIDDEN
Definition: package.c:382
@ MSITRANSFORM_ERROR_VIEWTRANSFORM
Definition: msiquery.h:156
static struct query * create_query(void)
Definition: pdh_main.c:152
#define ERROR_INVALID_TABLE
Definition: winerror.h:986

Referenced by apply_substorage_transform(), and MSI_DatabaseApplyTransformW().

◆ msi_table_assign()

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

Definition at line 1803 of file table.c.

1804{
1806 UINT r, row;
1807
1808 if (!tv->table)
1810
1811 r = msi_table_find_row(tv, rec, &row, NULL);
1812 if (r == ERROR_SUCCESS)
1813 return TABLE_set_row(view, row, rec, (1 << tv->num_cols) - 1);
1814 else
1815 return TABLE_insert_row( view, rec, -1, FALSE );
1816}
static UINT TABLE_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
Definition: table.c:1706
static UINT TABLE_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: table.c:1388
static UINT msi_table_find_row(MSITABLEVIEW *tv, MSIRECORD *rec, UINT *row, UINT *column)
Definition: table.c:3150

Referenced by TABLE_modify().

◆ msi_table_find_row()

static UINT msi_table_find_row ( MSITABLEVIEW tv,
MSIRECORD rec,
UINT row,
UINT column 
)
static

Definition at line 3150 of file table.c.

3151{
3153
3154 data = msi_record_to_row( tv, rec );
3155 if( !data )
3156 return r;
3157 for( i = 0; i < tv->table->row_count; i++ )
3158 {
3159 r = msi_row_matches( tv, i, data, column );
3160 if( r == ERROR_SUCCESS )
3161 {
3162 *row = i;
3163 break;
3164 }
3165 }
3166 msi_free( data );
3167 return r;
3168}
static UINT msi_row_matches(MSITABLEVIEW *tv, UINT row, const UINT *data, UINT *column)
Definition: table.c:3121
static UINT * msi_record_to_row(const MSITABLEVIEW *tv, MSIRECORD *rec)
Definition: table.c:3077

Referenced by msi_table_assign(), msi_table_load_transform(), msi_table_update(), TABLE_drop(), TABLE_modify(), TABLE_remove_column(), and table_validate_new().

◆ msi_table_get_row_size()

static UINT msi_table_get_row_size ( MSIDATABASE db,
const MSICOLUMNINFO cols,
UINT  count,
UINT  bytes_per_strref 
)
static

Definition at line 374 of file table.c.

375{
376 const MSICOLUMNINFO *last_col;
377
378 if (!count)
379 return 0;
380
381 if (bytes_per_strref != LONG_STR_BYTES)
382 {
383 UINT i, size = 0;
384 for (i = 0; i < count; i++) size += bytes_per_column( db, &cols[i], bytes_per_strref );
385 return size;
386 }
387 last_col = &cols[count - 1];
388 return last_col->offset + bytes_per_column( db, last_col, bytes_per_strref );
389}
GLsizeiptr size
Definition: glext.h:5919

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

◆ msi_table_load_transform()

static UINT msi_table_load_transform ( MSIDATABASE db,
IStorage stg,
string_table st,
TRANSFORMDATA transform,
UINT  bytes_per_strref,
int  err_cond 
)
static

Definition at line 3176 of file table.c.

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

Referenced by msi_table_apply_transform().

◆ msi_table_update()

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

Definition at line 1777 of file table.c.

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

Referenced by TABLE_modify().

◆ msi_update_table_columns()

static void msi_update_table_columns ( MSIDATABASE db,
LPCWSTR  name 
)
static

Definition at line 933 of file table.c.

934{
936 UINT size, offset, old_count;
937 UINT n;
938
939 if (!(table = find_cached_table( db, name ))) return;
940 old_count = table->col_count;
941 msi_free_colinfo( table->colinfo, table->col_count );
942 msi_free( table->colinfo );
943 table->colinfo = NULL;
944
945 table_get_column_info( db, name, &table->colinfo, &table->col_count );
946 if (!table->col_count) return;
947
948 size = msi_table_get_row_size( db, table->colinfo, table->col_count, LONG_STR_BYTES );
949 offset = table->colinfo[table->col_count - 1].offset;
950
951 for ( n = 0; n < table->row_count; n++ )
952 {
954 if (old_count < table->col_count)
955 memset( &table->data[n][offset], 0, size - offset );
956 }
957}
static UINT msi_table_get_row_size(MSIDATABASE *db, const MSICOLUMNINFO *cols, UINT count, UINT bytes_per_strref)
Definition: table.c:374
GLintptr offset
Definition: glext.h:5920

Referenced by msi_table_load_transform(), and TABLE_remove_column().

◆ read_raw_int()

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

Definition at line 2939 of file table.c.

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

Referenced by msi_get_transform_record().

◆ read_stream_data()

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

Definition at line 232 of file table.c.

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

Referenced by msi_table_load_transform(), and read_table_from_storage().

◆ read_table_from_storage()

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

Definition at line 392 of file table.c.

393{
394 BYTE *rawdata = NULL;
395 UINT rawsize = 0, i, j, row_size, row_size_mem;
396
397 TRACE("%s\n",debugstr_w(t->name));
398
399 row_size = msi_table_get_row_size( db, t->colinfo, t->col_count, db->bytes_per_strref );
400 row_size_mem = msi_table_get_row_size( db, t->colinfo, t->col_count, LONG_STR_BYTES );
401
402 /* if we can't read the table, just assume that it's empty */
403 read_stream_data( stg, t->name, TRUE, &rawdata, &rawsize );
404 if( !rawdata )
405 return ERROR_SUCCESS;
406
407 TRACE("Read %d bytes\n", rawsize );
408
409 if( rawsize % row_size )
410 {
411 WARN("Table size is invalid %d/%d\n", rawsize, row_size );
412 goto err;
413 }
414
415 if ((t->row_count = rawsize / row_size))
416 {
417 if (!(t->data = msi_alloc_zero( t->row_count * sizeof(USHORT *) ))) goto err;
418 if (!(t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL) ))) goto err;
419 }
420
421 /* transpose all the data */
422 TRACE("Transposing data from %d rows\n", t->row_count );
423 for (i = 0; i < t->row_count; i++)
424 {
425 UINT ofs = 0, ofs_mem = 0;
426
427 t->data[i] = msi_alloc( row_size_mem );
428 if( !t->data[i] )
429 goto err;
430 t->data_persistent[i] = TRUE;
431
432 for (j = 0; j < t->col_count; j++)
433 {
434 UINT m = bytes_per_column( db, &t->colinfo[j], LONG_STR_BYTES );
435 UINT n = bytes_per_column( db, &t->colinfo[j], db->bytes_per_strref );
436 UINT k;
437
438 if ( n != 2 && n != 3 && n != 4 )
439 {
440 ERR("oops - unknown column width %d\n", n);
441 goto err;
442 }
443 if (t->colinfo[j].type & MSITYPE_STRING && n < m)
444 {
445 for (k = 0; k < m; k++)
446 {
447 if (k < n)
448 t->data[i][ofs_mem + k] = rawdata[ofs * t->row_count + i * n + k];
449 else
450 t->data[i][ofs_mem + k] = 0;
451 }
452 }
453 else
454 {
455 for (k = 0; k < n; k++)
456 t->data[i][ofs_mem + k] = rawdata[ofs * t->row_count + i * n + k];
457 }
458 ofs_mem += m;
459 ofs += n;
460 }
461 }
462
463 msi_free( rawdata );
464 return ERROR_SUCCESS;
465err:
466 msi_free( rawdata );
468}
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

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 619 of file table.c.

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

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

◆ save_table()

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

Definition at line 858 of file table.c.

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

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 2023 of file table.c.

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

◆ TABLE_add_ref()

static UINT TABLE_add_ref ( struct tagMSIVIEW view)
static

Definition at line 1927 of file table.c.

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

Referenced by TABLE_add_column().

◆ table_calc_column_offsets()

static void table_calc_column_offsets ( MSIDATABASE db,
MSICOLUMNINFO colinfo,
DWORD  count 
)
static

Definition at line 492 of file table.c.

493{
494 DWORD i;
495
496 for (i = 0; colinfo && i < count; i++)
497 {
498 assert( i + 1 == colinfo[i].number );
499 if (i) colinfo[i].offset = colinfo[i - 1].offset +
500 bytes_per_column( db, &colinfo[i - 1], LONG_STR_BYTES );
501 else colinfo[i].offset = 0;
502
503 TRACE("column %d is [%s] with type %08x ofs %d\n",
504 colinfo[i].number, debugstr_w(colinfo[i].colname),
505 colinfo[i].type, colinfo[i].offset);
506 }
507}
#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 1543 of file table.c.

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

◆ table_create_new_row()

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

Definition at line 1473 of file table.c.

1474{
1476 BYTE **p, *row;
1477 BOOL *b;
1478 UINT sz;
1479 BYTE ***data_ptr;
1480 BOOL **data_persist_ptr;
1481 UINT *row_count;
1482
1483 TRACE("%p %s\n", view, temporary ? "TRUE" : "FALSE");
1484
1485 if( !tv->table )
1487
1488 row = msi_alloc_zero( tv->row_size );
1489 if( !row )
1491
1492 row_count = &tv->table->row_count;
1493 data_ptr = &tv->table->data;
1494 data_persist_ptr = &tv->table->data_persistent;
1495 if (*num == -1)
1496 *num = tv->table->row_count;
1497
1498 sz = (*row_count + 1) * sizeof (BYTE*);
1499 if( *data_ptr )
1500 p = msi_realloc( *data_ptr, sz );
1501 else
1502 p = msi_alloc( sz );
1503 if( !p )
1504 {
1505 msi_free( row );
1507 }
1508
1509 sz = (*row_count + 1) * sizeof (BOOL);
1510 if( *data_persist_ptr )
1511 b = msi_realloc( *data_persist_ptr, sz );
1512 else
1513 b = msi_alloc( sz );
1514 if( !b )
1515 {
1516 msi_free( row );
1517 msi_free( p );
1519 }
1520
1521 *data_ptr = p;
1522 (*data_ptr)[*row_count] = row;
1523
1524 *data_persist_ptr = b;
1525 (*data_persist_ptr)[*row_count] = !temporary;
1526
1527 (*row_count)++;
1528
1529 return ERROR_SUCCESS;
1530}
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLuint GLuint num
Definition: glext.h:9618
#define b
Definition: ke_i.h:79
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 2189 of file table.c.

2190{
2191 MSITABLEVIEW *tv ;
2192 UINT r, sz;
2193
2194 TRACE("%p %s %p\n", db, debugstr_w(name), view );
2195
2196 if ( !wcscmp( name, L"_Streams" ) )
2197 return STREAMS_CreateView( db, view );
2198 else if ( !wcscmp( name, L"_Storages" ) )
2199 return STORAGES_CreateView( db, view );
2200
2201 sz = FIELD_OFFSET( MSITABLEVIEW, name[lstrlenW( name ) + 1] );
2202 tv = msi_alloc_zero( sz );
2203 if( !tv )
2204 return ERROR_FUNCTION_FAILED;
2205
2206 r = get_table( db, name, &tv->table );
2207 if( r != ERROR_SUCCESS )
2208 {
2209 msi_free( tv );
2210 WARN("table not found\n");
2211 return r;
2212 }
2213
2214 TRACE("table %p found with %d columns\n", tv->table, tv->table->col_count);
2215
2216 /* fill the structure */
2217 tv->view.ops = &table_ops;
2218 tv->db = db;
2219 tv->columns = tv->table->colinfo;
2220 tv->num_cols = tv->table->col_count;
2222
2223 TRACE("%s one row is %d bytes\n", debugstr_w(name), tv->row_size );
2224
2225 *view = (MSIVIEW*) tv;
2226 lstrcpyW( tv->name, name );
2227
2228 return ERROR_SUCCESS;
2229}
static const MSIVIEWOPS table_ops
Definition: table.c:2166
UINT STORAGES_CreateView(MSIDATABASE *db, MSIVIEW **view) DECLSPEC_HIDDEN
Definition: storages.c:515
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view) DECLSPEC_HIDDEN
Definition: streams.c:539
#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(), msi_table_load_transform(), TABLE_add_column(), TABLE_drop(), TABLE_remove_column(), TransformView_Create(), UPDATE_CreateView(), and WHERE_CreateView().

◆ TABLE_delete()

static UINT TABLE_delete ( struct tagMSIVIEW view)
static

Definition at line 1913 of file table.c.

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

Referenced by TABLE_release(), and TransformView_delete().

◆ TABLE_delete_row()

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

Definition at line 1739 of file table.c.

1740{
1743
1744 TRACE("%p %d\n", tv, row);
1745
1746 if ( !tv->table )
1748
1750 if ( r != ERROR_SUCCESS )
1751 return r;
1752
1753 if ( row >= num_rows )
1754 return ERROR_FUNCTION_FAILED;
1755
1756 num_rows = tv->table->row_count;
1757 tv->table->row_count--;
1758
1759 /* reset the hash tables */
1760 for (i = 0; i < tv->num_cols; i++)
1761 {
1762 msi_free( tv->columns[i].hash_table );
1763 tv->columns[i].hash_table = NULL;
1764 }
1765
1766 for (i = row + 1; i < num_rows; i++)
1767 {
1768 memcpy(tv->table->data[i - 1], tv->table->data[i], tv->row_size);
1769 tv->table->data_persistent[i - 1] = tv->table->data_persistent[i];
1770 }
1771
1772 msi_free(tv->table->data[num_rows - 1]);
1773
1774 return ERROR_SUCCESS;
1775}
static UINT TABLE_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: table.c:1550
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 2118 of file table.c.

2119{
2121 MSIVIEW *tables = NULL;
2122 MSIRECORD *rec = NULL;
2123 UINT r, row;
2124 INT i;
2125
2126 TRACE("dropping table %s\n", debugstr_w(tv->name));
2127
2128 for (i = tv->table->col_count - 1; i >= 0; i--)
2129 {
2131 if (r != ERROR_SUCCESS)
2132 return r;
2133 }
2134
2135 rec = MSI_CreateRecord(1);
2136 if (!rec)
2137 return ERROR_OUTOFMEMORY;
2138
2139 MSI_RecordSetStringW(rec, 1, tv->name);
2140
2141 r = TABLE_CreateView(tv->db, L"_Tables", &tables);
2142 if (r != ERROR_SUCCESS)
2143 {
2144 msiobj_release(&rec->hdr);
2145 return r;
2146 }
2147
2149 if (r != ERROR_SUCCESS)
2150 goto done;
2151
2153 if (r != ERROR_SUCCESS)
2154 goto done;
2155
2156 list_remove(&tv->table->entry);
2157 free_table(tv->table);
2158
2159done:
2160 msiobj_release(&rec->hdr);
2161 tables->ops->delete(tables);
2162
2163 return r;
2164}
static UINT TABLE_delete_row(struct tagMSIVIEW *view, UINT row)
Definition: table.c:1739
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 1532 of file table.c.

1533{
1535
1536 TRACE("%p %p\n", tv, record);
1537
1538 TRACE("There are %d columns\n", tv->num_cols );
1539
1540 return ERROR_SUCCESS;
1541}

◆ TABLE_Exists()

BOOL TABLE_Exists ( MSIDATABASE db,
LPCWSTR  name 
)

Definition at line 960 of file table.c.

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

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 1005 of file table.c.

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

Referenced by compare_record(), get_stream_name(), msi_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 1132 of file table.c.

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

Referenced by TransformView_fetch_stream().

◆ table_get_column_info()

static UINT table_get_column_info ( MSIDATABASE db,
LPCWSTR  name,
MSICOLUMNINFO **  pcols,
UINT pcount 
)
static

Definition at line 540 of file table.c.

541{
542 UINT r, column_count = 0;
543 MSICOLUMNINFO *columns;
544
545 /* get the number of columns in this table */
546 column_count = 0;
547 r = get_tablecolumns( db, name, NULL, &column_count );
548 if (r != ERROR_SUCCESS)
549 return r;
550
551 *pcount = column_count;
552
553 /* if there are no columns, there's no table */
554 if (!column_count)
556
557 TRACE("table %s found\n", debugstr_w(name));
558
559 columns = msi_alloc( column_count * sizeof(MSICOLUMNINFO) );
560 if (!columns)
562
563 r = get_tablecolumns( db, name, columns, &column_count );
564 if (r != ERROR_SUCCESS)
565 {
566 msi_free( columns );
568 }
569 *pcols = columns;
570 return r;
571}
static UINT get_tablecolumns(MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz)
Definition: table.c:629

Referenced by get_table(), and msi_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 1568 of file table.c.

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

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 1550 of file table.c.

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

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 1278 of file table.c.

1279{
1281
1282 if (!tv->table)
1284
1285 return msi_view_get_row(tv->db, view, row, rec);
1286}
UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:353

Referenced by msi_refresh_record().

◆ TABLE_insert_row()

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

Definition at line 1706 of file table.c.

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

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

◆ TABLE_modify()

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

Definition at line 1838 of file table.c.

1840{
1842 UINT r, frow, column;
1843
1844 TRACE("%p %d %p\n", view, eModifyMode, rec );
1845
1846 switch (eModifyMode)
1847 {
1848 case MSIMODIFY_DELETE:
1849 r = TABLE_delete_row( view, row );
1850 break;
1852 r = table_validate_new( tv, rec, &column );
1853 if (r != ERROR_SUCCESS)
1854 {
1858 }
1859 break;
1860
1861 case MSIMODIFY_INSERT:
1862 r = table_validate_new( tv, rec, NULL );
1863 if (r != ERROR_SUCCESS)
1864 break;
1865 r = TABLE_insert_row( view, rec, -1, FALSE );
1866 break;
1867
1869 r = table_validate_new( tv, rec, NULL );
1870 if (r != ERROR_SUCCESS)
1871 break;
1872 r = TABLE_insert_row( view, rec, -1, TRUE );
1873 break;
1874
1875 case MSIMODIFY_REFRESH:
1876 r = msi_refresh_record( view, rec, row );
1877 break;
1878
1879 case MSIMODIFY_UPDATE:
1880 r = msi_table_update( view, rec, row );
1881 break;
1882
1883 case MSIMODIFY_ASSIGN:
1884 r = msi_table_assign( view, rec );
1885 break;
1886
1887 case MSIMODIFY_MERGE:
1888 /* check row that matches this record */
1889 r = msi_table_find_row( tv, rec, &frow, &column );
1890 if (r != ERROR_SUCCESS)
1891 {
1892 r = table_validate_new( tv, rec, NULL );
1893 if (r == ERROR_SUCCESS)
1894 r = TABLE_insert_row( view, rec, -1, FALSE );
1895 }
1896 break;
1897
1898 case MSIMODIFY_REPLACE:
1899 case MSIMODIFY_VALIDATE:
1902 FIXME("%p %d %p - mode not implemented\n", view, eModifyMode, rec );
1904 break;
1905
1906 default:
1908 }
1909
1910 return r;
1911}
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
static UINT msi_table_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
Definition: table.c:1803
static UINT msi_refresh_record(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: table.c:1818
static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: table.c:1777
@ 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 1986 of file table.c.

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

◆ TABLE_remove_column()

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

Definition at line 1935 of file table.c.

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

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

◆ table_set_bytes()

static UINT table_set_bytes ( MSITABLEVIEW tv,
UINT  row,
UINT  col,
UINT  val 
)
static

Definition at line 1157 of file table.c.

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

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 1214 of file table.c.

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

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

Referenced by msi_table_assign(), msi_table_update(), and TABLE_insert_row().

◆ TABLE_set_stream()

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

Definition at line 1340 of file table.c.

1341{
1343 WCHAR *name;
1344 UINT r;
1345
1346 TRACE("row %u, col %u, stream %p.\n", row, col, stream);
1347
1348 if ((r = get_stream_name( tv, row - 1, &name )))
1349 return r;
1350
1351 r = add_stream( tv->db, name, stream );
1352 msi_free( name );
1353 return r;
1354}
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 1241 of file table.c.

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

◆ table_validate_new()

static UINT table_validate_new ( MSITABLEVIEW tv,
MSIRECORD rec,
UINT column 
)
static

Definition at line 1604 of file table.c.

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

Referenced by TABLE_insert_row(), and TABLE_modify().

◆ TransformView_add_column()

static UINT TransformView_add_column ( MSITABLEVIEW tv,
MSIRECORD rec 
)
static

Definition at line 2501 of file table.c.

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

2720{
2721 return ERROR_SUCCESS;
2722}

◆ TransformView_Create()

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

Definition at line 2766 of file table.c.

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

Referenced by msi_table_load_transform().

◆ TransformView_create_table()

static UINT TransformView_create_table ( MSITABLEVIEW tv,
MSIRECORD rec 
)
static

Definition at line 2466 of file table.c.

2467{
2468 static const WCHAR query_fmt[] =
2469 L"INSERT INTO `_TransformView` (`Table`, `Column`, `new`) VALUES ('%s', 'CREATE', 1)";
2470
2471 WCHAR buf[256], *query = buf;
2472 const WCHAR *name;
2473 MSIQUERY *q;
2474 int len;
2475 UINT r;
2476
2477 name = msi_record_get_string( rec, 1, &len );
2478 if (!name)
2480
2481 len = _snwprintf( NULL, 0, query_fmt, name ) + 1;
2482 if (len > ARRAY_SIZE(buf))
2483 {
2484 query = msi_alloc( len * sizeof(WCHAR) );
2485 if (!query)
2486 return ERROR_OUTOFMEMORY;
2487 }
2488 swprintf( query, len, query_fmt, name );
2489
2490 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2491 if (query != buf)
2492 msi_free( query );
2493 if (r != ERROR_SUCCESS)
2494 return r;
2495
2496 r = MSI_ViewExecute( q, NULL );
2497 msiobj_release( &q->hdr );
2498 return r;
2499}
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 2735 of file table.c.

2736{
2738 if (!tv->table || tv->columns != tv->table->colinfo)
2739 msi_free( tv->columns );
2740 return TABLE_delete( view );
2741}

◆ TransformView_delete_row()

static UINT TransformView_delete_row ( MSIVIEW view,
UINT  row 
)
static

Definition at line 2648 of file table.c.

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

◆ TransformView_drop_table()

static UINT TransformView_drop_table ( MSITABLEVIEW tv,
UINT  row 
)
static

Definition at line 2604 of file table.c.

2605{
2606 static const WCHAR query_pfx[] = L"I