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

Go to the source code of this file.

Classes

struct  column_hash_entry
 
struct  column_info
 
struct  tagMSITABLE
 
struct  table_view
 
struct  transform_data
 

Macros

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

Functions

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

Variables

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

Macro Definition Documentation

◆ COBJMACROS

#define COBJMACROS

Definition at line 24 of file table.c.

◆ MAX_STREAM_NAME

#define MAX_STREAM_NAME   0x1f

Definition at line 87 of file table.c.

◆ MSITABLE_HASH_TABLE_SIZE

#define MSITABLE_HASH_TABLE_SIZE   37

Definition at line 41 of file table.c.

Function Documentation

◆ add_stream()

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

Definition at line 1290 of file table.c.

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

Referenced by TABLE_set_row(), and TABLE_set_stream().

◆ bytes_per_column()

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

Definition at line 89 of file table.c.

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

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

◆ compare_record()

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

Definition at line 1650 of file table.c.

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

Referenced by find_insert_index().

◆ create_key_string()

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

Definition at line 2250 of file table.c.

2251{
2252 DWORD i, p, len, key_len = 0;
2253 WCHAR *key;
2254
2255 for (i = 0; i < tv->num_cols; i++)
2256 {
2257 if (!(tv->columns[i].type & MSITYPE_KEY))
2258 continue;
2259 if (MSI_RecordGetStringW( rec, i+1, NULL, &len ) == ERROR_SUCCESS)
2260 key_len += len;
2261 key_len++;
2262 }
2263
2264 key = malloc( key_len * sizeof(WCHAR) );
2265 if(!key)
2266 return NULL;
2267
2268 p = 0;
2269 for (i = 0; i < tv->num_cols; i++)
2270 {
2271 if (!(tv->columns[i].type & MSITYPE_KEY))
2272 continue;
2273 if (p)
2274 key[p++] = '\t';
2275 len = key_len - p;
2276 if (MSI_RecordGetStringW( rec, i+1, key + p, &len ) == ERROR_SUCCESS)
2277 p += len;
2278 }
2279 return key;
2280}
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
unsigned long DWORD
Definition: ntddk_ex.h:95
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD)
short WCHAR
Definition: pedump.c:58
Definition: copy.c:22

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

◆ decode_streamname()

BOOL decode_streamname ( LPCWSTR  in,
LPWSTR  out 
)

Definition at line 180 of file table.c.

181{
182 WCHAR ch;
183 DWORD count = 0;
184
185 while ( (ch = *in++) )
186 {
187 if( (ch >= 0x3800 ) && (ch < 0x4840 ) )
188 {
189 if( ch >= 0x4800 )
190 ch = mime2utf(ch-0x4800);
191 else
192 {
193 ch -= 0x3800;
194 *out++ = mime2utf(ch&0x3f);
195 count++;
196 ch = mime2utf((ch>>6)&0x3f);
197 }
198 }
199 *out++ = ch;
200 count++;
201 }
202 *out = 0;
203 return count;
204}
static int mime2utf(int x)
Definition: table.c:167
unsigned char ch[4][2]
Definition: console.c:118
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint in
Definition: glext.h:9616
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383

Referenced by admin_remove_cabinet_streams(), 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 3082 of file table.c.

3083{
3084 UINT i;
3085 for (i = 0; i < rawsize / 2; i++)
3086 {
3087 int len;
3088 const WCHAR *sval = msi_string_lookup( st, rawdata[i], &len );
3089 MESSAGE(" %04x %s\n", rawdata[i], debugstr_wn(sval, len) );
3090 }
3091}
#define debugstr_wn
Definition: kernel32.h:33
#define MESSAGE
Definition: options.h:86
const WCHAR * msi_string_lookup(const string_table *st, UINT id, int *len)
Definition: string.c:343

Referenced by table_load_transform().

◆ encode_streamname()

LPWSTR encode_streamname ( BOOL  bTable,
LPCWSTR  in 
)

Definition at line 121 of file table.c.

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

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

◆ enum_stream_names()

void enum_stream_names ( IStorage *  stg)

Definition at line 206 of file table.c.

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

Referenced by MSI_DatabaseApplyTransformW(), and MSI_OpenDatabaseW().

◆ find_cached_table()

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

Definition at line 483 of file table.c.

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

Referenced by get_table(), and update_table_columns().

◆ find_insert_index()

static int find_insert_index ( struct table_view *  tv,
MSIRECORD *  rec,
BOOL  temporary 
)
static

Definition at line 1683 of file table.c.

1684{
1685 int idx, c, low = 0, high = tv->table->row_count - 1;
1686
1687 TRACE("%p %p\n", tv, rec);
1688
1689 for (c = 0; c < tv->num_cols; c++)
1690 {
1691 UINT ival;
1692
1693 if (!(tv->columns[c].type & MSITYPE_KEY)) continue;
1694
1695 /* Add primary key string - its index affects row index. */
1696 if (tv->columns[c].type & MSITYPE_STRING &&
1697 (get_table_value_from_record( tv, rec, c + 1, &ival ) == ERROR_NOT_FOUND))
1698 {
1699 int len;
1700 const WCHAR *sval = msi_record_get_string( rec, c + 1, &len );
1701 msi_add_string( tv->db->strings, sval, len, !temporary );
1702 }
1703 break;
1704 }
1705
1706 while (low <= high)
1707 {
1708 idx = (low + high) / 2;
1709 c = compare_record( tv, idx, rec );
1710
1711 if (c < 0)
1712 high = idx - 1;
1713 else if (c > 0)
1714 low = idx + 1;
1715 else
1716 {
1717 TRACE("found %u\n", idx);
1718 return idx;
1719 }
1720 }
1721 TRACE("found %u\n", high + 1);
1722 return high + 1;
1723}
unsigned int idx
Definition: utils.c:40
static int compare_record(struct table_view *tv, UINT row, MSIRECORD *rec)
Definition: table.c:1650
const GLubyte * c
Definition: glext.h:8905
#define c
Definition: ke_i.h:80
const WCHAR * msi_record_get_string(const MSIRECORD *, UINT, int *)
Definition: record.c:420
int msi_add_string(string_table *st, const WCHAR *data, int len, BOOL persistent)
Definition: string.c:303
MSIDATABASE * db
Definition: table.c:999
MSITABLE * table
Definition: table.c:1000
string_table * strings
Definition: msipriv.h:110
UINT row_count
Definition: table.c:64
#define ERROR_NOT_FOUND
Definition: winerror.h:1014

Referenced by TABLE_insert_row().

◆ free_cached_tables()

void free_cached_tables ( MSIDATABASE *  db)

Definition at line 472 of file table.c.

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

Referenced by MSI_CloseDatabase().

◆ free_colinfo()

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

Definition at line 358 of file table.c.

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

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

◆ free_table()

static void free_table ( MSITABLE *  table)
static

Definition at line 364 of file table.c.

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

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

◆ get_defaulttablecolumns()

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

Definition at line 511 of file table.c.

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

Referenced by get_tablecolumns().

◆ get_stream_name()

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

Definition at line 1044 of file table.c.

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

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

◆ get_table()

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

Definition at line 575 of file table.c.

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

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

◆ get_table_value_from_record()

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

Definition at line 1358 of file table.c.

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

Referenced by compare_record(), find_insert_index(), and TABLE_set_row().

◆ get_tablecolumns()

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

Definition at line 631 of file table.c.

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

Referenced by table_get_column_info().

◆ get_transform_record()

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

Definition at line 2994 of file table.c.

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

Referenced by table_load_transform().

◆ int_to_table_storage()

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

Definition at line 1196 of file table.c.

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

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

◆ mime2utf()

static int mime2utf ( int  x)
static

Definition at line 167 of file table.c.

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

Referenced by decode_streamname().

◆ MSI_CommitTables()

UINT MSI_CommitTables ( MSIDATABASE *  db)

Definition at line 2903 of file table.c.

2904{
2905 UINT r, bytes_per_strref;
2906 HRESULT hr;
2907 MSITABLE *table = NULL;
2908
2909 TRACE("%p\n",db);
2910
2911 r = msi_save_string_table( db->strings, db->storage, &bytes_per_strref );
2912 if( r != ERROR_SUCCESS )
2913 {
2914 WARN("failed to save string table r=%08x\n",r);
2915 return r;
2916 }
2917
2919 {
2920 r = save_table( db, table, bytes_per_strref );
2921 if( r != ERROR_SUCCESS )
2922 {
2923 WARN("failed to save table %s (r=%08x)\n",
2924 debugstr_w(table->name), r);
2925 return r;
2926 }
2927 }
2928
2929 hr = IStorage_Commit( db->storage, 0 );
2930 if (FAILED( hr ))
2931 {
2932 WARN( "failed to commit changes %#lx\n", hr );
2934 }
2935 return r;
2936}
HRESULT hr
Definition: delayimp.cpp:582
static UINT save_table(MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref)
Definition: table.c:860
UINT msi_save_string_table(const string_table *st, IStorage *storage, UINT *bytes_per_strref)
Definition: string.c:564

Referenced by MsiDatabaseCommit().

◆ msi_create_table()

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

Definition at line 707 of file table.c.

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

Referenced by CREATE_execute().

◆ MSI_DatabaseIsTablePersistent()

MSICONDITION MSI_DatabaseIsTablePersistent ( MSIDATABASE *  db,
LPCWSTR  table 
)

Definition at line 2938 of file table.c.

2939{
2940 MSITABLE *t;
2941 UINT r;
2942
2943 TRACE("%p %s\n", db, debugstr_w(table));
2944
2945 if (!table)
2946 return MSICONDITION_ERROR;
2947
2948 r = get_table( db, table, &t );
2949 if (r != ERROR_SUCCESS)
2950 return MSICONDITION_NONE;
2951
2952 return t->persistent;
2953}
@ MSICONDITION_ERROR
Definition: msiquery.h:29

Referenced by MsiDatabaseIsTablePersistentW().

◆ msi_table_apply_transform()

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

Definition at line 3385 of file table.c.

3386{
3387 struct list transforms;
3388 IEnumSTATSTG *stgenum = NULL;
3389 struct transform_data *transform;
3390 struct transform_data *tables = NULL, *columns = NULL;
3391 HRESULT hr;
3392 STATSTG stat;
3395 UINT bytes_per_strref;
3396 BOOL property_update = FALSE;
3397 MSIVIEW *transform_view = NULL;
3398
3399 TRACE("%p %p\n", db, stg );
3400
3401 strings = msi_load_string_table( stg, &bytes_per_strref );
3402 if( !strings )
3403 goto end;
3404
3405 hr = IStorage_EnumElements( stg, 0, NULL, 0, &stgenum );
3406 if (FAILED( hr ))
3407 goto end;
3408
3409 list_init(&transforms);
3410
3411 while ( TRUE )
3412 {
3413 struct table_view *tv = NULL;
3414 WCHAR name[0x40];
3415 ULONG count = 0;
3416
3417 hr = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
3418 if (FAILED( hr ) || !count)
3419 break;
3420
3421 decode_streamname( stat.pwcsName, name );
3422 CoTaskMemFree( stat.pwcsName );
3423 if ( name[0] != 0x4840 )
3424 continue;
3425
3426 if ( !wcscmp( name+1, L"_StringPool" ) ||
3427 !wcscmp( name+1, L"_StringData" ) )
3428 continue;
3429
3430 transform = calloc( 1, sizeof(*transform) );
3431 if ( !transform )
3432 break;
3433
3434 list_add_tail( &transforms, &transform->entry );
3435
3436 transform->name = wcsdup( name + 1 );
3437
3438 if ( !wcscmp( transform->name, L"_Tables" ) )
3439 tables = transform;
3440 else if (!wcscmp( transform->name, L"_Columns" ) )
3442 else if (!wcscmp( transform->name, L"Property" ))
3443 property_update = TRUE;
3444
3445 TRACE("transform contains stream %s\n", debugstr_w(name));
3446
3447 /* load the table */
3448 if (TABLE_CreateView( db, transform->name, (MSIVIEW**) &tv ) != ERROR_SUCCESS)
3449 continue;
3450
3451 if (tv->view.ops->execute( &tv->view, NULL ) != ERROR_SUCCESS)
3452 {
3453 tv->view.ops->delete( &tv->view );
3454 continue;
3455 }
3456
3457 tv->view.ops->delete( &tv->view );
3458 }
3459
3460 if (err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM)
3461 {
3462 static const WCHAR create_query[] = L"CREATE TABLE `_TransformView` ( "
3463 L"`Table` CHAR(0) NOT NULL TEMPORARY, `Column` CHAR(0) NOT NULL TEMPORARY, "
3464 L"`Row` CHAR(0) TEMPORARY, `Data` CHAR(0) TEMPORARY, `Current` CHAR(0) TEMPORARY "
3465 L"PRIMARY KEY `Table`, `Column`, `Row` ) HOLD";
3466
3467 MSIQUERY *query;
3468 UINT r;
3469
3471 if (r != ERROR_SUCCESS)
3472 goto end;
3473
3475 if (r == ERROR_SUCCESS)
3477 msiobj_release( &query->hdr );
3479 goto end;
3480
3481 if (TABLE_CreateView(db, L"_TransformView", &transform_view) != ERROR_SUCCESS)
3482 goto end;
3483
3485 transform_view->ops->add_ref( transform_view );
3486
3487 r = transform_view->ops->add_column( transform_view, L"new",
3488 MSITYPE_TEMPORARY | MSITYPE_NULLABLE | 0x402 /* INT */, FALSE );
3489 if (r != ERROR_SUCCESS)
3490 goto end;
3491 }
3492
3493 /*
3494 * Apply _Tables and _Columns transforms first so that
3495 * the table metadata is correct, and empty tables exist.
3496 */
3497 ret = table_load_transform( db, stg, strings, tables, bytes_per_strref, err_cond );
3499 goto end;
3500
3501 ret = table_load_transform( db, stg, strings, columns, bytes_per_strref, err_cond );
3503 goto end;
3504
3506
3507 while ( !list_empty( &transforms ) )
3508 {
3509 transform = LIST_ENTRY( list_head( &transforms ), struct transform_data, entry );
3510
3511 if ( wcscmp( transform->name, L"_Columns" ) &&
3512 wcscmp( transform->name, L"_Tables" ) &&
3513 ret == ERROR_SUCCESS )
3514 {
3515 ret = table_load_transform( db, stg, strings, transform, bytes_per_strref, err_cond );
3516 }
3517
3518 list_remove( &transform->entry );
3519 free( transform->name );
3520 free( transform );
3521 }
3522
3523 if ( ret == ERROR_SUCCESS )
3524 {
3525 append_storage_to_db( db, stg );
3526 if (property_update) msi_clone_properties( db );
3527 }
3528
3529end:
3530 if ( stgenum )
3531 IEnumSTATSTG_Release( stgenum );
3532 if ( strings )
3534 if (transform_view)
3535 {
3536 struct tagMSITABLE *table = ((struct table_view *)transform_view)->table;
3537
3538 if (ret != ERROR_SUCCESS)
3539 transform_view->ops->release( transform_view );
3540
3541 if (!wcscmp(table->colinfo[table->col_count - 1].colname, L"new"))
3542 TABLE_remove_column( transform_view, table->colinfo[table->col_count - 1].number );
3543 transform_view->ops->delete( transform_view );
3544 }
3545
3546 return ret;
3547}
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:39
#define TRUE
Definition: types.h:120
void append_storage_to_db(MSIDATABASE *db, IStorage *stg)
Definition: database.c:76
static UINT table_load_transform(MSIDATABASE *db, IStorage *stg, string_table *st, struct transform_data *transform, UINT bytes_per_strref, int err_cond)
Definition: table.c:3192
static UINT TABLE_remove_column(struct tagMSIVIEW *view, UINT number)
Definition: table.c:1954
static wchar_t * wcsdup(const wchar_t *str)
Definition: string.h:94
struct nls_table * tables
Definition: nls_base.c:22
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint GLuint end
Definition: gl.h:1545
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLsizei const GLchar *const * strings
Definition: glext.h:7622
UINT msi_clone_properties(MSIDATABASE *)
Definition: package.c:381
#define MSITYPE_TEMPORARY
Definition: msipriv.h:53
UINT MSI_ViewClose(MSIQUERY *)
Definition: msiquery.c:450
string_table * msi_load_string_table(IStorage *stg, UINT *bytes_per_strref)
Definition: string.c:478
#define MSITYPE_NULLABLE
Definition: msipriv.h:51
VOID msi_destroy_stringtable(string_table *st)
Definition: string.c:107
@ MSITRANSFORM_ERROR_VIEWTRANSFORM
Definition: msiquery.h:156
static struct query * create_query(void)
Definition: pdh_main.c:123
#define calloc
Definition: rosglue.h:14
UINT(* add_column)(struct tagMSIVIEW *view, LPCWSTR column, INT type, BOOL hold)
Definition: msipriv.h:339
UINT(* add_ref)(struct tagMSIVIEW *view)
Definition: msipriv.h:329
UINT(* release)(struct tagMSIVIEW *view)
Definition: msipriv.h:334
#define ERROR_INVALID_TABLE
Definition: winerror.h:1334

Referenced by apply_substorage_transform(), and MSI_DatabaseApplyTransformW().

◆ read_raw_int()

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

Definition at line 2955 of file table.c.

2956{
2957 UINT ret = 0, i;
2958
2959 for (i = 0; i < bytes; i++)
2960 ret += (data[col + i] << i * 8);
2961
2962 return ret;
2963}
static unsigned char bytes[4]
Definition: adnsresfilter.c:74

Referenced by get_transform_record().

◆ read_stream_data()

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

Definition at line 234 of file table.c.

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

Referenced by read_table_from_storage(), and table_load_transform().

◆ read_table_from_storage()

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

Definition at line 394 of file table.c.

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

Referenced by get_table().

◆ read_table_int()

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

Definition at line 621 of file table.c.

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

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

◆ record_encoded_stream_name()

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

Definition at line 2965 of file table.c.

2966{
2967 UINT r;
2968 DWORD len;
2969 WCHAR *name;
2970
2971 TRACE("%p %p\n", tv, rec);
2972
2973 r = record_stream_name( tv, rec, NULL, &len );
2974 if (r != ERROR_SUCCESS)
2975 return r;
2976 len++;
2977
2978 name = malloc( len * sizeof(WCHAR) );
2979 if (!name)
2980 return ERROR_OUTOFMEMORY;
2981
2982 r = record_stream_name( tv, rec, name, &len );
2983 if (r != ERROR_SUCCESS)
2984 {
2985 free( name );
2986 return r;
2987 }
2988
2989 *pstname = encode_streamname( FALSE, name );
2990 free( name );
2991 return ERROR_SUCCESS;
2992}
static UINT record_stream_name(const struct table_view *tv, MSIRECORD *rec, WCHAR *name, DWORD *len)
Definition: table.c:2282

Referenced by get_transform_record().

◆ record_stream_name()

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

Definition at line 2282 of file table.c.

2283{
2284 UINT p = 0, i, r;
2285 DWORD l;
2286
2287 l = wcslen( tv->name );
2288 if (name && *len > l)
2289 memcpy(name, tv->name, l * sizeof(WCHAR));
2290 p += l;
2291
2292 for ( i = 0; i < tv->num_cols; i++ )
2293 {
2294 if (!(tv->columns[i].type & MSITYPE_KEY))
2295 continue;
2296
2297 if (name && *len > p + 1)
2298 name[p] = '.';
2299 p++;
2300
2301 l = (*len > p ? *len - p : 0);
2302 r = MSI_RecordGetStringW( rec, i + 1, name ? name + p : NULL, &l );
2303 if (r != ERROR_SUCCESS)
2304 return r;
2305 p += l;
2306 }
2307
2308 if (name && *len > p)
2309 name[p] = 0;
2310
2311 *len = p;
2312 return ERROR_SUCCESS;
2313}
r l[0]
Definition: byte_order.h:168
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

Referenced by record_encoded_stream_name(), and TransformView_set_row().

◆ record_to_row()

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

Definition at line 3093 of file table.c.

3094{
3095 UINT i, r, *data;
3096
3097 data = malloc( tv->num_cols * sizeof (UINT) );
3098 for( i=0; i<tv->num_cols; i++ )
3099 {
3100 data[i] = 0;
3101
3102 if ( ~tv->columns[i].type & MSITYPE_KEY )
3103 continue;
3104
3105 /* turn the transform column value into a row value */
3106 if ( ( tv->columns[i].type & MSITYPE_STRING ) &&
3107 ! MSITYPE_IS_BINARY(tv->columns[i].type) )
3108 {
3109 int len;
3110 const WCHAR *str = msi_record_get_string( rec, i+1, &len );
3111 if (str)
3112 {
3113 r = msi_string2id( tv->db->strings, str, len, &data[i] );
3114
3115 /* if there's no matching string in the string table,
3116 these keys can't match any record, so fail now. */
3117 if (r != ERROR_SUCCESS)
3118 {
3119 free( data );
3120 return NULL;
3121 }
3122 }
3123 else data[i] = 0;
3124 }
3125 else
3126 {
3127 if (int_to_table_storage( tv, i + 1, MSI_RecordGetInteger( rec, i + 1 ), &data[i] ))
3128 {
3129 free( data );
3130 return NULL;
3131 }
3132 }
3133 }
3134 return data;
3135}
const WCHAR * str
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList

Referenced by table_find_row().

◆ refresh_record()

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

Definition at line 1837 of file table.c.

1838{
1839 MSIRECORD *curr;
1840 UINT r, i, count;
1841
1842 r = TABLE_get_row(view, row, &curr);
1843 if (r != ERROR_SUCCESS)
1844 return r;
1845
1846 /* Close the original record */
1847 MSI_CloseRecord(&rec->hdr);
1848
1850 for (i = 0; i < count; i++)
1851 MSI_RecordCopyField(curr, i + 1, rec, i + 1);
1852
1853 msiobj_release(&curr->hdr);
1854 return ERROR_SUCCESS;
1855}
static UINT TABLE_get_row(struct tagMSIVIEW *view, UINT row, MSIRECORD **rec)
Definition: table.c:1280
void MSI_CloseRecord(MSIOBJECTHDR *)
Definition: record.c:67
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT)
Definition: record.c:166
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec)
Definition: record.c:108

Referenced by TABLE_modify().

◆ row_matches()

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

Definition at line 3137 of file table.c.

3138{
3140
3141 for( i=0; i<tv->num_cols; i++ )
3142 {
3143 if ( ~tv->columns[i].type & MSITYPE_KEY )
3144 continue;
3145
3146 /* turn the transform column value into a row value */
3147 r = TABLE_fetch_int( &tv->view, row, i+1, &x );
3148 if ( r != ERROR_SUCCESS )
3149 {
3150 ERR("TABLE_fetch_int shouldn't fail here\n");
3151 break;
3152 }
3153
3154 /* if this key matches, move to the next column */
3155 if ( x != data[i] )
3156 {
3158 break;
3159 }
3160 if (column) *column = i;
3162 }
3163 return ret;
3164}

Referenced by table_find_row().

◆ save_table()

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

Definition at line 860 of file table.c.

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

Referenced by MSI_CommitTables().

◆ TABLE_add_column()

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

Definition at line 2042 of file table.c.

2044{
2045 UINT i, r, table_id, col_id, size, offset;
2046 BOOL temporary = type & MSITYPE_TEMPORARY;
2047 struct table_view *tv = (struct table_view *)view;
2048 struct column_info *colinfo;
2049
2050 if (temporary && !hold && !tv->table->ref_count)
2051 return ERROR_SUCCESS;
2052
2053 if (!temporary && tv->table->col_count &&
2054 tv->table->colinfo[tv->table->col_count-1].type & MSITYPE_TEMPORARY)
2056
2057 for (i = 0; i < tv->table->col_count; i++)
2058 {
2059 if (!wcscmp(tv->table->colinfo[i].colname, column))
2061 }
2062
2063 colinfo = realloc(tv->table->colinfo, sizeof(*tv->table->colinfo) * (tv->table->col_count + 1));
2064 if (!colinfo)
2065 return ERROR_OUTOFMEMORY;
2066 tv->table->colinfo = colinfo;
2067
2068 r = msi_string2id( tv->db->strings, tv->name, -1, &table_id );
2069 if (r != ERROR_SUCCESS)
2070 return r;
2071 col_id = msi_add_string( tv->db->strings, column, -1, !temporary );
2072
2073 colinfo[tv->table->col_count].tablename = msi_string_lookup( tv->db->strings, table_id, NULL );
2074 colinfo[tv->table->col_count].number = tv->table->col_count + 1;
2075 colinfo[tv->table->col_count].colname = msi_string_lookup( tv->db->strings, col_id, NULL );
2076 colinfo[tv->table->col_count].type = type;
2077 colinfo[tv->table->col_count].offset = 0;
2078 colinfo[tv->table->col_count].hash_table = NULL;
2079 tv->table->col_count++;
2080
2082
2084 offset = tv->table->colinfo[tv->table->col_count - 1].offset;
2085 for (i = 0; i < tv->table->row_count; i++)
2086 {
2087 BYTE *data = realloc(tv->table->data[i], size);
2088 if (!data)
2089 {
2090 tv->table->col_count--;
2091 return ERROR_OUTOFMEMORY;
2092 }
2093
2094 tv->table->data[i] = data;
2095 memset(data + offset, 0, size - offset);
2096 }
2097
2098 if (!temporary)
2099 {
2100 MSIVIEW *columns;
2101 MSIRECORD *rec;
2102
2103 rec = MSI_CreateRecord(4);
2104 if (!rec)
2105 {
2106 tv->table->col_count--;
2107 return ERROR_OUTOFMEMORY;
2108 }
2109
2110 MSI_RecordSetStringW(rec, 1, tv->name);
2111 MSI_RecordSetInteger(rec, 2, tv->table->col_count);
2113 MSI_RecordSetInteger(rec, 4, type);
2114
2115 r = TABLE_CreateView(tv->db, L"_Columns", &columns);
2116 if (r != ERROR_SUCCESS)
2117 {
2118 tv->table->col_count--;
2119 msiobj_release(&rec->hdr);
2120 return r;
2121 }
2122
2123 r = TABLE_insert_row(columns, rec, -1, FALSE);
2124 columns->ops->delete(columns);
2125 msiobj_release(&rec->hdr);
2126 if (r != ERROR_SUCCESS)
2127 {
2128 tv->table->col_count--;
2129 return r;
2130 }
2131 }
2132 if (hold)
2134 return ERROR_SUCCESS;
2135}
static UINT TABLE_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
Definition: table.c:1725
static UINT TABLE_add_ref(struct tagMSIVIEW *view)
Definition: table.c:1946
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
struct column_info * colinfo
Definition: table.c:66
BYTE ** data
Definition: table.c:62
LONG ref_count
Definition: table.c:69
UINT col_count
Definition: table.c:67

◆ TABLE_add_ref()

static UINT TABLE_add_ref ( struct tagMSIVIEW *  view)
static

Definition at line 1946 of file table.c.

1947{
1948 struct table_view *tv = (struct table_view *)view;
1949
1950 TRACE( "%p, %ld\n", view, tv->table->ref_count );
1951 return InterlockedIncrement(&tv->table->ref_count);
1952}
#define InterlockedIncrement
Definition: armddk.h:53

Referenced by TABLE_add_column().

◆ table_assign()

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

Definition at line 1822 of file table.c.

1823{
1824 struct table_view *tv = (struct table_view *)view;
1825 UINT r, row;
1826
1827 if (!tv->table)
1829
1830 r = table_find_row(tv, rec, &row, NULL);
1831 if (r == ERROR_SUCCESS)
1832 return TABLE_set_row(view, row, rec, (1 << tv->num_cols) - 1);
1833 else
1834 return TABLE_insert_row( view, rec, -1, FALSE );
1835}
static UINT TABLE_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: table.c:1390
static UINT table_find_row(struct table_view *, MSIRECORD *, UINT *, UINT *)
Definition: table.c:3166

Referenced by TABLE_modify().

◆ table_calc_column_offsets()

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

Definition at line 494 of file table.c.

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

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

◆ TABLE_close()

static UINT TABLE_close ( struct tagMSIVIEW *  view)
static

Definition at line 1545 of file table.c.

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

◆ table_create_new_row()

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

Definition at line 1475 of file table.c.

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

Referenced by TABLE_insert_row().

◆ TABLE_CreateView()

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

Definition at line 2208 of file table.c.

2209{
2210 struct table_view *tv ;
2211 UINT r, sz;
2212
2213 TRACE("%p %s %p\n", db, debugstr_w(name), view );
2214
2215 if ( !wcscmp( name, L"_Streams" ) )
2216 return STREAMS_CreateView( db, view );
2217 else if ( !wcscmp( name, L"_Storages" ) )
2218 return STORAGES_CreateView( db, view );
2219
2220 sz = FIELD_OFFSET( struct table_view, name[lstrlenW( name ) + 1] );
2221 tv = calloc( 1, sz );
2222 if( !tv )
2223 return ERROR_FUNCTION_FAILED;
2224
2225 r = get_table( db, name, &tv->table );
2226 if( r != ERROR_SUCCESS )
2227 {
2228 free( tv );
2229 WARN("table not found\n");
2230 return r;
2231 }
2232
2233 TRACE("table %p found with %d columns\n", tv->table, tv->table->col_count);
2234
2235 /* fill the structure */
2236 tv->view.ops = &table_ops;
2237 tv->db = db;
2238 tv->columns = tv->table->colinfo;
2239 tv->num_cols = tv->table->col_count;
2241
2242 TRACE("%s one row is %d bytes\n", debugstr_w(name), tv->row_size );
2243
2244 *view = (MSIVIEW*) tv;
2245 lstrcpyW( tv->name, name );
2246
2247 return ERROR_SUCCESS;
2248}
static const MSIVIEWOPS table_ops
Definition: table.c:2185
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
Definition: streams.c:539
UINT STORAGES_CreateView(MSIDATABASE *db, MSIVIEW **view)
Definition: storages.c:515
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

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

◆ TABLE_delete()

static UINT TABLE_delete ( struct tagMSIVIEW *  view)
static

Definition at line 1932 of file table.c.

1933{
1934 struct table_view *tv = (struct table_view *)view;
1935
1936 TRACE("%p\n", view );
1937
1938 tv->table = NULL;
1939 tv->columns = NULL;
1940
1941 free( tv );
1942
1943 return ERROR_SUCCESS;
1944}

Referenced by TABLE_release(), and TransformView_delete().

◆ TABLE_delete_row()

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

Definition at line 1758 of file table.c.

1759{
1760 struct table_view *tv = (struct table_view *)view;
1762
1763 TRACE("%p %d\n", tv, row);
1764
1765 if ( !tv->table )
1767
1769 if ( r != ERROR_SUCCESS )
1770 return r;
1771
1772 if ( row >= num_rows )
1773 return ERROR_FUNCTION_FAILED;
1774
1775 num_rows = tv->table->row_count;
1776 tv->table->row_count--;
1777
1778 /* reset the hash tables */
1779 for (i = 0; i < tv->num_cols; i++)
1780 {
1781 free(tv->columns[i].hash_table);
1782 tv->columns[i].hash_table = NULL;
1783 }
1784
1785 for (i = row + 1; i < num_rows; i++)
1786 {
1787 memcpy(tv->table->data[i - 1], tv->table->data[i], tv->row_size);
1788 tv->table->data_persistent[i - 1] = tv->table->data_persistent[i];
1789 }
1790
1791 free(tv->table->data[num_rows - 1]);
1792
1793 return ERROR_SUCCESS;
1794}
static UINT TABLE_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: table.c:1552
JSAMPARRAY int num_rows
Definition: jpegint.h:420

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

◆ TABLE_drop()

static UINT TABLE_drop ( struct tagMSIVIEW *  view)
static

Definition at line 2137 of file table.c.

2138{
2139 struct table_view *tv = (struct table_view *)view;
2140 MSIVIEW *tables = NULL;
2141 MSIRECORD *rec = NULL;
2142 UINT r, row;
2143 INT i;
2144
2145 TRACE("dropping table %s\n", debugstr_w(tv->name));
2146
2147 for (i = tv->table->col_count - 1; i >= 0; i--)
2148 {
2149 r = TABLE_remove_column(view, tv->table->colinfo[i].number);
2150 if (r != ERROR_SUCCESS)
2151 return r;
2152 }
2153
2154 rec = MSI_CreateRecord(1);
2155 if (!rec)
2156 return ERROR_OUTOFMEMORY;
2157
2158 MSI_RecordSetStringW(rec, 1, tv->name);
2159
2160 r = TABLE_CreateView(tv->db, L"_Tables", &tables);
2161 if (r != ERROR_SUCCESS)
2162 {
2163 msiobj_release(&rec->hdr);
2164 return r;
2165 }
2166
2167 r = table_find_row((struct table_view *)tables, rec, &row, NULL);
2168 if (r != ERROR_SUCCESS)
2169 goto done;
2170
2172 if (r != ERROR_SUCCESS)
2173 goto done;
2174
2175 list_remove(&tv->table->entry);
2176 free_table(tv->table);
2177
2178done:
2179 msiobj_release(&rec->hdr);
2180 tables->ops->delete(tables);
2181
2182 return r;
2183}
static UINT TABLE_delete_row(struct tagMSIVIEW *view, UINT row)
Definition: table.c:1758
struct list entry
Definition: table.c:65
int32_t INT
Definition: typedefs.h:58

◆ TABLE_execute()

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

Definition at line 1534 of file table.c.

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

◆ TABLE_Exists()

BOOL TABLE_Exists ( MSIDATABASE *  db,
LPCWSTR  name 
)

Definition at line 962 of file table.c.

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

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

◆ TABLE_fetch_int()

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

Definition at line 1007 of file table.c.

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

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

◆ TABLE_fetch_stream()

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

Definition at line 1134 of file table.c.

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

Referenced by TransformView_fetch_stream().

◆ table_find_row()

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

Definition at line 3166 of file table.c.

3167{
3169
3170 data = record_to_row( tv, rec );
3171 if( !data )
3172 return r;
3173 for( i = 0; i < tv->table->row_count; i++ )
3174 {
3175 r = row_matches( tv, i, data, column );
3176 if( r == ERROR_SUCCESS )
3177 {
3178 *row = i;
3179 break;
3180 }
3181 }
3182 free( data );
3183 return r;
3184}
static UINT * record_to_row(const struct table_view *tv, MSIRECORD *rec)
Definition: table.c:3093
static UINT row_matches(struct table_view *tv, UINT row, const UINT *data, UINT *column)
Definition: table.c:3137

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

◆ table_get_column_info()

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

Definition at line 542 of file table.c.

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

Referenced by get_table(), and update_table_columns().

◆ TABLE_get_column_info()

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

Definition at line 1570 of file table.c.

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

Referenced by TransformView_get_column_info().

◆ TABLE_get_dimensions()

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

Definition at line 1552 of file table.c.

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

Referenced by TABLE_delete_row(), and TransformView_get_dimensions().

◆ TABLE_get_row()

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

Definition at line 1280 of file table.c.

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

Referenced by refresh_record().

◆ table_get_row_size()

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

Definition at line 376 of file table.c.

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

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

◆ TABLE_insert_row()

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

Definition at line 1725 of file table.c.

1726{
1727 struct table_view *tv = (struct table_view *)view;
1728 UINT i, r;
1729
1730 TRACE("%p %p %s\n", tv, rec, temporary ? "TRUE" : "FALSE" );
1731
1732 /* check that the key is unique - can we find a matching row? */
1733 r = table_validate_new( tv, rec, NULL );
1734 if( r != ERROR_SUCCESS )
1735 return ERROR_FUNCTION_FAILED;
1736
1737 if (row == -1)
1738 row = find_insert_index( tv, rec, temporary );
1739
1740 r = table_create_new_row( view, &row, temporary );
1741 TRACE("insert_row returned %08x\n", r);
1742 if( r != ERROR_SUCCESS )
1743 return r;
1744
1745 /* shift the rows to make room for the new row */
1746 for (i = tv->table->row_count - 1; i > row; i--)
1747 {
1748 memmove(&(tv->table->data[i][0]),
1749 &(tv->table->data[i - 1][0]), tv->row_size);
1750 tv->table->data_persistent[i] = tv->table->data_persistent[i - 1];
1751 }
1752
1753 /* Re-set the persistence flag */
1754 tv->table->data_persistent[row] = !temporary;
1755 return TABLE_set_row( view, row, rec, (1<<tv->num_cols) - 1 );
1756}
static UINT table_validate_new(struct table_view *tv, MSIRECORD *rec, UINT *column)
Definition: table.c:1606
static UINT table_create_new_row(struct tagMSIVIEW *view, UINT *num, BOOL temporary)
Definition: table.c:1475
static int find_insert_index(struct table_view *tv, MSIRECORD *rec, BOOL temporary)
Definition: table.c:1683
#define memmove(s1, s2, n)
Definition: mkisofs.h:881

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

◆ table_load_transform()

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

Definition at line 3192 of file table.c.

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

Referenced by msi_table_apply_transform().

◆ TABLE_modify()

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

Definition at line 1857 of file table.c.

1859{
1860 struct table_view *tv = (struct table_view *)view;
1861 UINT r, frow, column;
1862
1863 TRACE("%p %d %p\n", view, eModifyMode, rec );
1864
1865 switch (eModifyMode)
1866 {
1867 case MSIMODIFY_DELETE:
1868 r = TABLE_delete_row( view, row );
1869 break;
1871 r = table_validate_new( tv, rec, &column );
1872 if (r != ERROR_SUCCESS)
1873 {
1875 tv->view.error_column = tv->columns[column].colname;
1877 }
1878 break;
1879
1880 case MSIMODIFY_INSERT:
1881 r = table_validate_new( tv, rec, NULL );
1882 if (r != ERROR_SUCCESS)
1883 break;
1884 r = TABLE_insert_row( view, rec, -1, FALSE );
1885 break;
1886
1888 r = table_validate_new( tv, rec, NULL );
1889 if (r != ERROR_SUCCESS)
1890 break;
1891 r = TABLE_insert_row( view, rec, -1, TRUE );
1892 break;
1893
1894 case MSIMODIFY_REFRESH:
1895 r = refresh_record( view, rec, row );
1896 break;
1897
1898 case MSIMODIFY_UPDATE:
1899 r = table_update( view, rec, row );
1900 break;
1901
1902 case MSIMODIFY_ASSIGN:
1903 r = table_assign( view, rec );
1904 break;
1905
1906 case MSIMODIFY_MERGE:
1907 /* check row that matches this record */
1908 r = table_find_row( tv, rec, &frow, &column );
1909 if (r != ERROR_SUCCESS)
1910 {
1911 r = table_validate_new( tv, rec, NULL );
1912 if (r == ERROR_SUCCESS)
1913 r = TABLE_insert_row( view, rec, -1, FALSE );
1914 }
1915 break;
1916
1917 case MSIMODIFY_REPLACE:
1918 case MSIMODIFY_VALIDATE:
1921 FIXME("%p %d %p - mode not implemented\n", view, eModifyMode, rec );
1923 break;
1924
1925 default:
1927 }
1928
1929 return r;
1930}
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
static UINT table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: table.c:1796
static UINT refresh_record(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: table.c:1837
static UINT table_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
Definition: table.c:1822
@ 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:238

◆ TABLE_release()

static UINT TABLE_release ( struct tagMSIVIEW *  view)
static

Definition at line 2005 of file table.c.

2006{
2007 struct table_view *tv = (struct table_view *)view;
2008 INT ref = tv->table->ref_count;
2009 UINT r;
2010 INT i;
2011
2012 TRACE("%p %d\n", view, ref);
2013
2015 if (ref == 0)
2016 {
2017 for (i = tv->table->col_count - 1; i >= 0; i--)
2018 {
2019 if (tv->table->colinfo[i].type & MSITYPE_TEMPORARY)
2020 {
2021 r = TABLE_remove_column(view, tv->table->colinfo[i].number);
2022 if (r != ERROR_SUCCESS)
2023 break;
2024 }
2025 else
2026 {
2027 break;
2028 }
2029 }
2030
2031 if (!tv->table->col_count)
2032 {
2033 list_remove(&tv->table->entry);
2034 free_table(tv->table);
2036 }
2037 }
2038
2039 return ref;
2040}
#define InterlockedDecrement
Definition: armddk.h:52
static UINT TABLE_delete(struct tagMSIVIEW *view)
Definition: table.c:1932
Definition: send.c:48

◆ TABLE_remove_column()

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

Definition at line 1954 of file table.c.

1955{
1956 struct table_view *tv = (struct table_view *)view;
1957 MSIRECORD *rec = NULL;
1958 MSIVIEW *columns = NULL;
1959 UINT row, r;
1960
1961 if (tv->table->col_count != number)
1963
1964 if (tv->table->colinfo[number-1].type & MSITYPE_TEMPORARY)
1965 {
1966 UINT size = tv->table->colinfo[number-1].offset;
1967 tv->table->col_count--;
1968 tv->table->colinfo = realloc(tv->table->colinfo, sizeof(*tv->table->colinfo) * tv->table->col_count);
1969
1970 for (row = 0; row < tv->table->row_count; row++)
1971 tv->table->data[row] = realloc(tv->table->data[row], size);
1972 return ERROR_SUCCESS;
1973 }
1974
1975 rec = MSI_CreateRecord(2);
1976 if (!rec)
1977 return ERROR_OUTOFMEMORY;
1978
1979 MSI_RecordSetStringW(rec, 1, tv->name);
1981
1982 r = TABLE_CreateView(tv->db, L"_Columns", &columns);
1983 if (r != ERROR_SUCCESS)
1984 {
1985 msiobj_release(&rec->hdr);
1986 return r;
1987 }
1988
1989 r = table_find_row((struct table_view *)columns, rec, &row, NULL);
1990 if (r != ERROR_SUCCESS)
1991 goto done;
1992
1994 if (r != ERROR_SUCCESS)
1995 goto done;
1996
1997 update_table_columns(tv->db, tv->name);
1998
1999done:
2000 msiobj_release(&rec->hdr);
2001 columns->ops->delete(columns);
2002 return r;
2003}

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

◆ table_set_bytes()

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

Definition at line 1159 of file table.c.

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

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

◆ TABLE_set_int()

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

Definition at line 1216 of file table.c.

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

◆ TABLE_set_row()

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

Definition at line 1390 of file table.c.

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

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

◆ TABLE_set_stream()

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

Definition at line 1342 of file table.c.

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

◆ TABLE_set_string()

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

Definition at line 1243 of file table.c.

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

◆ table_update()

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

Definition at line 1796 of file table.c.

1797{
1798 struct table_view *tv = (struct table_view *)view;
1799 UINT r, new_row;
1800
1801 /* FIXME: MsiViewFetch should set rec index 0 to some ID that
1802 * sets the fetched record apart from other records
1803 */
1804
1805 if (!tv->table)
1807
1808 r = table_find_row(tv, rec, &new_row, NULL);
1809 if (r != ERROR_SUCCESS)
1810 {
1811 ERR("can't find row to modify\n");
1812 return ERROR_FUNCTION_FAILED;
1813 }
1814
1815 /* the row cannot be changed */
1816 if (row != new_row)
1817 return ERROR_FUNCTION_FAILED;
1818
1819 return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1);
1820}

Referenced by TABLE_modify().

◆ table_validate_new()

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

Definition at line 1606 of file table.c.

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

Referenced by TABLE_insert_row(), and TABLE_modify().

◆ TransformView_add_column()

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

Definition at line 2520 of file table.c.

2521{
2522 static const WCHAR query_pfx[] =
2523 L"INSERT INTO `_TransformView` (`new`, `Table`, `Current`, `Column`, `Data`) VALUES (1, '";
2524
2525 WCHAR buf[256], *query = buf;
2526 UINT i, p, r, qlen;
2527 DWORD len;
2528 MSIQUERY *q;
2529
2530 qlen = p = wcslen( query_pfx );
2531 for (i = 1; i <= 4; i++)
2532 {
2533 r = MSI_RecordGetStringW( rec, i, NULL, &len );
2534 if (r != ERROR_SUCCESS)
2535 return r;
2536 qlen += len + 3; /* strlen( "','" ) */
2537 }
2538
2539 if (qlen > ARRAY_SIZE(buf))
2540 {
2541 query = malloc( len * sizeof(WCHAR) );
2542 qlen = len;
2543 if (!query)
2544 return ERROR_OUTOFMEMORY;
2545 }
2546
2547 memcpy( query, query_pfx, p * sizeof(WCHAR) );
2548 for (i = 1; i <= 4; i++)
2549 {
2550 len = qlen - p;
2551 MSI_RecordGetStringW( rec, i, query + p, &len );
2552 p += len;
2553 query[p++] = '\'';
2554 if (i != 4)
2555 {
2556 query[p++] = ',';
2557 query[p++] = '\'';
2558 }
2559 }
2560 query[p++] = ')';
2561 query[p++] = 0;
2562
2563 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2564 if (query != buf)
2565 free( query );
2566 if (r != ERROR_SUCCESS)
2567 return r;
2568
2569 r = MSI_ViewExecute( q, NULL );
2570 msiobj_release( &q->hdr );
2571 return r;
2572}
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 2738 of file table.c.

2739{
2740 return ERROR_SUCCESS;
2741}

◆ TransformView_Create()

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

Definition at line 2785 of file table.c.

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

Referenced by table_load_transform().

◆ TransformView_create_table()

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

Definition at line 2485 of file table.c.

2486{
2487 static const WCHAR query_fmt[] =
2488 L"INSERT INTO `_TransformView` (`Table`, `Column`, `new`) VALUES ('%s', 'CREATE', 1)";
2489
2490 WCHAR buf[256], *query = buf;
2491 const WCHAR *name;
2492 MSIQUERY *q;
2493 int len;
2494 UINT r;
2495
2496 name = msi_record_get_string( rec, 1, &len );
2497 if (!name)
2499
2500 len = _snwprintf( NULL, 0, query_fmt, name ) + 1;
2501 if (len > ARRAY_SIZE(buf))
2502 {
2503 query = malloc( len * sizeof(WCHAR) );
2504 if (!query)
2505 return ERROR_OUTOFMEMORY;
2506 }
2507 swprintf( query, len, query_fmt, name );
2508
2509 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2510 if (query != buf)
2511 free( query );
2512 if (r != ERROR_SUCCESS)
2513 return r;
2514
2515 r = MSI_ViewExecute( q, NULL );
2516 msiobj_release( &q->hdr );
2517 return r;
2518}
_ACRTIMP int __cdecl _snwprintf(wchar_t *, size_t, const wchar_t *,...)
Definition: wcs.c:1498
#define ERROR_INSTALL_TRANSFORM_FAILURE
Definition: winerror.h:1330

Referenced by TransformView_insert_row().

◆ TransformView_delete()

static UINT TransformView_delete ( MSIVIEW *  view)
static

Definition at line 2754 of file table.c.

2755{
2756 struct table_view *tv = (struct table_view *)view;
2757 if (!tv->table || tv->columns != tv->table->colinfo)
2758 free( tv->columns );
2759 return TABLE_delete( view );
2760}

◆ TransformView_delete_row()

static UINT TransformView_delete_row ( MSIVIEW *  view,
UINT  row 
)
static

Definition at line 2667 of file table.c.

2668{
2669 static const WCHAR query_pfx[] = L"INSERT INTO `_TransformView` ( `new`, `Table`, `Column`, `Row`) VALUES ( 1, '";
2670 static const WCHAR query_column[] = L"', 'DELETE', '";
2671 static const WCHAR query_sfx[] = L"')";
2672
2673 struct table_view *tv = (struct table_view *)view;
2674 WCHAR *key, buf[256], *query = buf;
2675 UINT r, len, name_len, key_len;
2676 MSIRECORD *rec;
2677 MSIQUERY *q;
2678
2679 if (!wcscmp( tv->name, L"_Columns" ))
2680 {
2681 ERR("trying to remove column\n");
2683 }
2684
2685 if (!wcscmp( tv->name, L"_Tables" ))
2686 return TransformView_drop_table( tv, row );
2687
2688 r = msi_view_get_row( tv->db, view, row, &rec );
2689 if (r != ERROR_SUCCESS)
2690 return r;
2691
2692 key = create_key_string( tv, rec );
2693 msiobj_release( &rec->hdr );
2694 if (!key)
2695 return ERROR_OUTOFMEMORY;
2696
2697 name_len = wcslen( tv->name );
2698 key_len = wcslen( key );
2699 len = ARRAY_SIZE(query_pfx) + name_len + ARRAY_SIZE(query_column) + key_len + ARRAY_SIZE(query_sfx) - 2;
2700 if (len > ARRAY_SIZE(buf))
2701 {
2702 query = malloc( len * sizeof(WCHAR) );
2703 if (!query)
2704 {
2705 free( tv );
2706 free( key );
2707 return ERROR_OUTOFMEMORY;
2708 }
2709 }
2710
2711 memcpy( query, query_pfx, ARRAY_SIZE(query_pfx) * sizeof(WCHAR) );
2712 len = ARRAY_SIZE(query_pfx) - 1;
2713 memcpy( query + len, tv->name, name_len * sizeof(WCHAR) );
2714 len += name_len;
2715 memcpy( query + len, query_column, ARRAY_SIZE(query_column) * sizeof(WCHAR) );
2716 len += ARRAY_SIZE(query_column) - 1;
2717 memcpy( query + len, key, key_len * sizeof(WCHAR) );
2718 len += key_len;
2719 memcpy( query + len, query_sfx, ARRAY_SIZE(query_sfx) * sizeof(WCHAR) );
2720 free( key );
2721
2722 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2723 if (query != buf)
2724 free( query );
2725 if (r != ERROR_SUCCESS)
2726 return r;
2727
2728 r = MSI_ViewExecute( q, NULL );
2729 msiobj_release( &q->hdr );
2730 return r;
2731}
static WCHAR * create_key_string(struct table_view *tv, MSIRECORD *rec)
Definition: table.c:2250
static UINT TransformView_drop_table(struct table_view *tv, UINT row)
Definition: table.c:2623

◆ TransformView_drop_table()

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

Definition at line 2623 of file table.c.

2624{
2625 static const WCHAR query_pfx[] = L"INSERT INTO `_TransformView` ( `new`, `Table`, `Column` ) VALUES ( 1, '";
2626 static const WCHAR query_sfx[] = L"', 'DROP' )";
2627
2628 WCHAR buf[256], *query = buf;
2629 UINT r, table_id, len;
2630 const WCHAR *table;
2631 int table_len;
2632 MSIQUERY *q;
2633
2634 r = TABLE_fetch_int( &tv->view, row, 1, &table_id );
2635 if (r != ERROR_SUCCESS)
2636 return r;
2637
2638 table = msi_string_lookup( tv->db->strings, table_id, &table_len );
2639 if (!table)
2641
2642 len = ARRAY_SIZE(query_pfx) - 1 + table_len + ARRAY_SIZE(query_sfx);
2643 if (len > ARRAY_SIZE(buf))
2644 {
2645 query = malloc( len * sizeof(WCHAR) );
2646 if (!query)
2647 return ERROR_OUTOFMEMORY;
2648 }
2649
2650 memcpy( query, query_pfx, ARRAY_SIZE(query_pfx) * sizeof(WCHAR) );
2651 len = ARRAY_SIZE(query_pfx) - 1;
2652 memcpy( query + len, table, table_len * sizeof(WCHAR) );
2653 len += table_len;
2654 memcpy( query + len, query_sfx, ARRAY_SIZE(query_sfx) * sizeof(WCHAR) );
2655
2656 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2657 if (query != buf)
2658 free( query );
2659 if (r != ERROR_SUCCESS)
2660 return r;
2661
2662 r = MSI_ViewExecute( q, NULL );
2663 msiobj_release( &q->hdr );
2664 return r;
2665}

Referenced by TransformView_delete_row().

◆ TransformView_execute()

static UINT TransformView_execute ( MSIVIEW *  view,
MSIRECORD *  record 
)
static

Definition at line 2733 of file table.c.

2734{
2735 return ERROR_SUCCESS;
2736}

◆ TransformView_fetch_int()

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

Definition at line 2315 of file table.c.

2316{
2317 struct table_view *tv = (struct table_view *)view;
2318
2319 if (!tv->table || col > tv->table->col_count)
2320 {
2321 *val = 0;
2322 return ERROR_SUCCESS;
2323 }
2324 return TABLE_fetch_int( view, row, col, val );
2325}

◆ TransformView_fetch_stream()

static UINT TransformView_fetch_stream ( MSIVIEW *  view,
UINT  row,
UINT  col,
IStream **  stm 
)
static

Definition at line 2327 of file table.c.

2328{
2329 struct table_view *tv = (struct table_view *)view;
2330
2331 if (!tv->table || col > tv->table->col_count)
2332 {
2333 *stm = NULL;
2334 return ERROR_SUCCESS;
2335 }
2336 return TABLE_fetch_stream( view, row, col, stm );
2337}
static UINT TABLE_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: table.c:1134

◆ TransformView_get_column_info()

static UINT TransformView_get_column_info ( MSIVIEW *  view,
UINT  n,
LPCWSTR *  name,
UINT *  type,
BOOL *  temporary,
LPCWSTR *  table_name 
)
static

Definition at line 2748 of file table.c.

2750{
2751 return TABLE_get_column_info( view, n, name, type, temporary, table_name );
2752}
static UINT TABLE_get_column_info(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: table.c:1570

◆ TransformView_get_dimensions()

static UINT TransformView_get_dimensions ( MSIVIEW *  view,
UINT *  rows,
UINT *  cols 
)
static

Definition at line 2743 of file table.c.

2744{
2745 return TABLE_get_dimensions( view, rows, cols );
2746}

◆ TransformView_insert_row()

static UINT TransformView_insert_row ( MSIVIEW *  view,
MSIRECORD *  rec,
UINT  row,
BOOL  temporary 
)
static

Definition at line 2574 of file table.c.

2575{
2576 static const WCHAR query_fmt[] =
2577 L"INSERT INTO `_TransformView` (`new`, `Table`, `Column`, `Row`) VALUES (1, '%s', 'INSERT', '%s')";
2578
2579 struct table_view *tv = (struct table_view *)view;
2580 WCHAR buf[256], *query = buf;
2581 MSIQUERY *q;
2582 WCHAR *key;
2583 int len;
2584 UINT r;
2585
2586 if (!wcscmp(tv->name, L"_Tables"))
2587 return TransformView_create_table( tv, rec );
2588
2589 if (!wcscmp(tv->name, L"_Columns"))
2590 return TransformView_add_column( tv, rec );
2591
2592 key = create_key_string( tv, rec );
2593 if (!key)
2594 return ERROR_OUTOFMEMORY;
2595
2596 len = _snwprintf( NULL, 0, query_fmt, tv->name, key ) + 1;
2597 if (len > ARRAY_SIZE(buf))
2598 {
2599 query = malloc( len * sizeof(WCHAR) );
2600 if (!query)
2601 {
2602 free( key );
2603 return ERROR_OUTOFMEMORY;
2604 }
2605 }
2606 swprintf( query, len, query_fmt, tv->name, key );
2607 free( key );
2608
2609 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2610 if (query != buf)
2611 free( query );
2612 if (r != ERROR_SUCCESS)
2613 return r;
2614
2615 r = MSI_ViewExecute( q, NULL );
2616 msiobj_release( &q->hdr );
2617 if (r != ERROR_SUCCESS)
2618 return r;
2619
2620 return TransformView_set_row( view, row, rec, ~0 );
2621}
static UINT TransformView_add_column(struct table_view *tv, MSIRECORD *rec)
Definition: table.c:2520
static UINT TransformView_create_table(struct table_view *tv, MSIRECORD *rec)
Definition: table.c:2485
static UINT TransformView_set_row(MSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: table.c:2339

◆ TransformView_set_row()

static UINT TransformView_set_row ( MSIVIEW *  view,
UINT  row,
MSIRECORD *  rec,
UINT  mask 
)
static

Definition at line 2339 of file table.c.

2340{
2341 static const WCHAR query_pfx[] =
2342 L"INSERT INTO `_TransformView` (`new`, `Table`, `Column`, `Row`, `Data`, `Current`) VALUES (1, '";
2343
2344 struct table_view *tv = (struct table_view *)view;
2345 WCHAR buf[256], *query;
2346 MSIRECORD *old_rec;
2347 MSIQUERY *q;
2348 WCHAR *key;
2349 UINT i, p, r, qlen;
2350 DWORD len;
2351
2352 if (!wcscmp( tv->name, L"_Columns" ))
2353 {
2354 ERR( "trying to modify existing column\n" );
2356 }
2357
2358 if (!wcscmp( tv->name, L"_Tables" ))
2359 {
2360 ERR( "trying to modify existing table\n" );
2362 }
2363
2364 key = create_key_string( tv, rec );
2365 if (!key)
2366 return ERROR_OUTOFMEMORY;
2367
2368 r = msi_view_get_row( tv->db, view, row, &old_rec );
2369 if (r != ERROR_SUCCESS)
2370 old_rec = NULL;
2371
2372 for (i = 0; i < tv->num_cols; i++)
2373 {
2374 if (!(mask & (1 << i)))
2375 continue;
2376 if (tv->columns[i].type & MSITYPE_KEY)
2377 continue;
2378
2379 qlen = p = ARRAY_SIZE( query_pfx ) - 1;
2380 qlen += wcslen( tv->name ) + 3; /* strlen("','") */
2381 qlen += wcslen( tv->columns[i].colname ) + 3;
2382 qlen += wcslen( key ) + 3;
2383 if (MSITYPE_IS_BINARY( tv->columns[i].type ))
2384 r = record_stream_name( tv, rec, NULL, &len );
2385 else
2386 r = MSI_RecordGetStringW( rec, i + 1, NULL, &len );
2387 if (r != ERROR_SUCCESS)
2388 {
2389 if (old_rec)
2390 msiobj_release( &old_rec->hdr );
2391 free( key );
2392 return r;
2393 }
2394 qlen += len + 3;
2395 if (old_rec && (r = MSI_RecordGetStringW( old_rec, i+1, NULL, &len )))
2396 {
2397 msiobj_release( &old_rec->hdr );
2398 free( key );
2399 return r;
2400 }
2401 qlen += len + 3; /* strlen("')") + 1 */
2402
2403 if (qlen > ARRAY_SIZE(buf))
2404 {
2405 query = malloc( qlen * sizeof(WCHAR) );
2406 if (!query)
2407 {
2408 if (old_rec)
2409 msiobj_release( &old_rec->hdr );
2410 free( key );
2411 return ERROR_OUTOFMEMORY;
2412 }
2413 }
2414 else
2415 {
2416 query = buf;
2417 }
2418
2419 memcpy( query, query_pfx, p * sizeof(WCHAR) );
2420 len = wcslen( tv->name );
2421 memcpy( query + p, tv->name, len * sizeof(WCHAR) );
2422 p += len;
2423 query[p++] = '\'';
2424 query[p++] = ',';
2425 query[p++] = '\'';
2426 len = wcslen( tv->columns[i].colname );
2427 memcpy( query + p, tv->columns[i].colname, len * sizeof(WCHAR) );
2428 p += len;
2429 query[p++] = '\'';
2430 query[p++] = ',';
2431 query[p++] = '\'';
2432 len = wcslen( key );
2433 memcpy( query + p, key, len * sizeof(WCHAR) );
2434 p += len;
2435 query[p++] = '\'';
2436 query[p++] = ',';
2437 query[p++] = '\'';
2438 len = qlen - p;
2439 if (MSITYPE_IS_BINARY( tv->columns[i].type ))
2440 record_stream_name( tv, rec, query + p, &len );
2441 else
2442 MSI_RecordGetStringW( rec, i + 1, query + p, &len );
2443 p += len;
2444 query[p++] = '\'';
2445 query[p++] = ',';
2446 query[p++] = '\'';
2447 if (old_rec)
2448 {
2449 len = qlen - p;
2450 MSI_RecordGetStringW( old_rec, i + 1, query + p, &len );
2451 p += len;
2452 }
2453 query[p++] = '\'';
2454 query[p++] = ')';
2455 query[p++] = 0;
2456
2457 r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2458 if (query != buf)
2459 free( query );
2460 if (r != ERROR_SUCCESS)
2461 {
2462 if (old_rec)
2463 msiobj_release( &old_rec->hdr );
2464 free( key );
2465 return r;
2466 }
2467
2468 r = MSI_ViewExecute( q, NULL );
2469 msiobj_release( &q->hdr );
2470 if (r != ERROR_SUCCESS)
2471 {
2472 if (old_rec)
2473 msiobj_release( &old_rec->hdr );
2474 free( key );
2475 return r;
2476 }
2477 }
2478
2479 if (old_rec)
2480 msiobj_release( &old_rec->hdr );
2481 free( key );
2482 return ERROR_SUCCESS;
2483}

Referenced by TransformView_insert_row().

◆ update_table_columns()

static void update_table_columns ( MSIDATABASE *  db,
const WCHAR *  name 
)
static

Definition at line 935 of file table.c.

936{
938 UINT size, offset, old_count;
939 UINT n;
940
941 if (!(table = find_cached_table( db, name ))) return;
942 old_count = table->col_count;
943 free_colinfo( table->colinfo, table->col_count );
944 free( table->colinfo );
945 table->colinfo = NULL;
946
947 table_get_column_info( db, name, &table->colinfo, &table->col_count );
948 if (!table->col_count) return;
949
950 size = table_get_row_size( db, table->colinfo, table->col_count, LONG_STR_BYTES );
951 offset = table->colinfo[table->col_count - 1].offset;
952
953 for ( n = 0; n < table->row_count; n++ )
954 {
955 table->data[n] = realloc( table->data[n], size );
956 if (old_count < table->col_count)
957 memset( &table->data[n][offset], 0, size - offset );
958 }
959}

Referenced by table_load_transform(), and TABLE_remove_column().

◆ utf2mime()

static int utf2mime ( int  x)
static

Definition at line 106 of file table.c.

107{
108 if( (x>='0') && (x<='9') )
109 return x-'0';
110 if( (x>='A') && (x<='Z') )
111 return x-'A'+10;
112 if( (x>='a') && (x<='z') )
113 return x-'a'+10+26;
114 if( x=='.' )
115 return 10+26+26;
116 if( x=='_' )
117 return 10+26+26+1;
118 return -1;
119}

Referenced by encode_streamname().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( msidb  )

◆ write_stream_data()

UINT write_stream_data ( IStorage *  stg,
LPCWSTR  stname,
LPCVOID  data,
UINT  sz,
BOOL  bTable 
)

Definition at line 298 of file table.c.

300{
301 HRESULT r;
303 ULONG count;
304 IStream *stm = NULL;
307 LPWSTR encname;
308
309 encname = encode_streamname(bTable, stname );
310 r = IStorage_OpenStream( stg, encname, NULL,
312 if( FAILED(r) )
313 {
314 r = IStorage_CreateStream( stg, encname,
315 STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
316 }
317 free( encname );
318 if( FAILED( r ) )
319 {
320 WARN( "open stream failed r = %#lx\n", r );
321 return ret;
322 }
323
324 size.QuadPart = sz;
325 r = IStream_SetSize( stm, size );
326 if( FAILED( r ) )
327 {
328 WARN("Failed to SetSize\n");
329 goto end;
330 }
331
332 pos.QuadPart = 0;
333 r = IStream_Seek( stm, pos, STREAM_SEEK_SET, NULL );
334 if( FAILED( r ) )
335 {
336 WARN("Failed to Seek\n");
337 goto end;
338 }
339
340 if (sz)
341 {
342 r = IStream_Write(stm, data, sz, &count );
343 if( FAILED( r ) || ( count != sz ) )
344 {
345 WARN("Failed to Write\n");
346 goto end;
347 }
348 }
349
351
352end:
353 IStream_Release( stm );
354
355 return ret;
356}
#define STGM_WRITE
Definition: objbase.h:937

Referenced by db_initialize(), msi_init_string_table(), msi_save_string_table(), and save_table().

Variable Documentation

◆ _Columns_cols

const struct column_info _Columns_cols[4]
static
Initial value:
=
{
{ L"_Columns", 1, L"Table", MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, NULL },
{ L"_Columns", 2, L"Number", MSITYPE_VALID | MSITYPE_KEY | 2, 2, NULL },
{ L"_Columns", 3, L"Name", MSITYPE_VALID | MSITYPE_STRING | 64, 4, NULL },
{ L"_Columns", 4, L"Type", MSITYPE_VALID | 2, 6, NULL },
}
#define MSITYPE_VALID
Definition: msipriv.h:48

Definition at line 74 of file table.c.

Referenced by get_defaulttablecolumns().

◆ _Tables_cols

const struct column_info _Tables_cols[1]
static
Initial value:
=
{
{ L"_Tables", 1, L"Name", MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, NULL },
}

Definition at line 82 of file table.c.

Referenced by get_defaulttablecolumns().

◆ table_ops

const MSIVIEWOPS table_ops
static
Initial value:
=
{
}
static UINT TABLE_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
Definition: table.c:1857
static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR column, INT type, BOOL hold)
Definition: table.c:2042
static UINT TABLE_drop(struct tagMSIVIEW *view)
Definition: table.c:2137
static UINT TABLE_close(struct tagMSIVIEW *view)
Definition: table.c:1545
static UINT TABLE_set_int(MSIVIEW *view, UINT row, UINT col, int val)
Definition: table.c:1216
static UINT TABLE_release(struct tagMSIVIEW *view)
Definition: table.c:2005
static UINT TABLE_execute(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: table.c:1534
static UINT TABLE_set_stream(MSIVIEW *view, UINT row, UINT col, IStream *stream)
Definition: table.c:1342
static UINT TABLE_set_string(MSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
Definition: table.c:1243

Definition at line 2185 of file table.c.

Referenced by TABLE_CreateView().

◆ transform_view_ops

const MSIVIEWOPS transform_view_ops
static
Initial value:
=
{
}
static UINT TransformView_get_column_info(MSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: table.c:2748
static UINT TransformView_insert_row(MSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
Definition: table.c:2574
static UINT TransformView_delete(MSIVIEW *view)
Definition: table.c:2754
static UINT TransformView_fetch_stream(MSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: table.c:2327
static UINT TransformView_get_dimensions(MSIVIEW *view, UINT *rows, UINT *cols)
Definition: table.c:2743
static UINT TransformView_fetch_int(MSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: table.c:2315
static UINT TransformView_execute(MSIVIEW *view, MSIRECORD *record)
Definition: table.c:2733
static UINT TransformView_delete_row(MSIVIEW *view, UINT row)
Definition: table.c:2667
static UINT TransformView_close(MSIVIEW *view)
Definition: table.c:2738

Definition at line 2762 of file table.c.

Referenced by TransformView_Create().