ReactOS 0.4.16-dev-188-g678aa63
database.c File Reference
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winnls.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
#include "objidl.h"
#include "objbase.h"
#include "msiserver.h"
#include "query.h"
#include "initguid.h"
Include dependency graph for database.c:

Go to the source code of this file.

Classes

struct  row_export_info
 
struct  merge_table
 
struct  merge_row
 
struct  merge_data
 

Macros

#define COBJMACROS
 
#define IS_INTMSIDBOPEN(x)   (((ULONG_PTR)(x) >> 16) == 0)
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (msi)
 
static void free_transforms (MSIDATABASE *db)
 
static void free_streams (MSIDATABASE *db)
 
void append_storage_to_db (MSIDATABASE *db, IStorage *stg)
 
static VOID MSI_CloseDatabase (MSIOBJECTHDR *arg)
 
static HRESULT db_initialize (IStorage *stg, const GUID *clsid)
 
UINT MSI_OpenDatabaseW (LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
 
UINT WINAPI MsiOpenDatabaseW (LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
 
UINT WINAPI MsiOpenDatabaseA (LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
 
static WCHARread_text_archive (const WCHAR *path, DWORD *len)
 
static UINT parse_line (WCHAR **line, WCHAR ***entries, DWORD *num_entries, DWORD *len)
 
static WCHARbuild_createsql_prelude (const WCHAR *table)
 
static WCHARbuild_createsql_columns (WCHAR **columns_data, WCHAR **types, DWORD num_columns)
 
static WCHARbuild_createsql_postlude (WCHAR **primary_keys, DWORD num_keys)
 
static UINT add_table_to_db (MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, DWORD num_labels, DWORD num_columns)
 
static WCHARimport_stream_filename (const WCHAR *path, const WCHAR *name)
 
static UINT construct_record (DWORD num_columns, LPWSTR *types, LPWSTR *data, LPWSTR path, MSIRECORD **rec)
 
static UINT add_records_to_table (MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, WCHAR ***records, int num_columns, int num_records, WCHAR *path)
 
static UINT MSI_DatabaseImport (MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
 
UINT WINAPI MsiDatabaseImportW (MSIHANDLE handle, const WCHAR *szFolder, const WCHAR *szFilename)
 
UINT WINAPI MsiDatabaseImportA (MSIHANDLE handle, const char *szFolder, const char *szFilename)
 
static UINT export_field (HANDLE handle, MSIRECORD *row, UINT field)
 
static UINT export_stream (const WCHAR *folder, const WCHAR *table, MSIRECORD *row, UINT field, UINT start)
 
static UINT export_record (struct row_export_info *row_export_info, MSIRECORD *row, UINT start)
 
static UINT export_row (MSIRECORD *row, void *arg)
 
static UINT export_forcecodepage (HANDLE handle, UINT codepage)
 
static UINT export_summaryinformation (MSIDATABASE *db, HANDLE handle)
 
static UINT MSI_DatabaseExport (MSIDATABASE *db, LPCWSTR table, LPCWSTR folder, LPCWSTR file)
 
UINT WINAPI MsiDatabaseExportW (MSIHANDLE handle, const WCHAR *szTable, const WCHAR *szFolder, const WCHAR *szFilename)
 
UINT WINAPI MsiDatabaseExportA (MSIHANDLE handle, const char *szTable, const char *szFolder, const char *szFilename)
 
UINT WINAPI MsiDatabaseMergeA (MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const char *szTableName)
 
static BOOL merge_type_match (LPCWSTR type1, LPCWSTR type2)
 
static UINT merge_verify_colnames (MSIQUERY *dbview, MSIQUERY *mergeview)
 
static UINT merge_verify_primary_keys (MSIDATABASE *db, MSIDATABASE *mergedb, LPCWSTR table)
 
static LPWSTR get_key_value (MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
 
static LPWSTR create_diff_row_query (MSIDATABASE *merge, MSIQUERY *view, LPWSTR table, MSIRECORD *rec)
 
static UINT merge_diff_row (MSIRECORD *rec, LPVOID param)
 
static UINT get_table_labels (MSIDATABASE *db, const WCHAR *table, WCHAR ***labels, DWORD *numlabels)
 
static UINT get_query_columns (MSIQUERY *query, WCHAR ***columns, DWORD *numcolumns)
 
static UINT get_query_types (MSIQUERY *query, WCHAR ***types, DWORD *numtypes)
 
static void merge_free_rows (struct merge_table *table)
 
static void free_merge_table (struct merge_table *table)
 
static UINT get_merge_table (MSIDATABASE *db, const WCHAR *name, struct merge_table **ptable)
 
static UINT merge_diff_tables (MSIRECORD *rec, LPVOID param)
 
static UINT gather_merge_data (MSIDATABASE *db, MSIDATABASE *merge, struct list *tabledata)
 
static UINT merge_table (MSIDATABASE *db, struct merge_table *table)
 
static UINT update_merge_errors (MSIDATABASE *db, LPCWSTR error, LPWSTR table, DWORD numconflicts)
 
UINT WINAPI MsiDatabaseMergeW (MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const WCHAR *szTableName)
 
MSIDBSTATE WINAPI MsiGetDatabaseState (MSIHANDLE handle)
 
MSICONDITION __cdecl s_remote_DatabaseIsTablePersistent (MSIHANDLE db, LPCWSTR table)
 
UINT __cdecl s_remote_DatabaseGetPrimaryKeys (MSIHANDLE db, LPCWSTR table, struct wire_record **rec)
 
UINT __cdecl s_remote_DatabaseGetSummaryInformation (MSIHANDLE db, UINT updatecount, MSIHANDLE *suminfo)
 
UINT __cdecl s_remote_DatabaseOpenView (MSIHANDLE db, LPCWSTR query, MSIHANDLE *view)
 

Macro Definition Documentation

◆ COBJMACROS

#define COBJMACROS

Definition at line 24 of file database.c.

◆ IS_INTMSIDBOPEN

#define IS_INTMSIDBOPEN (   x)    (((ULONG_PTR)(x) >> 16) == 0)

Definition at line 53 of file database.c.

Function Documentation

◆ add_records_to_table()

static UINT add_records_to_table ( MSIDATABASE db,
WCHAR **  columns,
WCHAR **  types,
WCHAR **  labels,
WCHAR ***  records,
int  num_columns,
int  num_records,
WCHAR path 
)
static

Definition at line 700 of file database.c.

702{
703 UINT r;
704 int i;
705 MSIQUERY *view;
706 MSIRECORD *rec;
707
708 r = MSI_OpenQuery(db, &view, L"SELECT * FROM `%s`", labels[0]);
709 if (r != ERROR_SUCCESS)
710 return r;
711
712 while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS)
713 {
715 msiobj_release(&rec->hdr);
716 if (r != ERROR_SUCCESS)
717 goto done;
718 }
719
720 for (i = 0; i < num_records; i++)
721 {
722 r = construct_record(num_columns, types, records[i], path, &rec);
723 if (r != ERROR_SUCCESS)
724 goto done;
725
727 if (r != ERROR_SUCCESS)
728 {
729 msiobj_release(&rec->hdr);
730 goto done;
731 }
732
733 msiobj_release(&rec->hdr);
734 }
735
736done:
737 msiobj_release(&view->hdr);
738 return r;
739}
#define ERROR_SUCCESS
Definition: deptool.c:10
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
static UINT construct_record(DWORD num_columns, LPWSTR *types, LPWSTR *data, LPWSTR path, MSIRECORD **rec)
Definition: database.c:656
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
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
UINT WINAPIV MSI_OpenQuery(MSIDATABASE *, MSIQUERY **, LPCWSTR,...)
Definition: msiquery.c:138
UINT MSI_ViewFetch(MSIQUERY *, MSIRECORD **)
Definition: msiquery.c:377
UINT MSI_ViewModify(MSIQUERY *, MSIMODIFY, MSIRECORD *)
Definition: msiquery.c:697
@ MSIMODIFY_DELETE
Definition: msiquery.h:57
@ MSIMODIFY_INSERT
Definition: msiquery.h:52
unsigned int UINT
Definition: ndis.h:50
#define L(x)
Definition: ntvdm.h:50
MSIOBJECTHDR hdr
Definition: msipriv.h:151
Definition: cmds.c:130

Referenced by MSI_DatabaseImport().

◆ add_table_to_db()

static UINT add_table_to_db ( MSIDATABASE db,
WCHAR **  columns,
WCHAR **  types,
WCHAR **  labels,
DWORD  num_labels,
DWORD  num_columns 
)
static

Definition at line 591 of file database.c.

593{
595 DWORD size;
596 MSIQUERY *view;
597 LPWSTR create_sql = NULL;
598 LPWSTR prelude, columns_sql, postlude;
599
600 prelude = build_createsql_prelude(labels[0]);
601 columns_sql = build_createsql_columns(columns, types, num_columns);
602 postlude = build_createsql_postlude(labels + 1, num_labels - 1); /* skip over table name */
603
604 if (!prelude || !columns_sql || !postlude)
605 goto done;
606
607 size = lstrlenW(prelude) + lstrlenW(columns_sql) + lstrlenW(postlude) + 1;
608 create_sql = malloc(size * sizeof(WCHAR));
609 if (!create_sql)
610 goto done;
611
612 lstrcpyW(create_sql, prelude);
613 lstrcatW(create_sql, columns_sql);
614 lstrcatW(create_sql, postlude);
615
616 r = MSI_DatabaseOpenViewW( db, create_sql, &view );
617 if (r != ERROR_SUCCESS)
618 goto done;
619
622 msiobj_release(&view->hdr);
623
624done:
625 free(prelude);
626 free(columns_sql);
627 free(postlude);
628 free(create_sql);
629 return r;
630}
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define NULL
Definition: types.h:112
#define lstrcpyW
Definition: compat.h:749
#define lstrlenW
Definition: compat.h:750
static WCHAR * build_createsql_columns(WCHAR **columns_data, WCHAR **types, DWORD num_columns)
Definition: database.c:472
static WCHAR * build_createsql_prelude(const WCHAR *table)
Definition: database.c:458
static WCHAR * build_createsql_postlude(WCHAR **primary_keys, DWORD num_keys)
Definition: database.c:559
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
UINT MSI_ViewExecute(MSIQUERY *, MSIRECORD *)
Definition: msiquery.c:502
UINT MSI_ViewClose(MSIQUERY *)
Definition: msiquery.c:454
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184

Referenced by merge_table(), and MSI_DatabaseImport().

◆ append_storage_to_db()

void append_storage_to_db ( MSIDATABASE db,
IStorage stg 
)

Definition at line 76 of file database.c.

77{
79
80 t = malloc( sizeof *t );
81 t->stg = stg;
82 IStorage_AddRef( stg );
83 list_add_head( &db->transforms, &t->entry );
84}
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
GLdouble GLdouble t
Definition: gl.h:2047
struct list transforms
Definition: msipriv.h:119

Referenced by msi_table_apply_transform().

◆ build_createsql_columns()

static WCHAR * build_createsql_columns ( WCHAR **  columns_data,
WCHAR **  types,
DWORD  num_columns 
)
static

Definition at line 472 of file database.c.

473{
474 LPWSTR columns, p;
476 DWORD sql_size = 1, i, len;
477 WCHAR expanded[128], *ptr;
478 WCHAR size[10], comma[2], extra[30];
479
480 columns = calloc(sql_size, sizeof(WCHAR));
481 if (!columns)
482 return NULL;
483
484 for (i = 0; i < num_columns; i++)
485 {
486 type = NULL;
487 comma[1] = size[0] = extra[0] = '\0';
488
489 if (i == num_columns - 1)
490 comma[0] = '\0';
491 else
492 comma[0] = ',';
493
494 ptr = &types[i][1];
495 len = wcstol(ptr, NULL, 10);
496 extra[0] = '\0';
497
498 switch (types[i][0])
499 {
500 case 'l':
501 lstrcpyW(extra, L" NOT NULL");
502 /* fall through */
503 case 'L':
504 lstrcatW(extra, L" LOCALIZABLE");
505 type = L"CHAR";
506 swprintf(size, ARRAY_SIZE(size), L"(%s)", ptr);
507 break;
508 case 's':
509 lstrcpyW(extra, L" NOT NULL");
510 /* fall through */
511 case 'S':
512 type = L"CHAR";
513 swprintf(size, ARRAY_SIZE(size), L"(%s)", ptr);
514 break;
515 case 'i':
516 lstrcpyW(extra, L" NOT NULL");
517 /* fall through */
518 case 'I':
519 if (len <= 2)
520 type = L"INT";
521 else if (len == 4)
522 type = L"LONG";
523 else
524 {
525 WARN("invalid int width %lu\n", len);
526 free(columns);
527 return NULL;
528 }
529 break;
530 case 'v':
531 lstrcpyW(extra, L" NOT NULL");
532 /* fall through */
533 case 'V':
534 type = L"OBJECT";
535 break;
536 default:
537 ERR("Unknown type: %c\n", types[i][0]);
538 free(columns);
539 return NULL;
540 }
541
542 swprintf(expanded, ARRAY_SIZE(expanded), L"`%s` %s%s%s%s ", columns_data[i], type, size, extra, comma);
543 sql_size += lstrlenW(expanded);
544
545 p = realloc(columns, sql_size * sizeof(WCHAR));
546 if (!p)
547 {
548 free(columns);
549 return NULL;
550 }
551 columns = p;
552
553 lstrcatW(columns, expanded);
554 }
555
556 return columns;
557}
#define ARRAY_SIZE(A)
Definition: main.h:20
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define realloc
Definition: debug_ros.c:6
#define swprintf
Definition: precomp.h:40
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
@ extra
Definition: id3.c:95
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
static PVOID ptr
Definition: dispmode.c:27
#define calloc
Definition: rosglue.h:14
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185

Referenced by add_table_to_db().

◆ build_createsql_postlude()

static WCHAR * build_createsql_postlude ( WCHAR **  primary_keys,
DWORD  num_keys 
)
static

Definition at line 559 of file database.c.

560{
561 LPWSTR postlude, keys, ptr;
562 DWORD size, i;
563
564 for (i = 0, size = 1; i < num_keys; i++)
565 size += lstrlenW(L"`%s`, ") + lstrlenW(primary_keys[i]) - 2;
566
567 keys = malloc(size * sizeof(WCHAR));
568 if (!keys)
569 return NULL;
570
571 for (i = 0, ptr = keys; i < num_keys; i++)
572 {
573 ptr += swprintf(ptr, size - (ptr - keys), L"`%s`, ", primary_keys[i]);
574 }
575
576 /* remove final ', ' */
577 *(ptr - 2) = '\0';
578
579 size = lstrlenW(L"PRIMARY KEY %s)") + size - 1;
580 postlude = malloc(size * sizeof(WCHAR));
581 if (!postlude)
582 goto done;
583
584 swprintf(postlude, size, L"PRIMARY KEY %s)", keys);
585
586done:
587 free(keys);
588 return postlude;
589}

Referenced by add_table_to_db().

◆ build_createsql_prelude()

static WCHAR * build_createsql_prelude ( const WCHAR table)
static

Definition at line 458 of file database.c.

459{
460 LPWSTR prelude;
461 DWORD size;
462
463 size = ARRAY_SIZE(L"CREATE TABLE `%s` ( ") + lstrlenW(table) - 2;
464 prelude = malloc(size * sizeof(WCHAR));
465 if (!prelude)
466 return NULL;
467
468 swprintf(prelude, size, L"CREATE TABLE `%s` ( ", table);
469 return prelude;
470}

Referenced by add_table_to_db().

◆ construct_record()

static UINT construct_record ( DWORD  num_columns,
LPWSTR types,
LPWSTR data,
LPWSTR  path,
MSIRECORD **  rec 
)
static

Definition at line 656 of file database.c.

658{
659 UINT i;
660
661 *rec = MSI_CreateRecord(num_columns);
662 if (!*rec)
663 return ERROR_OUTOFMEMORY;
664
665 for (i = 0; i < num_columns; i++)
666 {
667 switch (types[i][0])
668 {
669 case 'L': case 'l': case 'S': case 's':
670 MSI_RecordSetStringW(*rec, i + 1, data[i]);
671 break;
672 case 'I': case 'i':
673 if (*data[i])
674 MSI_RecordSetInteger(*rec, i + 1, wcstol(data[i], NULL, 10));
675 break;
676 case 'V': case 'v':
677 if (*data[i])
678 {
679 UINT r;
681 if (!file)
683
684 r = MSI_RecordSetStreamFromFileW(*rec, i + 1, file);
685 free (file);
686 if (r != ERROR_SUCCESS)
688 }
689 break;
690 default:
691 ERR("Unhandled column type: %c\n", types[i][0]);
692 msiobj_release(&(*rec)->hdr);
694 }
695 }
696
697 return ERROR_SUCCESS;
698}
static WCHAR * import_stream_filename(const WCHAR *path, const WCHAR *name)
Definition: database.c:632
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
UINT MSI_RecordSetStreamFromFileW(MSIRECORD *, UINT, LPCWSTR)
Definition: record.c:683
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int)
Definition: record.c:280
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR)
Definition: record.c:597
MSIRECORD * MSI_CreateRecord(UINT)
Definition: record.c:76
Definition: fci.c:127
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985

Referenced by add_records_to_table().

◆ create_diff_row_query()

static LPWSTR create_diff_row_query ( MSIDATABASE merge,
MSIQUERY view,
LPWSTR  table,
MSIRECORD rec 
)
static

Definition at line 1438 of file database.c.

1440{
1441 WCHAR *query = NULL, *clause = NULL, *new_clause, *val;
1442 LPCWSTR setptr, key;
1443 DWORD size, oldsize;
1444 MSIRECORD *keys;
1445 UINT r, i, count;
1446
1448 if (r != ERROR_SUCCESS)
1449 return NULL;
1450
1451 size = 1;
1453 for (i = 1; i <= count; i++)
1454 {
1455 key = MSI_RecordGetString(keys, i);
1456 val = get_key_value(view, key, rec);
1457
1458 if (i == count)
1459 setptr = L"`%s` = %s ";
1460 else
1461 setptr = L"`%s` = %s AND ";
1462
1463 oldsize = size;
1464 size += lstrlenW(setptr) + lstrlenW(key) + lstrlenW(val) - 4;
1465 new_clause = realloc(clause, size * sizeof(WCHAR));
1466 if (!new_clause)
1467 {
1468 free(val);
1469 goto done;
1470 }
1471 clause = new_clause;
1472
1473 swprintf(clause + oldsize - 1, size - (oldsize - 1), setptr, key, val);
1474 free(val);
1475 }
1476
1477 size = lstrlenW(L"SELECT * FROM `%s` WHERE %s") + lstrlenW(table) + lstrlenW(clause) + 1;
1478 query = malloc(size * sizeof(WCHAR));
1479 if (!query)
1480 goto done;
1481
1482 swprintf(query, size, L"SELECT * FROM `%s` WHERE %s", table, clause);
1483
1484done:
1485 free(clause);
1486 msiobj_release(&keys->hdr);
1487 return query;
1488}
_STLP_MOVE_TO_STD_NAMESPACE _OutputIter merge(_InputIter1 __first1, _InputIter1 __last1, _InputIter2 __first2, _InputIter2 __last2, _OutputIter __result)
Definition: _algo.c:1419
static LPWSTR get_key_value(MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
Definition: database.c:1380
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLfloat * val
Definition: glext.h:7180
UINT MSI_DatabaseGetPrimaryKeys(MSIDATABASE *, LPCWSTR, MSIRECORD **)
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT)
Definition: record.c:433
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec)
Definition: record.c:108
Definition: copy.c:22

Referenced by merge_diff_row().

◆ db_initialize()

static HRESULT db_initialize ( IStorage stg,
const GUID clsid 
)
static

Definition at line 104 of file database.c.

105{
106 HRESULT hr;
107
108 hr = IStorage_SetClass( stg, clsid );
109 if (FAILED( hr ))
110 {
111 WARN("failed to set class id %#lx\n", hr);
112 return hr;
113 }
114
115 /* create the _Tables stream */
116 hr = write_stream_data( stg, L"_Tables", NULL, 0, TRUE );
117 if (FAILED( hr ))
118 {
119 WARN("failed to create _Tables stream %#lx\n", hr);
120 return hr;
121 }
122
123 hr = msi_init_string_table( stg );
124 if (FAILED( hr ))
125 {
126 WARN("failed to initialize string table %#lx\n", hr);
127 return hr;
128 }
129
130 hr = IStorage_Commit( stg, 0 );
131 if (FAILED( hr ))
132 {
133 WARN("failed to commit changes %#lx\n", hr);
134 return hr;
135 }
136
137 return S_OK;
138}
#define TRUE
Definition: types.h:120
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
REFCLSID clsid
Definition: msctf.c:82
HRESULT msi_init_string_table(IStorage *stg)
Definition: string.c:460
UINT write_stream_data(IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable)
Definition: table.c:298
HRESULT hr
Definition: shlfolder.c:183

Referenced by MSI_OpenDatabaseW().

◆ export_field()

static UINT export_field ( HANDLE  handle,
MSIRECORD row,
UINT  field 
)
static

Definition at line 893 of file database.c.

894{
895 char *buffer, *ptr;
896 BOOL ret;
897 DWORD sz = 0x100;
898 UINT r;
899
900 buffer = malloc( sz );
901 if (!buffer)
902 return ERROR_OUTOFMEMORY;
903
905 if (r == ERROR_MORE_DATA)
906 {
907 char *tmp;
908
909 sz++; /* leave room for NULL terminator */
910 tmp = realloc( buffer, sz );
911 if (!tmp)
912 {
913 free( buffer );
914 return ERROR_OUTOFMEMORY;
915 }
916 buffer = tmp;
917
919 if (r != ERROR_SUCCESS)
920 {
921 free( buffer );
922 return r;
923 }
924 }
925 else if (r != ERROR_SUCCESS)
926 {
927 free( buffer );
928 return r;
929 }
930
931 ptr = buffer;
932 while( *ptr )
933 {
934 if (*ptr == '\r' && *( ptr + 1 ) == '\n')
935 {
936 *ptr++ = '\x11';
937 *ptr++ = '\x19';
938 continue;
939 }
940
941 if (*ptr == '\n')
942 *ptr = '\x19';
943
944 ptr++;
945 }
946
947 ret = WriteFile( handle, buffer, sz, &sz, NULL );
948 free( buffer );
950}
#define ERROR_MORE_DATA
Definition: dderror.h:13
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
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
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint buffer
Definition: glext.h:5915
UINT MSI_RecordGetStringA(MSIRECORD *, UINT, LPSTR, LPDWORD)
Definition: record.c:351
Definition: parser.c:44
int ret

Referenced by export_record().

◆ export_forcecodepage()

static UINT export_forcecodepage ( HANDLE  handle,
UINT  codepage 
)
static

Definition at line 1047 of file database.c.

1048{
1049 static const char fmt[] = "\r\n\r\n%u\t_ForceCodepage\r\n";
1050 char data[sizeof(fmt) + 10];
1051 DWORD sz = sprintf( data, fmt, codepage );
1052
1053 if (!WriteFile(handle, data, sz, &sz, NULL))
1054 return ERROR_FUNCTION_FAILED;
1055
1056 return ERROR_SUCCESS;
1057}
#define sprintf(buf, format,...)
Definition: sprintf.c:55
Definition: dsound.c:943
int codepage
Definition: win_iconv.c:156

Referenced by MSI_DatabaseExport().

◆ export_record()

static UINT export_record ( struct row_export_info row_export_info,
MSIRECORD row,
UINT  start 
)
static

Definition at line 1010 of file database.c.

1011{
1014 const char *sep;
1015 DWORD sz;
1016
1018 for (i = start; i <= count; i++)
1019 {
1020 r = export_field( handle, row, i );
1022 {
1024 if (r != ERROR_SUCCESS)
1025 return r;
1026
1027 /* exporting a binary stream, repeat the "Name" field */
1028 r = export_field( handle, row, start );
1029 if (r != ERROR_SUCCESS)
1030 return r;
1031 }
1032 else if (r != ERROR_SUCCESS)
1033 return r;
1034
1035 sep = (i < count) ? "\t" : "\r\n";
1036 if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
1037 return ERROR_FUNCTION_FAILED;
1038 }
1039 return r;
1040}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static UINT export_stream(const WCHAR *folder, const WCHAR *table, MSIRECORD *row, UINT field, UINT start)
Definition: database.c:952
static UINT export_field(HANDLE handle, MSIRECORD *row, UINT field)
Definition: database.c:893
GLuint start
Definition: gl.h:1545
const WCHAR * folder
Definition: database.c:1006
const WCHAR * table
Definition: database.c:1007

Referenced by export_row(), and MSI_DatabaseExport().

◆ export_row()

static UINT export_row ( MSIRECORD row,
void arg 
)
static

Definition at line 1042 of file database.c.

1043{
1044 return export_record( arg, row, 1 );
1045}
static UINT export_record(struct row_export_info *row_export_info, MSIRECORD *row, UINT start)
Definition: database.c:1010

Referenced by MSI_DatabaseExport().

◆ export_stream()

static UINT export_stream ( const WCHAR folder,
const WCHAR table,
MSIRECORD row,
UINT  field,
UINT  start 
)
static

Definition at line 952 of file database.c.

953{
955 DWORD sz, read_size, write_size;
956 char buffer[1024];
957 HANDLE file;
958 UINT len, r;
959
960 sz = ARRAY_SIZE( stream );
962 if (r != ERROR_SUCCESS)
963 return r;
964
965 len = sz + lstrlenW( folder ) + lstrlenW( table ) + ARRAY_SIZE( L"%s\\%s" ) + 1;
966 if (!(path = malloc( len * sizeof(WCHAR) )))
967 return ERROR_OUTOFMEMORY;
968
969 len = swprintf( path, len, L"%s\\%s", folder, table );
971 {
972 free( path );
974 }
975
976 path[len++] = '\\';
977 lstrcpyW( path + len, stream );
980 free( path );
983
984 read_size = sizeof(buffer);
985 while (read_size == sizeof(buffer))
986 {
987 r = MSI_RecordReadStream( row, field, buffer, &read_size );
988 if (r != ERROR_SUCCESS)
989 {
990 CloseHandle( file );
991 return r;
992 }
993 if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
994 {
995 CloseHandle( file );
996 return ERROR_WRITE_FAULT;
997 }
998 }
999 CloseHandle( file );
1000 return r;
1001}
#define CloseHandle
Definition: compat.h:739
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
UINT MSI_RecordReadStream(MSIRECORD *, UINT, char *, LPDWORD)
Definition: record.c:761
#define MAX_STREAM_NAME_LEN
Definition: msipriv.h:56
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define GENERIC_WRITE
Definition: nt_native.h:90
Definition: fci.c:116
Definition: parse.h:23
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_WRITE_FAULT
Definition: winerror.h:132

Referenced by export_record().

◆ export_summaryinformation()

static UINT export_summaryinformation ( MSIDATABASE db,
HANDLE  handle 
)
static

Definition at line 1059 of file database.c.

1060{
1061 static const char header[] = "PropertyId\tValue\r\n"
1062 "i2\tl255\r\n"
1063 "_SummaryInformation\tPropertyId\r\n";
1064 DWORD sz = ARRAY_SIZE(header) - 1;
1065
1066 if (!WriteFile(handle, header, sz, &sz, NULL))
1067 return ERROR_WRITE_FAULT;
1068
1069 return msi_export_suminfo( db, handle );
1070}
UINT msi_export_suminfo(MSIDATABASE *db, HANDLE handle)
Definition: suminfo.c:1195

Referenced by MSI_DatabaseExport().

◆ free_merge_table()

static void free_merge_table ( struct merge_table table)
static

Definition at line 1650 of file database.c.

1651{
1652 UINT i;
1653
1654 if (table->labels != NULL)
1655 {
1656 for (i = 0; i < table->numlabels; i++)
1657 free(table->labels[i]);
1658
1659 free(table->labels);
1660 }
1661
1662 if (table->columns != NULL)
1663 {
1664 for (i = 0; i < table->numcolumns; i++)
1665 free(table->columns[i]);
1666
1667 free(table->columns);
1668 }
1669
1670 if (table->types != NULL)
1671 {
1672 for (i = 0; i < table->numtypes; i++)
1673 free(table->types[i]);
1674
1675 free(table->types);
1676 }
1677
1678 free(table->name);
1680
1681 free(table);
1682}
static void merge_free_rows(struct merge_table *table)
Definition: database.c:1636
const struct column * columns
const WCHAR * name

Referenced by get_merge_table(), merge_diff_tables(), and MsiDatabaseMergeW().

◆ free_streams()

static void free_streams ( MSIDATABASE db)
static

Definition at line 66 of file database.c.

67{
68 UINT i;
69 for (i = 0; i < db->num_streams; i++)
70 {
71 if (db->streams[i].stream) IStream_Release( db->streams[i].stream );
72 }
73 free( db->streams );
74}
MSISTREAM * streams
Definition: msipriv.h:120
UINT num_streams
Definition: msipriv.h:121
IStream * stream
Definition: msipriv.h:89

Referenced by MSI_CloseDatabase().

◆ free_transforms()

static void free_transforms ( MSIDATABASE db)
static

Definition at line 55 of file database.c.

56{
57 while( !list_empty( &db->transforms ) )
58 {
60 list_remove( &t->entry );
61 IStorage_Release( t->stg );
62 free( t );
63 }
64}
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
uint32_t entry
Definition: isohybrid.c:63
Definition: list.h:15
#define LIST_ENTRY(type)
Definition: queue.h:175

Referenced by MSI_CloseDatabase().

◆ gather_merge_data()

static UINT gather_merge_data ( MSIDATABASE db,
MSIDATABASE merge,
struct list tabledata 
)
static

Definition at line 1780 of file database.c.

1782{
1783 MSIQUERY *view;
1784 struct merge_data data;
1785 UINT r;
1786
1787 r = MSI_DatabaseOpenViewW(merge, L"SELECT * FROM `_Tables`", &view);
1788 if (r != ERROR_SUCCESS)
1789 return r;
1790
1791 data.db = db;
1792 data.merge = merge;
1793 data.tabledata = tabledata;
1795 msiobj_release(&view->hdr);
1796 return r;
1797}
static UINT merge_diff_tables(MSIRECORD *rec, LPVOID param)
Definition: database.c:1729
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID)
Definition: msiquery.c:163
struct list * tabledata
Definition: database.c:1262
MSIDATABASE * db
Definition: database.c:1258

Referenced by MsiDatabaseMergeW().

◆ get_key_value()

static LPWSTR get_key_value ( MSIQUERY view,
LPCWSTR  key,
MSIRECORD rec 
)
static

Definition at line 1380 of file database.c.

1381{
1382 MSIRECORD *colnames;
1383 LPWSTR str, val;
1384 UINT r, i = 0;
1385 DWORD sz = 0;
1386 int cmp;
1387
1389 if (r != ERROR_SUCCESS)
1390 return NULL;
1391
1392 do
1393 {
1394 str = msi_dup_record_field(colnames, ++i);
1395 cmp = wcscmp( key, str );
1396 free(str);
1397 } while (cmp);
1398
1399 msiobj_release(&colnames->hdr);
1400
1401 r = MSI_RecordGetStringW(rec, i, NULL, &sz);
1402 if (r != ERROR_SUCCESS)
1403 return NULL;
1404 sz++;
1405
1406 if (MSI_RecordGetString(rec, i)) /* check record field is a string */
1407 {
1408 /* quote string record fields */
1409 sz += 2;
1410 val = malloc(sz * sizeof(WCHAR));
1411 if (!val)
1412 return NULL;
1413
1414 lstrcpyW(val, L"'");
1415 r = MSI_RecordGetStringW(rec, i, val + 1, &sz);
1416 lstrcpyW(val + 1 + sz, L"'");
1417 }
1418 else
1419 {
1420 /* do not quote integer record fields */
1421 val = malloc(sz * sizeof(WCHAR));
1422 if (!val)
1423 return NULL;
1424
1425 r = MSI_RecordGetStringW(rec, i, val, &sz);
1426 }
1427
1428 if (r != ERROR_SUCCESS)
1429 {
1430 ERR("failed to get string!\n");
1431 free(val);
1432 return NULL;
1433 }
1434
1435 return val;
1436}
#define cmp(status, error)
Definition: error.c:114
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index)
Definition: record.c:1002
UINT MSI_ViewGetColumnInfo(MSIQUERY *, MSICOLINFO, MSIRECORD **)
Definition: msiquery.c:602
@ MSICOLINFO_NAMES
Definition: msiquery.h:36
const WCHAR * str
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)

Referenced by create_diff_row_query().

◆ get_merge_table()

static UINT get_merge_table ( MSIDATABASE db,
const WCHAR name,
struct merge_table **  ptable 
)
static

Definition at line 1684 of file database.c.

1685{
1686 UINT r;
1687 struct merge_table *table;
1688 MSIQUERY *mergeview = NULL;
1689
1690 table = calloc(1, sizeof(*table));
1691 if (!table)
1692 {
1693 *ptable = NULL;
1694 return ERROR_OUTOFMEMORY;
1695 }
1696
1697 r = get_table_labels(db, name, &table->labels, &table->numlabels);
1698 if (r != ERROR_SUCCESS)
1699 goto err;
1700
1701 r = MSI_OpenQuery(db, &mergeview, L"SELECT * FROM `%s`", name);
1702 if (r != ERROR_SUCCESS)
1703 goto err;
1704
1705 r = get_query_columns(mergeview, &table->columns, &table->numcolumns);
1706 if (r != ERROR_SUCCESS)
1707 goto err;
1708
1709 r = get_query_types(mergeview, &table->types, &table->numtypes);
1710 if (r != ERROR_SUCCESS)
1711 goto err;
1712
1713 list_init(&table->rows);
1714
1715 table->name = wcsdup(name);
1716 table->numconflicts = 0;
1717
1718 msiobj_release(&mergeview->hdr);
1719 *ptable = table;
1720 return ERROR_SUCCESS;
1721
1722err:
1723 msiobj_release(&mergeview->hdr);
1725 *ptable = NULL;
1726 return r;
1727}
static void list_init(struct list_entry *head)
Definition: list.h:51
static UINT get_query_types(MSIQUERY *query, WCHAR ***types, DWORD *numtypes)
Definition: database.c:1608
static UINT get_query_columns(MSIQUERY *query, WCHAR ***columns, DWORD *numcolumns)
Definition: database.c:1579
static void free_merge_table(struct merge_table *table)
Definition: database.c:1650
static UINT get_table_labels(MSIDATABASE *db, const WCHAR *table, WCHAR ***labels, DWORD *numlabels)
Definition: database.c:1550
#define err(...)
_Check_return_ _CRTIMP wchar_t *__cdecl wcsdup(_In_z_ const wchar_t *_Str)
Definition: name.c:39
MSIOBJECTHDR hdr
Definition: msipriv.h:129

Referenced by merge_diff_tables().

◆ get_query_columns()

static UINT get_query_columns ( MSIQUERY query,
WCHAR ***  columns,
DWORD numcolumns 
)
static

Definition at line 1579 of file database.c.

1580{
1581 UINT r, i, count;
1582 MSIRECORD *prec = NULL;
1583
1585 if (r != ERROR_SUCCESS)
1586 return r;
1587
1589 *columns = malloc(count * sizeof(WCHAR *));
1590 if (!*columns)
1591 {
1593 goto end;
1594 }
1595
1596 for (i=1; i<=count; i++ )
1597 {
1598 (*columns)[i-1] = wcsdup(MSI_RecordGetString(prec, i));
1599 }
1600
1601 *numcolumns = count;
1602
1603end:
1604 msiobj_release( &prec->hdr );
1605 return r;
1606}
GLuint GLuint end
Definition: gl.h:1545

Referenced by get_merge_table().

◆ get_query_types()

static UINT get_query_types ( MSIQUERY query,
WCHAR ***  types,
DWORD numtypes 
)
static

Definition at line 1608 of file database.c.

1609{
1610 UINT r, i, count;
1611 MSIRECORD *prec = NULL;
1612
1614 if (r != ERROR_SUCCESS)
1615 return r;
1616
1618 *types = malloc(count * sizeof(WCHAR *));
1619 if (!*types)
1620 {
1622 goto end;
1623 }
1624
1625 *numtypes = count;
1626 for (i=1; i<=count; i++ )
1627 {
1628 (*types)[i-1] = wcsdup(MSI_RecordGetString(prec, i));
1629 }
1630
1631end:
1632 msiobj_release( &prec->hdr );
1633 return r;
1634}
@ MSICOLINFO_TYPES
Definition: msiquery.h:37

Referenced by get_merge_table().

◆ get_table_labels()

static UINT get_table_labels ( MSIDATABASE db,
const WCHAR table,
WCHAR ***  labels,
DWORD numlabels 
)
static

Definition at line 1550 of file database.c.

1551{
1552 UINT r, i, count;
1553 MSIRECORD *prec = NULL;
1554
1555 r = MSI_DatabaseGetPrimaryKeys(db, table, &prec);
1556 if (r != ERROR_SUCCESS)
1557 return r;
1558
1560 *numlabels = count + 1;
1561 *labels = malloc((*numlabels) * sizeof(WCHAR *));
1562 if (!*labels)
1563 {
1565 goto end;
1566 }
1567
1568 (*labels)[0] = wcsdup(table);
1569 for (i=1; i<=count; i++ )
1570 {
1571 (*labels)[i] = wcsdup(MSI_RecordGetString(prec, i));
1572 }
1573
1574end:
1575 msiobj_release( &prec->hdr );
1576 return r;
1577}

Referenced by get_merge_table().

◆ import_stream_filename()

static WCHAR * import_stream_filename ( const WCHAR path,
const WCHAR name 
)
static

Definition at line 632 of file database.c.

633{
634 DWORD len;
636
637 len = lstrlenW(path) + lstrlenW(name) + 1;
638 fullname = malloc(len * sizeof(WCHAR));
639 if (!fullname)
640 return NULL;
641
643
644 /* chop off extension from path */
645 ptr = wcsrchr(fullname, '.');
646 if (!ptr)
647 {
648 free(fullname);
649 return NULL;
650 }
651 *ptr++ = '\\';
652 lstrcpyW( ptr, name );
653 return fullname;
654}
#define wcsrchr
Definition: compat.h:16
const char * fullname
Definition: shader.c:1766

Referenced by construct_record().

◆ merge_diff_row()

static UINT merge_diff_row ( MSIRECORD rec,
LPVOID  param 
)
static

Definition at line 1490 of file database.c.

1491{
1492 struct merge_data *data = param;
1493 struct merge_table *table = data->curtable;
1494 struct merge_row *mergerow;
1495 MSIQUERY *dbview = NULL;
1496 MSIRECORD *row = NULL;
1497 LPWSTR query = NULL;
1499
1500 if (TABLE_Exists(data->db, table->name))
1501 {
1502 query = create_diff_row_query(data->merge, data->curview, table->name, rec);
1503 if (!query)
1504 return ERROR_OUTOFMEMORY;
1505
1506 r = MSI_DatabaseOpenViewW(data->db, query, &dbview);
1507 if (r != ERROR_SUCCESS)
1508 goto done;
1509
1510 r = MSI_ViewExecute(dbview, NULL);
1511 if (r != ERROR_SUCCESS)
1512 goto done;
1513
1514 r = MSI_ViewFetch(dbview, &row);
1515 if (r == ERROR_SUCCESS && !MSI_RecordsAreEqual(rec, row))
1516 {
1517 table->numconflicts++;
1518 goto done;
1519 }
1520 else if (r != ERROR_NO_MORE_ITEMS)
1521 goto done;
1522
1523 r = ERROR_SUCCESS;
1524 }
1525
1526 mergerow = malloc(sizeof(*mergerow));
1527 if (!mergerow)
1528 {
1530 goto done;
1531 }
1532
1533 mergerow->data = MSI_CloneRecord(rec);
1534 if (!mergerow->data)
1535 {
1537 free(mergerow);
1538 goto done;
1539 }
1540
1541 list_add_tail(&table->rows, &mergerow->entry);
1542
1543done:
1544 free(query);
1545 msiobj_release(&row->hdr);
1546 msiobj_release(&dbview->hdr);
1547 return r;
1548}
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static LPWSTR create_diff_row_query(MSIDATABASE *merge, MSIQUERY *view, LPWSTR table, MSIRECORD *rec)
Definition: database.c:1438
GLfloat param
Definition: glext.h:5796
BOOL MSI_RecordsAreEqual(MSIRECORD *, MSIRECORD *)
Definition: record.c:986
BOOL TABLE_Exists(MSIDATABASE *db, LPCWSTR name)
Definition: table.c:962
MSIRECORD * MSI_CloneRecord(MSIRECORD *)
Definition: record.c:921
MSIRECORD * data
Definition: database.c:1253
struct list entry
Definition: database.c:1252

Referenced by merge_diff_tables().

◆ merge_diff_tables()

static UINT merge_diff_tables ( MSIRECORD rec,
LPVOID  param 
)
static

Definition at line 1729 of file database.c.

1730{
1731 struct merge_data *data = param;
1732 struct merge_table *table;
1733 MSIQUERY *dbview = NULL;
1734 MSIQUERY *mergeview = NULL;
1735 LPCWSTR name;
1736 UINT r;
1737
1738 name = MSI_RecordGetString(rec, 1);
1739
1740 r = MSI_OpenQuery(data->merge, &mergeview, L"SELECT * FROM `%s`", name);
1741 if (r != ERROR_SUCCESS)
1742 goto done;
1743
1744 if (TABLE_Exists(data->db, name))
1745 {
1746 r = MSI_OpenQuery(data->db, &dbview, L"SELECT * FROM `%s`", name);
1747 if (r != ERROR_SUCCESS)
1748 goto done;
1749
1750 r = merge_verify_colnames(dbview, mergeview);
1751 if (r != ERROR_SUCCESS)
1752 goto done;
1753
1754 r = merge_verify_primary_keys(data->db, data->merge, name);
1755 if (r != ERROR_SUCCESS)
1756 goto done;
1757 }
1758
1759 r = get_merge_table(data->merge, name, &table);
1760 if (r != ERROR_SUCCESS)
1761 goto done;
1762
1763 data->curtable = table;
1764 data->curview = mergeview;
1766 if (r != ERROR_SUCCESS)
1767 {
1769 goto done;
1770 }
1771
1772 list_add_tail(data->tabledata, &table->entry);
1773
1774done:
1775 msiobj_release(&dbview->hdr);
1776 msiobj_release(&mergeview->hdr);
1777 return r;
1778}
static UINT merge_verify_primary_keys(MSIDATABASE *db, MSIDATABASE *mergedb, LPCWSTR table)
Definition: database.c:1343
static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
Definition: database.c:1278
static UINT get_merge_table(MSIDATABASE *db, const WCHAR *name, struct merge_table **ptable)
Definition: database.c:1684
static UINT merge_diff_row(MSIRECORD *rec, LPVOID param)
Definition: database.c:1490
LPWSTR name
Definition: database.c:1240
struct list entry

Referenced by gather_merge_data().

◆ merge_free_rows()

static void merge_free_rows ( struct merge_table table)
static

Definition at line 1636 of file database.c.

1637{
1638 struct list *item, *cursor;
1639
1641 {
1642 struct merge_row *row = LIST_ENTRY(item, struct merge_row, entry);
1643
1644 list_remove(&row->entry);
1645 msiobj_release(&row->data->hdr);
1646 free(row);
1647 }
1648}
Definition: list.h:37
const char cursor[]
Definition: icontest.c:13
static ATOM item
Definition: dde.c:856
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list)
Definition: list.h:192

Referenced by free_merge_table().

◆ merge_table()

static UINT merge_table ( MSIDATABASE db,
struct merge_table table 
)
static

Definition at line 1799 of file database.c.

1800{
1801 UINT r;
1802 struct merge_row *row;
1803 MSIVIEW *tv;
1804
1805 if (!TABLE_Exists(db, table->name))
1806 {
1807 r = add_table_to_db(db, table->columns, table->types, table->labels, table->numlabels, table->numcolumns);
1808 if (r != ERROR_SUCCESS)
1809 return ERROR_FUNCTION_FAILED;
1810 }
1811
1812 LIST_FOR_EACH_ENTRY(row, &table->rows, struct merge_row, entry)
1813 {
1814 r = TABLE_CreateView(db, table->name, &tv);
1815 if (r != ERROR_SUCCESS)
1816 return r;
1817
1818 r = tv->ops->insert_row(tv, row->data, -1, FALSE);
1819 tv->ops->delete(tv);
1820
1821 if (r != ERROR_SUCCESS)
1822 return r;
1823 }
1824
1825 return ERROR_SUCCESS;
1826}
#define FALSE
Definition: types.h:117
static UINT add_table_to_db(MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, DWORD num_labels, DWORD num_columns)
Definition: database.c:591
UINT TABLE_CreateView(MSIDATABASE *db, LPCWSTR name, MSIVIEW **view)
Definition: table.c:2191
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
UINT(* insert_row)(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: msipriv.h:283
UINT(* delete)(struct tagMSIVIEW *)
Definition: msipriv.h:324
const MSIVIEWOPS * ops
Definition: msipriv.h:355

◆ merge_type_match()

static BOOL merge_type_match ( LPCWSTR  type1,
LPCWSTR  type2 
)
static

Definition at line 1265 of file database.c.

1266{
1267 if (((type1[0] == 'l') || (type1[0] == 's')) &&
1268 ((type2[0] == 'l') || (type2[0] == 's')))
1269 return TRUE;
1270
1271 if (((type1[0] == 'L') || (type1[0] == 'S')) &&
1272 ((type2[0] == 'L') || (type2[0] == 'S')))
1273 return TRUE;
1274
1275 return !wcscmp( type1, type2 );
1276}

Referenced by merge_verify_colnames().

◆ merge_verify_colnames()

static UINT merge_verify_colnames ( MSIQUERY dbview,
MSIQUERY mergeview 
)
static

Definition at line 1278 of file database.c.

1279{
1280 MSIRECORD *dbrec, *mergerec;
1281 UINT r, i, count;
1282
1283 r = MSI_ViewGetColumnInfo(dbview, MSICOLINFO_NAMES, &dbrec);
1284 if (r != ERROR_SUCCESS)
1285 return r;
1286
1287 r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_NAMES, &mergerec);
1288 if (r != ERROR_SUCCESS)
1289 {
1290 msiobj_release(&dbrec->hdr);
1291 return r;
1292 }
1293
1295 for (i = 1; i <= count; i++)
1296 {
1297 if (!MSI_RecordGetString(mergerec, i))
1298 break;
1299
1300 if (wcscmp( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
1301 {
1303 goto done;
1304 }
1305 }
1306
1307 msiobj_release(&dbrec->hdr);
1308 msiobj_release(&mergerec->hdr);
1309 dbrec = mergerec = NULL;
1310
1311 r = MSI_ViewGetColumnInfo(dbview, MSICOLINFO_TYPES, &dbrec);
1312 if (r != ERROR_SUCCESS)
1313 return r;
1314
1315 r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_TYPES, &mergerec);
1316 if (r != ERROR_SUCCESS)
1317 {
1318 msiobj_release(&dbrec->hdr);
1319 return r;
1320 }
1321
1323 for (i = 1; i <= count; i++)
1324 {
1325 if (!MSI_RecordGetString(mergerec, i))
1326 break;
1327
1329 MSI_RecordGetString(mergerec, i)))
1330 {
1332 break;
1333 }
1334 }
1335
1336done:
1337 msiobj_release(&dbrec->hdr);
1338 msiobj_release(&mergerec->hdr);
1339
1340 return r;
1341}
static BOOL merge_type_match(LPCWSTR type1, LPCWSTR type2)
Definition: database.c:1265
#define ERROR_DATATYPE_MISMATCH
Definition: winerror.h:987

Referenced by merge_diff_tables().

◆ merge_verify_primary_keys()

static UINT merge_verify_primary_keys ( MSIDATABASE db,
MSIDATABASE mergedb,
LPCWSTR  table 
)
static

Definition at line 1343 of file database.c.

1345{
1346 MSIRECORD *dbrec, *mergerec = NULL;
1347 UINT r, i, count;
1348
1349 r = MSI_DatabaseGetPrimaryKeys(db, table, &dbrec);
1350 if (r != ERROR_SUCCESS)
1351 return r;
1352
1353 r = MSI_DatabaseGetPrimaryKeys(mergedb, table, &mergerec);
1354 if (r != ERROR_SUCCESS)
1355 goto done;
1356
1358 if (count != MSI_RecordGetFieldCount(mergerec))
1359 {
1361 goto done;
1362 }
1363
1364 for (i = 1; i <= count; i++)
1365 {
1366 if (wcscmp( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
1367 {
1369 goto done;
1370 }
1371 }
1372
1373done:
1374 msiobj_release(&dbrec->hdr);
1375 msiobj_release(&mergerec->hdr);
1376
1377 return r;
1378}

Referenced by merge_diff_tables().

◆ MSI_CloseDatabase()

static VOID MSI_CloseDatabase ( MSIOBJECTHDR arg)
static

Definition at line 86 of file database.c.

87{
88 MSIDATABASE *db = (MSIDATABASE *) arg;
89
90 free( db->path );
91 free_streams( db );
93 free_transforms( db );
95 IStorage_Release( db->storage );
96 if (db->deletefile)
97 {
99 free( db->deletefile );
100 }
101 free( db->tempfolder );
102}
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
static void free_streams(MSIDATABASE *db)
Definition: database.c:66
static void free_transforms(MSIDATABASE *db)
Definition: database.c:55
VOID msi_destroy_stringtable(string_table *st)
Definition: string.c:107
void free_cached_tables(MSIDATABASE *db)
Definition: table.c:472
LPWSTR deletefile
Definition: msipriv.h:113
IStorage * storage
Definition: msipriv.h:109
LPWSTR tempfolder
Definition: msipriv.h:114
string_table * strings
Definition: msipriv.h:110
LPWSTR path
Definition: msipriv.h:112

Referenced by MSI_OpenDatabaseW().

◆ MSI_DatabaseExport()

static UINT MSI_DatabaseExport ( MSIDATABASE db,
LPCWSTR  table,
LPCWSTR  folder,
LPCWSTR  file 
)
static

Definition at line 1072 of file database.c.

1073{
1074 MSIRECORD *rec = NULL;
1075 MSIQUERY *view = NULL;
1076 WCHAR *filename;
1077 HANDLE handle;
1078 UINT len, r;
1079
1080 TRACE("%p %s %s %s\n", db, debugstr_w(table),
1082
1083 if (!folder || !file)
1085
1086 len = lstrlenW(folder) + lstrlenW(file) + 2;
1087 filename = malloc(len * sizeof(WCHAR));
1088 if (!filename)
1089 return ERROR_OUTOFMEMORY;
1090
1092 lstrcatW( filename, L"\\" );
1094
1097 free( filename );
1099 return ERROR_FUNCTION_FAILED;
1100
1101 if (!wcscmp( table, L"_ForceCodepage" ))
1102 {
1105 goto done;
1106 }
1107
1108 if (!wcscmp( table, L"_SummaryInformation" ))
1109 {
1111 goto done;
1112 }
1113
1114 r = MSI_OpenQuery( db, &view, L"SELECT * FROM %s", table );
1115 if (r == ERROR_SUCCESS)
1116 {
1118
1119 /* write out row 1, the column names */
1121 if (r == ERROR_SUCCESS)
1122 {
1123 export_record( &row_export_info, rec, 1 );
1124 msiobj_release( &rec->hdr );
1125 }
1126
1127 /* write out row 2, the column types */
1129 if (r == ERROR_SUCCESS)
1130 {
1131 export_record( &row_export_info, rec, 1 );
1132 msiobj_release( &rec->hdr );
1133 }
1134
1135 /* write out row 3, the table name + keys */
1136 r = MSI_DatabaseGetPrimaryKeys( db, table, &rec );
1137 if (r == ERROR_SUCCESS)
1138 {
1139 MSI_RecordSetStringW( rec, 0, table );
1140 export_record( &row_export_info, rec, 0 );
1141 msiobj_release( &rec->hdr );
1142 }
1143
1144 /* write out row 4 onwards, the data */
1146 msiobj_release( &view->hdr );
1147 }
1148
1149done:
1151 return r;
1152}
#define GENERIC_READ
Definition: compat.h:135
static UINT export_row(MSIRECORD *row, void *arg)
Definition: database.c:1042
static UINT export_summaryinformation(MSIDATABASE *db, HANDLE handle)
Definition: database.c:1059
static UINT export_forcecodepage(HANDLE handle, UINT codepage)
Definition: database.c:1047
const char * filename
Definition: ioapi.h:137
#define debugstr_w
Definition: kernel32.h:32
UINT msi_get_string_table_codepage(const string_table *st)
Definition: string.c:671
#define TRACE(s)
Definition: solgame.cpp:4

Referenced by MsiDatabaseExportW().

◆ MSI_DatabaseImport()

static UINT MSI_DatabaseImport ( MSIDATABASE db,
LPCWSTR  folder,
LPCWSTR  file 
)
static

Definition at line 741 of file database.c.

742{
743 UINT r;
744 DWORD len, i, num_labels = 0, num_types = 0, num_columns = 0, num_records = 0;
745 WCHAR **columns, **types, **labels, *path, *ptr, *data, ***records = NULL, ***temp_records;
746
747 TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
748
749 if (!folder || !file)
751
752 len = lstrlenW(folder) + lstrlenW(L"\\") + lstrlenW(file) + 1;
753 path = malloc( len * sizeof(WCHAR) );
754 if (!path)
755 return ERROR_OUTOFMEMORY;
756
757 lstrcpyW( path, folder );
758 lstrcatW( path, L"\\" );
759 lstrcatW( path, file );
760
762 if (!data)
763 {
764 free(path);
766 }
767
768 ptr = data;
769 parse_line( &ptr, &columns, &num_columns, &len );
770 parse_line( &ptr, &types, &num_types, &len );
771 parse_line( &ptr, &labels, &num_labels, &len );
772
773 if (num_columns == 1 && !columns[0][0] && num_labels == 1 && !labels[0][0] &&
774 num_types == 2 && !wcscmp( types[1], L"_ForceCodepage" ))
775 {
777 goto done;
778 }
779
780 if (num_columns != num_types)
781 {
783 goto done;
784 }
785
786 records = malloc(sizeof(WCHAR **));
787 if (!records)
788 {
790 goto done;
791 }
792
793 /* read in the table records */
794 while (len)
795 {
796 r = parse_line( &ptr, &records[num_records], &num_columns, &len );
797 if (r != ERROR_SUCCESS)
798 goto done;
799
800 num_records++;
801 temp_records = realloc(records, (num_records + 1) * sizeof(WCHAR **));
802 if (!temp_records)
803 {
805 goto done;
806 }
807 records = temp_records;
808 }
809
810 if (!wcscmp(labels[0], L"_SummaryInformation"))
811 {
812 r = msi_add_suminfo( db, records, num_records, num_columns );
813 if (r != ERROR_SUCCESS)
814 {
816 goto done;
817 }
818 }
819 else
820 {
821 if (!TABLE_Exists(db, labels[0]))
822 {
823 r = add_table_to_db( db, columns, types, labels, num_labels, num_columns );
824 if (r != ERROR_SUCCESS)
825 {
827 goto done;
828 }
829 }
830
831 r = add_records_to_table( db, columns, types, labels, records, num_columns, num_records, path );
832 }
833
834done:
835 free(path);
836 free(data);
837 free(columns);
838 free(types);
839 free(labels);
840
841 for (i = 0; i < num_records; i++)
842 free(records[i]);
843
844 free(records);
845 return r;
846}
static UINT parse_line(WCHAR **line, WCHAR ***entries, DWORD *num_entries, DWORD *len)
Definition: database.c:380
static UINT add_records_to_table(MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, WCHAR ***records, int num_columns, int num_records, WCHAR *path)
Definition: database.c:700
static WCHAR * read_text_archive(const WCHAR *path, DWORD *len)
Definition: database.c:350
UINT msi_add_suminfo(MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns)
Definition: suminfo.c:1078
UINT msi_set_string_table_codepage(string_table *st, UINT codepage)
Definition: string.c:676

Referenced by MsiDatabaseImportW().

◆ MSI_OpenDatabaseW()

UINT MSI_OpenDatabaseW ( LPCWSTR  szDBPath,
LPCWSTR  szPersist,
MSIDATABASE **  pdb 
)

Definition at line 140 of file database.c.

141{
142 IStorage *stg = NULL;
143 HRESULT r;
144 MSIDATABASE *db = NULL;
147 UINT mode;
148 STATSTG stat;
149 BOOL created = FALSE, patch = FALSE;
151
152 TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
153
154 if( !pdb )
156
157 save_path = szDBPath;
158 if ( IS_INTMSIDBOPEN(szPersist) )
159 {
160 mode = LOWORD(szPersist);
161 }
162 else
163 {
164 if (!CopyFileW( szDBPath, szPersist, FALSE ))
165 return ERROR_OPEN_FAILED;
166
167 szDBPath = szPersist;
169 created = TRUE;
170 }
171
173 {
174 TRACE("Database is a patch\n");
175 mode &= ~MSI_OPEN_PATCHFILE;
176 patch = TRUE;
177 }
178
179 if( mode == MSI_OPEN_READONLY )
180 {
181 r = StgOpenStorage( szDBPath, NULL,
183 }
184 else if( mode == MSI_OPEN_CREATE )
185 {
186 r = StgCreateDocfile( szDBPath,
188
189 if( SUCCEEDED(r) )
190 r = db_initialize( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
191 created = TRUE;
192 }
193 else if( mode == MSI_OPEN_CREATEDIRECT )
194 {
195 r = StgCreateDocfile( szDBPath,
197
198 if( SUCCEEDED(r) )
199 r = db_initialize( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
200 created = TRUE;
201 }
202 else if( mode == MSI_OPEN_TRANSACT )
203 {
204 r = StgOpenStorage( szDBPath, NULL,
206 }
207 else if( mode == MSI_OPEN_DIRECT )
208 {
209 r = StgOpenStorage( szDBPath, NULL,
211 }
212 else
213 {
214 ERR("unknown flag %x\n",mode);
216 }
217
218 if( FAILED( r ) || !stg )
219 {
220 WARN("open failed r = %#lx for %s\n", r, debugstr_w(szDBPath));
222 }
223
224 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
225 if( FAILED( r ) )
226 {
227 FIXME("Failed to stat storage\n");
228 goto end;
229 }
230
231 if ( !IsEqualGUID( &stat.clsid, &CLSID_MsiDatabase ) &&
232 !IsEqualGUID( &stat.clsid, &CLSID_MsiPatch ) &&
233 !IsEqualGUID( &stat.clsid, &CLSID_MsiTransform ) )
234 {
235 ERR("storage GUID is not a MSI database GUID %s\n",
236 debugstr_guid(&stat.clsid) );
237 goto end;
238 }
239
240 if ( patch && !IsEqualGUID( &stat.clsid, &CLSID_MsiPatch ) )
241 {
242 ERR("storage GUID is not the MSI patch GUID %s\n",
243 debugstr_guid(&stat.clsid) );
245 goto end;
246 }
247
250 if( !db )
251 {
252 FIXME("Failed to allocate a handle\n");
253 goto end;
254 }
255
256 if (!wcschr( save_path, '\\' ))
257 {
259 lstrcatW( path, L"\\" );
261 }
262 else
264
265 db->path = wcsdup( path );
268
269 if( TRACE_ON( msi ) )
270 enum_stream_names( stg );
271
272 db->storage = stg;
273 db->mode = mode;
274 if (created)
275 db->deletefile = wcsdup( szDBPath );
276 list_init( &db->tables );
277 list_init( &db->transforms );
278
280 if( !db->strings )
281 goto end;
282
284
285 msiobj_addref( &db->hdr );
286 IStorage_AddRef( stg );
287 *pdb = db;
288
289end:
290 if( db )
291 msiobj_release( &db->hdr );
292 if( stg )
293 IStorage_Release( stg );
294
295 return ret;
296}
#define stat
Definition: acwin.h:99
static struct @1561 save_path[MOVE_LIST_SIZE]
#define FIXME(fmt,...)
Definition: precomp.h:53
static PDB pdb
Definition: db.cpp:172
#define wcschr
Definition: compat.h:17
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define TRACE_ON(x)
Definition: compat.h:75
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
static VOID MSI_CloseDatabase(MSIOBJECTHDR *arg)
Definition: database.c:86
#define IS_INTMSIDBOPEN(x)
Definition: database.c:53
static HRESULT db_initialize(IStorage *stg, const GUID *clsid)
Definition: database.c:104
void * alloc_msiobject(UINT type, UINT size, msihandledestructor destroy)
Definition: handle.c:201
void msiobj_addref(MSIOBJECTHDR *info)
Definition: handle.c:217
HRESULT WINAPI StgOpenStorage(const OLECHAR *pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8755
HRESULT WINAPI StgCreateDocfile(LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8636
GLenum mode
Definition: glext.h:6217
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define debugstr_guid
Definition: kernel32.h:35
#define MSI_INITIAL_MEDIA_TRANSFORM_DISKID
Definition: msipriv.h:84
#define MSIHANDLETYPE_DATABASE
Definition: msipriv.h:722
#define MSI_OPEN_DIRECT
Definition: msipriv.h:101
#define MSI_OPEN_CREATEDIRECT
Definition: msipriv.h:103
#define MSI_OPEN_TRANSACT
Definition: msipriv.h:100
string_table * msi_load_string_table(IStorage *stg, UINT *bytes_per_strref)
Definition: string.c:478
#define MSI_OPEN_CREATE
Definition: msipriv.h:102
#define MSI_OPEN_READONLY
Definition: msipriv.h:99
void enum_stream_names(IStorage *stg)
Definition: table.c:206
#define MSI_INITIAL_MEDIA_TRANSFORM_OFFSET
Definition: msipriv.h:83
#define MSI_OPEN_PATCHFILE
Definition: msipriv.h:104
#define STGM_CREATE
Definition: objbase.h:926
#define STGM_DIRECT
Definition: objbase.h:914
#define STGM_READWRITE
Definition: objbase.h:919
#define STGM_TRANSACTED
Definition: objbase.h:915
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_SHARE_DENY_WRITE
Definition: objbase.h:922
#define STGM_READ
Definition: objbase.h:917
#define LOWORD(l)
Definition: pedump.c:82
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
Definition: stat.h:55
UINT media_transform_disk_id
Definition: msipriv.h:117
UINT bytes_per_strref
Definition: msipriv.h:111
MSIOBJECTHDR hdr
Definition: msipriv.h:108
struct list tables
Definition: msipriv.h:118
UINT media_transform_offset
Definition: msipriv.h:116
#define ERROR_OPEN_FAILED
Definition: winerror.h:184

Referenced by apply_patch_package(), MSI_ApplicablePatchW(), msi_apply_registered_patch(), MSI_OpenPackageW(), MsiGetSummaryInformationW(), and MsiOpenDatabaseW().

◆ MsiDatabaseExportA()

UINT WINAPI MsiDatabaseExportA ( MSIHANDLE  handle,
const char szTable,
const char szFolder,
const char szFilename 
)

Definition at line 1184 of file database.c.

1185{
1186 WCHAR *path = NULL, *file = NULL, *table = NULL;
1188
1189 TRACE( "%lu %s %s %s\n", handle, debugstr_a(szTable), debugstr_a(szFolder), debugstr_a(szFilename) );
1190
1191 if( szTable )
1192 {
1193 table = strdupAtoW( szTable );
1194 if( !table )
1195 goto end;
1196 }
1197
1198 if( szFolder )
1199 {
1200 path = strdupAtoW( szFolder );
1201 if( !path )
1202 goto end;
1203 }
1204
1205 if( szFilename )
1206 {
1207 file = strdupAtoW( szFilename );
1208 if( !file )
1209 goto end;
1210 }
1211
1213
1214end:
1215 free( table );
1216 free( path );
1217 free( file );
1218
1219 return r;
1220}
static WCHAR * strdupAtoW(const char *str)
Definition: main.c:65
UINT WINAPI MsiDatabaseExportW(MSIHANDLE handle, const WCHAR *szTable, const WCHAR *szFolder, const WCHAR *szFilename)
Definition: database.c:1169
#define debugstr_a
Definition: kernel32.h:31

Referenced by test_embedded_nulls(), test_forcecodepage(), test_invalid_functions(), and test_msiexport().

◆ MsiDatabaseExportW()

UINT WINAPI MsiDatabaseExportW ( MSIHANDLE  handle,
const WCHAR szTable,
const WCHAR szFolder,
const WCHAR szFilename 
)

Definition at line 1169 of file database.c.

1170{
1171 MSIDATABASE *db;
1172 UINT r;
1173
1174 TRACE( "%lu %s %s %s\n", handle, debugstr_w(szTable), debugstr_w(szFolder), debugstr_w(szFilename) );
1175
1177 return ERROR_INVALID_HANDLE;
1178
1179 r = MSI_DatabaseExport( db, szTable, szFolder, szFilename );
1180 msiobj_release( &db->hdr );
1181 return r;
1182}
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
static UINT MSI_DatabaseExport(MSIDATABASE *db, LPCWSTR table, LPCWSTR folder, LPCWSTR file)
Definition: database.c:1072
void * msihandle2msiinfo(MSIHANDLE handle, UINT type)
Definition: handle.c:158

Referenced by MsiDatabaseExportA().

◆ MsiDatabaseImportA()

UINT WINAPI MsiDatabaseImportA ( MSIHANDLE  handle,
const char szFolder,
const char szFilename 
)

Definition at line 863 of file database.c.

864{
865 WCHAR *path = NULL, *file = NULL;
867
868 TRACE( "%lu %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename) );
869
870 if( szFolder )
871 {
872 path = strdupAtoW( szFolder );
873 if( !path )
874 goto end;
875 }
876
877 if( szFilename )
878 {
879 file = strdupAtoW( szFilename );
880 if( !file )
881 goto end;
882 }
883
885
886end:
887 free( path );
888 free( file );
889
890 return r;
891}
UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, const WCHAR *szFolder, const WCHAR *szFilename)
Definition: database.c:848

Referenced by add_table_to_db(), create_database_suminfo(), create_database_wordcount(), test_binary_import(), test_controlevent(), test_dbmerge(), test_embedded_nulls(), test_externalui_message(), test_forcecodepage(), test_invalid_functions(), test_msiimport(), test_quotes(), and test_top_level_action().

◆ MsiDatabaseImportW()

UINT WINAPI MsiDatabaseImportW ( MSIHANDLE  handle,
const WCHAR szFolder,
const WCHAR szFilename 
)

Definition at line 848 of file database.c.

849{
850 MSIDATABASE *db;
851 UINT r;
852
853 TRACE( "%lu %s %s\n", handle, debugstr_w(szFolder), debugstr_w(szFilename) );
854
857
858 r = MSI_DatabaseImport( db, szFolder, szFilename );
859 msiobj_release( &db->hdr );
860 return r;
861}
static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
Definition: database.c:741

Referenced by MsiDatabaseImportA(), and test_int_widths().

◆ MsiDatabaseMergeA()

UINT WINAPI MsiDatabaseMergeA ( MSIHANDLE  hDatabase,
MSIHANDLE  hDatabaseMerge,
const char szTableName 
)

Definition at line 1222 of file database.c.

1223{
1224 UINT r;
1225 WCHAR *table;
1226
1227 TRACE("%lu, %lu, %s\n", hDatabase, hDatabaseMerge, debugstr_a(szTableName) );
1228
1229 table = strdupAtoW(szTableName);
1230 r = MsiDatabaseMergeW(hDatabase, hDatabaseMerge, table);
1231
1232 free(table);
1233 return r;
1234}
UINT WINAPI MsiDatabaseMergeW(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const WCHAR *szTableName)
Definition: database.c:1857

Referenced by test_dbmerge(), and test_invalid_functions().

◆ MsiDatabaseMergeW()

UINT WINAPI MsiDatabaseMergeW ( MSIHANDLE  hDatabase,
MSIHANDLE  hDatabaseMerge,
const WCHAR szTableName 
)

Definition at line 1857 of file database.c.

1858{
1859 struct list tabledata = LIST_INIT(tabledata);
1860 struct list *item, *cursor;
1861 MSIDATABASE *db, *merge;
1862 struct merge_table *table;
1863 BOOL conflicts;
1864 UINT r;
1865
1866 TRACE( "%lu, %lu, %s\n", hDatabase, hDatabaseMerge, debugstr_w(szTableName) );
1867
1868 if (szTableName && !*szTableName)
1869 return ERROR_INVALID_TABLE;
1870
1873 if (!db || !merge)
1874 {
1876 goto done;
1877 }
1878
1879 r = gather_merge_data(db, merge, &tabledata);
1880 if (r != ERROR_SUCCESS)
1881 goto done;
1882
1883 conflicts = FALSE;
1884 LIST_FOR_EACH_ENTRY(table, &tabledata, struct merge_table, entry)
1885 {
1886 if (table->numconflicts)
1887 {
1888 conflicts = TRUE;
1889
1890 r = update_merge_errors(db, szTableName, table->name,
1891 table->numconflicts);
1892 if (r != ERROR_SUCCESS)
1893 break;
1894 }
1895 else
1896 {
1897 r = merge_table(db, table);
1898 if (r != ERROR_SUCCESS)
1899 break;
1900 }
1901 }
1902
1903 LIST_FOR_EACH_SAFE(item, cursor, &tabledata)
1904 {
1905 struct merge_table *table = LIST_ENTRY(item, struct merge_table, entry);
1908 }
1909
1910 if (conflicts)
1912
1913done:
1914 msiobj_release(&db->hdr);
1915 msiobj_release(&merge->hdr);
1916 return r;
1917}
static UINT gather_merge_data(MSIDATABASE *db, MSIDATABASE *merge, struct list *tabledata)
Definition: database.c:1780
static UINT update_merge_errors(MSIDATABASE *db, LPCWSTR error, LPWSTR table, DWORD numconflicts)
Definition: database.c:1828
#define LIST_INIT(head)
Definition: queue.h:197
#define ERROR_INVALID_TABLE
Definition: winerror.h:986

Referenced by MsiDatabaseMergeA().

◆ MsiGetDatabaseState()

MSIDBSTATE WINAPI MsiGetDatabaseState ( MSIHANDLE  handle)

Definition at line 1919 of file database.c.

1920{
1922 MSIDATABASE *db;
1923
1924 TRACE( "%lu\n", handle );
1925
1927 return MSIDBSTATE_ERROR;
1928
1929 if (db->mode != MSI_OPEN_READONLY )
1931 msiobj_release( &db->hdr );
1932
1933 return ret;
1934}
enum tagMSIDBSTATE MSIDBSTATE
@ MSIDBSTATE_READ
Definition: msiquery.h:144
@ MSIDBSTATE_ERROR
Definition: msiquery.h:143
@ MSIDBSTATE_WRITE
Definition: msiquery.h:145

Referenced by test_invalid_functions().

◆ MsiOpenDatabaseA()

UINT WINAPI MsiOpenDatabaseA ( LPCSTR  szDBPath,
LPCSTR  szPersist,
MSIHANDLE phDB 
)

Definition at line 317 of file database.c.

318{
320 LPWSTR szwDBPath = NULL, szwPersist = NULL;
321
322 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
323
324 if( szDBPath )
325 {
326 szwDBPath = strdupAtoW( szDBPath );
327 if( !szwDBPath )
328 goto end;
329 }
330
331 if( !IS_INTMSIDBOPEN(szPersist) )
332 {
333 szwPersist = strdupAtoW( szPersist );
334 if( !szwPersist )
335 goto end;
336 }
337 else
338 szwPersist = (LPWSTR)(DWORD_PTR)szPersist;
339
340 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
341
342end:
343 if( !IS_INTMSIDBOPEN(szPersist) )
344 free( szwPersist );
345 free( szwDBPath );
346
347 return r;
348}
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:298
uint32_t DWORD_PTR
Definition: typedefs.h:65

Referenced by test_states().

◆ MsiOpenDatabaseW()

UINT WINAPI MsiOpenDatabaseW ( LPCWSTR  szDBPath,
LPCWSTR  szPersist,
MSIHANDLE phDB 
)

Definition at line 298 of file database.c.

299{
300 MSIDATABASE *db;
301 UINT ret;
302
303 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
304
305 ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
306 if( ret == ERROR_SUCCESS )
307 {
308 *phDB = alloc_msihandle( &db->hdr );
309 if (! *phDB)
311 msiobj_release( &db->hdr );
312 }
313
314 return ret;
315}
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
Definition: database.c:140
MSIHANDLE alloc_msihandle(MSIOBJECTHDR *obj)
Definition: handle.c:111

Referenced by create_database_suminfo(), create_database_wordcount(), create_db(), create_package_db(), generate_transform(), get_patch_product_codes(), helper_createpackage(), InstallerImpl_OpenDatabase(), MsiOpenDatabaseA(), MsiVerifyPackageW(), set_admin_summary_info(), set_suminfo(), test_access(), test_binary(), test_binary_import(), test_carriagereturn(), test_collation(), test_createtable(), test_customaction1(), test_dbmerge(), test_dbtopackage(), test_defaultdatabase(), test_deleterow(), test_droptable(), test_embedded_nulls(), test_fieldzero(), test_forcecodepage(), test_icon_table(), test_int_widths(), test_integers(), test_longstrings(), test_msibadqueries(), test_msidatabase(), test_msiexport(), test_MsiGetProductProperty(), test_MsiGetSourcePath(), test_msiimport(), test_msiinsert(), test_MsiOpenDatabase(), test_msipackage(), test_noquotes(), test_packagecoltypes(), test_quotes(), test_rows_order(), test_select_column_names(), test_shortlongsource(), test_simple_patch(), test_special_tables(), test_states(), test_storages_table(), test_streamtable(), test_stringtable(), test_suminfo(), test_suminfo_import(), test_summary_binary(), test_tables_order(), test_try_transform(), test_update(), test_viewfetch_wraparound(), test_viewmodify(), test_viewmodify_assign(), test_viewmodify_delete(), test_viewmodify_delete_temporary(), test_viewmodify_refresh(), test_viewmodify_update(), and test_where_viewmodify().

◆ parse_line()

static UINT parse_line ( WCHAR **  line,
WCHAR ***  entries,
DWORD num_entries,
DWORD len 
)
static

Definition at line 380 of file database.c.

381{
382 LPWSTR ptr = *line, save;
383 DWORD i, count = 1, chars_left = *len;
384
385 *entries = NULL;
386
387 /* stay on this line */
388 while (chars_left && *ptr != '\n')
389 {
390 /* entries are separated by tabs */
391 if (*ptr == '\t')
392 count++;
393
394 ptr++;
395 chars_left--;
396 }
397
398 /*
399 * make sure this line has the same number of entries as there are columns
400 * which are indicated by the first line.
401 */
402 if (*num_entries && *num_entries != count)
404
405 *entries = malloc(count * sizeof(WCHAR *));
406 if (!*entries)
407 return ERROR_OUTOFMEMORY;
408
409 /* store pointers into the data */
410 chars_left = *len;
411 for (i = 0, ptr = *line; i < count; i++)
412 {
413 while (chars_left && *ptr == '\r')
414 {
415 ptr++;
416 chars_left--;
417 }
418 save = ptr;
419
420 while (chars_left && *ptr != '\t' && *ptr != '\n' && *ptr != '\r')
421 {
422 if (!*ptr) *ptr = '\n'; /* convert embedded nulls to \n */
423 if (ptr > *line && *ptr == '\x19' && *(ptr - 1) == '\x11')
424 {
425 *ptr = '\n';
426 *(ptr - 1) = '\r';
427 }
428 ptr++;
429 chars_left--;
430 }
431
432 /* NULL-separate the data */
433 if (*ptr == '\n' || *ptr == '\r')
434 {
435 while (chars_left && (*ptr == '\n' || *ptr == '\r'))
436 {
437 *(ptr++) = 0;
438 chars_left--;
439 }
440 }
441 else if (*ptr)
442 {
443 *(ptr++) = 0;
444 chars_left--;
445 }
446 (*entries)[i] = save;
447 }
448
449 /* move to the next line if there's more, else EOF */
450 *line = ptr;
451 *len = chars_left;
452 if (!*num_entries)
453 *num_entries = count;
454
455 return ERROR_SUCCESS;
456}
Definition: parser.c:49

Referenced by MSI_DatabaseImport().

◆ read_text_archive()

static WCHAR * read_text_archive ( const WCHAR path,
DWORD len 
)
static

Definition at line 350 of file database.c.

351{
352 HANDLE file;
353 LPSTR data = NULL;
354 LPWSTR wdata = NULL;
355 DWORD read, size = 0;
356
359 return NULL;
360
362 if (!(data = malloc( size ))) goto done;
363
364 if (!ReadFile( file, data, size, &read, NULL ) || read != size) goto done;
365
366 while (!data[size - 1]) size--;
368 if ((wdata = malloc( (*len + 1) * sizeof(WCHAR) )))
369 {
370 MultiByteToWideChar( CP_ACP, 0, data, size, wdata, *len );
371 wdata[*len] = 0;
372 }
373
374done:
375 CloseHandle( file );
376 free( data );
377 return wdata;
378}
#define read
Definition: acwin.h:96
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define MultiByteToWideChar
Definition: compat.h:110
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
char * LPSTR
Definition: xmlstorage.h:182

Referenced by MSI_DatabaseImport().

◆ s_remote_DatabaseGetPrimaryKeys()

UINT __cdecl s_remote_DatabaseGetPrimaryKeys ( MSIHANDLE  db,
LPCWSTR  table,
struct wire_record **  rec 
)

Definition at line 1941 of file database.c.

1942{
1945 *rec = NULL;
1946 if (!r)
1947 *rec = marshal_record(handle);
1949 return r;
1950}
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:269
struct wire_record * marshal_record(MSIHANDLE handle)
Definition: record.c:1109
UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb, const WCHAR *table, MSIHANDLE *phRec)
Definition: msiquery.c:1078
unsigned long MSIHANDLE
Definition: winemsi.idl:27

◆ s_remote_DatabaseGetSummaryInformation()

UINT __cdecl s_remote_DatabaseGetSummaryInformation ( MSIHANDLE  db,
UINT  updatecount,
MSIHANDLE suminfo 
)

Definition at line 1952 of file database.c.

1953{
1954 return MsiGetSummaryInformationW(db, NULL, updatecount, suminfo);
1955}
static const CHAR suminfo[]
Definition: db.c:2166
UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase, const WCHAR *szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
Definition: suminfo.c:519

◆ s_remote_DatabaseIsTablePersistent()

MSICONDITION __cdecl s_remote_DatabaseIsTablePersistent ( MSIHANDLE  db,
LPCWSTR  table 
)

Definition at line 1936 of file database.c.

1937{
1939}
MSICONDITION WINAPI MsiDatabaseIsTablePersistentW(MSIHANDLE hDatabase, const WCHAR *szTableName)
Definition: msiquery.c:1165

◆ s_remote_DatabaseOpenView()

UINT __cdecl s_remote_DatabaseOpenView ( MSIHANDLE  db,
LPCWSTR  query,
MSIHANDLE view 
)

Definition at line 1957 of file database.c.

1958{
1959 return MsiDatabaseOpenViewW(db, query, view);
1960}
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, LPCWSTR szQuery, MSIHANDLE *phView)
Definition: msiquery.c:236

◆ update_merge_errors()

static UINT update_merge_errors ( MSIDATABASE db,
LPCWSTR  error,
LPWSTR  table,
DWORD  numconflicts 
)
static

Definition at line 1828 of file database.c.

1830{
1831 UINT r;
1832 MSIQUERY *view;
1833
1834 if (!TABLE_Exists(db, error))
1835 {
1836 r = MSI_OpenQuery(db, &view, L"CREATE TABLE `%s` (`Table` CHAR(255) NOT NULL, `NumRowMergeConflicts` SHORT "
1837 "NOT NULL PRIMARY KEY `Table`)" , error);
1838 if (r != ERROR_SUCCESS)
1839 return r;
1840
1842 msiobj_release(&view->hdr);
1843 if (r != ERROR_SUCCESS)
1844 return r;
1845 }
1846
1847 r = MSI_OpenQuery(db, &view, L"INSERT INTO `%s` (`Table`, `NumRowMergeConflicts`) VALUES ('%s', %d)", error,
1848 table, numconflicts);
1849 if (r != ERROR_SUCCESS)
1850 return r;
1851
1853 msiobj_release(&view->hdr);
1854 return r;
1855}
#define error(str)
Definition: mkdosfs.c:1605

Referenced by MsiDatabaseMergeW().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( msi  )